aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb/host
diff options
context:
space:
mode:
authorPeter Chen <peter.chen@freescale.com>2014-01-10 13:51:26 +0800
committerBen Hutchings <ben@decadent.org.uk>2014-04-02 00:58:43 +0100
commitb7785833fe6d2c3027d3e385d72bd31775031d2b (patch)
treedb8f758528d832e24203f6f1f7f898bb30d8f22c /drivers/usb/host
parentb2cf3f5e629ff7424e683197e849f598be53a11c (diff)
downloadkernel_samsung_smdk4412-b7785833fe6d2c3027d3e385d72bd31775031d2b.zip
kernel_samsung_smdk4412-b7785833fe6d2c3027d3e385d72bd31775031d2b.tar.gz
kernel_samsung_smdk4412-b7785833fe6d2c3027d3e385d72bd31775031d2b.tar.bz2
usb: ehci: add freescale imx28 special write register method
commit feffe09f510c475df082546815f9e4a573f6a233 upstream. According to Freescale imx28 Errata, "ENGR119653 USB: ARM to USB register error issue", All USB register write operations must use the ARM SWP instruction. So, we implement a special ehci_write for imx28. Discussion for it at below: http://marc.info/?l=linux-usb&m=137996395529294&w=2 Without this patcheset, imx28 works unstable at high AHB bus loading. If the bus loading is not high, the imx28 usb can work well at the most of time. There is a IC errata for this problem, usually, we consider IC errata is a problem not a new feature, and this workaround is needed for that, so we need to add them to stable tree 3.11+. Cc: robert.hodaszi@digi.com Signed-off-by: Peter Chen <peter.chen@freescale.com> Acked-by: Alan Stern <stern@rowland.harvard.edu> Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de> Tested-by: Marc Kleine-Budde <mkl@pengutronix.de> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> [bwh: Backported to 3.2:adjust context] Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
Diffstat (limited to 'drivers/usb/host')
-rw-r--r--drivers/usb/host/ehci.h18
1 files changed, 17 insertions, 1 deletions
diff --git a/drivers/usb/host/ehci.h b/drivers/usb/host/ehci.h
index 0a5fda7..b65912d 100644
--- a/drivers/usb/host/ehci.h
+++ b/drivers/usb/host/ehci.h
@@ -147,6 +147,7 @@ struct ehci_hcd { /* one per controller */
unsigned use_dummy_qh:1; /* AMD Frame List table quirk*/
unsigned has_synopsys_hc_bug:1; /* Synopsys HC */
unsigned frame_index_bug:1; /* MosChip (AKA NetMos) */
+ unsigned imx28_write_fix:1; /* For Freescale i.MX28 */
/* required for usb32 quirk */
#define OHCI_CTRL_HCFS (3 << 6)
@@ -654,6 +655,18 @@ static inline unsigned int ehci_readl(const struct ehci_hcd *ehci,
#endif
}
+#ifdef CONFIG_SOC_IMX28
+static inline void imx28_ehci_writel(const unsigned int val,
+ volatile __u32 __iomem *addr)
+{
+ __asm__ ("swp %0, %0, [%1]" : : "r"(val), "r"(addr));
+}
+#else
+static inline void imx28_ehci_writel(const unsigned int val,
+ volatile __u32 __iomem *addr)
+{
+}
+#endif
static inline void ehci_writel(const struct ehci_hcd *ehci,
const unsigned int val, __u32 __iomem *regs)
{
@@ -662,7 +675,10 @@ static inline void ehci_writel(const struct ehci_hcd *ehci,
writel_be(val, regs) :
writel(val, regs);
#else
- writel(val, regs);
+ if (ehci->imx28_write_fix)
+ imx28_ehci_writel(val, regs);
+ else
+ writel(val, regs);
#endif
}