misc: tegra-baseband: Add support for L2 and cleanup code.
Raj Jayaraman [Mon, 13 Feb 2012 22:12:04 +0000 (14:12 -0800)]
Bug 886459

Signed-off-by: Raj Jayaraman <rjayaraman@nvidia.com>
(cherry picked from commit 9032b38a76d8337ee6b9582265171ca09473a3e9)

Change-Id: Ifa5ad5bdb3a782119a2920281bc39ce5f6fd2a5a
Reviewed-on: http://git-master/r/88868
Reviewed-by: Rajkumar Jayaraman <rjayaraman@nvidia.com>
Tested-by: Rajkumar Jayaraman <rjayaraman@nvidia.com>
Reviewed-by: Steve Lin <stlin@nvidia.com>

drivers/misc/tegra-baseband/bb-m7400.c
drivers/misc/tegra-baseband/bb-power.h

index 4209151..5808a6e 100644 (file)
@@ -45,6 +45,7 @@ static struct tegra_bb_gpio_data m7400_gpios[] = {
        { { GPIO_INVALID, 0, NULL }, false },   /* End of table */
 };
 static bool ehci_registered;
+static int modem_status;
 static int gpio_awr;
 static int gpio_cwr;
 static int gpio_arr;
@@ -83,8 +84,9 @@ static int m7400_apup_handshake(bool checkresponse)
 {
        int retval = 0;
 
-       /* Signal AP ready - Drive AWR high. */
+       /* Signal AP ready - Drive AWR and ARR high. */
        gpio_set_value(gpio_awr, 1);
+       gpio_set_value(gpio_arr, 1);
 
        if (checkresponse) {
                /* Wait for CP ack - by driving CWR high. */
@@ -106,41 +108,70 @@ static void m7400_apdown_handshake(void)
 
 static int m7400_l2_suspend(void)
 {
+       /* Gets called for two cases :
+               a) Port suspend.
+               b) Bus suspend. */
+       if (modem_status == BBSTATE_L2)
+               return 0;
+
        /* Post bus suspend: Drive ARR low. */
        gpio_set_value(gpio_arr, 0);
+       modem_status = BBSTATE_L2;
        return 0;
 }
 
 static int m7400_l2_resume(void)
 {
+       /* Gets called for two cases :
+               a) L2 resume.
+               b) bus resume phase of L3 resume. */
+       if (modem_status == BBSTATE_L0)
+               return 0;
+
        /* Pre bus resume: Drive ARR high. */
        gpio_set_value(gpio_arr, 1);
 
-       /* Wait for CP ack - by driving CWR high. */
+       /* If host initiated resume - Wait for CP ack (CWR goes high). */
+       /* If device initiated resume - CWR will be already high. */
        if (gpio_wait_timeout(gpio_cwr, 1, 10) != 0) {
                pr_info("%s: Error: timeout waiting for modem ack.\n",
                                                __func__);
                return -1;
        }
+       modem_status = BBSTATE_L0;
        return 0;
 }
 
 static void m7400_l3_suspend(void)
 {
        m7400_apdown_handshake();
+       modem_status = BBSTATE_L3;
 }
 
 static void m7400_l3_resume(void)
 {
        m7400_apup_handshake(true);
+       modem_status = BBSTATE_L0;
 }
 
 static irqreturn_t m7400_wake_irq(int irq, void *dev_id)
 {
-       pr_info("%s called.\n", __func__);
-
-       /* Resume usb host activity. */
-       /* TBD */
+       struct usb_interface *intf;
+
+       switch (modem_status) {
+       case BBSTATE_L2:
+               /* Resume usb host activity. */
+               if (m7400_usb_device) {
+                       usb_lock_device(m7400_usb_device);
+                       intf = usb_ifnum_to_if(m7400_usb_device, 0);
+                       usb_autopm_get_interface(intf);
+                       usb_autopm_put_interface(intf);
+                       usb_unlock_device(m7400_usb_device);
+               }
+               break;
+       default:
+               break;
+       }
 
        return IRQ_HANDLED;
 }
@@ -225,8 +256,8 @@ static int m7400_attrib_write(struct device *dev, int value)
 
 static int m7400_registered(struct usb_device *udev)
 {
-       pr_info("%s called.\n", __func__);
        m7400_usb_device = udev;
+       modem_status = BBSTATE_L0;
        return 0;
 }
 
@@ -285,6 +316,7 @@ static void *m7400_init(void *pdata)
        }
 
        ehci_registered = false;
+       modem_status = BBSTATE_UNKNOWN;
        return (void *) &m7400_data;
 }
 
index 84f9e85..cdd6938 100644 (file)
  *
  */
 
+enum tegra_bb_state {
+       BBSTATE_UNKNOWN,
+       /* Baseband state L0 - Running */
+       BBSTATE_L0,
+       /* Baseband state L2 - Suspended */
+       BBSTATE_L2,
+       /* Baseband state L3 - Suspended and detached */
+       BBSTATE_L3,
+};
+
 enum tegra_bb_pwrstate {
+       /* System power state - Entering suspend */
        PWRSTATE_L2L3,
+       /* System power state - Resuming from suspend */
        PWRSTATE_L3L0,
        PWRSTATE_INVALID,
 };
 
 struct tegra_bb_gpio_data {
+       /* Baseband gpio data */
        struct gpio data;
+       /* Baseband gpio - Should it be exported to sysfs ? */
        bool doexport;
 };
 
 struct tegra_bb_gpio_irqdata {
+       /* Baseband gpio IRQ - Id */
        int id;
+       /* Baseband gpio IRQ - Friendly name */
        const char *name;
+       /* Baseband gpio IRQ - IRQ handler */
        irq_handler_t handler;
+       /* Baseband gpio IRQ - IRQ trigger flags */
        int flags;
+       /* Baseband gpio IRQ - Can the gpio wake system from sleep ? */
        bool wake_capable;
        void *cookie;
 };
@@ -47,10 +66,15 @@ struct tegra_bb_power_gdata {
 };
 
 struct tegra_bb_power_mdata {
+       /* Baseband USB vendor ID */
        int vid;
+       /* Baseband USB product ID */
        int pid;
+       /* Baseband capability - Can it generate a wakeup ? */
        bool wake_capable;
+       /* Baseband capability - Can it be auto/runtime suspended ? */
        bool autosuspend_ready;
+       /* Baseband callback after a successful registration */
        modem_register_cb reg_cb;
 };