USB: RK3288 USB CTLR initialization
[firefly-linux-kernel-4.4.55.git] / drivers / usb / host / ehci-hcd.c
index f89f77f1b339f4a73200a95750f3c5200fb84b84..16068290a74f4a221cff76d0d9cc59803cb8705a 100644 (file)
@@ -30,8 +30,7 @@
 #include <linux/vmalloc.h>
 #include <linux/errno.h>
 #include <linux/init.h>
-#include <linux/timer.h>
-#include <linux/ktime.h>
+#include <linux/hrtimer.h>
 #include <linux/list.h>
 #include <linux/interrupt.h>
 #include <linux/usb.h>
 #include <linux/dma-mapping.h>
 #include <linux/debugfs.h>
 #include <linux/slab.h>
-#include <linux/uaccess.h>
 
 #include <asm/byteorder.h>
 #include <asm/io.h>
 #include <asm/irq.h>
-#include <asm/system.h>
 #include <asm/unaligned.h>
 
+#if defined(CONFIG_PPC_PS3)
+#include <asm/firmware.h>
+#endif
+
 /*-------------------------------------------------------------------------*/
 
 /*
@@ -73,10 +74,6 @@ static const char    hcd_name [] = "ehci_hcd";
 #undef VERBOSE_DEBUG
 #undef EHCI_URB_TRACE
 
-#ifdef DEBUG
-#define EHCI_STATS
-#endif
-
 /* magic numbers that can affect system performance */
 #define        EHCI_TUNE_CERR          3       /* 0-3 qtd retries; 0 == don't stop */
 #define        EHCI_TUNE_RL_HS         4       /* nak throttle; see 4.9 */
@@ -91,12 +88,6 @@ static const char    hcd_name [] = "ehci_hcd";
  */
 #define        EHCI_TUNE_FLS           1       /* (medium) 512-frame schedule */
 
-#define EHCI_IAA_MSECS         10              /* arbitrary */
-#define EHCI_IO_JIFFIES                (HZ/10)         /* io watchdog > irq_thresh */
-#define EHCI_ASYNC_JIFFIES     (HZ/20)         /* async idle timeout */
-#define EHCI_SHRINK_JIFFIES    (DIV_ROUND_UP(HZ, 200) + 1)
-                                               /* 200-ms async qh unlink delay */
-
 /* Initial IRQ latency:  faster than hw default */
 static int log2_irq_thresh = 0;                // 0 to 6
 module_param (log2_irq_thresh, int, S_IRUGO);
@@ -108,58 +99,43 @@ module_param (park, uint, S_IRUGO);
 MODULE_PARM_DESC (park, "park setting; 1-3 back-to-back async packets");
 
 /* for flakey hardware, ignore overcurrent indicators */
-static int ignore_oc = 0;
+static bool ignore_oc = 0;
 module_param (ignore_oc, bool, S_IRUGO);
 MODULE_PARM_DESC (ignore_oc, "ignore bogus hardware overcurrent indications");
 
-/* for link power management(LPM) feature */
-static unsigned int hird;
-module_param(hird, int, S_IRUGO);
-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)
 
 /*-------------------------------------------------------------------------*/
 
 #include "ehci.h"
-#include "ehci-dbg.c"
 #include "pci-quirks.h"
 
-/*-------------------------------------------------------------------------*/
-
-static void
-timer_action(struct ehci_hcd *ehci, enum ehci_timer_action action)
+/*
+ * The MosChip MCS9990 controller updates its microframe counter
+ * a little before the frame counter, and occasionally we will read
+ * the invalid intermediate value.  Avoid problems by checking the
+ * microframe number (the low-order 3 bits); if they are 0 then
+ * re-read the register to get the correct value.
+ */
+static unsigned ehci_moschip_read_frame_index(struct ehci_hcd *ehci)
 {
-       /* Don't override timeouts which shrink or (later) disable
-        * the async ring; just the I/O watchdog.  Note that if a
-        * SHRINK were pending, OFF would never be requested.
-        */
-       if (timer_pending(&ehci->watchdog)
-                       && ((BIT(TIMER_ASYNC_SHRINK) | BIT(TIMER_ASYNC_OFF))
-                               & ehci->actions))
-               return;
+       unsigned uf;
 
-       if (!test_and_set_bit(action, &ehci->actions)) {
-               unsigned long t;
+       uf = ehci_readl(ehci, &ehci->regs->frame_index);
+       if (unlikely((uf & 7) == 0))
+               uf = ehci_readl(ehci, &ehci->regs->frame_index);
+       return uf;
+}
 
-               switch (action) {
-               case TIMER_IO_WATCHDOG:
-                       if (!ehci->need_io_watchdog)
-                               return;
-                       t = EHCI_IO_JIFFIES;
-                       break;
-               case TIMER_ASYNC_OFF:
-                       t = EHCI_ASYNC_JIFFIES;
-                       break;
-               /* case TIMER_ASYNC_SHRINK: */
-               default:
-                       t = EHCI_SHRINK_JIFFIES;
-                       break;
-               }
-               mod_timer(&ehci->watchdog, t + jiffies);
-       }
+static inline unsigned ehci_read_frame_index(struct ehci_hcd *ehci)
+{
+       if (ehci->frame_index_bug)
+               return ehci_moschip_read_frame_index(ehci);
+       return ehci_readl(ehci, &ehci->regs->frame_index);
 }
 
+#include "ehci-dbg.c"
+
 /*-------------------------------------------------------------------------*/
 
 /*
@@ -200,60 +176,52 @@ static int handshake (struct ehci_hcd *ehci, void __iomem *ptr,
 /* check TDI/ARC silicon is in host mode */
 static int tdi_in_host_mode (struct ehci_hcd *ehci)
 {
-       u32 __iomem     *reg_ptr;
        u32             tmp;
 
-       reg_ptr = (u32 __iomem *)(((u8 __iomem *)ehci->regs) + USBMODE);
-       tmp = ehci_readl(ehci, reg_ptr);
+       tmp = ehci_readl(ehci, &ehci->regs->usbmode);
        return (tmp & 3) == USBMODE_CM_HC;
 }
 
-/* force HC to halt state from unknown (EHCI spec section 2.3) */
+/*
+ * Force HC to halt state from unknown (EHCI spec section 2.3).
+ * Must be called with interrupts enabled and the lock not held.
+ */
 static int ehci_halt (struct ehci_hcd *ehci)
 {
-       u32     temp = ehci_readl(ehci, &ehci->regs->status);
+       u32     temp;
+
+       spin_lock_irq(&ehci->lock);
 
        /* disable any irqs left enabled by previous code */
        ehci_writel(ehci, 0, &ehci->regs->intr_enable);
 
-       if (ehci_is_TDI(ehci) && tdi_in_host_mode(ehci) == 0) {
+       if (ehci_is_TDI(ehci) && !tdi_in_host_mode(ehci)) {
+               spin_unlock_irq(&ehci->lock);
                return 0;
        }
 
-       if ((temp & STS_HALT) != 0)
-               return 0;
-
+       /*
+        * This routine gets called during probe before ehci->command
+        * has been initialized, so we can't rely on its value.
+        */
+       ehci->command &= ~CMD_RUN;
        temp = ehci_readl(ehci, &ehci->regs->command);
-       temp &= ~CMD_RUN;
+       temp &= ~(CMD_RUN | CMD_IAAD);
        ehci_writel(ehci, temp, &ehci->regs->command);
-       return handshake (ehci, &ehci->regs->status,
-                         STS_HALT, STS_HALT, 16 * 125);
-}
 
-static int handshake_on_error_set_halt(struct ehci_hcd *ehci, void __iomem *ptr,
-                                      u32 mask, u32 done, int usec)
-{
-       int error;
-
-       error = handshake(ehci, ptr, mask, done, usec);
-       if (error) {
-               ehci_halt(ehci);
-               ehci_to_hcd(ehci)->state = HC_STATE_HALT;
-               ehci_err(ehci, "force halt; handshake %p %08x %08x -> %d\n",
-                       ptr, mask, done, error);
-       }
+       spin_unlock_irq(&ehci->lock);
+       synchronize_irq(ehci_to_hcd(ehci)->irq);
 
-       return error;
+       return handshake(ehci, &ehci->regs->status,
+                         STS_HALT, STS_HALT, 16 * 125);
 }
 
 /* put TDI/ARC silicon into EHCI mode */
 static void tdi_reset (struct ehci_hcd *ehci)
 {
-       u32 __iomem     *reg_ptr;
        u32             tmp;
 
-       reg_ptr = (u32 __iomem *)(((u8 __iomem *)ehci->regs) + USBMODE);
-       tmp = ehci_readl(ehci, reg_ptr);
+       tmp = ehci_readl(ehci, &ehci->regs->usbmode);
        tmp |= USBMODE_CM_HC;
        /* The default byte access to MMR space is LE after
         * controller reset. Set the required endian mode
@@ -261,10 +229,13 @@ static void tdi_reset (struct ehci_hcd *ehci)
         */
        if (ehci_big_endian_mmio(ehci))
                tmp |= USBMODE_BE;
-       ehci_writel(ehci, tmp, reg_ptr);
+       ehci_writel(ehci, tmp, &ehci->regs->usbmode);
 }
 
-/* reset a non-running (STS_HALT == 1) controller */
+/*
+ * Reset a non-running (STS_HALT == 1) controller.
+ * Must be called with interrupts enabled and the lock not held.
+ */
 static int ehci_reset (struct ehci_hcd *ehci)
 {
        int     retval;
@@ -272,22 +243,21 @@ static int ehci_reset (struct ehci_hcd *ehci)
 
        /* If the EHCI debug controller is active, special care must be
         * taken before and after a host controller reset */
-       if (ehci->debug && !dbgp_reset_prep())
+       if (ehci->debug && !dbgp_reset_prep(ehci_to_hcd(ehci)))
                ehci->debug = NULL;
 
        command |= CMD_RESET;
        dbg_cmd (ehci, "reset", command);
        ehci_writel(ehci, command, &ehci->regs->command);
-       ehci_to_hcd(ehci)->state = HC_STATE_HALT;
+       ehci->rh_state = EHCI_RH_HALTED;
        ehci->next_statechange = jiffies;
        retval = handshake (ehci, &ehci->regs->command,
                            CMD_RESET, 0, 250 * 1000);
 
        if (ehci->has_hostpc) {
                ehci_writel(ehci, USBMODE_EX_HC | USBMODE_EX_VBPS,
-                       (u32 __iomem *)(((u8 *)ehci->regs) + USBMODE_EX));
-               ehci_writel(ehci, TXFIFO_DEFAULT,
-                       (u32 __iomem *)(((u8 *)ehci->regs) + TXFILLTUNING));
+                               &ehci->regs->usbmode_ex);
+               ehci_writel(ehci, TXFIFO_DEFAULT, &ehci->regs->txfill_tuning);
        }
        if (retval)
                return retval;
@@ -296,116 +266,56 @@ static int ehci_reset (struct ehci_hcd *ehci)
                tdi_reset (ehci);
 
        if (ehci->debug)
-               dbgp_external_startup();
+               dbgp_external_startup(ehci_to_hcd(ehci));
 
+       ehci->port_c_suspend = ehci->suspended_ports =
+                       ehci->resuming_ports = 0;
        return retval;
 }
 
-/* idle the controller (from running) */
+/*
+ * Idle the controller (turn off the schedules).
+ * Must be called with interrupts enabled and the lock not held.
+ */
 static void ehci_quiesce (struct ehci_hcd *ehci)
 {
        u32     temp;
 
-#ifdef DEBUG
-       if (!HC_IS_RUNNING (ehci_to_hcd(ehci)->state))
-               BUG ();
-#endif
+       if (ehci->rh_state != EHCI_RH_RUNNING)
+               return;
 
        /* wait for any schedule enables/disables to take effect */
-       temp = ehci_readl(ehci, &ehci->regs->command) << 10;
-       temp &= STS_ASS | STS_PSS;
-       if (handshake_on_error_set_halt(ehci, &ehci->regs->status,
-                                       STS_ASS | STS_PSS, temp, 16 * 125))
-               return;
+       temp = (ehci->command << 10) & (STS_ASS | STS_PSS);
+       handshake(ehci, &ehci->regs->status, STS_ASS | STS_PSS, temp, 16 * 125);
 
        /* then disable anything that's still active */
-       temp = ehci_readl(ehci, &ehci->regs->command);
-       temp &= ~(CMD_ASE | CMD_IAAD | CMD_PSE);
-       ehci_writel(ehci, temp, &ehci->regs->command);
+       spin_lock_irq(&ehci->lock);
+       ehci->command &= ~(CMD_ASE | CMD_PSE);
+       ehci_writel(ehci, ehci->command, &ehci->regs->command);
+       spin_unlock_irq(&ehci->lock);
 
        /* hardware can take 16 microframes to turn off ... */
-       handshake_on_error_set_halt(ehci, &ehci->regs->status,
-                                   STS_ASS | STS_PSS, 0, 16 * 125);
+       handshake(ehci, &ehci->regs->status, STS_ASS | STS_PSS, 0, 16 * 125);
 }
 
 /*-------------------------------------------------------------------------*/
 
 static void end_unlink_async(struct ehci_hcd *ehci);
+static void unlink_empty_async(struct ehci_hcd *ehci);
+static void unlink_empty_async_suspended(struct ehci_hcd *ehci);
 static void ehci_work(struct ehci_hcd *ehci);
+static void start_unlink_intr(struct ehci_hcd *ehci, struct ehci_qh *qh);
+static void end_unlink_intr(struct ehci_hcd *ehci, struct ehci_qh *qh);
 
+#include "ehci-timer.c"
 #include "ehci-hub.c"
-#include "ehci-lpm.c"
 #include "ehci-mem.c"
 #include "ehci-q.c"
 #include "ehci-sched.c"
+#include "ehci-sysfs.c"
 
 /*-------------------------------------------------------------------------*/
 
-static void ehci_iaa_watchdog(unsigned long param)
-{
-       struct ehci_hcd         *ehci = (struct ehci_hcd *) param;
-       unsigned long           flags;
-
-       spin_lock_irqsave (&ehci->lock, flags);
-
-       /* Lost IAA irqs wedge things badly; seen first with a vt8235.
-        * So we need this watchdog, but must protect it against both
-        * (a) SMP races against real IAA firing and retriggering, and
-        * (b) clean HC shutdown, when IAA watchdog was pending.
-        */
-       if (ehci->reclaim
-                       && !timer_pending(&ehci->iaa_watchdog)
-                       && HC_IS_RUNNING(ehci_to_hcd(ehci)->state)) {
-               u32 cmd, status;
-
-               /* If we get here, IAA is *REALLY* late.  It's barely
-                * conceivable that the system is so busy that CMD_IAAD
-                * is still legitimately set, so let's be sure it's
-                * clear before we read STS_IAA.  (The HC should clear
-                * CMD_IAAD when it sets STS_IAA.)
-                */
-               cmd = ehci_readl(ehci, &ehci->regs->command);
-               if (cmd & CMD_IAAD)
-                       ehci_writel(ehci, cmd & ~CMD_IAAD,
-                                       &ehci->regs->command);
-
-               /* If IAA is set here it either legitimately triggered
-                * before we cleared IAAD above (but _way_ late, so we'll
-                * still count it as lost) ... or a silicon erratum:
-                * - VIA seems to set IAA without triggering the IRQ;
-                * - IAAD potentially cleared without setting IAA.
-                */
-               status = ehci_readl(ehci, &ehci->regs->status);
-               if ((status & STS_IAA) || !(cmd & CMD_IAAD)) {
-                       COUNT (ehci->stats.lost_iaa);
-                       ehci_writel(ehci, STS_IAA, &ehci->regs->status);
-               }
-
-               ehci_vdbg(ehci, "IAA watchdog: status %x cmd %x\n",
-                               status, cmd);
-               end_unlink_async(ehci);
-       }
-
-       spin_unlock_irqrestore(&ehci->lock, flags);
-}
-
-static void ehci_watchdog(unsigned long param)
-{
-       struct ehci_hcd         *ehci = (struct ehci_hcd *) param;
-       unsigned long           flags;
-
-       spin_lock_irqsave(&ehci->lock, flags);
-
-       /* stop async processing after it's idled a bit */
-       if (test_bit (TIMER_ASYNC_OFF, &ehci->actions))
-               start_unlink_async (ehci, ehci->async);
-
-       /* ehci could run by timer, without IRQs ... */
-       ehci_work (ehci);
-
-       spin_unlock_irqrestore (&ehci->lock, flags);
-}
-
 /* On some systems, leaving remote wakeup enabled prevents system shutdown.
  * The firmware seems to think that powering off is a wakeup event!
  * This routine turns off remote wakeup and everything else, on all ports.
@@ -421,11 +331,14 @@ static void ehci_turn_off_all_ports(struct ehci_hcd *ehci)
 
 /*
  * Halt HC, turn off all ports, and let the BIOS use the companion controllers.
- * Should be called with ehci->lock held.
+ * Must be called with interrupts enabled and the lock not held.
  */
 static void ehci_silence_controller(struct ehci_hcd *ehci)
 {
        ehci_halt(ehci);
+
+       spin_lock_irq(&ehci->lock);
+       ehci->rh_state = EHCI_RH_HALTED;
        ehci_turn_off_all_ports(ehci);
 
        /* make BIOS/etc use companion controller during reboot */
@@ -433,6 +346,7 @@ static void ehci_silence_controller(struct ehci_hcd *ehci)
 
        /* unblock posted writes */
        ehci_readl(ehci, &ehci->regs->configured_flag);
+       spin_unlock_irq(&ehci->lock);
 }
 
 /* ehci_shutdown kick in for silicon on any bus (not just pci, etc).
@@ -443,30 +357,15 @@ static void ehci_shutdown(struct usb_hcd *hcd)
 {
        struct ehci_hcd *ehci = hcd_to_ehci(hcd);
 
-       del_timer_sync(&ehci->watchdog);
-       del_timer_sync(&ehci->iaa_watchdog);
-
        spin_lock_irq(&ehci->lock);
-       ehci_silence_controller(ehci);
+       ehci->shutdown = true;
+       ehci->rh_state = EHCI_RH_STOPPING;
+       ehci->enabled_hrtimer_events = 0;
        spin_unlock_irq(&ehci->lock);
-}
 
-static void ehci_port_power (struct ehci_hcd *ehci, int is_on)
-{
-       unsigned port;
-
-       if (!HCS_PPC (ehci->hcs_params))
-               return;
+       ehci_silence_controller(ehci);
 
-       ehci_dbg (ehci, "...power%s ports...\n", is_on ? "up" : "down");
-       for (port = HCS_N_PORTS (ehci->hcs_params); port > 0; )
-               (void) ehci_hub_control(ehci_to_hcd(ehci),
-                               is_on ? SetPortFeature : ClearPortFeature,
-                               USB_PORT_FEAT_POWER,
-                               port--, NULL, 0);
-       /* Flush those writes */
-       ehci_readl(ehci, &ehci->regs->command);
-       msleep(20);
+       hrtimer_cancel(&ehci->hrtimer);
 }
 
 /*-------------------------------------------------------------------------*/
@@ -477,28 +376,33 @@ static void ehci_port_power (struct ehci_hcd *ehci, int is_on)
  */
 static void ehci_work (struct ehci_hcd *ehci)
 {
-       timer_action_done (ehci, TIMER_IO_WATCHDOG);
-
        /* another CPU may drop ehci->lock during a schedule scan while
         * it reports urb completions.  this flag guards against bogus
         * attempts at re-entrant schedule scanning.
         */
-       if (ehci->scanning)
+       if (ehci->scanning) {
+               ehci->need_rescan = true;
                return;
-       ehci->scanning = 1;
-       scan_async (ehci);
-       if (ehci->next_uframe != -1)
-               scan_periodic (ehci);
-       ehci->scanning = 0;
+       }
+       ehci->scanning = true;
+
+ rescan:
+       ehci->need_rescan = false;
+       if (ehci->async_count)
+               scan_async(ehci);
+       if (ehci->intr_count > 0)
+               scan_intr(ehci);
+       if (ehci->isoc_count > 0)
+               scan_isoc(ehci);
+       if (ehci->need_rescan)
+               goto rescan;
+       ehci->scanning = false;
 
        /* the IO watchdog guards against hardware or driver bugs that
         * misplace IRQs, and should let us run completely without IRQs.
         * such lossage has been observed on both VT6202 and VT8235.
         */
-       if (HC_IS_RUNNING (ehci_to_hcd(ehci)->state) &&
-                       (ehci->async->qh_next.ptr != NULL ||
-                        ehci->periodic_sched != 0))
-               timer_action (ehci, TIMER_IO_WATCHDOG);
+       turn_on_io_watchdog(ehci);
 }
 
 /*
@@ -511,24 +415,22 @@ static void ehci_stop (struct usb_hcd *hcd)
        ehci_dbg (ehci, "stop\n");
 
        /* no more interrupts ... */
-       del_timer_sync (&ehci->watchdog);
-       del_timer_sync(&ehci->iaa_watchdog);
 
        spin_lock_irq(&ehci->lock);
-       if (HC_IS_RUNNING (hcd->state))
-               ehci_quiesce (ehci);
+       ehci->enabled_hrtimer_events = 0;
+       spin_unlock_irq(&ehci->lock);
 
+       ehci_quiesce(ehci);
        ehci_silence_controller(ehci);
        ehci_reset (ehci);
-       spin_unlock_irq(&ehci->lock);
 
-       remove_companion_file(ehci);
+       hrtimer_cancel(&ehci->hrtimer);
+       remove_sysfs_files(ehci);
        remove_debug_files (ehci);
 
        /* root hub is shut down separately (first, when possible) */
        spin_lock_irq (&ehci->lock);
-       if (ehci->async)
-               ehci_work (ehci);
+       end_free_itds(ehci);
        spin_unlock_irq (&ehci->lock);
        ehci_mem_cleanup (ehci);
 
@@ -536,8 +438,8 @@ static void ehci_stop (struct usb_hcd *hcd)
                usb_amd_dev_put();
 
 #ifdef EHCI_STATS
-       ehci_dbg (ehci, "irq normal %ld err %ld reclaim %ld (lost %ld)\n",
-               ehci->stats.normal, ehci->stats.error, ehci->stats.reclaim,
+       ehci_dbg(ehci, "irq normal %ld err %ld iaa %ld (lost %ld)\n",
+               ehci->stats.normal, ehci->stats.error, ehci->stats.iaa,
                ehci->stats.lost_iaa);
        ehci_dbg (ehci, "complete %ld unlink %ld\n",
                ehci->stats.complete, ehci->stats.unlink);
@@ -562,21 +464,28 @@ static int ehci_init(struct usb_hcd *hcd)
         * keep io watchdog by default, those good HCDs could turn off it later
         */
        ehci->need_io_watchdog = 1;
-       init_timer(&ehci->watchdog);
-       ehci->watchdog.function = ehci_watchdog;
-       ehci->watchdog.data = (unsigned long) ehci;
 
-       init_timer(&ehci->iaa_watchdog);
-       ehci->iaa_watchdog.function = ehci_iaa_watchdog;
-       ehci->iaa_watchdog.data = (unsigned long) ehci;
+       hrtimer_init(&ehci->hrtimer, CLOCK_MONOTONIC, HRTIMER_MODE_ABS);
+       ehci->hrtimer.function = ehci_hrtimer_func;
+       ehci->next_hrtimer_event = EHCI_HRTIMER_NO_EVENT;
 
        hcc_params = ehci_readl(ehci, &ehci->caps->hcc_params);
 
+       /*
+        * by default set standard 80% (== 100 usec/uframe) max periodic
+        * bandwidth as required by USB 2.0
+        */
+       ehci->uframe_periodic_max = 100;
+
        /*
         * hw default: 1K periodic list heads, one per frame.
         * periodic_size can shrink by USBCMD update if hcc_params allows.
         */
        ehci->periodic_size = DEFAULT_I_TDPS;
+       INIT_LIST_HEAD(&ehci->async_unlink);
+       INIT_LIST_HEAD(&ehci->async_idle);
+       INIT_LIST_HEAD(&ehci->intr_unlink);
+       INIT_LIST_HEAD(&ehci->intr_qh_list);
        INIT_LIST_HEAD(&ehci->cached_itd_list);
        INIT_LIST_HEAD(&ehci->cached_sitd_list);
 
@@ -594,14 +503,10 @@ static int ehci_init(struct usb_hcd *hcd)
 
        /* controllers may cache some of the periodic schedule ... */
        if (HCC_ISOC_CACHE(hcc_params))         // full frame cache
-               ehci->i_thresh = 2 + 8;
+               ehci->i_thresh = 0;
        else                                    // N microframes cached
                ehci->i_thresh = 2 + HCC_ISOC_THRES(hcc_params);
 
-       ehci->reclaim = NULL;
-       ehci->next_uframe = -1;
-       ehci->clock_frame = -1;
-
        /*
         * dedicate a qh for the async ring head, since we couldn't unlink
         * a 'real' qh without stopping the async schedule [4.8].  use it
@@ -613,6 +518,9 @@ static int ehci_init(struct usb_hcd *hcd)
        hw = ehci->async->hw;
        hw->hw_next = QH_NEXT(ehci, ehci->async->qh_dma);
        hw->hw_info1 = cpu_to_hc32(ehci, QH_HEAD);
+#if defined(CONFIG_PPC_PS3)
+       hw->hw_info1 |= cpu_to_hc32(ehci, QH_INACTIVATE);
+#endif
        hw->hw_token = cpu_to_hc32(ehci, QTD_STS_HALT);
        hw->hw_qtd_next = EHCI_LIST_END(ehci);
        ehci->async->qh_state = QH_STATE_LINKED;
@@ -647,17 +555,6 @@ static int ehci_init(struct usb_hcd *hcd)
                temp &= ~(3 << 2);
                temp |= (EHCI_TUNE_FLS << 2);
        }
-       if (HCC_LPM(hcc_params)) {
-               /* support link power management EHCI 1.1 addendum */
-               ehci_dbg(ehci, "support lpm\n");
-               ehci->has_lpm = 1;
-               if (hird > 0xf) {
-                       ehci_dbg(ehci, "hird %d invalid, use default 0",
-                       hird);
-                       hird = 0;
-               }
-               temp |= hird << 24;
-       }
        ehci->command = temp;
 
        /* Accept arbitrarily long scatter-gather lists */
@@ -670,22 +567,13 @@ static int ehci_init(struct usb_hcd *hcd)
 static int ehci_run (struct usb_hcd *hcd)
 {
        struct ehci_hcd         *ehci = hcd_to_ehci (hcd);
-       int                     retval;
        u32                     temp;
        u32                     hcc_params;
 
        hcd->uses_new_polling = 1;
 
        /* EHCI spec section 4.1 */
-       /*
-        * 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;
-       }
+
        ehci_writel(ehci, ehci->periodic_dma, &ehci->regs->frame_list);
        ehci_writel(ehci, (u32)ehci->async->qh_dma, &ehci->regs->async_next);
 
@@ -734,7 +622,7 @@ static int ehci_run (struct usb_hcd *hcd)
         * be started before the port switching actions could complete.
         */
        down_write(&ehci_cf_port_reset_rwsem);
-       hcd->state = HC_STATE_RUNNING;
+       ehci->rh_state = EHCI_RH_RUNNING;
        ehci_writel(ehci, FLAG_CF, &ehci->regs->configured_flag);
        ehci_readl(ehci, &ehci->regs->command); /* unblock posted writes */
        msleep(5);
@@ -756,12 +644,12 @@ static int ehci_run (struct usb_hcd *hcd)
         * since the class device isn't created that early.
         */
        create_debug_files(ehci);
-       create_companion_file(ehci);
+       create_sysfs_files(ehci);
 
        return 0;
 }
 
-static int __maybe_unused ehci_setup (struct usb_hcd *hcd)
+int ehci_setup(struct usb_hcd *hcd)
 {
        struct ehci_hcd *ehci = hcd_to_ehci(hcd);
        int retval;
@@ -776,12 +664,12 @@ static int __maybe_unused ehci_setup (struct usb_hcd *hcd)
 
        ehci->sbrn = HCD_USB2;
 
-       retval = ehci_halt(ehci);
+       /* data structure init */
+       retval = ehci_init(hcd);
        if (retval)
                return retval;
 
-       /* data structure init */
-       retval = ehci_init(hcd);
+       retval = ehci_halt(ehci);
        if (retval)
                return retval;
 
@@ -789,6 +677,7 @@ static int __maybe_unused ehci_setup (struct usb_hcd *hcd)
 
        return 0;
 }
+EXPORT_SYMBOL_GPL(ehci_setup);
 
 /*-------------------------------------------------------------------------*/
 
@@ -815,7 +704,7 @@ static irqreturn_t ehci_irq (struct usb_hcd *hcd)
        masked_status = status & (INTR_MASK | STS_FLR);
 
        /* Shared IRQ? */
-       if (!masked_status || unlikely(hcd->state == HC_STATE_HALT)) {
+       if (!masked_status || unlikely(ehci->rh_state == EHCI_RH_HALTED)) {
                spin_unlock(&ehci->lock);
                return IRQ_NONE;
        }
@@ -843,29 +732,38 @@ static irqreturn_t ehci_irq (struct usb_hcd *hcd)
 
        /* complete the unlinking of some qh [4.15.2.3] */
        if (status & STS_IAA) {
+
+               /* Turn off the IAA watchdog */
+               ehci->enabled_hrtimer_events &= ~BIT(EHCI_HRTIMER_IAA_WATCHDOG);
+
+               /*
+                * Mild optimization: Allow another IAAD to reset the
+                * hrtimer, if one occurs before the next expiration.
+                * In theory we could always cancel the hrtimer, but
+                * tests show that about half the time it will be reset
+                * for some other event anyway.
+                */
+               if (ehci->next_hrtimer_event == EHCI_HRTIMER_IAA_WATCHDOG)
+                       ++ehci->next_hrtimer_event;
+
                /* guard against (alleged) silicon errata */
-               if (cmd & CMD_IAAD) {
-                       ehci_writel(ehci, cmd & ~CMD_IAAD,
-                                       &ehci->regs->command);
+               if (cmd & CMD_IAAD)
                        ehci_dbg(ehci, "IAA with IAAD still set?\n");
-               }
-               if (ehci->reclaim) {
-                       COUNT(ehci->stats.reclaim);
-                       end_unlink_async(ehci);
-               } else
-                       ehci_dbg(ehci, "IAA with nothing to reclaim?\n");
+               if (ehci->iaa_in_progress)
+                       COUNT(ehci->stats.iaa);
+               end_unlink_async(ehci);
        }
 
        /* remote wakeup [4.3.1] */
        if (status & STS_PCD) {
                unsigned        i = HCS_N_PORTS (ehci->hcs_params);
-               u32             ppcd = 0;
+               u32             ppcd = ~0;
 
                /* kick root hub later */
                pcd_status = status;
 
                /* resume root hub? */
-               if (hcd->state == HC_STATE_SUSPENDED)
+               if (ehci->rh_state == EHCI_RH_SUSPENDED)
                        usb_hcd_resume_root_hub(hcd);
 
                /* get per-port change detect bits */
@@ -876,7 +774,7 @@ static irqreturn_t ehci_irq (struct usb_hcd *hcd)
                        int pstatus;
 
                        /* leverage per-port change bits feature */
-                       if (ehci->has_ppcd && !(ppcd & (1 << i)))
+                       if (!(ppcd & (1 << i)))
                                continue;
                        pstatus = ehci_readl(ehci,
                                         &ehci->regs->port_status[i]);
@@ -896,7 +794,9 @@ static irqreturn_t ehci_irq (struct usb_hcd *hcd)
                         * like usb_port_resume() does.
                         */
                        ehci->reset_done[i] = jiffies + msecs_to_jiffies(25);
+                       set_bit(i, &ehci->resuming_ports);
                        ehci_dbg (ehci, "port %d remote wakeup\n", i + 1);
+                       usb_hcd_start_port_resume(&hcd->self, i);
                        mod_timer(&hcd->rh_timer, ehci->reset_done[i]);
                }
        }
@@ -906,15 +806,19 @@ static irqreturn_t ehci_irq (struct usb_hcd *hcd)
                ehci_err(ehci, "fatal error\n");
                dbg_cmd(ehci, "fatal", cmd);
                dbg_status(ehci, "fatal", status);
-               ehci_halt(ehci);
 dead:
-               ehci_reset(ehci);
-               ehci_writel(ehci, 0, &ehci->regs->configured_flag);
                usb_hc_died(hcd);
-               /* generic layer kills/unlinks all urbs, then
-                * uses ehci_stop to clean up the rest
-                */
-               bh = 1;
+
+               /* Don't let the controller do anything more */
+               ehci->shutdown = true;
+               ehci->rh_state = EHCI_RH_STOPPING;
+               ehci->command &= ~(CMD_RUN | CMD_ASE | CMD_PSE);
+               ehci_writel(ehci, ehci->command, &ehci->regs->command);
+               ehci_writel(ehci, 0, &ehci->regs->intr_enable);
+               ehci_handle_controller_death(ehci);
+
+               /* Handle completions when the controller stops */
+               bh = 0;
        }
 
        if (bh)
@@ -976,38 +880,6 @@ static int ehci_urb_enqueue (
        }
 }
 
-static void unlink_async (struct ehci_hcd *ehci, struct ehci_qh *qh)
-{
-       /* failfast */
-       if (!HC_IS_RUNNING(ehci_to_hcd(ehci)->state) && ehci->reclaim)
-               end_unlink_async(ehci);
-
-       /* If the QH isn't linked then there's nothing we can do
-        * unless we were called during a giveback, in which case
-        * qh_completions() has to deal with it.
-        */
-       if (qh->qh_state != QH_STATE_LINKED) {
-               if (qh->qh_state == QH_STATE_COMPLETING)
-                       qh->needs_rescan = 1;
-               return;
-       }
-
-       /* defer till later if busy */
-       if (ehci->reclaim) {
-               struct ehci_qh          *last;
-
-               for (last = ehci->reclaim;
-                               last->reclaim;
-                               last = last->reclaim)
-                       continue;
-               qh->qh_state = QH_STATE_UNLINK_WAIT;
-               last->reclaim = qh;
-
-       /* start IAA cycle */
-       } else
-               start_unlink_async (ehci, qh);
-}
-
 /* remove from hardware lists
  * completions normally happen asynchronously
  */
@@ -1024,17 +896,24 @@ static int ehci_urb_dequeue(struct usb_hcd *hcd, struct urb *urb, int status)
        if (rc)
                goto done;
 
-       switch (usb_pipetype (urb->pipe)) {
-       // case PIPE_CONTROL:
-       // case PIPE_BULK:
-       default:
+       if (usb_pipetype(urb->pipe) == PIPE_ISOCHRONOUS) {
+               /*
+                * We don't expedite dequeue for isochronous URBs.
+                * Just wait until they complete normally or their
+                * time slot expires.
+                */
+       } else {
                qh = (struct ehci_qh *) urb->hcpriv;
-               if (!qh)
-                       break;
+               qh->exception = 1;
                switch (qh->qh_state) {
                case QH_STATE_LINKED:
+                       if (usb_pipetype(urb->pipe) == PIPE_INTERRUPT)
+                               start_unlink_intr(ehci, qh);
+                       else
+                               start_unlink_async(ehci, qh);
+                       break;
                case QH_STATE_COMPLETING:
-                       unlink_async(ehci, qh);
+                       qh->dequeue_during_giveback = 1;
                        break;
                case QH_STATE_UNLINK:
                case QH_STATE_UNLINK_WAIT:
@@ -1045,33 +924,6 @@ static int ehci_urb_dequeue(struct usb_hcd *hcd, struct urb *urb, int status)
                        qh_completions(ehci, qh);
                        break;
                }
-               break;
-
-       case PIPE_INTERRUPT:
-               qh = (struct ehci_qh *) urb->hcpriv;
-               if (!qh)
-                       break;
-               switch (qh->qh_state) {
-               case QH_STATE_LINKED:
-               case QH_STATE_COMPLETING:
-                       intr_deschedule (ehci, qh);
-                       break;
-               case QH_STATE_IDLE:
-                       qh_completions (ehci, qh);
-                       break;
-               default:
-                       ehci_dbg (ehci, "bogus qh %p state %d\n",
-                                       qh, qh->qh_state);
-                       goto done;
-               }
-               break;
-
-       case PIPE_ISOCHRONOUS:
-               // itd or sitd ...
-
-               // wait till next completion, do it then.
-               // completion irqs can wait up to 1024 msec,
-               break;
        }
 done:
        spin_unlock_irqrestore (&ehci->lock, flags);
@@ -1102,11 +954,18 @@ rescan:
         * accelerate iso completions ... so spin a while.
         */
        if (qh->hw == NULL) {
-               ehci_vdbg (ehci, "iso delay\n");
-               goto idle_timeout;
+               struct ehci_iso_stream  *stream = ep->hcpriv;
+
+               if (!list_empty(&stream->td_list))
+                       goto idle_timeout;
+
+               /* BUG_ON(!list_empty(&stream->free_list)); */
+               kfree(stream);
+               goto done;
        }
 
-       if (!HC_IS_RUNNING (hcd->state))
+       qh->exception = 1;
+       if (ehci->rh_state < EHCI_RH_RUNNING)
                qh->qh_state = QH_STATE_IDLE;
        switch (qh->qh_state) {
        case QH_STATE_LINKED:
@@ -1119,7 +978,7 @@ rescan:
                 * may already be unlinked.
                 */
                if (tmp)
-                       unlink_async(ehci, qh);
+                       start_unlink_async(ehci, qh);
                /* FALL THROUGH */
        case QH_STATE_UNLINK:           /* wait for hw to finish? */
        case QH_STATE_UNLINK_WAIT:
@@ -1131,7 +990,7 @@ idle_timeout:
                if (qh->clearing_tt)
                        goto idle_timeout;
                if (list_empty (&qh->qtd_list)) {
-                       qh_put (qh);
+                       qh_destroy(ehci, qh);
                        break;
                }
                /* else FALL THROUGH */
@@ -1144,8 +1003,8 @@ idle_timeout:
                        list_empty (&qh->qtd_list) ? "" : "(has tds)");
                break;
        }
+ done:
        ep->hcpriv = NULL;
-done:
        spin_unlock_irqrestore (&ehci->lock, flags);
 }
 
@@ -1174,17 +1033,16 @@ ehci_endpoint_reset(struct usb_hcd *hcd, struct usb_host_endpoint *ep)
                usb_settoggle(qh->dev, epnum, is_out, 0);
                if (!list_empty(&qh->qtd_list)) {
                        WARN_ONCE(1, "clear_halt for a busy endpoint\n");
-               } else if (qh->qh_state == QH_STATE_LINKED ||
-                               qh->qh_state == QH_STATE_COMPLETING) {
-
+               } else {
                        /* The toggle value in the QH can't be updated
                         * while the QH is active.  Unlink it now;
                         * re-linking will call qh_refresh().
                         */
+                       qh->exception = 1;
                        if (eptype == USB_ENDPOINT_XFER_BULK)
-                               unlink_async(ehci, qh);
+                               start_unlink_async(ehci, qh);
                        else
-                               intr_deschedule(ehci, qh);
+                               start_unlink_intr(ehci, qh);
                }
        }
        spin_unlock_irqrestore(&ehci->lock, flags);
@@ -1198,40 +1056,181 @@ static int ehci_get_frame (struct usb_hcd *hcd)
 
 /*-------------------------------------------------------------------------*/
 
+#ifdef CONFIG_PM
+
+/* suspend/resume, section 4.3 */
+
+/* These routines handle the generic parts of controller suspend/resume */
+
+int ehci_suspend(struct usb_hcd *hcd, bool do_wakeup)
+{
+       struct ehci_hcd         *ehci = hcd_to_ehci(hcd);
+
+       if (time_before(jiffies, ehci->next_statechange))
+               msleep(10);
+
+       /*
+        * Root hub was already suspended.  Disable IRQ emission and
+        * mark HW unaccessible.  The PM and USB cores make sure that
+        * the root hub is either suspended or stopped.
+        */
+       ehci_prepare_ports_for_controller_suspend(ehci, do_wakeup);
+
+       spin_lock_irq(&ehci->lock);
+       ehci_writel(ehci, 0, &ehci->regs->intr_enable);
+       (void) ehci_readl(ehci, &ehci->regs->intr_enable);
+
+       clear_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags);
+       spin_unlock_irq(&ehci->lock);
+
+       return 0;
+}
+EXPORT_SYMBOL_GPL(ehci_suspend);
+
+/* Returns 0 if power was preserved, 1 if power was lost */
+int ehci_resume(struct usb_hcd *hcd, bool hibernated)
+{
+       struct ehci_hcd         *ehci = hcd_to_ehci(hcd);
+
+       if (time_before(jiffies, ehci->next_statechange))
+               msleep(100);
+
+       /* Mark hardware accessible again as we are back to full power by now */
+       set_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags);
+
+       if (ehci->shutdown)
+               return 0;               /* Controller is dead */
+
+       /*
+        * If CF is still set and we aren't resuming from hibernation
+        * then we maintained suspend power.
+        * Just undo the effect of ehci_suspend().
+        */
+       if (ehci_readl(ehci, &ehci->regs->configured_flag) == FLAG_CF &&
+                       !hibernated) {
+               int     mask = INTR_MASK;
+
+               ehci_prepare_ports_for_controller_resume(ehci);
+
+               spin_lock_irq(&ehci->lock);
+               if (ehci->shutdown)
+                       goto skip;
+
+               if (!hcd->self.root_hub->do_remote_wakeup)
+                       mask &= ~STS_PCD;
+               ehci_writel(ehci, mask, &ehci->regs->intr_enable);
+               ehci_readl(ehci, &ehci->regs->intr_enable);
+ skip:
+               spin_unlock_irq(&ehci->lock);
+               return 0;
+       }
+
+       /*
+        * Else reset, to cope with power loss or resume from hibernation
+        * having let the firmware kick in during reboot.
+        */
+       usb_root_hub_lost_power(hcd->self.root_hub);
+       (void) ehci_halt(ehci);
+       (void) ehci_reset(ehci);
+
+       spin_lock_irq(&ehci->lock);
+       if (ehci->shutdown)
+               goto skip;
+
+       ehci_writel(ehci, ehci->command, &ehci->regs->command);
+       ehci_writel(ehci, FLAG_CF, &ehci->regs->configured_flag);
+       ehci_readl(ehci, &ehci->regs->command); /* unblock posted writes */
+
+       ehci->rh_state = EHCI_RH_SUSPENDED;
+       spin_unlock_irq(&ehci->lock);
+
+       return 1;
+}
+EXPORT_SYMBOL_GPL(ehci_resume);
+
+#endif
+
+/*-------------------------------------------------------------------------*/
+
+/*
+ * Generic structure: This gets copied for platform drivers so that
+ * individual entries can be overridden as needed.
+ */
+
+static const struct hc_driver ehci_hc_driver = {
+       .description =          hcd_name,
+       .product_desc =         "EHCI Host Controller",
+       .hcd_priv_size =        sizeof(struct ehci_hcd),
+
+       /*
+        * generic hardware linkage
+        */
+       .irq =                  ehci_irq,
+       .flags =                HCD_MEMORY | HCD_USB2,
+
+       /*
+        * basic lifecycle operations
+        */
+       .reset =                ehci_setup,
+       .start =                ehci_run,
+       .stop =                 ehci_stop,
+       .shutdown =             ehci_shutdown,
+
+       /*
+        * 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,
+       .clear_tt_buffer_complete =     ehci_clear_tt_buffer_complete,
+
+       /*
+        * 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,
+};
+
+void ehci_init_driver(struct hc_driver *drv,
+               const struct ehci_driver_overrides *over)
+{
+       /* Copy the generic table to drv and then apply the overrides */
+       *drv = ehci_hc_driver;
+
+       if (over) {
+               drv->hcd_priv_size += over->extra_priv_size;
+               if (over->reset)
+                       drv->reset = over->reset;
+       }
+}
+EXPORT_SYMBOL_GPL(ehci_init_driver);
+
+/*-------------------------------------------------------------------------*/
+
 MODULE_DESCRIPTION(DRIVER_DESC);
 MODULE_AUTHOR (DRIVER_AUTHOR);
 MODULE_LICENSE ("GPL");
 
-#ifdef CONFIG_PCI
-#include "ehci-pci.c"
-#define        PCI_DRIVER              ehci_pci_driver
-#endif
-
 #ifdef CONFIG_USB_EHCI_FSL
 #include "ehci-fsl.c"
 #define        PLATFORM_DRIVER         ehci_fsl_driver
 #endif
 
-#ifdef CONFIG_USB_EHCI_MXC
-#include "ehci-mxc.c"
-#define PLATFORM_DRIVER                ehci_mxc_driver
-#endif
-
 #ifdef CONFIG_USB_EHCI_SH
 #include "ehci-sh.c"
 #define PLATFORM_DRIVER                ehci_hcd_sh_driver
 #endif
 
-#ifdef CONFIG_SOC_AU1200
-#include "ehci-au1xxx.c"
-#define        PLATFORM_DRIVER         ehci_hcd_au1xxx_driver
-#endif
-
-#ifdef CONFIG_USB_EHCI_HCD_OMAP
-#include "ehci-omap.c"
-#define        PLATFORM_DRIVER         ehci_hcd_omap_driver
-#endif
-
 #ifdef CONFIG_PPC_PS3
 #include "ehci-ps3.c"
 #define        PS3_SYSTEM_BUS_DRIVER   ps3_ehci_driver
@@ -1247,49 +1246,29 @@ MODULE_LICENSE ("GPL");
 #define XILINX_OF_PLATFORM_DRIVER      ehci_hcd_xilinx_of_driver
 #endif
 
-#ifdef CONFIG_PLAT_ORION
-#include "ehci-orion.c"
-#define        PLATFORM_DRIVER         ehci_orion_driver
-#endif
-
-#ifdef CONFIG_ARCH_IXP4XX
-#include "ehci-ixp4xx.c"
-#define        PLATFORM_DRIVER         ixp4xx_ehci_driver
-#endif
-
 #ifdef CONFIG_USB_W90X900_EHCI
 #include "ehci-w90x900.c"
 #define        PLATFORM_DRIVER         ehci_hcd_w90x900_driver
 #endif
 
-#ifdef CONFIG_ARCH_AT91
-#include "ehci-atmel.c"
-#define        PLATFORM_DRIVER         ehci_atmel_driver
-#endif
-
 #ifdef CONFIG_USB_OCTEON_EHCI
 #include "ehci-octeon.c"
 #define PLATFORM_DRIVER                ehci_octeon_driver
 #endif
 
-#ifdef CONFIG_USB_CNS3XXX_EHCI
-#include "ehci-cns3xxx.c"
-#define PLATFORM_DRIVER                cns3xxx_ehci_driver
+#ifdef CONFIG_TILE_USB
+#include "ehci-tilegx.c"
+#define        PLATFORM_DRIVER         ehci_hcd_tilegx_driver
 #endif
 
-#ifdef CONFIG_ARCH_VT8500
-#include "ehci-vt8500.c"
-#define        PLATFORM_DRIVER         vt8500_ehci_driver
+#ifdef CONFIG_USB_EHCI_RK
+#include "ehci-rk.c"
+#define PLATFORM_DRIVER         ehci_rk_driver
 #endif
 
-#ifdef CONFIG_PLAT_SPEAR
-#include "ehci-spear.c"
-#define PLATFORM_DRIVER                spear_ehci_hcd_driver
-#endif
-
-#ifdef CONFIG_USB_EHCI_MSM
-#include "ehci-msm.c"
-#define PLATFORM_DRIVER                ehci_msm_driver
+#ifdef CONFIG_USB_EHCI_RKHSIC
+#include "ehci-rkhsic.c"
+#define RK_PLATFORM_DRIVER         ehci_rkhsic_driver
 #endif
 
 #ifdef CONFIG_USB_EHCI_HCD_PMC_MSP
@@ -1302,25 +1281,19 @@ MODULE_LICENSE ("GPL");
 #define PLATFORM_DRIVER                tegra_ehci_driver
 #endif
 
-#ifdef CONFIG_USB_EHCI_S5P
-#include "ehci-s5p.c"
-#define PLATFORM_DRIVER                s5p_ehci_driver
-#endif
-
-#ifdef CONFIG_USB_EHCI_ATH79
-#include "ehci-ath79.c"
-#define PLATFORM_DRIVER                ehci_ath79_driver
-#endif
-
 #ifdef CONFIG_SPARC_LEON
 #include "ehci-grlib.c"
 #define PLATFORM_DRIVER                ehci_grlib_driver
 #endif
 
-#if !defined(PCI_DRIVER) && !defined(PLATFORM_DRIVER) && \
-    !defined(PS3_SYSTEM_BUS_DRIVER) && !defined(OF_PLATFORM_DRIVER) && \
-    !defined(XILINX_OF_PLATFORM_DRIVER)
-#error "missing bus glue for ehci-hcd"
+#ifdef CONFIG_USB_EHCI_MV
+#include "ehci-mv.c"
+#define        PLATFORM_DRIVER         ehci_mv_driver
+#endif
+
+#ifdef CONFIG_MIPS_SEAD3
+#include "ehci-sead3.c"
+#define        PLATFORM_DRIVER         ehci_hcd_sead3_driver
 #endif
 
 static int __init ehci_hcd_init(void)
@@ -1356,12 +1329,6 @@ static int __init ehci_hcd_init(void)
                goto clean0;
 #endif
 
-#ifdef PCI_DRIVER
-       retval = pci_register_driver(&PCI_DRIVER);
-       if (retval < 0)
-               goto clean1;
-#endif
-
 #ifdef PS3_SYSTEM_BUS_DRIVER
        retval = ps3_ehci_driver_register(&PS3_SYSTEM_BUS_DRIVER);
        if (retval < 0)
@@ -1379,8 +1346,19 @@ static int __init ehci_hcd_init(void)
        if (retval < 0)
                goto clean4;
 #endif
+
+#ifdef RK_PLATFORM_DRIVER
+       retval = platform_driver_register(&RK_PLATFORM_DRIVER);
+       if (retval < 0)
+               goto clean5;
+#endif
        return retval;
 
+#ifdef RK_PLATFORM_DRIVER
+       platform_driver_unregister(&RK_PLATFORM_DRIVER);
+clean5:
+#endif
+
 #ifdef XILINX_OF_PLATFORM_DRIVER
        /* platform_driver_unregister(&XILINX_OF_PLATFORM_DRIVER); */
 clean4:
@@ -1393,10 +1371,6 @@ clean3:
        ps3_ehci_driver_unregister(&PS3_SYSTEM_BUS_DRIVER);
 clean2:
 #endif
-#ifdef PCI_DRIVER
-       pci_unregister_driver(&PCI_DRIVER);
-clean1:
-#endif
 #ifdef PLATFORM_DRIVER
        platform_driver_unregister(&PLATFORM_DRIVER);
 clean0:
@@ -1413,6 +1387,9 @@ module_init(ehci_hcd_init);
 
 static void __exit ehci_hcd_cleanup(void)
 {
+#ifdef RK_PLATFORM_DRIVER
+       platform_driver_unregister(&RK_PLATFORM_DRIVER);
+#endif
 #ifdef XILINX_OF_PLATFORM_DRIVER
        platform_driver_unregister(&XILINX_OF_PLATFORM_DRIVER);
 #endif
@@ -1422,9 +1399,6 @@ static void __exit ehci_hcd_cleanup(void)
 #ifdef PLATFORM_DRIVER
        platform_driver_unregister(&PLATFORM_DRIVER);
 #endif
-#ifdef PCI_DRIVER
-       pci_unregister_driver(&PCI_DRIVER);
-#endif
 #ifdef PS3_SYSTEM_BUS_DRIVER
        ps3_ehci_driver_unregister(&PS3_SYSTEM_BUS_DRIVER);
 #endif
@@ -1434,4 +1408,3 @@ static void __exit ehci_hcd_cleanup(void)
        clear_bit(USB_EHCI_LOADED, &usb_hcds_loaded);
 }
 module_exit(ehci_hcd_cleanup);
-