msm: mdm: Add support for remote MDM image upgrade

mdm-driver is informed that an image upgrade of the remote modem is
required, at which point it stops monitoring the error gpios and takes
the appropriate actions. Support for the "USB Switch" gpio is added.
This is needed to write a image to an empty modem flash.

Change-Id: I4c05a80955124a3eb7edc11e99f4945f9de79e6b
Signed-off-by: Ameya Thakur <ameyat@codeaurora.org>
This commit is contained in:
Ameya Thakur
2012-07-10 18:50:52 -07:00
committed by Stephen Boyd
parent 6c84e45301
commit 27a0e1f889
8 changed files with 87 additions and 6 deletions

View File

@@ -240,6 +240,12 @@ static struct gpiomux_setting ap2mdm_kpdpwr_n_cfg = {
.pull = GPIOMUX_PULL_DOWN, .pull = GPIOMUX_PULL_DOWN,
}; };
static struct gpiomux_setting usbsw_cfg = {
.func = GPIOMUX_FUNC_GPIO,
.drv = GPIOMUX_DRV_8MA,
.pull = GPIOMUX_PULL_DOWN,
};
static struct gpiomux_setting mdp_vsync_suspend_cfg = { static struct gpiomux_setting mdp_vsync_suspend_cfg = {
.func = GPIOMUX_FUNC_GPIO, .func = GPIOMUX_FUNC_GPIO,
.drv = GPIOMUX_DRV_2MA, .drv = GPIOMUX_DRV_2MA,
@@ -760,6 +766,13 @@ static struct msm_gpiomux_config sglte_configs[] __initdata = {
[GPIOMUX_SUSPENDED] = &ap2mdm_cfg, [GPIOMUX_SUSPENDED] = &ap2mdm_cfg,
} }
}, },
/* USB_SW */
{
.gpio = 25,
.settings = {
[GPIOMUX_SUSPENDED] = &usbsw_cfg,
}
}
}; };
static struct msm_gpiomux_config msm8960_mdp_vsync_configs[] __initdata = { static struct msm_gpiomux_config msm8960_mdp_vsync_configs[] __initdata = {

View File

@@ -1293,6 +1293,7 @@ static struct mdm_platform_data sglte_platform_data = {
.peripheral_platform_device = NULL, .peripheral_platform_device = NULL,
.ramdump_timeout_ms = 600000, .ramdump_timeout_ms = 600000,
.no_powerdown_after_ramdumps = 1, .no_powerdown_after_ramdumps = 1,
.image_upgrade_supported = 1,
}; };
#define MSM_TSIF0_PHYS (0x18200000) #define MSM_TSIF0_PHYS (0x18200000)

View File

@@ -3812,6 +3812,7 @@ struct platform_device msm8960_cache_dump_device = {
#define AP2MDM_PMIC_PWR_EN 22 #define AP2MDM_PMIC_PWR_EN 22
#define AP2MDM_KPDPWR_N 79 #define AP2MDM_KPDPWR_N 79
#define AP2MDM_SOFT_RESET 78 #define AP2MDM_SOFT_RESET 78
#define USB_SW 25
static struct resource sglte_resources[] = { static struct resource sglte_resources[] = {
{ {
@@ -3856,6 +3857,12 @@ static struct resource sglte_resources[] = {
.name = "AP2MDM_SOFT_RESET", .name = "AP2MDM_SOFT_RESET",
.flags = IORESOURCE_IO, .flags = IORESOURCE_IO,
}, },
{
.start = USB_SW,
.end = USB_SW,
.name = "USB_SW",
.flags = IORESOURCE_IO,
},
}; };
struct platform_device mdm_sglte_device = { struct platform_device mdm_sglte_device = {

View File

@@ -31,6 +31,7 @@ struct mdm_platform_data {
struct mdm_vddmin_resource *vddmin_resource; struct mdm_vddmin_resource *vddmin_resource;
struct platform_device *peripheral_platform_device; struct platform_device *peripheral_platform_device;
const unsigned int ramdump_timeout_ms; const unsigned int ramdump_timeout_ms;
int image_upgrade_supported;
}; };
#endif #endif

View File

@@ -249,6 +249,33 @@ static void mdm_status_changed(struct mdm_modem_drv *mdm_drv, int value)
} }
} }
static void mdm_image_upgrade(struct mdm_modem_drv *mdm_drv, int type)
{
switch (type) {
case APQ_CONTROLLED_UPGRADE:
pr_debug("%s APQ controlled modem image upgrade\n", __func__);
mdm_drv->mdm_ready = 0;
mdm_toggle_soft_reset(mdm_drv);
break;
case MDM_CONTROLLED_UPGRADE:
pr_debug("%s MDM controlled modem image upgrade\n", __func__);
mdm_drv->mdm_ready = 0;
/*
* If we have no image currently present on the modem, then we
* would be in PBL, in which case the status gpio would not go
* high.
*/
mdm_drv->disable_status_check = 1;
if (mdm_drv->usb_switch_gpio > 0) {
pr_info("%s Switching usb control to MDM\n", __func__);
gpio_direction_output(mdm_drv->usb_switch_gpio, 1);
} else
pr_err("%s usb switch gpio unavailable\n", __func__);
break;
default:
pr_err("%s invalid upgrade type\n", __func__);
}
}
static struct mdm_ops mdm_cb = { static struct mdm_ops mdm_cb = {
.power_on_mdm_cb = mdm_power_on_common, .power_on_mdm_cb = mdm_power_on_common,
.reset_mdm_cb = mdm_power_on_common, .reset_mdm_cb = mdm_power_on_common,
@@ -256,6 +283,7 @@ static struct mdm_ops mdm_cb = {
.power_down_mdm_cb = mdm_power_down_common, .power_down_mdm_cb = mdm_power_down_common,
.debug_state_changed_cb = debug_state_changed, .debug_state_changed_cb = debug_state_changed,
.status_cb = mdm_status_changed, .status_cb = mdm_status_changed,
.image_upgrade_cb = mdm_image_upgrade,
}; };
static int __init mdm_modem_probe(struct platform_device *pdev) static int __init mdm_modem_probe(struct platform_device *pdev)

View File

@@ -151,6 +151,7 @@ static void mdm2ap_status_check(struct work_struct *work)
* If the mdm modem did not pull the MDM2AP_STATUS gpio * If the mdm modem did not pull the MDM2AP_STATUS gpio
* high then call subsystem_restart. * high then call subsystem_restart.
*/ */
if (!mdm_drv->disable_status_check) {
if (gpio_get_value(mdm_drv->mdm2ap_status_gpio) == 0) { if (gpio_get_value(mdm_drv->mdm2ap_status_gpio) == 0) {
pr_err("%s: MDM2AP_STATUS gpio did not go high\n", pr_err("%s: MDM2AP_STATUS gpio did not go high\n",
__func__); __func__);
@@ -158,6 +159,7 @@ static void mdm2ap_status_check(struct work_struct *work)
subsystem_restart_dev(mdm_subsys_dev); subsystem_restart_dev(mdm_subsys_dev);
} }
} }
}
static DECLARE_DELAYED_WORK(mdm2ap_status_check_work, mdm2ap_status_check); static DECLARE_DELAYED_WORK(mdm2ap_status_check_work, mdm2ap_status_check);
@@ -239,6 +241,15 @@ long mdm_modem_ioctl(struct file *filp, unsigned int cmd,
else else
put_user(0, (unsigned long __user *) arg); put_user(0, (unsigned long __user *) arg);
break; break;
case IMAGE_UPGRADE:
pr_debug("%s Image upgrade ioctl recieved\n", __func__);
if (mdm_drv->pdata->image_upgrade_supported &&
mdm_drv->ops->image_upgrade_cb) {
get_user(status, (unsigned long __user *) arg);
mdm_drv->ops->image_upgrade_cb(mdm_drv, status);
} else
pr_debug("%s Image upgrade not supported\n", __func__);
break;
default: default:
pr_err("%s: invalid ioctl cmd = %d\n", __func__, _IOC_NR(cmd)); pr_err("%s: invalid ioctl cmd = %d\n", __func__, _IOC_NR(cmd));
ret = -EINVAL; ret = -EINVAL;
@@ -364,7 +375,6 @@ static int mdm_subsys_shutdown(const struct subsys_desc *crashed_subsys)
mdm_drv->ops->reset_mdm_cb(mdm_drv); mdm_drv->ops->reset_mdm_cb(mdm_drv);
else else
mdm_drv->mdm_unexpected_reset_occurred = 0; mdm_drv->mdm_unexpected_reset_occurred = 0;
return 0; return 0;
} }
@@ -515,6 +525,12 @@ static void mdm_modem_initialize_data(struct platform_device *pdev,
if (pres) if (pres)
mdm_drv->mdm2ap_pblrdy = pres->start; mdm_drv->mdm2ap_pblrdy = pres->start;
/*USB_SW*/
pres = platform_get_resource_byname(pdev, IORESOURCE_IO,
"USB_SW");
if (pres)
mdm_drv->usb_switch_gpio = pres->start;
mdm_drv->boot_type = CHARM_NORMAL_BOOT; mdm_drv->boot_type = CHARM_NORMAL_BOOT;
mdm_drv->ops = mdm_ops; mdm_drv->ops = mdm_ops;
@@ -557,6 +573,13 @@ int mdm_common_create(struct platform_device *pdev,
if (mdm_drv->ap2mdm_wakeup_gpio > 0) if (mdm_drv->ap2mdm_wakeup_gpio > 0)
gpio_request(mdm_drv->ap2mdm_wakeup_gpio, "AP2MDM_WAKEUP"); gpio_request(mdm_drv->ap2mdm_wakeup_gpio, "AP2MDM_WAKEUP");
if (mdm_drv->usb_switch_gpio > 0) {
if (gpio_request(mdm_drv->usb_switch_gpio, "USB_SW")) {
pr_err("%s Failed to get usb switch gpio\n", __func__);
mdm_drv->usb_switch_gpio = -1;
}
}
gpio_direction_output(mdm_drv->ap2mdm_status_gpio, 1); gpio_direction_output(mdm_drv->ap2mdm_status_gpio, 1);
gpio_direction_output(mdm_drv->ap2mdm_errfatal_gpio, 0); gpio_direction_output(mdm_drv->ap2mdm_errfatal_gpio, 0);

View File

@@ -23,6 +23,7 @@ struct mdm_ops {
void (*power_down_mdm_cb)(struct mdm_modem_drv *mdm_drv); void (*power_down_mdm_cb)(struct mdm_modem_drv *mdm_drv);
void (*debug_state_changed_cb)(int value); void (*debug_state_changed_cb)(int value);
void (*status_cb)(struct mdm_modem_drv *mdm_drv, int value); void (*status_cb)(struct mdm_modem_drv *mdm_drv, int value);
void (*image_upgrade_cb)(struct mdm_modem_drv *mdm_drv, int type);
}; };
/* Private mdm2 data structure */ /* Private mdm2 data structure */
@@ -37,6 +38,7 @@ struct mdm_modem_drv {
unsigned ap2mdm_soft_reset_gpio; unsigned ap2mdm_soft_reset_gpio;
unsigned ap2mdm_pmic_pwr_en_gpio; unsigned ap2mdm_pmic_pwr_en_gpio;
unsigned mdm2ap_pblrdy; unsigned mdm2ap_pblrdy;
unsigned usb_switch_gpio;
int mdm_errfatal_irq; int mdm_errfatal_irq;
int mdm_status_irq; int mdm_status_irq;
@@ -46,6 +48,7 @@ struct mdm_modem_drv {
enum charm_boot_type boot_type; enum charm_boot_type boot_type;
int mdm_debug_on; int mdm_debug_on;
int mdm_unexpected_reset_occurred; int mdm_unexpected_reset_occurred;
int disable_status_check;
struct mdm_ops *ops; struct mdm_ops *ops;
struct mdm_platform_data *pdata; struct mdm_platform_data *pdata;

View File

@@ -11,10 +11,15 @@
#define RAM_DUMP_DONE _IOW(CHARM_CODE, 6, int) #define RAM_DUMP_DONE _IOW(CHARM_CODE, 6, int)
#define WAIT_FOR_RESTART _IOR(CHARM_CODE, 7, int) #define WAIT_FOR_RESTART _IOR(CHARM_CODE, 7, int)
#define GET_DLOAD_STATUS _IOR(CHARM_CODE, 8, int) #define GET_DLOAD_STATUS _IOR(CHARM_CODE, 8, int)
#define IMAGE_UPGRADE _IOW(CHARM_CODE, 9, int)
enum charm_boot_type { enum charm_boot_type {
CHARM_NORMAL_BOOT = 0, CHARM_NORMAL_BOOT = 0,
CHARM_RAM_DUMPS, CHARM_RAM_DUMPS,
}; };
enum image_upgrade_type {
APQ_CONTROLLED_UPGRADE = 0,
MDM_CONTROLLED_UPGRADE,
};
#endif #endif