From 527efd9d01dc6c14b9b3ed21ae2165e99cd19ae2 Mon Sep 17 00:00:00 2001 From: Raj Jayaraman Date: Mon, 13 Feb 2012 14:12:04 -0800 Subject: misc: tegra-baseband: Add support for L2 and cleanup code. Bug 886459 Signed-off-by: Raj Jayaraman (cherry picked from commit 9032b38a76d8337ee6b9582265171ca09473a3e9) Change-Id: Ifa5ad5bdb3a782119a2920281bc39ce5f6fd2a5a Reviewed-on: http://git-master/r/88868 Reviewed-by: Rajkumar Jayaraman Tested-by: Rajkumar Jayaraman Reviewed-by: Steve Lin --- drivers/misc/tegra-baseband/bb-m7400.c | 46 ++++++++++++++++++++++++++++------ drivers/misc/tegra-baseband/bb-power.h | 24 ++++++++++++++++++ 2 files changed, 63 insertions(+), 7 deletions(-) diff --git a/drivers/misc/tegra-baseband/bb-m7400.c b/drivers/misc/tegra-baseband/bb-m7400.c index 4209151e5f39..5808a6e321cd 100644 --- a/drivers/misc/tegra-baseband/bb-m7400.c +++ b/drivers/misc/tegra-baseband/bb-m7400.c @@ -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; } diff --git a/drivers/misc/tegra-baseband/bb-power.h b/drivers/misc/tegra-baseband/bb-power.h index 84f9e85994b1..cdd693802031 100644 --- a/drivers/misc/tegra-baseband/bb-power.h +++ b/drivers/misc/tegra-baseband/bb-power.h @@ -14,22 +14,41 @@ * */ +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; }; -- cgit v1.2.3