Hi,
I had a lot of USB errors on i.mx28. I could reproduce it most easily
with USB-serial adapters, and USB modems (CDC and WWAN drivers). If I
sent some data to the TTY port with the echo command in a loop (so
basically open the port, send data, and close the port), all of the
devices were dropped down from the root hub. (Later I found, it is
enough to just periodically open and close the TTY port.)
The reason was an mx28 errata: "ENGR119653 USB: ARM to USB register
error issue"
Freescale issued a patch for 2.6.35 to workaround this problem last
year. I ported this patch. However, it is not totally "device tree
compatible". I mean, this patch is only needed for mx28, not for the
other SOCs using chipidea, and I used ifdefs. So you can't compile a
kernel both for mx28 and e.g. for mx23. If you check the patch, you see,
that it is modifying the lowest layer, the writel() function; it is
changing it to an SWP instruction. According the errata, I need to use
SWP instructions to write USB registers.
So I'm curious, what other possibilities do I have to make this patch
device tree compatible? I mean, I can't check the machine's type on each
USB register writing. Then I could use function pointers for register
writing function, or weak aliases somehow. But that would causes an
overhead because of the additional function calling, instead of simple
inline assembly codes.
What's the standard way in this case? Or should I just leave the patch
as it is?
--------
Robert Hodaszi
From de71990cd37a973a598ba8924d415696ea5dabdf Mon Sep 17 00:00:00 2001
From: Robert Hodaszi <robert.hodaszi@xxxxxxxx>
Date: Mon, 23 Sep 2013 18:07:18 +0200
Subject: [PATCH] usb: chipidea: implement workaround for i.mx28 errata
ENGR119653: USB: ARM to USB register error issue
From the i.mx28 Errata:
ENGR119653 USB: ARM to USB register error issue
Description:
The ARM writes a data error to the USB core register unless SRM SWP
instruction is used.
The issue occurs when all of the following conditions are met:
1. Last AHB access is to the non-USB AHB slave
2. Current AHB access is to the USB
3. These two accesses are back-to-back
4. The last data phase of the last AHB access has a wait state
5. Only happens when D-cache is enabled
Projected Impact:
The USB register does not get correct data when writing to the USB slave
through the AHB bus
when D-cache is enabled.
Workaround:
All USB register write operations must use the ARM SWP instruction.
Projected Solution:
No fix scheduled.
Signed-off-by: Robert Hodaszi <robert.hodaszi@xxxxxxxx>
---
drivers/usb/chipidea/ci.h | 13 +++++++++++++
drivers/usb/host/ehci.h | 9 +++++++++
2 files changed, 22 insertions(+)
diff --git a/drivers/usb/chipidea/ci.h b/drivers/usb/chipidea/ci.h
index 1c94fc5..1ba7428 100644
--- a/drivers/usb/chipidea/ci.h
+++ b/drivers/usb/chipidea/ci.h
@@ -25,6 +25,19 @@
#define CI_HDRC_PAGE_SIZE 4096ul /* page size for TD's */
#define ENDPT_MAX 32
+#ifdef CONFIG_SOC_IMX28
+/* Fix errata ENGR119653 for i.mx28 */
+static inline void safe_writel(u32 val32, volatile u32 *addr)
+{
+ __asm__ ("swp %0, %0, [%1]" : : "r"(val32), "r"(addr));
+}
+
+#undef iowrite32
+#undef writel
+#define iowrite32(v, addr) safe_writel(v, addr)
+#define writel(v, addr) safe_writel(v, addr)
+#endif
+
/******************************************************************************
* STRUCTURES
*****************************************************************************/
diff --git a/drivers/usb/host/ehci.h b/drivers/usb/host/ehci.h
index 7c978b2..34dbec0 100644
--- a/drivers/usb/host/ehci.h
+++ b/drivers/usb/host/ehci.h
@@ -675,6 +675,13 @@ static inline unsigned int ehci_readl(const struct
ehci_hcd *ehci,
#endif
}
+#ifdef CONFIG_SOC_IMX28
+static inline void fsl_safe_writel(u32 val32, volatile u32 *addr)
+{
+ __asm__ ("swp %0, %0, [%1]" : : "r"(val32), "r"(addr));
+}
+#endif
+
static inline void ehci_writel(const struct ehci_hcd *ehci,
const unsigned int val, __u32 __iomem *regs)
{
@@ -682,6 +689,8 @@ static inline void ehci_writel(const struct ehci_hcd
*ehci,
ehci_big_endian_mmio(ehci) ?
writel_be(val, regs) :
writel(val, regs);
+#elif defined(CONFIG_SOC_IMX28)
+ fsl_safe_writel(val, regs);
#else
writel(val, regs);
#endif
--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html