aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPeter Chen <peter.chen@freescale.com>2014-01-10 00:51:26 -0500
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2014-01-13 18:54:03 -0500
commitfeffe09f510c475df082546815f9e4a573f6a233 (patch)
tree7400f447302b69558d4677b758c090844b042b17
parent1b9fb31f7db7882d475bdc8b335403e8eaabf1ef (diff)
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>
-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 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 */
225 unsigned has_synopsys_hc_bug:1; /* Synopsys HC */ 225 unsigned has_synopsys_hc_bug:1; /* Synopsys HC */
226 unsigned frame_index_bug:1; /* MosChip (AKA NetMos) */ 226 unsigned frame_index_bug:1; /* MosChip (AKA NetMos) */
227 unsigned need_oc_pp_cycle:1; /* MPC834X port power */ 227 unsigned need_oc_pp_cycle:1; /* MPC834X port power */
228 unsigned imx28_write_fix:1; /* For Freescale i.MX28 */
228 229
229 /* required for usb32 quirk */ 230 /* required for usb32 quirk */
230 #define OHCI_CTRL_HCFS (3 << 6) 231 #define OHCI_CTRL_HCFS (3 << 6)
@@ -728,6 +729,18 @@ static inline unsigned int ehci_readl(const struct ehci_hcd *ehci,
728#endif 729#endif
729} 730}
730 731
732#ifdef CONFIG_SOC_IMX28
733static inline void imx28_ehci_writel(const unsigned int val,
734 volatile __u32 __iomem *addr)
735{
736 __asm__ ("swp %0, %0, [%1]" : : "r"(val), "r"(addr));
737}
738#else
739static inline void imx28_ehci_writel(const unsigned int val,
740 volatile __u32 __iomem *addr)
741{
742}
743#endif
731static inline void ehci_writel(const struct ehci_hcd *ehci, 744static inline void ehci_writel(const struct ehci_hcd *ehci,
732 const unsigned int val, __u32 __iomem *regs) 745 const unsigned int val, __u32 __iomem *regs)
733{ 746{
@@ -736,7 +749,10 @@ static inline void ehci_writel(const struct ehci_hcd *ehci,
736 writel_be(val, regs) : 749 writel_be(val, regs) :
737 writel(val, regs); 750 writel(val, regs);
738#else 751#else
739 writel(val, regs); 752 if (ehci->imx28_write_fix)
753 imx28_ehci_writel(val, regs);
754 else
755 writel(val, regs);
740#endif 756#endif
741} 757}
742 758