diff options
author | Chris Packham | 2018-10-04 02:03:53 -0500 |
---|---|---|
committer | York Sun | 2018-10-29 15:13:05 -0500 |
commit | 4eaf7f525a0874a1eff0f5666004896cc5c89fa3 (patch) | |
tree | 551c1b5d786f0f8fc0182361ad98f591c6a71481 /drivers | |
parent | 454cf76184c65426b68033a23da086e73663f2fc (diff) | |
download | u-boot-4eaf7f525a0874a1eff0f5666004896cc5c89fa3.tar.gz u-boot-4eaf7f525a0874a1eff0f5666004896cc5c89fa3.tar.xz u-boot-4eaf7f525a0874a1eff0f5666004896cc5c89fa3.zip |
fsl/usb: Workaround for USB erratum-A005275
Workaround makes FS as default mode on all affected socs.
Add support to check erratum-A005275 validity for an soc. This info is
required to determine whether a given soc is affected by this erratum.
Add quirk for this erratum "has_fsl_erratum_a005275" . This quirk is used
to enable workaround for the errata
Force FS mode as default by:
- making EPS as FS
- setting PFSC bit to disable HS chirping
This workaround can be disabled by mentioning "no_erratum_a005275" in
hwconfig string
Signed-off-by: Chris Packham <judge.packham@gmail.com>
Reviewed-by: York Sun <york.sun@nxp.com>
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/usb/common/fsl-errata.c | 28 | ||||
-rw-r--r-- | drivers/usb/host/ehci-fsl.c | 7 | ||||
-rw-r--r-- | drivers/usb/host/ehci-hcd.c | 12 | ||||
-rw-r--r-- | drivers/usb/host/ehci.h | 4 |
4 files changed, 50 insertions, 1 deletions
diff --git a/drivers/usb/common/fsl-errata.c b/drivers/usb/common/fsl-errata.c index 386130d7a1..9eb1d23067 100644 --- a/drivers/usb/common/fsl-errata.c +++ b/drivers/usb/common/fsl-errata.c | |||
@@ -6,6 +6,7 @@ | |||
6 | */ | 6 | */ |
7 | 7 | ||
8 | #include <common.h> | 8 | #include <common.h> |
9 | #include <hwconfig.h> | ||
9 | #include <fsl_errata.h> | 10 | #include <fsl_errata.h> |
10 | #include<fsl_usb.h> | 11 | #include<fsl_usb.h> |
11 | #if defined(CONFIG_FSL_LSCH2) || defined(CONFIG_FSL_LSCH3) || \ | 12 | #if defined(CONFIG_FSL_LSCH2) || defined(CONFIG_FSL_LSCH3) || \ |
@@ -44,6 +45,33 @@ bool has_dual_phy(void) | |||
44 | return false; | 45 | return false; |
45 | } | 46 | } |
46 | 47 | ||
48 | bool has_erratum_a005275(void) | ||
49 | { | ||
50 | u32 svr = get_svr(); | ||
51 | u32 soc = SVR_SOC_VER(svr); | ||
52 | |||
53 | if (hwconfig("no_erratum_a005275")) | ||
54 | return false; | ||
55 | |||
56 | switch (soc) { | ||
57 | #ifdef CONFIG_PPC | ||
58 | case SVR_P3041: | ||
59 | case SVR_P2041: | ||
60 | case SVR_P2040: | ||
61 | return IS_SVR_REV(svr, 1, 0) || IS_SVR_REV(svr, 1, 1); | ||
62 | case SVR_P5010: | ||
63 | case SVR_P5020: | ||
64 | case SVR_P5021: | ||
65 | return IS_SVR_REV(svr, 1, 0) || IS_SVR_REV(svr, 2, 0); | ||
66 | case SVR_P5040: | ||
67 | case SVR_P1010: | ||
68 | return IS_SVR_REV(svr, 1, 0); | ||
69 | #endif | ||
70 | } | ||
71 | |||
72 | return false; | ||
73 | } | ||
74 | |||
47 | bool has_erratum_a006261(void) | 75 | bool has_erratum_a006261(void) |
48 | { | 76 | { |
49 | u32 svr = get_svr(); | 77 | u32 svr = get_svr(); |
diff --git a/drivers/usb/host/ehci-fsl.c b/drivers/usb/host/ehci-fsl.c index a04f6a31c8..a8fb2b8ac3 100644 --- a/drivers/usb/host/ehci-fsl.c +++ b/drivers/usb/host/ehci-fsl.c | |||
@@ -93,6 +93,7 @@ static int ehci_fsl_probe(struct udevice *dev) | |||
93 | struct usb_ehci *ehci = NULL; | 93 | struct usb_ehci *ehci = NULL; |
94 | struct ehci_hccr *hccr; | 94 | struct ehci_hccr *hccr; |
95 | struct ehci_hcor *hcor; | 95 | struct ehci_hcor *hcor; |
96 | struct ehci_ctrl *ehci_ctrl = &priv->ehci; | ||
96 | 97 | ||
97 | /* | 98 | /* |
98 | * Get the base address for EHCI controller from the device node | 99 | * Get the base address for EHCI controller from the device node |
@@ -107,6 +108,8 @@ static int ehci_fsl_probe(struct udevice *dev) | |||
107 | hcor = (struct ehci_hcor *) | 108 | hcor = (struct ehci_hcor *) |
108 | ((void *)hccr + HC_LENGTH(ehci_readl(&hccr->cr_capbase))); | 109 | ((void *)hccr + HC_LENGTH(ehci_readl(&hccr->cr_capbase))); |
109 | 110 | ||
111 | ehci_ctrl->has_fsl_erratum_a005275 = has_erratum_a005275(); | ||
112 | |||
110 | if (ehci_fsl_init(priv, ehci, hccr, hcor) < 0) | 113 | if (ehci_fsl_init(priv, ehci, hccr, hcor) < 0) |
111 | return -ENXIO; | 114 | return -ENXIO; |
112 | 115 | ||
@@ -145,6 +148,8 @@ U_BOOT_DRIVER(ehci_fsl) = { | |||
145 | int ehci_hcd_init(int index, enum usb_init_type init, | 148 | int ehci_hcd_init(int index, enum usb_init_type init, |
146 | struct ehci_hccr **hccr, struct ehci_hcor **hcor) | 149 | struct ehci_hccr **hccr, struct ehci_hcor **hcor) |
147 | { | 150 | { |
151 | struct ehci_ctrl *ehci_ctrl = container_of(hccr, | ||
152 | struct ehci_ctrl, hccr); | ||
148 | struct usb_ehci *ehci = NULL; | 153 | struct usb_ehci *ehci = NULL; |
149 | 154 | ||
150 | switch (index) { | 155 | switch (index) { |
@@ -163,6 +168,8 @@ int ehci_hcd_init(int index, enum usb_init_type init, | |||
163 | *hcor = (struct ehci_hcor *)((uint32_t) *hccr + | 168 | *hcor = (struct ehci_hcor *)((uint32_t) *hccr + |
164 | HC_LENGTH(ehci_readl(&(*hccr)->cr_capbase))); | 169 | HC_LENGTH(ehci_readl(&(*hccr)->cr_capbase))); |
165 | 170 | ||
171 | ehci_ctrl->has_fsl_erratum_a005275 = has_erratum_a005275(); | ||
172 | |||
166 | return ehci_fsl_init(index, ehci, *hccr, *hcor); | 173 | return ehci_fsl_init(index, ehci, *hccr, *hcor); |
167 | } | 174 | } |
168 | 175 | ||
diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c index 199b3a8b26..d1d8f08d98 100644 --- a/drivers/usb/host/ehci-hcd.c +++ b/drivers/usb/host/ehci-hcd.c | |||
@@ -409,9 +409,15 @@ ehci_submit_async(struct usb_device *dev, unsigned long pipe, void *buffer, | |||
409 | endpt = QH_ENDPT1_RL(8) | QH_ENDPT1_C(c) | | 409 | endpt = QH_ENDPT1_RL(8) | QH_ENDPT1_C(c) | |
410 | QH_ENDPT1_MAXPKTLEN(maxpacket) | QH_ENDPT1_H(0) | | 410 | QH_ENDPT1_MAXPKTLEN(maxpacket) | QH_ENDPT1_H(0) | |
411 | QH_ENDPT1_DTC(QH_ENDPT1_DTC_DT_FROM_QTD) | | 411 | QH_ENDPT1_DTC(QH_ENDPT1_DTC_DT_FROM_QTD) | |
412 | QH_ENDPT1_EPS(ehci_encode_speed(dev->speed)) | | ||
413 | QH_ENDPT1_ENDPT(usb_pipeendpoint(pipe)) | QH_ENDPT1_I(0) | | 412 | QH_ENDPT1_ENDPT(usb_pipeendpoint(pipe)) | QH_ENDPT1_I(0) | |
414 | QH_ENDPT1_DEVADDR(usb_pipedevice(pipe)); | 413 | QH_ENDPT1_DEVADDR(usb_pipedevice(pipe)); |
414 | |||
415 | /* Force FS for fsl HS quirk */ | ||
416 | if (!ctrl->has_fsl_erratum_a005275) | ||
417 | endpt |= QH_ENDPT1_EPS(ehci_encode_speed(dev->speed)); | ||
418 | else | ||
419 | endpt |= QH_ENDPT1_EPS(ehci_encode_speed(QH_FULL_SPEED)); | ||
420 | |||
415 | qh->qh_endpt1 = cpu_to_hc32(endpt); | 421 | qh->qh_endpt1 = cpu_to_hc32(endpt); |
416 | endpt = QH_ENDPT2_MULT(1) | QH_ENDPT2_UFCMASK(0) | QH_ENDPT2_UFSMASK(0); | 422 | endpt = QH_ENDPT2_MULT(1) | QH_ENDPT2_UFCMASK(0) | QH_ENDPT2_UFSMASK(0); |
417 | qh->qh_endpt2 = cpu_to_hc32(endpt); | 423 | qh->qh_endpt2 = cpu_to_hc32(endpt); |
@@ -832,6 +838,10 @@ static int ehci_submit_root(struct usb_device *dev, unsigned long pipe, | |||
832 | } else { | 838 | } else { |
833 | int ret; | 839 | int ret; |
834 | 840 | ||
841 | /* Disable chirp for HS erratum */ | ||
842 | if (ctrl->has_fsl_erratum_a005275) | ||
843 | reg |= PORTSC_FSL_PFSC; | ||
844 | |||
835 | reg |= EHCI_PS_PR; | 845 | reg |= EHCI_PS_PR; |
836 | reg &= ~EHCI_PS_PE; | 846 | reg &= ~EHCI_PS_PE; |
837 | ehci_writel(status_reg, reg); | 847 | ehci_writel(status_reg, reg); |
diff --git a/drivers/usb/host/ehci.h b/drivers/usb/host/ehci.h index 7945016624..6c359af90c 100644 --- a/drivers/usb/host/ehci.h +++ b/drivers/usb/host/ehci.h | |||
@@ -8,6 +8,7 @@ | |||
8 | #ifndef USB_EHCI_H | 8 | #ifndef USB_EHCI_H |
9 | #define USB_EHCI_H | 9 | #define USB_EHCI_H |
10 | 10 | ||
11 | #include <stdbool.h> | ||
11 | #include <usb.h> | 12 | #include <usb.h> |
12 | #include <generic-phy.h> | 13 | #include <generic-phy.h> |
13 | 14 | ||
@@ -66,6 +67,8 @@ struct ehci_hcor { | |||
66 | #define PORTSC_PSPD_FS 0x0 | 67 | #define PORTSC_PSPD_FS 0x0 |
67 | #define PORTSC_PSPD_LS 0x1 | 68 | #define PORTSC_PSPD_LS 0x1 |
68 | #define PORTSC_PSPD_HS 0x2 | 69 | #define PORTSC_PSPD_HS 0x2 |
70 | #define PORTSC_FSL_PFSC BIT(24) /* PFSC bit to disable HS chirping */ | ||
71 | |||
69 | uint32_t or_systune; | 72 | uint32_t or_systune; |
70 | } __attribute__ ((packed, aligned(4))); | 73 | } __attribute__ ((packed, aligned(4))); |
71 | 74 | ||
@@ -251,6 +254,7 @@ struct ehci_ctrl { | |||
251 | uint32_t *periodic_list; | 254 | uint32_t *periodic_list; |
252 | int periodic_schedules; | 255 | int periodic_schedules; |
253 | int ntds; | 256 | int ntds; |
257 | bool has_fsl_erratum_a005275; /* Freescale HS silicon quirk */ | ||
254 | struct ehci_ops ops; | 258 | struct ehci_ops ops; |
255 | void *priv; /* client's private data */ | 259 | void *priv; /* client's private data */ |
256 | }; | 260 | }; |