misc: mdm6600_ctrl: update shutdown to reset unresponsive modem.
authorJames Wylder <james.wylder@motorola.com>
Fri, 20 Aug 2010 01:23:12 +0000 (20:23 -0500)
committerColin Cross <ccross@android.com>
Wed, 6 Oct 2010 23:51:17 +0000 (16:51 -0700)
    - fix initialization of BP_PWRON (PS6), and BP_RESIN (PZ1) gpios,
    - cleanup kernel log messages,
    - assert BP_RESIN gpio to reset unresponsive modem.

Change-Id: Iaf6b7d553fec1a6e9254b7183c1beacf7ad4d555
Signed-off-by: James Wylder <james.wylder@motorola.com>
drivers/misc/mdm6600_ctrl.c
include/linux/mdm6600_ctrl.h

index e8f0cad79edf01720c07a60845f2bd9bd6f392a2..13f8ff53cf5cde62d4e5599dc6d7dbf2bcd27831 100644 (file)
 #define BP_STATUS_SHUTDOWN_ACK      0x06
 #define BP_STATUS_UNDEFINED         0x07
 
+#define LOOP_DELAY_TIME_MS          500
+
+char *bp_status[8] = {
+       "panic",
+       "panic busy wait",
+       "qc dload",
+       "ram downloader",
+       "awake",
+       "asleep",
+       "shutdown ack",
+       "undefined",
+};
+
+static char *bp_status_string(unsigned int stat)
+{
+       if (stat < 8)
+               return bp_status[stat];
+       else
+               return "status out of range";
+}
+
 static unsigned int mdm_gpio_get_value(struct mdm_ctrl_gpio gpio)
 {
        return gpio_get_value(gpio.number);
@@ -57,13 +78,12 @@ static void mdm_gpio_free(struct mdm_ctrl_gpio *gpio)
 
 static int mdm_gpio_setup(struct mdm_ctrl_gpio *gpio)
 {
-       snprintf(gpio->name, MAX_GPIO_NAME, "mdm_gpio_%05d", gpio->number);
-
        if (gpio_request(gpio->number, gpio->name))  {
                printk(KERN_ERR "failed to aquire gpio %s", gpio->name);
                return -1;
        }
        gpio->allocated = 1;
+       gpio_export(gpio->number, false);
        if (gpio->direction == MDM_GPIO_DIRECTION_IN)
                gpio_direction_input(gpio->number);
        else if (gpio->direction == MDM_GPIO_DIRECTION_OUT)
@@ -160,31 +180,34 @@ static int __devexit mdm_ctrl_remove(struct platform_device *pdev)
 }
 
 static unsigned int __devexit bp_shutdown_wait(struct platform_device *pdev,
-                    struct mdm_ctrl_platform_data *pdata)
+               struct mdm_ctrl_platform_data *pdata,
+               unsigned int delay_sec)
 {
-       unsigned int delay;
+       unsigned int i, loop_count;
        unsigned int bp_status;
        unsigned int gpio_value;
        unsigned int pd_failure = 1;
 
-       for (delay = 0; delay < 10; delay++) {
+       loop_count = (delay_sec * 1000) / LOOP_DELAY_TIME_MS;
+
+       for (i = 0; i < loop_count; i++) {
+               msleep(LOOP_DELAY_TIME_MS);
                bp_status = get_bp_status(pdata);
                if (bp_status == BP_STATUS_SHUTDOWN_ACK) {
-                       dev_info(&pdev->dev, "Modem power down success.\n");
+                       dev_info(&pdev->dev, "Modem powered off (with ack).\n");
                        pd_failure = 0;
                        break;
                }
                gpio_value = mdm_gpio_get_value(
                        pdata->gpios[MDM_CTRL_GPIO_BP_RESOUT]);
 
-               dev_info(&pdev->dev, "gpio_resout_gpio = %d\n", gpio_value);
-               if (!gpio_value) {
-                       dev_info(&pdev->dev, "Modem reporting Panic.\n");
+               if (gpio_value == 0) {
+                       dev_info(&pdev->dev, "Modem powered off.\n");
                        pd_failure = 0;
                        break;
                } else {
-                       dev_info(&pdev->dev, "Modem status 0x%x\n", bp_status);
-                       msleep(500);
+                       dev_info(&pdev->dev, "Modem status %s [0x%x]\n",
+                                bp_status_string(bp_status), bp_status);
                }
        }
        return pd_failure;
@@ -193,16 +216,15 @@ static unsigned int __devexit bp_shutdown_wait(struct platform_device *pdev,
 static void __devexit mdm_ctrl_shutdown(struct platform_device *pdev)
 {
        unsigned int pd_failure;
+       unsigned int bp_status;
 
        struct mdm_ctrl_platform_data *pdata = pdev->dev.platform_data;
 
        dev_info(&pdev->dev, "Shutting down modem.\n");
 
-       dev_info(&pdev->dev, "Initial modem status 0x%x\n",
-                get_bp_status(pdata));
-
-       dev_info(&pdev->dev, "Initial ap status 0x%x\n",
-                get_ap_status(pdata));
+       bp_status = get_bp_status(pdata);
+       dev_info(&pdev->dev, "Initial Modem status %s [0x%x]\n",
+                bp_status_string(bp_status), bp_status);
 
        set_ap_status(pdata, AP_STATUS_BP_SHUTDOWN_REQ);
 
@@ -220,16 +242,15 @@ static void __devexit mdm_ctrl_shutdown(struct platform_device *pdev)
        /* if this doesn't work, reset the modem and try */
        /* one more time, ultimately the modem will be   */
        /* hard powered off */
-       pd_failure = bp_shutdown_wait(pdev, pdata);
+       pd_failure = bp_shutdown_wait(pdev, pdata, 5);
        if (pd_failure) {
-               mdm_gpio_set_value(pdata->gpios[MDM_CTRL_GPIO_BP_PWRON], 1);
-               pd_failure = bp_shutdown_wait(pdev, pdata);
+               dev_info(&pdev->dev, "Resetting unresponsive modem.\n");
+               mdm_gpio_set_value(pdata->gpios[MDM_CTRL_GPIO_BP_RESIN], 1);
+               pd_failure = bp_shutdown_wait(pdev, pdata, 5);
        }
 
        if (pd_failure)
                dev_err(&pdev->dev, "Modem failed to power down.\n");
-       else
-               dev_info(&pdev->dev, "Modem successfully powered down.\n");
 }
 
 static struct platform_driver mdm6x00_ctrl_driver = {
index 597e5cbafdce64b0f35f816c5fde564d6650a843..91251f9df987eb45486adec5650f13bea10e09a1 100644 (file)
@@ -38,7 +38,6 @@ enum {
 enum {
        MDM_GPIO_DIRECTION_IN,
        MDM_GPIO_DIRECTION_OUT,
-       MDM_GPIO_DIRECTION_OUT_NO_DEFAULT,
 };
 
 struct mdm_ctrl_gpio {
@@ -46,7 +45,7 @@ struct mdm_ctrl_gpio {
        unsigned int direction;
        unsigned int default_value;
        unsigned int allocated;
-       char name[MAX_GPIO_NAME];
+       char *name;
 };
 
 struct mdm_ctrl_platform_data {