diff options
-rw-r--r-- | arch/powerpc/include/asm/mpc85xx.h | 13 | ||||
-rw-r--r-- | drivers/usb/host/ehci-fsl.c | 4 | ||||
-rw-r--r-- | drivers/usb/host/ehci-hub.c | 7 | ||||
-rw-r--r-- | drivers/usb/host/ehci-q.c | 6 | ||||
-rw-r--r-- | drivers/usb/host/ehci.h | 12 | ||||
-rw-r--r-- | drivers/usb/host/fsl-mph-dr-of.c | 35 | ||||
-rw-r--r-- | include/linux/fsl_devices.h | 1 |
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; |