summaryrefslogtreecommitdiffstats
path: root/drivers/usb/host/ehci-hcd.c
diff options
context:
space:
mode:
authorAlan Stern <stern@rowland.harvard.edu>2012-10-10 21:07:39 +0200
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2012-10-24 23:45:17 +0200
commitacc08503406f97ce6582c92fd8c8139f1e871a96 (patch)
tree29fff5e0ba8e5bd14c96864ea5475ab6c957c5b4 /drivers/usb/host/ehci-hcd.c
parentUSB: EHCI: move logging macros to ehci.h (diff)
downloadlinux-acc08503406f97ce6582c92fd8c8139f1e871a96.tar.xz
linux-acc08503406f97ce6582c92fd8c8139f1e871a96.zip
USB: EHCI: make ehci_read_frame_index platform independent
In preparation for splitting the ehci-hcd driver into a core library and separate platform-specific driver modules, this patch (as1617) changes the way ehci_read_frame_index() is handled. Since the same core library will have to work with both PCI and non-PCI platforms, the quirk handler routine will be compiled unconditionally. The decision about whether to call it or simply to read the frame index register is made at run time, based on whether the frame_index_bug quirk flag is set. Signed-off-by: Alan Stern <stern@rowland.harvard.edu> Acked-by: Felipe Balbi <balbi@ti.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'drivers/usb/host/ehci-hcd.c')
-rw-r--r--drivers/usb/host/ehci-hcd.c27
1 files changed, 26 insertions, 1 deletions
diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c
index 28fb5ddaf786..9c2afb516fe5 100644
--- a/drivers/usb/host/ehci-hcd.c
+++ b/drivers/usb/host/ehci-hcd.c
@@ -118,9 +118,34 @@ MODULE_PARM_DESC(hird, "host initiated resume duration, +1 for each 75us");
/*-------------------------------------------------------------------------*/
#include "ehci.h"
-#include "ehci-dbg.c"
#include "pci-quirks.h"
+/*
+ * 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)
+{
+ unsigned uf;
+
+ uf = ehci_readl(ehci, &ehci->regs->frame_index);
+ if (unlikely((uf & 7) == 0))
+ uf = ehci_readl(ehci, &ehci->regs->frame_index);
+ return uf;
+}
+
+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"
+
/*-------------------------------------------------------------------------*/
/*