From 43248fd4cb8b95b6fe52c23e9834b739f0195b7a Mon Sep 17 00:00:00 2001 From: Ameya Thakur Date: Tue, 10 Jul 2012 18:50:52 -0700 Subject: [PATCH] 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 --- arch/arm/mach-msm/board-8960-gpiomux.c | 13 ++++++++++ arch/arm/mach-msm/board-8960.c | 1 + arch/arm/mach-msm/devices-8960.c | 7 ++++++ arch/arm/mach-msm/include/mach/mdm2.h | 1 + arch/arm/mach-msm/mdm2.c | 28 +++++++++++++++++++++ arch/arm/mach-msm/mdm_common.c | 35 +++++++++++++++++++++----- arch/arm/mach-msm/mdm_private.h | 3 +++ include/linux/msm_charm.h | 5 ++++ 8 files changed, 87 insertions(+), 6 deletions(-) diff --git a/arch/arm/mach-msm/board-8960-gpiomux.c b/arch/arm/mach-msm/board-8960-gpiomux.c index fd326f1921e..53e7c9e413d 100644 --- a/arch/arm/mach-msm/board-8960-gpiomux.c +++ b/arch/arm/mach-msm/board-8960-gpiomux.c @@ -240,6 +240,12 @@ static struct gpiomux_setting ap2mdm_kpdpwr_n_cfg = { .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 = { .func = GPIOMUX_FUNC_GPIO, .drv = GPIOMUX_DRV_2MA, @@ -760,6 +766,13 @@ static struct msm_gpiomux_config sglte_configs[] __initdata = { [GPIOMUX_SUSPENDED] = &ap2mdm_cfg, } }, + /* USB_SW */ + { + .gpio = 25, + .settings = { + [GPIOMUX_SUSPENDED] = &usbsw_cfg, + } + } }; static struct msm_gpiomux_config msm8960_mdp_vsync_configs[] __initdata = { diff --git a/arch/arm/mach-msm/board-8960.c b/arch/arm/mach-msm/board-8960.c index bb20d04e2c9..cbdc9ff5455 100644 --- a/arch/arm/mach-msm/board-8960.c +++ b/arch/arm/mach-msm/board-8960.c @@ -1293,6 +1293,7 @@ static struct mdm_platform_data sglte_platform_data = { .peripheral_platform_device = NULL, .ramdump_timeout_ms = 600000, .no_powerdown_after_ramdumps = 1, + .image_upgrade_supported = 1, }; #define MSM_TSIF0_PHYS (0x18200000) diff --git a/arch/arm/mach-msm/devices-8960.c b/arch/arm/mach-msm/devices-8960.c index 79f8c8823d9..d74d4aa49d9 100644 --- a/arch/arm/mach-msm/devices-8960.c +++ b/arch/arm/mach-msm/devices-8960.c @@ -3812,6 +3812,7 @@ struct platform_device msm8960_cache_dump_device = { #define AP2MDM_PMIC_PWR_EN 22 #define AP2MDM_KPDPWR_N 79 #define AP2MDM_SOFT_RESET 78 +#define USB_SW 25 static struct resource sglte_resources[] = { { @@ -3856,6 +3857,12 @@ static struct resource sglte_resources[] = { .name = "AP2MDM_SOFT_RESET", .flags = IORESOURCE_IO, }, + { + .start = USB_SW, + .end = USB_SW, + .name = "USB_SW", + .flags = IORESOURCE_IO, + }, }; struct platform_device mdm_sglte_device = { diff --git a/arch/arm/mach-msm/include/mach/mdm2.h b/arch/arm/mach-msm/include/mach/mdm2.h index 637a3cc3047..c4877cc861d 100644 --- a/arch/arm/mach-msm/include/mach/mdm2.h +++ b/arch/arm/mach-msm/include/mach/mdm2.h @@ -31,6 +31,7 @@ struct mdm_platform_data { struct mdm_vddmin_resource *vddmin_resource; struct platform_device *peripheral_platform_device; const unsigned int ramdump_timeout_ms; + int image_upgrade_supported; }; #endif diff --git a/arch/arm/mach-msm/mdm2.c b/arch/arm/mach-msm/mdm2.c index 6e7086eccc4..e74af2ebfef 100644 --- a/arch/arm/mach-msm/mdm2.c +++ b/arch/arm/mach-msm/mdm2.c @@ -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 = { .power_on_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, .debug_state_changed_cb = debug_state_changed, .status_cb = mdm_status_changed, + .image_upgrade_cb = mdm_image_upgrade, }; static int __init mdm_modem_probe(struct platform_device *pdev) diff --git a/arch/arm/mach-msm/mdm_common.c b/arch/arm/mach-msm/mdm_common.c index ac9da2e7796..6b40cda54f6 100644 --- a/arch/arm/mach-msm/mdm_common.c +++ b/arch/arm/mach-msm/mdm_common.c @@ -151,11 +151,13 @@ static void mdm2ap_status_check(struct work_struct *work) * If the mdm modem did not pull the MDM2AP_STATUS gpio * high then call subsystem_restart. */ - if (gpio_get_value(mdm_drv->mdm2ap_status_gpio) == 0) { - pr_err("%s: MDM2AP_STATUS gpio did not go high\n", - __func__); - mdm_drv->mdm_ready = 0; - subsystem_restart_dev(mdm_subsys_dev); + if (!mdm_drv->disable_status_check) { + if (gpio_get_value(mdm_drv->mdm2ap_status_gpio) == 0) { + pr_err("%s: MDM2AP_STATUS gpio did not go high\n", + __func__); + mdm_drv->mdm_ready = 0; + subsystem_restart_dev(mdm_subsys_dev); + } } } @@ -239,6 +241,15 @@ long mdm_modem_ioctl(struct file *filp, unsigned int cmd, else put_user(0, (unsigned long __user *) arg); 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: pr_err("%s: invalid ioctl cmd = %d\n", __func__, _IOC_NR(cmd)); 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); else mdm_drv->mdm_unexpected_reset_occurred = 0; - return 0; } @@ -515,6 +525,12 @@ static void mdm_modem_initialize_data(struct platform_device *pdev, if (pres) 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->ops = mdm_ops; @@ -557,6 +573,13 @@ int mdm_common_create(struct platform_device *pdev, if (mdm_drv->ap2mdm_wakeup_gpio > 0) 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_errfatal_gpio, 0); diff --git a/arch/arm/mach-msm/mdm_private.h b/arch/arm/mach-msm/mdm_private.h index 7ac37274d88..7aba83d6bd3 100644 --- a/arch/arm/mach-msm/mdm_private.h +++ b/arch/arm/mach-msm/mdm_private.h @@ -23,6 +23,7 @@ struct mdm_ops { void (*power_down_mdm_cb)(struct mdm_modem_drv *mdm_drv); void (*debug_state_changed_cb)(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 */ @@ -37,6 +38,7 @@ struct mdm_modem_drv { unsigned ap2mdm_soft_reset_gpio; unsigned ap2mdm_pmic_pwr_en_gpio; unsigned mdm2ap_pblrdy; + unsigned usb_switch_gpio; int mdm_errfatal_irq; int mdm_status_irq; @@ -46,6 +48,7 @@ struct mdm_modem_drv { enum charm_boot_type boot_type; int mdm_debug_on; int mdm_unexpected_reset_occurred; + int disable_status_check; struct mdm_ops *ops; struct mdm_platform_data *pdata; diff --git a/include/linux/msm_charm.h b/include/linux/msm_charm.h index c31e49375cf..44d25532f1e 100644 --- a/include/linux/msm_charm.h +++ b/include/linux/msm_charm.h @@ -11,10 +11,15 @@ #define RAM_DUMP_DONE _IOW(CHARM_CODE, 6, int) #define WAIT_FOR_RESTART _IOR(CHARM_CODE, 7, int) #define GET_DLOAD_STATUS _IOR(CHARM_CODE, 8, int) +#define IMAGE_UPGRADE _IOW(CHARM_CODE, 9, int) enum charm_boot_type { CHARM_NORMAL_BOOT = 0, CHARM_RAM_DUMPS, }; +enum image_upgrade_type { + APQ_CONTROLLED_UPGRADE = 0, + MDM_CONTROLLED_UPGRADE, +}; #endif