summary refs log tree commit diff
path: root/drivers/usb/host
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2011-03-16 15:04:26 -0700
committerLinus Torvalds <torvalds@linux-foundation.org>2011-03-16 15:04:26 -0700
commit971f115a50afbe409825c9f3399d5a3b9aca4381 (patch)
treecb42dc07a032e325f22b64d961587c081225c6d6 /drivers/usb/host
parent2e270d84223262a38d4755c61d55f5c73ea89e56 (diff)
parent500132a0f26ad7d9916102193cbc6c1b1becb373 (diff)
downloadlinux-971f115a50afbe409825c9f3399d5a3b9aca4381.tar.gz
Merge branch 'usb-next' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/usb-2.6
* 'usb-next' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/usb-2.6: (172 commits)
  USB: Add support for SuperSpeed isoc endpoints
  xhci: Clean up cycle bit math used during stalls.
  xhci: Fix cycle bit calculation during stall handling.
  xhci: Update internal dequeue pointers after stalls.
  USB: Disable auto-suspend for USB 3.0 hubs.
  USB: Remove bogus USB_PORT_STAT_SUPER_SPEED symbol.
  xhci: Return canceled URBs immediately when host is halted.
  xhci: Fixes for suspend/resume of shared HCDs.
  xhci: Fix re-init on power loss after resume.
  xhci: Make roothub functions deal with device removal.
  xhci: Limit roothub ports to 15 USB3 & 31 USB2 ports.
  xhci: Return a USB 3.0 hub descriptor for USB3 roothub.
  xhci: Register second xHCI roothub.
  xhci: Change xhci_find_slot_id_by_port() API.
  xhci: Refactor bus suspend state into a struct.
  xhci: Index with a port array instead of PORTSC addresses.
  USB: Set usb_hcd->state and flags for shared roothubs.
  usb: Make core allocate resources per PCI-device.
  usb: Store bus type in usb_hcd, not in driver flags.
  usb: Change usb_hcd->bandwidth_mutex to a pointer.
  ...
Diffstat (limited to 'drivers/usb/host')
-rw-r--r--drivers/usb/host/Kconfig39
-rw-r--r--drivers/usb/host/ehci-atmel.c6
-rw-r--r--drivers/usb/host/ehci-dbg.c4
-rw-r--r--drivers/usb/host/ehci-hcd.c29
-rw-r--r--drivers/usb/host/ehci-hub.c32
-rw-r--r--drivers/usb/host/ehci-lpm.c5
-rw-r--r--drivers/usb/host/ehci-msm.c96
-rw-r--r--drivers/usb/host/ehci-omap.c882
-rw-r--r--drivers/usb/host/ehci-orion.c5
-rw-r--r--drivers/usb/host/ehci-pci.c45
-rw-r--r--drivers/usb/host/ehci-pmcmsp.c383
-rw-r--r--drivers/usb/host/ehci-q.c18
-rw-r--r--drivers/usb/host/ehci-sched.c76
-rw-r--r--drivers/usb/host/ehci-tegra.c715
-rw-r--r--drivers/usb/host/ehci.h2
-rw-r--r--drivers/usb/host/imx21-hcd.c9
-rw-r--r--drivers/usb/host/isp116x-hcd.c6
-rw-r--r--drivers/usb/host/isp1362-hcd.c13
-rw-r--r--drivers/usb/host/isp1760-hcd.c1395
-rw-r--r--drivers/usb/host/isp1760-hcd.h56
-rw-r--r--drivers/usb/host/ohci-hcd.c18
-rw-r--r--drivers/usb/host/ohci-hub.c13
-rw-r--r--drivers/usb/host/ohci-omap3.c584
-rw-r--r--drivers/usb/host/ohci-pci.c114
-rw-r--r--drivers/usb/host/ohci-q.c4
-rw-r--r--drivers/usb/host/ohci.h4
-rw-r--r--drivers/usb/host/oxu210hp-hcd.c6
-rw-r--r--drivers/usb/host/pci-quirks.c258
-rw-r--r--drivers/usb/host/pci-quirks.h10
-rw-r--r--drivers/usb/host/r8a66597-hcd.c5
-rw-r--r--drivers/usb/host/sl811-hcd.c6
-rw-r--r--drivers/usb/host/u132-hcd.c11
-rw-r--r--drivers/usb/host/uhci-hcd.c2
-rw-r--r--drivers/usb/host/xhci-ext-caps.h4
-rw-r--r--drivers/usb/host/xhci-hub.c392
-rw-r--r--drivers/usb/host/xhci-mem.c93
-rw-r--r--drivers/usb/host/xhci-pci.c124
-rw-r--r--drivers/usb/host/xhci-ring.c195
-rw-r--r--drivers/usb/host/xhci.c129
-rw-r--r--drivers/usb/host/xhci.h53
40 files changed, 3089 insertions, 2752 deletions
diff --git a/drivers/usb/host/Kconfig b/drivers/usb/host/Kconfig
index 0e6afa260ed8..9483acdf2e9e 100644
--- a/drivers/usb/host/Kconfig
+++ b/drivers/usb/host/Kconfig
@@ -91,17 +91,28 @@ config USB_EHCI_TT_NEWSCHED
 
 	  If unsure, say Y.
 
+config USB_EHCI_HCD_PMC_MSP
+	tristate "EHCI support for on-chip PMC MSP71xx USB controller"
+	depends on USB_EHCI_HCD && MSP_HAS_USB
+	default n
+	select USB_EHCI_BIG_ENDIAN_DESC
+	select USB_EHCI_BIG_ENDIAN_MMIO
+	---help---
+		Enables support for the onchip USB controller on the PMC_MSP7100 Family SoC's.
+		If unsure, say N.
+
 config USB_EHCI_BIG_ENDIAN_MMIO
 	bool
 	depends on USB_EHCI_HCD && (PPC_CELLEB || PPC_PS3 || 440EPX || \
 				    ARCH_IXP4XX || XPS_USB_HCD_XILINX || \
-				    PPC_MPC512x || CPU_CAVIUM_OCTEON)
+				    PPC_MPC512x || CPU_CAVIUM_OCTEON || \
+				    PMC_MSP)
 	default y
 
 config USB_EHCI_BIG_ENDIAN_DESC
 	bool
 	depends on USB_EHCI_HCD && (440EPX || ARCH_IXP4XX || XPS_USB_HCD_XILINX || \
-				    PPC_MPC512x)
+				    PPC_MPC512x || PMC_MSP)
 	default y
 
 config XPS_USB_HCD_XILINX
@@ -145,7 +156,7 @@ config USB_EHCI_MSM
 	bool "Support for MSM on-chip EHCI USB controller"
 	depends on USB_EHCI_HCD && ARCH_MSM
 	select USB_EHCI_ROOT_HUB_TT
-	select USB_MSM_OTG_72K
+	select USB_MSM_OTG
 	---help---
 	  Enables support for the USB Host controller present on the
 	  Qualcomm chipsets. Root Hub has inbuilt TT.
@@ -154,6 +165,14 @@ config USB_EHCI_MSM
 	  This driver is not supported on boards like trout which
 	  has an external PHY.
 
+config USB_EHCI_TEGRA
+       boolean "NVIDIA Tegra HCD support"
+       depends on USB_EHCI_HCD && ARCH_TEGRA
+       select USB_EHCI_ROOT_HUB_TT
+       help
+         This driver enables support for the internal USB Host Controllers
+         found in NVIDIA Tegra SoCs. The controllers are EHCI compliant.
+
 config USB_EHCI_HCD_PPC_OF
 	bool "EHCI support for PPC USB controller on OF platform bus"
 	depends on USB_EHCI_HCD && PPC_OF
@@ -162,6 +181,13 @@ config USB_EHCI_HCD_PPC_OF
 	  Enables support for the USB controller present on the PowerPC
 	  OpenFirmware platform bus.
 
+config USB_EHCI_SH
+	bool "EHCI support for SuperH USB controller"
+	depends on USB_EHCI_HCD && SUPERH
+	---help---
+	  Enables support for the on-chip EHCI controller on the SuperH.
+	  If you use the PCI EHCI controller, this option is not necessary.
+
 config USB_W90X900_EHCI
 	bool "W90X900(W90P910) EHCI support"
 	depends on USB_EHCI_HCD && ARCH_W90X900
@@ -315,6 +341,13 @@ config USB_OHCI_HCD_SSB
 
 	  If unsure, say N.
 
+config USB_OHCI_SH
+	bool "OHCI support for SuperH USB controller"
+	depends on USB_OHCI_HCD && SUPERH
+	---help---
+	  Enables support for the on-chip OHCI controller on the SuperH.
+	  If you use the PCI OHCI controller, this option is not necessary.
+
 config USB_CNS3XXX_OHCI
 	bool "Cavium CNS3XXX OHCI Module"
 	depends on USB_OHCI_HCD && ARCH_CNS3XXX
diff --git a/drivers/usb/host/ehci-atmel.c b/drivers/usb/host/ehci-atmel.c
index d6a69d514a84..b2ed55cb811d 100644
--- a/drivers/usb/host/ehci-atmel.c
+++ b/drivers/usb/host/ehci-atmel.c
@@ -115,7 +115,7 @@ static const struct hc_driver ehci_atmel_hc_driver = {
 	.clear_tt_buffer_complete	= ehci_clear_tt_buffer_complete,
 };
 
-static int __init ehci_atmel_drv_probe(struct platform_device *pdev)
+static int __devinit ehci_atmel_drv_probe(struct platform_device *pdev)
 {
 	struct usb_hcd *hcd;
 	const struct hc_driver *driver = &ehci_atmel_hc_driver;
@@ -207,7 +207,7 @@ fail_create_hcd:
 	return retval;
 }
 
-static int __exit ehci_atmel_drv_remove(struct platform_device *pdev)
+static int __devexit ehci_atmel_drv_remove(struct platform_device *pdev)
 {
 	struct usb_hcd *hcd = platform_get_drvdata(pdev);
 
@@ -227,7 +227,7 @@ static int __exit ehci_atmel_drv_remove(struct platform_device *pdev)
 
 static struct platform_driver ehci_atmel_driver = {
 	.probe		= ehci_atmel_drv_probe,
-	.remove		= __exit_p(ehci_atmel_drv_remove),
+	.remove		= __devexit_p(ehci_atmel_drv_remove),
 	.shutdown	= usb_hcd_platform_shutdown,
 	.driver.name	= "atmel-ehci",
 };
diff --git a/drivers/usb/host/ehci-dbg.c b/drivers/usb/host/ehci-dbg.c
index 3be238a24cc5..693c29b30521 100644
--- a/drivers/usb/host/ehci-dbg.c
+++ b/drivers/usb/host/ehci-dbg.c
@@ -28,11 +28,9 @@
 	dev_warn (ehci_to_hcd(ehci)->self.controller , fmt , ## args )
 
 #ifdef VERBOSE_DEBUG
-#	define vdbg dbg
 #	define ehci_vdbg ehci_dbg
 #else
-#	define vdbg(fmt,args...) do { } while (0)
-#	define ehci_vdbg(ehci, fmt, args...) do { } while (0)
+	static inline void ehci_vdbg(struct ehci_hcd *ehci, ...) {}
 #endif
 
 #ifdef	DEBUG
diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c
index 74dcf49bd015..d30c4e08c137 100644
--- a/drivers/usb/host/ehci-hcd.c
+++ b/drivers/usb/host/ehci-hcd.c
@@ -114,13 +114,11 @@ MODULE_PARM_DESC(hird, "host initiated resume duration, +1 for each 75us\n");
 
 #define	INTR_MASK (STS_IAA | STS_FATAL | STS_PCD | STS_ERR | STS_INT)
 
-/* for ASPM quirk of ISOC on AMD SB800 */
-static struct pci_dev *amd_nb_dev;
-
 /*-------------------------------------------------------------------------*/
 
 #include "ehci.h"
 #include "ehci-dbg.c"
+#include "pci-quirks.h"
 
 /*-------------------------------------------------------------------------*/
 
@@ -532,10 +530,8 @@ static void ehci_stop (struct usb_hcd *hcd)
 	spin_unlock_irq (&ehci->lock);
 	ehci_mem_cleanup (ehci);
 
-	if (amd_nb_dev) {
-		pci_dev_put(amd_nb_dev);
-		amd_nb_dev = NULL;
-	}
+	if (ehci->amd_pll_fix == 1)
+		usb_amd_dev_put();
 
 #ifdef	EHCI_STATS
 	ehci_dbg (ehci, "irq normal %ld err %ld reclaim %ld (lost %ld)\n",
@@ -679,7 +675,12 @@ static int ehci_run (struct usb_hcd *hcd)
 	hcd->uses_new_polling = 1;
 
 	/* EHCI spec section 4.1 */
-	if ((retval = ehci_reset(ehci)) != 0) {
+	/*
+	 * TDI driver does the ehci_reset in their reset callback.
+	 * Don't reset here, because configuration settings will
+	 * vanish.
+	 */
+	if (!ehci_is_TDI(ehci) && (retval = ehci_reset(ehci)) != 0) {
 		ehci_mem_cleanup(ehci);
 		return retval;
 	}
@@ -1179,7 +1180,7 @@ MODULE_LICENSE ("GPL");
 #define PLATFORM_DRIVER		ehci_mxc_driver
 #endif
 
-#ifdef CONFIG_CPU_SUBTYPE_SH7786
+#ifdef CONFIG_USB_EHCI_SH
 #include "ehci-sh.c"
 #define PLATFORM_DRIVER		ehci_hcd_sh_driver
 #endif
@@ -1254,6 +1255,16 @@ MODULE_LICENSE ("GPL");
 #define PLATFORM_DRIVER		ehci_msm_driver
 #endif
 
+#ifdef CONFIG_USB_EHCI_HCD_PMC_MSP
+#include "ehci-pmcmsp.c"
+#define	PLATFORM_DRIVER		ehci_hcd_msp_driver
+#endif
+
+#ifdef CONFIG_USB_EHCI_TEGRA
+#include "ehci-tegra.c"
+#define PLATFORM_DRIVER		tegra_ehci_driver
+#endif
+
 #if !defined(PCI_DRIVER) && !defined(PLATFORM_DRIVER) && \
     !defined(PS3_SYSTEM_BUS_DRIVER) && !defined(OF_PLATFORM_DRIVER) && \
     !defined(XILINX_OF_PLATFORM_DRIVER)
diff --git a/drivers/usb/host/ehci-hub.c b/drivers/usb/host/ehci-hub.c
index 8a515f0d5988..d05ea03cfb4d 100644
--- a/drivers/usb/host/ehci-hub.c
+++ b/drivers/usb/host/ehci-hub.c
@@ -106,6 +106,27 @@ static void ehci_handover_companion_ports(struct ehci_hcd *ehci)
 	ehci->owned_ports = 0;
 }
 
+static int ehci_port_change(struct ehci_hcd *ehci)
+{
+	int i = HCS_N_PORTS(ehci->hcs_params);
+
+	/* First check if the controller indicates a change event */
+
+	if (ehci_readl(ehci, &ehci->regs->status) & STS_PCD)
+		return 1;
+
+	/*
+	 * Not all controllers appear to update this while going from D3 to D0,
+	 * so check the individual port status registers as well
+	 */
+
+	while (i--)
+		if (ehci_readl(ehci, &ehci->regs->port_status[i]) & PORT_CSC)
+			return 1;
+
+	return 0;
+}
+
 static void ehci_adjust_port_wakeup_flags(struct ehci_hcd *ehci,
 		bool suspending, bool do_wakeup)
 {
@@ -173,7 +194,7 @@ static void ehci_adjust_port_wakeup_flags(struct ehci_hcd *ehci,
 	}
 
 	/* Does the root hub have a port wakeup pending? */
-	if (!suspending && (ehci_readl(ehci, &ehci->regs->status) & STS_PCD))
+	if (!suspending && ehci_port_change(ehci))
 		usb_hcd_resume_root_hub(ehci_to_hcd(ehci));
 
 	spin_unlock_irqrestore(&ehci->lock, flags);
@@ -538,14 +559,15 @@ static ssize_t store_companion(struct device *dev,
 }
 static DEVICE_ATTR(companion, 0644, show_companion, store_companion);
 
-static inline void create_companion_file(struct ehci_hcd *ehci)
+static inline int create_companion_file(struct ehci_hcd *ehci)
 {
-	int	i;
+	int	i = 0;
 
 	/* with integrated TT there is no companion! */
 	if (!ehci_is_TDI(ehci))
 		i = device_create_file(ehci_to_hcd(ehci)->self.controller,
 				       &dev_attr_companion);
+	return i;
 }
 
 static inline void remove_companion_file(struct ehci_hcd *ehci)
@@ -695,8 +717,8 @@ ehci_hub_descriptor (
 	desc->bDescLength = 7 + 2 * temp;
 
 	/* two bitmaps:  ports removable, and usb 1.0 legacy PortPwrCtrlMask */
-	memset (&desc->bitmap [0], 0, temp);
-	memset (&desc->bitmap [temp], 0xff, temp);
+	memset(&desc->u.hs.DeviceRemovable[0], 0, temp);
+	memset(&desc->u.hs.DeviceRemovable[temp], 0xff, temp);
 
 	temp = 0x0008;			/* per-port overcurrent reporting */
 	if (HCS_PPC (ehci->hcs_params))
diff --git a/drivers/usb/host/ehci-lpm.c b/drivers/usb/host/ehci-lpm.c
index b4d4d63c13ed..2111627a19de 100644
--- a/drivers/usb/host/ehci-lpm.c
+++ b/drivers/usb/host/ehci-lpm.c
@@ -17,7 +17,8 @@
 */
 
 /* this file is part of ehci-hcd.c */
-static int ehci_lpm_set_da(struct ehci_hcd *ehci, int dev_addr, int port_num)
+static int __maybe_unused ehci_lpm_set_da(struct ehci_hcd *ehci,
+	int dev_addr, int port_num)
 {
 	u32 __iomem portsc;
 
@@ -37,7 +38,7 @@ static int ehci_lpm_set_da(struct ehci_hcd *ehci, int dev_addr, int port_num)
  * this function is used to check if the device support LPM
  * if yes, mark the PORTSC register with PORT_LPM bit
  */
-static int ehci_lpm_check(struct ehci_hcd *ehci, int port)
+static int __maybe_unused ehci_lpm_check(struct ehci_hcd *ehci, int port)
 {
 	u32 __iomem	*portsc ;
 	u32 val32;
diff --git a/drivers/usb/host/ehci-msm.c b/drivers/usb/host/ehci-msm.c
index 413f4deca532..9ce1b0bc186d 100644
--- a/drivers/usb/host/ehci-msm.c
+++ b/drivers/usb/host/ehci-msm.c
@@ -1,6 +1,6 @@
 /* ehci-msm.c - HSUSB Host Controller Driver Implementation
  *
- * Copyright (c) 2008-2010, Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2008-2011, Code Aurora Forum. All rights reserved.
  *
  * Partly derived from ehci-fsl.c and ehci-hcd.c
  * Copyright (c) 2000-2004 by David Brownell
@@ -34,92 +34,6 @@
 
 static struct otg_transceiver *otg;
 
-/*
- * ehci_run defined in drivers/usb/host/ehci-hcd.c reset the controller and
- * the configuration settings in ehci_msm_reset vanish after controller is
- * reset. Resetting the controler in ehci_run seems to be un-necessary
- * provided HCD reset the controller before calling ehci_run. Most of the HCD
- * do but some are not. So this function is same as ehci_run but we don't
- * reset the controller here.
- */
-static int ehci_msm_run(struct usb_hcd *hcd)
-{
-	struct ehci_hcd		*ehci = hcd_to_ehci(hcd);
-	u32			temp;
-	u32			hcc_params;
-
-	hcd->uses_new_polling = 1;
-
-	ehci_writel(ehci, ehci->periodic_dma, &ehci->regs->frame_list);
-	ehci_writel(ehci, (u32)ehci->async->qh_dma, &ehci->regs->async_next);
-
-	/*
-	 * hcc_params controls whether ehci->regs->segment must (!!!)
-	 * be used; it constrains QH/ITD/SITD and QTD locations.
-	 * pci_pool consistent memory always uses segment zero.
-	 * streaming mappings for I/O buffers, like pci_map_single(),
-	 * can return segments above 4GB, if the device allows.
-	 *
-	 * NOTE:  the dma mask is visible through dma_supported(), so
-	 * drivers can pass this info along ... like NETIF_F_HIGHDMA,
-	 * Scsi_Host.highmem_io, and so forth.  It's readonly to all
-	 * host side drivers though.
-	 */
-	hcc_params = ehci_readl(ehci, &ehci->caps->hcc_params);
-	if (HCC_64BIT_ADDR(hcc_params))
-		ehci_writel(ehci, 0, &ehci->regs->segment);
-
-	/*
-	 * Philips, Intel, and maybe others need CMD_RUN before the
-	 * root hub will detect new devices (why?); NEC doesn't
-	 */
-	ehci->command &= ~(CMD_LRESET|CMD_IAAD|CMD_PSE|CMD_ASE|CMD_RESET);
-	ehci->command |= CMD_RUN;
-	ehci_writel(ehci, ehci->command, &ehci->regs->command);
-	dbg_cmd(ehci, "init", ehci->command);
-
-	/*
-	 * Start, enabling full USB 2.0 functionality ... usb 1.1 devices
-	 * are explicitly handed to companion controller(s), so no TT is
-	 * involved with the root hub.  (Except where one is integrated,
-	 * and there's no companion controller unless maybe for USB OTG.)
-	 *
-	 * Turning on the CF flag will transfer ownership of all ports
-	 * from the companions to the EHCI controller.  If any of the
-	 * companions are in the middle of a port reset at the time, it
-	 * could cause trouble.  Write-locking ehci_cf_port_reset_rwsem
-	 * guarantees that no resets are in progress.  After we set CF,
-	 * a short delay lets the hardware catch up; new resets shouldn't
-	 * be started before the port switching actions could complete.
-	 */
-	down_write(&ehci_cf_port_reset_rwsem);
-	hcd->state = HC_STATE_RUNNING;
-	ehci_writel(ehci, FLAG_CF, &ehci->regs->configured_flag);
-	ehci_readl(ehci, &ehci->regs->command);	/* unblock posted writes */
-	usleep_range(5000, 5500);
-	up_write(&ehci_cf_port_reset_rwsem);
-	ehci->last_periodic_enable = ktime_get_real();
-
-	temp = HC_VERSION(ehci_readl(ehci, &ehci->caps->hc_capbase));
-	ehci_info(ehci,
-		"USB %x.%x started, EHCI %x.%02x%s\n",
-		((ehci->sbrn & 0xf0)>>4), (ehci->sbrn & 0x0f),
-		temp >> 8, temp & 0xff,
-		ignore_oc ? ", overcurrent ignored" : "");
-
-	ehci_writel(ehci, INTR_MASK,
-		    &ehci->regs->intr_enable); /* Turn On Interrupts */
-
-	/* GRR this is run-once init(), being done every time the HC starts.
-	 * So long as they're part of class devices, we can't do it init()
-	 * since the class device isn't created that early.
-	 */
-	create_debug_files(ehci);
-	create_companion_file(ehci);
-
-	return 0;
-}
-
 static int ehci_msm_reset(struct usb_hcd *hcd)
 {
 	struct ehci_hcd *ehci = hcd_to_ehci(hcd);
@@ -128,6 +42,8 @@ static int ehci_msm_reset(struct usb_hcd *hcd)
 	ehci->caps = USB_CAPLENGTH;
 	ehci->regs = USB_CAPLENGTH +
 		HC_LENGTH(ehci_readl(ehci, &ehci->caps->hc_capbase));
+	dbg_hcs_params(ehci, "reset");
+	dbg_hcc_params(ehci, "reset");
 
 	/* cache the data to minimize the chip reads*/
 	ehci->hcs_params = ehci_readl(ehci, &ehci->caps->hcs_params);
@@ -135,6 +51,10 @@ static int ehci_msm_reset(struct usb_hcd *hcd)
 	hcd->has_tt = 1;
 	ehci->sbrn = HCD_USB2;
 
+	retval = ehci_halt(ehci);
+	if (retval)
+		return retval;
+
 	/* data structure init */
 	retval = ehci_init(hcd);
 	if (retval)
@@ -167,7 +87,7 @@ static struct hc_driver msm_hc_driver = {
 	.flags			= HCD_USB2 | HCD_MEMORY,
 
 	.reset			= ehci_msm_reset,
-	.start			= ehci_msm_run,
+	.start			= ehci_run,
 
 	.stop			= ehci_stop,
 	.shutdown		= ehci_shutdown,
diff --git a/drivers/usb/host/ehci-omap.c b/drivers/usb/host/ehci-omap.c
index f784ceb862a3..7e41a95c5ceb 100644
--- a/drivers/usb/host/ehci-omap.c
+++ b/drivers/usb/host/ehci-omap.c
@@ -4,9 +4,10 @@
  * Bus Glue for the EHCI controllers in OMAP3/4
  * Tested on several OMAP3 boards, and OMAP4 Pandaboard
  *
- * Copyright (C) 2007-2010 Texas Instruments, Inc.
+ * Copyright (C) 2007-2011 Texas Instruments, Inc.
  *	Author: Vikram Pandita <vikram.pandita@ti.com>
  *	Author: Anand Gadiyar <gadiyar@ti.com>
+ *	Author: Keshava Munegowda <keshava_mgowda@ti.com>
  *
  * Copyright (C) 2009 Nokia Corporation
  *	Contact: Felipe Balbi <felipe.balbi@nokia.com>
@@ -27,116 +28,19 @@
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
  *
- * TODO (last updated Nov 21, 2010):
+ * TODO (last updated Feb 27, 2010):
  *	- add kernel-doc
  *	- enable AUTOIDLE
  *	- add suspend/resume
- *	- move workarounds to board-files
- *	- factor out code common to OHCI
  *	- add HSIC and TLL support
  *	- convert to use hwmod and runtime PM
  */
 
 #include <linux/platform_device.h>
-#include <linux/clk.h>
-#include <linux/gpio.h>
-#include <linux/regulator/consumer.h>
 #include <linux/slab.h>
 #include <linux/usb/ulpi.h>
 #include <plat/usb.h>
 
-/*
- * OMAP USBHOST Register addresses: VIRTUAL ADDRESSES
- *	Use ehci_omap_readl()/ehci_omap_writel() functions
- */
-
-/* TLL Register Set */
-#define	OMAP_USBTLL_REVISION				(0x00)
-#define	OMAP_USBTLL_SYSCONFIG				(0x10)
-#define	OMAP_USBTLL_SYSCONFIG_CACTIVITY			(1 << 8)
-#define	OMAP_USBTLL_SYSCONFIG_SIDLEMODE			(1 << 3)
-#define	OMAP_USBTLL_SYSCONFIG_ENAWAKEUP			(1 << 2)
-#define	OMAP_USBTLL_SYSCONFIG_SOFTRESET			(1 << 1)
-#define	OMAP_USBTLL_SYSCONFIG_AUTOIDLE			(1 << 0)
-
-#define	OMAP_USBTLL_SYSSTATUS				(0x14)
-#define	OMAP_USBTLL_SYSSTATUS_RESETDONE			(1 << 0)
-
-#define	OMAP_USBTLL_IRQSTATUS				(0x18)
-#define	OMAP_USBTLL_IRQENABLE				(0x1C)
-
-#define	OMAP_TLL_SHARED_CONF				(0x30)
-#define	OMAP_TLL_SHARED_CONF_USB_90D_DDR_EN		(1 << 6)
-#define	OMAP_TLL_SHARED_CONF_USB_180D_SDR_EN		(1 << 5)
-#define	OMAP_TLL_SHARED_CONF_USB_DIVRATION		(1 << 2)
-#define	OMAP_TLL_SHARED_CONF_FCLK_REQ			(1 << 1)
-#define	OMAP_TLL_SHARED_CONF_FCLK_IS_ON			(1 << 0)
-
-#define	OMAP_TLL_CHANNEL_CONF(num)			(0x040 + 0x004 * num)
-#define	OMAP_TLL_CHANNEL_CONF_ULPINOBITSTUFF		(1 << 11)
-#define	OMAP_TLL_CHANNEL_CONF_ULPI_ULPIAUTOIDLE		(1 << 10)
-#define	OMAP_TLL_CHANNEL_CONF_UTMIAUTOIDLE		(1 << 9)
-#define	OMAP_TLL_CHANNEL_CONF_ULPIDDRMODE		(1 << 8)
-#define	OMAP_TLL_CHANNEL_CONF_CHANEN			(1 << 0)
-
-#define	OMAP_TLL_ULPI_FUNCTION_CTRL(num)		(0x804 + 0x100 * num)
-#define	OMAP_TLL_ULPI_INTERFACE_CTRL(num)		(0x807 + 0x100 * num)
-#define	OMAP_TLL_ULPI_OTG_CTRL(num)			(0x80A + 0x100 * num)
-#define	OMAP_TLL_ULPI_INT_EN_RISE(num)			(0x80D + 0x100 * num)
-#define	OMAP_TLL_ULPI_INT_EN_FALL(num)			(0x810 + 0x100 * num)
-#define	OMAP_TLL_ULPI_INT_STATUS(num)			(0x813 + 0x100 * num)
-#define	OMAP_TLL_ULPI_INT_LATCH(num)			(0x814 + 0x100 * num)
-#define	OMAP_TLL_ULPI_DEBUG(num)			(0x815 + 0x100 * num)
-#define	OMAP_TLL_ULPI_SCRATCH_REGISTER(num)		(0x816 + 0x100 * num)
-
-#define OMAP_TLL_CHANNEL_COUNT				3
-#define OMAP_TLL_CHANNEL_1_EN_MASK			(1 << 0)
-#define OMAP_TLL_CHANNEL_2_EN_MASK			(1 << 1)
-#define OMAP_TLL_CHANNEL_3_EN_MASK			(1 << 2)
-
-/* UHH Register Set */
-#define	OMAP_UHH_REVISION				(0x00)
-#define	OMAP_UHH_SYSCONFIG				(0x10)
-#define	OMAP_UHH_SYSCONFIG_MIDLEMODE			(1 << 12)
-#define	OMAP_UHH_SYSCONFIG_CACTIVITY			(1 << 8)
-#define	OMAP_UHH_SYSCONFIG_SIDLEMODE			(1 << 3)
-#define	OMAP_UHH_SYSCONFIG_ENAWAKEUP			(1 << 2)
-#define	OMAP_UHH_SYSCONFIG_SOFTRESET			(1 << 1)
-#define	OMAP_UHH_SYSCONFIG_AUTOIDLE			(1 << 0)
-
-#define	OMAP_UHH_SYSSTATUS				(0x14)
-#define	OMAP_UHH_HOSTCONFIG				(0x40)
-#define	OMAP_UHH_HOSTCONFIG_ULPI_BYPASS			(1 << 0)
-#define	OMAP_UHH_HOSTCONFIG_ULPI_P1_BYPASS		(1 << 0)
-#define	OMAP_UHH_HOSTCONFIG_ULPI_P2_BYPASS		(1 << 11)
-#define	OMAP_UHH_HOSTCONFIG_ULPI_P3_BYPASS		(1 << 12)
-#define OMAP_UHH_HOSTCONFIG_INCR4_BURST_EN		(1 << 2)
-#define OMAP_UHH_HOSTCONFIG_INCR8_BURST_EN		(1 << 3)
-#define OMAP_UHH_HOSTCONFIG_INCR16_BURST_EN		(1 << 4)
-#define OMAP_UHH_HOSTCONFIG_INCRX_ALIGN_EN		(1 << 5)
-#define OMAP_UHH_HOSTCONFIG_P1_CONNECT_STATUS		(1 << 8)
-#define OMAP_UHH_HOSTCONFIG_P2_CONNECT_STATUS		(1 << 9)
-#define OMAP_UHH_HOSTCONFIG_P3_CONNECT_STATUS		(1 << 10)
-
-/* OMAP4-specific defines */
-#define OMAP4_UHH_SYSCONFIG_IDLEMODE_CLEAR		(3 << 2)
-#define OMAP4_UHH_SYSCONFIG_NOIDLE			(1 << 2)
-
-#define OMAP4_UHH_SYSCONFIG_STDBYMODE_CLEAR		(3 << 4)
-#define OMAP4_UHH_SYSCONFIG_NOSTDBY			(1 << 4)
-#define OMAP4_UHH_SYSCONFIG_SOFTRESET			(1 << 0)
-
-#define OMAP4_P1_MODE_CLEAR				(3 << 16)
-#define OMAP4_P1_MODE_TLL				(1 << 16)
-#define OMAP4_P1_MODE_HSIC				(3 << 16)
-#define OMAP4_P2_MODE_CLEAR				(3 << 18)
-#define OMAP4_P2_MODE_TLL				(1 << 18)
-#define OMAP4_P2_MODE_HSIC				(3 << 18)
-
-#define OMAP_REV2_TLL_CHANNEL_COUNT			2
-
-#define	OMAP_UHH_DEBUG_CSR				(0x44)
-
 /* EHCI Register Set */
 #define EHCI_INSNREG04					(0xA0)
 #define EHCI_INSNREG04_DISABLE_UNSUSPEND		(1 << 5)
@@ -148,137 +52,24 @@
 #define	EHCI_INSNREG05_ULPI_EXTREGADD_SHIFT		8
 #define	EHCI_INSNREG05_ULPI_WRDATA_SHIFT		0
 
-/* Values of UHH_REVISION - Note: these are not given in the TRM */
-#define OMAP_EHCI_REV1	0x00000010	/* OMAP3 */
-#define OMAP_EHCI_REV2	0x50700100	/* OMAP4 */
-
-#define is_omap_ehci_rev1(x)	(x->omap_ehci_rev == OMAP_EHCI_REV1)
-#define is_omap_ehci_rev2(x)	(x->omap_ehci_rev == OMAP_EHCI_REV2)
+/*-------------------------------------------------------------------------*/
 
-#define is_ehci_phy_mode(x)	(x == EHCI_HCD_OMAP_MODE_PHY)
-#define is_ehci_tll_mode(x)	(x == EHCI_HCD_OMAP_MODE_TLL)
-#define is_ehci_hsic_mode(x)	(x == EHCI_HCD_OMAP_MODE_HSIC)
+static const struct hc_driver ehci_omap_hc_driver;
 
-/*-------------------------------------------------------------------------*/
 
-static inline void ehci_omap_writel(void __iomem *base, u32 reg, u32 val)
+static inline void ehci_write(void __iomem *base, u32 reg, u32 val)
 {
 	__raw_writel(val, base + reg);
 }
 
-static inline u32 ehci_omap_readl(void __iomem *base, u32 reg)
+static inline u32 ehci_read(void __iomem *base, u32 reg)
 {
 	return __raw_readl(base + reg);
 }
 
-static inline void ehci_omap_writeb(void __iomem *base, u8 reg, u8 val)
-{
-	__raw_writeb(val, base + reg);
-}
-
-static inline u8 ehci_omap_readb(void __iomem *base, u8 reg)
-{
-	return __raw_readb(base + reg);
-}
-
-/*-------------------------------------------------------------------------*/
-
-struct ehci_hcd_omap {
-	struct ehci_hcd		*ehci;
-	struct device		*dev;
-
-	struct clk		*usbhost_ick;
-	struct clk		*usbhost_hs_fck;
-	struct clk		*usbhost_fs_fck;
-	struct clk		*usbtll_fck;
-	struct clk		*usbtll_ick;
-	struct clk		*xclk60mhsp1_ck;
-	struct clk		*xclk60mhsp2_ck;
-	struct clk		*utmi_p1_fck;
-	struct clk		*utmi_p2_fck;
-
-	/* FIXME the following two workarounds are
-	 * board specific not silicon-specific so these
-	 * should be moved to board-file instead.
-	 *
-	 * Maybe someone from TI will know better which
-	 * board is affected and needs the workarounds
-	 * to be applied
-	 */
-
-	/* gpio for resetting phy */
-	int			reset_gpio_port[OMAP3_HS_USB_PORTS];
-
-	/* phy reset workaround */
-	int			phy_reset;
-
-	/* IP revision */
-	u32			omap_ehci_rev;
-
-	/* desired phy_mode: TLL, PHY */
-	enum ehci_hcd_omap_mode	port_mode[OMAP3_HS_USB_PORTS];
-
-	void __iomem		*uhh_base;
-	void __iomem		*tll_base;
-	void __iomem		*ehci_base;
-
-	/* Regulators for USB PHYs.
-	 * Each PHY can have a separate regulator.
-	 */
-	struct regulator        *regulator[OMAP3_HS_USB_PORTS];
-};
-
-/*-------------------------------------------------------------------------*/
-
-static void omap_usb_utmi_init(struct ehci_hcd_omap *omap, u8 tll_channel_mask,
-				u8 tll_channel_count)
-{
-	unsigned reg;
-	int i;
-
-	/* Program the 3 TLL channels upfront */
-	for (i = 0; i < tll_channel_count; i++) {
-		reg = ehci_omap_readl(omap->tll_base, OMAP_TLL_CHANNEL_CONF(i));
-
-		/* Disable AutoIdle, BitStuffing and use SDR Mode */
-		reg &= ~(OMAP_TLL_CHANNEL_CONF_UTMIAUTOIDLE
-				| OMAP_TLL_CHANNEL_CONF_ULPINOBITSTUFF
-				| OMAP_TLL_CHANNEL_CONF_ULPIDDRMODE);
-		ehci_omap_writel(omap->tll_base, OMAP_TLL_CHANNEL_CONF(i), reg);
-	}
-
-	/* Program Common TLL register */
-	reg = ehci_omap_readl(omap->tll_base, OMAP_TLL_SHARED_CONF);
-	reg |= (OMAP_TLL_SHARED_CONF_FCLK_IS_ON
-			| OMAP_TLL_SHARED_CONF_USB_DIVRATION
-			| OMAP_TLL_SHARED_CONF_USB_180D_SDR_EN);
-	reg &= ~OMAP_TLL_SHARED_CONF_USB_90D_DDR_EN;
-
-	ehci_omap_writel(omap->tll_base, OMAP_TLL_SHARED_CONF, reg);
-
-	/* Enable channels now */
-	for (i = 0; i < tll_channel_count; i++) {
-		reg = ehci_omap_readl(omap->tll_base, OMAP_TLL_CHANNEL_CONF(i));
-
-		/* Enable only the reg that is needed */
-		if (!(tll_channel_mask & 1<<i))
-			continue;
-
-		reg |= OMAP_TLL_CHANNEL_CONF_CHANEN;
-		ehci_omap_writel(omap->tll_base, OMAP_TLL_CHANNEL_CONF(i), reg);
-
-		ehci_omap_writeb(omap->tll_base,
-				OMAP_TLL_ULPI_SCRATCH_REGISTER(i), 0xbe);
-		dev_dbg(omap->dev, "ULPI_SCRATCH_REG[ch=%d]= 0x%02x\n",
-				i+1, ehci_omap_readb(omap->tll_base,
-				OMAP_TLL_ULPI_SCRATCH_REGISTER(i)));
-	}
-}
-
-/*-------------------------------------------------------------------------*/
-
-static void omap_ehci_soft_phy_reset(struct ehci_hcd_omap *omap, u8 port)
+static void omap_ehci_soft_phy_reset(struct platform_device *pdev, u8 port)
 {
+	struct usb_hcd	*hcd = dev_get_drvdata(&pdev->dev);
 	unsigned long timeout = jiffies + msecs_to_jiffies(1000);
 	unsigned reg = 0;
 
@@ -292,266 +83,87 @@ static void omap_ehci_soft_phy_reset(struct ehci_hcd_omap *omap, u8 port)
 		/* start ULPI access*/
 		| (1 << EHCI_INSNREG05_ULPI_CONTROL_SHIFT);
 
-	ehci_omap_writel(omap->ehci_base, EHCI_INSNREG05_ULPI, reg);
+	ehci_write(hcd->regs, EHCI_INSNREG05_ULPI, reg);
 
 	/* Wait for ULPI access completion */
-	while ((ehci_omap_readl(omap->ehci_base, EHCI_INSNREG05_ULPI)
+	while ((ehci_read(hcd->regs, EHCI_INSNREG05_ULPI)
 			& (1 << EHCI_INSNREG05_ULPI_CONTROL_SHIFT))) {
 		cpu_relax();
 
 		if (time_after(jiffies, timeout)) {
-			dev_dbg(omap->dev, "phy reset operation timed out\n");
+			dev_dbg(&pdev->dev, "phy reset operation timed out\n");
 			break;
 		}
 	}
 }
 
-/* omap_start_ehc
- *	- Start the TI USBHOST controller
- */
-static int omap_start_ehc(struct ehci_hcd_omap *omap, struct usb_hcd *hcd)
-{
-	unsigned long timeout = jiffies + msecs_to_jiffies(1000);
-	u8 tll_ch_mask = 0;
-	unsigned reg = 0;
-	int ret = 0;
-
-	dev_dbg(omap->dev, "starting TI EHCI USB Controller\n");
 
-	/* Enable Clocks for USBHOST */
-	omap->usbhost_ick = clk_get(omap->dev, "usbhost_ick");
-	if (IS_ERR(omap->usbhost_ick)) {
-		ret =  PTR_ERR(omap->usbhost_ick);
-		goto err_host_ick;
-	}
-	clk_enable(omap->usbhost_ick);
-
-	omap->usbhost_hs_fck = clk_get(omap->dev, "hs_fck");
-	if (IS_ERR(omap->usbhost_hs_fck)) {
-		ret = PTR_ERR(omap->usbhost_hs_fck);
-		goto err_host_120m_fck;
-	}
-	clk_enable(omap->usbhost_hs_fck);
+/* configure so an HC device and id are always provided */
+/* always called with process context; sleeping is OK */
 
-	omap->usbhost_fs_fck = clk_get(omap->dev, "fs_fck");
-	if (IS_ERR(omap->usbhost_fs_fck)) {
-		ret = PTR_ERR(omap->usbhost_fs_fck);
-		goto err_host_48m_fck;
-	}
-	clk_enable(omap->usbhost_fs_fck);
-
-	if (omap->phy_reset) {
-		/* Refer: ISSUE1 */
-		if (gpio_is_valid(omap->reset_gpio_port[0])) {
-			gpio_request(omap->reset_gpio_port[0],
-						"USB1 PHY reset");
-			gpio_direction_output(omap->reset_gpio_port[0], 0);
-		}
+/**
+ * ehci_hcd_omap_probe - initialize TI-based HCDs
+ *
+ * Allocates basic resources for this USB host controller, and
+ * then invokes the start() method for the HCD associated with it
+ * through the hotplug entry's driver_data.
+ */
+static int ehci_hcd_omap_probe(struct platform_device *pdev)
+{
+	struct device				*dev = &pdev->dev;
+	struct ehci_hcd_omap_platform_data	*pdata = dev->platform_data;
+	struct resource				*res;
+	struct usb_hcd				*hcd;
+	void __iomem				*regs;
+	struct ehci_hcd				*omap_ehci;
+	int					ret = -ENODEV;
+	int					irq;
 
-		if (gpio_is_valid(omap->reset_gpio_port[1])) {
-			gpio_request(omap->reset_gpio_port[1],
-						"USB2 PHY reset");
-			gpio_direction_output(omap->reset_gpio_port[1], 0);
-		}
+	if (usb_disabled())
+		return -ENODEV;
 
-		/* Hold the PHY in RESET for enough time till DIR is high */
-		udelay(10);
+	if (!dev->parent) {
+		dev_err(dev, "Missing parent device\n");
+		return -ENODEV;
 	}
 
-	/* Configure TLL for 60Mhz clk for ULPI */
-	omap->usbtll_fck = clk_get(omap->dev, "usbtll_fck");
-	if (IS_ERR(omap->usbtll_fck)) {
-		ret = PTR_ERR(omap->usbtll_fck);
-		goto err_tll_fck;
+	irq = platform_get_irq_byname(pdev, "ehci-irq");
+	if (irq < 0) {
+		dev_err(dev, "EHCI irq failed\n");
+		return -ENODEV;
 	}
-	clk_enable(omap->usbtll_fck);
 
-	omap->usbtll_ick = clk_get(omap->dev, "usbtll_ick");
-	if (IS_ERR(omap->usbtll_ick)) {
-		ret = PTR_ERR(omap->usbtll_ick);
-		goto err_tll_ick;
+	res =  platform_get_resource_byname(pdev,
+				IORESOURCE_MEM, "ehci");
+	if (!res) {
+		dev_err(dev, "UHH EHCI get resource failed\n");
+		return -ENODEV;
 	}
-	clk_enable(omap->usbtll_ick);
-
-	omap->omap_ehci_rev = ehci_omap_readl(omap->uhh_base,
-						OMAP_UHH_REVISION);
-	dev_dbg(omap->dev, "OMAP UHH_REVISION 0x%x\n",
-					omap->omap_ehci_rev);
 
-	/*
-	 * Enable per-port clocks as needed (newer controllers only).
-	 * - External ULPI clock for PHY mode
-	 * - Internal clocks for TLL and HSIC modes (TODO)
-	 */
-	if (is_omap_ehci_rev2(omap)) {
-		switch (omap->port_mode[0]) {
-		case EHCI_HCD_OMAP_MODE_PHY:
-			omap->xclk60mhsp1_ck = clk_get(omap->dev,
-							"xclk60mhsp1_ck");
-			if (IS_ERR(omap->xclk60mhsp1_ck)) {
-				ret = PTR_ERR(omap->xclk60mhsp1_ck);
-				dev_err(omap->dev,
-					"Unable to get Port1 ULPI clock\n");
-			}
-
-			omap->utmi_p1_fck = clk_get(omap->dev,
-							"utmi_p1_gfclk");
-			if (IS_ERR(omap->utmi_p1_fck)) {
-				ret = PTR_ERR(omap->utmi_p1_fck);
-				dev_err(omap->dev,
-					"Unable to get utmi_p1_fck\n");
-			}
-
-			ret = clk_set_parent(omap->utmi_p1_fck,
-						omap->xclk60mhsp1_ck);
-			if (ret != 0) {
-				dev_err(omap->dev,
-					"Unable to set P1 f-clock\n");
-			}
-			break;
-		case EHCI_HCD_OMAP_MODE_TLL:
-			/* TODO */
-		default:
-			break;
-		}
-		switch (omap->port_mode[1]) {
-		case EHCI_HCD_OMAP_MODE_PHY:
-			omap->xclk60mhsp2_ck = clk_get(omap->dev,
-							"xclk60mhsp2_ck");
-			if (IS_ERR(omap->xclk60mhsp2_ck)) {
-				ret = PTR_ERR(omap->xclk60mhsp2_ck);
-				dev_err(omap->dev,
-					"Unable to get Port2 ULPI clock\n");
-			}
-
-			omap->utmi_p2_fck = clk_get(omap->dev,
-							"utmi_p2_gfclk");
-			if (IS_ERR(omap->utmi_p2_fck)) {
-				ret = PTR_ERR(omap->utmi_p2_fck);
-				dev_err(omap->dev,
-					"Unable to get utmi_p2_fck\n");
-			}
-
-			ret = clk_set_parent(omap->utmi_p2_fck,
-						omap->xclk60mhsp2_ck);
-			if (ret != 0) {
-				dev_err(omap->dev,
-					"Unable to set P2 f-clock\n");
-			}
-			break;
-		case EHCI_HCD_OMAP_MODE_TLL:
-			/* TODO */
-		default:
-			break;
-		}
+	regs = ioremap(res->start, resource_size(res));
+	if (!regs) {
+		dev_err(dev, "UHH EHCI ioremap failed\n");
+		return -ENOMEM;
 	}
 
-
-	/* perform TLL soft reset, and wait until reset is complete */
-	ehci_omap_writel(omap->tll_base, OMAP_USBTLL_SYSCONFIG,
-			OMAP_USBTLL_SYSCONFIG_SOFTRESET);
-
-	/* Wait for TLL reset to complete */
-	while (!(ehci_omap_readl(omap->tll_base, OMAP_USBTLL_SYSSTATUS)
-			& OMAP_USBTLL_SYSSTATUS_RESETDONE)) {
-		cpu_relax();
-
-		if (time_after(jiffies, timeout)) {
-			dev_dbg(omap->dev, "operation timed out\n");
-			ret = -EINVAL;
-			goto err_sys_status;
-		}
+	hcd = usb_create_hcd(&ehci_omap_hc_driver, dev,
+			dev_name(dev));
+	if (!hcd) {
+		dev_err(dev, "failed to create hcd with err %d\n", ret);
+		ret = -ENOMEM;
+		goto err_io;
 	}
 
-	dev_dbg(omap->dev, "TLL RESET DONE\n");
-
-	/* (1<<3) = no idle mode only for initial debugging */
-	ehci_omap_writel(omap->tll_base, OMAP_USBTLL_SYSCONFIG,
-			OMAP_USBTLL_SYSCONFIG_ENAWAKEUP |
-			OMAP_USBTLL_SYSCONFIG_SIDLEMODE |
-			OMAP_USBTLL_SYSCONFIG_CACTIVITY);
-
-
-	/* Put UHH in NoIdle/NoStandby mode */
-	reg = ehci_omap_readl(omap->uhh_base, OMAP_UHH_SYSCONFIG);
-	if (is_omap_ehci_rev1(omap)) {
-		reg |= (OMAP_UHH_SYSCONFIG_ENAWAKEUP
-				| OMAP_UHH_SYSCONFIG_SIDLEMODE
-				| OMAP_UHH_SYSCONFIG_CACTIVITY
-				| OMAP_UHH_SYSCONFIG_MIDLEMODE);
-		reg &= ~OMAP_UHH_SYSCONFIG_AUTOIDLE;
-
+	hcd->rsrc_start = res->start;
+	hcd->rsrc_len = resource_size(res);
+	hcd->regs = regs;
 
-	} else if (is_omap_ehci_rev2(omap)) {
-		reg &= ~OMAP4_UHH_SYSCONFIG_IDLEMODE_CLEAR;
-		reg |= OMAP4_UHH_SYSCONFIG_NOIDLE;
-		reg &= ~OMAP4_UHH_SYSCONFIG_STDBYMODE_CLEAR;
-		reg |= OMAP4_UHH_SYSCONFIG_NOSTDBY;
-	}
-	ehci_omap_writel(omap->uhh_base, OMAP_UHH_SYSCONFIG, reg);
-
-	reg = ehci_omap_readl(omap->uhh_base, OMAP_UHH_HOSTCONFIG);
-
-	/* setup ULPI bypass and burst configurations */
-	reg |= (OMAP_UHH_HOSTCONFIG_INCR4_BURST_EN
-			| OMAP_UHH_HOSTCONFIG_INCR8_BURST_EN
-			| OMAP_UHH_HOSTCONFIG_INCR16_BURST_EN);
-	reg &= ~OMAP_UHH_HOSTCONFIG_INCRX_ALIGN_EN;
-
-	if (is_omap_ehci_rev1(omap)) {
-		if (omap->port_mode[0] == EHCI_HCD_OMAP_MODE_UNKNOWN)
-			reg &= ~OMAP_UHH_HOSTCONFIG_P1_CONNECT_STATUS;
-		if (omap->port_mode[1] == EHCI_HCD_OMAP_MODE_UNKNOWN)
-			reg &= ~OMAP_UHH_HOSTCONFIG_P2_CONNECT_STATUS;
-		if (omap->port_mode[2] == EHCI_HCD_OMAP_MODE_UNKNOWN)
-			reg &= ~OMAP_UHH_HOSTCONFIG_P3_CONNECT_STATUS;
-
-		/* Bypass the TLL module for PHY mode operation */
-		if (cpu_is_omap3430() && (omap_rev() <= OMAP3430_REV_ES2_1)) {
-			dev_dbg(omap->dev, "OMAP3 ES version <= ES2.1\n");
-			if (is_ehci_phy_mode(omap->port_mode[0]) ||
-				is_ehci_phy_mode(omap->port_mode[1]) ||
-					is_ehci_phy_mode(omap->port_mode[2]))
-				reg &= ~OMAP_UHH_HOSTCONFIG_ULPI_BYPASS;
-			else
-				reg |= OMAP_UHH_HOSTCONFIG_ULPI_BYPASS;
-		} else {
-			dev_dbg(omap->dev, "OMAP3 ES version > ES2.1\n");
-			if (is_ehci_phy_mode(omap->port_mode[0]))
-				reg &= ~OMAP_UHH_HOSTCONFIG_ULPI_P1_BYPASS;
-			else if (is_ehci_tll_mode(omap->port_mode[0]))
-				reg |= OMAP_UHH_HOSTCONFIG_ULPI_P1_BYPASS;
-
-			if (is_ehci_phy_mode(omap->port_mode[1]))
-				reg &= ~OMAP_UHH_HOSTCONFIG_ULPI_P2_BYPASS;
-			else if (is_ehci_tll_mode(omap->port_mode[1]))
-				reg |= OMAP_UHH_HOSTCONFIG_ULPI_P2_BYPASS;
-
-			if (is_ehci_phy_mode(omap->port_mode[2]))
-				reg &= ~OMAP_UHH_HOSTCONFIG_ULPI_P3_BYPASS;
-			else if (is_ehci_tll_mode(omap->port_mode[2]))
-				reg |= OMAP_UHH_HOSTCONFIG_ULPI_P3_BYPASS;
-		}
-	} else if (is_omap_ehci_rev2(omap)) {
-		/* Clear port mode fields for PHY mode*/
-		reg &= ~OMAP4_P1_MODE_CLEAR;
-		reg &= ~OMAP4_P2_MODE_CLEAR;
-
-		if (is_ehci_tll_mode(omap->port_mode[0]))
-			reg |= OMAP4_P1_MODE_TLL;
-		else if (is_ehci_hsic_mode(omap->port_mode[0]))
-			reg |= OMAP4_P1_MODE_HSIC;
-
-		if (is_ehci_tll_mode(omap->port_mode[1]))
-			reg |= OMAP4_P2_MODE_TLL;
-		else if (is_ehci_hsic_mode(omap->port_mode[1]))
-			reg |= OMAP4_P2_MODE_HSIC;
+	ret = omap_usbhs_enable(dev);
+	if (ret) {
+		dev_err(dev, "failed to start usbhs with err %d\n", ret);
+		goto err_enable;
 	}
 
-	ehci_omap_writel(omap->uhh_base, OMAP_UHH_HOSTCONFIG, reg);
-	dev_dbg(omap->dev, "UHH setup done, uhh_hostconfig=%x\n", reg);
-
-
 	/*
 	 * An undocumented "feature" in the OMAP3 EHCI controller,
 	 * causes suspended ports to be taken out of suspend when
@@ -561,363 +173,50 @@ static int omap_start_ehc(struct ehci_hcd_omap *omap, struct usb_hcd *hcd)
 	 * to suspend. Writing 1 to this undocumented register bit
 	 * disables this feature and restores normal behavior.
 	 */
-	ehci_omap_writel(omap->ehci_base, EHCI_INSNREG04,
+	ehci_write(regs, EHCI_INSNREG04,
 				EHCI_INSNREG04_DISABLE_UNSUSPEND);
 
-	if ((omap->port_mode[0] == EHCI_HCD_OMAP_MODE_TLL) ||
-		(omap->port_mode[1] == EHCI_HCD_OMAP_MODE_TLL) ||
-			(omap->port_mode[2] == EHCI_HCD_OMAP_MODE_TLL)) {
-
-		if (omap->port_mode[0] == EHCI_HCD_OMAP_MODE_TLL)
-			tll_ch_mask |= OMAP_TLL_CHANNEL_1_EN_MASK;
-		if (omap->port_mode[1] == EHCI_HCD_OMAP_MODE_TLL)
-			tll_ch_mask |= OMAP_TLL_CHANNEL_2_EN_MASK;
-		if (omap->port_mode[2] == EHCI_HCD_OMAP_MODE_TLL)
-			tll_ch_mask |= OMAP_TLL_CHANNEL_3_EN_MASK;
-
-		/* Enable UTMI mode for required TLL channels */
-		omap_usb_utmi_init(omap, tll_ch_mask, OMAP_TLL_CHANNEL_COUNT);
-	}
-
-	if (omap->phy_reset) {
-		/* Refer ISSUE1:
-		 * Hold the PHY in RESET for enough time till
-		 * PHY is settled and ready
-		 */
-		udelay(10);
-
-		if (gpio_is_valid(omap->reset_gpio_port[0]))
-			gpio_set_value(omap->reset_gpio_port[0], 1);
-
-		if (gpio_is_valid(omap->reset_gpio_port[1]))
-			gpio_set_value(omap->reset_gpio_port[1], 1);
-	}
-
 	/* Soft reset the PHY using PHY reset command over ULPI */
-	if (omap->port_mode[0] == EHCI_HCD_OMAP_MODE_PHY)
-		omap_ehci_soft_phy_reset(omap, 0);
-	if (omap->port_mode[1] == EHCI_HCD_OMAP_MODE_PHY)
-		omap_ehci_soft_phy_reset(omap, 1);
-
-	return 0;
-
-err_sys_status:
-	clk_disable(omap->utmi_p2_fck);
-	clk_put(omap->utmi_p2_fck);
-	clk_disable(omap->xclk60mhsp2_ck);
-	clk_put(omap->xclk60mhsp2_ck);
-	clk_disable(omap->utmi_p1_fck);
-	clk_put(omap->utmi_p1_fck);
-	clk_disable(omap->xclk60mhsp1_ck);
-	clk_put(omap->xclk60mhsp1_ck);
-	clk_disable(omap->usbtll_ick);
-	clk_put(omap->usbtll_ick);
-
-err_tll_ick:
-	clk_disable(omap->usbtll_fck);
-	clk_put(omap->usbtll_fck);
-
-err_tll_fck:
-	clk_disable(omap->usbhost_fs_fck);
-	clk_put(omap->usbhost_fs_fck);
-
-	if (omap->phy_reset) {
-		if (gpio_is_valid(omap->reset_gpio_port[0]))
-			gpio_free(omap->reset_gpio_port[0]);
-
-		if (gpio_is_valid(omap->reset_gpio_port[1]))
-			gpio_free(omap->reset_gpio_port[1]);
-	}
-
-err_host_48m_fck:
-	clk_disable(omap->usbhost_hs_fck);
-	clk_put(omap->usbhost_hs_fck);
+	if (pdata->port_mode[0] == OMAP_EHCI_PORT_MODE_PHY)
+		omap_ehci_soft_phy_reset(pdev, 0);
+	if (pdata->port_mode[1] == OMAP_EHCI_PORT_MODE_PHY)
+		omap_ehci_soft_phy_reset(pdev, 1);
 
-err_host_120m_fck:
-	clk_disable(omap->usbhost_ick);
-	clk_put(omap->usbhost_ick);
-
-err_host_ick:
-	return ret;
-}
-
-static void omap_stop_ehc(struct ehci_hcd_omap *omap, struct usb_hcd *hcd)
-{
-	unsigned long timeout = jiffies + msecs_to_jiffies(100);
-
-	dev_dbg(omap->dev, "stopping TI EHCI USB Controller\n");
-
-	/* Reset OMAP modules for insmod/rmmod to work */
-	ehci_omap_writel(omap->uhh_base, OMAP_UHH_SYSCONFIG,
-			is_omap_ehci_rev2(omap) ?
-			OMAP4_UHH_SYSCONFIG_SOFTRESET :
-			OMAP_UHH_SYSCONFIG_SOFTRESET);
-	while (!(ehci_omap_readl(omap->uhh_base, OMAP_UHH_SYSSTATUS)
-				& (1 << 0))) {
-		cpu_relax();
-
-		if (time_after(jiffies, timeout))
-			dev_dbg(omap->dev, "operation timed out\n");
-	}
-
-	while (!(ehci_omap_readl(omap->uhh_base, OMAP_UHH_SYSSTATUS)
-				& (1 << 1))) {
-		cpu_relax();
-
-		if (time_after(jiffies, timeout))
-			dev_dbg(omap->dev, "operation timed out\n");
-	}
-
-	while (!(ehci_omap_readl(omap->uhh_base, OMAP_UHH_SYSSTATUS)
-				& (1 << 2))) {
-		cpu_relax();
-
-		if (time_after(jiffies, timeout))
-			dev_dbg(omap->dev, "operation timed out\n");
-	}
-
-	ehci_omap_writel(omap->tll_base, OMAP_USBTLL_SYSCONFIG, (1 << 1));
-
-	while (!(ehci_omap_readl(omap->tll_base, OMAP_USBTLL_SYSSTATUS)
-				& (1 << 0))) {
-		cpu_relax();
-
-		if (time_after(jiffies, timeout))
-			dev_dbg(omap->dev, "operation timed out\n");
-	}
-
-	if (omap->usbtll_fck != NULL) {
-		clk_disable(omap->usbtll_fck);
-		clk_put(omap->usbtll_fck);
-		omap->usbtll_fck = NULL;
-	}
-
-	if (omap->usbhost_ick != NULL) {
-		clk_disable(omap->usbhost_ick);
-		clk_put(omap->usbhost_ick);
-		omap->usbhost_ick = NULL;
-	}
-
-	if (omap->usbhost_fs_fck != NULL) {
-		clk_disable(omap->usbhost_fs_fck);
-		clk_put(omap->usbhost_fs_fck);
-		omap->usbhost_fs_fck = NULL;
-	}
-
-	if (omap->usbhost_hs_fck != NULL) {
-		clk_disable(omap->usbhost_hs_fck);
-		clk_put(omap->usbhost_hs_fck);
-		omap->usbhost_hs_fck = NULL;
-	}
-
-	if (omap->usbtll_ick != NULL) {
-		clk_disable(omap->usbtll_ick);
-		clk_put(omap->usbtll_ick);
-		omap->usbtll_ick = NULL;
-	}
-
-	if (is_omap_ehci_rev2(omap)) {
-		if (omap->xclk60mhsp1_ck != NULL) {
-			clk_disable(omap->xclk60mhsp1_ck);
-			clk_put(omap->xclk60mhsp1_ck);
-			omap->xclk60mhsp1_ck = NULL;
-		}
-
-		if (omap->utmi_p1_fck != NULL) {
-			clk_disable(omap->utmi_p1_fck);
-			clk_put(omap->utmi_p1_fck);
-			omap->utmi_p1_fck = NULL;
-		}
-
-		if (omap->xclk60mhsp2_ck != NULL) {
-			clk_disable(omap->xclk60mhsp2_ck);
-			clk_put(omap->xclk60mhsp2_ck);
-			omap->xclk60mhsp2_ck = NULL;
-		}
-
-		if (omap->utmi_p2_fck != NULL) {
-			clk_disable(omap->utmi_p2_fck);
-			clk_put(omap->utmi_p2_fck);
-			omap->utmi_p2_fck = NULL;
-		}
-	}
-
-	if (omap->phy_reset) {
-		if (gpio_is_valid(omap->reset_gpio_port[0]))
-			gpio_free(omap->reset_gpio_port[0]);
-
-		if (gpio_is_valid(omap->reset_gpio_port[1]))
-			gpio_free(omap->reset_gpio_port[1]);
-	}
-
-	dev_dbg(omap->dev, "Clock to USB host has been disabled\n");
-}
-
-/*-------------------------------------------------------------------------*/
-
-static const struct hc_driver ehci_omap_hc_driver;
-
-/* configure so an HC device and id are always provided */
-/* always called with process context; sleeping is OK */
-
-/**
- * ehci_hcd_omap_probe - initialize TI-based HCDs
- *
- * Allocates basic resources for this USB host controller, and
- * then invokes the start() method for the HCD associated with it
- * through the hotplug entry's driver_data.
- */
-static int ehci_hcd_omap_probe(struct platform_device *pdev)
-{
-	struct ehci_hcd_omap_platform_data *pdata = pdev->dev.platform_data;
-	struct ehci_hcd_omap *omap;
-	struct resource *res;
-	struct usb_hcd *hcd;
-
-	int irq = platform_get_irq(pdev, 0);
-	int ret = -ENODEV;
-	int i;
-	char supply[7];
-
-	if (!pdata) {
-		dev_dbg(&pdev->dev, "missing platform_data\n");
-		goto err_pdata;
-	}
-
-	if (usb_disabled())
-		goto err_disabled;
-
-	omap = kzalloc(sizeof(*omap), GFP_KERNEL);
-	if (!omap) {
-		ret = -ENOMEM;
-		goto err_disabled;
-	}
-
-	hcd = usb_create_hcd(&ehci_omap_hc_driver, &pdev->dev,
-			dev_name(&pdev->dev));
-	if (!hcd) {
-		dev_err(&pdev->dev, "failed to create hcd with err %d\n", ret);
-		ret = -ENOMEM;
-		goto err_create_hcd;
-	}
-
-	platform_set_drvdata(pdev, omap);
-	omap->dev		= &pdev->dev;
-	omap->phy_reset		= pdata->phy_reset;
-	omap->reset_gpio_port[0]	= pdata->reset_gpio_port[0];
-	omap->reset_gpio_port[1]	= pdata->reset_gpio_port[1];
-	omap->reset_gpio_port[2]	= pdata->reset_gpio_port[2];
-	omap->port_mode[0]		= pdata->port_mode[0];
-	omap->port_mode[1]		= pdata->port_mode[1];
-	omap->port_mode[2]		= pdata->port_mode[2];
-	omap->ehci		= hcd_to_ehci(hcd);
-	omap->ehci->sbrn	= 0x20;
-
-	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-
-	hcd->rsrc_start = res->start;
-	hcd->rsrc_len = resource_size(res);
-
-	hcd->regs = ioremap(hcd->rsrc_start, hcd->rsrc_len);
-	if (!hcd->regs) {
-		dev_err(&pdev->dev, "EHCI ioremap failed\n");
-		ret = -ENOMEM;
-		goto err_ioremap;
-	}
+	omap_ehci = hcd_to_ehci(hcd);
+	omap_ehci->sbrn = 0x20;
 
 	/* we know this is the memory we want, no need to ioremap again */
-	omap->ehci->caps = hcd->regs;
-	omap->ehci_base = hcd->regs;
-
-	res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
-	omap->uhh_base = ioremap(res->start, resource_size(res));
-	if (!omap->uhh_base) {
-		dev_err(&pdev->dev, "UHH ioremap failed\n");
-		ret = -ENOMEM;
-		goto err_uhh_ioremap;
-	}
-
-	res = platform_get_resource(pdev, IORESOURCE_MEM, 2);
-	omap->tll_base = ioremap(res->start, resource_size(res));
-	if (!omap->tll_base) {
-		dev_err(&pdev->dev, "TLL ioremap failed\n");
-		ret = -ENOMEM;
-		goto err_tll_ioremap;
-	}
-
-	/* get ehci regulator and enable */
-	for (i = 0 ; i < OMAP3_HS_USB_PORTS ; i++) {
-		if (omap->port_mode[i] != EHCI_HCD_OMAP_MODE_PHY) {
-			omap->regulator[i] = NULL;
-			continue;
-		}
-		snprintf(supply, sizeof(supply), "hsusb%d", i);
-		omap->regulator[i] = regulator_get(omap->dev, supply);
-		if (IS_ERR(omap->regulator[i])) {
-			omap->regulator[i] = NULL;
-			dev_dbg(&pdev->dev,
-			"failed to get ehci port%d regulator\n", i);
-		} else {
-			regulator_enable(omap->regulator[i]);
-		}
-	}
-
-	ret = omap_start_ehc(omap, hcd);
-	if (ret) {
-		dev_err(&pdev->dev, "failed to start ehci with err %d\n", ret);
-		goto err_start;
-	}
+	omap_ehci->caps = hcd->regs;
+	omap_ehci->regs = hcd->regs
+			+ HC_LENGTH(readl(&omap_ehci->caps->hc_capbase));
 
-	omap->ehci->regs = hcd->regs
-		+ HC_LENGTH(readl(&omap->ehci->caps->hc_capbase));
-
-	dbg_hcs_params(omap->ehci, "reset");
-	dbg_hcc_params(omap->ehci, "reset");
+	dbg_hcs_params(omap_ehci, "reset");
+	dbg_hcc_params(omap_ehci, "reset");
 
 	/* cache this readonly data; minimize chip reads */
-	omap->ehci->hcs_params = readl(&omap->ehci->caps->hcs_params);
+	omap_ehci->hcs_params = readl(&omap_ehci->caps->hcs_params);
 
 	ret = usb_add_hcd(hcd, irq, IRQF_DISABLED | IRQF_SHARED);
 	if (ret) {
-		dev_err(&pdev->dev, "failed to add hcd with err %d\n", ret);
+		dev_err(dev, "failed to add hcd with err %d\n", ret);
 		goto err_add_hcd;
 	}
 
 	/* root ports should always stay powered */
-	ehci_port_power(omap->ehci, 1);
+	ehci_port_power(omap_ehci, 1);
 
 	return 0;
 
 err_add_hcd:
-	omap_stop_ehc(omap, hcd);
+	omap_usbhs_disable(dev);
 
-err_start:
-	for (i = 0 ; i < OMAP3_HS_USB_PORTS ; i++) {
-		if (omap->regulator[i]) {
-			regulator_disable(omap->regulator[i]);
-			regulator_put(omap->regulator[i]);
-		}
-	}
-	iounmap(omap->tll_base);
-
-err_tll_ioremap:
-	iounmap(omap->uhh_base);
-
-err_uhh_ioremap:
-	iounmap(hcd->regs);
-
-err_ioremap:
+err_enable:
 	usb_put_hcd(hcd);
 
-err_create_hcd:
-	kfree(omap);
-err_disabled:
-err_pdata:
+err_io:
 	return ret;
 }
 
-/* may be called without controller electrically present */
-/* may be called with controller, bus, and devices active */
 
 /**
  * ehci_hcd_omap_remove - shutdown processing for EHCI HCDs
@@ -929,31 +228,18 @@ err_pdata:
  */
 static int ehci_hcd_omap_remove(struct platform_device *pdev)
 {
-	struct ehci_hcd_omap *omap = platform_get_drvdata(pdev);
-	struct usb_hcd *hcd = ehci_to_hcd(omap->ehci);
-	int i;
+	struct device *dev	= &pdev->dev;
+	struct usb_hcd *hcd	= dev_get_drvdata(dev);
 
 	usb_remove_hcd(hcd);
-	omap_stop_ehc(omap, hcd);
-	iounmap(hcd->regs);
-	for (i = 0 ; i < OMAP3_HS_USB_PORTS ; i++) {
-		if (omap->regulator[i]) {
-			regulator_disable(omap->regulator[i]);
-			regulator_put(omap->regulator[i]);
-		}
-	}
-	iounmap(omap->tll_base);
-	iounmap(omap->uhh_base);
+	omap_usbhs_disable(dev);
 	usb_put_hcd(hcd);
-	kfree(omap);
-
 	return 0;
 }
 
 static void ehci_hcd_omap_shutdown(struct platform_device *pdev)
 {
-	struct ehci_hcd_omap *omap = platform_get_drvdata(pdev);
-	struct usb_hcd *hcd = ehci_to_hcd(omap->ehci);
+	struct usb_hcd *hcd = dev_get_drvdata(&pdev->dev);
 
 	if (hcd->driver->shutdown)
 		hcd->driver->shutdown(hcd);
diff --git a/drivers/usb/host/ehci-orion.c b/drivers/usb/host/ehci-orion.c
index 0f87dc72820a..281e094e1c18 100644
--- a/drivers/usb/host/ehci-orion.c
+++ b/drivers/usb/host/ehci-orion.c
@@ -105,7 +105,8 @@ static int ehci_orion_setup(struct usb_hcd *hcd)
 	struct ehci_hcd *ehci = hcd_to_ehci(hcd);
 	int retval;
 
-	ehci_reset(ehci);
+	hcd->has_tt = 1;
+
 	retval = ehci_halt(ehci);
 	if (retval)
 		return retval;
@@ -117,7 +118,7 @@ static int ehci_orion_setup(struct usb_hcd *hcd)
 	if (retval)
 		return retval;
 
-	hcd->has_tt = 1;
+	ehci_reset(ehci);
 
 	ehci_port_power(ehci, 0);
 
diff --git a/drivers/usb/host/ehci-pci.c b/drivers/usb/host/ehci-pci.c
index 07bb982e59f6..d5eaea7caf89 100644
--- a/drivers/usb/host/ehci-pci.c
+++ b/drivers/usb/host/ehci-pci.c
@@ -44,42 +44,6 @@ static int ehci_pci_reinit(struct ehci_hcd *ehci, struct pci_dev *pdev)
 	return 0;
 }
 
-static int ehci_quirk_amd_hudson(struct ehci_hcd *ehci)
-{
-	struct pci_dev *amd_smbus_dev;
-	u8 rev = 0;
-
-	amd_smbus_dev = pci_get_device(PCI_VENDOR_ID_ATI, 0x4385, NULL);
-	if (amd_smbus_dev) {
-		pci_read_config_byte(amd_smbus_dev, PCI_REVISION_ID, &rev);
-		if (rev < 0x40) {
-			pci_dev_put(amd_smbus_dev);
-			amd_smbus_dev = NULL;
-			return 0;
-		}
-	} else {
-		amd_smbus_dev = pci_get_device(PCI_VENDOR_ID_AMD, 0x780b, NULL);
-		if (!amd_smbus_dev)
-			return 0;
-		pci_read_config_byte(amd_smbus_dev, PCI_REVISION_ID, &rev);
-		if (rev < 0x11 || rev > 0x18) {
-			pci_dev_put(amd_smbus_dev);
-			amd_smbus_dev = NULL;
-			return 0;
-		}
-	}
-
-	if (!amd_nb_dev)
-		amd_nb_dev = pci_get_device(PCI_VENDOR_ID_AMD, 0x1510, NULL);
-
-	ehci_info(ehci, "QUIRK: Enable exception for AMD Hudson ASPM\n");
-
-	pci_dev_put(amd_smbus_dev);
-	amd_smbus_dev = NULL;
-
-	return 1;
-}
-
 /* called during probe() after chip reset completes */
 static int ehci_pci_setup(struct usb_hcd *hcd)
 {
@@ -138,9 +102,6 @@ static int ehci_pci_setup(struct usb_hcd *hcd)
 	/* cache this readonly data; minimize chip reads */
 	ehci->hcs_params = ehci_readl(ehci, &ehci->caps->hcs_params);
 
-	if (ehci_quirk_amd_hudson(ehci))
-		ehci->amd_l1_fix = 1;
-
 	retval = ehci_halt(ehci);
 	if (retval)
 		return retval;
@@ -191,6 +152,9 @@ static int ehci_pci_setup(struct usb_hcd *hcd)
 		}
 		break;
 	case PCI_VENDOR_ID_AMD:
+		/* AMD PLL quirk */
+		if (usb_amd_find_chipset_info())
+			ehci->amd_pll_fix = 1;
 		/* AMD8111 EHCI doesn't work, according to AMD errata */
 		if (pdev->device == 0x7463) {
 			ehci_info(ehci, "ignoring AMD8111 (errata)\n");
@@ -236,6 +200,9 @@ static int ehci_pci_setup(struct usb_hcd *hcd)
 		}
 		break;
 	case PCI_VENDOR_ID_ATI:
+		/* AMD PLL quirk */
+		if (usb_amd_find_chipset_info())
+			ehci->amd_pll_fix = 1;
 		/* SB600 and old version of SB700 have a bug in EHCI controller,
 		 * which causes usb devices lose response in some cases.
 		 */
diff --git a/drivers/usb/host/ehci-pmcmsp.c b/drivers/usb/host/ehci-pmcmsp.c
new file mode 100644
index 000000000000..a2168642175b
--- /dev/null
+++ b/drivers/usb/host/ehci-pmcmsp.c
@@ -0,0 +1,383 @@
+/*
+ * PMC MSP EHCI (Host Controller Driver) for USB.
+ *
+ * (C) Copyright 2006-2010 PMC-Sierra Inc
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ */
+
+/* includes */
+#include <linux/platform_device.h>
+#include <linux/gpio.h>
+#include <linux/usb.h>
+#include <msp_usb.h>
+
+/* stream disable*/
+#define USB_CTRL_MODE_STREAM_DISABLE	0x10
+
+/* threshold */
+#define USB_CTRL_FIFO_THRESH		0x00300000
+
+/* register offset for usb_mode */
+#define USB_EHCI_REG_USB_MODE		0x68
+
+/* register offset for usb fifo */
+#define USB_EHCI_REG_USB_FIFO		0x24
+
+/* register offset for usb status */
+#define USB_EHCI_REG_USB_STATUS		0x44
+
+/* serial/parallel transceiver */
+#define USB_EHCI_REG_BIT_STAT_STS	(1<<29)
+
+/* TWI USB0 host device pin */
+#define MSP_PIN_USB0_HOST_DEV		49
+
+/* TWI USB1 host device pin */
+#define MSP_PIN_USB1_HOST_DEV		50
+
+
+static void usb_hcd_tdi_set_mode(struct ehci_hcd *ehci)
+{
+	u8 *base;
+	u8 *statreg;
+	u8 *fiforeg;
+	u32 val;
+	struct ehci_regs *reg_base = ehci->regs;
+
+	/* get register base */
+	base = (u8 *)reg_base + USB_EHCI_REG_USB_MODE;
+	statreg = (u8 *)reg_base + USB_EHCI_REG_USB_STATUS;
+	fiforeg = (u8 *)reg_base + USB_EHCI_REG_USB_FIFO;
+
+	/* Disable controller mode stream */
+	val = ehci_readl(ehci, (u32 *)base);
+	ehci_writel(ehci, (val | USB_CTRL_MODE_STREAM_DISABLE),
+			(u32 *)base);
+
+	/* clear STS to select parallel transceiver interface */
+	val = ehci_readl(ehci, (u32 *)statreg);
+	val = val & ~USB_EHCI_REG_BIT_STAT_STS;
+	ehci_writel(ehci, val, (u32 *)statreg);
+
+	/* write to set the proper fifo threshold */
+	ehci_writel(ehci, USB_CTRL_FIFO_THRESH, (u32 *)fiforeg);
+
+	/* set TWI GPIO USB_HOST_DEV pin high */
+	gpio_direction_output(MSP_PIN_USB0_HOST_DEV, 1);
+#ifdef CONFIG_MSP_HAS_DUAL_USB
+	gpio_direction_output(MSP_PIN_USB1_HOST_DEV, 1);
+#endif
+}
+
+/* called during probe() after chip reset completes */
+static int ehci_msp_setup(struct usb_hcd *hcd)
+{
+	struct ehci_hcd		*ehci = hcd_to_ehci(hcd);
+	int			retval;
+	ehci->big_endian_mmio = 1;
+	ehci->big_endian_desc = 1;
+
+	ehci->caps = hcd->regs;
+	ehci->regs = hcd->regs +
+			HC_LENGTH(ehci_readl(ehci, &ehci->caps->hc_capbase));
+	dbg_hcs_params(ehci, "reset");
+	dbg_hcc_params(ehci, "reset");
+
+	/* cache this readonly data; minimize chip reads */
+	ehci->hcs_params = ehci_readl(ehci, &ehci->caps->hcs_params);
+	hcd->has_tt = 1;
+
+	retval = ehci_halt(ehci);
+	if (retval)
+		return retval;
+
+	ehci_reset(ehci);
+
+	/* data structure init */
+	retval = ehci_init(hcd);
+	if (retval)
+		return retval;
+
+	usb_hcd_tdi_set_mode(ehci);
+	ehci_port_power(ehci, 0);
+
+	return retval;
+}
+
+
+/* configure so an HC device and id are always provided
+ * always called with process context; sleeping is OK
+ */
+
+static int usb_hcd_msp_map_regs(struct mspusb_device *dev)
+{
+	struct resource *res;
+	struct platform_device *pdev = &dev->dev;
+	u32 res_len;
+	int retval;
+
+	/* MAB register space */
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
+	if (res == NULL)
+		return -ENOMEM;
+	res_len = res->end - res->start + 1;
+	if (!request_mem_region(res->start, res_len, "mab regs"))
+		return -EBUSY;
+
+	dev->mab_regs = ioremap_nocache(res->start, res_len);
+	if (dev->mab_regs == NULL) {
+		retval = -ENOMEM;
+		goto err1;
+	}
+
+	/* MSP USB register space */
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 2);
+	if (res == NULL) {
+		retval = -ENOMEM;
+		goto err2;
+	}
+	res_len = res->end - res->start + 1;
+	if (!request_mem_region(res->start, res_len, "usbid regs")) {
+		retval = -EBUSY;
+		goto err2;
+	}
+	dev->usbid_regs = ioremap_nocache(res->start, res_len);
+	if (dev->usbid_regs == NULL) {
+		retval = -ENOMEM;
+		goto err3;
+	}
+
+	return 0;
+err3:
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 2);
+	res_len = res->end - res->start + 1;
+	release_mem_region(res->start, res_len);
+err2:
+	iounmap(dev->mab_regs);
+err1:
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
+	res_len = res->end - res->start + 1;
+	release_mem_region(res->start, res_len);
+	dev_err(&pdev->dev, "Failed to map non-EHCI regs.\n");
+	return retval;
+}
+
+/**
+ * usb_hcd_msp_probe - initialize PMC MSP-based HCDs
+ * Context: !in_interrupt()
+ *
+ * Allocates basic resources for this USB host controller, and
+ * then invokes the start() method for the HCD associated with it
+ * through the hotplug entry's driver_data.
+ *
+ */
+int usb_hcd_msp_probe(const struct hc_driver *driver,
+			  struct platform_device *dev)
+{
+	int retval;
+	struct usb_hcd *hcd;
+	struct resource *res;
+	struct ehci_hcd		*ehci ;
+
+	hcd = usb_create_hcd(driver, &dev->dev, "pmcmsp");
+	if (!hcd)
+		return -ENOMEM;
+
+	res = platform_get_resource(dev, IORESOURCE_MEM, 0);
+	if (res == NULL) {
+		pr_debug("No IOMEM resource info for %s.\n", dev->name);
+		retval = -ENOMEM;
+		goto err1;
+	}
+	hcd->rsrc_start = res->start;
+	hcd->rsrc_len = res->end - res->start + 1;
+	if (!request_mem_region(hcd->rsrc_start, hcd->rsrc_len, dev->name)) {
+		retval = -EBUSY;
+		goto err1;
+	}
+	hcd->regs = ioremap_nocache(hcd->rsrc_start, hcd->rsrc_len);
+	if (!hcd->regs) {
+		pr_debug("ioremap failed");
+		retval = -ENOMEM;
+		goto err2;
+	}
+
+	res = platform_get_resource(dev, IORESOURCE_IRQ, 0);
+	if (res == NULL) {
+		dev_err(&dev->dev, "No IRQ resource info for %s.\n", dev->name);
+		retval = -ENOMEM;
+		goto err3;
+	}
+
+	/* Map non-EHCI register spaces */
+	retval = usb_hcd_msp_map_regs(to_mspusb_device(dev));
+	if (retval != 0)
+		goto err3;
+
+	ehci = hcd_to_ehci(hcd);
+	ehci->big_endian_mmio = 1;
+	ehci->big_endian_desc = 1;
+
+
+	retval = usb_add_hcd(hcd, res->start, IRQF_SHARED);
+	if (retval == 0)
+		return 0;
+
+	usb_remove_hcd(hcd);
+err3:
+	iounmap(hcd->regs);
+err2:
+	release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
+err1:
+	usb_put_hcd(hcd);
+
+	return retval;
+}
+
+
+
+/**
+ * usb_hcd_msp_remove - shutdown processing for PMC MSP-based HCDs
+ * @dev: USB Host Controller being removed
+ * Context: !in_interrupt()
+ *
+ * Reverses the effect of usb_hcd_msp_probe(), first invoking
+ * the HCD's stop() method.  It is always called from a thread
+ * context, normally "rmmod", "apmd", or something similar.
+ *
+ * may be called without controller electrically present
+ * may be called with controller, bus, and devices active
+ */
+void usb_hcd_msp_remove(struct usb_hcd *hcd, struct platform_device *dev)
+{
+	usb_remove_hcd(hcd);
+	iounmap(hcd->regs);
+	release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
+	usb_put_hcd(hcd);
+}
+
+#ifdef CONFIG_MSP_HAS_DUAL_USB
+/*
+ * Wrapper around the main ehci_irq.  Since both USB host controllers are
+ * sharing the same IRQ, need to first determine whether we're the intended
+ * recipient of this interrupt.
+ */
+static irqreturn_t ehci_msp_irq(struct usb_hcd *hcd)
+{
+	u32 int_src;
+	struct device *dev = hcd->self.controller;
+	struct platform_device *pdev;
+	struct mspusb_device *mdev;
+	struct ehci_hcd	*ehci = hcd_to_ehci(hcd);
+	/* need to reverse-map a couple of containers to get our device */
+	pdev = to_platform_device(dev);
+	mdev = to_mspusb_device(pdev);
+
+	/* Check to see if this interrupt is for this host controller */
+	int_src = ehci_readl(ehci, &mdev->mab_regs->int_stat);
+	if (int_src & (1 << pdev->id))
+		return ehci_irq(hcd);
+
+	/* Not for this device */
+	return IRQ_NONE;
+}
+#endif /* DUAL_USB */
+
+static const struct hc_driver ehci_msp_hc_driver = {
+	.description =		hcd_name,
+	.product_desc =		"PMC MSP EHCI",
+	.hcd_priv_size =	sizeof(struct ehci_hcd),
+
+	/*
+	 * generic hardware linkage
+	 */
+#ifdef CONFIG_MSP_HAS_DUAL_USB
+	.irq =			ehci_msp_irq,
+#else
+	.irq =			ehci_irq,
+#endif
+	.flags =		HCD_MEMORY | HCD_USB2,
+
+	/*
+	 * basic lifecycle operations
+	 */
+	.reset =		ehci_msp_setup,
+	.start =		ehci_run,
+	.shutdown		= ehci_shutdown,
+	.start			= ehci_run,
+	.stop			= ehci_stop,
+
+	/*
+	 * managing i/o requests and associated device resources
+	 */
+	.urb_enqueue		= ehci_urb_enqueue,
+	.urb_dequeue		= ehci_urb_dequeue,
+	.endpoint_disable	= ehci_endpoint_disable,
+	.endpoint_reset		= ehci_endpoint_reset,
+
+	/*
+	 * scheduling support
+	 */
+	.get_frame_number	= ehci_get_frame,
+
+	/*
+	 * root hub support
+	 */
+	.hub_status_data	= ehci_hub_status_data,
+	.hub_control		= ehci_hub_control,
+	.bus_suspend		= ehci_bus_suspend,
+	.bus_resume		= ehci_bus_resume,
+	.relinquish_port	= ehci_relinquish_port,
+	.port_handed_over	= ehci_port_handed_over,
+
+	.clear_tt_buffer_complete	= ehci_clear_tt_buffer_complete,
+};
+
+static int ehci_hcd_msp_drv_probe(struct platform_device *pdev)
+{
+	int ret;
+
+	pr_debug("In ehci_hcd_msp_drv_probe");
+
+	if (usb_disabled())
+		return -ENODEV;
+
+	gpio_request(MSP_PIN_USB0_HOST_DEV, "USB0_HOST_DEV_GPIO");
+#ifdef CONFIG_MSP_HAS_DUAL_USB
+	gpio_request(MSP_PIN_USB1_HOST_DEV, "USB1_HOST_DEV_GPIO");
+#endif
+
+	ret = usb_hcd_msp_probe(&ehci_msp_hc_driver, pdev);
+
+	return ret;
+}
+
+static int ehci_hcd_msp_drv_remove(struct platform_device *pdev)
+{
+	struct usb_hcd *hcd = platform_get_drvdata(pdev);
+
+	usb_hcd_msp_remove(hcd, pdev);
+
+	/* free TWI GPIO USB_HOST_DEV pin */
+	gpio_free(MSP_PIN_USB0_HOST_DEV);
+#ifdef CONFIG_MSP_HAS_DUAL_USB
+	gpio_free(MSP_PIN_USB1_HOST_DEV);
+#endif
+
+	return 0;
+}
+
+MODULE_ALIAS("pmcmsp-ehci");
+
+static struct platform_driver ehci_hcd_msp_driver = {
+	.probe		= ehci_hcd_msp_drv_probe,
+	.remove		= ehci_hcd_msp_drv_remove,
+	.driver		= {
+		.name	= "pmcmsp-ehci",
+		.owner	= THIS_MODULE,
+	},
+};
diff --git a/drivers/usb/host/ehci-q.c b/drivers/usb/host/ehci-q.c
index 233c288e3f93..fe99895fb098 100644
--- a/drivers/usb/host/ehci-q.c
+++ b/drivers/usb/host/ehci-q.c
@@ -1107,22 +1107,24 @@ submit_async (
 	struct list_head	*qtd_list,
 	gfp_t			mem_flags
 ) {
-	struct ehci_qtd		*qtd;
 	int			epnum;
 	unsigned long		flags;
 	struct ehci_qh		*qh = NULL;
 	int			rc;
 
-	qtd = list_entry (qtd_list->next, struct ehci_qtd, qtd_list);
 	epnum = urb->ep->desc.bEndpointAddress;
 
 #ifdef EHCI_URB_TRACE
-	ehci_dbg (ehci,
-		"%s %s urb %p ep%d%s len %d, qtd %p [qh %p]\n",
-		__func__, urb->dev->devpath, urb,
-		epnum & 0x0f, (epnum & USB_DIR_IN) ? "in" : "out",
-		urb->transfer_buffer_length,
-		qtd, urb->ep->hcpriv);
+	{
+		struct ehci_qtd *qtd;
+		qtd = list_entry(qtd_list->next, struct ehci_qtd, qtd_list);
+		ehci_dbg(ehci,
+			 "%s %s urb %p ep%d%s len %d, qtd %p [qh %p]\n",
+			 __func__, urb->dev->devpath, urb,
+			 epnum & 0x0f, (epnum & USB_DIR_IN) ? "in" : "out",
+			 urb->transfer_buffer_length,
+			 qtd, urb->ep->hcpriv);
+	}
 #endif
 
 	spin_lock_irqsave (&ehci->lock, flags);
diff --git a/drivers/usb/host/ehci-sched.c b/drivers/usb/host/ehci-sched.c
index aa46f57f9ec8..1543c838b3d1 100644
--- a/drivers/usb/host/ehci-sched.c
+++ b/drivers/usb/host/ehci-sched.c
@@ -1048,8 +1048,6 @@ iso_stream_put(struct ehci_hcd *ehci, struct ehci_iso_stream *stream)
 	 * not like a QH -- no persistent state (toggle, halt)
 	 */
 	if (stream->refcount == 1) {
-		int		is_in;
-
 		// BUG_ON (!list_empty(&stream->td_list));
 
 		while (!list_empty (&stream->free_list)) {
@@ -1076,7 +1074,6 @@ iso_stream_put(struct ehci_hcd *ehci, struct ehci_iso_stream *stream)
 			}
 		}
 
-		is_in = (stream->bEndpointAddress & USB_DIR_IN) ? 0x10 : 0;
 		stream->bEndpointAddress &= 0x0f;
 		if (stream->ep)
 			stream->ep->hcpriv = NULL;
@@ -1590,63 +1587,6 @@ itd_link (struct ehci_hcd *ehci, unsigned frame, struct ehci_itd *itd)
 	*hw_p = cpu_to_hc32(ehci, itd->itd_dma | Q_TYPE_ITD);
 }
 
-#define AB_REG_BAR_LOW 0xe0
-#define AB_REG_BAR_HIGH 0xe1
-#define AB_INDX(addr) ((addr) + 0x00)
-#define AB_DATA(addr) ((addr) + 0x04)
-#define NB_PCIE_INDX_ADDR 0xe0
-#define NB_PCIE_INDX_DATA 0xe4
-#define NB_PIF0_PWRDOWN_0 0x01100012
-#define NB_PIF0_PWRDOWN_1 0x01100013
-
-static void ehci_quirk_amd_L1(struct ehci_hcd *ehci, int disable)
-{
-	u32 addr, addr_low, addr_high, val;
-
-	outb_p(AB_REG_BAR_LOW, 0xcd6);
-	addr_low = inb_p(0xcd7);
-	outb_p(AB_REG_BAR_HIGH, 0xcd6);
-	addr_high = inb_p(0xcd7);
-	addr = addr_high << 8 | addr_low;
-	outl_p(0x30, AB_INDX(addr));
-	outl_p(0x40, AB_DATA(addr));
-	outl_p(0x34, AB_INDX(addr));
-	val = inl_p(AB_DATA(addr));
-
-	if (disable) {
-		val &= ~0x8;
-		val |= (1 << 4) | (1 << 9);
-	} else {
-		val |= 0x8;
-		val &= ~((1 << 4) | (1 << 9));
-	}
-	outl_p(val, AB_DATA(addr));
-
-	if (amd_nb_dev) {
-		addr = NB_PIF0_PWRDOWN_0;
-		pci_write_config_dword(amd_nb_dev, NB_PCIE_INDX_ADDR, addr);
-		pci_read_config_dword(amd_nb_dev, NB_PCIE_INDX_DATA, &val);
-		if (disable)
-			val &= ~(0x3f << 7);
-		else
-			val |= 0x3f << 7;
-
-		pci_write_config_dword(amd_nb_dev, NB_PCIE_INDX_DATA, val);
-
-		addr = NB_PIF0_PWRDOWN_1;
-		pci_write_config_dword(amd_nb_dev, NB_PCIE_INDX_ADDR, addr);
-		pci_read_config_dword(amd_nb_dev, NB_PCIE_INDX_DATA, &val);
-		if (disable)
-			val &= ~(0x3f << 7);
-		else
-			val |= 0x3f << 7;
-
-		pci_write_config_dword(amd_nb_dev, NB_PCIE_INDX_DATA, val);
-	}
-
-	return;
-}
-
 /* fit urb's itds into the selected schedule slot; activate as needed */
 static int
 itd_link_urb (
@@ -1675,8 +1615,8 @@ itd_link_urb (
 	}
 
 	if (ehci_to_hcd(ehci)->self.bandwidth_isoc_reqs == 0) {
-		if (ehci->amd_l1_fix == 1)
-			ehci_quirk_amd_L1(ehci, 1);
+		if (ehci->amd_pll_fix == 1)
+			usb_amd_quirk_pll_disable();
 	}
 
 	ehci_to_hcd(ehci)->self.bandwidth_isoc_reqs++;
@@ -1804,8 +1744,8 @@ itd_complete (
 	ehci_to_hcd(ehci)->self.bandwidth_isoc_reqs--;
 
 	if (ehci_to_hcd(ehci)->self.bandwidth_isoc_reqs == 0) {
-		if (ehci->amd_l1_fix == 1)
-			ehci_quirk_amd_L1(ehci, 0);
+		if (ehci->amd_pll_fix == 1)
+			usb_amd_quirk_pll_enable();
 	}
 
 	if (unlikely(list_is_singular(&stream->td_list))) {
@@ -2095,8 +2035,8 @@ sitd_link_urb (
 	}
 
 	if (ehci_to_hcd(ehci)->self.bandwidth_isoc_reqs == 0) {
-		if (ehci->amd_l1_fix == 1)
-			ehci_quirk_amd_L1(ehci, 1);
+		if (ehci->amd_pll_fix == 1)
+			usb_amd_quirk_pll_disable();
 	}
 
 	ehci_to_hcd(ehci)->self.bandwidth_isoc_reqs++;
@@ -2200,8 +2140,8 @@ sitd_complete (
 	ehci_to_hcd(ehci)->self.bandwidth_isoc_reqs--;
 
 	if (ehci_to_hcd(ehci)->self.bandwidth_isoc_reqs == 0) {
-		if (ehci->amd_l1_fix == 1)
-			ehci_quirk_amd_L1(ehci, 0);
+		if (ehci->amd_pll_fix == 1)
+			usb_amd_quirk_pll_enable();
 	}
 
 	if (list_is_singular(&stream->td_list)) {
diff --git a/drivers/usb/host/ehci-tegra.c b/drivers/usb/host/ehci-tegra.c
new file mode 100644
index 000000000000..a516af28c29b
--- /dev/null
+++ b/drivers/usb/host/ehci-tegra.c
@@ -0,0 +1,715 @@
+/*
+ * EHCI-compliant USB host controller driver for NVIDIA Tegra SoCs
+ *
+ * Copyright (C) 2010 Google, Inc.
+ * Copyright (C) 2009 NVIDIA Corporation
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ */
+
+#include <linux/clk.h>
+#include <linux/platform_device.h>
+#include <linux/platform_data/tegra_usb.h>
+#include <linux/irq.h>
+#include <linux/usb/otg.h>
+#include <mach/usb_phy.h>
+
+#define TEGRA_USB_DMA_ALIGN 32
+
+struct tegra_ehci_hcd {
+	struct ehci_hcd *ehci;
+	struct tegra_usb_phy *phy;
+	struct clk *clk;
+	struct clk *emc_clk;
+	struct otg_transceiver *transceiver;
+	int host_resumed;
+	int bus_suspended;
+	int port_resuming;
+	int power_down_on_bus_suspend;
+	enum tegra_usb_phy_port_speed port_speed;
+};
+
+static void tegra_ehci_power_up(struct usb_hcd *hcd)
+{
+	struct tegra_ehci_hcd *tegra = dev_get_drvdata(hcd->self.controller);
+
+	clk_enable(tegra->emc_clk);
+	clk_enable(tegra->clk);
+	tegra_usb_phy_power_on(tegra->phy);
+	tegra->host_resumed = 1;
+}
+
+static void tegra_ehci_power_down(struct usb_hcd *hcd)
+{
+	struct tegra_ehci_hcd *tegra = dev_get_drvdata(hcd->self.controller);
+
+	tegra->host_resumed = 0;
+	tegra_usb_phy_power_off(tegra->phy);
+	clk_disable(tegra->clk);
+	clk_disable(tegra->emc_clk);
+}
+
+static int tegra_ehci_hub_control(
+	struct usb_hcd	*hcd,
+	u16		typeReq,
+	u16		wValue,
+	u16		wIndex,
+	char		*buf,
+	u16		wLength
+)
+{
+	struct ehci_hcd	*ehci = hcd_to_ehci(hcd);
+	struct tegra_ehci_hcd *tegra = dev_get_drvdata(hcd->self.controller);
+	u32 __iomem	*status_reg;
+	u32		temp;
+	unsigned long	flags;
+	int		retval = 0;
+
+	status_reg = &ehci->regs->port_status[(wIndex & 0xff) - 1];
+
+	spin_lock_irqsave(&ehci->lock, flags);
+
+	/*
+	 * In ehci_hub_control() for USB_PORT_FEAT_ENABLE clears the other bits
+	 * that are write on clear, by writing back the register read value, so
+	 * USB_PORT_FEAT_ENABLE is handled by masking the set on clear bits
+	 */
+	if (typeReq == ClearPortFeature && wValue == USB_PORT_FEAT_ENABLE) {
+		temp = ehci_readl(ehci, status_reg) & ~PORT_RWC_BITS;
+		ehci_writel(ehci, temp & ~PORT_PE, status_reg);
+		goto done;
+	}
+
+	else if (typeReq == GetPortStatus) {
+		temp = ehci_readl(ehci, status_reg);
+		if (tegra->port_resuming && !(temp & PORT_SUSPEND)) {
+			/* Resume completed, re-enable disconnect detection */
+			tegra->port_resuming = 0;
+			tegra_usb_phy_postresume(tegra->phy);
+		}
+	}
+
+	else if (typeReq == SetPortFeature && wValue == USB_PORT_FEAT_SUSPEND) {
+		temp = ehci_readl(ehci, status_reg);
+		if ((temp & PORT_PE) == 0 || (temp & PORT_RESET) != 0) {
+			retval = -EPIPE;
+			goto done;
+		}
+
+		temp &= ~PORT_WKCONN_E;
+		temp |= PORT_WKDISC_E | PORT_WKOC_E;
+		ehci_writel(ehci, temp | PORT_SUSPEND, status_reg);
+
+		/*
+		 * If a transaction is in progress, there may be a delay in
+		 * suspending the port. Poll until the port is suspended.
+		 */
+		if (handshake(ehci, status_reg, PORT_SUSPEND,
+						PORT_SUSPEND, 5000))
+			pr_err("%s: timeout waiting for SUSPEND\n", __func__);
+
+		set_bit((wIndex & 0xff) - 1, &ehci->suspended_ports);
+		goto done;
+	}
+
+	/*
+	 * Tegra host controller will time the resume operation to clear the bit
+	 * when the port control state switches to HS or FS Idle. This behavior
+	 * is different from EHCI where the host controller driver is required
+	 * to set this bit to a zero after the resume duration is timed in the
+	 * driver.
+	 */
+	else if (typeReq == ClearPortFeature &&
+					wValue == USB_PORT_FEAT_SUSPEND) {
+		temp = ehci_readl(ehci, status_reg);
+		if ((temp & PORT_RESET) || !(temp & PORT_PE)) {
+			retval = -EPIPE;
+			goto done;
+		}
+
+		if (!(temp & PORT_SUSPEND))
+			goto done;
+
+		/* Disable disconnect detection during port resume */
+		tegra_usb_phy_preresume(tegra->phy);
+
+		ehci->reset_done[wIndex-1] = jiffies + msecs_to_jiffies(25);
+
+		temp &= ~(PORT_RWC_BITS | PORT_WAKE_BITS);
+		/* start resume signalling */
+		ehci_writel(ehci, temp | PORT_RESUME, status_reg);
+
+		spin_unlock_irqrestore(&ehci->lock, flags);
+		msleep(20);
+		spin_lock_irqsave(&ehci->lock, flags);
+
+		/* Poll until the controller clears RESUME and SUSPEND */
+		if (handshake(ehci, status_reg, PORT_RESUME, 0, 2000))
+			pr_err("%s: timeout waiting for RESUME\n", __func__);
+		if (handshake(ehci, status_reg, PORT_SUSPEND, 0, 2000))
+			pr_err("%s: timeout waiting for SUSPEND\n", __func__);
+
+		ehci->reset_done[wIndex-1] = 0;
+
+		tegra->port_resuming = 1;
+		goto done;
+	}
+
+	spin_unlock_irqrestore(&ehci->lock, flags);
+
+	/* Handle the hub control events here */
+	return ehci_hub_control(hcd, typeReq, wValue, wIndex, buf, wLength);
+done:
+	spin_unlock_irqrestore(&ehci->lock, flags);
+	return retval;
+}
+
+static void tegra_ehci_restart(struct usb_hcd *hcd)
+{
+	struct ehci_hcd *ehci = hcd_to_ehci(hcd);
+
+	ehci_reset(ehci);
+
+	/* setup the frame list and Async q heads */
+	ehci_writel(ehci, ehci->periodic_dma, &ehci->regs->frame_list);
+	ehci_writel(ehci, (u32)ehci->async->qh_dma, &ehci->regs->async_next);
+	/* setup the command register and set the controller in RUN mode */
+	ehci->command &= ~(CMD_LRESET|CMD_IAAD|CMD_PSE|CMD_ASE|CMD_RESET);
+	ehci->command |= CMD_RUN;
+	ehci_writel(ehci, ehci->command, &ehci->regs->command);
+
+	down_write(&ehci_cf_port_reset_rwsem);
+	ehci_writel(ehci, FLAG_CF, &ehci->regs->configured_flag);
+	/* flush posted writes */
+	ehci_readl(ehci, &ehci->regs->command);
+	up_write(&ehci_cf_port_reset_rwsem);
+}
+
+static int tegra_usb_suspend(struct usb_hcd *hcd)
+{
+	struct tegra_ehci_hcd *tegra = dev_get_drvdata(hcd->self.controller);
+	struct ehci_regs __iomem *hw = tegra->ehci->regs;
+	unsigned long flags;
+
+	spin_lock_irqsave(&tegra->ehci->lock, flags);
+
+	tegra->port_speed = (readl(&hw->port_status[0]) >> 26) & 0x3;
+	ehci_halt(tegra->ehci);
+	clear_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags);
+
+	spin_unlock_irqrestore(&tegra->ehci->lock, flags);
+
+	tegra_ehci_power_down(hcd);
+	return 0;
+}
+
+static int tegra_usb_resume(struct usb_hcd *hcd)
+{
+	struct tegra_ehci_hcd *tegra = dev_get_drvdata(hcd->self.controller);
+	struct ehci_hcd	*ehci = hcd_to_ehci(hcd);
+	struct ehci_regs __iomem *hw = ehci->regs;
+	unsigned long val;
+
+	set_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags);
+	tegra_ehci_power_up(hcd);
+
+	if (tegra->port_speed > TEGRA_USB_PHY_PORT_SPEED_HIGH) {
+		/* Wait for the phy to detect new devices
+		 * before we restart the controller */
+		msleep(10);
+		goto restart;
+	}
+
+	/* Force the phy to keep data lines in suspend state */
+	tegra_ehci_phy_restore_start(tegra->phy, tegra->port_speed);
+
+	/* Enable host mode */
+	tdi_reset(ehci);
+
+	/* Enable Port Power */
+	val = readl(&hw->port_status[0]);
+	val |= PORT_POWER;
+	writel(val, &hw->port_status[0]);
+	udelay(10);
+
+	/* Check if the phy resume from LP0. When the phy resume from LP0
+	 * USB register will be reset. */
+	if (!readl(&hw->async_next)) {
+		/* Program the field PTC based on the saved speed mode */
+		val = readl(&hw->port_status[0]);
+		val &= ~PORT_TEST(~0);
+		if (tegra->port_speed == TEGRA_USB_PHY_PORT_SPEED_HIGH)
+			val |= PORT_TEST_FORCE;
+		else if (tegra->port_speed == TEGRA_USB_PHY_PORT_SPEED_FULL)
+			val |= PORT_TEST(6);
+		else if (tegra->port_speed == TEGRA_USB_PHY_PORT_SPEED_LOW)
+			val |= PORT_TEST(7);
+		writel(val, &hw->port_status[0]);
+		udelay(10);
+
+		/* Disable test mode by setting PTC field to NORMAL_OP */
+		val = readl(&hw->port_status[0]);
+		val &= ~PORT_TEST(~0);
+		writel(val, &hw->port_status[0]);
+		udelay(10);
+	}
+
+	/* Poll until CCS is enabled */
+	if (handshake(ehci, &hw->port_status[0], PORT_CONNECT,
+						 PORT_CONNECT, 2000)) {
+		pr_err("%s: timeout waiting for PORT_CONNECT\n", __func__);
+		goto restart;
+	}
+
+	/* Poll until PE is enabled */
+	if (handshake(ehci, &hw->port_status[0], PORT_PE,
+						 PORT_PE, 2000)) {
+		pr_err("%s: timeout waiting for USB_PORTSC1_PE\n", __func__);
+		goto restart;
+	}
+
+	/* Clear the PCI status, to avoid an interrupt taken upon resume */
+	val = readl(&hw->status);
+	val |= STS_PCD;
+	writel(val, &hw->status);
+
+	/* Put controller in suspend mode by writing 1 to SUSP bit of PORTSC */
+	val = readl(&hw->port_status[0]);
+	if ((val & PORT_POWER) && (val & PORT_PE)) {
+		val |= PORT_SUSPEND;
+		writel(val, &hw->port_status[0]);
+
+		/* Wait until port suspend completes */
+		if (handshake(ehci, &hw->port_status[0], PORT_SUSPEND,
+							 PORT_SUSPEND, 1000)) {
+			pr_err("%s: timeout waiting for PORT_SUSPEND\n",
+								__func__);
+			goto restart;
+		}
+	}
+
+	tegra_ehci_phy_restore_end(tegra->phy);
+	return 0;
+
+restart:
+	if (tegra->port_speed <= TEGRA_USB_PHY_PORT_SPEED_HIGH)
+		tegra_ehci_phy_restore_end(tegra->phy);
+
+	tegra_ehci_restart(hcd);
+	return 0;
+}
+
+static void tegra_ehci_shutdown(struct usb_hcd *hcd)
+{
+	struct tegra_ehci_hcd *tegra = dev_get_drvdata(hcd->self.controller);
+
+	/* ehci_shutdown touches the USB controller registers, make sure
+	 * controller has clocks to it */
+	if (!tegra->host_resumed)
+		tegra_ehci_power_up(hcd);
+
+	ehci_shutdown(hcd);
+}
+
+static int tegra_ehci_setup(struct usb_hcd *hcd)
+{
+	struct ehci_hcd *ehci = hcd_to_ehci(hcd);
+	int retval;
+
+	/* EHCI registers start at offset 0x100 */
+	ehci->caps = hcd->regs + 0x100;
+	ehci->regs = hcd->regs + 0x100 +
+		HC_LENGTH(readl(&ehci->caps->hc_capbase));
+
+	dbg_hcs_params(ehci, "reset");
+	dbg_hcc_params(ehci, "reset");
+
+	/* cache this readonly data; minimize chip reads */
+	ehci->hcs_params = readl(&ehci->caps->hcs_params);
+
+	/* switch to host mode */
+	hcd->has_tt = 1;
+	ehci_reset(ehci);
+
+	retval = ehci_halt(ehci);
+	if (retval)
+		return retval;
+
+	/* data structure init */
+	retval = ehci_init(hcd);
+	if (retval)
+		return retval;
+
+	ehci->sbrn = 0x20;
+
+	ehci_port_power(ehci, 1);
+	return retval;
+}
+
+#ifdef CONFIG_PM
+static int tegra_ehci_bus_suspend(struct usb_hcd *hcd)
+{
+	struct tegra_ehci_hcd *tegra = dev_get_drvdata(hcd->self.controller);
+	int error_status = 0;
+
+	error_status = ehci_bus_suspend(hcd);
+	if (!error_status && tegra->power_down_on_bus_suspend) {
+		tegra_usb_suspend(hcd);
+		tegra->bus_suspended = 1;
+	}
+
+	return error_status;
+}
+
+static int tegra_ehci_bus_resume(struct usb_hcd *hcd)
+{
+	struct tegra_ehci_hcd *tegra = dev_get_drvdata(hcd->self.controller);
+
+	if (tegra->bus_suspended && tegra->power_down_on_bus_suspend) {
+		tegra_usb_resume(hcd);
+		tegra->bus_suspended = 0;
+	}
+
+	tegra_usb_phy_preresume(tegra->phy);
+	tegra->port_resuming = 1;
+	return ehci_bus_resume(hcd);
+}
+#endif
+
+struct temp_buffer {
+	void *kmalloc_ptr;
+	void *old_xfer_buffer;
+	u8 data[0];
+};
+
+static void free_temp_buffer(struct urb *urb)
+{
+	enum dma_data_direction dir;
+	struct temp_buffer *temp;
+
+	if (!(urb->transfer_flags & URB_ALIGNED_TEMP_BUFFER))
+		return;
+
+	dir = usb_urb_dir_in(urb) ? DMA_FROM_DEVICE : DMA_TO_DEVICE;
+
+	temp = container_of(urb->transfer_buffer, struct temp_buffer,
+			    data);
+
+	if (dir == DMA_FROM_DEVICE)
+		memcpy(temp->old_xfer_buffer, temp->data,
+		       urb->transfer_buffer_length);
+	urb->transfer_buffer = temp->old_xfer_buffer;
+	kfree(temp->kmalloc_ptr);
+
+	urb->transfer_flags &= ~URB_ALIGNED_TEMP_BUFFER;
+}
+
+static int alloc_temp_buffer(struct urb *urb, gfp_t mem_flags)
+{
+	enum dma_data_direction dir;
+	struct temp_buffer *temp, *kmalloc_ptr;
+	size_t kmalloc_size;
+
+	if (urb->num_sgs || urb->sg ||
+	    urb->transfer_buffer_length == 0 ||
+	    !((uintptr_t)urb->transfer_buffer & (TEGRA_USB_DMA_ALIGN - 1)))
+		return 0;
+
+	dir = usb_urb_dir_in(urb) ? DMA_FROM_DEVICE : DMA_TO_DEVICE;
+
+	/* Allocate a buffer with enough padding for alignment */
+	kmalloc_size = urb->transfer_buffer_length +
+		sizeof(struct temp_buffer) + TEGRA_USB_DMA_ALIGN - 1;
+
+	kmalloc_ptr = kmalloc(kmalloc_size, mem_flags);
+	if (!kmalloc_ptr)
+		return -ENOMEM;
+
+	/* Position our struct temp_buffer such that data is aligned */
+	temp = PTR_ALIGN(kmalloc_ptr + 1, TEGRA_USB_DMA_ALIGN) - 1;
+
+	temp->kmalloc_ptr = kmalloc_ptr;
+	temp->old_xfer_buffer = urb->transfer_buffer;
+	if (dir == DMA_TO_DEVICE)
+		memcpy(temp->data, urb->transfer_buffer,
+		       urb->transfer_buffer_length);
+	urb->transfer_buffer = temp->data;
+
+	urb->transfer_flags |= URB_ALIGNED_TEMP_BUFFER;
+
+	return 0;
+}
+
+static int tegra_ehci_map_urb_for_dma(struct usb_hcd *hcd, struct urb *urb,
+				      gfp_t mem_flags)
+{
+	int ret;
+
+	ret = alloc_temp_buffer(urb, mem_flags);
+	if (ret)
+		return ret;
+
+	ret = usb_hcd_map_urb_for_dma(hcd, urb, mem_flags);
+	if (ret)
+		free_temp_buffer(urb);
+
+	return ret;
+}
+
+static void tegra_ehci_unmap_urb_for_dma(struct usb_hcd *hcd, struct urb *urb)
+{
+	usb_hcd_unmap_urb_for_dma(hcd, urb);
+	free_temp_buffer(urb);
+}
+
+static const struct hc_driver tegra_ehci_hc_driver = {
+	.description		= hcd_name,
+	.product_desc		= "Tegra EHCI Host Controller",
+	.hcd_priv_size		= sizeof(struct ehci_hcd),
+
+	.flags			= HCD_USB2 | HCD_MEMORY,
+
+	.reset			= tegra_ehci_setup,
+	.irq			= ehci_irq,
+
+	.start			= ehci_run,
+	.stop			= ehci_stop,
+	.shutdown		= tegra_ehci_shutdown,
+	.urb_enqueue		= ehci_urb_enqueue,
+	.urb_dequeue		= ehci_urb_dequeue,
+	.map_urb_for_dma	= tegra_ehci_map_urb_for_dma,
+	.unmap_urb_for_dma	= tegra_ehci_unmap_urb_for_dma,
+	.endpoint_disable	= ehci_endpoint_disable,
+	.endpoint_reset		= ehci_endpoint_reset,
+	.get_frame_number	= ehci_get_frame,
+	.hub_status_data	= ehci_hub_status_data,
+	.hub_control		= tegra_ehci_hub_control,
+	.clear_tt_buffer_complete = ehci_clear_tt_buffer_complete,
+#ifdef CONFIG_PM
+	.bus_suspend		= tegra_ehci_bus_suspend,
+	.bus_resume		= tegra_ehci_bus_resume,
+#endif
+	.relinquish_port	= ehci_relinquish_port,
+	.port_handed_over	= ehci_port_handed_over,
+};
+
+static int tegra_ehci_probe(struct platform_device *pdev)
+{
+	struct resource *res;
+	struct usb_hcd *hcd;
+	struct tegra_ehci_hcd *tegra;
+	struct tegra_ehci_platform_data *pdata;
+	int err = 0;
+	int irq;
+	int instance = pdev->id;
+
+	pdata = pdev->dev.platform_data;
+	if (!pdata) {
+		dev_err(&pdev->dev, "Platform data missing\n");
+		return -EINVAL;
+	}
+
+	tegra = kzalloc(sizeof(struct tegra_ehci_hcd), GFP_KERNEL);
+	if (!tegra)
+		return -ENOMEM;
+
+	hcd = usb_create_hcd(&tegra_ehci_hc_driver, &pdev->dev,
+					dev_name(&pdev->dev));
+	if (!hcd) {
+		dev_err(&pdev->dev, "Unable to create HCD\n");
+		err = -ENOMEM;
+		goto fail_hcd;
+	}
+
+	platform_set_drvdata(pdev, tegra);
+
+	tegra->clk = clk_get(&pdev->dev, NULL);
+	if (IS_ERR(tegra->clk)) {
+		dev_err(&pdev->dev, "Can't get ehci clock\n");
+		err = PTR_ERR(tegra->clk);
+		goto fail_clk;
+	}
+
+	err = clk_enable(tegra->clk);
+	if (err)
+		goto fail_clken;
+
+	tegra->emc_clk = clk_get(&pdev->dev, "emc");
+	if (IS_ERR(tegra->emc_clk)) {
+		dev_err(&pdev->dev, "Can't get emc clock\n");
+		err = PTR_ERR(tegra->emc_clk);
+		goto fail_emc_clk;
+	}
+
+	clk_enable(tegra->emc_clk);
+	clk_set_rate(tegra->emc_clk, 400000000);
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!res) {
+		dev_err(&pdev->dev, "Failed to get I/O memory\n");
+		err = -ENXIO;
+		goto fail_io;
+	}
+	hcd->rsrc_start = res->start;
+	hcd->rsrc_len = resource_size(res);
+	hcd->regs = ioremap(res->start, resource_size(res));
+	if (!hcd->regs) {
+		dev_err(&pdev->dev, "Failed to remap I/O memory\n");
+		err = -ENOMEM;
+		goto fail_io;
+	}
+
+	tegra->phy = tegra_usb_phy_open(instance, hcd->regs, pdata->phy_config,
+						TEGRA_USB_PHY_MODE_HOST);
+	if (IS_ERR(tegra->phy)) {
+		dev_err(&pdev->dev, "Failed to open USB phy\n");
+		err = -ENXIO;
+		goto fail_phy;
+	}
+
+	err = tegra_usb_phy_power_on(tegra->phy);
+	if (err) {
+		dev_err(&pdev->dev, "Failed to power on the phy\n");
+		goto fail;
+	}
+
+	tegra->host_resumed = 1;
+	tegra->power_down_on_bus_suspend = pdata->power_down_on_bus_suspend;
+	tegra->ehci = hcd_to_ehci(hcd);
+
+	irq = platform_get_irq(pdev, 0);
+	if (!irq) {
+		dev_err(&pdev->dev, "Failed to get IRQ\n");
+		err = -ENODEV;
+		goto fail;
+	}
+	set_irq_flags(irq, IRQF_VALID);
+
+#ifdef CONFIG_USB_OTG_UTILS
+	if (pdata->operating_mode == TEGRA_USB_OTG) {
+		tegra->transceiver = otg_get_transceiver();
+		if (tegra->transceiver)
+			otg_set_host(tegra->transceiver, &hcd->self);
+	}
+#endif
+
+	err = usb_add_hcd(hcd, irq, IRQF_DISABLED | IRQF_SHARED);
+	if (err) {
+		dev_err(&pdev->dev, "Failed to add USB HCD\n");
+		goto fail;
+	}
+
+	return err;
+
+fail:
+#ifdef CONFIG_USB_OTG_UTILS
+	if (tegra->transceiver) {
+		otg_set_host(tegra->transceiver, NULL);
+		otg_put_transceiver(tegra->transceiver);
+	}
+#endif
+	tegra_usb_phy_close(tegra->phy);
+fail_phy:
+	iounmap(hcd->regs);
+fail_io:
+	clk_disable(tegra->emc_clk);
+	clk_put(tegra->emc_clk);
+fail_emc_clk:
+	clk_disable(tegra->clk);
+fail_clken:
+	clk_put(tegra->clk);
+fail_clk:
+	usb_put_hcd(hcd);
+fail_hcd:
+	kfree(tegra);
+	return err;
+}
+
+#ifdef CONFIG_PM
+static int tegra_ehci_resume(struct platform_device *pdev)
+{
+	struct tegra_ehci_hcd *tegra = platform_get_drvdata(pdev);
+	struct usb_hcd *hcd = ehci_to_hcd(tegra->ehci);
+
+	if (tegra->bus_suspended)
+		return 0;
+
+	return tegra_usb_resume(hcd);
+}
+
+static int tegra_ehci_suspend(struct platform_device *pdev, pm_message_t state)
+{
+	struct tegra_ehci_hcd *tegra = platform_get_drvdata(pdev);
+	struct usb_hcd *hcd = ehci_to_hcd(tegra->ehci);
+
+	if (tegra->bus_suspended)
+		return 0;
+
+	if (time_before(jiffies, tegra->ehci->next_statechange))
+		msleep(10);
+
+	return tegra_usb_suspend(hcd);
+}
+#endif
+
+static int tegra_ehci_remove(struct platform_device *pdev)
+{
+	struct tegra_ehci_hcd *tegra = platform_get_drvdata(pdev);
+	struct usb_hcd *hcd = ehci_to_hcd(tegra->ehci);
+
+	if (tegra == NULL || hcd == NULL)
+		return -EINVAL;
+
+#ifdef CONFIG_USB_OTG_UTILS
+	if (tegra->transceiver) {
+		otg_set_host(tegra->transceiver, NULL);
+		otg_put_transceiver(tegra->transceiver);
+	}
+#endif
+
+	usb_remove_hcd(hcd);
+	usb_put_hcd(hcd);
+
+	tegra_usb_phy_close(tegra->phy);
+	iounmap(hcd->regs);
+
+	clk_disable(tegra->clk);
+	clk_put(tegra->clk);
+
+	clk_disable(tegra->emc_clk);
+	clk_put(tegra->emc_clk);
+
+	kfree(tegra);
+	return 0;
+}
+
+static void tegra_ehci_hcd_shutdown(struct platform_device *pdev)
+{
+	struct tegra_ehci_hcd *tegra = platform_get_drvdata(pdev);
+	struct usb_hcd *hcd = ehci_to_hcd(tegra->ehci);
+
+	if (hcd->driver->shutdown)
+		hcd->driver->shutdown(hcd);
+}
+
+static struct platform_driver tegra_ehci_driver = {
+	.probe		= tegra_ehci_probe,
+	.remove		= tegra_ehci_remove,
+#ifdef CONFIG_PM
+	.suspend	= tegra_ehci_suspend,
+	.resume		= tegra_ehci_resume,
+#endif
+	.shutdown	= tegra_ehci_hcd_shutdown,
+	.driver		= {
+		.name	= "tegra-ehci",
+	}
+};
diff --git a/drivers/usb/host/ehci.h b/drivers/usb/host/ehci.h
index 799ac16a54b4..f86d3fa20214 100644
--- a/drivers/usb/host/ehci.h
+++ b/drivers/usb/host/ehci.h
@@ -131,7 +131,7 @@ struct ehci_hcd {			/* one per controller */
 	unsigned		has_amcc_usb23:1;
 	unsigned		need_io_watchdog:1;
 	unsigned		broken_periodic:1;
-	unsigned		amd_l1_fix:1;
+	unsigned		amd_pll_fix:1;
 	unsigned		fs_i_thresh:1;	/* Intel iso scheduling */
 	unsigned		use_dummy_qh:1;	/* AMD Frame List table quirk*/
 
diff --git a/drivers/usb/host/imx21-hcd.c b/drivers/usb/host/imx21-hcd.c
index f90d003f2302..2562e92e3178 100644
--- a/drivers/usb/host/imx21-hcd.c
+++ b/drivers/usb/host/imx21-hcd.c
@@ -927,7 +927,8 @@ static void schedule_nonisoc_etd(struct imx21 *imx21, struct urb *urb)
 		if (state == US_CTRL_SETUP) {
 			dir = TD_DIR_SETUP;
 			if (unsuitable_for_dma(urb->setup_dma))
-				unmap_urb_setup_for_dma(imx21->hcd, urb);
+				usb_hcd_unmap_urb_setup_for_dma(imx21->hcd,
+					urb);
 			etd->dma_handle = urb->setup_dma;
 			etd->cpu_buffer = urb->setup_packet;
 			bufround = 0;
@@ -943,7 +944,7 @@ static void schedule_nonisoc_etd(struct imx21 *imx21, struct urb *urb)
 		dir = usb_pipeout(pipe) ? TD_DIR_OUT : TD_DIR_IN;
 		bufround = (dir == TD_DIR_IN) ? 1 : 0;
 		if (unsuitable_for_dma(urb->transfer_dma))
-			unmap_urb_for_dma(imx21->hcd, urb);
+			usb_hcd_unmap_urb_for_dma(imx21->hcd, urb);
 
 		etd->dma_handle = urb->transfer_dma;
 		etd->cpu_buffer = urb->transfer_buffer;
@@ -1471,8 +1472,8 @@ static int get_hub_descriptor(struct usb_hcd *hcd,
 		0x0010 |	/* No over current protection */
 		0);
 
-	desc->bitmap[0] = 1 << 1;
-	desc->bitmap[1] = ~0;
+	desc->u.hs.DeviceRemovable[0] = 1 << 1;
+	desc->u.hs.DeviceRemovable[1] = ~0;
 	return 0;
 }
 
diff --git a/drivers/usb/host/isp116x-hcd.c b/drivers/usb/host/isp116x-hcd.c
index 0da7fc05f453..c0e22f26da19 100644
--- a/drivers/usb/host/isp116x-hcd.c
+++ b/drivers/usb/host/isp116x-hcd.c
@@ -951,9 +951,9 @@ static void isp116x_hub_descriptor(struct isp116x *isp116x,
 	/* Power switching, device type, overcurrent. */
 	desc->wHubCharacteristics = cpu_to_le16((u16) ((reg >> 8) & 0x1f));
 	desc->bPwrOn2PwrGood = (u8) ((reg >> 24) & 0xff);
-	/* two bitmaps:  ports removable, and legacy PortPwrCtrlMask */
-	desc->bitmap[0] = 0;
-	desc->bitmap[1] = ~0;
+	/* ports removable, and legacy PortPwrCtrlMask */
+	desc->u.hs.DeviceRemovable[0] = 0;
+	desc->u.hs.DeviceRemovable[1] = ~0;
 }
 
 /* Perform reset of a given port.
diff --git a/drivers/usb/host/isp1362-hcd.c b/drivers/usb/host/isp1362-hcd.c
index 43a39eb56cc6..662cd002adfc 100644
--- a/drivers/usb/host/isp1362-hcd.c
+++ b/drivers/usb/host/isp1362-hcd.c
@@ -226,7 +226,6 @@ static int claim_ptd_buffers(struct isp1362_ep_queue *epq,
 
 static inline void release_ptd_buffers(struct isp1362_ep_queue *epq, struct isp1362_ep *ep)
 {
-	int index = ep->ptd_index;
 	int last = ep->ptd_index + ep->num_ptds;
 
 	if (last > epq->buf_count)
@@ -236,10 +235,8 @@ static inline void release_ptd_buffers(struct isp1362_ep_queue *epq, struct isp1
 		    epq->buf_map, epq->skip_map);
 	BUG_ON(last > epq->buf_count);
 
-	for (; index < last; index++) {
-		__clear_bit(index, &epq->buf_map);
-		__set_bit(index, &epq->skip_map);
-	}
+	bitmap_clear(&epq->buf_map, ep->ptd_index, ep->num_ptds);
+	bitmap_set(&epq->skip_map, ep->ptd_index, ep->num_ptds);
 	epq->buf_avail += ep->num_ptds;
 	epq->ptd_count--;
 
@@ -1555,9 +1552,9 @@ static void isp1362_hub_descriptor(struct isp1362_hcd *isp1362_hcd,
 	desc->wHubCharacteristics = cpu_to_le16((reg >> 8) & 0x1f);
 	DBG(0, "%s: hubcharacteristics = %02x\n", __func__, cpu_to_le16((reg >> 8) & 0x1f));
 	desc->bPwrOn2PwrGood = (reg >> 24) & 0xff;
-	/* two bitmaps:  ports removable, and legacy PortPwrCtrlMask */
-	desc->bitmap[0] = desc->bNbrPorts == 1 ? 1 << 1 : 3 << 1;
-	desc->bitmap[1] = ~0;
+	/* ports removable, and legacy PortPwrCtrlMask */
+	desc->u.hs.DeviceRemovable[0] = desc->bNbrPorts == 1 ? 1 << 1 : 3 << 1;
+	desc->u.hs.DeviceRemovable[1] = ~0;
 
 	DBG(3, "%s: exit\n", __func__);
 }
diff --git a/drivers/usb/host/isp1760-hcd.c b/drivers/usb/host/isp1760-hcd.c
index bdba8c5d844a..f50e84ac570a 100644
--- a/drivers/usb/host/isp1760-hcd.c
+++ b/drivers/usb/host/isp1760-hcd.c
@@ -33,6 +33,7 @@ struct isp1760_hcd {
 	struct inter_packet_info atl_ints[32];
 	struct inter_packet_info int_ints[32];
 	struct memory_chunk memory_pool[BLOCKS];
+	u32 atl_queued;
 
 	/* periodic schedule support */
 #define	DEFAULT_I_TDPS		1024
@@ -47,10 +48,6 @@ static inline struct isp1760_hcd *hcd_to_priv(struct usb_hcd *hcd)
 {
 	return (struct isp1760_hcd *) (hcd->hcd_priv);
 }
-static inline struct usb_hcd *priv_to_hcd(struct isp1760_hcd *priv)
-{
-	return container_of((void *) priv, struct usb_hcd, hcd_priv);
-}
 
 /* Section 2.2 Host Controller Capability Registers */
 #define HC_LENGTH(p)		(((p)>>00)&0x00ff)	/* bits 7:0 */
@@ -80,11 +77,10 @@ static inline struct usb_hcd *priv_to_hcd(struct isp1760_hcd *priv)
 #define PORT_RWC_BITS   (PORT_CSC)
 
 struct isp1760_qtd {
-	struct isp1760_qtd *hw_next;
 	u8 packet_type;
-	u8 toggle;
-
 	void *data_buffer;
+	u32 payload_addr;
+
 	/* the rest is HCD-private */
 	struct list_head qtd_list;
 	struct urb *urb;
@@ -92,205 +88,267 @@ struct isp1760_qtd {
 
 	/* isp special*/
 	u32 status;
-#define URB_COMPLETE_NOTIFY	(1 << 0)
 #define URB_ENQUEUED		(1 << 1)
-#define URB_TYPE_ATL		(1 << 2)
-#define URB_TYPE_INT		(1 << 3)
 };
 
 struct isp1760_qh {
 	/* first part defined by EHCI spec */
 	struct list_head qtd_list;
-	struct isp1760_hcd *priv;
-
-	/* periodic schedule info */
-	unsigned short period;		/* polling interval */
-	struct usb_device *dev;
 
 	u32 toggle;
 	u32 ping;
 };
 
-#define ehci_port_speed(priv, portsc) USB_PORT_STAT_HIGH_SPEED
-
-static unsigned int isp1760_readl(__u32 __iomem *regs)
+/*
+ * Access functions for isp176x registers (addresses 0..0x03FF).
+ */
+static u32 reg_read32(void __iomem *base, u32 reg)
 {
-	return readl(regs);
+	return readl(base + reg);
 }
 
-static void isp1760_writel(const unsigned int val, __u32 __iomem *regs)
+static void reg_write32(void __iomem *base, u32 reg, u32 val)
 {
-	writel(val, regs);
+	writel(val, base + reg);
 }
 
 /*
- * The next two copy via MMIO data to/from the device. memcpy_{to|from}io()
+ * Access functions for isp176x memory (offset >= 0x0400).
+ *
+ * bank_reads8() reads memory locations prefetched by an earlier write to
+ * HC_MEMORY_REG (see isp176x datasheet). Unless you want to do fancy multi-
+ * bank optimizations, you should use the more generic mem_reads8() below.
+ *
+ * For access to ptd memory, use the specialized ptd_read() and ptd_write()
+ * below.
+ *
+ * These functions copy via MMIO data to/from the device. memcpy_{to|from}io()
  * doesn't quite work because some people have to enforce 32-bit access
  */
-static void priv_read_copy(struct isp1760_hcd *priv, u32 *src,
-		__u32 __iomem *dst, u32 len)
+static void bank_reads8(void __iomem *src_base, u32 src_offset, u32 bank_addr,
+							__u32 *dst, u32 bytes)
 {
+	__u32 __iomem *src;
 	u32 val;
-	u8 *buff8;
+	__u8 *src_byteptr;
+	__u8 *dst_byteptr;
 
-	if (!src) {
-		printk(KERN_ERR "ERROR: buffer: %p len: %d\n", src, len);
-		return;
-	}
+	src = src_base + (bank_addr | src_offset);
 
-	while (len >= 4) {
-		*src = __raw_readl(dst);
-		len -= 4;
-		src++;
-		dst++;
+	if (src_offset < PAYLOAD_OFFSET) {
+		while (bytes >= 4) {
+			*dst = le32_to_cpu(__raw_readl(src));
+			bytes -= 4;
+			src++;
+			dst++;
+		}
+	} else {
+		while (bytes >= 4) {
+			*dst = __raw_readl(src);
+			bytes -= 4;
+			src++;
+			dst++;
+		}
 	}
 
-	if (!len)
+	if (!bytes)
 		return;
 
 	/* in case we have 3, 2 or 1 by left. The dst buffer may not be fully
 	 * allocated.
 	 */
-	val = isp1760_readl(dst);
-
-	buff8 = (u8 *)src;
-	while (len) {
-
-		*buff8 = val;
-		val >>= 8;
-		len--;
-		buff8++;
+	if (src_offset < PAYLOAD_OFFSET)
+		val = le32_to_cpu(__raw_readl(src));
+	else
+		val = __raw_readl(src);
+
+	dst_byteptr = (void *) dst;
+	src_byteptr = (void *) &val;
+	while (bytes > 0) {
+		*dst_byteptr = *src_byteptr;
+		dst_byteptr++;
+		src_byteptr++;
+		bytes--;
 	}
 }
 
-static void priv_write_copy(const struct isp1760_hcd *priv, const u32 *src,
-		__u32 __iomem *dst, u32 len)
+static void mem_reads8(void __iomem *src_base, u32 src_offset, void *dst,
+								u32 bytes)
 {
-	while (len >= 4) {
-		__raw_writel(*src, dst);
-		len -= 4;
-		src++;
-		dst++;
+	reg_write32(src_base, HC_MEMORY_REG, src_offset + ISP_BANK(0));
+	ndelay(90);
+	bank_reads8(src_base, src_offset, ISP_BANK(0), dst, bytes);
+}
+
+static void mem_writes8(void __iomem *dst_base, u32 dst_offset,
+						__u32 const *src, u32 bytes)
+{
+	__u32 __iomem *dst;
+
+	dst = dst_base + dst_offset;
+
+	if (dst_offset < PAYLOAD_OFFSET) {
+		while (bytes >= 4) {
+			__raw_writel(cpu_to_le32(*src), dst);
+			bytes -= 4;
+			src++;
+			dst++;
+		}
+	} else {
+		while (bytes >= 4) {
+			__raw_writel(*src, dst);
+			bytes -= 4;
+			src++;
+			dst++;
+		}
 	}
 
-	if (!len)
+	if (!bytes)
 		return;
-	/* in case we have 3, 2 or 1 by left. The buffer is allocated and the
-	 * extra bytes should not be read by the HW
+	/* in case we have 3, 2 or 1 bytes left. The buffer is allocated and the
+	 * extra bytes should not be read by the HW.
 	 */
 
-	__raw_writel(*src, dst);
+	if (dst_offset < PAYLOAD_OFFSET)
+		__raw_writel(cpu_to_le32(*src), dst);
+	else
+		__raw_writel(*src, dst);
+}
+
+/*
+ * Read and write ptds. 'ptd_offset' should be one of ISO_PTD_OFFSET,
+ * INT_PTD_OFFSET, and ATL_PTD_OFFSET. 'slot' should be less than 32.
+ */
+static void ptd_read(void __iomem *base, u32 ptd_offset, u32 slot,
+								struct ptd *ptd)
+{
+	reg_write32(base, HC_MEMORY_REG,
+				ISP_BANK(0) + ptd_offset + slot*sizeof(*ptd));
+	ndelay(90);
+	bank_reads8(base, ptd_offset + slot*sizeof(*ptd), ISP_BANK(0),
+						(void *) ptd, sizeof(*ptd));
+}
+
+static void ptd_write(void __iomem *base, u32 ptd_offset, u32 slot,
+								struct ptd *ptd)
+{
+	mem_writes8(base, ptd_offset + slot*sizeof(*ptd) + sizeof(ptd->dw0),
+						&ptd->dw1, 7*sizeof(ptd->dw1));
+	/* Make sure dw0 gets written last (after other dw's and after payload)
+	   since it contains the enable bit */
+	wmb();
+	mem_writes8(base, ptd_offset + slot*sizeof(*ptd), &ptd->dw0,
+							sizeof(ptd->dw0));
 }
 
+
 /* memory management of the 60kb on the chip from 0x1000 to 0xffff */
 static void init_memory(struct isp1760_hcd *priv)
 {
-	int i;
-	u32 payload;
+	int i, curr;
+	u32 payload_addr;
 
-	payload = 0x1000;
+	payload_addr = PAYLOAD_OFFSET;
 	for (i = 0; i < BLOCK_1_NUM; i++) {
-		priv->memory_pool[i].start = payload;
+		priv->memory_pool[i].start = payload_addr;
 		priv->memory_pool[i].size = BLOCK_1_SIZE;
 		priv->memory_pool[i].free = 1;
-		payload += priv->memory_pool[i].size;
+		payload_addr += priv->memory_pool[i].size;
 	}
 
-
-	for (i = BLOCK_1_NUM; i < BLOCK_1_NUM + BLOCK_2_NUM; i++) {
-		priv->memory_pool[i].start = payload;
-		priv->memory_pool[i].size = BLOCK_2_SIZE;
-		priv->memory_pool[i].free = 1;
-		payload += priv->memory_pool[i].size;
+	curr = i;
+	for (i = 0; i < BLOCK_2_NUM; i++) {
+		priv->memory_pool[curr + i].start = payload_addr;
+		priv->memory_pool[curr + i].size = BLOCK_2_SIZE;
+		priv->memory_pool[curr + i].free = 1;
+		payload_addr += priv->memory_pool[curr + i].size;
 	}
 
-
-	for (i = BLOCK_1_NUM + BLOCK_2_NUM; i < BLOCKS; i++) {
-		priv->memory_pool[i].start = payload;
-		priv->memory_pool[i].size = BLOCK_3_SIZE;
-		priv->memory_pool[i].free = 1;
-		payload += priv->memory_pool[i].size;
+	curr = i;
+	for (i = 0; i < BLOCK_3_NUM; i++) {
+		priv->memory_pool[curr + i].start = payload_addr;
+		priv->memory_pool[curr + i].size = BLOCK_3_SIZE;
+		priv->memory_pool[curr + i].free = 1;
+		payload_addr += priv->memory_pool[curr + i].size;
 	}
 
-	BUG_ON(payload - priv->memory_pool[i - 1].size > PAYLOAD_SIZE);
+	BUG_ON(payload_addr - priv->memory_pool[0].start > PAYLOAD_AREA_SIZE);
 }
 
-static u32 alloc_mem(struct isp1760_hcd *priv, u32 size)
+static void alloc_mem(struct usb_hcd *hcd, struct isp1760_qtd *qtd)
 {
+	struct isp1760_hcd *priv = hcd_to_priv(hcd);
 	int i;
 
-	if (!size)
-		return ISP1760_NULL_POINTER;
+	BUG_ON(qtd->payload_addr);
+
+	if (!qtd->length)
+		return;
 
 	for (i = 0; i < BLOCKS; i++) {
-		if (priv->memory_pool[i].size >= size &&
+		if (priv->memory_pool[i].size >= qtd->length &&
 				priv->memory_pool[i].free) {
-
 			priv->memory_pool[i].free = 0;
-			return priv->memory_pool[i].start;
+			qtd->payload_addr = priv->memory_pool[i].start;
+			return;
 		}
 	}
 
-	printk(KERN_ERR "ISP1760 MEM: can not allocate %d bytes of memory\n",
-			size);
-	printk(KERN_ERR "Current memory map:\n");
+	dev_err(hcd->self.controller,
+				"%s: Can not allocate %lu bytes of memory\n"
+				"Current memory map:\n",
+				__func__, qtd->length);
 	for (i = 0; i < BLOCKS; i++) {
-		printk(KERN_ERR "Pool %2d size %4d status: %d\n",
+		dev_err(hcd->self.controller, "Pool %2d size %4d status: %d\n",
 				i, priv->memory_pool[i].size,
 				priv->memory_pool[i].free);
 	}
 	/* XXX maybe -ENOMEM could be possible */
 	BUG();
-	return 0;
+	return;
 }
 
-static void free_mem(struct isp1760_hcd *priv, u32 mem)
+static void free_mem(struct usb_hcd *hcd, struct isp1760_qtd *qtd)
 {
+	struct isp1760_hcd *priv = hcd_to_priv(hcd);
 	int i;
 
-	if (mem == ISP1760_NULL_POINTER)
+	if (!qtd->payload_addr)
 		return;
 
 	for (i = 0; i < BLOCKS; i++) {
-		if (priv->memory_pool[i].start == mem) {
-
+		if (priv->memory_pool[i].start == qtd->payload_addr) {
 			BUG_ON(priv->memory_pool[i].free);
-
 			priv->memory_pool[i].free = 1;
-			return ;
+			qtd->payload_addr = 0;
+			return;
 		}
 	}
 
-	printk(KERN_ERR "Trying to free not-here-allocated memory :%08x\n",
-			mem);
+	dev_err(hcd->self.controller, "%s: Invalid pointer: %08x\n",
+						__func__, qtd->payload_addr);
 	BUG();
 }
 
 static void isp1760_init_regs(struct usb_hcd *hcd)
 {
-	isp1760_writel(0, hcd->regs + HC_BUFFER_STATUS_REG);
-	isp1760_writel(NO_TRANSFER_ACTIVE, hcd->regs +
-			HC_ATL_PTD_SKIPMAP_REG);
-	isp1760_writel(NO_TRANSFER_ACTIVE, hcd->regs +
-			HC_INT_PTD_SKIPMAP_REG);
-	isp1760_writel(NO_TRANSFER_ACTIVE, hcd->regs +
-			HC_ISO_PTD_SKIPMAP_REG);
-
-	isp1760_writel(~NO_TRANSFER_ACTIVE, hcd->regs +
-			HC_ATL_PTD_DONEMAP_REG);
-	isp1760_writel(~NO_TRANSFER_ACTIVE, hcd->regs +
-			HC_INT_PTD_DONEMAP_REG);
-	isp1760_writel(~NO_TRANSFER_ACTIVE, hcd->regs +
-			HC_ISO_PTD_DONEMAP_REG);
+	reg_write32(hcd->regs, HC_BUFFER_STATUS_REG, 0);
+	reg_write32(hcd->regs, HC_ATL_PTD_SKIPMAP_REG, NO_TRANSFER_ACTIVE);
+	reg_write32(hcd->regs, HC_INT_PTD_SKIPMAP_REG, NO_TRANSFER_ACTIVE);
+	reg_write32(hcd->regs, HC_ISO_PTD_SKIPMAP_REG, NO_TRANSFER_ACTIVE);
+
+	reg_write32(hcd->regs, HC_ATL_PTD_DONEMAP_REG, ~NO_TRANSFER_ACTIVE);
+	reg_write32(hcd->regs, HC_INT_PTD_DONEMAP_REG, ~NO_TRANSFER_ACTIVE);
+	reg_write32(hcd->regs, HC_ISO_PTD_DONEMAP_REG, ~NO_TRANSFER_ACTIVE);
 }
 
-static int handshake(struct isp1760_hcd *priv, void __iomem *ptr,
+static int handshake(struct usb_hcd *hcd, u32 reg,
 		      u32 mask, u32 done, int usec)
 {
 	u32 result;
 
 	do {
-		result = isp1760_readl(ptr);
+		result = reg_read32(hcd->regs, reg);
 		if (result == ~0)
 			return -ENODEV;
 		result &= mask;
@@ -303,17 +361,18 @@ static int handshake(struct isp1760_hcd *priv, void __iomem *ptr,
 }
 
 /* reset a non-running (STS_HALT == 1) controller */
-static int ehci_reset(struct isp1760_hcd *priv)
+static int ehci_reset(struct usb_hcd *hcd)
 {
 	int retval;
-	struct usb_hcd *hcd = priv_to_hcd(priv);
-	u32 command = isp1760_readl(hcd->regs + HC_USBCMD);
+	struct isp1760_hcd *priv = hcd_to_priv(hcd);
+
+	u32 command = reg_read32(hcd->regs, HC_USBCMD);
 
 	command |= CMD_RESET;
-	isp1760_writel(command, hcd->regs + HC_USBCMD);
+	reg_write32(hcd->regs, HC_USBCMD, command);
 	hcd->state = HC_STATE_HALT;
 	priv->next_statechange = jiffies;
-	retval = handshake(priv, hcd->regs + HC_USBCMD,
+	retval = handshake(hcd, HC_USBCMD,
 			    CMD_RESET, 0, 250 * 1000);
 	return retval;
 }
@@ -324,8 +383,7 @@ static void qh_destroy(struct isp1760_qh *qh)
 	kmem_cache_free(qh_cachep, qh);
 }
 
-static struct isp1760_qh *isp1760_qh_alloc(struct isp1760_hcd *priv,
-		gfp_t flags)
+static struct isp1760_qh *isp1760_qh_alloc(gfp_t flags)
 {
 	struct isp1760_qh *qh;
 
@@ -334,7 +392,6 @@ static struct isp1760_qh *isp1760_qh_alloc(struct isp1760_hcd *priv,
 		return qh;
 
 	INIT_LIST_HEAD(&qh->qtd_list);
-	qh->priv = priv;
 	return qh;
 }
 
@@ -361,7 +418,7 @@ static int priv_init(struct usb_hcd *hcd)
 	priv->periodic_size = DEFAULT_I_TDPS;
 
 	/* controllers may cache some of the periodic schedule ... */
-	hcc_params = isp1760_readl(hcd->regs + HC_HCCPARAMS);
+	hcc_params = reg_read32(hcd->regs, HC_HCCPARAMS);
 	/* full frame cache */
 	if (HCC_ISOC_CACHE(hcc_params))
 		priv->i_thresh = 8;
@@ -398,15 +455,15 @@ static int isp1760_hc_setup(struct usb_hcd *hcd)
 	 * Write it twice to ensure correct upper bits if switching
 	 * to 16-bit mode.
 	 */
-	isp1760_writel(hwmode, hcd->regs + HC_HW_MODE_CTRL);
-	isp1760_writel(hwmode, hcd->regs + HC_HW_MODE_CTRL);
+	reg_write32(hcd->regs, HC_HW_MODE_CTRL, hwmode);
+	reg_write32(hcd->regs, HC_HW_MODE_CTRL, hwmode);
 
-	isp1760_writel(0xdeadbabe, hcd->regs + HC_SCRATCH_REG);
+	reg_write32(hcd->regs, HC_SCRATCH_REG, 0xdeadbabe);
 	/* Change bus pattern */
-	scratch = isp1760_readl(hcd->regs + HC_CHIP_ID_REG);
-	scratch = isp1760_readl(hcd->regs + HC_SCRATCH_REG);
+	scratch = reg_read32(hcd->regs, HC_CHIP_ID_REG);
+	scratch = reg_read32(hcd->regs, HC_SCRATCH_REG);
 	if (scratch != 0xdeadbabe) {
-		printk(KERN_ERR "ISP1760: Scratch test failed.\n");
+		dev_err(hcd->self.controller, "Scratch test failed.\n");
 		return -ENODEV;
 	}
 
@@ -414,30 +471,30 @@ static int isp1760_hc_setup(struct usb_hcd *hcd)
 	isp1760_init_regs(hcd);
 
 	/* reset */
-	isp1760_writel(SW_RESET_RESET_ALL, hcd->regs + HC_RESET_REG);
+	reg_write32(hcd->regs, HC_RESET_REG, SW_RESET_RESET_ALL);
 	mdelay(100);
 
-	isp1760_writel(SW_RESET_RESET_HC, hcd->regs + HC_RESET_REG);
+	reg_write32(hcd->regs, HC_RESET_REG, SW_RESET_RESET_HC);
 	mdelay(100);
 
-	result = ehci_reset(priv);
+	result = ehci_reset(hcd);
 	if (result)
 		return result;
 
 	/* Step 11 passed */
 
-	isp1760_info(priv, "bus width: %d, oc: %s\n",
+	dev_info(hcd->self.controller, "bus width: %d, oc: %s\n",
 			   (priv->devflags & ISP1760_FLAG_BUS_WIDTH_16) ?
 			   16 : 32, (priv->devflags & ISP1760_FLAG_ANALOG_OC) ?
 			   "analog" : "digital");
 
 	/* ATL reset */
-	isp1760_writel(hwmode | ALL_ATX_RESET, hcd->regs + HC_HW_MODE_CTRL);
+	reg_write32(hcd->regs, HC_HW_MODE_CTRL, hwmode | ALL_ATX_RESET);
 	mdelay(10);
-	isp1760_writel(hwmode, hcd->regs + HC_HW_MODE_CTRL);
+	reg_write32(hcd->regs, HC_HW_MODE_CTRL, hwmode);
 
-	isp1760_writel(INTERRUPT_ENABLE_MASK, hcd->regs + HC_INTERRUPT_REG);
-	isp1760_writel(INTERRUPT_ENABLE_MASK, hcd->regs + HC_INTERRUPT_ENABLE);
+	reg_write32(hcd->regs, HC_INTERRUPT_REG, INTERRUPT_ENABLE_MASK);
+	reg_write32(hcd->regs, HC_INTERRUPT_ENABLE, INTERRUPT_ENABLE_MASK);
 
 	/*
 	 * PORT 1 Control register of the ISP1760 is the OTG control
@@ -445,11 +502,10 @@ static int isp1760_hc_setup(struct usb_hcd *hcd)
 	 * support in this driver, we use port 1 as a "normal" USB host port on
 	 * both chips.
 	 */
-	isp1760_writel(PORT1_POWER | PORT1_INIT2,
-		       hcd->regs + HC_PORT1_CTRL);
+	reg_write32(hcd->regs, HC_PORT1_CTRL, PORT1_POWER | PORT1_INIT2);
 	mdelay(10);
 
-	priv->hcs_params = isp1760_readl(hcd->regs + HC_HCSPARAMS);
+	priv->hcs_params = reg_read32(hcd->regs, HC_HCSPARAMS);
 
 	return priv_init(hcd);
 }
@@ -457,25 +513,24 @@ static int isp1760_hc_setup(struct usb_hcd *hcd)
 static void isp1760_init_maps(struct usb_hcd *hcd)
 {
 	/*set last maps, for iso its only 1, else 32 tds bitmap*/
-	isp1760_writel(0x80000000, hcd->regs + HC_ATL_PTD_LASTPTD_REG);
-	isp1760_writel(0x80000000, hcd->regs + HC_INT_PTD_LASTPTD_REG);
-	isp1760_writel(0x00000001, hcd->regs + HC_ISO_PTD_LASTPTD_REG);
+	reg_write32(hcd->regs, HC_ATL_PTD_LASTPTD_REG, 0x80000000);
+	reg_write32(hcd->regs, HC_INT_PTD_LASTPTD_REG, 0x80000000);
+	reg_write32(hcd->regs, HC_ISO_PTD_LASTPTD_REG, 0x00000001);
 }
 
 static void isp1760_enable_interrupts(struct usb_hcd *hcd)
 {
-	isp1760_writel(0, hcd->regs + HC_ATL_IRQ_MASK_AND_REG);
-	isp1760_writel(0, hcd->regs + HC_ATL_IRQ_MASK_OR_REG);
-	isp1760_writel(0, hcd->regs + HC_INT_IRQ_MASK_AND_REG);
-	isp1760_writel(0, hcd->regs + HC_INT_IRQ_MASK_OR_REG);
-	isp1760_writel(0, hcd->regs + HC_ISO_IRQ_MASK_AND_REG);
-	isp1760_writel(0xffffffff, hcd->regs + HC_ISO_IRQ_MASK_OR_REG);
+	reg_write32(hcd->regs, HC_ATL_IRQ_MASK_AND_REG, 0);
+	reg_write32(hcd->regs, HC_ATL_IRQ_MASK_OR_REG, 0);
+	reg_write32(hcd->regs, HC_INT_IRQ_MASK_AND_REG, 0);
+	reg_write32(hcd->regs, HC_INT_IRQ_MASK_OR_REG, 0);
+	reg_write32(hcd->regs, HC_ISO_IRQ_MASK_AND_REG, 0);
+	reg_write32(hcd->regs, HC_ISO_IRQ_MASK_OR_REG, 0xffffffff);
 	/* step 23 passed */
 }
 
 static int isp1760_run(struct usb_hcd *hcd)
 {
-	struct isp1760_hcd *priv = hcd_to_priv(hcd);
 	int retval;
 	u32 temp;
 	u32 command;
@@ -485,15 +540,15 @@ static int isp1760_run(struct usb_hcd *hcd)
 
 	hcd->state = HC_STATE_RUNNING;
 	isp1760_enable_interrupts(hcd);
-	temp = isp1760_readl(hcd->regs + HC_HW_MODE_CTRL);
-	isp1760_writel(temp | HW_GLOBAL_INTR_EN, hcd->regs + HC_HW_MODE_CTRL);
+	temp = reg_read32(hcd->regs, HC_HW_MODE_CTRL);
+	reg_write32(hcd->regs, HC_HW_MODE_CTRL, temp | HW_GLOBAL_INTR_EN);
 
-	command = isp1760_readl(hcd->regs + HC_USBCMD);
+	command = reg_read32(hcd->regs, HC_USBCMD);
 	command &= ~(CMD_LRESET|CMD_RESET);
 	command |= CMD_RUN;
-	isp1760_writel(command, hcd->regs + HC_USBCMD);
+	reg_write32(hcd->regs, HC_USBCMD, command);
 
-	retval = handshake(priv, hcd->regs + HC_USBCMD,	CMD_RUN, CMD_RUN,
+	retval = handshake(hcd, HC_USBCMD, CMD_RUN, CMD_RUN,
 			250 * 1000);
 	if (retval)
 		return retval;
@@ -504,17 +559,16 @@ static int isp1760_run(struct usb_hcd *hcd)
 	 * the semaphore while doing so.
 	 */
 	down_write(&ehci_cf_port_reset_rwsem);
-	isp1760_writel(FLAG_CF, hcd->regs + HC_CONFIGFLAG);
+	reg_write32(hcd->regs, HC_CONFIGFLAG, FLAG_CF);
 
-	retval = handshake(priv, hcd->regs + HC_CONFIGFLAG, FLAG_CF, FLAG_CF,
-			250 * 1000);
+	retval = handshake(hcd, HC_CONFIGFLAG, FLAG_CF, FLAG_CF, 250 * 1000);
 	up_write(&ehci_cf_port_reset_rwsem);
 	if (retval)
 		return retval;
 
-	chipid = isp1760_readl(hcd->regs + HC_CHIP_ID_REG);
-	isp1760_info(priv, "USB ISP %04x HW rev. %d started\n",	chipid & 0xffff,
-			chipid >> 16);
+	chipid = reg_read32(hcd->regs, HC_CHIP_ID_REG);
+	dev_info(hcd->self.controller, "USB ISP %04x HW rev. %d started\n",
+					chipid & 0xffff, chipid >> 16);
 
 	/* PTD Register Init Part 2, Step 28 */
 	/* enable INTs */
@@ -532,160 +586,156 @@ static u32 base_to_chip(u32 base)
 	return ((base - 0x400) >> 3);
 }
 
-static void transform_into_atl(struct isp1760_hcd *priv, struct isp1760_qh *qh,
-			struct isp1760_qtd *qtd, struct urb *urb,
-			u32 payload, struct ptd *ptd)
+static int last_qtd_of_urb(struct isp1760_qtd *qtd, struct isp1760_qh *qh)
+{
+	struct urb *urb;
+
+	if (list_is_last(&qtd->qtd_list, &qh->qtd_list))
+		return 1;
+
+	urb = qtd->urb;
+	qtd = list_entry(qtd->qtd_list.next, typeof(*qtd), qtd_list);
+	return (qtd->urb != urb);
+}
+
+static void transform_into_atl(struct isp1760_qh *qh,
+			struct isp1760_qtd *qtd, struct ptd *ptd)
 {
-	u32 dw0;
-	u32 dw1;
-	u32 dw2;
-	u32 dw3;
 	u32 maxpacket;
 	u32 multi;
 	u32 pid_code;
 	u32 rl = RL_COUNTER;
 	u32 nak = NAK_COUNTER;
 
+	memset(ptd, 0, sizeof(*ptd));
+
 	/* according to 3.6.2, max packet len can not be > 0x400 */
-	maxpacket = usb_maxpacket(urb->dev, urb->pipe, usb_pipeout(urb->pipe));
+	maxpacket = usb_maxpacket(qtd->urb->dev, qtd->urb->pipe,
+						usb_pipeout(qtd->urb->pipe));
 	multi =  1 + ((maxpacket >> 11) & 0x3);
 	maxpacket &= 0x7ff;
 
 	/* DW0 */
-	dw0 = PTD_VALID;
-	dw0 |= PTD_LENGTH(qtd->length);
-	dw0 |= PTD_MAXPACKET(maxpacket);
-	dw0 |= PTD_ENDPOINT(usb_pipeendpoint(urb->pipe));
-	dw1 = usb_pipeendpoint(urb->pipe) >> 1;
+	ptd->dw0 = PTD_VALID;
+	ptd->dw0 |= PTD_LENGTH(qtd->length);
+	ptd->dw0 |= PTD_MAXPACKET(maxpacket);
+	ptd->dw0 |= PTD_ENDPOINT(usb_pipeendpoint(qtd->urb->pipe));
 
 	/* DW1 */
-	dw1 |= PTD_DEVICE_ADDR(usb_pipedevice(urb->pipe));
+	ptd->dw1 = usb_pipeendpoint(qtd->urb->pipe) >> 1;
+	ptd->dw1 |= PTD_DEVICE_ADDR(usb_pipedevice(qtd->urb->pipe));
 
 	pid_code = qtd->packet_type;
-	dw1 |= PTD_PID_TOKEN(pid_code);
+	ptd->dw1 |= PTD_PID_TOKEN(pid_code);
 
-	if (usb_pipebulk(urb->pipe))
-		dw1 |= PTD_TRANS_BULK;
-	else if  (usb_pipeint(urb->pipe))
-		dw1 |= PTD_TRANS_INT;
+	if (usb_pipebulk(qtd->urb->pipe))
+		ptd->dw1 |= PTD_TRANS_BULK;
+	else if  (usb_pipeint(qtd->urb->pipe))
+		ptd->dw1 |= PTD_TRANS_INT;
 
-	if (urb->dev->speed != USB_SPEED_HIGH) {
+	if (qtd->urb->dev->speed != USB_SPEED_HIGH) {
 		/* split transaction */
 
-		dw1 |= PTD_TRANS_SPLIT;
-		if (urb->dev->speed == USB_SPEED_LOW)
-			dw1 |= PTD_SE_USB_LOSPEED;
+		ptd->dw1 |= PTD_TRANS_SPLIT;
+		if (qtd->urb->dev->speed == USB_SPEED_LOW)
+			ptd->dw1 |= PTD_SE_USB_LOSPEED;
 
-		dw1 |= PTD_PORT_NUM(urb->dev->ttport);
-		dw1 |= PTD_HUB_NUM(urb->dev->tt->hub->devnum);
+		ptd->dw1 |= PTD_PORT_NUM(qtd->urb->dev->ttport);
+		ptd->dw1 |= PTD_HUB_NUM(qtd->urb->dev->tt->hub->devnum);
 
 		/* SE bit for Split INT transfers */
-		if (usb_pipeint(urb->pipe) &&
-				(urb->dev->speed == USB_SPEED_LOW))
-			dw1 |= 2 << 16;
+		if (usb_pipeint(qtd->urb->pipe) &&
+				(qtd->urb->dev->speed == USB_SPEED_LOW))
+			ptd->dw1 |= 2 << 16;
 
-		dw3 = 0;
+		ptd->dw3 = 0;
 		rl = 0;
 		nak = 0;
 	} else {
-		dw0 |= PTD_MULTI(multi);
-		if (usb_pipecontrol(urb->pipe) || usb_pipebulk(urb->pipe))
-			dw3 = qh->ping;
+		ptd->dw0 |= PTD_MULTI(multi);
+		if (usb_pipecontrol(qtd->urb->pipe) ||
+						usb_pipebulk(qtd->urb->pipe))
+			ptd->dw3 = qh->ping;
 		else
-			dw3 = 0;
+			ptd->dw3 = 0;
 	}
 	/* DW2 */
-	dw2 = 0;
-	dw2 |= PTD_DATA_START_ADDR(base_to_chip(payload));
-	dw2 |= PTD_RL_CNT(rl);
-	dw3 |= PTD_NAC_CNT(nak);
+	ptd->dw2 = 0;
+	ptd->dw2 |= PTD_DATA_START_ADDR(base_to_chip(qtd->payload_addr));
+	ptd->dw2 |= PTD_RL_CNT(rl);
+	ptd->dw3 |= PTD_NAC_CNT(nak);
 
 	/* DW3 */
-	if (usb_pipecontrol(urb->pipe))
-		dw3 |= PTD_DATA_TOGGLE(qtd->toggle);
-	else
-		dw3 |= qh->toggle;
-
+	ptd->dw3 |= qh->toggle;
+	if (usb_pipecontrol(qtd->urb->pipe)) {
+		if (qtd->data_buffer == qtd->urb->setup_packet)
+			ptd->dw3 &= ~PTD_DATA_TOGGLE(1);
+		else if (last_qtd_of_urb(qtd, qh))
+			ptd->dw3 |= PTD_DATA_TOGGLE(1);
+	}
 
-	dw3 |= PTD_ACTIVE;
+	ptd->dw3 |= PTD_ACTIVE;
 	/* Cerr */
-	dw3 |= PTD_CERR(ERR_COUNTER);
-
-	memset(ptd, 0, sizeof(*ptd));
-
-	ptd->dw0 = cpu_to_le32(dw0);
-	ptd->dw1 = cpu_to_le32(dw1);
-	ptd->dw2 = cpu_to_le32(dw2);
-	ptd->dw3 = cpu_to_le32(dw3);
+	ptd->dw3 |= PTD_CERR(ERR_COUNTER);
 }
 
-static void transform_add_int(struct isp1760_hcd *priv, struct isp1760_qh *qh,
-			struct isp1760_qtd *qtd, struct urb *urb,
-			u32 payload, struct ptd *ptd)
+static void transform_add_int(struct isp1760_qh *qh,
+			struct isp1760_qtd *qtd, struct ptd *ptd)
 {
-	u32 maxpacket;
-	u32 multi;
-	u32 numberofusofs;
-	u32 i;
-	u32 usofmask, usof;
+	u32 usof;
 	u32 period;
 
-	maxpacket = usb_maxpacket(urb->dev, urb->pipe, usb_pipeout(urb->pipe));
-	multi =  1 + ((maxpacket >> 11) & 0x3);
-	maxpacket &= 0x7ff;
-	/* length of the data per uframe */
-	maxpacket = multi * maxpacket;
-
-	numberofusofs = urb->transfer_buffer_length / maxpacket;
-	if (urb->transfer_buffer_length % maxpacket)
-		numberofusofs += 1;
-
-	usofmask = 1;
-	usof = 0;
-	for (i = 0; i < numberofusofs; i++) {
-		usof |= usofmask;
-		usofmask <<= 1;
-	}
-
-	if (urb->dev->speed != USB_SPEED_HIGH) {
-		/* split */
-		ptd->dw5 = cpu_to_le32(0x1c);
+	/*
+	 * Most of this is guessing. ISP1761 datasheet is quite unclear, and
+	 * the algorithm from the original Philips driver code, which was
+	 * pretty much used in this driver before as well, is quite horrendous
+	 * and, i believe, incorrect. The code below follows the datasheet and
+	 * USB2.0 spec as far as I can tell, and plug/unplug seems to be much
+	 * more reliable this way (fingers crossed...).
+	 */
 
-		if (qh->period >= 32)
-			period = qh->period / 2;
+	if (qtd->urb->dev->speed == USB_SPEED_HIGH) {
+		/* urb->interval is in units of microframes (1/8 ms) */
+		period = qtd->urb->interval >> 3;
+
+		if (qtd->urb->interval > 4)
+			usof = 0x01; /* One bit set =>
+						interval 1 ms * uFrame-match */
+		else if (qtd->urb->interval > 2)
+			usof = 0x22; /* Two bits set => interval 1/2 ms */
+		else if (qtd->urb->interval > 1)
+			usof = 0x55; /* Four bits set => interval 1/4 ms */
 		else
-			period = qh->period;
-
+			usof = 0xff; /* All bits set => interval 1/8 ms */
 	} else {
+		/* urb->interval is in units of frames (1 ms) */
+		period = qtd->urb->interval;
+		usof = 0x0f;		/* Execute Start Split on any of the
+					   four first uFrames */
 
-		if (qh->period >= 8)
-			period = qh->period/8;
-		else
-			period = qh->period;
-
-		if (period >= 32)
-			period  = 16;
-
-		if (qh->period >= 8) {
-			/* millisecond period */
-			period = (period << 3);
-		} else {
-			/* usof based tranmsfers */
-			/* minimum 4 usofs */
-			usof = 0x11;
-		}
+		/*
+		 * First 8 bits in dw5 is uSCS and "specifies which uSOF the
+		 * complete split needs to be sent. Valid only for IN." Also,
+		 * "All bits can be set to one for every transfer." (p 82,
+		 * ISP1761 data sheet.) 0x1c is from Philips driver. Where did
+		 * that number come from? 0xff seems to work fine...
+		 */
+		/* ptd->dw5 = 0x1c; */
+		ptd->dw5 = 0xff; /* Execute Complete Split on any uFrame */
 	}
 
-	ptd->dw2 |= cpu_to_le32(period);
-	ptd->dw4 = cpu_to_le32(usof);
+	period = period >> 1;/* Ensure equal or shorter period than requested */
+	period &= 0xf8; /* Mask off too large values and lowest unused 3 bits */
+
+	ptd->dw2 |= period;
+	ptd->dw4 = usof;
 }
 
-static void transform_into_int(struct isp1760_hcd *priv, struct isp1760_qh *qh,
-			struct isp1760_qtd *qtd, struct urb *urb,
-			u32 payload, struct ptd *ptd)
+static void transform_into_int(struct isp1760_qh *qh,
+			struct isp1760_qtd *qtd, struct ptd *ptd)
 {
-	transform_into_atl(priv, qh, qtd, urb, payload, ptd);
-	transform_add_int(priv, qh, qtd, urb,  payload, ptd);
+	transform_into_atl(qh, qtd, ptd);
+	transform_add_int(qh, qtd, ptd);
 }
 
 static int qtd_fill(struct isp1760_qtd *qtd, void *databuffer, size_t len,
@@ -695,10 +745,9 @@ static int qtd_fill(struct isp1760_qtd *qtd, void *databuffer, size_t len,
 
 	qtd->data_buffer = databuffer;
 	qtd->packet_type = GET_QTD_TOKEN_TYPE(token);
-	qtd->toggle = GET_DATA_TOGGLE(token);
 
-	if (len > HC_ATL_PL_SIZE)
-		count = HC_ATL_PL_SIZE;
+	if (len > MAX_PAYLOAD_SIZE)
+		count = MAX_PAYLOAD_SIZE;
 	else
 		count = len;
 
@@ -706,29 +755,27 @@ static int qtd_fill(struct isp1760_qtd *qtd, void *databuffer, size_t len,
 	return count;
 }
 
-static int check_error(struct ptd *ptd)
+static int check_error(struct usb_hcd *hcd, struct ptd *ptd)
 {
 	int error = 0;
-	u32 dw3;
 
-	dw3 = le32_to_cpu(ptd->dw3);
-	if (dw3 & DW3_HALT_BIT) {
+	if (ptd->dw3 & DW3_HALT_BIT) {
 		error = -EPIPE;
 
-		if (dw3 & DW3_ERROR_BIT)
+		if (ptd->dw3 & DW3_ERROR_BIT)
 			pr_err("error bit is set in DW3\n");
 	}
 
-	if (dw3 & DW3_QTD_ACTIVE) {
-		printk(KERN_ERR "transfer active bit is set DW3\n");
-		printk(KERN_ERR "nak counter: %d, rl: %d\n", (dw3 >> 19) & 0xf,
-				(le32_to_cpu(ptd->dw2) >> 25) & 0xf);
+	if (ptd->dw3 & DW3_QTD_ACTIVE) {
+		dev_err(hcd->self.controller, "Transfer active bit is set DW3\n"
+			"nak counter: %d, rl: %d\n",
+			(ptd->dw3 >> 19) & 0xf, (ptd->dw2 >> 25) & 0xf);
 	}
 
 	return error;
 }
 
-static void check_int_err_status(u32 dw4)
+static void check_int_err_status(struct usb_hcd *hcd, u32 dw4)
 {
 	u32 i;
 
@@ -737,79 +784,67 @@ static void check_int_err_status(u32 dw4)
 	for (i = 0; i < 8; i++) {
 		switch (dw4 & 0x7) {
 		case INT_UNDERRUN:
-			printk(KERN_ERR "ERROR: under run , %d\n", i);
+			dev_err(hcd->self.controller, "Underrun (%d)\n", i);
 			break;
 
 		case INT_EXACT:
-			printk(KERN_ERR "ERROR: transaction error, %d\n", i);
+			dev_err(hcd->self.controller,
+						"Transaction error (%d)\n", i);
 			break;
 
 		case INT_BABBLE:
-			printk(KERN_ERR "ERROR: babble error, %d\n", i);
+			dev_err(hcd->self.controller, "Babble error (%d)\n", i);
 			break;
 		}
 		dw4 >>= 3;
 	}
 }
 
-static void enqueue_one_qtd(struct isp1760_qtd *qtd, struct isp1760_hcd *priv,
-		u32 payload)
+static void enqueue_one_qtd(struct usb_hcd *hcd, struct isp1760_qtd *qtd)
 {
-	u32 token;
-	struct usb_hcd *hcd = priv_to_hcd(priv);
-
-	token = qtd->packet_type;
-
-	if (qtd->length && (qtd->length <= HC_ATL_PL_SIZE)) {
-		switch (token) {
+	if (qtd->length && (qtd->length <= MAX_PAYLOAD_SIZE)) {
+		switch (qtd->packet_type) {
 		case IN_PID:
 			break;
 		case OUT_PID:
 		case SETUP_PID:
-			priv_write_copy(priv, qtd->data_buffer,
-					hcd->regs + payload,
-					qtd->length);
+			mem_writes8(hcd->regs, qtd->payload_addr,
+						qtd->data_buffer, qtd->length);
 		}
 	}
 }
 
-static void enqueue_one_atl_qtd(u32 atl_regs, u32 payload,
-		struct isp1760_hcd *priv, struct isp1760_qh *qh,
-		struct urb *urb, u32 slot, struct isp1760_qtd *qtd)
+static void enqueue_one_atl_qtd(struct usb_hcd *hcd, struct isp1760_qh *qh,
+					u32 slot, struct isp1760_qtd *qtd)
 {
+	struct isp1760_hcd *priv = hcd_to_priv(hcd);
 	struct ptd ptd;
-	struct usb_hcd *hcd = priv_to_hcd(priv);
 
-	transform_into_atl(priv, qh, qtd, urb, payload, &ptd);
-	priv_write_copy(priv, (u32 *)&ptd, hcd->regs + atl_regs, sizeof(ptd));
-	enqueue_one_qtd(qtd, priv, payload);
+	alloc_mem(hcd, qtd);
+	transform_into_atl(qh, qtd, &ptd);
+	ptd_write(hcd->regs, ATL_PTD_OFFSET, slot, &ptd);
+	enqueue_one_qtd(hcd, qtd);
 
-	priv->atl_ints[slot].urb = urb;
 	priv->atl_ints[slot].qh = qh;
 	priv->atl_ints[slot].qtd = qtd;
-	priv->atl_ints[slot].data_buffer = qtd->data_buffer;
-	priv->atl_ints[slot].payload = payload;
-	qtd->status |= URB_ENQUEUED | URB_TYPE_ATL;
+	qtd->status |= URB_ENQUEUED;
 	qtd->status |= slot << 16;
 }
 
-static void enqueue_one_int_qtd(u32 int_regs, u32 payload,
-		struct isp1760_hcd *priv, struct isp1760_qh *qh,
-		struct urb *urb, u32 slot,  struct isp1760_qtd *qtd)
+static void enqueue_one_int_qtd(struct usb_hcd *hcd, struct isp1760_qh *qh,
+					u32 slot, struct isp1760_qtd *qtd)
 {
+	struct isp1760_hcd *priv = hcd_to_priv(hcd);
 	struct ptd ptd;
-	struct usb_hcd *hcd = priv_to_hcd(priv);
 
-	transform_into_int(priv, qh, qtd, urb, payload, &ptd);
-	priv_write_copy(priv, (u32 *)&ptd, hcd->regs + int_regs, sizeof(ptd));
-	enqueue_one_qtd(qtd, priv, payload);
+	alloc_mem(hcd, qtd);
+	transform_into_int(qh, qtd, &ptd);
+	ptd_write(hcd->regs, INT_PTD_OFFSET, slot, &ptd);
+	enqueue_one_qtd(hcd, qtd);
 
-	priv->int_ints[slot].urb = urb;
 	priv->int_ints[slot].qh = qh;
 	priv->int_ints[slot].qtd = qtd;
-	priv->int_ints[slot].data_buffer = qtd->data_buffer;
-	priv->int_ints[slot].payload = payload;
-	qtd->status |= URB_ENQUEUED | URB_TYPE_INT;
+	qtd->status |= URB_ENQUEUED;
 	qtd->status |= slot << 16;
 }
 
@@ -818,9 +853,7 @@ static void enqueue_an_ATL_packet(struct usb_hcd *hcd, struct isp1760_qh *qh,
 {
 	struct isp1760_hcd *priv = hcd_to_priv(hcd);
 	u32 skip_map, or_map;
-	u32 queue_entry;
 	u32 slot;
-	u32 atl_regs, payload;
 	u32 buffstatus;
 
 	/*
@@ -831,38 +864,35 @@ static void enqueue_an_ATL_packet(struct usb_hcd *hcd, struct isp1760_qh *qh,
 	 */
 	mmiowb();
 	ndelay(195);
-	skip_map = isp1760_readl(hcd->regs + HC_ATL_PTD_SKIPMAP_REG);
+	skip_map = reg_read32(hcd->regs, HC_ATL_PTD_SKIPMAP_REG);
 
 	BUG_ON(!skip_map);
 	slot = __ffs(skip_map);
-	queue_entry = 1 << slot;
-
-	atl_regs = ATL_REGS_OFFSET + slot * sizeof(struct ptd);
 
-	payload = alloc_mem(priv, qtd->length);
+	enqueue_one_atl_qtd(hcd, qh, slot, qtd);
 
-	enqueue_one_atl_qtd(atl_regs, payload, priv, qh, qtd->urb, slot, qtd);
+	or_map = reg_read32(hcd->regs, HC_ATL_IRQ_MASK_OR_REG);
+	or_map |= (1 << slot);
+	reg_write32(hcd->regs, HC_ATL_IRQ_MASK_OR_REG, or_map);
 
-	or_map = isp1760_readl(hcd->regs + HC_ATL_IRQ_MASK_OR_REG);
-	or_map |= queue_entry;
-	isp1760_writel(or_map, hcd->regs + HC_ATL_IRQ_MASK_OR_REG);
+	skip_map &= ~(1 << slot);
+	reg_write32(hcd->regs, HC_ATL_PTD_SKIPMAP_REG, skip_map);
 
-	skip_map &= ~queue_entry;
-	isp1760_writel(skip_map, hcd->regs + HC_ATL_PTD_SKIPMAP_REG);
+	priv->atl_queued++;
+	if (priv->atl_queued == 2)
+		reg_write32(hcd->regs, HC_INTERRUPT_ENABLE,
+				INTERRUPT_ENABLE_SOT_MASK);
 
-	buffstatus = isp1760_readl(hcd->regs + HC_BUFFER_STATUS_REG);
+	buffstatus = reg_read32(hcd->regs, HC_BUFFER_STATUS_REG);
 	buffstatus |= ATL_BUFFER;
-	isp1760_writel(buffstatus, hcd->regs + HC_BUFFER_STATUS_REG);
+	reg_write32(hcd->regs, HC_BUFFER_STATUS_REG, buffstatus);
 }
 
 static void enqueue_an_INT_packet(struct usb_hcd *hcd, struct isp1760_qh *qh,
 				  struct isp1760_qtd *qtd)
 {
-	struct isp1760_hcd *priv = hcd_to_priv(hcd);
 	u32 skip_map, or_map;
-	u32 queue_entry;
 	u32 slot;
-	u32 int_regs, payload;
 	u32 buffstatus;
 
 	/*
@@ -873,37 +903,34 @@ static void enqueue_an_INT_packet(struct usb_hcd *hcd, struct isp1760_qh *qh,
 	 */
 	mmiowb();
 	ndelay(195);
-	skip_map = isp1760_readl(hcd->regs + HC_INT_PTD_SKIPMAP_REG);
+	skip_map = reg_read32(hcd->regs, HC_INT_PTD_SKIPMAP_REG);
 
 	BUG_ON(!skip_map);
 	slot = __ffs(skip_map);
-	queue_entry = 1 << slot;
-
-	int_regs = INT_REGS_OFFSET + slot * sizeof(struct ptd);
 
-	payload = alloc_mem(priv, qtd->length);
+	enqueue_one_int_qtd(hcd, qh, slot, qtd);
 
-	enqueue_one_int_qtd(int_regs, payload, priv, qh, qtd->urb, slot, qtd);
+	or_map = reg_read32(hcd->regs, HC_INT_IRQ_MASK_OR_REG);
+	or_map |= (1 << slot);
+	reg_write32(hcd->regs, HC_INT_IRQ_MASK_OR_REG, or_map);
 
-	or_map = isp1760_readl(hcd->regs + HC_INT_IRQ_MASK_OR_REG);
-	or_map |= queue_entry;
-	isp1760_writel(or_map, hcd->regs + HC_INT_IRQ_MASK_OR_REG);
+	skip_map &= ~(1 << slot);
+	reg_write32(hcd->regs, HC_INT_PTD_SKIPMAP_REG, skip_map);
 
-	skip_map &= ~queue_entry;
-	isp1760_writel(skip_map, hcd->regs + HC_INT_PTD_SKIPMAP_REG);
-
-	buffstatus = isp1760_readl(hcd->regs + HC_BUFFER_STATUS_REG);
+	buffstatus = reg_read32(hcd->regs, HC_BUFFER_STATUS_REG);
 	buffstatus |= INT_BUFFER;
-	isp1760_writel(buffstatus, hcd->regs + HC_BUFFER_STATUS_REG);
+	reg_write32(hcd->regs, HC_BUFFER_STATUS_REG, buffstatus);
 }
 
-static void isp1760_urb_done(struct isp1760_hcd *priv, struct urb *urb, int status)
+static void isp1760_urb_done(struct usb_hcd *hcd, struct urb *urb)
 __releases(priv->lock)
 __acquires(priv->lock)
 {
+	struct isp1760_hcd *priv = hcd_to_priv(hcd);
+
 	if (!urb->unlinked) {
-		if (status == -EINPROGRESS)
-			status = 0;
+		if (urb->status == -EINPROGRESS)
+			urb->status = 0;
 	}
 
 	if (usb_pipein(urb->pipe) && usb_pipetype(urb->pipe) != PIPE_CONTROL) {
@@ -915,22 +942,28 @@ __acquires(priv->lock)
 	}
 
 	/* complete() can reenter this HCD */
-	usb_hcd_unlink_urb_from_ep(priv_to_hcd(priv), urb);
+	usb_hcd_unlink_urb_from_ep(hcd, urb);
 	spin_unlock(&priv->lock);
-	usb_hcd_giveback_urb(priv_to_hcd(priv), urb, status);
+	usb_hcd_giveback_urb(hcd, urb, urb->status);
 	spin_lock(&priv->lock);
 }
 
 static void isp1760_qtd_free(struct isp1760_qtd *qtd)
 {
+	BUG_ON(qtd->payload_addr);
 	kmem_cache_free(qtd_cachep, qtd);
 }
 
-static struct isp1760_qtd *clean_this_qtd(struct isp1760_qtd *qtd)
+static struct isp1760_qtd *clean_this_qtd(struct isp1760_qtd *qtd,
+							struct isp1760_qh *qh)
 {
 	struct isp1760_qtd *tmp_qtd;
 
-	tmp_qtd = qtd->hw_next;
+	if (list_is_last(&qtd->qtd_list, &qh->qtd_list))
+		tmp_qtd = NULL;
+	else
+		tmp_qtd = list_entry(qtd->qtd_list.next, struct isp1760_qtd,
+								qtd_list);
 	list_del(&qtd->qtd_list);
 	isp1760_qtd_free(qtd);
 	return tmp_qtd;
@@ -941,32 +974,26 @@ static struct isp1760_qtd *clean_this_qtd(struct isp1760_qtd *qtd)
  * isn't the last one than remove also his successor(s).
  * Returns the QTD which is part of an new URB and should be enqueued.
  */
-static struct isp1760_qtd *clean_up_qtdlist(struct isp1760_qtd *qtd)
+static struct isp1760_qtd *clean_up_qtdlist(struct isp1760_qtd *qtd,
+							struct isp1760_qh *qh)
 {
-	struct isp1760_qtd *tmp_qtd;
-	int last_one;
+	struct urb *urb;
 
+	urb = qtd->urb;
 	do {
-		tmp_qtd = qtd->hw_next;
-		last_one = qtd->status & URB_COMPLETE_NOTIFY;
-		list_del(&qtd->qtd_list);
-		isp1760_qtd_free(qtd);
-		qtd = tmp_qtd;
-	} while (!last_one && qtd);
+		qtd = clean_this_qtd(qtd, qh);
+	} while (qtd && (qtd->urb == urb));
 
 	return qtd;
 }
 
-static void do_atl_int(struct usb_hcd *usb_hcd)
+static void do_atl_int(struct usb_hcd *hcd)
 {
-	struct isp1760_hcd *priv = hcd_to_priv(usb_hcd);
+	struct isp1760_hcd *priv = hcd_to_priv(hcd);
 	u32 done_map, skip_map;
 	struct ptd ptd;
-	struct urb *urb = NULL;
-	u32 atl_regs_base;
-	u32 atl_regs;
-	u32 queue_entry;
-	u32 payload;
+	struct urb *urb;
+	u32 slot;
 	u32 length;
 	u32 or_map;
 	u32 status = -EINVAL;
@@ -976,62 +1003,36 @@ static void do_atl_int(struct usb_hcd *usb_hcd)
 	u32 rl;
 	u32 nakcount;
 
-	done_map = isp1760_readl(usb_hcd->regs +
-			HC_ATL_PTD_DONEMAP_REG);
-	skip_map = isp1760_readl(usb_hcd->regs +
-			HC_ATL_PTD_SKIPMAP_REG);
+	done_map = reg_read32(hcd->regs, HC_ATL_PTD_DONEMAP_REG);
+	skip_map = reg_read32(hcd->regs, HC_ATL_PTD_SKIPMAP_REG);
 
-	or_map = isp1760_readl(usb_hcd->regs + HC_ATL_IRQ_MASK_OR_REG);
+	or_map = reg_read32(hcd->regs, HC_ATL_IRQ_MASK_OR_REG);
 	or_map &= ~done_map;
-	isp1760_writel(or_map, usb_hcd->regs + HC_ATL_IRQ_MASK_OR_REG);
+	reg_write32(hcd->regs, HC_ATL_IRQ_MASK_OR_REG, or_map);
 
-	atl_regs_base = ATL_REGS_OFFSET;
 	while (done_map) {
-		u32 dw1;
-		u32 dw2;
-		u32 dw3;
-
 		status = 0;
+		priv->atl_queued--;
 
-		queue_entry = __ffs(done_map);
-		done_map &= ~(1 << queue_entry);
-		skip_map |= 1 << queue_entry;
-
-		atl_regs = atl_regs_base + queue_entry * sizeof(struct ptd);
+		slot = __ffs(done_map);
+		done_map &= ~(1 << slot);
+		skip_map |= (1 << slot);
 
-		urb = priv->atl_ints[queue_entry].urb;
-		qtd = priv->atl_ints[queue_entry].qtd;
-		qh = priv->atl_ints[queue_entry].qh;
-		payload = priv->atl_ints[queue_entry].payload;
+		qtd = priv->atl_ints[slot].qtd;
+		qh = priv->atl_ints[slot].qh;
 
 		if (!qh) {
-			printk(KERN_ERR "qh is 0\n");
+			dev_err(hcd->self.controller, "qh is 0\n");
 			continue;
 		}
-		isp1760_writel(atl_regs + ISP_BANK(0), usb_hcd->regs +
-				HC_MEMORY_REG);
-		isp1760_writel(payload  + ISP_BANK(1), usb_hcd->regs +
-				HC_MEMORY_REG);
-		/*
-		 * write bank1 address twice to ensure the 90ns delay (time
-		 * between BANK0 write and the priv_read_copy() call is at
-		 * least 3*t_WHWL + 2*t_w11 = 3*25ns + 2*17ns = 109ns)
-		 */
-		isp1760_writel(payload  + ISP_BANK(1), usb_hcd->regs +
-				HC_MEMORY_REG);
+		ptd_read(hcd->regs, ATL_PTD_OFFSET, slot, &ptd);
 
-		priv_read_copy(priv, (u32 *)&ptd, usb_hcd->regs + atl_regs +
-				ISP_BANK(0), sizeof(ptd));
-
-		dw1 = le32_to_cpu(ptd.dw1);
-		dw2 = le32_to_cpu(ptd.dw2);
-		dw3 = le32_to_cpu(ptd.dw3);
-		rl = (dw2 >> 25) & 0x0f;
-		nakcount = (dw3 >> 19) & 0xf;
+		rl = (ptd.dw2 >> 25) & 0x0f;
+		nakcount = (ptd.dw3 >> 19) & 0xf;
 
 		/* Transfer Error, *but* active and no HALT -> reload */
-		if ((dw3 & DW3_ERROR_BIT) && (dw3 & DW3_QTD_ACTIVE) &&
-				!(dw3 & DW3_HALT_BIT)) {
+		if ((ptd.dw3 & DW3_ERROR_BIT) && (ptd.dw3 & DW3_QTD_ACTIVE) &&
+				!(ptd.dw3 & DW3_HALT_BIT)) {
 
 			/* according to ppriv code, we have to
 			 * reload this one if trasfered bytes != requested bytes
@@ -1040,13 +1041,14 @@ static void do_atl_int(struct usb_hcd *usb_hcd)
 			 * triggered so far.
 			 */
 
-			length = PTD_XFERRED_LENGTH(dw3);
-			printk(KERN_ERR "Should reload now.... transfered %d "
+			length = PTD_XFERRED_LENGTH(ptd.dw3);
+			dev_err(hcd->self.controller,
+					"Should reload now... transferred %d "
 					"of %zu\n", length, qtd->length);
 			BUG();
 		}
 
-		if (!nakcount && (dw3 & DW3_QTD_ACTIVE)) {
+		if (!nakcount && (ptd.dw3 & DW3_QTD_ACTIVE)) {
 			u32 buffstatus;
 
 			/*
@@ -1054,52 +1056,45 @@ static void do_atl_int(struct usb_hcd *usb_hcd)
 			 * device is not able to send data fast enough.
 			 * This happens mostly on slower hardware.
 			 */
-			printk(KERN_NOTICE "Reloading ptd %p/%p... qh %p read: "
-					"%d of %zu done: %08x cur: %08x\n", qtd,
-					urb, qh, PTD_XFERRED_LENGTH(dw3),
-					qtd->length, done_map,
-					(1 << queue_entry));
 
 			/* RL counter = ERR counter */
-			dw3 &= ~(0xf << 19);
-			dw3 |= rl << 19;
-			dw3 &= ~(3 << (55 - 32));
-			dw3 |= ERR_COUNTER << (55 - 32);
+			ptd.dw3 &= ~(0xf << 19);
+			ptd.dw3 |= rl << 19;
+			ptd.dw3 &= ~(3 << (55 - 32));
+			ptd.dw3 |= ERR_COUNTER << (55 - 32);
 
 			/*
 			 * It is not needed to write skip map back because it
 			 * is unchanged. Just make sure that this entry is
 			 * unskipped once it gets written to the HW.
 			 */
-			skip_map &= ~(1 << queue_entry);
-			or_map = isp1760_readl(usb_hcd->regs +
-					HC_ATL_IRQ_MASK_OR_REG);
-			or_map |= 1 << queue_entry;
-			isp1760_writel(or_map, usb_hcd->regs +
-					HC_ATL_IRQ_MASK_OR_REG);
-
-			ptd.dw3 = cpu_to_le32(dw3);
-			priv_write_copy(priv, (u32 *)&ptd, usb_hcd->regs +
-					atl_regs, sizeof(ptd));
-
-			ptd.dw0 |= cpu_to_le32(PTD_VALID);
-			priv_write_copy(priv, (u32 *)&ptd, usb_hcd->regs +
-					atl_regs, sizeof(ptd));
-
-			buffstatus = isp1760_readl(usb_hcd->regs +
-					HC_BUFFER_STATUS_REG);
+			skip_map &= ~(1 << slot);
+			or_map = reg_read32(hcd->regs, HC_ATL_IRQ_MASK_OR_REG);
+			or_map |= 1 << slot;
+			reg_write32(hcd->regs, HC_ATL_IRQ_MASK_OR_REG, or_map);
+
+			ptd.dw0 |= PTD_VALID;
+			ptd_write(hcd->regs, ATL_PTD_OFFSET, slot, &ptd);
+
+			priv->atl_queued++;
+			if (priv->atl_queued == 2)
+				reg_write32(hcd->regs, HC_INTERRUPT_ENABLE,
+						INTERRUPT_ENABLE_SOT_MASK);
+
+			buffstatus = reg_read32(hcd->regs,
+							HC_BUFFER_STATUS_REG);
 			buffstatus |= ATL_BUFFER;
-			isp1760_writel(buffstatus, usb_hcd->regs +
-					HC_BUFFER_STATUS_REG);
+			reg_write32(hcd->regs, HC_BUFFER_STATUS_REG,
+								buffstatus);
 			continue;
 		}
 
-		error = check_error(&ptd);
+		error = check_error(hcd, &ptd);
 		if (error) {
 			status = error;
-			priv->atl_ints[queue_entry].qh->toggle = 0;
-			priv->atl_ints[queue_entry].qh->ping = 0;
-			urb->status = -EPIPE;
+			priv->atl_ints[slot].qh->toggle = 0;
+			priv->atl_ints[slot].qh->ping = 0;
+			qtd->urb->status = -EPIPE;
 
 #if 0
 			printk(KERN_ERR "Error in %s().\n", __func__);
@@ -1110,154 +1105,123 @@ static void do_atl_int(struct usb_hcd *usb_hcd)
 					ptd.dw4, ptd.dw5, ptd.dw6, ptd.dw7);
 #endif
 		} else {
-			if (usb_pipetype(urb->pipe) == PIPE_BULK) {
-				priv->atl_ints[queue_entry].qh->toggle = dw3 &
-					(1 << 25);
-				priv->atl_ints[queue_entry].qh->ping = dw3 &
-					(1 << 26);
-			}
+			priv->atl_ints[slot].qh->toggle = ptd.dw3 & (1 << 25);
+			priv->atl_ints[slot].qh->ping = ptd.dw3 & (1 << 26);
 		}
 
-		length = PTD_XFERRED_LENGTH(dw3);
+		length = PTD_XFERRED_LENGTH(ptd.dw3);
 		if (length) {
-			switch (DW1_GET_PID(dw1)) {
+			switch (DW1_GET_PID(ptd.dw1)) {
 			case IN_PID:
-				priv_read_copy(priv,
-					priv->atl_ints[queue_entry].data_buffer,
-					usb_hcd->regs + payload + ISP_BANK(1),
-					length);
+				mem_reads8(hcd->regs, qtd->payload_addr,
+						qtd->data_buffer, length);
 
 			case OUT_PID:
 
-				urb->actual_length += length;
+				qtd->urb->actual_length += length;
 
 			case SETUP_PID:
 				break;
 			}
 		}
 
-		priv->atl_ints[queue_entry].data_buffer = NULL;
-		priv->atl_ints[queue_entry].urb = NULL;
-		priv->atl_ints[queue_entry].qtd = NULL;
-		priv->atl_ints[queue_entry].qh = NULL;
+		priv->atl_ints[slot].qtd = NULL;
+		priv->atl_ints[slot].qh = NULL;
 
-		free_mem(priv, payload);
+		free_mem(hcd, qtd);
 
-		isp1760_writel(skip_map, usb_hcd->regs +
-				HC_ATL_PTD_SKIPMAP_REG);
+		reg_write32(hcd->regs, HC_ATL_PTD_SKIPMAP_REG, skip_map);
 
-		if (urb->status == -EPIPE) {
+		if (qtd->urb->status == -EPIPE) {
 			/* HALT was received */
 
-			qtd = clean_up_qtdlist(qtd);
-			isp1760_urb_done(priv, urb, urb->status);
+			urb = qtd->urb;
+			qtd = clean_up_qtdlist(qtd, qh);
+			isp1760_urb_done(hcd, urb);
 
-		} else if (usb_pipebulk(urb->pipe) && (length < qtd->length)) {
+		} else if (usb_pipebulk(qtd->urb->pipe) &&
+						(length < qtd->length)) {
 			/* short BULK received */
 
-			if (urb->transfer_flags & URB_SHORT_NOT_OK) {
-				urb->status = -EREMOTEIO;
-				isp1760_dbg(priv, "short bulk, %d instead %zu "
-					"with URB_SHORT_NOT_OK flag.\n",
-					length, qtd->length);
+			if (qtd->urb->transfer_flags & URB_SHORT_NOT_OK) {
+				qtd->urb->status = -EREMOTEIO;
+				dev_dbg(hcd->self.controller,
+						"short bulk, %d instead %zu "
+						"with URB_SHORT_NOT_OK flag.\n",
+						length, qtd->length);
 			}
 
-			if (urb->status == -EINPROGRESS)
-				urb->status = 0;
-
-			qtd = clean_up_qtdlist(qtd);
+			if (qtd->urb->status == -EINPROGRESS)
+				qtd->urb->status = 0;
 
-			isp1760_urb_done(priv, urb, urb->status);
+			urb = qtd->urb;
+			qtd = clean_up_qtdlist(qtd, qh);
+			isp1760_urb_done(hcd, urb);
 
-		} else if (qtd->status & URB_COMPLETE_NOTIFY) {
+		} else if (last_qtd_of_urb(qtd, qh)) {
 			/* that was the last qtd of that URB */
 
-			if (urb->status == -EINPROGRESS)
-				urb->status = 0;
+			if (qtd->urb->status == -EINPROGRESS)
+				qtd->urb->status = 0;
 
-			qtd = clean_this_qtd(qtd);
-			isp1760_urb_done(priv, urb, urb->status);
+			urb = qtd->urb;
+			qtd = clean_up_qtdlist(qtd, qh);
+			isp1760_urb_done(hcd, urb);
 
 		} else {
 			/* next QTD of this URB */
 
-			qtd = clean_this_qtd(qtd);
+			qtd = clean_this_qtd(qtd, qh);
 			BUG_ON(!qtd);
 		}
 
 		if (qtd)
-			enqueue_an_ATL_packet(usb_hcd, qh, qtd);
+			enqueue_an_ATL_packet(hcd, qh, qtd);
 
-		skip_map = isp1760_readl(usb_hcd->regs +
-				HC_ATL_PTD_SKIPMAP_REG);
+		skip_map = reg_read32(hcd->regs, HC_ATL_PTD_SKIPMAP_REG);
 	}
+	if (priv->atl_queued <= 1)
+		reg_write32(hcd->regs, HC_INTERRUPT_ENABLE,
+							INTERRUPT_ENABLE_MASK);
 }
 
-static void do_intl_int(struct usb_hcd *usb_hcd)
+static void do_intl_int(struct usb_hcd *hcd)
 {
-	struct isp1760_hcd *priv = hcd_to_priv(usb_hcd);
+	struct isp1760_hcd *priv = hcd_to_priv(hcd);
 	u32 done_map, skip_map;
 	struct ptd ptd;
-	struct urb *urb = NULL;
-	u32 int_regs;
-	u32 int_regs_base;
-	u32 payload;
+	struct urb *urb;
 	u32 length;
 	u32 or_map;
 	int error;
-	u32 queue_entry;
+	u32 slot;
 	struct isp1760_qtd *qtd;
 	struct isp1760_qh *qh;
 
-	done_map = isp1760_readl(usb_hcd->regs +
-			HC_INT_PTD_DONEMAP_REG);
-	skip_map = isp1760_readl(usb_hcd->regs +
-			HC_INT_PTD_SKIPMAP_REG);
+	done_map = reg_read32(hcd->regs, HC_INT_PTD_DONEMAP_REG);
+	skip_map = reg_read32(hcd->regs, HC_INT_PTD_SKIPMAP_REG);
 
-	or_map = isp1760_readl(usb_hcd->regs + HC_INT_IRQ_MASK_OR_REG);
+	or_map = reg_read32(hcd->regs, HC_INT_IRQ_MASK_OR_REG);
 	or_map &= ~done_map;
-	isp1760_writel(or_map, usb_hcd->regs + HC_INT_IRQ_MASK_OR_REG);
-
-	int_regs_base = INT_REGS_OFFSET;
+	reg_write32(hcd->regs, HC_INT_IRQ_MASK_OR_REG, or_map);
 
 	while (done_map) {
-		u32 dw1;
-		u32 dw3;
+		slot = __ffs(done_map);
+		done_map &= ~(1 << slot);
+		skip_map |= (1 << slot);
 
-		queue_entry = __ffs(done_map);
-		done_map &= ~(1 << queue_entry);
-		skip_map |= 1 << queue_entry;
-
-		int_regs = int_regs_base + queue_entry * sizeof(struct ptd);
-		urb = priv->int_ints[queue_entry].urb;
-		qtd = priv->int_ints[queue_entry].qtd;
-		qh = priv->int_ints[queue_entry].qh;
-		payload = priv->int_ints[queue_entry].payload;
+		qtd = priv->int_ints[slot].qtd;
+		qh = priv->int_ints[slot].qh;
 
 		if (!qh) {
-			printk(KERN_ERR "(INT) qh is 0\n");
+			dev_err(hcd->self.controller, "(INT) qh is 0\n");
 			continue;
 		}
 
-		isp1760_writel(int_regs + ISP_BANK(0), usb_hcd->regs +
-				HC_MEMORY_REG);
-		isp1760_writel(payload  + ISP_BANK(1), usb_hcd->regs +
-				HC_MEMORY_REG);
-		/*
-		 * write bank1 address twice to ensure the 90ns delay (time
-		 * between BANK0 write and the priv_read_copy() call is at
-		 * least 3*t_WHWL + 2*t_w11 = 3*25ns + 2*17ns = 92ns)
-		 */
-		isp1760_writel(payload  + ISP_BANK(1), usb_hcd->regs +
-				HC_MEMORY_REG);
+		ptd_read(hcd->regs, INT_PTD_OFFSET, slot, &ptd);
+		check_int_err_status(hcd, ptd.dw4);
 
-		priv_read_copy(priv, (u32 *)&ptd, usb_hcd->regs + int_regs +
-				ISP_BANK(0), sizeof(ptd));
-		dw1 = le32_to_cpu(ptd.dw1);
-		dw3 = le32_to_cpu(ptd.dw3);
-		check_int_err_status(le32_to_cpu(ptd.dw4));
-
-		error = check_error(&ptd);
+		error = check_error(hcd, &ptd);
 		if (error) {
 #if 0
 			printk(KERN_ERR "Error in %s().\n", __func__);
@@ -1267,83 +1231,77 @@ static void do_intl_int(struct usb_hcd *usb_hcd)
 					ptd.dw0, ptd.dw1, ptd.dw2, ptd.dw3,
 					ptd.dw4, ptd.dw5, ptd.dw6, ptd.dw7);
 #endif
-			urb->status = -EPIPE;
-			priv->int_ints[queue_entry].qh->toggle = 0;
-			priv->int_ints[queue_entry].qh->ping = 0;
+			qtd->urb->status = -EPIPE;
+			priv->int_ints[slot].qh->toggle = 0;
+			priv->int_ints[slot].qh->ping = 0;
 
 		} else {
-			priv->int_ints[queue_entry].qh->toggle =
-				dw3 & (1 << 25);
-			priv->int_ints[queue_entry].qh->ping = dw3 & (1 << 26);
+			priv->int_ints[slot].qh->toggle = ptd.dw3 & (1 << 25);
+			priv->int_ints[slot].qh->ping = ptd.dw3 & (1 << 26);
 		}
 
-		if (urb->dev->speed != USB_SPEED_HIGH)
-			length = PTD_XFERRED_LENGTH_LO(dw3);
+		if (qtd->urb->dev->speed != USB_SPEED_HIGH)
+			length = PTD_XFERRED_LENGTH_LO(ptd.dw3);
 		else
-			length = PTD_XFERRED_LENGTH(dw3);
+			length = PTD_XFERRED_LENGTH(ptd.dw3);
 
 		if (length) {
-			switch (DW1_GET_PID(dw1)) {
+			switch (DW1_GET_PID(ptd.dw1)) {
 			case IN_PID:
-				priv_read_copy(priv,
-					priv->int_ints[queue_entry].data_buffer,
-					usb_hcd->regs + payload + ISP_BANK(1),
-					length);
+				mem_reads8(hcd->regs, qtd->payload_addr,
+						qtd->data_buffer, length);
 			case OUT_PID:
 
-				urb->actual_length += length;
+				qtd->urb->actual_length += length;
 
 			case SETUP_PID:
 				break;
 			}
 		}
 
-		priv->int_ints[queue_entry].data_buffer = NULL;
-		priv->int_ints[queue_entry].urb = NULL;
-		priv->int_ints[queue_entry].qtd = NULL;
-		priv->int_ints[queue_entry].qh = NULL;
+		priv->int_ints[slot].qtd = NULL;
+		priv->int_ints[slot].qh = NULL;
 
-		isp1760_writel(skip_map, usb_hcd->regs +
-				HC_INT_PTD_SKIPMAP_REG);
-		free_mem(priv, payload);
+		reg_write32(hcd->regs, HC_INT_PTD_SKIPMAP_REG, skip_map);
+		free_mem(hcd, qtd);
 
-		if (urb->status == -EPIPE) {
+		if (qtd->urb->status == -EPIPE) {
 			/* HALT received */
 
-			 qtd = clean_up_qtdlist(qtd);
-			 isp1760_urb_done(priv, urb, urb->status);
+			urb = qtd->urb;
+			qtd = clean_up_qtdlist(qtd, qh);
+			isp1760_urb_done(hcd, urb);
 
-		} else if (qtd->status & URB_COMPLETE_NOTIFY) {
+		} else if (last_qtd_of_urb(qtd, qh)) {
 
-			if (urb->status == -EINPROGRESS)
-				urb->status = 0;
+			if (qtd->urb->status == -EINPROGRESS)
+				qtd->urb->status = 0;
 
-			qtd = clean_this_qtd(qtd);
-			isp1760_urb_done(priv, urb, urb->status);
+			urb = qtd->urb;
+			qtd = clean_up_qtdlist(qtd, qh);
+			isp1760_urb_done(hcd, urb);
 
 		} else {
 			/* next QTD of this URB */
 
-			qtd = clean_this_qtd(qtd);
+			qtd = clean_this_qtd(qtd, qh);
 			BUG_ON(!qtd);
 		}
 
 		if (qtd)
-			enqueue_an_INT_packet(usb_hcd, qh, qtd);
+			enqueue_an_INT_packet(hcd, qh, qtd);
 
-		skip_map = isp1760_readl(usb_hcd->regs +
-				HC_INT_PTD_SKIPMAP_REG);
+		skip_map = reg_read32(hcd->regs, HC_INT_PTD_SKIPMAP_REG);
 	}
 }
 
-#define max_packet(wMaxPacketSize) ((wMaxPacketSize) & 0x07ff)
-static struct isp1760_qh *qh_make(struct isp1760_hcd *priv, struct urb *urb,
+static struct isp1760_qh *qh_make(struct usb_hcd *hcd, struct urb *urb,
 		gfp_t flags)
 {
 	struct isp1760_qh *qh;
 	int is_input, type;
 
-	qh = isp1760_qh_alloc(priv, flags);
+	qh = isp1760_qh_alloc(flags);
 	if (!qh)
 		return qh;
 
@@ -1353,29 +1311,6 @@ static struct isp1760_qh *qh_make(struct isp1760_hcd *priv, struct urb *urb,
 	is_input = usb_pipein(urb->pipe);
 	type = usb_pipetype(urb->pipe);
 
-	if (type == PIPE_INTERRUPT) {
-
-		if (urb->dev->speed == USB_SPEED_HIGH) {
-
-			qh->period = urb->interval >> 3;
-			if (qh->period == 0 && urb->interval != 1) {
-				/* NOTE interval 2 or 4 uframes could work.
-				 * But interval 1 scheduling is simpler, and
-				 * includes high bandwidth.
-				 */
-				printk(KERN_ERR "intr period %d uframes, NYET!",
-						urb->interval);
-				qh_destroy(qh);
-				return NULL;
-			}
-		} else {
-			qh->period = urb->interval;
-		}
-	}
-
-	/* support for tt scheduling, and access to toggles */
-	qh->dev = urb->dev;
-
 	if (!usb_pipecontrol(urb->pipe))
 		usb_settoggle(urb->dev, usb_pipeendpoint(urb->pipe), !is_input,
 				1);
@@ -1388,43 +1323,27 @@ static struct isp1760_qh *qh_make(struct isp1760_hcd *priv, struct urb *urb,
  * Returns null if it can't allocate a QH it needs to.
  * If the QH has TDs (urbs) already, that's great.
  */
-static struct isp1760_qh *qh_append_tds(struct isp1760_hcd *priv,
+static struct isp1760_qh *qh_append_tds(struct usb_hcd *hcd,
 		struct urb *urb, struct list_head *qtd_list, int epnum,
 		void **ptr)
 {
 	struct isp1760_qh *qh;
-	struct isp1760_qtd *qtd;
-	struct isp1760_qtd *prev_qtd;
 
 	qh = (struct isp1760_qh *)*ptr;
 	if (!qh) {
 		/* can't sleep here, we have priv->lock... */
-		qh = qh_make(priv, urb, GFP_ATOMIC);
+		qh = qh_make(hcd, urb, GFP_ATOMIC);
 		if (!qh)
 			return qh;
 		*ptr = qh;
 	}
 
-	qtd = list_entry(qtd_list->next, struct isp1760_qtd,
-			qtd_list);
-	if (!list_empty(&qh->qtd_list))
-		prev_qtd = list_entry(qh->qtd_list.prev,
-				struct isp1760_qtd, qtd_list);
-	else
-		prev_qtd = NULL;
-
 	list_splice(qtd_list, qh->qtd_list.prev);
-	if (prev_qtd) {
-		BUG_ON(prev_qtd->hw_next);
-		prev_qtd->hw_next = qtd;
-	}
 
-	urb->hcpriv = qh;
 	return qh;
 }
 
-static void qtd_list_free(struct isp1760_hcd *priv, struct urb *urb,
-		struct list_head *qtd_list)
+static void qtd_list_free(struct urb *urb, struct list_head *qtd_list)
 {
 	struct list_head *entry, *temp;
 
@@ -1437,9 +1356,10 @@ static void qtd_list_free(struct isp1760_hcd *priv, struct urb *urb,
 	}
 }
 
-static int isp1760_prepare_enqueue(struct isp1760_hcd *priv, struct urb *urb,
+static int isp1760_prepare_enqueue(struct usb_hcd *hcd, struct urb *urb,
 		struct list_head *qtd_list, gfp_t mem_flags, packet_enqueue *p)
 {
+	struct isp1760_hcd *priv = hcd_to_priv(hcd);
 	struct isp1760_qtd         *qtd;
 	int                     epnum;
 	unsigned long           flags;
@@ -1451,11 +1371,11 @@ static int isp1760_prepare_enqueue(struct isp1760_hcd *priv, struct urb *urb,
 	epnum = urb->ep->desc.bEndpointAddress;
 
 	spin_lock_irqsave(&priv->lock, flags);
-	if (!HCD_HW_ACCESSIBLE(priv_to_hcd(priv))) {
+	if (!HCD_HW_ACCESSIBLE(hcd)) {
 		rc = -ESHUTDOWN;
 		goto done;
 	}
-	rc = usb_hcd_link_urb_to_ep(priv_to_hcd(priv), urb);
+	rc = usb_hcd_link_urb_to_ep(hcd, urb);
 	if (rc)
 		goto done;
 
@@ -1465,25 +1385,24 @@ static int isp1760_prepare_enqueue(struct isp1760_hcd *priv, struct urb *urb,
 	else
 		qh_busy = 0;
 
-	qh = qh_append_tds(priv, urb, qtd_list, epnum, &urb->ep->hcpriv);
+	qh = qh_append_tds(hcd, urb, qtd_list, epnum, &urb->ep->hcpriv);
 	if (!qh) {
-		usb_hcd_unlink_urb_from_ep(priv_to_hcd(priv), urb);
+		usb_hcd_unlink_urb_from_ep(hcd, urb);
 		rc = -ENOMEM;
 		goto done;
 	}
 
 	if (!qh_busy)
-		p(priv_to_hcd(priv), qh, qtd);
+		p(hcd, qh, qtd);
 
 done:
 	spin_unlock_irqrestore(&priv->lock, flags);
 	if (!qh)
-		qtd_list_free(priv, urb, qtd_list);
+		qtd_list_free(urb, qtd_list);
 	return rc;
 }
 
-static struct isp1760_qtd *isp1760_qtd_alloc(struct isp1760_hcd *priv,
-		gfp_t flags)
+static struct isp1760_qtd *isp1760_qtd_alloc(gfp_t flags)
 {
 	struct isp1760_qtd *qtd;
 
@@ -1497,10 +1416,11 @@ static struct isp1760_qtd *isp1760_qtd_alloc(struct isp1760_hcd *priv,
 /*
  * create a list of filled qtds for this URB; won't link into qh.
  */
-static struct list_head *qh_urb_transaction(struct isp1760_hcd *priv,
+#define max_packet(wMaxPacketSize) ((wMaxPacketSize) & 0x07ff)
+static struct list_head *qh_urb_transaction(struct usb_hcd *hcd,
 		struct urb *urb, struct list_head *head, gfp_t flags)
 {
-	struct isp1760_qtd *qtd, *qtd_prev;
+	struct isp1760_qtd *qtd;
 	void *buf;
 	int len, maxpacket;
 	int is_input;
@@ -1509,7 +1429,7 @@ static struct list_head *qh_urb_transaction(struct isp1760_hcd *priv,
 	/*
 	 * URBs map to sequences of QTDs:  one logical transaction
 	 */
-	qtd = isp1760_qtd_alloc(priv, flags);
+	qtd = isp1760_qtd_alloc(flags);
 	if (!qtd)
 		return NULL;
 
@@ -1529,13 +1449,10 @@ static struct list_head *qh_urb_transaction(struct isp1760_hcd *priv,
 				token | SETUP_PID);
 
 		/* ... and always at least one more pid */
-		token ^= DATA_TOGGLE;
-		qtd_prev = qtd;
-		qtd = isp1760_qtd_alloc(priv, flags);
+		qtd = isp1760_qtd_alloc(flags);
 		if (!qtd)
 			goto cleanup;
 		qtd->urb = urb;
-		qtd_prev->hw_next = qtd;
 		list_add_tail(&qtd->qtd_list, head);
 
 		/* for zero length DATA stages, STATUS is always IN */
@@ -1565,7 +1482,7 @@ static struct list_head *qh_urb_transaction(struct isp1760_hcd *priv,
 
 		if (!buf && len) {
 			/* XXX This looks like usb storage / SCSI bug */
-			printk(KERN_ERR "buf is null, dma is %08lx len is %d\n",
+			dev_err(hcd->self.controller, "buf is null, dma is %08lx len is %d\n",
 					(long unsigned)urb->transfer_dma, len);
 			WARN_ON(1);
 		}
@@ -1574,19 +1491,13 @@ static struct list_head *qh_urb_transaction(struct isp1760_hcd *priv,
 		len -= this_qtd_len;
 		buf += this_qtd_len;
 
-		/* qh makes control packets use qtd toggle; maybe switch it */
-		if ((maxpacket & (this_qtd_len + (maxpacket - 1))) == 0)
-			token ^= DATA_TOGGLE;
-
 		if (len <= 0)
 			break;
 
-		qtd_prev = qtd;
-		qtd = isp1760_qtd_alloc(priv, flags);
+		qtd = isp1760_qtd_alloc(flags);
 		if (!qtd)
 			goto cleanup;
 		qtd->urb = urb;
-		qtd_prev->hw_next = qtd;
 		list_add_tail(&qtd->qtd_list, head);
 	}
 
@@ -1601,20 +1512,16 @@ static struct list_head *qh_urb_transaction(struct isp1760_hcd *priv,
 			one_more = 1;
 			/* "in" <--> "out"  */
 			token ^= IN_PID;
-			/* force DATA1 */
-			token |= DATA_TOGGLE;
 		} else if (usb_pipebulk(urb->pipe)
 				&& (urb->transfer_flags & URB_ZERO_PACKET)
 				&& !(urb->transfer_buffer_length % maxpacket)) {
 			one_more = 1;
 		}
 		if (one_more) {
-			qtd_prev = qtd;
-			qtd = isp1760_qtd_alloc(priv, flags);
+			qtd = isp1760_qtd_alloc(flags);
 			if (!qtd)
 				goto cleanup;
 			qtd->urb = urb;
-			qtd_prev->hw_next = qtd;
 			list_add_tail(&qtd->qtd_list, head);
 
 			/* never any data in such packets */
@@ -1622,18 +1529,17 @@ static struct list_head *qh_urb_transaction(struct isp1760_hcd *priv,
 		}
 	}
 
-	qtd->status = URB_COMPLETE_NOTIFY;
+	qtd->status = 0;
 	return head;
 
 cleanup:
-	qtd_list_free(priv, urb, head);
+	qtd_list_free(urb, head);
 	return NULL;
 }
 
 static int isp1760_urb_enqueue(struct usb_hcd *hcd, struct urb *urb,
 		gfp_t mem_flags)
 {
-	struct isp1760_hcd *priv = hcd_to_priv(hcd);
 	struct list_head qtd_list;
 	packet_enqueue *pe;
 
@@ -1642,29 +1548,27 @@ static int isp1760_urb_enqueue(struct usb_hcd *hcd, struct urb *urb,
 	switch (usb_pipetype(urb->pipe)) {
 	case PIPE_CONTROL:
 	case PIPE_BULK:
-
-		if (!qh_urb_transaction(priv, urb, &qtd_list, mem_flags))
+		if (!qh_urb_transaction(hcd, urb, &qtd_list, mem_flags))
 			return -ENOMEM;
 		pe =  enqueue_an_ATL_packet;
 		break;
 
 	case PIPE_INTERRUPT:
-		if (!qh_urb_transaction(priv, urb, &qtd_list, mem_flags))
+		if (!qh_urb_transaction(hcd, urb, &qtd_list, mem_flags))
 			return -ENOMEM;
 		pe = enqueue_an_INT_packet;
 		break;
 
 	case PIPE_ISOCHRONOUS:
-		printk(KERN_ERR "PIPE_ISOCHRONOUS ain't supported\n");
+		dev_err(hcd->self.controller, "PIPE_ISOCHRONOUS ain't supported\n");
 	default:
 		return -EPIPE;
 	}
 
-	return isp1760_prepare_enqueue(priv, urb, &qtd_list, mem_flags, pe);
+	return isp1760_prepare_enqueue(hcd, urb, &qtd_list, mem_flags, pe);
 }
 
-static int isp1760_urb_dequeue(struct usb_hcd *hcd, struct urb *urb,
-		int status)
+static int isp1760_urb_dequeue(struct usb_hcd *hcd, struct urb *urb, int status)
 {
 	struct isp1760_hcd *priv = hcd_to_priv(hcd);
 	struct inter_packet_info *ints;
@@ -1681,7 +1585,7 @@ static int isp1760_urb_dequeue(struct usb_hcd *hcd, struct urb *urb,
 
 	case PIPE_INTERRUPT:
 		ints = priv->int_ints;
-		reg_base = INT_REGS_OFFSET;
+		reg_base = INT_PTD_OFFSET;
 		or_reg = HC_INT_IRQ_MASK_OR_REG;
 		skip_reg = HC_INT_PTD_SKIPMAP_REG;
 		pe = enqueue_an_INT_packet;
@@ -1689,7 +1593,7 @@ static int isp1760_urb_dequeue(struct usb_hcd *hcd, struct urb *urb,
 
 	default:
 		ints = priv->atl_ints;
-		reg_base = ATL_REGS_OFFSET;
+		reg_base = ATL_PTD_OFFSET;
 		or_reg = HC_ATL_IRQ_MASK_OR_REG;
 		skip_reg = HC_ATL_PTD_SKIPMAP_REG;
 		pe =  enqueue_an_ATL_packet;
@@ -1700,81 +1604,84 @@ static int isp1760_urb_dequeue(struct usb_hcd *hcd, struct urb *urb,
 	spin_lock_irqsave(&priv->lock, flags);
 
 	for (i = 0; i < 32; i++) {
-		if (ints->urb == urb) {
+		if (!ints[i].qh)
+			continue;
+		BUG_ON(!ints[i].qtd);
+
+		if (ints[i].qtd->urb == urb) {
 			u32 skip_map;
 			u32 or_map;
 			struct isp1760_qtd *qtd;
-			struct isp1760_qh *qh = ints->qh;
+			struct isp1760_qh *qh;
 
-			skip_map = isp1760_readl(hcd->regs + skip_reg);
+			skip_map = reg_read32(hcd->regs, skip_reg);
 			skip_map |= 1 << i;
-			isp1760_writel(skip_map, hcd->regs + skip_reg);
+			reg_write32(hcd->regs, skip_reg, skip_map);
 
-			or_map = isp1760_readl(hcd->regs + or_reg);
+			or_map = reg_read32(hcd->regs, or_reg);
 			or_map &= ~(1 << i);
-			isp1760_writel(or_map, hcd->regs + or_reg);
+			reg_write32(hcd->regs, or_reg, or_map);
+
+			ptd_write(hcd->regs, reg_base, i, &ptd);
 
-			priv_write_copy(priv, (u32 *)&ptd, hcd->regs + reg_base
-					+ i * sizeof(ptd), sizeof(ptd));
-			qtd = ints->qtd;
-			qtd = clean_up_qtdlist(qtd);
+			qtd = ints[i].qtd;
+			qh = ints[i].qh;
 
-			free_mem(priv, ints->payload);
+			free_mem(hcd, qtd);
+			qtd = clean_up_qtdlist(qtd, qh);
 
-			ints->urb = NULL;
-			ints->qh = NULL;
-			ints->qtd = NULL;
-			ints->data_buffer = NULL;
-			ints->payload = 0;
+			ints[i].qh = NULL;
+			ints[i].qtd = NULL;
 
-			isp1760_urb_done(priv, urb, status);
+			isp1760_urb_done(hcd, urb);
 			if (qtd)
 				pe(hcd, qh, qtd);
 			break;
 
-		} else if (ints->qtd) {
-			struct isp1760_qtd *qtd, *prev_qtd = ints->qtd;
+		} else {
+			struct isp1760_qtd *qtd;
 
-			for (qtd = ints->qtd->hw_next; qtd; qtd = qtd->hw_next) {
+			list_for_each_entry(qtd, &ints[i].qtd->qtd_list,
+								qtd_list) {
 				if (qtd->urb == urb) {
-					prev_qtd->hw_next = clean_up_qtdlist(qtd);
-					isp1760_urb_done(priv, urb, status);
+					clean_up_qtdlist(qtd, ints[i].qh);
+					isp1760_urb_done(hcd, urb);
+					qtd = NULL;
 					break;
 				}
-				prev_qtd = qtd;
 			}
-			/* we found the urb before the end of the list */
-			if (qtd)
+
+			/* We found the urb before the last slot */
+			if (!qtd)
 				break;
 		}
-		ints++;
 	}
 
 	spin_unlock_irqrestore(&priv->lock, flags);
 	return 0;
 }
 
-static irqreturn_t isp1760_irq(struct usb_hcd *usb_hcd)
+static irqreturn_t isp1760_irq(struct usb_hcd *hcd)
 {
-	struct isp1760_hcd *priv = hcd_to_priv(usb_hcd);
+	struct isp1760_hcd *priv = hcd_to_priv(hcd);
 	u32 imask;
 	irqreturn_t irqret = IRQ_NONE;
 
 	spin_lock(&priv->lock);
 
-	if (!(usb_hcd->state & HC_STATE_RUNNING))
+	if (!(hcd->state & HC_STATE_RUNNING))
 		goto leave;
 
-	imask = isp1760_readl(usb_hcd->regs + HC_INTERRUPT_REG);
+	imask = reg_read32(hcd->regs, HC_INTERRUPT_REG);
 	if (unlikely(!imask))
 		goto leave;
 
-	isp1760_writel(imask, usb_hcd->regs + HC_INTERRUPT_REG);
-	if (imask & HC_ATL_INT)
-		do_atl_int(usb_hcd);
+	reg_write32(hcd->regs, HC_INTERRUPT_REG, imask);
+	if (imask & (HC_ATL_INT | HC_SOT_INT))
+		do_atl_int(hcd);
 
 	if (imask & HC_INTL_INT)
-		do_intl_int(usb_hcd);
+		do_intl_int(hcd);
 
 	irqret = IRQ_HANDLED;
 leave:
@@ -1799,12 +1706,12 @@ static int isp1760_hub_status_data(struct usb_hcd *hcd, char *buf)
 	mask = PORT_CSC;
 
 	spin_lock_irqsave(&priv->lock, flags);
-	temp = isp1760_readl(hcd->regs + HC_PORTSC1);
+	temp = reg_read32(hcd->regs, HC_PORTSC1);
 
 	if (temp & PORT_OWNER) {
 		if (temp & PORT_CSC) {
 			temp &= ~PORT_CSC;
-			isp1760_writel(temp, hcd->regs + HC_PORTSC1);
+			reg_write32(hcd->regs, HC_PORTSC1, temp);
 			goto done;
 		}
 	}
@@ -1844,9 +1751,9 @@ static void isp1760_hub_descriptor(struct isp1760_hcd *priv,
 	temp = 1 + (ports / 8);
 	desc->bDescLength = 7 + 2 * temp;
 
-	/* two bitmaps:  ports removable, and usb 1.0 legacy PortPwrCtrlMask */
-	memset(&desc->bitmap[0], 0, temp);
-	memset(&desc->bitmap[temp], 0xff, temp);
+	/* ports removable, and usb 1.0 legacy PortPwrCtrlMask */
+	memset(&desc->u.hs.DeviceRemovable[0], 0, temp);
+	memset(&desc->u.hs.DeviceRemovable[temp], 0xff, temp);
 
 	/* per-port overcurrent reporting */
 	temp = 0x0008;
@@ -1861,8 +1768,8 @@ static void isp1760_hub_descriptor(struct isp1760_hcd *priv,
 
 #define	PORT_WAKE_BITS	(PORT_WKOC_E|PORT_WKDISC_E|PORT_WKCONN_E)
 
-static int check_reset_complete(struct isp1760_hcd *priv, int index,
-		u32 __iomem *status_reg, int port_status)
+static int check_reset_complete(struct usb_hcd *hcd, int index,
+		int port_status)
 {
 	if (!(port_status & PORT_CONNECT))
 		return port_status;
@@ -1870,15 +1777,17 @@ static int check_reset_complete(struct isp1760_hcd *priv, int index,
 	/* if reset finished and it's still not enabled -- handoff */
 	if (!(port_status & PORT_PE)) {
 
-		printk(KERN_ERR "port %d full speed --> companion\n",
-			index + 1);
+		dev_err(hcd->self.controller,
+					"port %d full speed --> companion\n",
+					index + 1);
 
 		port_status |= PORT_OWNER;
 		port_status &= ~PORT_RWC_BITS;
-		isp1760_writel(port_status, status_reg);
+		reg_write32(hcd->regs, HC_PORTSC1, port_status);
 
 	} else
-		printk(KERN_ERR "port %d high speed\n", index + 1);
+		dev_err(hcd->self.controller, "port %d high speed\n",
+								index + 1);
 
 	return port_status;
 }
@@ -1888,7 +1797,6 @@ static int isp1760_hub_control(struct usb_hcd *hcd, u16 typeReq,
 {
 	struct isp1760_hcd *priv = hcd_to_priv(hcd);
 	int ports = HCS_N_PORTS(priv->hcs_params);
-	u32 __iomem *status_reg = hcd->regs + HC_PORTSC1;
 	u32 temp, status;
 	unsigned long flags;
 	int retval = 0;
@@ -1917,7 +1825,7 @@ static int isp1760_hub_control(struct usb_hcd *hcd, u16 typeReq,
 		if (!wIndex || wIndex > ports)
 			goto error;
 		wIndex--;
-		temp = isp1760_readl(status_reg);
+		temp = reg_read32(hcd->regs, HC_PORTSC1);
 
 		/*
 		 * Even if OWNER is set, so the port is owned by the
@@ -1928,7 +1836,7 @@ static int isp1760_hub_control(struct usb_hcd *hcd, u16 typeReq,
 
 		switch (wValue) {
 		case USB_PORT_FEAT_ENABLE:
-			isp1760_writel(temp & ~PORT_PE, status_reg);
+			reg_write32(hcd->regs, HC_PORTSC1, temp & ~PORT_PE);
 			break;
 		case USB_PORT_FEAT_C_ENABLE:
 			/* XXX error? */
@@ -1942,8 +1850,8 @@ static int isp1760_hub_control(struct usb_hcd *hcd, u16 typeReq,
 					goto error;
 				/* resume signaling for 20 msec */
 				temp &= ~(PORT_RWC_BITS);
-				isp1760_writel(temp | PORT_RESUME,
-						status_reg);
+				reg_write32(hcd->regs, HC_PORTSC1,
+							temp | PORT_RESUME);
 				priv->reset_done = jiffies +
 					msecs_to_jiffies(20);
 			}
@@ -1953,11 +1861,11 @@ static int isp1760_hub_control(struct usb_hcd *hcd, u16 typeReq,
 			break;
 		case USB_PORT_FEAT_POWER:
 			if (HCS_PPC(priv->hcs_params))
-				isp1760_writel(temp & ~PORT_POWER, status_reg);
+				reg_write32(hcd->regs, HC_PORTSC1,
+							temp & ~PORT_POWER);
 			break;
 		case USB_PORT_FEAT_C_CONNECTION:
-			isp1760_writel(temp | PORT_CSC,
-					status_reg);
+			reg_write32(hcd->regs, HC_PORTSC1, temp | PORT_CSC);
 			break;
 		case USB_PORT_FEAT_C_OVER_CURRENT:
 			/* XXX error ?*/
@@ -1968,7 +1876,7 @@ static int isp1760_hub_control(struct usb_hcd *hcd, u16 typeReq,
 		default:
 			goto error;
 		}
-		isp1760_readl(hcd->regs + HC_USBCMD);
+		reg_read32(hcd->regs, HC_USBCMD);
 		break;
 	case GetHubDescriptor:
 		isp1760_hub_descriptor(priv, (struct usb_hub_descriptor *)
@@ -1983,7 +1891,7 @@ static int isp1760_hub_control(struct usb_hcd *hcd, u16 typeReq,
 			goto error;
 		wIndex--;
 		status = 0;
-		temp = isp1760_readl(status_reg);
+		temp = reg_read32(hcd->regs, HC_PORTSC1);
 
 		/* wPortChange bits */
 		if (temp & PORT_CSC)
@@ -1992,7 +1900,7 @@ static int isp1760_hub_control(struct usb_hcd *hcd, u16 typeReq,
 
 		/* whoever resumes must GetPortStatus to complete it!! */
 		if (temp & PORT_RESUME) {
-			printk(KERN_ERR "Port resume should be skipped.\n");
+			dev_err(hcd->self.controller, "Port resume should be skipped.\n");
 
 			/* Remote Wakeup received? */
 			if (!priv->reset_done) {
@@ -2000,8 +1908,7 @@ static int isp1760_hub_control(struct usb_hcd *hcd, u16 typeReq,
 				priv->reset_done = jiffies
 						+ msecs_to_jiffies(20);
 				/* check the port again */
-				mod_timer(&priv_to_hcd(priv)->rh_timer,
-						priv->reset_done);
+				mod_timer(&hcd->rh_timer, priv->reset_done);
 			}
 
 			/* resume completed? */
@@ -2011,14 +1918,13 @@ static int isp1760_hub_control(struct usb_hcd *hcd, u16 typeReq,
 				priv->reset_done = 0;
 
 				/* stop resume signaling */
-				temp = isp1760_readl(status_reg);
-				isp1760_writel(
-					temp & ~(PORT_RWC_BITS | PORT_RESUME),
-					status_reg);
-				retval = handshake(priv, status_reg,
+				temp = reg_read32(hcd->regs, HC_PORTSC1);
+				reg_write32(hcd->regs, HC_PORTSC1,
+					temp & ~(PORT_RWC_BITS | PORT_RESUME));
+				retval = handshake(hcd, HC_PORTSC1,
 					   PORT_RESUME, 0, 2000 /* 2msec */);
 				if (retval != 0) {
-					isp1760_err(priv,
+					dev_err(hcd->self.controller,
 						"port %d resume error %d\n",
 						wIndex + 1, retval);
 					goto error;
@@ -2035,22 +1941,21 @@ static int isp1760_hub_control(struct usb_hcd *hcd, u16 typeReq,
 			priv->reset_done = 0;
 
 			/* force reset to complete */
-			isp1760_writel(temp & ~PORT_RESET,
-					status_reg);
+			reg_write32(hcd->regs, HC_PORTSC1, temp & ~PORT_RESET);
 			/* REVISIT:  some hardware needs 550+ usec to clear
 			 * this bit; seems too long to spin routinely...
 			 */
-			retval = handshake(priv, status_reg,
+			retval = handshake(hcd, HC_PORTSC1,
 					PORT_RESET, 0, 750);
 			if (retval != 0) {
-				isp1760_err(priv, "port %d reset error %d\n",
+				dev_err(hcd->self.controller, "port %d reset error %d\n",
 						wIndex + 1, retval);
 				goto error;
 			}
 
 			/* see what we found out */
-			temp = check_reset_complete(priv, wIndex, status_reg,
-					isp1760_readl(status_reg));
+			temp = check_reset_complete(hcd, wIndex,
+					reg_read32(hcd->regs, HC_PORTSC1));
 		}
 		/*
 		 * Even if OWNER is set, there's no harm letting khubd
@@ -2059,12 +1964,12 @@ static int isp1760_hub_control(struct usb_hcd *hcd, u16 typeReq,
 		 */
 
 		if (temp & PORT_OWNER)
-			printk(KERN_ERR "Warning: PORT_OWNER is set\n");
+			dev_err(hcd->self.controller, "PORT_OWNER is set\n");
 
 		if (temp & PORT_CONNECT) {
 			status |= USB_PORT_STAT_CONNECTION;
 			/* status may be from integrated TT */
-			status |= ehci_port_speed(priv, temp);
+			status |= USB_PORT_STAT_HIGH_SPEED;
 		}
 		if (temp & PORT_PE)
 			status |= USB_PORT_STAT_ENABLE;
@@ -2093,14 +1998,14 @@ static int isp1760_hub_control(struct usb_hcd *hcd, u16 typeReq,
 		if (!wIndex || wIndex > ports)
 			goto error;
 		wIndex--;
-		temp = isp1760_readl(status_reg);
+		temp = reg_read32(hcd->regs, HC_PORTSC1);
 		if (temp & PORT_OWNER)
 			break;
 
 /*		temp &= ~PORT_RWC_BITS; */
 		switch (wValue) {
 		case USB_PORT_FEAT_ENABLE:
-			isp1760_writel(temp | PORT_PE, status_reg);
+			reg_write32(hcd->regs, HC_PORTSC1, temp | PORT_PE);
 			break;
 
 		case USB_PORT_FEAT_SUSPEND:
@@ -2108,12 +2013,12 @@ static int isp1760_hub_control(struct usb_hcd *hcd, u16 typeReq,
 					|| (temp & PORT_RESET) != 0)
 				goto error;
 
-			isp1760_writel(temp | PORT_SUSPEND, status_reg);
+			reg_write32(hcd->regs, HC_PORTSC1, temp | PORT_SUSPEND);
 			break;
 		case USB_PORT_FEAT_POWER:
 			if (HCS_PPC(priv->hcs_params))
-				isp1760_writel(temp | PORT_POWER,
-						status_reg);
+				reg_write32(hcd->regs, HC_PORTSC1,
+							temp | PORT_POWER);
 			break;
 		case USB_PORT_FEAT_RESET:
 			if (temp & PORT_RESUME)
@@ -2136,12 +2041,12 @@ static int isp1760_hub_control(struct usb_hcd *hcd, u16 typeReq,
 				priv->reset_done = jiffies +
 					msecs_to_jiffies(50);
 			}
-			isp1760_writel(temp, status_reg);
+			reg_write32(hcd->regs, HC_PORTSC1, temp);
 			break;
 		default:
 			goto error;
 		}
-		isp1760_readl(hcd->regs + HC_USBCMD);
+		reg_read32(hcd->regs, HC_USBCMD);
 		break;
 
 	default:
@@ -2153,10 +2058,10 @@ error:
 	return retval;
 }
 
-static void isp1760_endpoint_disable(struct usb_hcd *usb_hcd,
+static void isp1760_endpoint_disable(struct usb_hcd *hcd,
 		struct usb_host_endpoint *ep)
 {
-	struct isp1760_hcd *priv = hcd_to_priv(usb_hcd);
+	struct isp1760_hcd *priv = hcd_to_priv(hcd);
 	struct isp1760_qh *qh;
 	struct isp1760_qtd *qtd;
 	unsigned long flags;
@@ -2176,16 +2081,16 @@ static void isp1760_endpoint_disable(struct usb_hcd *usb_hcd,
 				qtd_list);
 
 		if (qtd->status & URB_ENQUEUED) {
-
 			spin_unlock_irqrestore(&priv->lock, flags);
-			isp1760_urb_dequeue(usb_hcd, qtd->urb, -ECONNRESET);
+			isp1760_urb_dequeue(hcd, qtd->urb, -ECONNRESET);
 			spin_lock_irqsave(&priv->lock, flags);
 		} else {
 			struct urb *urb;
 
 			urb = qtd->urb;
-			clean_up_qtdlist(qtd);
-			isp1760_urb_done(priv, urb, -ECONNRESET);
+			clean_up_qtdlist(qtd, qh);
+			urb->status = -ECONNRESET;
+			isp1760_urb_done(hcd, urb);
 		}
 	} while (1);
 
@@ -2203,7 +2108,7 @@ static int isp1760_get_frame(struct usb_hcd *hcd)
 	struct isp1760_hcd *priv = hcd_to_priv(hcd);
 	u32 fr;
 
-	fr = isp1760_readl(hcd->regs + HC_FRINDEX);
+	fr = reg_read32(hcd->regs, HC_FRINDEX);
 	return (fr >> 3) % priv->periodic_size;
 }
 
@@ -2217,13 +2122,13 @@ static void isp1760_stop(struct usb_hcd *hcd)
 	mdelay(20);
 
 	spin_lock_irq(&priv->lock);
-	ehci_reset(priv);
+	ehci_reset(hcd);
 	/* Disable IRQ */
-	temp = isp1760_readl(hcd->regs + HC_HW_MODE_CTRL);
-	isp1760_writel(temp &= ~HW_GLOBAL_INTR_EN, hcd->regs + HC_HW_MODE_CTRL);
+	temp = reg_read32(hcd->regs, HC_HW_MODE_CTRL);
+	reg_write32(hcd->regs, HC_HW_MODE_CTRL, temp &= ~HW_GLOBAL_INTR_EN);
 	spin_unlock_irq(&priv->lock);
 
-	isp1760_writel(0, hcd->regs + HC_CONFIGFLAG);
+	reg_write32(hcd->regs, HC_CONFIGFLAG, 0);
 }
 
 static void isp1760_shutdown(struct usb_hcd *hcd)
@@ -2231,12 +2136,12 @@ static void isp1760_shutdown(struct usb_hcd *hcd)
 	u32 command, temp;
 
 	isp1760_stop(hcd);
-	temp = isp1760_readl(hcd->regs + HC_HW_MODE_CTRL);
-	isp1760_writel(temp &= ~HW_GLOBAL_INTR_EN, hcd->regs + HC_HW_MODE_CTRL);
+	temp = reg_read32(hcd->regs, HC_HW_MODE_CTRL);
+	reg_write32(hcd->regs, HC_HW_MODE_CTRL, temp &= ~HW_GLOBAL_INTR_EN);
 
-	command = isp1760_readl(hcd->regs + HC_USBCMD);
+	command = reg_read32(hcd->regs, HC_USBCMD);
 	command &= ~CMD_RUN;
-	isp1760_writel(command, hcd->regs + HC_USBCMD);
+	reg_write32(hcd->regs, HC_USBCMD, command);
 }
 
 static const struct hc_driver isp1760_hc_driver = {
diff --git a/drivers/usb/host/isp1760-hcd.h b/drivers/usb/host/isp1760-hcd.h
index 6931ef5c9650..870507690607 100644
--- a/drivers/usb/host/isp1760-hcd.h
+++ b/drivers/usb/host/isp1760-hcd.h
@@ -69,6 +69,7 @@ void deinit_kmem_cache(void);
 
 #define HC_INTERRUPT_ENABLE	0x314
 #define INTERRUPT_ENABLE_MASK	(HC_INTL_INT | HC_ATL_INT | HC_EOT_INT)
+#define INTERRUPT_ENABLE_SOT_MASK	(HC_INTL_INT | HC_SOT_INT | HC_EOT_INT)
 
 #define HC_ISO_INT		(1 << 9)
 #define HC_ATL_INT		(1 << 8)
@@ -83,37 +84,29 @@ void deinit_kmem_cache(void);
 #define HC_INT_IRQ_MASK_AND_REG	0x328
 #define HC_ATL_IRQ_MASK_AND_REG	0x32C
 
-/* Register sets */
-#define HC_BEGIN_OF_ATL		0x0c00
-#define HC_BEGIN_OF_INT		0x0800
-#define HC_BEGIN_OF_ISO		0x0400
-#define HC_BEGIN_OF_PAYLOAD	0x1000
-
 /* urb state*/
 #define DELETE_URB		(0x0008)
 #define NO_TRANSFER_ACTIVE	(0xffffffff)
 
-#define ATL_REGS_OFFSET		(0xc00)
-#define INT_REGS_OFFSET		(0x800)
-
-/* Philips Transfer Descriptor (PTD) */
+/* Philips Proprietary Transfer Descriptor (PTD) */
+typedef __u32 __bitwise __dw;
 struct ptd {
-	__le32 dw0;
-	__le32 dw1;
-	__le32 dw2;
-	__le32 dw3;
-	__le32 dw4;
-	__le32 dw5;
-	__le32 dw6;
-	__le32 dw7;
+	__dw dw0;
+	__dw dw1;
+	__dw dw2;
+	__dw dw3;
+	__dw dw4;
+	__dw dw5;
+	__dw dw6;
+	__dw dw7;
 };
+#define PTD_OFFSET		0x0400
+#define ISO_PTD_OFFSET		0x0400
+#define INT_PTD_OFFSET		0x0800
+#define ATL_PTD_OFFSET		0x0c00
+#define PAYLOAD_OFFSET		0x1000
 
 struct inter_packet_info {
-	void *data_buffer;
-	u32 payload;
-#define PTD_FIRE_NEXT		(1 << 0)
-#define PTD_URB_FINISHED	(1 << 1)
-	struct urb *urb;
 	struct isp1760_qh *qh;
 	struct isp1760_qtd *qtd;
 };
@@ -122,15 +115,6 @@ struct inter_packet_info {
 typedef void (packet_enqueue)(struct usb_hcd *hcd, struct isp1760_qh *qh,
 		struct isp1760_qtd *qtd);
 
-#define isp1760_dbg(priv, fmt, args...) \
-	dev_dbg(priv_to_hcd(priv)->self.controller, fmt, ##args)
-
-#define isp1760_info(priv, fmt, args...) \
-	dev_info(priv_to_hcd(priv)->self.controller, fmt, ##args)
-
-#define isp1760_err(priv, fmt, args...) \
-	dev_err(priv_to_hcd(priv)->self.controller, fmt, ##args)
-
 /*
  * Device flags that can vary from board to board.  All of these
  * indicate the most "atypical" case, so that a devflags of 0 is
@@ -167,10 +151,8 @@ struct memory_chunk {
 #define BLOCK_2_SIZE 1024
 #define BLOCK_3_SIZE 8192
 #define BLOCKS (BLOCK_1_NUM + BLOCK_2_NUM + BLOCK_3_NUM)
-#define PAYLOAD_SIZE 0xf000
-
-/* I saw if some reloads if the pointer was negative */
-#define ISP1760_NULL_POINTER	(0x400)
+#define MAX_PAYLOAD_SIZE BLOCK_3_SIZE
+#define PAYLOAD_AREA_SIZE 0xf000
 
 /* ATL */
 /* DW0 */
@@ -224,6 +206,4 @@ struct memory_chunk {
 #define NAK_COUNTER	(0)
 #define ERR_COUNTER	(2)
 
-#define HC_ATL_PL_SIZE	(8192)
-
 #endif
diff --git a/drivers/usb/host/ohci-hcd.c b/drivers/usb/host/ohci-hcd.c
index 759a12ff8048..fb035751e4b2 100644
--- a/drivers/usb/host/ohci-hcd.c
+++ b/drivers/usb/host/ohci-hcd.c
@@ -75,6 +75,7 @@ static const char	hcd_name [] = "ohci_hcd";
 #define	STATECHANGE_DELAY	msecs_to_jiffies(300)
 
 #include "ohci.h"
+#include "pci-quirks.h"
 
 static void ohci_dump (struct ohci_hcd *ohci, int verbose);
 static int ohci_init (struct ohci_hcd *ohci);
@@ -85,18 +86,8 @@ static int ohci_restart (struct ohci_hcd *ohci);
 #endif
 
 #ifdef CONFIG_PCI
-static void quirk_amd_pll(int state);
-static void amd_iso_dev_put(void);
 static void sb800_prefetch(struct ohci_hcd *ohci, int on);
 #else
-static inline void quirk_amd_pll(int state)
-{
-	return;
-}
-static inline void amd_iso_dev_put(void)
-{
-	return;
-}
 static inline void sb800_prefetch(struct ohci_hcd *ohci, int on)
 {
 	return;
@@ -912,7 +903,7 @@ static void ohci_stop (struct usb_hcd *hcd)
 	if (quirk_zfmicro(ohci))
 		del_timer(&ohci->unlink_watchdog);
 	if (quirk_amdiso(ohci))
-		amd_iso_dev_put();
+		usb_amd_dev_put();
 
 	remove_debug_files (ohci);
 	ohci_mem_cleanup (ohci);
@@ -1068,10 +1059,7 @@ MODULE_LICENSE ("GPL");
 #define PLATFORM_DRIVER		ohci_hcd_da8xx_driver
 #endif
 
-#if defined(CONFIG_CPU_SUBTYPE_SH7720) || \
-    defined(CONFIG_CPU_SUBTYPE_SH7721) || \
-    defined(CONFIG_CPU_SUBTYPE_SH7763) || \
-    defined(CONFIG_CPU_SUBTYPE_SH7786)
+#ifdef CONFIG_USB_OHCI_SH
 #include "ohci-sh.c"
 #define PLATFORM_DRIVER		ohci_hcd_sh_driver
 #endif
diff --git a/drivers/usb/host/ohci-hub.c b/drivers/usb/host/ohci-hub.c
index cddcda95b579..9154615292db 100644
--- a/drivers/usb/host/ohci-hub.c
+++ b/drivers/usb/host/ohci-hub.c
@@ -580,15 +580,16 @@ ohci_hub_descriptor (
 	    temp |= 0x0008;
 	desc->wHubCharacteristics = (__force __u16)cpu_to_hc16(ohci, temp);
 
-	/* two bitmaps:  ports removable, and usb 1.0 legacy PortPwrCtrlMask */
+	/* ports removable, and usb 1.0 legacy PortPwrCtrlMask */
 	rh = roothub_b (ohci);
-	memset(desc->bitmap, 0xff, sizeof(desc->bitmap));
-	desc->bitmap [0] = rh & RH_B_DR;
+	memset(desc->u.hs.DeviceRemovable, 0xff,
+			sizeof(desc->u.hs.DeviceRemovable));
+	desc->u.hs.DeviceRemovable[0] = rh & RH_B_DR;
 	if (ohci->num_ports > 7) {
-		desc->bitmap [1] = (rh & RH_B_DR) >> 8;
-		desc->bitmap [2] = 0xff;
+		desc->u.hs.DeviceRemovable[1] = (rh & RH_B_DR) >> 8;
+		desc->u.hs.DeviceRemovable[2] = 0xff;
 	} else
-		desc->bitmap [1] = 0xff;
+		desc->u.hs.DeviceRemovable[1] = 0xff;
 }
 
 /*-------------------------------------------------------------------------*/
diff --git a/drivers/usb/host/ohci-omap3.c b/drivers/usb/host/ohci-omap3.c
index a37d5993e4e3..6048f2f64f73 100644
--- a/drivers/usb/host/ohci-omap3.c
+++ b/drivers/usb/host/ohci-omap3.c
@@ -7,6 +7,7 @@
  * Copyright (C) 2007-2010 Texas Instruments, Inc.
  * Author: Vikram Pandita <vikram.pandita@ti.com>
  * Author: Anand Gadiyar <gadiyar@ti.com>
+ * Author: Keshava Munegowda <keshava_mgowda@ti.com>
  *
  * Based on ehci-omap.c and some other ohci glue layers
  *
@@ -24,150 +25,15 @@
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
  *
- * TODO (last updated Mar 10th, 2010):
+ * TODO (last updated Feb 27, 2011):
  *	- add kernel-doc
- *	- Factor out code common to EHCI to a separate file
- *	- Make EHCI and OHCI coexist together
- *	  - needs newer silicon versions to actually work
- *	  - the last one to be loaded currently steps on the other's toes
- *	- Add hooks for configuring transceivers, etc. at init/exit
- *	- Add aggressive clock-management code
  */
 
 #include <linux/platform_device.h>
-#include <linux/clk.h>
-
 #include <plat/usb.h>
 
-/*
- * OMAP USBHOST Register addresses: VIRTUAL ADDRESSES
- *	Use ohci_omap_readl()/ohci_omap_writel() functions
- */
-
-/* TLL Register Set */
-#define	OMAP_USBTLL_REVISION				(0x00)
-#define	OMAP_USBTLL_SYSCONFIG				(0x10)
-#define	OMAP_USBTLL_SYSCONFIG_CACTIVITY			(1 << 8)
-#define	OMAP_USBTLL_SYSCONFIG_SIDLEMODE			(1 << 3)
-#define	OMAP_USBTLL_SYSCONFIG_ENAWAKEUP			(1 << 2)
-#define	OMAP_USBTLL_SYSCONFIG_SOFTRESET			(1 << 1)
-#define	OMAP_USBTLL_SYSCONFIG_AUTOIDLE			(1 << 0)
-
-#define	OMAP_USBTLL_SYSSTATUS				(0x14)
-#define	OMAP_USBTLL_SYSSTATUS_RESETDONE			(1 << 0)
-
-#define	OMAP_USBTLL_IRQSTATUS				(0x18)
-#define	OMAP_USBTLL_IRQENABLE				(0x1C)
-
-#define	OMAP_TLL_SHARED_CONF				(0x30)
-#define	OMAP_TLL_SHARED_CONF_USB_90D_DDR_EN		(1 << 6)
-#define	OMAP_TLL_SHARED_CONF_USB_180D_SDR_EN		(1 << 5)
-#define	OMAP_TLL_SHARED_CONF_USB_DIVRATION		(1 << 2)
-#define	OMAP_TLL_SHARED_CONF_FCLK_REQ			(1 << 1)
-#define	OMAP_TLL_SHARED_CONF_FCLK_IS_ON			(1 << 0)
-
-#define	OMAP_TLL_CHANNEL_CONF(num)			(0x040 + 0x004 * num)
-#define OMAP_TLL_CHANNEL_CONF_FSLSMODE_SHIFT		24
-#define	OMAP_TLL_CHANNEL_CONF_ULPINOBITSTUFF		(1 << 11)
-#define	OMAP_TLL_CHANNEL_CONF_ULPI_ULPIAUTOIDLE		(1 << 10)
-#define	OMAP_TLL_CHANNEL_CONF_UTMIAUTOIDLE		(1 << 9)
-#define	OMAP_TLL_CHANNEL_CONF_ULPIDDRMODE		(1 << 8)
-#define OMAP_TLL_CHANNEL_CONF_CHANMODE_FSLS		(1 << 1)
-#define	OMAP_TLL_CHANNEL_CONF_CHANEN			(1 << 0)
-
-#define OMAP_TLL_CHANNEL_COUNT				3
-
-/* UHH Register Set */
-#define	OMAP_UHH_REVISION				(0x00)
-#define	OMAP_UHH_SYSCONFIG				(0x10)
-#define	OMAP_UHH_SYSCONFIG_MIDLEMODE			(1 << 12)
-#define	OMAP_UHH_SYSCONFIG_CACTIVITY			(1 << 8)
-#define	OMAP_UHH_SYSCONFIG_SIDLEMODE			(1 << 3)
-#define	OMAP_UHH_SYSCONFIG_ENAWAKEUP			(1 << 2)
-#define	OMAP_UHH_SYSCONFIG_SOFTRESET			(1 << 1)
-#define	OMAP_UHH_SYSCONFIG_AUTOIDLE			(1 << 0)
-
-#define	OMAP_UHH_SYSSTATUS				(0x14)
-#define OMAP_UHH_SYSSTATUS_UHHRESETDONE			(1 << 0)
-#define OMAP_UHH_SYSSTATUS_OHCIRESETDONE		(1 << 1)
-#define OMAP_UHH_SYSSTATUS_EHCIRESETDONE		(1 << 2)
-#define	OMAP_UHH_HOSTCONFIG				(0x40)
-#define	OMAP_UHH_HOSTCONFIG_ULPI_BYPASS			(1 << 0)
-#define	OMAP_UHH_HOSTCONFIG_ULPI_P1_BYPASS		(1 << 0)
-#define	OMAP_UHH_HOSTCONFIG_ULPI_P2_BYPASS		(1 << 11)
-#define	OMAP_UHH_HOSTCONFIG_ULPI_P3_BYPASS		(1 << 12)
-#define OMAP_UHH_HOSTCONFIG_INCR4_BURST_EN		(1 << 2)
-#define OMAP_UHH_HOSTCONFIG_INCR8_BURST_EN		(1 << 3)
-#define OMAP_UHH_HOSTCONFIG_INCR16_BURST_EN		(1 << 4)
-#define OMAP_UHH_HOSTCONFIG_INCRX_ALIGN_EN		(1 << 5)
-#define OMAP_UHH_HOSTCONFIG_P1_CONNECT_STATUS		(1 << 8)
-#define OMAP_UHH_HOSTCONFIG_P2_CONNECT_STATUS		(1 << 9)
-#define OMAP_UHH_HOSTCONFIG_P3_CONNECT_STATUS		(1 << 10)
-
-#define	OMAP_UHH_DEBUG_CSR				(0x44)
-
 /*-------------------------------------------------------------------------*/
 
-static inline void ohci_omap_writel(void __iomem *base, u32 reg, u32 val)
-{
-	__raw_writel(val, base + reg);
-}
-
-static inline u32 ohci_omap_readl(void __iomem *base, u32 reg)
-{
-	return __raw_readl(base + reg);
-}
-
-static inline void ohci_omap_writeb(void __iomem *base, u8 reg, u8 val)
-{
-	__raw_writeb(val, base + reg);
-}
-
-static inline u8 ohci_omap_readb(void __iomem *base, u8 reg)
-{
-	return __raw_readb(base + reg);
-}
-
-/*-------------------------------------------------------------------------*/
-
-struct ohci_hcd_omap3 {
-	struct ohci_hcd		*ohci;
-	struct device		*dev;
-
-	struct clk		*usbhost_ick;
-	struct clk		*usbhost2_120m_fck;
-	struct clk		*usbhost1_48m_fck;
-	struct clk		*usbtll_fck;
-	struct clk		*usbtll_ick;
-
-	/* port_mode: TLL/PHY, 2/3/4/6-PIN, DP-DM/DAT-SE0 */
-	enum ohci_omap3_port_mode	port_mode[OMAP3_HS_USB_PORTS];
-	void __iomem		*uhh_base;
-	void __iomem		*tll_base;
-	void __iomem		*ohci_base;
-
-	unsigned		es2_compatibility:1;
-};
-
-/*-------------------------------------------------------------------------*/
-
-static void ohci_omap3_clock_power(struct ohci_hcd_omap3 *omap, int on)
-{
-	if (on) {
-		clk_enable(omap->usbtll_ick);
-		clk_enable(omap->usbtll_fck);
-		clk_enable(omap->usbhost_ick);
-		clk_enable(omap->usbhost1_48m_fck);
-		clk_enable(omap->usbhost2_120m_fck);
-	} else {
-		clk_disable(omap->usbhost2_120m_fck);
-		clk_disable(omap->usbhost1_48m_fck);
-		clk_disable(omap->usbhost_ick);
-		clk_disable(omap->usbtll_fck);
-		clk_disable(omap->usbtll_ick);
-	}
-}
-
 static int ohci_omap3_init(struct usb_hcd *hcd)
 {
 	dev_dbg(hcd->self.controller, "starting OHCI controller\n");
@@ -175,7 +41,6 @@ static int ohci_omap3_init(struct usb_hcd *hcd)
 	return ohci_init(hcd_to_ohci(hcd));
 }
 
-
 /*-------------------------------------------------------------------------*/
 
 static int ohci_omap3_start(struct usb_hcd *hcd)
@@ -202,325 +67,6 @@ static int ohci_omap3_start(struct usb_hcd *hcd)
 
 /*-------------------------------------------------------------------------*/
 
-/*
- * convert the port-mode enum to a value we can use in the FSLSMODE
- * field of USBTLL_CHANNEL_CONF
- */
-static unsigned ohci_omap3_fslsmode(enum ohci_omap3_port_mode mode)
-{
-	switch (mode) {
-	case OMAP_OHCI_PORT_MODE_UNUSED:
-	case OMAP_OHCI_PORT_MODE_PHY_6PIN_DATSE0:
-		return 0x0;
-
-	case OMAP_OHCI_PORT_MODE_PHY_6PIN_DPDM:
-		return 0x1;
-
-	case OMAP_OHCI_PORT_MODE_PHY_3PIN_DATSE0:
-		return 0x2;
-
-	case OMAP_OHCI_PORT_MODE_PHY_4PIN_DPDM:
-		return 0x3;
-
-	case OMAP_OHCI_PORT_MODE_TLL_6PIN_DATSE0:
-		return 0x4;
-
-	case OMAP_OHCI_PORT_MODE_TLL_6PIN_DPDM:
-		return 0x5;
-
-	case OMAP_OHCI_PORT_MODE_TLL_3PIN_DATSE0:
-		return 0x6;
-
-	case OMAP_OHCI_PORT_MODE_TLL_4PIN_DPDM:
-		return 0x7;
-
-	case OMAP_OHCI_PORT_MODE_TLL_2PIN_DATSE0:
-		return 0xA;
-
-	case OMAP_OHCI_PORT_MODE_TLL_2PIN_DPDM:
-		return 0xB;
-	default:
-		pr_warning("Invalid port mode, using default\n");
-		return 0x0;
-	}
-}
-
-static void ohci_omap3_tll_config(struct ohci_hcd_omap3 *omap)
-{
-	u32 reg;
-	int i;
-
-	/* Program TLL SHARED CONF */
-	reg = ohci_omap_readl(omap->tll_base, OMAP_TLL_SHARED_CONF);
-	reg &= ~OMAP_TLL_SHARED_CONF_USB_90D_DDR_EN;
-	reg &= ~OMAP_TLL_SHARED_CONF_USB_180D_SDR_EN;
-	reg |= OMAP_TLL_SHARED_CONF_USB_DIVRATION;
-	reg |= OMAP_TLL_SHARED_CONF_FCLK_IS_ON;
-	ohci_omap_writel(omap->tll_base, OMAP_TLL_SHARED_CONF, reg);
-
-	/* Program each TLL channel */
-	/*
-	 * REVISIT: Only the 3-pin and 4-pin PHY modes have
-	 * actually been tested.
-	 */
-	for (i = 0; i < OMAP_TLL_CHANNEL_COUNT; i++) {
-
-		/* Enable only those channels that are actually used */
-		if (omap->port_mode[i] == OMAP_OHCI_PORT_MODE_UNUSED)
-			continue;
-
-		reg = ohci_omap_readl(omap->tll_base, OMAP_TLL_CHANNEL_CONF(i));
-		reg |= ohci_omap3_fslsmode(omap->port_mode[i])
-				<< OMAP_TLL_CHANNEL_CONF_FSLSMODE_SHIFT;
-		reg |= OMAP_TLL_CHANNEL_CONF_CHANMODE_FSLS;
-		reg |= OMAP_TLL_CHANNEL_CONF_CHANEN;
-		ohci_omap_writel(omap->tll_base, OMAP_TLL_CHANNEL_CONF(i), reg);
-	}
-}
-
-/* omap3_start_ohci
- *	- Start the TI USBHOST controller
- */
-static int omap3_start_ohci(struct ohci_hcd_omap3 *omap, struct usb_hcd *hcd)
-{
-	unsigned long timeout = jiffies + msecs_to_jiffies(1000);
-	u32 reg = 0;
-	int ret = 0;
-
-	dev_dbg(omap->dev, "starting TI OHCI USB Controller\n");
-
-	/* Get all the clock handles we need */
-	omap->usbhost_ick = clk_get(omap->dev, "usbhost_ick");
-	if (IS_ERR(omap->usbhost_ick)) {
-		dev_err(omap->dev, "could not get usbhost_ick\n");
-		ret =  PTR_ERR(omap->usbhost_ick);
-		goto err_host_ick;
-	}
-
-	omap->usbhost2_120m_fck = clk_get(omap->dev, "usbhost_120m_fck");
-	if (IS_ERR(omap->usbhost2_120m_fck)) {
-		dev_err(omap->dev, "could not get usbhost_120m_fck\n");
-		ret = PTR_ERR(omap->usbhost2_120m_fck);
-		goto err_host_120m_fck;
-	}
-
-	omap->usbhost1_48m_fck = clk_get(omap->dev, "usbhost_48m_fck");
-	if (IS_ERR(omap->usbhost1_48m_fck)) {
-		dev_err(omap->dev, "could not get usbhost_48m_fck\n");
-		ret = PTR_ERR(omap->usbhost1_48m_fck);
-		goto err_host_48m_fck;
-	}
-
-	omap->usbtll_fck = clk_get(omap->dev, "usbtll_fck");
-	if (IS_ERR(omap->usbtll_fck)) {
-		dev_err(omap->dev, "could not get usbtll_fck\n");
-		ret = PTR_ERR(omap->usbtll_fck);
-		goto err_tll_fck;
-	}
-
-	omap->usbtll_ick = clk_get(omap->dev, "usbtll_ick");
-	if (IS_ERR(omap->usbtll_ick)) {
-		dev_err(omap->dev, "could not get usbtll_ick\n");
-		ret = PTR_ERR(omap->usbtll_ick);
-		goto err_tll_ick;
-	}
-
-	/* Now enable all the clocks in the correct order */
-	ohci_omap3_clock_power(omap, 1);
-
-	/* perform TLL soft reset, and wait until reset is complete */
-	ohci_omap_writel(omap->tll_base, OMAP_USBTLL_SYSCONFIG,
-			OMAP_USBTLL_SYSCONFIG_SOFTRESET);
-
-	/* Wait for TLL reset to complete */
-	while (!(ohci_omap_readl(omap->tll_base, OMAP_USBTLL_SYSSTATUS)
-			& OMAP_USBTLL_SYSSTATUS_RESETDONE)) {
-		cpu_relax();
-
-		if (time_after(jiffies, timeout)) {
-			dev_dbg(omap->dev, "operation timed out\n");
-			ret = -EINVAL;
-			goto err_sys_status;
-		}
-	}
-
-	dev_dbg(omap->dev, "TLL reset done\n");
-
-	/* (1<<3) = no idle mode only for initial debugging */
-	ohci_omap_writel(omap->tll_base, OMAP_USBTLL_SYSCONFIG,
-			OMAP_USBTLL_SYSCONFIG_ENAWAKEUP |
-			OMAP_USBTLL_SYSCONFIG_SIDLEMODE |
-			OMAP_USBTLL_SYSCONFIG_CACTIVITY);
-
-
-	/* Put UHH in NoIdle/NoStandby mode */
-	reg = ohci_omap_readl(omap->uhh_base, OMAP_UHH_SYSCONFIG);
-	reg |= (OMAP_UHH_SYSCONFIG_ENAWAKEUP
-			| OMAP_UHH_SYSCONFIG_SIDLEMODE
-			| OMAP_UHH_SYSCONFIG_CACTIVITY
-			| OMAP_UHH_SYSCONFIG_MIDLEMODE);
-	reg &= ~OMAP_UHH_SYSCONFIG_AUTOIDLE;
-	reg &= ~OMAP_UHH_SYSCONFIG_SOFTRESET;
-
-	ohci_omap_writel(omap->uhh_base, OMAP_UHH_SYSCONFIG, reg);
-
-	reg = ohci_omap_readl(omap->uhh_base, OMAP_UHH_HOSTCONFIG);
-
-	/* setup ULPI bypass and burst configurations */
-	reg |= (OMAP_UHH_HOSTCONFIG_INCR4_BURST_EN
-			| OMAP_UHH_HOSTCONFIG_INCR8_BURST_EN
-			| OMAP_UHH_HOSTCONFIG_INCR16_BURST_EN);
-	reg &= ~OMAP_UHH_HOSTCONFIG_INCRX_ALIGN_EN;
-
-	/*
-	 * REVISIT: Pi_CONNECT_STATUS controls MStandby
-	 * assertion and Swakeup generation - let us not
-	 * worry about this for now. OMAP HWMOD framework
-	 * might take care of this later. If not, we can
-	 * update these registers when adding aggressive
-	 * clock management code.
-	 *
-	 * For now, turn off all the Pi_CONNECT_STATUS bits
-	 *
-	if (omap->port_mode[0] == OMAP_OHCI_PORT_MODE_UNUSED)
-		reg &= ~OMAP_UHH_HOSTCONFIG_P1_CONNECT_STATUS;
-	if (omap->port_mode[1] == OMAP_OHCI_PORT_MODE_UNUSED)
-		reg &= ~OMAP_UHH_HOSTCONFIG_P2_CONNECT_STATUS;
-	if (omap->port_mode[2] == OMAP_OHCI_PORT_MODE_UNUSED)
-		reg &= ~OMAP_UHH_HOSTCONFIG_P3_CONNECT_STATUS;
-	 */
-	reg &= ~OMAP_UHH_HOSTCONFIG_P1_CONNECT_STATUS;
-	reg &= ~OMAP_UHH_HOSTCONFIG_P2_CONNECT_STATUS;
-	reg &= ~OMAP_UHH_HOSTCONFIG_P3_CONNECT_STATUS;
-
-	 if (omap->es2_compatibility) {
-		/*
-		 * All OHCI modes need to go through the TLL,
-		 * unlike in the EHCI case. So use UTMI mode
-		 * for all ports for OHCI, on ES2.x silicon
-		 */
-		dev_dbg(omap->dev, "OMAP3 ES version <= ES2.1\n");
-		reg |= OMAP_UHH_HOSTCONFIG_ULPI_BYPASS;
-	} else {
-		dev_dbg(omap->dev, "OMAP3 ES version > ES2.1\n");
-		if (omap->port_mode[0] == OMAP_OHCI_PORT_MODE_UNUSED)
-			reg &= ~OMAP_UHH_HOSTCONFIG_ULPI_P1_BYPASS;
-		else
-			reg |= OMAP_UHH_HOSTCONFIG_ULPI_P1_BYPASS;
-
-		if (omap->port_mode[1] == OMAP_OHCI_PORT_MODE_UNUSED)
-			reg &= ~OMAP_UHH_HOSTCONFIG_ULPI_P2_BYPASS;
-		else
-			reg |= OMAP_UHH_HOSTCONFIG_ULPI_P2_BYPASS;
-
-		if (omap->port_mode[2] == OMAP_OHCI_PORT_MODE_UNUSED)
-			reg &= ~OMAP_UHH_HOSTCONFIG_ULPI_P3_BYPASS;
-		else
-			reg |= OMAP_UHH_HOSTCONFIG_ULPI_P3_BYPASS;
-
-	}
-	ohci_omap_writel(omap->uhh_base, OMAP_UHH_HOSTCONFIG, reg);
-	dev_dbg(omap->dev, "UHH setup done, uhh_hostconfig=%x\n", reg);
-
-	ohci_omap3_tll_config(omap);
-
-	return 0;
-
-err_sys_status:
-	ohci_omap3_clock_power(omap, 0);
-	clk_put(omap->usbtll_ick);
-
-err_tll_ick:
-	clk_put(omap->usbtll_fck);
-
-err_tll_fck:
-	clk_put(omap->usbhost1_48m_fck);
-
-err_host_48m_fck:
-	clk_put(omap->usbhost2_120m_fck);
-
-err_host_120m_fck:
-	clk_put(omap->usbhost_ick);
-
-err_host_ick:
-	return ret;
-}
-
-static void omap3_stop_ohci(struct ohci_hcd_omap3 *omap, struct usb_hcd *hcd)
-{
-	unsigned long timeout = jiffies + msecs_to_jiffies(100);
-
-	dev_dbg(omap->dev, "stopping TI EHCI USB Controller\n");
-
-	/* Reset USBHOST for insmod/rmmod to work */
-	ohci_omap_writel(omap->uhh_base, OMAP_UHH_SYSCONFIG,
-			OMAP_UHH_SYSCONFIG_SOFTRESET);
-	while (!(ohci_omap_readl(omap->uhh_base, OMAP_UHH_SYSSTATUS)
-				& OMAP_UHH_SYSSTATUS_UHHRESETDONE)) {
-		cpu_relax();
-
-		if (time_after(jiffies, timeout))
-			dev_dbg(omap->dev, "operation timed out\n");
-	}
-
-	while (!(ohci_omap_readl(omap->uhh_base, OMAP_UHH_SYSSTATUS)
-				& OMAP_UHH_SYSSTATUS_OHCIRESETDONE)) {
-		cpu_relax();
-
-		if (time_after(jiffies, timeout))
-			dev_dbg(omap->dev, "operation timed out\n");
-	}
-
-	while (!(ohci_omap_readl(omap->uhh_base, OMAP_UHH_SYSSTATUS)
-				& OMAP_UHH_SYSSTATUS_EHCIRESETDONE)) {
-		cpu_relax();
-
-		if (time_after(jiffies, timeout))
-			dev_dbg(omap->dev, "operation timed out\n");
-	}
-
-	ohci_omap_writel(omap->tll_base, OMAP_USBTLL_SYSCONFIG, (1 << 1));
-
-	while (!(ohci_omap_readl(omap->tll_base, OMAP_USBTLL_SYSSTATUS)
-				& (1 << 0))) {
-		cpu_relax();
-
-		if (time_after(jiffies, timeout))
-			dev_dbg(omap->dev, "operation timed out\n");
-	}
-
-	ohci_omap3_clock_power(omap, 0);
-
-	if (omap->usbtll_fck != NULL) {
-		clk_put(omap->usbtll_fck);
-		omap->usbtll_fck = NULL;
-	}
-
-	if (omap->usbhost_ick != NULL) {
-		clk_put(omap->usbhost_ick);
-		omap->usbhost_ick = NULL;
-	}
-
-	if (omap->usbhost1_48m_fck != NULL) {
-		clk_put(omap->usbhost1_48m_fck);
-		omap->usbhost1_48m_fck = NULL;
-	}
-
-	if (omap->usbhost2_120m_fck != NULL) {
-		clk_put(omap->usbhost2_120m_fck);
-		omap->usbhost2_120m_fck = NULL;
-	}
-
-	if (omap->usbtll_ick != NULL) {
-		clk_put(omap->usbtll_ick);
-		omap->usbtll_ick = NULL;
-	}
-
-	dev_dbg(omap->dev, "Clock to USB host has been disabled\n");
-}
-
-/*-------------------------------------------------------------------------*/
-
 static const struct hc_driver ohci_omap3_hc_driver = {
 	.description =		hcd_name,
 	.product_desc =		"OMAP3 OHCI Host Controller",
@@ -580,107 +126,77 @@ static const struct hc_driver ohci_omap3_hc_driver = {
  */
 static int __devinit ohci_hcd_omap3_probe(struct platform_device *pdev)
 {
-	struct ohci_hcd_omap_platform_data *pdata = pdev->dev.platform_data;
-	struct ohci_hcd_omap3 *omap;
-	struct resource *res;
-	struct usb_hcd *hcd;
-	int ret = -ENODEV;
-	int irq;
+	struct device		*dev = &pdev->dev;
+	struct usb_hcd		*hcd = NULL;
+	void __iomem		*regs = NULL;
+	struct resource		*res;
+	int			ret = -ENODEV;
+	int			irq;
 
 	if (usb_disabled())
-		goto err_disabled;
+		goto err_end;
 
-	if (!pdata) {
-		dev_dbg(&pdev->dev, "missing platform_data\n");
-		goto err_pdata;
+	if (!dev->parent) {
+		dev_err(dev, "Missing parent device\n");
+		return -ENODEV;
 	}
 
-	irq = platform_get_irq(pdev, 0);
+	irq = platform_get_irq_byname(pdev, "ohci-irq");
+	if (irq < 0) {
+		dev_err(dev, "OHCI irq failed\n");
+		return -ENODEV;
+	}
 
-	omap = kzalloc(sizeof(*omap), GFP_KERNEL);
-	if (!omap) {
-		ret = -ENOMEM;
-		goto err_disabled;
+	res = platform_get_resource_byname(pdev,
+				IORESOURCE_MEM, "ohci");
+	if (!ret) {
+		dev_err(dev, "UHH OHCI get resource failed\n");
+		return -ENOMEM;
 	}
 
-	hcd = usb_create_hcd(&ohci_omap3_hc_driver, &pdev->dev,
-			dev_name(&pdev->dev));
-	if (!hcd) {
-		ret = -ENOMEM;
-		goto err_create_hcd;
+	regs = ioremap(res->start, resource_size(res));
+	if (!regs) {
+		dev_err(dev, "UHH OHCI ioremap failed\n");
+		return -ENOMEM;
 	}
 
-	platform_set_drvdata(pdev, omap);
-	omap->dev		= &pdev->dev;
-	omap->port_mode[0]	= pdata->port_mode[0];
-	omap->port_mode[1]	= pdata->port_mode[1];
-	omap->port_mode[2]	= pdata->port_mode[2];
-	omap->es2_compatibility	= pdata->es2_compatibility;
-	omap->ohci		= hcd_to_ohci(hcd);
 
-	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	hcd = usb_create_hcd(&ohci_omap3_hc_driver, dev,
+			dev_name(dev));
+	if (!hcd) {
+		dev_err(dev, "usb_create_hcd failed\n");
+		goto err_io;
+	}
 
 	hcd->rsrc_start = res->start;
 	hcd->rsrc_len = resource_size(res);
+	hcd->regs =  regs;
 
-	hcd->regs = ioremap(hcd->rsrc_start, hcd->rsrc_len);
-	if (!hcd->regs) {
-		dev_err(&pdev->dev, "OHCI ioremap failed\n");
-		ret = -ENOMEM;
-		goto err_ioremap;
-	}
-
-	res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
-	omap->uhh_base = ioremap(res->start, resource_size(res));
-	if (!omap->uhh_base) {
-		dev_err(&pdev->dev, "UHH ioremap failed\n");
-		ret = -ENOMEM;
-		goto err_uhh_ioremap;
-	}
-
-	res = platform_get_resource(pdev, IORESOURCE_MEM, 2);
-	omap->tll_base = ioremap(res->start, resource_size(res));
-	if (!omap->tll_base) {
-		dev_err(&pdev->dev, "TLL ioremap failed\n");
-		ret = -ENOMEM;
-		goto err_tll_ioremap;
-	}
-
-	ret = omap3_start_ohci(omap, hcd);
+	ret = omap_usbhs_enable(dev);
 	if (ret) {
-		dev_dbg(&pdev->dev, "failed to start ohci\n");
-		goto err_start;
+		dev_dbg(dev, "failed to start ohci\n");
+		goto err_end;
 	}
 
-	ohci_hcd_init(omap->ohci);
+	ohci_hcd_init(hcd_to_ohci(hcd));
 
 	ret = usb_add_hcd(hcd, irq, IRQF_DISABLED);
 	if (ret) {
-		dev_dbg(&pdev->dev, "failed to add hcd with err %d\n", ret);
+		dev_dbg(dev, "failed to add hcd with err %d\n", ret);
 		goto err_add_hcd;
 	}
 
 	return 0;
 
 err_add_hcd:
-	omap3_stop_ohci(omap, hcd);
-
-err_start:
-	iounmap(omap->tll_base);
-
-err_tll_ioremap:
-	iounmap(omap->uhh_base);
-
-err_uhh_ioremap:
-	iounmap(hcd->regs);
+	omap_usbhs_disable(dev);
 
-err_ioremap:
+err_end:
 	usb_put_hcd(hcd);
 
-err_create_hcd:
-	kfree(omap);
-err_pdata:
-err_disabled:
+err_io:
+	iounmap(regs);
+
 	return ret;
 }
 
@@ -699,24 +215,20 @@ err_disabled:
  */
 static int __devexit ohci_hcd_omap3_remove(struct platform_device *pdev)
 {
-	struct ohci_hcd_omap3 *omap = platform_get_drvdata(pdev);
-	struct usb_hcd *hcd = ohci_to_hcd(omap->ohci);
+	struct device *dev	= &pdev->dev;
+	struct usb_hcd *hcd	= dev_get_drvdata(dev);
 
-	usb_remove_hcd(hcd);
-	omap3_stop_ohci(omap, hcd);
 	iounmap(hcd->regs);
-	iounmap(omap->tll_base);
-	iounmap(omap->uhh_base);
+	usb_remove_hcd(hcd);
+	omap_usbhs_disable(dev);
 	usb_put_hcd(hcd);
-	kfree(omap);
 
 	return 0;
 }
 
 static void ohci_hcd_omap3_shutdown(struct platform_device *pdev)
 {
-	struct ohci_hcd_omap3 *omap = platform_get_drvdata(pdev);
-	struct usb_hcd *hcd = ohci_to_hcd(omap->ohci);
+	struct usb_hcd *hcd = dev_get_drvdata(&pdev->dev);
 
 	if (hcd->driver->shutdown)
 		hcd->driver->shutdown(hcd);
diff --git a/drivers/usb/host/ohci-pci.c b/drivers/usb/host/ohci-pci.c
index 36ee9a666e93..d84d6f0314f9 100644
--- a/drivers/usb/host/ohci-pci.c
+++ b/drivers/usb/host/ohci-pci.c
@@ -22,24 +22,6 @@
 #include <linux/io.h>
 
 
-/* constants used to work around PM-related transfer
- * glitches in some AMD 700 series southbridges
- */
-#define AB_REG_BAR	0xf0
-#define AB_INDX(addr)	((addr) + 0x00)
-#define AB_DATA(addr)	((addr) + 0x04)
-#define AX_INDXC	0X30
-#define AX_DATAC	0x34
-
-#define NB_PCIE_INDX_ADDR	0xe0
-#define NB_PCIE_INDX_DATA	0xe4
-#define PCIE_P_CNTL		0x10040
-#define BIF_NB			0x10002
-
-static struct pci_dev *amd_smbus_dev;
-static struct pci_dev *amd_hb_dev;
-static int amd_ohci_iso_count;
-
 /*-------------------------------------------------------------------------*/
 
 static int broken_suspend(struct usb_hcd *hcd)
@@ -168,15 +150,18 @@ static int ohci_quirk_nec(struct usb_hcd *hcd)
 static int ohci_quirk_amd700(struct usb_hcd *hcd)
 {
 	struct ohci_hcd *ohci = hcd_to_ohci(hcd);
-	u8 rev = 0;
+	struct pci_dev *amd_smbus_dev;
+	u8 rev;
 
-	if (!amd_smbus_dev)
-		amd_smbus_dev = pci_get_device(PCI_VENDOR_ID_ATI,
-				PCI_DEVICE_ID_ATI_SBX00_SMBUS, NULL);
+	if (usb_amd_find_chipset_info())
+		ohci->flags |= OHCI_QUIRK_AMD_PLL;
+
+	amd_smbus_dev = pci_get_device(PCI_VENDOR_ID_ATI,
+			PCI_DEVICE_ID_ATI_SBX00_SMBUS, NULL);
 	if (!amd_smbus_dev)
 		return 0;
 
-	pci_read_config_byte(amd_smbus_dev, PCI_REVISION_ID, &rev);
+	rev = amd_smbus_dev->revision;
 
 	/* SB800 needs pre-fetch fix */
 	if ((rev >= 0x40) && (rev <= 0x4f)) {
@@ -184,19 +169,8 @@ static int ohci_quirk_amd700(struct usb_hcd *hcd)
 		ohci_dbg(ohci, "enabled AMD prefetch quirk\n");
 	}
 
-	if ((rev > 0x3b) || (rev < 0x30)) {
-		pci_dev_put(amd_smbus_dev);
-		amd_smbus_dev = NULL;
-		return 0;
-	}
-
-	amd_ohci_iso_count++;
-
-	if (!amd_hb_dev)
-		amd_hb_dev = pci_get_device(PCI_VENDOR_ID_AMD, 0x9600, NULL);
-
-	ohci->flags |= OHCI_QUIRK_AMD_ISO;
-	ohci_dbg(ohci, "enabled AMD ISO transfers quirk\n");
+	pci_dev_put(amd_smbus_dev);
+	amd_smbus_dev = NULL;
 
 	return 0;
 }
@@ -215,74 +189,6 @@ static int ohci_quirk_nvidia_shutdown(struct usb_hcd *hcd)
 	return 0;
 }
 
-/*
- * The hardware normally enables the A-link power management feature, which
- * lets the system lower the power consumption in idle states.
- *
- * Assume the system is configured to have USB 1.1 ISO transfers going
- * to or from a USB device.  Without this quirk, that stream may stutter
- * or have breaks occasionally.  For transfers going to speakers, this
- * makes a very audible mess...
- *
- * That audio playback corruption is due to the audio stream getting
- * interrupted occasionally when the link goes in lower power state
- * This USB quirk prevents the link going into that lower power state
- * during audio playback or other ISO operations.
- */
-static void quirk_amd_pll(int on)
-{
-	u32 addr;
-	u32 val;
-	u32 bit = (on > 0) ? 1 : 0;
-
-	pci_read_config_dword(amd_smbus_dev, AB_REG_BAR, &addr);
-
-	/* BIT names/meanings are NDA-protected, sorry ... */
-
-	outl(AX_INDXC, AB_INDX(addr));
-	outl(0x40, AB_DATA(addr));
-	outl(AX_DATAC, AB_INDX(addr));
-	val = inl(AB_DATA(addr));
-	val &= ~((1 << 3) | (1 << 4) | (1 << 9));
-	val |= (bit << 3) | ((!bit) << 4) | ((!bit) << 9);
-	outl(val, AB_DATA(addr));
-
-	if (amd_hb_dev) {
-		addr = PCIE_P_CNTL;
-		pci_write_config_dword(amd_hb_dev, NB_PCIE_INDX_ADDR, addr);
-
-		pci_read_config_dword(amd_hb_dev, NB_PCIE_INDX_DATA, &val);
-		val &= ~(1 | (1 << 3) | (1 << 4) | (1 << 9) | (1 << 12));
-		val |= bit | (bit << 3) | (bit << 12);
-		val |= ((!bit) << 4) | ((!bit) << 9);
-		pci_write_config_dword(amd_hb_dev, NB_PCIE_INDX_DATA, val);
-
-		addr = BIF_NB;
-		pci_write_config_dword(amd_hb_dev, NB_PCIE_INDX_ADDR, addr);
-
-		pci_read_config_dword(amd_hb_dev, NB_PCIE_INDX_DATA, &val);
-		val &= ~(1 << 8);
-		val |= bit << 8;
-		pci_write_config_dword(amd_hb_dev, NB_PCIE_INDX_DATA, val);
-	}
-}
-
-static void amd_iso_dev_put(void)
-{
-	amd_ohci_iso_count--;
-	if (amd_ohci_iso_count == 0) {
-		if (amd_smbus_dev) {
-			pci_dev_put(amd_smbus_dev);
-			amd_smbus_dev = NULL;
-		}
-		if (amd_hb_dev) {
-			pci_dev_put(amd_hb_dev);
-			amd_hb_dev = NULL;
-		}
-	}
-
-}
-
 static void sb800_prefetch(struct ohci_hcd *ohci, int on)
 {
 	struct pci_dev *pdev;
diff --git a/drivers/usb/host/ohci-q.c b/drivers/usb/host/ohci-q.c
index 83094d067e0f..dd24fc115e48 100644
--- a/drivers/usb/host/ohci-q.c
+++ b/drivers/usb/host/ohci-q.c
@@ -52,7 +52,7 @@ __acquires(ohci->lock)
 		ohci_to_hcd(ohci)->self.bandwidth_isoc_reqs--;
 		if (ohci_to_hcd(ohci)->self.bandwidth_isoc_reqs == 0) {
 			if (quirk_amdiso(ohci))
-				quirk_amd_pll(1);
+				usb_amd_quirk_pll_enable();
 			if (quirk_amdprefetch(ohci))
 				sb800_prefetch(ohci, 0);
 		}
@@ -686,7 +686,7 @@ static void td_submit_urb (
 		}
 		if (ohci_to_hcd(ohci)->self.bandwidth_isoc_reqs == 0) {
 			if (quirk_amdiso(ohci))
-				quirk_amd_pll(0);
+				usb_amd_quirk_pll_disable();
 			if (quirk_amdprefetch(ohci))
 				sb800_prefetch(ohci, 1);
 		}
diff --git a/drivers/usb/host/ohci.h b/drivers/usb/host/ohci.h
index 51facb985c84..bad11a72c202 100644
--- a/drivers/usb/host/ohci.h
+++ b/drivers/usb/host/ohci.h
@@ -401,7 +401,7 @@ struct ohci_hcd {
 #define	OHCI_QUIRK_NEC		0x40			/* lost interrupts */
 #define	OHCI_QUIRK_FRAME_NO	0x80			/* no big endian frame_no shift */
 #define	OHCI_QUIRK_HUB_POWER	0x100			/* distrust firmware power/oc setup */
-#define	OHCI_QUIRK_AMD_ISO	0x200			/* ISO transfers*/
+#define	OHCI_QUIRK_AMD_PLL	0x200			/* AMD PLL quirk*/
 #define	OHCI_QUIRK_AMD_PREFETCH	0x400			/* pre-fetch for ISO transfer */
 #define	OHCI_QUIRK_SHUTDOWN	0x800			/* nVidia power bug */
 	// there are also chip quirks/bugs in init logic
@@ -433,7 +433,7 @@ static inline int quirk_zfmicro(struct ohci_hcd *ohci)
 }
 static inline int quirk_amdiso(struct ohci_hcd *ohci)
 {
-	return ohci->flags & OHCI_QUIRK_AMD_ISO;
+	return ohci->flags & OHCI_QUIRK_AMD_PLL;
 }
 static inline int quirk_amdprefetch(struct ohci_hcd *ohci)
 {
diff --git a/drivers/usb/host/oxu210hp-hcd.c b/drivers/usb/host/oxu210hp-hcd.c
index e0cb12b573f9..38193f4e980e 100644
--- a/drivers/usb/host/oxu210hp-hcd.c
+++ b/drivers/usb/host/oxu210hp-hcd.c
@@ -451,9 +451,9 @@ static void ehci_hub_descriptor(struct oxu_hcd *oxu,
 	temp = 1 + (ports / 8);
 	desc->bDescLength = 7 + 2 * temp;
 
-	/* two bitmaps:  ports removable, and usb 1.0 legacy PortPwrCtrlMask */
-	memset(&desc->bitmap[0], 0, temp);
-	memset(&desc->bitmap[temp], 0xff, temp);
+	/* ports removable, and usb 1.0 legacy PortPwrCtrlMask */
+	memset(&desc->u.hs.DeviceRemovable[0], 0, temp);
+	memset(&desc->u.hs.DeviceRemovable[temp], 0xff, temp);
 
 	temp = 0x0008;			/* per-port overcurrent reporting */
 	if (HCS_PPC(oxu->hcs_params))
diff --git a/drivers/usb/host/pci-quirks.c b/drivers/usb/host/pci-quirks.c
index 4c502c890ebd..1d586d4f7b56 100644
--- a/drivers/usb/host/pci-quirks.c
+++ b/drivers/usb/host/pci-quirks.c
@@ -52,6 +52,264 @@
 #define EHCI_USBLEGCTLSTS	4		/* legacy control/status */
 #define EHCI_USBLEGCTLSTS_SOOE	(1 << 13)	/* SMI on ownership change */
 
+/* AMD quirk use */
+#define	AB_REG_BAR_LOW		0xe0
+#define	AB_REG_BAR_HIGH		0xe1
+#define	AB_REG_BAR_SB700	0xf0
+#define	AB_INDX(addr)		((addr) + 0x00)
+#define	AB_DATA(addr)		((addr) + 0x04)
+#define	AX_INDXC		0x30
+#define	AX_DATAC		0x34
+
+#define	NB_PCIE_INDX_ADDR	0xe0
+#define	NB_PCIE_INDX_DATA	0xe4
+#define	PCIE_P_CNTL		0x10040
+#define	BIF_NB			0x10002
+#define	NB_PIF0_PWRDOWN_0	0x01100012
+#define	NB_PIF0_PWRDOWN_1	0x01100013
+
+static struct amd_chipset_info {
+	struct pci_dev	*nb_dev;
+	struct pci_dev	*smbus_dev;
+	int nb_type;
+	int sb_type;
+	int isoc_reqs;
+	int probe_count;
+	int probe_result;
+} amd_chipset;
+
+static DEFINE_SPINLOCK(amd_lock);
+
+int usb_amd_find_chipset_info(void)
+{
+	u8 rev = 0;
+	unsigned long flags;
+
+	spin_lock_irqsave(&amd_lock, flags);
+
+	amd_chipset.probe_count++;
+	/* probe only once */
+	if (amd_chipset.probe_count > 1) {
+		spin_unlock_irqrestore(&amd_lock, flags);
+		return amd_chipset.probe_result;
+	}
+
+	amd_chipset.smbus_dev = pci_get_device(PCI_VENDOR_ID_ATI, 0x4385, NULL);
+	if (amd_chipset.smbus_dev) {
+		rev = amd_chipset.smbus_dev->revision;
+		if (rev >= 0x40)
+			amd_chipset.sb_type = 1;
+		else if (rev >= 0x30 && rev <= 0x3b)
+			amd_chipset.sb_type = 3;
+	} else {
+		amd_chipset.smbus_dev = pci_get_device(PCI_VENDOR_ID_AMD,
+							0x780b, NULL);
+		if (!amd_chipset.smbus_dev) {
+			spin_unlock_irqrestore(&amd_lock, flags);
+			return 0;
+		}
+		rev = amd_chipset.smbus_dev->revision;
+		if (rev >= 0x11 && rev <= 0x18)
+			amd_chipset.sb_type = 2;
+	}
+
+	if (amd_chipset.sb_type == 0) {
+		if (amd_chipset.smbus_dev) {
+			pci_dev_put(amd_chipset.smbus_dev);
+			amd_chipset.smbus_dev = NULL;
+		}
+		spin_unlock_irqrestore(&amd_lock, flags);
+		return 0;
+	}
+
+	amd_chipset.nb_dev = pci_get_device(PCI_VENDOR_ID_AMD, 0x9601, NULL);
+	if (amd_chipset.nb_dev) {
+		amd_chipset.nb_type = 1;
+	} else {
+		amd_chipset.nb_dev = pci_get_device(PCI_VENDOR_ID_AMD,
+							0x1510, NULL);
+		if (amd_chipset.nb_dev) {
+			amd_chipset.nb_type = 2;
+		} else  {
+			amd_chipset.nb_dev = pci_get_device(PCI_VENDOR_ID_AMD,
+								0x9600, NULL);
+			if (amd_chipset.nb_dev)
+				amd_chipset.nb_type = 3;
+		}
+	}
+
+	amd_chipset.probe_result = 1;
+	printk(KERN_DEBUG "QUIRK: Enable AMD PLL fix\n");
+
+	spin_unlock_irqrestore(&amd_lock, flags);
+	return amd_chipset.probe_result;
+}
+EXPORT_SYMBOL_GPL(usb_amd_find_chipset_info);
+
+/*
+ * The hardware normally enables the A-link power management feature, which
+ * lets the system lower the power consumption in idle states.
+ *
+ * This USB quirk prevents the link going into that lower power state
+ * during isochronous transfers.
+ *
+ * Without this quirk, isochronous stream on OHCI/EHCI/xHCI controllers of
+ * some AMD platforms may stutter or have breaks occasionally.
+ */
+static void usb_amd_quirk_pll(int disable)
+{
+	u32 addr, addr_low, addr_high, val;
+	u32 bit = disable ? 0 : 1;
+	unsigned long flags;
+
+	spin_lock_irqsave(&amd_lock, flags);
+
+	if (disable) {
+		amd_chipset.isoc_reqs++;
+		if (amd_chipset.isoc_reqs > 1) {
+			spin_unlock_irqrestore(&amd_lock, flags);
+			return;
+		}
+	} else {
+		amd_chipset.isoc_reqs--;
+		if (amd_chipset.isoc_reqs > 0) {
+			spin_unlock_irqrestore(&amd_lock, flags);
+			return;
+		}
+	}
+
+	if (amd_chipset.sb_type == 1 || amd_chipset.sb_type == 2) {
+		outb_p(AB_REG_BAR_LOW, 0xcd6);
+		addr_low = inb_p(0xcd7);
+		outb_p(AB_REG_BAR_HIGH, 0xcd6);
+		addr_high = inb_p(0xcd7);
+		addr = addr_high << 8 | addr_low;
+
+		outl_p(0x30, AB_INDX(addr));
+		outl_p(0x40, AB_DATA(addr));
+		outl_p(0x34, AB_INDX(addr));
+		val = inl_p(AB_DATA(addr));
+	} else if (amd_chipset.sb_type == 3) {
+		pci_read_config_dword(amd_chipset.smbus_dev,
+					AB_REG_BAR_SB700, &addr);
+		outl(AX_INDXC, AB_INDX(addr));
+		outl(0x40, AB_DATA(addr));
+		outl(AX_DATAC, AB_INDX(addr));
+		val = inl(AB_DATA(addr));
+	} else {
+		spin_unlock_irqrestore(&amd_lock, flags);
+		return;
+	}
+
+	if (disable) {
+		val &= ~0x08;
+		val |= (1 << 4) | (1 << 9);
+	} else {
+		val |= 0x08;
+		val &= ~((1 << 4) | (1 << 9));
+	}
+	outl_p(val, AB_DATA(addr));
+
+	if (!amd_chipset.nb_dev) {
+		spin_unlock_irqrestore(&amd_lock, flags);
+		return;
+	}
+
+	if (amd_chipset.nb_type == 1 || amd_chipset.nb_type == 3) {
+		addr = PCIE_P_CNTL;
+		pci_write_config_dword(amd_chipset.nb_dev,
+					NB_PCIE_INDX_ADDR, addr);
+		pci_read_config_dword(amd_chipset.nb_dev,
+					NB_PCIE_INDX_DATA, &val);
+
+		val &= ~(1 | (1 << 3) | (1 << 4) | (1 << 9) | (1 << 12));
+		val |= bit | (bit << 3) | (bit << 12);
+		val |= ((!bit) << 4) | ((!bit) << 9);
+		pci_write_config_dword(amd_chipset.nb_dev,
+					NB_PCIE_INDX_DATA, val);
+
+		addr = BIF_NB;
+		pci_write_config_dword(amd_chipset.nb_dev,
+					NB_PCIE_INDX_ADDR, addr);
+		pci_read_config_dword(amd_chipset.nb_dev,
+					NB_PCIE_INDX_DATA, &val);
+		val &= ~(1 << 8);
+		val |= bit << 8;
+
+		pci_write_config_dword(amd_chipset.nb_dev,
+					NB_PCIE_INDX_DATA, val);
+	} else if (amd_chipset.nb_type == 2) {
+		addr = NB_PIF0_PWRDOWN_0;
+		pci_write_config_dword(amd_chipset.nb_dev,
+					NB_PCIE_INDX_ADDR, addr);
+		pci_read_config_dword(amd_chipset.nb_dev,
+					NB_PCIE_INDX_DATA, &val);
+		if (disable)
+			val &= ~(0x3f << 7);
+		else
+			val |= 0x3f << 7;
+
+		pci_write_config_dword(amd_chipset.nb_dev,
+					NB_PCIE_INDX_DATA, val);
+
+		addr = NB_PIF0_PWRDOWN_1;
+		pci_write_config_dword(amd_chipset.nb_dev,
+					NB_PCIE_INDX_ADDR, addr);
+		pci_read_config_dword(amd_chipset.nb_dev,
+					NB_PCIE_INDX_DATA, &val);
+		if (disable)
+			val &= ~(0x3f << 7);
+		else
+			val |= 0x3f << 7;
+
+		pci_write_config_dword(amd_chipset.nb_dev,
+					NB_PCIE_INDX_DATA, val);
+	}
+
+	spin_unlock_irqrestore(&amd_lock, flags);
+	return;
+}
+
+void usb_amd_quirk_pll_disable(void)
+{
+	usb_amd_quirk_pll(1);
+}
+EXPORT_SYMBOL_GPL(usb_amd_quirk_pll_disable);
+
+void usb_amd_quirk_pll_enable(void)
+{
+	usb_amd_quirk_pll(0);
+}
+EXPORT_SYMBOL_GPL(usb_amd_quirk_pll_enable);
+
+void usb_amd_dev_put(void)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&amd_lock, flags);
+
+	amd_chipset.probe_count--;
+	if (amd_chipset.probe_count > 0) {
+		spin_unlock_irqrestore(&amd_lock, flags);
+		return;
+	}
+
+	if (amd_chipset.nb_dev) {
+		pci_dev_put(amd_chipset.nb_dev);
+		amd_chipset.nb_dev = NULL;
+	}
+	if (amd_chipset.smbus_dev) {
+		pci_dev_put(amd_chipset.smbus_dev);
+		amd_chipset.smbus_dev = NULL;
+	}
+	amd_chipset.nb_type = 0;
+	amd_chipset.sb_type = 0;
+	amd_chipset.isoc_reqs = 0;
+	amd_chipset.probe_result = 0;
+
+	spin_unlock_irqrestore(&amd_lock, flags);
+}
+EXPORT_SYMBOL_GPL(usb_amd_dev_put);
 
 /*
  * Make sure the controller is completely inactive, unable to
diff --git a/drivers/usb/host/pci-quirks.h b/drivers/usb/host/pci-quirks.h
index 1564edfff6fe..6ae9f78e9938 100644
--- a/drivers/usb/host/pci-quirks.h
+++ b/drivers/usb/host/pci-quirks.h
@@ -1,7 +1,17 @@
 #ifndef __LINUX_USB_PCI_QUIRKS_H
 #define __LINUX_USB_PCI_QUIRKS_H
 
+#ifdef CONFIG_PCI
 void uhci_reset_hc(struct pci_dev *pdev, unsigned long base);
 int uhci_check_and_reset_hc(struct pci_dev *pdev, unsigned long base);
+int usb_amd_find_chipset_info(void);
+void usb_amd_dev_put(void);
+void usb_amd_quirk_pll_disable(void);
+void usb_amd_quirk_pll_enable(void);
+#else
+static inline void usb_amd_quirk_pll_disable(void) {}
+static inline void usb_amd_quirk_pll_enable(void) {}
+static inline void usb_amd_dev_put(void) {}
+#endif  /* CONFIG_PCI */
 
 #endif  /*  __LINUX_USB_PCI_QUIRKS_H  */
diff --git a/drivers/usb/host/r8a66597-hcd.c b/drivers/usb/host/r8a66597-hcd.c
index 3076b1cc05df..db6f8b9c19b6 100644
--- a/drivers/usb/host/r8a66597-hcd.c
+++ b/drivers/usb/host/r8a66597-hcd.c
@@ -2150,8 +2150,9 @@ static void r8a66597_hub_descriptor(struct r8a66597 *r8a66597,
 	desc->bDescLength = 9;
 	desc->bPwrOn2PwrGood = 0;
 	desc->wHubCharacteristics = cpu_to_le16(0x0011);
-	desc->bitmap[0] = ((1 << r8a66597->max_root_hub) - 1) << 1;
-	desc->bitmap[1] = ~0;
+	desc->u.hs.DeviceRemovable[0] =
+		((1 << r8a66597->max_root_hub) - 1) << 1;
+	desc->u.hs.DeviceRemovable[1] = ~0;
 }
 
 static int r8a66597_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue,
diff --git a/drivers/usb/host/sl811-hcd.c b/drivers/usb/host/sl811-hcd.c
index 2e9602a10e9b..18b7099a8125 100644
--- a/drivers/usb/host/sl811-hcd.c
+++ b/drivers/usb/host/sl811-hcd.c
@@ -1111,9 +1111,9 @@ sl811h_hub_descriptor (
 
 	desc->wHubCharacteristics = cpu_to_le16(temp);
 
-	/* two bitmaps:  ports removable, and legacy PortPwrCtrlMask */
-	desc->bitmap[0] = 0 << 1;
-	desc->bitmap[1] = ~0;
+	/* ports removable, and legacy PortPwrCtrlMask */
+	desc->u.hs.DeviceRemovable[0] = 0 << 1;
+	desc->u.hs.DeviceRemovable[1] = ~0;
 }
 
 static void
diff --git a/drivers/usb/host/u132-hcd.c b/drivers/usb/host/u132-hcd.c
index fab764946c74..b4785934e091 100644
--- a/drivers/usb/host/u132-hcd.c
+++ b/drivers/usb/host/u132-hcd.c
@@ -2604,13 +2604,14 @@ static int u132_roothub_descriptor(struct u132 *u132,
 	retval = u132_read_pcimem(u132, roothub.b, &rh_b);
 	if (retval)
 		return retval;
-	memset(desc->bitmap, 0xff, sizeof(desc->bitmap));
-	desc->bitmap[0] = rh_b & RH_B_DR;
+	memset(desc->u.hs.DeviceRemovable, 0xff,
+			sizeof(desc->u.hs.DeviceRemovable));
+	desc->u.hs.DeviceRemovable[0] = rh_b & RH_B_DR;
 	if (u132->num_ports > 7) {
-		desc->bitmap[1] = (rh_b & RH_B_DR) >> 8;
-		desc->bitmap[2] = 0xff;
+		desc->u.hs.DeviceRemovable[1] = (rh_b & RH_B_DR) >> 8;
+		desc->u.hs.DeviceRemovable[2] = 0xff;
 	} else
-		desc->bitmap[1] = 0xff;
+		desc->u.hs.DeviceRemovable[1] = 0xff;
 	return 0;
 }
 
diff --git a/drivers/usb/host/uhci-hcd.c b/drivers/usb/host/uhci-hcd.c
index cee867829ec9..4f65b14e5e08 100644
--- a/drivers/usb/host/uhci-hcd.c
+++ b/drivers/usb/host/uhci-hcd.c
@@ -471,7 +471,7 @@ static irqreturn_t uhci_irq(struct usb_hcd *hcd)
 
 /*
  * Store the current frame number in uhci->frame_number if the controller
- * is runnning.  Expand from 11 bits (of which we use only 10) to a
+ * is running.  Expand from 11 bits (of which we use only 10) to a
  * full-sized integer.
  *
  * Like many other parts of the driver, this code relies on being polled
diff --git a/drivers/usb/host/xhci-ext-caps.h b/drivers/usb/host/xhci-ext-caps.h
index 78c4edac1db1..ce5c9e51748e 100644
--- a/drivers/usb/host/xhci-ext-caps.h
+++ b/drivers/usb/host/xhci-ext-caps.h
@@ -19,8 +19,8 @@
  * along with this program; if not, write to the Free Software Foundation,
  * Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  */
-/* Up to 16 microframes to halt an HC - one microframe is 125 microsectonds */
-#define XHCI_MAX_HALT_USEC	(16*125)
+/* Up to 16 ms to halt an HC */
+#define XHCI_MAX_HALT_USEC	(16*1000)
 /* HC not running - set to 1 when run/stop bit is cleared. */
 #define XHCI_STS_HALT		(1<<0)
 
diff --git a/drivers/usb/host/xhci-hub.c b/drivers/usb/host/xhci-hub.c
index 5d963e350494..a78f2ebd11b7 100644
--- a/drivers/usb/host/xhci-hub.c
+++ b/drivers/usb/host/xhci-hub.c
@@ -28,27 +28,15 @@
 #define	PORT_RWC_BITS	(PORT_CSC | PORT_PEC | PORT_WRC | PORT_OCC | \
 			 PORT_RC | PORT_PLC | PORT_PE)
 
-static void xhci_hub_descriptor(struct xhci_hcd *xhci,
-		struct usb_hub_descriptor *desc)
+static void xhci_common_hub_descriptor(struct xhci_hcd *xhci,
+		struct usb_hub_descriptor *desc, int ports)
 {
-	int ports;
 	u16 temp;
 
-	ports = HCS_MAX_PORTS(xhci->hcs_params1);
-
-	/* USB 3.0 hubs have a different descriptor, but we fake this for now */
-	desc->bDescriptorType = 0x29;
 	desc->bPwrOn2PwrGood = 10;	/* xhci section 5.4.9 says 20ms max */
 	desc->bHubContrCurrent = 0;
 
 	desc->bNbrPorts = ports;
-	temp = 1 + (ports / 8);
-	desc->bDescLength = 7 + 2 * temp;
-
-	/* Why does core/hcd.h define bitmap?  It's just confusing. */
-	memset(&desc->DeviceRemovable[0], 0, temp);
-	memset(&desc->DeviceRemovable[temp], 0xff, temp);
-
 	/* Ugh, these should be #defines, FIXME */
 	/* Using table 11-13 in USB 2.0 spec. */
 	temp = 0;
@@ -65,14 +53,108 @@ static void xhci_hub_descriptor(struct xhci_hcd *xhci,
 	desc->wHubCharacteristics = (__force __u16) cpu_to_le16(temp);
 }
 
+/* Fill in the USB 2.0 roothub descriptor */
+static void xhci_usb2_hub_descriptor(struct usb_hcd *hcd, struct xhci_hcd *xhci,
+		struct usb_hub_descriptor *desc)
+{
+	int ports;
+	u16 temp;
+	__u8 port_removable[(USB_MAXCHILDREN + 1 + 7) / 8];
+	u32 portsc;
+	unsigned int i;
+
+	ports = xhci->num_usb2_ports;
+
+	xhci_common_hub_descriptor(xhci, desc, ports);
+	desc->bDescriptorType = 0x29;
+	temp = 1 + (ports / 8);
+	desc->bDescLength = 7 + 2 * temp;
+
+	/* The Device Removable bits are reported on a byte granularity.
+	 * If the port doesn't exist within that byte, the bit is set to 0.
+	 */
+	memset(port_removable, 0, sizeof(port_removable));
+	for (i = 0; i < ports; i++) {
+		portsc = xhci_readl(xhci, xhci->usb3_ports[i]);
+		/* If a device is removable, PORTSC reports a 0, same as in the
+		 * hub descriptor DeviceRemovable bits.
+		 */
+		if (portsc & PORT_DEV_REMOVE)
+			/* This math is hairy because bit 0 of DeviceRemovable
+			 * is reserved, and bit 1 is for port 1, etc.
+			 */
+			port_removable[(i + 1) / 8] |= 1 << ((i + 1) % 8);
+	}
+
+	/* ch11.h defines a hub descriptor that has room for USB_MAXCHILDREN
+	 * ports on it.  The USB 2.0 specification says that there are two
+	 * variable length fields at the end of the hub descriptor:
+	 * DeviceRemovable and PortPwrCtrlMask.  But since we can have less than
+	 * USB_MAXCHILDREN ports, we may need to use the DeviceRemovable array
+	 * to set PortPwrCtrlMask bits.  PortPwrCtrlMask must always be set to
+	 * 0xFF, so we initialize the both arrays (DeviceRemovable and
+	 * PortPwrCtrlMask) to 0xFF.  Then we set the DeviceRemovable for each
+	 * set of ports that actually exist.
+	 */
+	memset(desc->u.hs.DeviceRemovable, 0xff,
+			sizeof(desc->u.hs.DeviceRemovable));
+	memset(desc->u.hs.PortPwrCtrlMask, 0xff,
+			sizeof(desc->u.hs.PortPwrCtrlMask));
+
+	for (i = 0; i < (ports + 1 + 7) / 8; i++)
+		memset(&desc->u.hs.DeviceRemovable[i], port_removable[i],
+				sizeof(__u8));
+}
+
+/* Fill in the USB 3.0 roothub descriptor */
+static void xhci_usb3_hub_descriptor(struct usb_hcd *hcd, struct xhci_hcd *xhci,
+		struct usb_hub_descriptor *desc)
+{
+	int ports;
+	u16 port_removable;
+	u32 portsc;
+	unsigned int i;
+
+	ports = xhci->num_usb3_ports;
+	xhci_common_hub_descriptor(xhci, desc, ports);
+	desc->bDescriptorType = 0x2a;
+	desc->bDescLength = 12;
+
+	/* header decode latency should be zero for roothubs,
+	 * see section 4.23.5.2.
+	 */
+	desc->u.ss.bHubHdrDecLat = 0;
+	desc->u.ss.wHubDelay = 0;
+
+	port_removable = 0;
+	/* bit 0 is reserved, bit 1 is for port 1, etc. */
+	for (i = 0; i < ports; i++) {
+		portsc = xhci_readl(xhci, xhci->usb3_ports[i]);
+		if (portsc & PORT_DEV_REMOVE)
+			port_removable |= 1 << (i + 1);
+	}
+	memset(&desc->u.ss.DeviceRemovable,
+			(__force __u16) cpu_to_le16(port_removable),
+			sizeof(__u16));
+}
+
+static void xhci_hub_descriptor(struct usb_hcd *hcd, struct xhci_hcd *xhci,
+		struct usb_hub_descriptor *desc)
+{
+
+	if (hcd->speed == HCD_USB3)
+		xhci_usb3_hub_descriptor(hcd, xhci, desc);
+	else
+		xhci_usb2_hub_descriptor(hcd, xhci, desc);
+
+}
+
 static unsigned int xhci_port_speed(unsigned int port_status)
 {
 	if (DEV_LOWSPEED(port_status))
 		return USB_PORT_STAT_LOW_SPEED;
 	if (DEV_HIGHSPEED(port_status))
 		return USB_PORT_STAT_HIGH_SPEED;
-	if (DEV_SUPERSPEED(port_status))
-		return USB_PORT_STAT_SUPER_SPEED;
 	/*
 	 * FIXME: Yes, we should check for full speed, but the core uses that as
 	 * a default in portspeed() in usb/core/hub.c (which is the only place
@@ -135,17 +217,22 @@ u32 xhci_port_state_to_neutral(u32 state)
 
 /*
  * find slot id based on port number.
+ * @port: The one-based port number from one of the two split roothubs.
  */
-int xhci_find_slot_id_by_port(struct xhci_hcd *xhci, u16 port)
+int xhci_find_slot_id_by_port(struct usb_hcd *hcd, struct xhci_hcd *xhci,
+		u16 port)
 {
 	int slot_id;
 	int i;
+	enum usb_device_speed speed;
 
 	slot_id = 0;
 	for (i = 0; i < MAX_HC_SLOTS; i++) {
 		if (!xhci->devs[i])
 			continue;
-		if (xhci->devs[i]->port == port) {
+		speed = xhci->devs[i]->udev->speed;
+		if (((speed == USB_SPEED_SUPER) == (hcd->speed == HCD_USB3))
+				&& xhci->devs[i]->port == port) {
 			slot_id = i;
 			break;
 		}
@@ -226,11 +313,11 @@ void xhci_ring_device(struct xhci_hcd *xhci, int slot_id)
 	return;
 }
 
-static void xhci_disable_port(struct xhci_hcd *xhci, u16 wIndex,
-		u32 __iomem *addr, u32 port_status)
+static void xhci_disable_port(struct usb_hcd *hcd, struct xhci_hcd *xhci,
+		u16 wIndex, u32 __iomem *addr, u32 port_status)
 {
 	/* Don't allow the USB core to disable SuperSpeed ports. */
-	if (xhci->port_array[wIndex] == 0x03) {
+	if (hcd->speed == HCD_USB3) {
 		xhci_dbg(xhci, "Ignoring request to disable "
 				"SuperSpeed port.\n");
 		return;
@@ -289,10 +376,18 @@ int xhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue,
 	unsigned long flags;
 	u32 temp, temp1, status;
 	int retval = 0;
-	u32 __iomem *addr;
+	u32 __iomem **port_array;
 	int slot_id;
-
-	ports = HCS_MAX_PORTS(xhci->hcs_params1);
+	struct xhci_bus_state *bus_state;
+
+	if (hcd->speed == HCD_USB3) {
+		ports = xhci->num_usb3_ports;
+		port_array = xhci->usb3_ports;
+	} else {
+		ports = xhci->num_usb2_ports;
+		port_array = xhci->usb2_ports;
+	}
+	bus_state = &xhci->bus_state[hcd_index(hcd)];
 
 	spin_lock_irqsave(&xhci->lock, flags);
 	switch (typeReq) {
@@ -301,17 +396,35 @@ int xhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue,
 		memset(buf, 0, 4);
 		break;
 	case GetHubDescriptor:
-		xhci_hub_descriptor(xhci, (struct usb_hub_descriptor *) buf);
+		/* Check to make sure userspace is asking for the USB 3.0 hub
+		 * descriptor for the USB 3.0 roothub.  If not, we stall the
+		 * endpoint, like external hubs do.
+		 */
+		if (hcd->speed == HCD_USB3 &&
+				(wLength < USB_DT_SS_HUB_SIZE ||
+				 wValue != (USB_DT_SS_HUB << 8))) {
+			xhci_dbg(xhci, "Wrong hub descriptor type for "
+					"USB 3.0 roothub.\n");
+			goto error;
+		}
+		xhci_hub_descriptor(hcd, xhci,
+				(struct usb_hub_descriptor *) buf);
 		break;
 	case GetPortStatus:
 		if (!wIndex || wIndex > ports)
 			goto error;
 		wIndex--;
 		status = 0;
-		addr = &xhci->op_regs->port_status_base + NUM_PORT_REGS*(wIndex & 0xff);
-		temp = xhci_readl(xhci, addr);
+		temp = xhci_readl(xhci, port_array[wIndex]);
+		if (temp == 0xffffffff) {
+			retval = -ENODEV;
+			break;
+		}
 		xhci_dbg(xhci, "get port status, actual port %d status  = 0x%x\n", wIndex, temp);
 
+		/* FIXME - should we return a port status value like the USB
+		 * 3.0 external hubs do?
+		 */
 		/* wPortChange bits */
 		if (temp & PORT_CSC)
 			status |= USB_PORT_STAT_C_CONNECTION << 16;
@@ -330,38 +443,33 @@ int xhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue,
 			if ((temp & PORT_RESET) || !(temp & PORT_PE))
 				goto error;
 			if (!DEV_SUPERSPEED(temp) && time_after_eq(jiffies,
-						xhci->resume_done[wIndex])) {
+						bus_state->resume_done[wIndex])) {
 				xhci_dbg(xhci, "Resume USB2 port %d\n",
 					wIndex + 1);
-				xhci->resume_done[wIndex] = 0;
+				bus_state->resume_done[wIndex] = 0;
 				temp1 = xhci_port_state_to_neutral(temp);
 				temp1 &= ~PORT_PLS_MASK;
 				temp1 |= PORT_LINK_STROBE | XDEV_U0;
-				xhci_writel(xhci, temp1, addr);
+				xhci_writel(xhci, temp1, port_array[wIndex]);
 
 				xhci_dbg(xhci, "set port %d resume\n",
 					wIndex + 1);
-				slot_id = xhci_find_slot_id_by_port(xhci,
+				slot_id = xhci_find_slot_id_by_port(hcd, xhci,
 								 wIndex + 1);
 				if (!slot_id) {
 					xhci_dbg(xhci, "slot_id is zero\n");
 					goto error;
 				}
 				xhci_ring_device(xhci, slot_id);
-				xhci->port_c_suspend[wIndex >> 5] |=
-						1 << (wIndex & 31);
-				xhci->suspended_ports[wIndex >> 5] &=
-						~(1 << (wIndex & 31));
+				bus_state->port_c_suspend |= 1 << wIndex;
+				bus_state->suspended_ports &= ~(1 << wIndex);
 			}
 		}
 		if ((temp & PORT_PLS_MASK) == XDEV_U0
 			&& (temp & PORT_POWER)
-			&& (xhci->suspended_ports[wIndex >> 5] &
-			    (1 << (wIndex & 31)))) {
-			xhci->suspended_ports[wIndex >> 5] &=
-					~(1 << (wIndex & 31));
-			xhci->port_c_suspend[wIndex >> 5] |=
-					1 << (wIndex & 31);
+			&& (bus_state->suspended_ports & (1 << wIndex))) {
+			bus_state->suspended_ports &= ~(1 << wIndex);
+			bus_state->port_c_suspend |= 1 << wIndex;
 		}
 		if (temp & PORT_CONNECT) {
 			status |= USB_PORT_STAT_CONNECTION;
@@ -375,7 +483,7 @@ int xhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue,
 			status |= USB_PORT_STAT_RESET;
 		if (temp & PORT_POWER)
 			status |= USB_PORT_STAT_POWER;
-		if (xhci->port_c_suspend[wIndex >> 5] & (1 << (wIndex & 31)))
+		if (bus_state->port_c_suspend & (1 << wIndex))
 			status |= 1 << USB_PORT_FEAT_C_SUSPEND;
 		xhci_dbg(xhci, "Get port status returned 0x%x\n", status);
 		put_unaligned(cpu_to_le32(status), (__le32 *) buf);
@@ -385,12 +493,16 @@ int xhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue,
 		if (!wIndex || wIndex > ports)
 			goto error;
 		wIndex--;
-		addr = &xhci->op_regs->port_status_base + NUM_PORT_REGS*(wIndex & 0xff);
-		temp = xhci_readl(xhci, addr);
+		temp = xhci_readl(xhci, port_array[wIndex]);
+		if (temp == 0xffffffff) {
+			retval = -ENODEV;
+			break;
+		}
 		temp = xhci_port_state_to_neutral(temp);
+		/* FIXME: What new port features do we need to support? */
 		switch (wValue) {
 		case USB_PORT_FEAT_SUSPEND:
-			temp = xhci_readl(xhci, addr);
+			temp = xhci_readl(xhci, port_array[wIndex]);
 			/* In spec software should not attempt to suspend
 			 * a port unless the port reports that it is in the
 			 * enabled (PED = ‘1’,PLS < ‘3’) state.
@@ -402,7 +514,8 @@ int xhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue,
 				goto error;
 			}
 
-			slot_id = xhci_find_slot_id_by_port(xhci, wIndex + 1);
+			slot_id = xhci_find_slot_id_by_port(hcd, xhci,
+					wIndex + 1);
 			if (!slot_id) {
 				xhci_warn(xhci, "slot_id is zero\n");
 				goto error;
@@ -415,15 +528,14 @@ int xhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue,
 			temp = xhci_port_state_to_neutral(temp);
 			temp &= ~PORT_PLS_MASK;
 			temp |= PORT_LINK_STROBE | XDEV_U3;
-			xhci_writel(xhci, temp, addr);
+			xhci_writel(xhci, temp, port_array[wIndex]);
 
 			spin_unlock_irqrestore(&xhci->lock, flags);
 			msleep(10); /* wait device to enter */
 			spin_lock_irqsave(&xhci->lock, flags);
 
-			temp = xhci_readl(xhci, addr);
-			xhci->suspended_ports[wIndex >> 5] |=
-					1 << (wIndex & (31));
+			temp = xhci_readl(xhci, port_array[wIndex]);
+			bus_state->suspended_ports |= 1 << wIndex;
 			break;
 		case USB_PORT_FEAT_POWER:
 			/*
@@ -432,34 +544,39 @@ int xhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue,
 			 * However, khubd will ignore the roothub events until
 			 * the roothub is registered.
 			 */
-			xhci_writel(xhci, temp | PORT_POWER, addr);
+			xhci_writel(xhci, temp | PORT_POWER,
+					port_array[wIndex]);
 
-			temp = xhci_readl(xhci, addr);
+			temp = xhci_readl(xhci, port_array[wIndex]);
 			xhci_dbg(xhci, "set port power, actual port %d status  = 0x%x\n", wIndex, temp);
 			break;
 		case USB_PORT_FEAT_RESET:
 			temp = (temp | PORT_RESET);
-			xhci_writel(xhci, temp, addr);
+			xhci_writel(xhci, temp, port_array[wIndex]);
 
-			temp = xhci_readl(xhci, addr);
+			temp = xhci_readl(xhci, port_array[wIndex]);
 			xhci_dbg(xhci, "set port reset, actual port %d status  = 0x%x\n", wIndex, temp);
 			break;
 		default:
 			goto error;
 		}
-		temp = xhci_readl(xhci, addr); /* unblock any posted writes */
+		/* unblock any posted writes */
+		temp = xhci_readl(xhci, port_array[wIndex]);
 		break;
 	case ClearPortFeature:
 		if (!wIndex || wIndex > ports)
 			goto error;
 		wIndex--;
-		addr = &xhci->op_regs->port_status_base +
-			NUM_PORT_REGS*(wIndex & 0xff);
-		temp = xhci_readl(xhci, addr);
+		temp = xhci_readl(xhci, port_array[wIndex]);
+		if (temp == 0xffffffff) {
+			retval = -ENODEV;
+			break;
+		}
+		/* FIXME: What new port features do we need to support? */
 		temp = xhci_port_state_to_neutral(temp);
 		switch (wValue) {
 		case USB_PORT_FEAT_SUSPEND:
-			temp = xhci_readl(xhci, addr);
+			temp = xhci_readl(xhci, port_array[wIndex]);
 			xhci_dbg(xhci, "clear USB_PORT_FEAT_SUSPEND\n");
 			xhci_dbg(xhci, "PORTSC %04x\n", temp);
 			if (temp & PORT_RESET)
@@ -471,30 +588,34 @@ int xhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue,
 					temp = xhci_port_state_to_neutral(temp);
 					temp &= ~PORT_PLS_MASK;
 					temp |= PORT_LINK_STROBE | XDEV_U0;
-					xhci_writel(xhci, temp, addr);
-					xhci_readl(xhci, addr);
+					xhci_writel(xhci, temp,
+							port_array[wIndex]);
+					xhci_readl(xhci, port_array[wIndex]);
 				} else {
 					temp = xhci_port_state_to_neutral(temp);
 					temp &= ~PORT_PLS_MASK;
 					temp |= PORT_LINK_STROBE | XDEV_RESUME;
-					xhci_writel(xhci, temp, addr);
+					xhci_writel(xhci, temp,
+							port_array[wIndex]);
 
 					spin_unlock_irqrestore(&xhci->lock,
 							       flags);
 					msleep(20);
 					spin_lock_irqsave(&xhci->lock, flags);
 
-					temp = xhci_readl(xhci, addr);
+					temp = xhci_readl(xhci,
+							port_array[wIndex]);
 					temp = xhci_port_state_to_neutral(temp);
 					temp &= ~PORT_PLS_MASK;
 					temp |= PORT_LINK_STROBE | XDEV_U0;
-					xhci_writel(xhci, temp, addr);
+					xhci_writel(xhci, temp,
+							port_array[wIndex]);
 				}
-				xhci->port_c_suspend[wIndex >> 5] |=
-						1 << (wIndex & 31);
+				bus_state->port_c_suspend |= 1 << wIndex;
 			}
 
-			slot_id = xhci_find_slot_id_by_port(xhci, wIndex + 1);
+			slot_id = xhci_find_slot_id_by_port(hcd, xhci,
+					wIndex + 1);
 			if (!slot_id) {
 				xhci_dbg(xhci, "slot_id is zero\n");
 				goto error;
@@ -502,17 +623,17 @@ int xhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue,
 			xhci_ring_device(xhci, slot_id);
 			break;
 		case USB_PORT_FEAT_C_SUSPEND:
-			xhci->port_c_suspend[wIndex >> 5] &=
-					~(1 << (wIndex & 31));
+			bus_state->port_c_suspend &= ~(1 << wIndex);
 		case USB_PORT_FEAT_C_RESET:
 		case USB_PORT_FEAT_C_CONNECTION:
 		case USB_PORT_FEAT_C_OVER_CURRENT:
 		case USB_PORT_FEAT_C_ENABLE:
 			xhci_clear_port_change_bit(xhci, wValue, wIndex,
-					addr, temp);
+					port_array[wIndex], temp);
 			break;
 		case USB_PORT_FEAT_ENABLE:
-			xhci_disable_port(xhci, wIndex, addr, temp);
+			xhci_disable_port(hcd, xhci, wIndex,
+					port_array[wIndex], temp);
 			break;
 		default:
 			goto error;
@@ -543,9 +664,17 @@ int xhci_hub_status_data(struct usb_hcd *hcd, char *buf)
 	int i, retval;
 	struct xhci_hcd	*xhci = hcd_to_xhci(hcd);
 	int ports;
-	u32 __iomem *addr;
-
-	ports = HCS_MAX_PORTS(xhci->hcs_params1);
+	u32 __iomem **port_array;
+	struct xhci_bus_state *bus_state;
+
+	if (hcd->speed == HCD_USB3) {
+		ports = xhci->num_usb3_ports;
+		port_array = xhci->usb3_ports;
+	} else {
+		ports = xhci->num_usb2_ports;
+		port_array = xhci->usb2_ports;
+	}
+	bus_state = &xhci->bus_state[hcd_index(hcd)];
 
 	/* Initial status is no changes */
 	retval = (ports + 8) / 8;
@@ -557,13 +686,15 @@ int xhci_hub_status_data(struct usb_hcd *hcd, char *buf)
 	spin_lock_irqsave(&xhci->lock, flags);
 	/* For each port, did anything change?  If so, set that bit in buf. */
 	for (i = 0; i < ports; i++) {
-		addr = &xhci->op_regs->port_status_base +
-			NUM_PORT_REGS*i;
-		temp = xhci_readl(xhci, addr);
+		temp = xhci_readl(xhci, port_array[i]);
+		if (temp == 0xffffffff) {
+			retval = -ENODEV;
+			break;
+		}
 		if ((temp & mask) != 0 ||
-			(xhci->port_c_suspend[i >> 5] &	1 << (i & 31)) ||
-			(xhci->resume_done[i] && time_after_eq(
-			    jiffies, xhci->resume_done[i]))) {
+			(bus_state->port_c_suspend & 1 << i) ||
+			(bus_state->resume_done[i] && time_after_eq(
+			    jiffies, bus_state->resume_done[i]))) {
 			buf[(i + 1) / 8] |= 1 << (i + 1) % 8;
 			status = 1;
 		}
@@ -577,42 +708,51 @@ int xhci_hub_status_data(struct usb_hcd *hcd, char *buf)
 int xhci_bus_suspend(struct usb_hcd *hcd)
 {
 	struct xhci_hcd	*xhci = hcd_to_xhci(hcd);
-	int port;
+	int max_ports, port_index;
+	u32 __iomem **port_array;
+	struct xhci_bus_state *bus_state;
 	unsigned long flags;
 
-	xhci_dbg(xhci, "suspend root hub\n");
+	if (hcd->speed == HCD_USB3) {
+		max_ports = xhci->num_usb3_ports;
+		port_array = xhci->usb3_ports;
+		xhci_dbg(xhci, "suspend USB 3.0 root hub\n");
+	} else {
+		max_ports = xhci->num_usb2_ports;
+		port_array = xhci->usb2_ports;
+		xhci_dbg(xhci, "suspend USB 2.0 root hub\n");
+	}
+	bus_state = &xhci->bus_state[hcd_index(hcd)];
 
 	spin_lock_irqsave(&xhci->lock, flags);
 
 	if (hcd->self.root_hub->do_remote_wakeup) {
-		port = HCS_MAX_PORTS(xhci->hcs_params1);
-		while (port--) {
-			if (xhci->resume_done[port] != 0) {
+		port_index = max_ports;
+		while (port_index--) {
+			if (bus_state->resume_done[port_index] != 0) {
 				spin_unlock_irqrestore(&xhci->lock, flags);
 				xhci_dbg(xhci, "suspend failed because "
 						"port %d is resuming\n",
-						port + 1);
+						port_index + 1);
 				return -EBUSY;
 			}
 		}
 	}
 
-	port = HCS_MAX_PORTS(xhci->hcs_params1);
-	xhci->bus_suspended = 0;
-	while (port--) {
+	port_index = max_ports;
+	bus_state->bus_suspended = 0;
+	while (port_index--) {
 		/* suspend the port if the port is not suspended */
-		u32 __iomem *addr;
 		u32 t1, t2;
 		int slot_id;
 
-		addr = &xhci->op_regs->port_status_base +
-			NUM_PORT_REGS * (port & 0xff);
-		t1 = xhci_readl(xhci, addr);
+		t1 = xhci_readl(xhci, port_array[port_index]);
 		t2 = xhci_port_state_to_neutral(t1);
 
 		if ((t1 & PORT_PE) && !(t1 & PORT_PLS_MASK)) {
-			xhci_dbg(xhci, "port %d not suspended\n", port);
-			slot_id = xhci_find_slot_id_by_port(xhci, port + 1);
+			xhci_dbg(xhci, "port %d not suspended\n", port_index);
+			slot_id = xhci_find_slot_id_by_port(hcd, xhci,
+					port_index + 1);
 			if (slot_id) {
 				spin_unlock_irqrestore(&xhci->lock, flags);
 				xhci_stop_device(xhci, slot_id, 1);
@@ -620,7 +760,7 @@ int xhci_bus_suspend(struct usb_hcd *hcd)
 			}
 			t2 &= ~PORT_PLS_MASK;
 			t2 |= PORT_LINK_STROBE | XDEV_U3;
-			set_bit(port, &xhci->bus_suspended);
+			set_bit(port_index, &bus_state->bus_suspended);
 		}
 		if (hcd->self.root_hub->do_remote_wakeup) {
 			if (t1 & PORT_CONNECT) {
@@ -635,22 +775,24 @@ int xhci_bus_suspend(struct usb_hcd *hcd)
 
 		t1 = xhci_port_state_to_neutral(t1);
 		if (t1 != t2)
-			xhci_writel(xhci, t2, addr);
+			xhci_writel(xhci, t2, port_array[port_index]);
 
 		if (DEV_HIGHSPEED(t1)) {
 			/* enable remote wake up for USB 2.0 */
 			u32 __iomem *addr;
 			u32 tmp;
 
-			addr = &xhci->op_regs->port_power_base +
-				NUM_PORT_REGS * (port & 0xff);
+			/* Add one to the port status register address to get
+			 * the port power control register address.
+			 */
+			addr = port_array[port_index] + 1;
 			tmp = xhci_readl(xhci, addr);
 			tmp |= PORT_RWE;
 			xhci_writel(xhci, tmp, addr);
 		}
 	}
 	hcd->state = HC_STATE_SUSPENDED;
-	xhci->next_statechange = jiffies + msecs_to_jiffies(10);
+	bus_state->next_statechange = jiffies + msecs_to_jiffies(10);
 	spin_unlock_irqrestore(&xhci->lock, flags);
 	return 0;
 }
@@ -658,13 +800,24 @@ int xhci_bus_suspend(struct usb_hcd *hcd)
 int xhci_bus_resume(struct usb_hcd *hcd)
 {
 	struct xhci_hcd	*xhci = hcd_to_xhci(hcd);
-	int port;
+	int max_ports, port_index;
+	u32 __iomem **port_array;
+	struct xhci_bus_state *bus_state;
 	u32 temp;
 	unsigned long flags;
 
-	xhci_dbg(xhci, "resume root hub\n");
+	if (hcd->speed == HCD_USB3) {
+		max_ports = xhci->num_usb3_ports;
+		port_array = xhci->usb3_ports;
+		xhci_dbg(xhci, "resume USB 3.0 root hub\n");
+	} else {
+		max_ports = xhci->num_usb2_ports;
+		port_array = xhci->usb2_ports;
+		xhci_dbg(xhci, "resume USB 2.0 root hub\n");
+	}
+	bus_state = &xhci->bus_state[hcd_index(hcd)];
 
-	if (time_before(jiffies, xhci->next_statechange))
+	if (time_before(jiffies, bus_state->next_statechange))
 		msleep(5);
 
 	spin_lock_irqsave(&xhci->lock, flags);
@@ -678,57 +831,57 @@ int xhci_bus_resume(struct usb_hcd *hcd)
 	temp &= ~CMD_EIE;
 	xhci_writel(xhci, temp, &xhci->op_regs->command);
 
-	port = HCS_MAX_PORTS(xhci->hcs_params1);
-	while (port--) {
+	port_index = max_ports;
+	while (port_index--) {
 		/* Check whether need resume ports. If needed
 		   resume port and disable remote wakeup */
-		u32 __iomem *addr;
 		u32 temp;
 		int slot_id;
 
-		addr = &xhci->op_regs->port_status_base +
-			NUM_PORT_REGS * (port & 0xff);
-		temp = xhci_readl(xhci, addr);
+		temp = xhci_readl(xhci, port_array[port_index]);
 		if (DEV_SUPERSPEED(temp))
 			temp &= ~(PORT_RWC_BITS | PORT_CEC | PORT_WAKE_BITS);
 		else
 			temp &= ~(PORT_RWC_BITS | PORT_WAKE_BITS);
-		if (test_bit(port, &xhci->bus_suspended) &&
+		if (test_bit(port_index, &bus_state->bus_suspended) &&
 		    (temp & PORT_PLS_MASK)) {
 			if (DEV_SUPERSPEED(temp)) {
 				temp = xhci_port_state_to_neutral(temp);
 				temp &= ~PORT_PLS_MASK;
 				temp |= PORT_LINK_STROBE | XDEV_U0;
-				xhci_writel(xhci, temp, addr);
+				xhci_writel(xhci, temp, port_array[port_index]);
 			} else {
 				temp = xhci_port_state_to_neutral(temp);
 				temp &= ~PORT_PLS_MASK;
 				temp |= PORT_LINK_STROBE | XDEV_RESUME;
-				xhci_writel(xhci, temp, addr);
+				xhci_writel(xhci, temp, port_array[port_index]);
 
 				spin_unlock_irqrestore(&xhci->lock, flags);
 				msleep(20);
 				spin_lock_irqsave(&xhci->lock, flags);
 
-				temp = xhci_readl(xhci, addr);
+				temp = xhci_readl(xhci, port_array[port_index]);
 				temp = xhci_port_state_to_neutral(temp);
 				temp &= ~PORT_PLS_MASK;
 				temp |= PORT_LINK_STROBE | XDEV_U0;
-				xhci_writel(xhci, temp, addr);
+				xhci_writel(xhci, temp, port_array[port_index]);
 			}
-			slot_id = xhci_find_slot_id_by_port(xhci, port + 1);
+			slot_id = xhci_find_slot_id_by_port(hcd,
+					xhci, port_index + 1);
 			if (slot_id)
 				xhci_ring_device(xhci, slot_id);
 		} else
-			xhci_writel(xhci, temp, addr);
+			xhci_writel(xhci, temp, port_array[port_index]);
 
 		if (DEV_HIGHSPEED(temp)) {
 			/* disable remote wake up for USB 2.0 */
 			u32 __iomem *addr;
 			u32 tmp;
 
-			addr = &xhci->op_regs->port_power_base +
-				NUM_PORT_REGS * (port & 0xff);
+			/* Add one to the port status register address to get
+			 * the port power control register address.
+			 */
+			addr = port_array[port_index] + 1;
 			tmp = xhci_readl(xhci, addr);
 			tmp &= ~PORT_RWE;
 			xhci_writel(xhci, tmp, addr);
@@ -737,8 +890,7 @@ int xhci_bus_resume(struct usb_hcd *hcd)
 
 	(void) xhci_readl(xhci, &xhci->op_regs->command);
 
-	xhci->next_statechange = jiffies + msecs_to_jiffies(5);
-	hcd->state = HC_STATE_RUNNING;
+	bus_state->next_statechange = jiffies + msecs_to_jiffies(5);
 	/* re-enable irqs */
 	temp = xhci_readl(xhci, &xhci->op_regs->command);
 	temp |= CMD_EIE;
diff --git a/drivers/usb/host/xhci-mem.c b/drivers/usb/host/xhci-mem.c
index a9534396e85b..a003e79aacdc 100644
--- a/drivers/usb/host/xhci-mem.c
+++ b/drivers/usb/host/xhci-mem.c
@@ -814,14 +814,64 @@ void xhci_copy_ep0_dequeue_into_input_ctx(struct xhci_hcd *xhci,
 	ep0_ctx->deq |= ep_ring->cycle_state;
 }
 
+/*
+ * The xHCI roothub may have ports of differing speeds in any order in the port
+ * status registers.  xhci->port_array provides an array of the port speed for
+ * each offset into the port status registers.
+ *
+ * The xHCI hardware wants to know the roothub port number that the USB device
+ * is attached to (or the roothub port its ancestor hub is attached to).  All we
+ * know is the index of that port under either the USB 2.0 or the USB 3.0
+ * roothub, but that doesn't give us the real index into the HW port status
+ * registers.  Scan through the xHCI roothub port array, looking for the Nth
+ * entry of the correct port speed.  Return the port number of that entry.
+ */
+static u32 xhci_find_real_port_number(struct xhci_hcd *xhci,
+		struct usb_device *udev)
+{
+	struct usb_device *top_dev;
+	unsigned int num_similar_speed_ports;
+	unsigned int faked_port_num;
+	int i;
+
+	for (top_dev = udev; top_dev->parent && top_dev->parent->parent;
+			top_dev = top_dev->parent)
+		/* Found device below root hub */;
+	faked_port_num = top_dev->portnum;
+	for (i = 0, num_similar_speed_ports = 0;
+			i < HCS_MAX_PORTS(xhci->hcs_params1); i++) {
+		u8 port_speed = xhci->port_array[i];
+
+		/*
+		 * Skip ports that don't have known speeds, or have duplicate
+		 * Extended Capabilities port speed entries.
+		 */
+		if (port_speed == 0 || port_speed == -1)
+			continue;
+
+		/*
+		 * USB 3.0 ports are always under a USB 3.0 hub.  USB 2.0 and
+		 * 1.1 ports are under the USB 2.0 hub.  If the port speed
+		 * matches the device speed, it's a similar speed port.
+		 */
+		if ((port_speed == 0x03) == (udev->speed == USB_SPEED_SUPER))
+			num_similar_speed_ports++;
+		if (num_similar_speed_ports == faked_port_num)
+			/* Roothub ports are numbered from 1 to N */
+			return i+1;
+	}
+	return 0;
+}
+
 /* Setup an xHCI virtual device for a Set Address command */
 int xhci_setup_addressable_virt_dev(struct xhci_hcd *xhci, struct usb_device *udev)
 {
 	struct xhci_virt_device *dev;
 	struct xhci_ep_ctx	*ep0_ctx;
-	struct usb_device	*top_dev;
 	struct xhci_slot_ctx    *slot_ctx;
 	struct xhci_input_control_ctx *ctrl_ctx;
+	u32			port_num;
+	struct usb_device *top_dev;
 
 	dev = xhci->devs[udev->slot_id];
 	/* Slot ID 0 is reserved */
@@ -863,16 +913,20 @@ int xhci_setup_addressable_virt_dev(struct xhci_hcd *xhci, struct usb_device *ud
 		BUG();
 	}
 	/* Find the root hub port this device is under */
+	port_num = xhci_find_real_port_number(xhci, udev);
+	if (!port_num)
+		return -EINVAL;
+	slot_ctx->dev_info2 |= (u32) ROOT_HUB_PORT(port_num);
+	/* Set the port number in the virtual_device to the faked port number */
 	for (top_dev = udev; top_dev->parent && top_dev->parent->parent;
 			top_dev = top_dev->parent)
 		/* Found device below root hub */;
-	slot_ctx->dev_info2 |= (u32) ROOT_HUB_PORT(top_dev->portnum);
 	dev->port = top_dev->portnum;
-	xhci_dbg(xhci, "Set root hub portnum to %d\n", top_dev->portnum);
+	xhci_dbg(xhci, "Set root hub portnum to %d\n", port_num);
+	xhci_dbg(xhci, "Set fake root hub portnum to %d\n", dev->port);
 
-	/* Is this a LS/FS device under a HS hub? */
-	if ((udev->speed == USB_SPEED_LOW || udev->speed == USB_SPEED_FULL) &&
-			udev->tt) {
+	/* Is this a LS/FS device under an external HS hub? */
+	if (udev->tt && udev->tt->hub->parent) {
 		slot_ctx->tt_info = udev->tt->hub->slot_id;
 		slot_ctx->tt_info |= udev->ttport << 8;
 		if (udev->tt->multi)
@@ -1452,7 +1506,8 @@ void xhci_mem_cleanup(struct xhci_hcd *xhci)
 
 	xhci->page_size = 0;
 	xhci->page_shift = 0;
-	xhci->bus_suspended = 0;
+	xhci->bus_state[0].bus_suspended = 0;
+	xhci->bus_state[1].bus_suspended = 0;
 }
 
 static int xhci_test_trb_in_td(struct xhci_hcd *xhci,
@@ -1748,6 +1803,20 @@ static int xhci_setup_port_arrays(struct xhci_hcd *xhci, gfp_t flags)
 	}
 	xhci_dbg(xhci, "Found %u USB 2.0 ports and %u USB 3.0 ports.\n",
 			xhci->num_usb2_ports, xhci->num_usb3_ports);
+
+	/* Place limits on the number of roothub ports so that the hub
+	 * descriptors aren't longer than the USB core will allocate.
+	 */
+	if (xhci->num_usb3_ports > 15) {
+		xhci_dbg(xhci, "Limiting USB 3.0 roothub ports to 15.\n");
+		xhci->num_usb3_ports = 15;
+	}
+	if (xhci->num_usb2_ports > USB_MAXCHILDREN) {
+		xhci_dbg(xhci, "Limiting USB 2.0 roothub ports to %u.\n",
+				USB_MAXCHILDREN);
+		xhci->num_usb2_ports = USB_MAXCHILDREN;
+	}
+
 	/*
 	 * Note we could have all USB 3.0 ports, or all USB 2.0 ports.
 	 * Not sure how the USB core will handle a hub with no ports...
@@ -1772,6 +1841,8 @@ static int xhci_setup_port_arrays(struct xhci_hcd *xhci, gfp_t flags)
 					"addr = %p\n", i,
 					xhci->usb2_ports[port_index]);
 			port_index++;
+			if (port_index == xhci->num_usb2_ports)
+				break;
 		}
 	}
 	if (xhci->num_usb3_ports) {
@@ -1790,6 +1861,8 @@ static int xhci_setup_port_arrays(struct xhci_hcd *xhci, gfp_t flags)
 						"addr = %p\n", i,
 						xhci->usb3_ports[port_index]);
 				port_index++;
+				if (port_index == xhci->num_usb3_ports)
+					break;
 			}
 	}
 	return 0;
@@ -1971,8 +2044,10 @@ int xhci_mem_init(struct xhci_hcd *xhci, gfp_t flags)
 	init_completion(&xhci->addr_dev);
 	for (i = 0; i < MAX_HC_SLOTS; ++i)
 		xhci->devs[i] = NULL;
-	for (i = 0; i < MAX_HC_PORTS; ++i)
-		xhci->resume_done[i] = 0;
+	for (i = 0; i < USB_MAXCHILDREN; ++i) {
+		xhci->bus_state[0].resume_done[i] = 0;
+		xhci->bus_state[1].resume_done[i] = 0;
+	}
 
 	if (scratchpad_alloc(xhci, flags))
 		goto fail;
diff --git a/drivers/usb/host/xhci-pci.c b/drivers/usb/host/xhci-pci.c
index bb668a894ab9..ceea9f33491c 100644
--- a/drivers/usb/host/xhci-pci.c
+++ b/drivers/usb/host/xhci-pci.c
@@ -50,13 +50,45 @@ static int xhci_pci_reinit(struct xhci_hcd *xhci, struct pci_dev *pdev)
 /* called during probe() after chip reset completes */
 static int xhci_pci_setup(struct usb_hcd *hcd)
 {
-	struct xhci_hcd		*xhci = hcd_to_xhci(hcd);
+	struct xhci_hcd		*xhci;
 	struct pci_dev		*pdev = to_pci_dev(hcd->self.controller);
 	int			retval;
 	u32			temp;
 
 	hcd->self.sg_tablesize = TRBS_PER_SEGMENT - 2;
 
+	if (usb_hcd_is_primary_hcd(hcd)) {
+		xhci = kzalloc(sizeof(struct xhci_hcd), GFP_KERNEL);
+		if (!xhci)
+			return -ENOMEM;
+		*((struct xhci_hcd **) hcd->hcd_priv) = xhci;
+		xhci->main_hcd = hcd;
+		/* Mark the first roothub as being USB 2.0.
+		 * The xHCI driver will register the USB 3.0 roothub.
+		 */
+		hcd->speed = HCD_USB2;
+		hcd->self.root_hub->speed = USB_SPEED_HIGH;
+		/*
+		 * USB 2.0 roothub under xHCI has an integrated TT,
+		 * (rate matching hub) as opposed to having an OHCI/UHCI
+		 * companion controller.
+		 */
+		hcd->has_tt = 1;
+	} else {
+		/* xHCI private pointer was set in xhci_pci_probe for the second
+		 * registered roothub.
+		 */
+		xhci = hcd_to_xhci(hcd);
+		temp = xhci_readl(xhci, &xhci->cap_regs->hcc_params);
+		if (HCC_64BIT_ADDR(temp)) {
+			xhci_dbg(xhci, "Enabling 64-bit DMA addresses.\n");
+			dma_set_mask(hcd->self.controller, DMA_BIT_MASK(64));
+		} else {
+			dma_set_mask(hcd->self.controller, DMA_BIT_MASK(32));
+		}
+		return 0;
+	}
+
 	xhci->cap_regs = hcd->regs;
 	xhci->op_regs = hcd->regs +
 		HC_LENGTH(xhci_readl(xhci, &xhci->cap_regs->hc_capbase));
@@ -85,13 +117,13 @@ static int xhci_pci_setup(struct usb_hcd *hcd)
 	/* Make sure the HC is halted. */
 	retval = xhci_halt(xhci);
 	if (retval)
-		return retval;
+		goto error;
 
 	xhci_dbg(xhci, "Resetting HCD\n");
 	/* Reset the internal HC memory state and registers. */
 	retval = xhci_reset(xhci);
 	if (retval)
-		return retval;
+		goto error;
 	xhci_dbg(xhci, "Reset complete\n");
 
 	temp = xhci_readl(xhci, &xhci->cap_regs->hcc_params);
@@ -106,14 +138,85 @@ static int xhci_pci_setup(struct usb_hcd *hcd)
 	/* Initialize HCD and host controller data structures. */
 	retval = xhci_init(hcd);
 	if (retval)
-		return retval;
+		goto error;
 	xhci_dbg(xhci, "Called HCD init\n");
 
 	pci_read_config_byte(pdev, XHCI_SBRN_OFFSET, &xhci->sbrn);
 	xhci_dbg(xhci, "Got SBRN %u\n", (unsigned int) xhci->sbrn);
 
 	/* Find any debug ports */
-	return xhci_pci_reinit(xhci, pdev);
+	retval = xhci_pci_reinit(xhci, pdev);
+	if (!retval)
+		return retval;
+
+error:
+	kfree(xhci);
+	return retval;
+}
+
+/*
+ * We need to register our own PCI probe function (instead of the USB core's
+ * function) in order to create a second roothub under xHCI.
+ */
+static int xhci_pci_probe(struct pci_dev *dev, const struct pci_device_id *id)
+{
+	int retval;
+	struct xhci_hcd *xhci;
+	struct hc_driver *driver;
+	struct usb_hcd *hcd;
+
+	driver = (struct hc_driver *)id->driver_data;
+	/* Register the USB 2.0 roothub.
+	 * FIXME: USB core must know to register the USB 2.0 roothub first.
+	 * This is sort of silly, because we could just set the HCD driver flags
+	 * to say USB 2.0, but I'm not sure what the implications would be in
+	 * the other parts of the HCD code.
+	 */
+	retval = usb_hcd_pci_probe(dev, id);
+
+	if (retval)
+		return retval;
+
+	/* USB 2.0 roothub is stored in the PCI device now. */
+	hcd = dev_get_drvdata(&dev->dev);
+	xhci = hcd_to_xhci(hcd);
+	xhci->shared_hcd = usb_create_shared_hcd(driver, &dev->dev,
+				pci_name(dev), hcd);
+	if (!xhci->shared_hcd) {
+		retval = -ENOMEM;
+		goto dealloc_usb2_hcd;
+	}
+
+	/* Set the xHCI pointer before xhci_pci_setup() (aka hcd_driver.reset)
+	 * is called by usb_add_hcd().
+	 */
+	*((struct xhci_hcd **) xhci->shared_hcd->hcd_priv) = xhci;
+
+	retval = usb_add_hcd(xhci->shared_hcd, dev->irq,
+			IRQF_DISABLED | IRQF_SHARED);
+	if (retval)
+		goto put_usb3_hcd;
+	/* Roothub already marked as USB 3.0 speed */
+	return 0;
+
+put_usb3_hcd:
+	usb_put_hcd(xhci->shared_hcd);
+dealloc_usb2_hcd:
+	usb_hcd_pci_remove(dev);
+	return retval;
+}
+
+static void xhci_pci_remove(struct pci_dev *dev)
+{
+	struct xhci_hcd *xhci;
+
+	xhci = hcd_to_xhci(pci_get_drvdata(dev));
+	if (xhci->shared_hcd) {
+		usb_remove_hcd(xhci->shared_hcd);
+		usb_put_hcd(xhci->shared_hcd);
+	}
+	usb_hcd_pci_remove(dev);
+	kfree(xhci);
 }
 
 #ifdef CONFIG_PM
@@ -122,7 +225,8 @@ static int xhci_pci_suspend(struct usb_hcd *hcd, bool do_wakeup)
 	struct xhci_hcd	*xhci = hcd_to_xhci(hcd);
 	int	retval = 0;
 
-	if (hcd->state != HC_STATE_SUSPENDED)
+	if (hcd->state != HC_STATE_SUSPENDED ||
+			xhci->shared_hcd->state != HC_STATE_SUSPENDED)
 		return -EINVAL;
 
 	retval = xhci_suspend(xhci);
@@ -143,13 +247,13 @@ static int xhci_pci_resume(struct usb_hcd *hcd, bool hibernated)
 static const struct hc_driver xhci_pci_hc_driver = {
 	.description =		hcd_name,
 	.product_desc =		"xHCI Host Controller",
-	.hcd_priv_size =	sizeof(struct xhci_hcd),
+	.hcd_priv_size =	sizeof(struct xhci_hcd *),
 
 	/*
 	 * generic hardware linkage
 	 */
 	.irq =			xhci_irq,
-	.flags =		HCD_MEMORY | HCD_USB3,
+	.flags =		HCD_MEMORY | HCD_USB3 | HCD_SHARED,
 
 	/*
 	 * basic lifecycle operations
@@ -210,8 +314,8 @@ static struct pci_driver xhci_pci_driver = {
 	.name =		(char *) hcd_name,
 	.id_table =	pci_ids,
 
-	.probe =	usb_hcd_pci_probe,
-	.remove =	usb_hcd_pci_remove,
+	.probe =	xhci_pci_probe,
+	.remove =	xhci_pci_remove,
 	/* suspend and resume implemented later */
 
 	.shutdown = 	usb_hcd_pci_shutdown,
diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c
index 3289bf4832c9..cfc1ad92473f 100644
--- a/drivers/usb/host/xhci-ring.c
+++ b/drivers/usb/host/xhci-ring.c
@@ -380,10 +380,8 @@ static struct xhci_segment *find_trb_seg(
 	while (cur_seg->trbs > trb ||
 			&cur_seg->trbs[TRBS_PER_SEGMENT - 1] < trb) {
 		generic_trb = &cur_seg->trbs[TRBS_PER_SEGMENT - 1].generic;
-		if ((generic_trb->field[3] & TRB_TYPE_BITMASK) ==
-				TRB_TYPE(TRB_LINK) &&
-				(generic_trb->field[3] & LINK_TOGGLE))
-			*cycle_state = ~(*cycle_state) & 0x1;
+		if (generic_trb->field[3] & LINK_TOGGLE)
+			*cycle_state ^= 0x1;
 		cur_seg = cur_seg->next;
 		if (cur_seg == start_seg)
 			/* Looped over the entire list.  Oops! */
@@ -497,18 +495,29 @@ void xhci_find_new_dequeue_state(struct xhci_hcd *xhci,
 	trb = &state->new_deq_ptr->generic;
 	if ((trb->field[3] & TRB_TYPE_BITMASK) == TRB_TYPE(TRB_LINK) &&
 				(trb->field[3] & LINK_TOGGLE))
-		state->new_cycle_state = ~(state->new_cycle_state) & 0x1;
+		state->new_cycle_state ^= 0x1;
 	next_trb(xhci, ep_ring, &state->new_deq_seg, &state->new_deq_ptr);
 
+	/*
+	 * If there is only one segment in a ring, find_trb_seg()'s while loop
+	 * will not run, and it will return before it has a chance to see if it
+	 * needs to toggle the cycle bit.  It can't tell if the stalled transfer
+	 * ended just before the link TRB on a one-segment ring, or if the TD
+	 * wrapped around the top of the ring, because it doesn't have the TD in
+	 * question.  Look for the one-segment case where stalled TRB's address
+	 * is greater than the new dequeue pointer address.
+	 */
+	if (ep_ring->first_seg == ep_ring->first_seg->next &&
+			state->new_deq_ptr < dev->eps[ep_index].stopped_trb)
+		state->new_cycle_state ^= 0x1;
+	xhci_dbg(xhci, "Cycle state = 0x%x\n", state->new_cycle_state);
+
 	/* Don't update the ring cycle state for the producer (us). */
 	xhci_dbg(xhci, "New dequeue segment = %p (virtual)\n",
 			state->new_deq_seg);
 	addr = xhci_trb_virt_to_dma(state->new_deq_seg, state->new_deq_ptr);
 	xhci_dbg(xhci, "New dequeue pointer = 0x%llx (DMA)\n",
 			(unsigned long long) addr);
-	xhci_dbg(xhci, "Setting dequeue pointer in internal ring state.\n");
-	ep_ring->dequeue = state->new_deq_ptr;
-	ep_ring->deq_seg = state->new_deq_seg;
 }
 
 static void td_to_noop(struct xhci_hcd *xhci, struct xhci_ring *ep_ring,
@@ -599,13 +608,14 @@ static inline void xhci_stop_watchdog_timer_in_irq(struct xhci_hcd *xhci,
 static void xhci_giveback_urb_in_irq(struct xhci_hcd *xhci,
 		struct xhci_td *cur_td, int status, char *adjective)
 {
-	struct usb_hcd *hcd = xhci_to_hcd(xhci);
+	struct usb_hcd *hcd;
 	struct urb	*urb;
 	struct urb_priv	*urb_priv;
 
 	urb = cur_td->urb;
 	urb_priv = urb->hcpriv;
 	urb_priv->td_cnt++;
+	hcd = bus_to_hcd(urb->dev->bus);
 
 	/* Only giveback urb when this is the last td in urb */
 	if (urb_priv->td_cnt == urb_priv->length) {
@@ -824,8 +834,7 @@ void xhci_stop_endpoint_command_watchdog(unsigned long arg)
 	if (ret < 0) {
 		/* This is bad; the host is not responding to commands and it's
 		 * not allowing itself to be halted.  At least interrupts are
-		 * disabled, so we can set HC_STATE_HALT and notify the
-		 * USB core.  But if we call usb_hc_died(), it will attempt to
+		 * disabled. If we call usb_hc_died(), it will attempt to
 		 * disconnect all device drivers under this host.  Those
 		 * disconnect() methods will wait for all URBs to be unlinked,
 		 * so we must complete them.
@@ -870,9 +879,8 @@ void xhci_stop_endpoint_command_watchdog(unsigned long arg)
 		}
 	}
 	spin_unlock(&xhci->lock);
-	xhci_to_hcd(xhci)->state = HC_STATE_HALT;
 	xhci_dbg(xhci, "Calling usb_hc_died()\n");
-	usb_hc_died(xhci_to_hcd(xhci));
+	usb_hc_died(xhci_to_hcd(xhci)->primary_hcd);
 	xhci_dbg(xhci, "xHCI host controller is dead.\n");
 }
 
@@ -951,9 +959,26 @@ static void handle_set_deq_completion(struct xhci_hcd *xhci,
 	} else {
 		xhci_dbg(xhci, "Successful Set TR Deq Ptr cmd, deq = @%08llx\n",
 				ep_ctx->deq);
+		if (xhci_trb_virt_to_dma(dev->eps[ep_index].queued_deq_seg,
+					dev->eps[ep_index].queued_deq_ptr) ==
+				(ep_ctx->deq & ~(EP_CTX_CYCLE_MASK))) {
+			/* Update the ring's dequeue segment and dequeue pointer
+			 * to reflect the new position.
+			 */
+			ep_ring->deq_seg = dev->eps[ep_index].queued_deq_seg;
+			ep_ring->dequeue = dev->eps[ep_index].queued_deq_ptr;
+		} else {
+			xhci_warn(xhci, "Mismatch between completed Set TR Deq "
+					"Ptr command & xHCI internal state.\n");
+			xhci_warn(xhci, "ep deq seg = %p, deq ptr = %p\n",
+					dev->eps[ep_index].queued_deq_seg,
+					dev->eps[ep_index].queued_deq_ptr);
+		}
 	}
 
 	dev->eps[ep_index].ep_state &= ~SET_DEQ_PENDING;
+	dev->eps[ep_index].queued_deq_seg = NULL;
+	dev->eps[ep_index].queued_deq_ptr = NULL;
 	/* Restart any rings with pending URBs */
 	ring_doorbell_for_active_rings(xhci, slot_id, ep_index);
 }
@@ -1118,7 +1143,6 @@ bandwidth_change:
 		handle_set_deq_completion(xhci, event, xhci->cmd_ring->dequeue);
 		break;
 	case TRB_TYPE(TRB_CMD_NOOP):
-		++xhci->noops_handled;
 		break;
 	case TRB_TYPE(TRB_RESET_EP):
 		handle_reset_ep_completion(xhci, event, xhci->cmd_ring->dequeue);
@@ -1162,15 +1186,55 @@ static void handle_vendor_event(struct xhci_hcd *xhci,
 		handle_cmd_completion(xhci, &event->event_cmd);
 }
 
+/* @port_id: the one-based port ID from the hardware (indexed from array of all
+ * port registers -- USB 3.0 and USB 2.0).
+ *
+ * Returns a zero-based port number, which is suitable for indexing into each of
+ * the split roothubs' port arrays and bus state arrays.
+ */
+static unsigned int find_faked_portnum_from_hw_portnum(struct usb_hcd *hcd,
+		struct xhci_hcd *xhci, u32 port_id)
+{
+	unsigned int i;
+	unsigned int num_similar_speed_ports = 0;
+
+	/* port_id from the hardware is 1-based, but port_array[], usb3_ports[],
+	 * and usb2_ports are 0-based indexes.  Count the number of similar
+	 * speed ports, up to 1 port before this port.
+	 */
+	for (i = 0; i < (port_id - 1); i++) {
+		u8 port_speed = xhci->port_array[i];
+
+		/*
+		 * Skip ports that don't have known speeds, or have duplicate
+		 * Extended Capabilities port speed entries.
+		 */
+		if (port_speed == 0 || port_speed == -1)
+			continue;
+
+		/*
+		 * USB 3.0 ports are always under a USB 3.0 hub.  USB 2.0 and
+		 * 1.1 ports are under the USB 2.0 hub.  If the port speed
+		 * matches the device speed, it's a similar speed port.
+		 */
+		if ((port_speed == 0x03) == (hcd->speed == HCD_USB3))
+			num_similar_speed_ports++;
+	}
+	return num_similar_speed_ports;
+}
+
 static void handle_port_status(struct xhci_hcd *xhci,
 		union xhci_trb *event)
 {
-	struct usb_hcd *hcd = xhci_to_hcd(xhci);
+	struct usb_hcd *hcd;
 	u32 port_id;
 	u32 temp, temp1;
-	u32 __iomem *addr;
-	int ports;
+	int max_ports;
 	int slot_id;
+	unsigned int faked_port_index;
+	u8 major_revision;
+	struct xhci_bus_state *bus_state;
+	u32 __iomem **port_array;
 
 	/* Port status change events always have a successful completion code */
 	if (GET_COMP_CODE(event->generic.field[2]) != COMP_SUCCESS) {
@@ -1180,14 +1244,50 @@ static void handle_port_status(struct xhci_hcd *xhci,
 	port_id = GET_PORT_ID(event->generic.field[0]);
 	xhci_dbg(xhci, "Port Status Change Event for port %d\n", port_id);
 
-	ports = HCS_MAX_PORTS(xhci->hcs_params1);
-	if ((port_id <= 0) || (port_id > ports)) {
+	max_ports = HCS_MAX_PORTS(xhci->hcs_params1);
+	if ((port_id <= 0) || (port_id > max_ports)) {
 		xhci_warn(xhci, "Invalid port id %d\n", port_id);
 		goto cleanup;
 	}
 
-	addr = &xhci->op_regs->port_status_base + NUM_PORT_REGS * (port_id - 1);
-	temp = xhci_readl(xhci, addr);
+	/* Figure out which usb_hcd this port is attached to:
+	 * is it a USB 3.0 port or a USB 2.0/1.1 port?
+	 */
+	major_revision = xhci->port_array[port_id - 1];
+	if (major_revision == 0) {
+		xhci_warn(xhci, "Event for port %u not in "
+				"Extended Capabilities, ignoring.\n",
+				port_id);
+		goto cleanup;
+	}
+	if (major_revision == (u8) -1) {
+		xhci_warn(xhci, "Event for port %u duplicated in"
+				"Extended Capabilities, ignoring.\n",
+				port_id);
+		goto cleanup;
+	}
+
+	/*
+	 * Hardware port IDs reported by a Port Status Change Event include USB
+	 * 3.0 and USB 2.0 ports.  We want to check if the port has reported a
+	 * resume event, but we first need to translate the hardware port ID
+	 * into the index into the ports on the correct split roothub, and the
+	 * correct bus_state structure.
+	 */
+	/* Find the right roothub. */
+	hcd = xhci_to_hcd(xhci);
+	if ((major_revision == 0x03) != (hcd->speed == HCD_USB3))
+		hcd = xhci->shared_hcd;
+	bus_state = &xhci->bus_state[hcd_index(hcd)];
+	if (hcd->speed == HCD_USB3)
+		port_array = xhci->usb3_ports;
+	else
+		port_array = xhci->usb2_ports;
+	/* Find the faked port hub number */
+	faked_port_index = find_faked_portnum_from_hw_portnum(hcd, xhci,
+			port_id);
+
+	temp = xhci_readl(xhci, port_array[faked_port_index]);
 	if (hcd->state == HC_STATE_SUSPENDED) {
 		xhci_dbg(xhci, "resume root hub\n");
 		usb_hcd_resume_root_hub(hcd);
@@ -1207,8 +1307,9 @@ static void handle_port_status(struct xhci_hcd *xhci,
 			temp = xhci_port_state_to_neutral(temp);
 			temp &= ~PORT_PLS_MASK;
 			temp |= PORT_LINK_STROBE | XDEV_U0;
-			xhci_writel(xhci, temp, addr);
-			slot_id = xhci_find_slot_id_by_port(xhci, port_id);
+			xhci_writel(xhci, temp, port_array[faked_port_index]);
+			slot_id = xhci_find_slot_id_by_port(hcd, xhci,
+					faked_port_index);
 			if (!slot_id) {
 				xhci_dbg(xhci, "slot_id is zero\n");
 				goto cleanup;
@@ -1216,16 +1317,16 @@ static void handle_port_status(struct xhci_hcd *xhci,
 			xhci_ring_device(xhci, slot_id);
 			xhci_dbg(xhci, "resume SS port %d finished\n", port_id);
 			/* Clear PORT_PLC */
-			temp = xhci_readl(xhci, addr);
+			temp = xhci_readl(xhci, port_array[faked_port_index]);
 			temp = xhci_port_state_to_neutral(temp);
 			temp |= PORT_PLC;
-			xhci_writel(xhci, temp, addr);
+			xhci_writel(xhci, temp, port_array[faked_port_index]);
 		} else {
 			xhci_dbg(xhci, "resume HS port %d\n", port_id);
-			xhci->resume_done[port_id - 1] = jiffies +
+			bus_state->resume_done[faked_port_index] = jiffies +
 				msecs_to_jiffies(20);
 			mod_timer(&hcd->rh_timer,
-				  xhci->resume_done[port_id - 1]);
+				  bus_state->resume_done[faked_port_index]);
 			/* Do the rest in GetPortStatus */
 		}
 	}
@@ -1236,7 +1337,7 @@ cleanup:
 
 	spin_unlock(&xhci->lock);
 	/* Pass this up to the core */
-	usb_hcd_poll_rh_status(xhci_to_hcd(xhci));
+	usb_hcd_poll_rh_status(hcd);
 	spin_lock(&xhci->lock);
 }
 
@@ -1990,12 +2091,12 @@ cleanup:
 					trb_comp_code != COMP_BABBLE))
 				xhci_urb_free_priv(xhci, urb_priv);
 
-			usb_hcd_unlink_urb_from_ep(xhci_to_hcd(xhci), urb);
+			usb_hcd_unlink_urb_from_ep(bus_to_hcd(urb->dev->bus), urb);
 			xhci_dbg(xhci, "Giveback URB %p, len = %d, "
 					"status = %d\n",
 					urb, urb->actual_length, status);
 			spin_unlock(&xhci->lock);
-			usb_hcd_giveback_urb(xhci_to_hcd(xhci), urb, status);
+			usb_hcd_giveback_urb(bus_to_hcd(urb->dev->bus), urb, status);
 			spin_lock(&xhci->lock);
 		}
 
@@ -2119,7 +2220,6 @@ irqreturn_t xhci_irq(struct usb_hcd *hcd)
 		xhci_warn(xhci, "WARNING: Host System Error\n");
 		xhci_halt(xhci);
 hw_died:
-		xhci_to_hcd(xhci)->state = HC_STATE_HALT;
 		spin_unlock(&xhci->lock);
 		return -ESHUTDOWN;
 	}
@@ -2187,8 +2287,12 @@ hw_died:
 irqreturn_t xhci_msi_irq(int irq, struct usb_hcd *hcd)
 {
 	irqreturn_t ret;
+	struct xhci_hcd *xhci;
 
+	xhci = hcd_to_xhci(hcd);
 	set_bit(HCD_FLAG_SAW_IRQ, &hcd->flags);
+	if (xhci->shared_hcd)
+		set_bit(HCD_FLAG_SAW_IRQ, &xhci->shared_hcd->flags);
 
 	ret = xhci_irq(hcd);
 
@@ -2332,7 +2436,7 @@ static int prepare_transfer(struct xhci_hcd *xhci,
 	INIT_LIST_HEAD(&td->cancelled_td_list);
 
 	if (td_index == 0) {
-		ret = usb_hcd_link_urb_to_ep(xhci_to_hcd(xhci), urb);
+		ret = usb_hcd_link_urb_to_ep(bus_to_hcd(urb->dev->bus), urb);
 		if (unlikely(ret)) {
 			xhci_urb_free_priv(xhci, urb_priv);
 			urb->hcpriv = NULL;
@@ -3131,24 +3235,6 @@ static int queue_command(struct xhci_hcd *xhci, u32 field1, u32 field2,
 	return 0;
 }
 
-/* Queue a no-op command on the command ring */
-static int queue_cmd_noop(struct xhci_hcd *xhci)
-{
-	return queue_command(xhci, 0, 0, 0, TRB_TYPE(TRB_CMD_NOOP), false);
-}
-
-/*
- * Place a no-op command on the command ring to test the command and
- * event ring.
- */
-void *xhci_setup_one_noop(struct xhci_hcd *xhci)
-{
-	if (queue_cmd_noop(xhci) < 0)
-		return NULL;
-	xhci->noops_submitted++;
-	return xhci_ring_cmd_db;
-}
-
 /* Queue a slot enable or disable request on the command ring */
 int xhci_queue_slot_control(struct xhci_hcd *xhci, u32 trb_type, u32 slot_id)
 {
@@ -3229,6 +3315,7 @@ static int queue_set_tr_deq(struct xhci_hcd *xhci, int slot_id,
 	u32 trb_ep_index = EP_ID_FOR_TRB(ep_index);
 	u32 trb_stream_id = STREAM_ID_FOR_TRB(stream_id);
 	u32 type = TRB_TYPE(TRB_SET_DEQ);
+	struct xhci_virt_ep *ep;
 
 	addr = xhci_trb_virt_to_dma(deq_seg, deq_ptr);
 	if (addr == 0) {
@@ -3237,6 +3324,14 @@ static int queue_set_tr_deq(struct xhci_hcd *xhci, int slot_id,
 				deq_seg, deq_ptr);
 		return 0;
 	}
+	ep = &xhci->devs[slot_id]->eps[ep_index];
+	if ((ep->ep_state & SET_DEQ_PENDING)) {
+		xhci_warn(xhci, "WARN Cannot submit Set TR Deq Ptr\n");
+		xhci_warn(xhci, "A Set TR Deq Ptr command is pending.\n");
+		return 0;
+	}
+	ep->queued_deq_seg = deq_seg;
+	ep->queued_deq_ptr = deq_ptr;
 	return queue_command(xhci, lower_32_bits(addr) | cycle_state,
 			upper_32_bits(addr), trb_stream_id,
 			trb_slot_id | trb_ep_index | type, false);
diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c
index 2083fc2179b2..9a3645fd759b 100644
--- a/drivers/usb/host/xhci.c
+++ b/drivers/usb/host/xhci.c
@@ -93,17 +93,20 @@ void xhci_quiesce(struct xhci_hcd *xhci)
  *
  * Disable any IRQs and clear the run/stop bit.
  * HC will complete any current and actively pipelined transactions, and
- * should halt within 16 microframes of the run/stop bit being cleared.
+ * should halt within 16 ms of the run/stop bit being cleared.
  * Read HC Halted bit in the status register to see when the HC is finished.
- * XXX: shouldn't we set HC_STATE_HALT here somewhere?
  */
 int xhci_halt(struct xhci_hcd *xhci)
 {
+	int ret;
 	xhci_dbg(xhci, "// Halt the HC\n");
 	xhci_quiesce(xhci);
 
-	return handshake(xhci, &xhci->op_regs->status,
+	ret = handshake(xhci, &xhci->op_regs->status,
 			STS_HALT, STS_HALT, XHCI_MAX_HALT_USEC);
+	if (!ret)
+		xhci->xhc_state |= XHCI_STATE_HALTED;
+	return ret;
 }
 
 /*
@@ -130,11 +133,13 @@ static int xhci_start(struct xhci_hcd *xhci)
 		xhci_err(xhci, "Host took too long to start, "
 				"waited %u microseconds.\n",
 				XHCI_MAX_HALT_USEC);
+	if (!ret)
+		xhci->xhc_state &= ~XHCI_STATE_HALTED;
 	return ret;
 }
 
 /*
- * Reset a halted HC, and set the internal HC state to HC_STATE_HALT.
+ * Reset a halted HC.
  *
  * This resets pipelines, timers, counters, state machines, etc.
  * Transactions will be terminated immediately, and operational registers
@@ -156,8 +161,6 @@ int xhci_reset(struct xhci_hcd *xhci)
 	command = xhci_readl(xhci, &xhci->op_regs->command);
 	command |= CMD_RESET;
 	xhci_writel(xhci, command, &xhci->op_regs->command);
-	/* XXX: Why does EHCI set this here?  Shouldn't other code do this? */
-	xhci_to_hcd(xhci)->state = HC_STATE_HALT;
 
 	ret = handshake(xhci, &xhci->op_regs->command,
 			CMD_RESET, 0, 250 * 1000);
@@ -350,7 +353,6 @@ static void xhci_event_ring_work(unsigned long arg)
 
 	temp = xhci_readl(xhci, &xhci->ir_set->irq_pending);
 	xhci_dbg(xhci, "ir_set 0 pending = 0x%x\n", temp);
-	xhci_dbg(xhci, "No-op commands handled = %d\n", xhci->noops_handled);
 	xhci_dbg(xhci, "HC error bitmask = 0x%x\n", xhci->error_bitmask);
 	xhci->error_bitmask = 0;
 	xhci_dbg(xhci, "Event ring:\n");
@@ -370,10 +372,6 @@ static void xhci_event_ring_work(unsigned long arg)
 			xhci_dbg_ep_rings(xhci, i, j, &xhci->devs[i]->eps[j]);
 		}
 	}
-
-	if (xhci->noops_submitted != NUM_TEST_NOOPS)
-		if (xhci_setup_one_noop(xhci))
-			xhci_ring_cmd_db(xhci);
 	spin_unlock_irqrestore(&xhci->lock, flags);
 
 	if (!xhci->zombie)
@@ -383,6 +381,21 @@ static void xhci_event_ring_work(unsigned long arg)
 }
 #endif
 
+static int xhci_run_finished(struct xhci_hcd *xhci)
+{
+	if (xhci_start(xhci)) {
+		xhci_halt(xhci);
+		return -ENODEV;
+	}
+	xhci->shared_hcd->state = HC_STATE_RUNNING;
+
+	if (xhci->quirks & XHCI_NEC_HOST)
+		xhci_ring_cmd_db(xhci);
+
+	xhci_dbg(xhci, "Finished xhci_run for USB3 roothub\n");
+	return 0;
+}
+
 /*
  * Start the HC after it was halted.
  *
@@ -402,9 +415,14 @@ int xhci_run(struct usb_hcd *hcd)
 	u32 ret;
 	struct xhci_hcd *xhci = hcd_to_xhci(hcd);
 	struct pci_dev  *pdev = to_pci_dev(xhci_to_hcd(xhci)->self.controller);
-	void (*doorbell)(struct xhci_hcd *) = NULL;
+
+	/* Start the xHCI host controller running only after the USB 2.0 roothub
+	 * is setup.
+	 */
 
 	hcd->uses_new_polling = 1;
+	if (!usb_hcd_is_primary_hcd(hcd))
+		return xhci_run_finished(xhci);
 
 	xhci_dbg(xhci, "xhci_run\n");
 	/* unregister the legacy interrupt */
@@ -461,7 +479,6 @@ int xhci_run(struct usb_hcd *hcd)
 	xhci_writel(xhci, temp, &xhci->ir_set->irq_control);
 
 	/* Set the HCD state before we enable the irqs */
-	hcd->state = HC_STATE_RUNNING;
 	temp = xhci_readl(xhci, &xhci->op_regs->command);
 	temp |= (CMD_EIE);
 	xhci_dbg(xhci, "// Enable interrupts, cmd = 0x%x.\n",
@@ -475,24 +492,27 @@ int xhci_run(struct usb_hcd *hcd)
 			&xhci->ir_set->irq_pending);
 	xhci_print_ir_set(xhci, 0);
 
-	if (NUM_TEST_NOOPS > 0)
-		doorbell = xhci_setup_one_noop(xhci);
 	if (xhci->quirks & XHCI_NEC_HOST)
 		xhci_queue_vendor_command(xhci, 0, 0, 0,
 				TRB_TYPE(TRB_NEC_GET_FW));
 
-	if (xhci_start(xhci)) {
-		xhci_halt(xhci);
-		return -ENODEV;
-	}
+	xhci_dbg(xhci, "Finished xhci_run for USB2 roothub\n");
+	return 0;
+}
 
-	if (doorbell)
-		(*doorbell)(xhci);
-	if (xhci->quirks & XHCI_NEC_HOST)
-		xhci_ring_cmd_db(xhci);
+static void xhci_only_stop_hcd(struct usb_hcd *hcd)
+{
+	struct xhci_hcd *xhci = hcd_to_xhci(hcd);
 
-	xhci_dbg(xhci, "Finished xhci_run\n");
-	return 0;
+	spin_lock_irq(&xhci->lock);
+	xhci_halt(xhci);
+
+	/* The shared_hcd is going to be deallocated shortly (the USB core only
+	 * calls this function when allocation fails in usb_add_hcd(), or
+	 * usb_remove_hcd() is called).  So we need to unset xHCI's pointer.
+	 */
+	xhci->shared_hcd = NULL;
+	spin_unlock_irq(&xhci->lock);
 }
 
 /*
@@ -509,7 +529,15 @@ void xhci_stop(struct usb_hcd *hcd)
 	u32 temp;
 	struct xhci_hcd *xhci = hcd_to_xhci(hcd);
 
+	if (!usb_hcd_is_primary_hcd(hcd)) {
+		xhci_only_stop_hcd(xhci->shared_hcd);
+		return;
+	}
+
 	spin_lock_irq(&xhci->lock);
+	/* Make sure the xHC is halted for a USB3 roothub
+	 * (xhci_stop() could be called as part of failed init).
+	 */
 	xhci_halt(xhci);
 	xhci_reset(xhci);
 	spin_unlock_irq(&xhci->lock);
@@ -542,6 +570,8 @@ void xhci_stop(struct usb_hcd *hcd)
  * This is called when the machine is rebooting or halting.  We assume that the
  * machine will be powered off, and the HC's internal state will be reset.
  * Don't bother to free memory.
+ *
+ * This will only ever be called with the main usb_hcd (the USB3 roothub).
  */
 void xhci_shutdown(struct usb_hcd *hcd)
 {
@@ -657,6 +687,7 @@ int xhci_suspend(struct xhci_hcd *xhci)
 
 	spin_lock_irq(&xhci->lock);
 	clear_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags);
+	clear_bit(HCD_FLAG_HW_ACCESSIBLE, &xhci->shared_hcd->flags);
 	/* step 1: stop endpoint */
 	/* skipped assuming that port suspend has done */
 
@@ -706,10 +737,15 @@ int xhci_resume(struct xhci_hcd *xhci, bool hibernated)
 {
 	u32			command, temp = 0;
 	struct usb_hcd		*hcd = xhci_to_hcd(xhci);
-	int	old_state, retval;
+	struct usb_hcd		*secondary_hcd;
+	int			retval;
 
-	old_state = hcd->state;
-	if (time_before(jiffies, xhci->next_statechange))
+	/* Wait a bit if either of the roothubs need to settle from the
+	 * transistion into bus suspend.
+	 */
+	if (time_before(jiffies, xhci->bus_state[0].next_statechange) ||
+			time_before(jiffies,
+				xhci->bus_state[1].next_statechange))
 		msleep(100);
 
 	spin_lock_irq(&xhci->lock);
@@ -762,16 +798,34 @@ int xhci_resume(struct xhci_hcd *xhci, bool hibernated)
 		xhci_dbg(xhci, "xhci_stop completed - status = %x\n",
 			    xhci_readl(xhci, &xhci->op_regs->status));
 
-		xhci_dbg(xhci, "Initialize the HCD\n");
-		retval = xhci_init(hcd);
+		/* USB core calls the PCI reinit and start functions twice:
+		 * first with the primary HCD, and then with the secondary HCD.
+		 * If we don't do the same, the host will never be started.
+		 */
+		if (!usb_hcd_is_primary_hcd(hcd))
+			secondary_hcd = hcd;
+		else
+			secondary_hcd = xhci->shared_hcd;
+
+		xhci_dbg(xhci, "Initialize the xhci_hcd\n");
+		retval = xhci_init(hcd->primary_hcd);
 		if (retval)
 			return retval;
+		xhci_dbg(xhci, "Start the primary HCD\n");
+		retval = xhci_run(hcd->primary_hcd);
+		if (retval)
+			goto failed_restart;
 
-		xhci_dbg(xhci, "Start the HCD\n");
-		retval = xhci_run(hcd);
-		if (!retval)
+		xhci_dbg(xhci, "Start the secondary HCD\n");
+		retval = xhci_run(secondary_hcd);
+		if (!retval) {
 			set_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags);
+			set_bit(HCD_FLAG_HW_ACCESSIBLE,
+					&xhci->shared_hcd->flags);
+		}
+failed_restart:
 		hcd->state = HC_STATE_SUSPENDED;
+		xhci->shared_hcd->state = HC_STATE_SUSPENDED;
 		return retval;
 	}
 
@@ -792,10 +846,7 @@ int xhci_resume(struct xhci_hcd *xhci, bool hibernated)
 	 */
 
 	set_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags);
-	if (!hibernated)
-		hcd->state = old_state;
-	else
-		hcd->state = HC_STATE_SUSPENDED;
+	set_bit(HCD_FLAG_HW_ACCESSIBLE, &xhci->shared_hcd->flags);
 
 	spin_unlock_irq(&xhci->lock);
 	return 0;
@@ -1167,13 +1218,13 @@ int xhci_urb_dequeue(struct usb_hcd *hcd, struct urb *urb, int status)
 	if (ret || !urb->hcpriv)
 		goto done;
 	temp = xhci_readl(xhci, &xhci->op_regs->status);
-	if (temp == 0xffffffff) {
+	if (temp == 0xffffffff || (xhci->xhc_state & XHCI_STATE_HALTED)) {
 		xhci_dbg(xhci, "HW died, freeing TD.\n");
 		urb_priv = urb->hcpriv;
 
 		usb_hcd_unlink_urb_from_ep(hcd, urb);
 		spin_unlock_irqrestore(&xhci->lock, flags);
-		usb_hcd_giveback_urb(xhci_to_hcd(xhci), urb, -ESHUTDOWN);
+		usb_hcd_giveback_urb(hcd, urb, -ESHUTDOWN);
 		xhci_urb_free_priv(xhci, urb_priv);
 		return ret;
 	}
diff --git a/drivers/usb/host/xhci.h b/drivers/usb/host/xhci.h
index 7f127df6dd55..711de253bc0f 100644
--- a/drivers/usb/host/xhci.h
+++ b/drivers/usb/host/xhci.h
@@ -644,6 +644,9 @@ struct xhci_ep_ctx {
 #define AVG_TRB_LENGTH_FOR_EP(p)	((p) & 0xffff)
 #define MAX_ESIT_PAYLOAD_FOR_EP(p)	(((p) & 0xffff) << 16)
 
+/* deq bitmasks */
+#define EP_CTX_CYCLE_MASK		(1 << 0)
+
 
 /**
  * struct xhci_input_control_context
@@ -746,6 +749,12 @@ struct xhci_virt_ep {
 	struct timer_list	stop_cmd_timer;
 	int			stop_cmds_pending;
 	struct xhci_hcd		*xhci;
+	/* Dequeue pointer and dequeue segment for a submitted Set TR Dequeue
+	 * command.  We'll need to update the ring's dequeue segment and dequeue
+	 * pointer after the command completes.
+	 */
+	struct xhci_segment	*queued_deq_seg;
+	union xhci_trb		*queued_deq_ptr;
 	/*
 	 * Sometimes the xHC can not process isochronous endpoint ring quickly
 	 * enough, and it will miss some isoc tds on the ring and generate
@@ -1161,8 +1170,29 @@ struct s3_save {
 	u64	erst_dequeue;
 };
 
+struct xhci_bus_state {
+	unsigned long		bus_suspended;
+	unsigned long		next_statechange;
+
+	/* Port suspend arrays are indexed by the portnum of the fake roothub */
+	/* ports suspend status arrays - max 31 ports for USB2, 15 for USB3 */
+	u32			port_c_suspend;
+	u32			suspended_ports;
+	unsigned long		resume_done[USB_MAXCHILDREN];
+};
+
+static inline unsigned int hcd_index(struct usb_hcd *hcd)
+{
+	if (hcd->speed == HCD_USB3)
+		return 0;
+	else
+		return 1;
+}
+
 /* There is one ehci_hci structure per controller */
 struct xhci_hcd {
+	struct usb_hcd *main_hcd;
+	struct usb_hcd *shared_hcd;
 	/* glue to PCI and HCD framework */
 	struct xhci_cap_regs __iomem *cap_regs;
 	struct xhci_op_regs __iomem *op_regs;
@@ -1224,9 +1254,6 @@ struct xhci_hcd {
 	/* Host controller watchdog timer structures */
 	unsigned int		xhc_state;
 
-	unsigned long		bus_suspended;
-	unsigned long		next_statechange;
-
 	u32			command;
 	struct s3_save		s3;
 /* Host controller is dying - not responding to commands. "I'm not dead yet!"
@@ -1242,18 +1269,15 @@ struct xhci_hcd {
  * There are no reports of xHCI host controllers that display this issue.
  */
 #define XHCI_STATE_DYING	(1 << 0)
+#define XHCI_STATE_HALTED	(1 << 1)
 	/* Statistics */
-	int			noops_submitted;
-	int			noops_handled;
 	int			error_bitmask;
 	unsigned int		quirks;
 #define	XHCI_LINK_TRB_QUIRK	(1 << 0)
 #define XHCI_RESET_EP_QUIRK	(1 << 1)
 #define XHCI_NEC_HOST		(1 << 2)
-	u32			port_c_suspend[8];	/* port suspend change*/
-	u32			suspended_ports[8];	/* which ports are
-							   suspended */
-	unsigned long		resume_done[MAX_HC_PORTS];
+	/* There are two roothubs to keep track of bus suspend info for */
+	struct xhci_bus_state   bus_state[2];
 	/* Is each xHCI roothub port a USB 3.0, USB 2.0, or USB 1.1 port? */
 	u8			*port_array;
 	/* Array of pointers to USB 3.0 PORTSC registers */
@@ -1264,18 +1288,15 @@ struct xhci_hcd {
 	unsigned int		num_usb2_ports;
 };
 
-/* For testing purposes */
-#define NUM_TEST_NOOPS	0
-
 /* convert between an HCD pointer and the corresponding EHCI_HCD */
 static inline struct xhci_hcd *hcd_to_xhci(struct usb_hcd *hcd)
 {
-	return (struct xhci_hcd *) (hcd->hcd_priv);
+	return *((struct xhci_hcd **) (hcd->hcd_priv));
 }
 
 static inline struct usb_hcd *xhci_to_hcd(struct xhci_hcd *xhci)
 {
-	return container_of((void *) xhci, struct usb_hcd, hcd_priv);
+	return xhci->main_hcd;
 }
 
 #ifdef CONFIG_USB_XHCI_HCD_DEBUGGING
@@ -1471,7 +1492,6 @@ struct xhci_segment *trb_in_td(struct xhci_segment *start_seg,
 		dma_addr_t suspect_dma);
 int xhci_is_vendor_info_code(struct xhci_hcd *xhci, unsigned int trb_comp_code);
 void xhci_ring_cmd_db(struct xhci_hcd *xhci);
-void *xhci_setup_one_noop(struct xhci_hcd *xhci);
 int xhci_queue_slot_control(struct xhci_hcd *xhci, u32 trb_type, u32 slot_id);
 int xhci_queue_address_device(struct xhci_hcd *xhci, dma_addr_t in_ctx_ptr,
 		u32 slot_id);
@@ -1525,7 +1545,8 @@ int xhci_bus_resume(struct usb_hcd *hcd);
 #endif	/* CONFIG_PM */
 
 u32 xhci_port_state_to_neutral(u32 state);
-int xhci_find_slot_id_by_port(struct xhci_hcd *xhci, u16 port);
+int xhci_find_slot_id_by_port(struct usb_hcd *hcd, struct xhci_hcd *xhci,
+		u16 port);
 void xhci_ring_device(struct xhci_hcd *xhci, int slot_id);
 
 /* xHCI contexts */