diff options
author | Peter Chen <peter.chen@freescale.com> | 2014-01-10 09:51:26 +0400 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2014-01-14 03:54:03 +0400 |
commit | feffe09f510c475df082546815f9e4a573f6a233 (patch) | |
tree | 7400f447302b69558d4677b758c090844b042b17 /drivers | |
parent | 1b9fb31f7db7882d475bdc8b335403e8eaabf1ef (diff) | |
download | linux-feffe09f510c475df082546815f9e4a573f6a233.tar.xz |
usb: ehci: add freescale imx28 special write register method
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: stable@vger.kernel.org
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>
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/usb/host/ehci.h | 18 |
1 files changed, 17 insertions, 1 deletions
diff --git a/drivers/usb/host/ehci.h b/drivers/usb/host/ehci.h index c35a6e2b94e5..9dfc6c1394d6 100644 --- a/drivers/usb/host/ehci.h +++ b/drivers/usb/host/ehci.h @@ -225,6 +225,7 @@ struct ehci_hcd { /* one per controller */ unsigned has_synopsys_hc_bug:1; /* Synopsys HC */ unsigned frame_index_bug:1; /* MosChip (AKA NetMos) */ unsigned need_oc_pp_cycle:1; /* MPC834X port power */ + unsigned imx28_write_fix:1; /* For Freescale i.MX28 */ /* required for usb32 quirk */ #define OHCI_CTRL_HCFS (3 << 6) @@ -728,6 +729,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) { @@ -736,7 +749,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 } |