summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorVenkat Moganty <vmoganty@nvidia.com>2010-07-08 10:29:21 +0530
committerGary King <gking@nvidia.com>2010-07-09 15:59:16 -0700
commit0a78303054f9fd89d382cc14f0b8dff69ac937cb (patch)
treed204539a779e47d77004fc468fc97689eb924e0c
parent53c61075afabff54b883590ca000e45cd8748c19 (diff)
[tegra-usb] Fix USB-OTG for CONFIG_USB_SUSPEND
When CONFIG_USB_SUSPEND is enabled, after auto suspend by the usb core driver, USB devices(mouse,keyboard etc.) are not recognised. After auto suspend device state goes to suspend and not resuming to the address. This is fixed by changing the device state to address state on USB cable insertion. Bug 674938 Bug 698734 Change-Id: I837562fd1eb020f400824f2d475289df5fbc1f83 Reviewed-on: http://git-master/r/3494 Reviewed-by: Gary King <gking@nvidia.com> Tested-by: Hanumanth Venkateswa Moganty <vmoganty@nvidia.com>
-rw-r--r--drivers/usb/host/ehci-tegra.c24
-rw-r--r--drivers/usb/otg/tegra-otg.c1
2 files changed, 21 insertions, 4 deletions
diff --git a/drivers/usb/host/ehci-tegra.c b/drivers/usb/host/ehci-tegra.c
index a5a32021f2a6..21d18bebb562 100644
--- a/drivers/usb/host/ehci-tegra.c
+++ b/drivers/usb/host/ehci-tegra.c
@@ -35,6 +35,7 @@
#include "nvrm_power.h"
#include "nvrm_hardware_access.h"
#include "nvddk_usbphy.h"
+#include "../core/usb.h"
#define TEGRA_USB_ID_INT_ENABLE (1 << 0)
#define TEGRA_USB_ID_INT_STATUS (1 << 1)
@@ -58,7 +59,7 @@ static void tegra_ehci_busy_hint_work(struct work_struct* work)
struct tegra_hcd_platform_data *pdata =
container_of(work, struct tegra_hcd_platform_data, work);
NvDdkUsbPhyIoctl_UsbBusyHintsOnOffInputArgs busyhint;
- busyhint.OnOff = NV_TRUE;
+ busyhint.OnOff = true;
/* USB transfers will be done with in 1 sec, this need to be *
* fine tuned (if required). with safe limit set to 2 sec */
@@ -76,7 +77,7 @@ static void tegra_ehci_power_up(struct usb_hcd *hcd)
pdata = hcd->self.controller->platform_data;
- NV_ASSERT_SUCCESS(NvDdkUsbPhyPowerUp(pdata->hUsbPhy, NV_TRUE, 0));
+ NV_ASSERT_SUCCESS(NvDdkUsbPhyPowerUp(pdata->hUsbPhy, true, 0));
ehci->host_resumed = 1;
}
@@ -87,7 +88,7 @@ static void tegra_ehci_power_down(struct usb_hcd *hcd)
pdata = hcd->self.controller->platform_data;
- NV_ASSERT_SUCCESS(NvDdkUsbPhyPowerDown(pdata->hUsbPhy, NV_TRUE, 0));
+ NV_ASSERT_SUCCESS(NvDdkUsbPhyPowerDown(pdata->hUsbPhy, true, 0));
ehci->host_resumed = 0;
}
@@ -142,6 +143,7 @@ static int tegra_ehci_hub_control (
&& ehci->host_reinited) {
/* indicate hcd flags, that hardware is not accessable now */
clear_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags);
+ ehci_halt(ehci);
tegra_ehci_power_down(hcd);
ehci->transceiver->state = OTG_STATE_UNDEFINED;
ehci->host_reinited = 0;
@@ -215,6 +217,7 @@ static void tegra_ehci_irq_work(struct work_struct* irq_work)
struct usb_hcd *hcd = ehci_to_hcd(ehci);
struct tegra_hcd_platform_data *pdata;
u32 status;
+ bool kick_rhub = false;
pdata = hcd->self.controller->platform_data;
@@ -224,6 +227,8 @@ static void tegra_ehci_irq_work(struct work_struct* irq_work)
if (!ehci->host_reinited) {
ehci->host_reinited = 1;
tegra_ehci_power_up(hcd);
+ if (hcd->state == HC_STATE_SUSPENDED)
+ kick_rhub = true;
tegra_ehci_restart(hcd);
}
}
@@ -238,9 +243,18 @@ static void tegra_ehci_irq_work(struct work_struct* irq_work)
tegra_ehci_power_down(hcd);
} else {
tegra_ehci_power_up(hcd);
+ if (hcd->state == HC_STATE_SUSPENDED)
+ kick_rhub = true;
}
}
}
+
+ if (kick_rhub && hcd->rh_registered) {
+ hcd->poll_rh = 0;
+ usb_set_device_state (hcd->self.root_hub, USB_STATE_ADDRESS);
+ hcd->state = HC_STATE_RUNNING;
+ usb_kick_khubd (hcd->self.root_hub);
+ }
}
@@ -260,6 +274,8 @@ static irqreturn_t tegra_ehci_irq (struct usb_hcd *hcd)
if (ehci->transceiver->state == OTG_STATE_A_HOST) {
if (!ehci->host_reinited) {
schedule_work(&ehci->irq_work);
+ spin_unlock (&ehci->lock);
+ return IRQ_HANDLED;
}
} else if (ehci->transceiver->state == OTG_STATE_A_SUSPEND) {
if (!ehci->host_reinited) {
@@ -281,6 +297,8 @@ static irqreturn_t tegra_ehci_irq (struct usb_hcd *hcd)
/* Check if there is any ID pin interrupt */
if (status & TEGRA_USB_ID_INT_STATUS) {
schedule_work(&ehci->irq_work);
+ spin_unlock (&ehci->lock);
+ return IRQ_HANDLED;
}
}
}
diff --git a/drivers/usb/otg/tegra-otg.c b/drivers/usb/otg/tegra-otg.c
index 8bf00010edcc..42b292c90fd5 100644
--- a/drivers/usb/otg/tegra-otg.c
+++ b/drivers/usb/otg/tegra-otg.c
@@ -81,7 +81,6 @@ static irqreturn_t tegra_otg_irq(int irq, void *data)
tegra_otg->otg.state = OTG_STATE_A_SUSPEND;
} else {
tegra_otg->otg.state = OTG_STATE_A_HOST;
- hcd->state = HC_STATE_RUNNING;
/* set HCD flags to start host ISR */
set_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags);
}