summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--arch/powerpc/include/asm/mpc85xx.h13
-rw-r--r--drivers/usb/host/ehci-fsl.c4
-rw-r--r--drivers/usb/host/ehci-hub.c7
-rw-r--r--drivers/usb/host/ehci-q.c6
-rw-r--r--drivers/usb/host/ehci.h12
-rw-r--r--drivers/usb/host/fsl-mph-dr-of.c35
-rw-r--r--include/linux/fsl_devices.h1
7 files changed, 75 insertions, 3 deletions
diff --git a/arch/powerpc/include/asm/mpc85xx.h b/arch/powerpc/include/asm/mpc85xx.h
index 65e4b66..a49fead 100644
--- a/arch/powerpc/include/asm/mpc85xx.h
+++ b/arch/powerpc/include/asm/mpc85xx.h
@@ -53,8 +53,17 @@
#define SVR_8572 0x80E000
#define SVR_8572_E 0x80E800
#define SVR_P1010 0x80f900
-#define SVR_P2041 0x821801
-#define SVR_P3041 0x821903
+#define SVR_P1010_E 0x80F100
+#define SVR_P2041 0x821001
+#define SVR_P2041_E 0x821801
+#define SVR_P3041 0x821103
+#define SVR_P3041_E 0x821903
+#define SVR_P5010 0x822100
+#define SVR_P5010_E 0x822900
+#define SVR_P5020 0x822000
+#define SVR_P5020_E 0x822800
+#define SVR_P5040 0x820400
+#define SVR_P5040_E 0x820B00
#define SVR_T4240 0x824800
#define SVR_B4860 0x868800
diff --git a/drivers/usb/host/ehci-fsl.c b/drivers/usb/host/ehci-fsl.c
index 50167c3..732bc43 100644
--- a/drivers/usb/host/ehci-fsl.c
+++ b/drivers/usb/host/ehci-fsl.c
@@ -365,6 +365,10 @@ static int ehci_fsl_usb_setup(struct ehci_hcd *ehci)
out_be32(non_ehci + FSL_SOC_USB_SNOOP2, 0x80000000 | SNOOP_SIZE_2GB);
}
+ /* Deal with USB erratum A-005275 */
+ if (pdata->has_fsl_erratum_a005275 == 1)
+ ehci->has_fsl_hs_errata = 1;
+
if ((pdata->operating_mode == FSL_USB2_DR_HOST) ||
(pdata->operating_mode == FSL_USB2_DR_OTG))
if (ehci_fsl_setup_phy(hcd, pdata->phy_mode, 0))
diff --git a/drivers/usb/host/ehci-hub.c b/drivers/usb/host/ehci-hub.c
index 7d06e77..586b2d4 100644
--- a/drivers/usb/host/ehci-hub.c
+++ b/drivers/usb/host/ehci-hub.c
@@ -1064,6 +1064,13 @@ static int ehci_hub_control (
ehci->reset_done [wIndex] = jiffies
+ msecs_to_jiffies (50);
}
+
+ /* Force full-speed connect for FSL high-speed erratum;
+ * disable HS Chirp by setting PFSC bit
+ */
+ if (ehci_has_fsl_hs_errata(ehci))
+ temp |= (1 << PORTSC_FSL_PFSC);
+
ehci_writel(ehci, temp, status_reg);
break;
diff --git a/drivers/usb/host/ehci-q.c b/drivers/usb/host/ehci-q.c
index 23d1369..8cc03ee 100644
--- a/drivers/usb/host/ehci-q.c
+++ b/drivers/usb/host/ehci-q.c
@@ -926,7 +926,11 @@ qh_make (
break;
case USB_SPEED_HIGH: /* no TT involved */
- info1 |= QH_HIGH_SPEED;
+ if (!ehci_has_fsl_hs_errata(ehci))
+ info1 |= QH_HIGH_SPEED;
+ else
+ info1 |= QH_FULL_SPEED;
+
if (type == PIPE_CONTROL) {
info1 |= (EHCI_TUNE_RL_HS << 28);
info1 |= 64 << 16; /* usb2 fixed maxpacket */
diff --git a/drivers/usb/host/ehci.h b/drivers/usb/host/ehci.h
index c204b81..8703484 100644
--- a/drivers/usb/host/ehci.h
+++ b/drivers/usb/host/ehci.h
@@ -194,6 +194,7 @@ struct ehci_hcd { /* one per controller */
/* SILICON QUIRKS */
unsigned no_selective_suspend:1;
unsigned has_fsl_port_bug:1; /* FreeScale */
+ unsigned has_fsl_hs_errata:1; /* Freescale HS quirk */
unsigned big_endian_mmio:1;
unsigned big_endian_desc:1;
unsigned big_endian_capbase:1;
@@ -622,6 +623,17 @@ ehci_port_speed(struct ehci_hcd *ehci, unsigned int portsc)
#define ehci_port_speed(ehci, portsc) USB_PORT_STAT_HIGH_SPEED
#endif
+#define PORTSC_FSL_PFSC 24 /* Port Force Full-Speed Connect */
+
+#if defined(CONFIG_PPC_85xx)
+/* Some Freescale processors have an erratum (USB A-005275) in which
+ * incoming packets get corrupted in HS mode
+ */
+#define ehci_has_fsl_hs_errata(e) ((e)->has_fsl_hs_errata)
+#else
+#define ehci_has_fsl_hs_errata(e) (0)
+#endif
+
/*-------------------------------------------------------------------------*/
#ifdef CONFIG_PPC_83xx
diff --git a/drivers/usb/host/fsl-mph-dr-of.c b/drivers/usb/host/fsl-mph-dr-of.c
index 11e0b79..20e89ca 100644
--- a/drivers/usb/host/fsl-mph-dr-of.c
+++ b/drivers/usb/host/fsl-mph-dr-of.c
@@ -17,6 +17,7 @@
#include <linux/of_platform.h>
#include <linux/clk.h>
#include <linux/module.h>
+#include <asm/mpc85xx.h>
struct fsl_usb2_dev_data {
char *dr_mode; /* controller mode */
@@ -119,6 +120,30 @@ error:
static const struct of_device_id fsl_usb2_mph_dr_of_match[];
+static bool has_erratum_a005275(struct device_node *node)
+{
+ unsigned int svr = mfspr(SPRN_SVR);
+ bool flag = false;
+ /* Deal with USB Erratum USB A-005275
+ * Packet corruption in HS mode, default to
+ * FS mode for the following
+ * P3041 and P2041 rev 1.0 and 1.1
+ * P5020 and P5010 rev 1.0 and 2.0
+ * P5040 and P1010 rev 1.0
+ */
+ if ((fsl_svr_is(SVR_P3041)) || (fsl_svr_is(SVR_P3041_E)) ||
+ (fsl_svr_is(SVR_P2041)) || (fsl_svr_is(SVR_P2041_E)))
+ flag = (IS_SVR_REV(svr, 1, 0)) || (IS_SVR_REV(svr, 1, 1));
+ else if ((fsl_svr_is(SVR_P5020)) || (fsl_svr_is(SVR_P5020_E)) ||
+ (fsl_svr_is(SVR_P5010)) || (fsl_svr_is(SVR_P5010_E)))
+ flag = (IS_SVR_REV(svr, 1, 0)) || (IS_SVR_REV(svr, 2, 0));
+ else if ((fsl_svr_is(SVR_P5040)) || (fsl_svr_is(SVR_P5040_E)) ||
+ (fsl_svr_is(SVR_P1010)) || (fsl_svr_is(SVR_P1010_E)))
+ flag = IS_SVR_REV(svr, 1, 0);
+
+ return flag;
+}
+
static int usb_get_ver_info(struct device_node *np)
{
int ver = -1;
@@ -206,6 +231,16 @@ static int fsl_usb2_mph_dr_of_probe(struct platform_device *ofdev)
pdata->phy_mode = determine_usb_phy(prop);
pdata->controller_ver = usb_get_ver_info(np);
+ /* Activate workaround for USB erratum-A005275 if
+ * fsl,no-erratum-a005275 property not defined for
+ * affected socs
+ */
+ if (!of_get_property(np, "fsl,no-erratum-a005275", NULL) &&
+ has_erratum_a005275(np))
+ pdata->has_fsl_erratum_a005275 = 1;
+ else
+ pdata->has_fsl_erratum_a005275 = 0;
+
if (pdata->have_sysif_regs) {
if (pdata->controller_ver < 0) {
dev_warn(&ofdev->dev, "Could not get controller version\n");
diff --git a/include/linux/fsl_devices.h b/include/linux/fsl_devices.h
index a82296a..af5c229 100644
--- a/include/linux/fsl_devices.h
+++ b/include/linux/fsl_devices.h
@@ -92,6 +92,7 @@ struct fsl_usb2_platform_data {
unsigned suspended:1;
unsigned already_suspended:1;
+ unsigned has_fsl_erratum_a005275:1;
/* register save area for suspend/resume */
u32 pm_command;