Commit e00fcce4d91d809dca4d8413a24da16e02490e9d
1 parent
d857a7b9af
Exists in
smarc_8mq-imx_v2020.04_5.4.24_2.1.0
and in
3 other branches
MLK-23110-1 usb: Decouple the CI_UDC DM gadget driver with EHCI MX6 driver
On 2019.04 SPL, we enabled DM gadget driver for QM/QXP to support dual USB ports. The CI_UDC DM gadget driver will call init function inside EHCI mx6 driver, so when building SPL on iMX8QM/QXP with CI UDC enabled, we have to enable usb host driver as well, and this introduces about more than 40KB size to SPL. Move the common codes to a independent file, so that both host driver and gadget driver can call it, then decouple the host and gadget driver. Note: the patch only applies to ci_udc gadget DM driver. For non-DM gadget driver, it still depends ehci host interfaces. Signed-off-by: Ye Li <ye.li@nxp.com> Acked-by: Peng Fan <peng.fan@nxp.com> (cherry picked from commit 1afed171a77b4c95cd4ea76f29d5a0a6bb199820)
Showing 8 changed files with 418 additions and 371 deletions Side-by-side Diff
Makefile
... | ... | @@ -748,6 +748,7 @@ |
748 | 748 | libs-$(CONFIG_$(SPL_)ALTERA_SDRAM) += drivers/ddr/altera/ |
749 | 749 | libs-y += drivers/serial/ |
750 | 750 | libs-y += drivers/usb/cdns3/ |
751 | +libs-y += drivers/usb/imx/ | |
751 | 752 | libs-y += drivers/usb/dwc3/ |
752 | 753 | libs-y += drivers/usb/common/ |
753 | 754 | libs-y += drivers/usb/emul/ |
drivers/usb/gadget/ci_udc.c
drivers/usb/host/ehci-mx6.c
... | ... | @@ -2,7 +2,7 @@ |
2 | 2 | /* |
3 | 3 | * Copyright (c) 2009 Daniel Mack <daniel@caiaq.de> |
4 | 4 | * Copyright (C) 2010 Freescale Semiconductor, Inc. |
5 | - * Copyright 2017 NXP | |
5 | + * Copyright 2017-2019 NXP | |
6 | 6 | * |
7 | 7 | */ |
8 | 8 | |
... | ... | @@ -12,6 +12,7 @@ |
12 | 12 | #include <wait_bit.h> |
13 | 13 | #include <linux/compiler.h> |
14 | 14 | #include <usb/ehci-ci.h> |
15 | +#include <usb/usb_mx6_common.h> | |
15 | 16 | #include <asm/io.h> |
16 | 17 | #include <asm/arch/imx-regs.h> |
17 | 18 | #include <asm/arch/clock.h> |
... | ... | @@ -31,302 +32,6 @@ |
31 | 32 | |
32 | 33 | DECLARE_GLOBAL_DATA_PTR; |
33 | 34 | |
34 | -#define USB_OTGREGS_OFFSET 0x000 | |
35 | -#define USB_H1REGS_OFFSET 0x200 | |
36 | -#define USB_H2REGS_OFFSET 0x400 | |
37 | -#define USB_H3REGS_OFFSET 0x600 | |
38 | -#define USB_OTHERREGS_OFFSET 0x800 | |
39 | - | |
40 | -#define USB_H1_CTRL_OFFSET 0x04 | |
41 | - | |
42 | -#define ANADIG_USB2_CHRG_DETECT_EN_B 0x00100000 | |
43 | -#define ANADIG_USB2_CHRG_DETECT_CHK_CHRG_B 0x00080000 | |
44 | - | |
45 | -#define ANADIG_USB2_PLL_480_CTRL_BYPASS 0x00010000 | |
46 | -#define ANADIG_USB2_PLL_480_CTRL_ENABLE 0x00002000 | |
47 | -#define ANADIG_USB2_PLL_480_CTRL_POWER 0x00001000 | |
48 | -#define ANADIG_USB2_PLL_480_CTRL_EN_USB_CLKS 0x00000040 | |
49 | - | |
50 | -#define USBNC_OFFSET 0x200 | |
51 | -#define USBNC_PHYCFG2_ACAENB (1 << 4) /* otg_id detection enable */ | |
52 | -#define UCTRL_PWR_POL (1 << 9) /* OTG Polarity of Power Pin */ | |
53 | -#define UCTRL_OVER_CUR_POL (1 << 8) /* OTG Polarity of Overcurrent */ | |
54 | -#define UCTRL_OVER_CUR_DIS (1 << 7) /* Disable OTG Overcurrent Detection */ | |
55 | - | |
56 | -#define PLL_USB_EN_USB_CLKS_MASK (0x01 << 6) | |
57 | -#define PLL_USB_PWR_MASK (0x01 << 12) | |
58 | -#define PLL_USB_ENABLE_MASK (0x01 << 13) | |
59 | -#define PLL_USB_BYPASS_MASK (0x01 << 16) | |
60 | -#define PLL_USB_REG_ENABLE_MASK (0x01 << 21) | |
61 | -#define PLL_USB_DIV_SEL_MASK (0x07 << 22) | |
62 | -#define PLL_USB_LOCK_MASK (0x01 << 31) | |
63 | - | |
64 | -/* USBCMD */ | |
65 | -#define UCMD_RUN_STOP (1 << 0) /* controller run/stop */ | |
66 | -#define UCMD_RESET (1 << 1) /* controller reset */ | |
67 | - | |
68 | -#if defined(CONFIG_MX6) || defined(CONFIG_MX7ULP) || defined(CONFIG_IMX8) | |
69 | -static const ulong phy_bases[] = { | |
70 | - USB_PHY0_BASE_ADDR, | |
71 | -#if defined(USB_PHY1_BASE_ADDR) | |
72 | - USB_PHY1_BASE_ADDR, | |
73 | -#endif | |
74 | -}; | |
75 | - | |
76 | -static void usb_internal_phy_clock_gate(int index, int on) | |
77 | -{ | |
78 | - void __iomem *phy_reg; | |
79 | - | |
80 | - if (index >= ARRAY_SIZE(phy_bases)) | |
81 | - return; | |
82 | - | |
83 | - phy_reg = (void __iomem *)phy_bases[index]; | |
84 | - phy_reg += on ? USBPHY_CTRL_CLR : USBPHY_CTRL_SET; | |
85 | - writel(USBPHY_CTRL_CLKGATE, phy_reg); | |
86 | -} | |
87 | - | |
88 | -static void usb_power_config(int index) | |
89 | -{ | |
90 | -#if defined(CONFIG_MX7ULP) | |
91 | - struct usbphy_regs __iomem *usbphy = | |
92 | - (struct usbphy_regs __iomem *)USB_PHY0_BASE_ADDR; | |
93 | - | |
94 | - if (index > 0) | |
95 | - return; | |
96 | - | |
97 | - writel(ANADIG_USB2_CHRG_DETECT_EN_B | | |
98 | - ANADIG_USB2_CHRG_DETECT_CHK_CHRG_B, | |
99 | - &usbphy->usb1_chrg_detect); | |
100 | - | |
101 | - scg_enable_usb_pll(true); | |
102 | - | |
103 | -#elif defined(CONFIG_IMX8) | |
104 | - struct usbphy_regs __iomem *usbphy = | |
105 | - (struct usbphy_regs __iomem *)USB_PHY0_BASE_ADDR; | |
106 | - int timeout = 1000000; | |
107 | - | |
108 | - if (index > 0) | |
109 | - return; | |
110 | - | |
111 | - writel(ANADIG_USB2_CHRG_DETECT_EN_B | | |
112 | - ANADIG_USB2_CHRG_DETECT_CHK_CHRG_B, | |
113 | - &usbphy->usb1_chrg_detect); | |
114 | - | |
115 | - if (!(readl(&usbphy->usb1_pll_480_ctrl) & PLL_USB_LOCK_MASK)) { | |
116 | - | |
117 | - /* Enable the regulator first */ | |
118 | - writel(PLL_USB_REG_ENABLE_MASK, | |
119 | - &usbphy->usb1_pll_480_ctrl_set); | |
120 | - | |
121 | - /* Wait at least 25us */ | |
122 | - udelay(25); | |
123 | - | |
124 | - /* Enable the power */ | |
125 | - writel(PLL_USB_PWR_MASK, &usbphy->usb1_pll_480_ctrl_set); | |
126 | - | |
127 | - /* Wait lock */ | |
128 | - while (timeout--) { | |
129 | - if (readl(&usbphy->usb1_pll_480_ctrl) & | |
130 | - PLL_USB_LOCK_MASK) | |
131 | - break; | |
132 | - udelay(10); | |
133 | - } | |
134 | - | |
135 | - if (timeout <= 0) { | |
136 | - /* If timeout, we power down the pll */ | |
137 | - writel(PLL_USB_PWR_MASK, | |
138 | - &usbphy->usb1_pll_480_ctrl_clr); | |
139 | - return; | |
140 | - } | |
141 | - } | |
142 | - | |
143 | - /* Clear the bypass */ | |
144 | - writel(PLL_USB_BYPASS_MASK, &usbphy->usb1_pll_480_ctrl_clr); | |
145 | - | |
146 | - /* Enable the PLL clock out to USB */ | |
147 | - writel((PLL_USB_EN_USB_CLKS_MASK | PLL_USB_ENABLE_MASK), | |
148 | - &usbphy->usb1_pll_480_ctrl_set); | |
149 | - | |
150 | -#else | |
151 | - struct anatop_regs __iomem *anatop = | |
152 | - (struct anatop_regs __iomem *)ANATOP_BASE_ADDR; | |
153 | - void __iomem *chrg_detect; | |
154 | - void __iomem *pll_480_ctrl_clr; | |
155 | - void __iomem *pll_480_ctrl_set; | |
156 | - | |
157 | - switch (index) { | |
158 | - case 0: | |
159 | - chrg_detect = &anatop->usb1_chrg_detect; | |
160 | - pll_480_ctrl_clr = &anatop->usb1_pll_480_ctrl_clr; | |
161 | - pll_480_ctrl_set = &anatop->usb1_pll_480_ctrl_set; | |
162 | - break; | |
163 | - case 1: | |
164 | - chrg_detect = &anatop->usb2_chrg_detect; | |
165 | - pll_480_ctrl_clr = &anatop->usb2_pll_480_ctrl_clr; | |
166 | - pll_480_ctrl_set = &anatop->usb2_pll_480_ctrl_set; | |
167 | - break; | |
168 | - default: | |
169 | - return; | |
170 | - } | |
171 | - /* | |
172 | - * Some phy and power's special controls | |
173 | - * 1. The external charger detector needs to be disabled | |
174 | - * or the signal at DP will be poor | |
175 | - * 2. The PLL's power and output to usb | |
176 | - * is totally controlled by IC, so the Software only needs | |
177 | - * to enable them at initializtion. | |
178 | - */ | |
179 | - writel(ANADIG_USB2_CHRG_DETECT_EN_B | | |
180 | - ANADIG_USB2_CHRG_DETECT_CHK_CHRG_B, | |
181 | - chrg_detect); | |
182 | - | |
183 | - writel(ANADIG_USB2_PLL_480_CTRL_BYPASS, | |
184 | - pll_480_ctrl_clr); | |
185 | - | |
186 | - writel(ANADIG_USB2_PLL_480_CTRL_ENABLE | | |
187 | - ANADIG_USB2_PLL_480_CTRL_POWER | | |
188 | - ANADIG_USB2_PLL_480_CTRL_EN_USB_CLKS, | |
189 | - pll_480_ctrl_set); | |
190 | - | |
191 | -#endif | |
192 | -} | |
193 | - | |
194 | -/* Return 0 : host node, <>0 : device mode */ | |
195 | -static int usb_phy_enable(int index, struct usb_ehci *ehci) | |
196 | -{ | |
197 | - void __iomem *phy_reg; | |
198 | - void __iomem *phy_ctrl; | |
199 | - void __iomem *usb_cmd; | |
200 | - int ret; | |
201 | - | |
202 | - if (index >= ARRAY_SIZE(phy_bases)) | |
203 | - return 0; | |
204 | - | |
205 | - phy_reg = (void __iomem *)phy_bases[index]; | |
206 | - phy_ctrl = (void __iomem *)(phy_reg + USBPHY_CTRL); | |
207 | - usb_cmd = (void __iomem *)&ehci->usbcmd; | |
208 | - | |
209 | - /* Stop then Reset */ | |
210 | - clrbits_le32(usb_cmd, UCMD_RUN_STOP); | |
211 | - ret = wait_for_bit_le32(usb_cmd, UCMD_RUN_STOP, false, 10000, false); | |
212 | - if (ret) | |
213 | - return ret; | |
214 | - | |
215 | - setbits_le32(usb_cmd, UCMD_RESET); | |
216 | - ret = wait_for_bit_le32(usb_cmd, UCMD_RESET, false, 10000, false); | |
217 | - if (ret) | |
218 | - return ret; | |
219 | - | |
220 | - /* Reset USBPHY module */ | |
221 | - setbits_le32(phy_ctrl, USBPHY_CTRL_SFTRST); | |
222 | - udelay(10); | |
223 | - | |
224 | - /* Remove CLKGATE and SFTRST */ | |
225 | - clrbits_le32(phy_ctrl, USBPHY_CTRL_CLKGATE | USBPHY_CTRL_SFTRST); | |
226 | - udelay(10); | |
227 | - | |
228 | - /* Power up the PHY */ | |
229 | - writel(0, phy_reg + USBPHY_PWD); | |
230 | - /* enable FS/LS device */ | |
231 | - setbits_le32(phy_ctrl, USBPHY_CTRL_ENUTMILEVEL2 | | |
232 | - USBPHY_CTRL_ENUTMILEVEL3); | |
233 | - | |
234 | - return 0; | |
235 | -} | |
236 | - | |
237 | -int usb_phy_mode(int port) | |
238 | -{ | |
239 | - void __iomem *phy_reg; | |
240 | - void __iomem *phy_ctrl; | |
241 | - u32 val; | |
242 | - | |
243 | - phy_reg = (void __iomem *)phy_bases[port]; | |
244 | - phy_ctrl = (void __iomem *)(phy_reg + USBPHY_CTRL); | |
245 | - | |
246 | - val = readl(phy_ctrl); | |
247 | - | |
248 | - if (val & USBPHY_CTRL_OTG_ID) | |
249 | - return USB_INIT_DEVICE; | |
250 | - else | |
251 | - return USB_INIT_HOST; | |
252 | -} | |
253 | - | |
254 | -#if defined(CONFIG_MX7ULP) | |
255 | -struct usbnc_regs { | |
256 | - u32 ctrl1; | |
257 | - u32 ctrl2; | |
258 | - u32 reserve0[2]; | |
259 | - u32 hsic_ctrl; | |
260 | -}; | |
261 | -#elif defined(CONFIG_IMX8) | |
262 | -struct usbnc_regs { | |
263 | - u32 ctrl1; | |
264 | - u32 ctrl2; | |
265 | - u32 reserve1[10]; | |
266 | - u32 phy_cfg1; | |
267 | - u32 phy_cfg2; | |
268 | - u32 reserve2; | |
269 | - u32 phy_status; | |
270 | - u32 reserve3[4]; | |
271 | - u32 adp_cfg1; | |
272 | - u32 adp_cfg2; | |
273 | - u32 adp_status; | |
274 | -}; | |
275 | -#else | |
276 | -/* Base address for this IP block is 0x02184800 */ | |
277 | -struct usbnc_regs { | |
278 | - u32 ctrl[4]; /* otg/host1-3 */ | |
279 | - u32 uh2_hsic_ctrl; | |
280 | - u32 uh3_hsic_ctrl; | |
281 | - u32 otg_phy_ctrl_0; | |
282 | - u32 uh1_phy_ctrl_0; | |
283 | -}; | |
284 | -#endif | |
285 | - | |
286 | -#elif defined(CONFIG_USB_EHCI_MX7) | |
287 | -struct usbnc_regs { | |
288 | - u32 ctrl1; | |
289 | - u32 ctrl2; | |
290 | - u32 reserve1[10]; | |
291 | - u32 phy_cfg1; | |
292 | - u32 phy_cfg2; | |
293 | - u32 reserve2; | |
294 | - u32 phy_status; | |
295 | - u32 reserve3[4]; | |
296 | - u32 adp_cfg1; | |
297 | - u32 adp_cfg2; | |
298 | - u32 adp_status; | |
299 | -}; | |
300 | - | |
301 | -static void usb_power_config(int index) | |
302 | -{ | |
303 | - struct usbnc_regs *usbnc = (struct usbnc_regs *)(ulong)(USB_BASE_ADDR + | |
304 | - (0x10000 * index) + USBNC_OFFSET); | |
305 | - void __iomem *phy_cfg2 = (void __iomem *)(&usbnc->phy_cfg2); | |
306 | - | |
307 | - /* | |
308 | - * Clear the ACAENB to enable usb_otg_id detection, | |
309 | - * otherwise it is the ACA detection enabled. | |
310 | - */ | |
311 | - clrbits_le32(phy_cfg2, USBNC_PHYCFG2_ACAENB); | |
312 | -} | |
313 | - | |
314 | -int usb_phy_mode(int port) | |
315 | -{ | |
316 | - struct usbnc_regs *usbnc = (struct usbnc_regs *)(ulong)(USB_BASE_ADDR + | |
317 | - (0x10000 * port) + USBNC_OFFSET); | |
318 | - void __iomem *status = (void __iomem *)(&usbnc->phy_status); | |
319 | - u32 val; | |
320 | - | |
321 | - val = readl(status); | |
322 | - | |
323 | - if (val & USBNC_PHYSTATUS_ID_DIG) | |
324 | - return USB_INIT_DEVICE; | |
325 | - else | |
326 | - return USB_INIT_HOST; | |
327 | -} | |
328 | -#endif | |
329 | - | |
330 | 35 | static void ehci_mx6_powerup_fixup(struct ehci_ctrl *ctrl, uint32_t *status_reg, |
331 | 36 | uint32_t *reg) |
332 | 37 | { |
... | ... | @@ -346,35 +51,6 @@ |
346 | 51 | *reg = ehci_readl(status_reg); |
347 | 52 | } |
348 | 53 | |
349 | -static void usb_oc_config(int index) | |
350 | -{ | |
351 | -#if defined(CONFIG_MX6) | |
352 | - struct usbnc_regs *usbnc = (struct usbnc_regs *)(USB_BASE_ADDR + | |
353 | - USB_OTHERREGS_OFFSET); | |
354 | - void __iomem *ctrl = (void __iomem *)(&usbnc->ctrl[index]); | |
355 | -#elif defined(CONFIG_USB_EHCI_MX7) || defined(CONFIG_MX7ULP) || defined(CONFIG_IMX8) | |
356 | - struct usbnc_regs *usbnc = (struct usbnc_regs *)(ulong)(USB_BASE_ADDR + | |
357 | - (0x10000 * index) + USBNC_OFFSET); | |
358 | - void __iomem *ctrl = (void __iomem *)(&usbnc->ctrl1); | |
359 | -#endif | |
360 | - | |
361 | -#if CONFIG_MACH_TYPE == MACH_TYPE_MX6Q_ARM2 | |
362 | - /* mx6qarm2 seems to required a different setting*/ | |
363 | - clrbits_le32(ctrl, UCTRL_OVER_CUR_POL); | |
364 | -#else | |
365 | - setbits_le32(ctrl, UCTRL_OVER_CUR_POL); | |
366 | -#endif | |
367 | - | |
368 | - setbits_le32(ctrl, UCTRL_OVER_CUR_DIS); | |
369 | - | |
370 | - /* Set power polarity to high active */ | |
371 | -#ifdef CONFIG_MXC_USB_OTG_HACTIVE | |
372 | - setbits_le32(ctrl, UCTRL_PWR_POL); | |
373 | -#else | |
374 | - clrbits_le32(ctrl, UCTRL_PWR_POL); | |
375 | -#endif | |
376 | -} | |
377 | - | |
378 | 54 | /** |
379 | 55 | * board_usb_phy_mode - override usb phy mode |
380 | 56 | * @port: usb host/otg port |
... | ... | @@ -393,20 +69,6 @@ |
393 | 69 | } |
394 | 70 | |
395 | 71 | /** |
396 | - * board_ehci_hcd_init - set usb vbus voltage | |
397 | - * @port: usb otg port | |
398 | - * | |
399 | - * Target board specific, setup iomux pad to setup supply vbus voltage | |
400 | - * for usb otg port. Machine board file overrides board_ehci_hcd_init | |
401 | - * | |
402 | - * Return: 0 Success | |
403 | - */ | |
404 | -int __weak board_ehci_hcd_init(int port) | |
405 | -{ | |
406 | - return 0; | |
407 | -} | |
408 | - | |
409 | -/** | |
410 | 72 | * board_ehci_power - enables/disables usb vbus voltage |
411 | 73 | * @port: usb otg port |
412 | 74 | * @on: on/off vbus voltage |
... | ... | @@ -418,36 +80,6 @@ |
418 | 80 | */ |
419 | 81 | int __weak board_ehci_power(int port, int on) |
420 | 82 | { |
421 | - return 0; | |
422 | -} | |
423 | - | |
424 | -int ehci_mx6_common_init(struct usb_ehci *ehci, int index) | |
425 | -{ | |
426 | - int ret; | |
427 | - u32 portsc; | |
428 | - | |
429 | - enable_usboh3_clk(1); | |
430 | - mdelay(1); | |
431 | - | |
432 | - portsc = readl(&ehci->portsc); | |
433 | - if (portsc & PORT_PTS_PHCD) { | |
434 | - debug("suspended: portsc %x, enabled it.\n", portsc); | |
435 | - clrbits_le32(&ehci->portsc, PORT_PTS_PHCD); | |
436 | - } | |
437 | - | |
438 | - /* Do board specific initialization */ | |
439 | - ret = board_ehci_hcd_init(index); | |
440 | - if (ret) | |
441 | - return ret; | |
442 | - | |
443 | - usb_power_config(index); | |
444 | - usb_oc_config(index); | |
445 | - | |
446 | -#if defined(CONFIG_MX6) || defined(CONFIG_MX7ULP) || defined(CONFIG_IMX8) | |
447 | - usb_internal_phy_clock_gate(index, 1); | |
448 | - usb_phy_enable(index, ehci); | |
449 | -#endif | |
450 | - | |
451 | 83 | return 0; |
452 | 84 | } |
453 | 85 |
drivers/usb/imx/Makefile
drivers/usb/imx/usb-mx6-common.c
1 | +// SPDX-License-Identifier: GPL-2.0+ | |
2 | +/* | |
3 | + * Copyright (c) 2009 Daniel Mack <daniel@caiaq.de> | |
4 | + * Copyright (C) 2010 Freescale Semiconductor, Inc. | |
5 | + * Copyright 2017-2019 NXP | |
6 | + * | |
7 | + */ | |
8 | + | |
9 | +#include <common.h> | |
10 | +#include <usb.h> | |
11 | +#include <errno.h> | |
12 | +#include <wait_bit.h> | |
13 | +#include <linux/compiler.h> | |
14 | +#include <usb/ehci-ci.h> | |
15 | +#include <asm/io.h> | |
16 | +#include <asm/arch/imx-regs.h> | |
17 | +#include <asm/arch/clock.h> | |
18 | +#include <asm/mach-imx/iomux-v3.h> | |
19 | +#include <asm/mach-imx/regs-usbphy.h> | |
20 | +#include <asm/mach-imx/sys_proto.h> | |
21 | +#include <asm/mach-types.h> | |
22 | +#include <asm/arch/sys_proto.h> | |
23 | + | |
24 | +DECLARE_GLOBAL_DATA_PTR; | |
25 | + | |
26 | +#define USB_OTGREGS_OFFSET 0x000 | |
27 | +#define USB_H1REGS_OFFSET 0x200 | |
28 | +#define USB_H2REGS_OFFSET 0x400 | |
29 | +#define USB_H3REGS_OFFSET 0x600 | |
30 | +#define USB_OTHERREGS_OFFSET 0x800 | |
31 | + | |
32 | +#define USB_H1_CTRL_OFFSET 0x04 | |
33 | + | |
34 | +#define ANADIG_USB2_CHRG_DETECT_EN_B 0x00100000 | |
35 | +#define ANADIG_USB2_CHRG_DETECT_CHK_CHRG_B 0x00080000 | |
36 | + | |
37 | +#define ANADIG_USB2_PLL_480_CTRL_BYPASS 0x00010000 | |
38 | +#define ANADIG_USB2_PLL_480_CTRL_ENABLE 0x00002000 | |
39 | +#define ANADIG_USB2_PLL_480_CTRL_POWER 0x00001000 | |
40 | +#define ANADIG_USB2_PLL_480_CTRL_EN_USB_CLKS 0x00000040 | |
41 | + | |
42 | +#define USBNC_OFFSET 0x200 | |
43 | +#define USBNC_PHYCFG2_ACAENB (1 << 4) /* otg_id detection enable */ | |
44 | +#define UCTRL_PWR_POL (1 << 9) /* OTG Polarity of Power Pin */ | |
45 | +#define UCTRL_OVER_CUR_POL (1 << 8) /* OTG Polarity of Overcurrent */ | |
46 | +#define UCTRL_OVER_CUR_DIS (1 << 7) /* Disable OTG Overcurrent Detection */ | |
47 | + | |
48 | +#define PLL_USB_EN_USB_CLKS_MASK (0x01 << 6) | |
49 | +#define PLL_USB_PWR_MASK (0x01 << 12) | |
50 | +#define PLL_USB_ENABLE_MASK (0x01 << 13) | |
51 | +#define PLL_USB_BYPASS_MASK (0x01 << 16) | |
52 | +#define PLL_USB_REG_ENABLE_MASK (0x01 << 21) | |
53 | +#define PLL_USB_DIV_SEL_MASK (0x07 << 22) | |
54 | +#define PLL_USB_LOCK_MASK (0x01 << 31) | |
55 | + | |
56 | +/* USBCMD */ | |
57 | +#define UCMD_RUN_STOP (1 << 0) /* controller run/stop */ | |
58 | +#define UCMD_RESET (1 << 1) /* controller reset */ | |
59 | + | |
60 | +#if defined(CONFIG_MX6) || defined(CONFIG_MX7ULP) || defined(CONFIG_IMX8) | |
61 | +static const ulong phy_bases[] = { | |
62 | + USB_PHY0_BASE_ADDR, | |
63 | +#if defined(USB_PHY1_BASE_ADDR) | |
64 | + USB_PHY1_BASE_ADDR, | |
65 | +#endif | |
66 | +}; | |
67 | + | |
68 | +static void usb_internal_phy_clock_gate(int index, int on) | |
69 | +{ | |
70 | + void __iomem *phy_reg; | |
71 | + | |
72 | + if (index >= ARRAY_SIZE(phy_bases)) | |
73 | + return; | |
74 | + | |
75 | + phy_reg = (void __iomem *)phy_bases[index]; | |
76 | + phy_reg += on ? USBPHY_CTRL_CLR : USBPHY_CTRL_SET; | |
77 | + writel(USBPHY_CTRL_CLKGATE, phy_reg); | |
78 | +} | |
79 | + | |
80 | +static void usb_power_config(int index) | |
81 | +{ | |
82 | +#if defined(CONFIG_MX7ULP) | |
83 | + struct usbphy_regs __iomem *usbphy = | |
84 | + (struct usbphy_regs __iomem *)USB_PHY0_BASE_ADDR; | |
85 | + | |
86 | + if (index > 0) | |
87 | + return; | |
88 | + | |
89 | + writel(ANADIG_USB2_CHRG_DETECT_EN_B | | |
90 | + ANADIG_USB2_CHRG_DETECT_CHK_CHRG_B, | |
91 | + &usbphy->usb1_chrg_detect); | |
92 | + | |
93 | + scg_enable_usb_pll(true); | |
94 | + | |
95 | +#elif defined(CONFIG_IMX8) | |
96 | + struct usbphy_regs __iomem *usbphy = | |
97 | + (struct usbphy_regs __iomem *)USB_PHY0_BASE_ADDR; | |
98 | + int timeout = 1000000; | |
99 | + | |
100 | + if (index > 0) | |
101 | + return; | |
102 | + | |
103 | + writel(ANADIG_USB2_CHRG_DETECT_EN_B | | |
104 | + ANADIG_USB2_CHRG_DETECT_CHK_CHRG_B, | |
105 | + &usbphy->usb1_chrg_detect); | |
106 | + | |
107 | + if (!(readl(&usbphy->usb1_pll_480_ctrl) & PLL_USB_LOCK_MASK)) { | |
108 | + | |
109 | + /* Enable the regulator first */ | |
110 | + writel(PLL_USB_REG_ENABLE_MASK, | |
111 | + &usbphy->usb1_pll_480_ctrl_set); | |
112 | + | |
113 | + /* Wait at least 25us */ | |
114 | + udelay(25); | |
115 | + | |
116 | + /* Enable the power */ | |
117 | + writel(PLL_USB_PWR_MASK, &usbphy->usb1_pll_480_ctrl_set); | |
118 | + | |
119 | + /* Wait lock */ | |
120 | + while (timeout--) { | |
121 | + if (readl(&usbphy->usb1_pll_480_ctrl) & | |
122 | + PLL_USB_LOCK_MASK) | |
123 | + break; | |
124 | + udelay(10); | |
125 | + } | |
126 | + | |
127 | + if (timeout <= 0) { | |
128 | + /* If timeout, we power down the pll */ | |
129 | + writel(PLL_USB_PWR_MASK, | |
130 | + &usbphy->usb1_pll_480_ctrl_clr); | |
131 | + return; | |
132 | + } | |
133 | + } | |
134 | + | |
135 | + /* Clear the bypass */ | |
136 | + writel(PLL_USB_BYPASS_MASK, &usbphy->usb1_pll_480_ctrl_clr); | |
137 | + | |
138 | + /* Enable the PLL clock out to USB */ | |
139 | + writel((PLL_USB_EN_USB_CLKS_MASK | PLL_USB_ENABLE_MASK), | |
140 | + &usbphy->usb1_pll_480_ctrl_set); | |
141 | + | |
142 | +#else | |
143 | + struct anatop_regs __iomem *anatop = | |
144 | + (struct anatop_regs __iomem *)ANATOP_BASE_ADDR; | |
145 | + void __iomem *chrg_detect; | |
146 | + void __iomem *pll_480_ctrl_clr; | |
147 | + void __iomem *pll_480_ctrl_set; | |
148 | + | |
149 | + switch (index) { | |
150 | + case 0: | |
151 | + chrg_detect = &anatop->usb1_chrg_detect; | |
152 | + pll_480_ctrl_clr = &anatop->usb1_pll_480_ctrl_clr; | |
153 | + pll_480_ctrl_set = &anatop->usb1_pll_480_ctrl_set; | |
154 | + break; | |
155 | + case 1: | |
156 | + chrg_detect = &anatop->usb2_chrg_detect; | |
157 | + pll_480_ctrl_clr = &anatop->usb2_pll_480_ctrl_clr; | |
158 | + pll_480_ctrl_set = &anatop->usb2_pll_480_ctrl_set; | |
159 | + break; | |
160 | + default: | |
161 | + return; | |
162 | + } | |
163 | + /* | |
164 | + * Some phy and power's special controls | |
165 | + * 1. The external charger detector needs to be disabled | |
166 | + * or the signal at DP will be poor | |
167 | + * 2. The PLL's power and output to usb | |
168 | + * is totally controlled by IC, so the Software only needs | |
169 | + * to enable them at initializtion. | |
170 | + */ | |
171 | + writel(ANADIG_USB2_CHRG_DETECT_EN_B | | |
172 | + ANADIG_USB2_CHRG_DETECT_CHK_CHRG_B, | |
173 | + chrg_detect); | |
174 | + | |
175 | + writel(ANADIG_USB2_PLL_480_CTRL_BYPASS, | |
176 | + pll_480_ctrl_clr); | |
177 | + | |
178 | + writel(ANADIG_USB2_PLL_480_CTRL_ENABLE | | |
179 | + ANADIG_USB2_PLL_480_CTRL_POWER | | |
180 | + ANADIG_USB2_PLL_480_CTRL_EN_USB_CLKS, | |
181 | + pll_480_ctrl_set); | |
182 | + | |
183 | +#endif | |
184 | +} | |
185 | + | |
186 | +/* Return 0 : host node, <>0 : device mode */ | |
187 | +static int usb_phy_enable(int index, struct usb_ehci *ehci) | |
188 | +{ | |
189 | + void __iomem *phy_reg; | |
190 | + void __iomem *phy_ctrl; | |
191 | + void __iomem *usb_cmd; | |
192 | + int ret; | |
193 | + | |
194 | + if (index >= ARRAY_SIZE(phy_bases)) | |
195 | + return 0; | |
196 | + | |
197 | + phy_reg = (void __iomem *)phy_bases[index]; | |
198 | + phy_ctrl = (void __iomem *)(phy_reg + USBPHY_CTRL); | |
199 | + usb_cmd = (void __iomem *)&ehci->usbcmd; | |
200 | + | |
201 | + /* Stop then Reset */ | |
202 | + clrbits_le32(usb_cmd, UCMD_RUN_STOP); | |
203 | + ret = wait_for_bit_le32(usb_cmd, UCMD_RUN_STOP, false, 10000, false); | |
204 | + if (ret) | |
205 | + return ret; | |
206 | + | |
207 | + setbits_le32(usb_cmd, UCMD_RESET); | |
208 | + ret = wait_for_bit_le32(usb_cmd, UCMD_RESET, false, 10000, false); | |
209 | + if (ret) | |
210 | + return ret; | |
211 | + | |
212 | + /* Reset USBPHY module */ | |
213 | + setbits_le32(phy_ctrl, USBPHY_CTRL_SFTRST); | |
214 | + udelay(10); | |
215 | + | |
216 | + /* Remove CLKGATE and SFTRST */ | |
217 | + clrbits_le32(phy_ctrl, USBPHY_CTRL_CLKGATE | USBPHY_CTRL_SFTRST); | |
218 | + udelay(10); | |
219 | + | |
220 | + /* Power up the PHY */ | |
221 | + writel(0, phy_reg + USBPHY_PWD); | |
222 | + /* enable FS/LS device */ | |
223 | + setbits_le32(phy_ctrl, USBPHY_CTRL_ENUTMILEVEL2 | | |
224 | + USBPHY_CTRL_ENUTMILEVEL3); | |
225 | + | |
226 | + return 0; | |
227 | +} | |
228 | + | |
229 | +int usb_phy_mode(int port) | |
230 | +{ | |
231 | + void __iomem *phy_reg; | |
232 | + void __iomem *phy_ctrl; | |
233 | + u32 val; | |
234 | + | |
235 | + phy_reg = (void __iomem *)phy_bases[port]; | |
236 | + phy_ctrl = (void __iomem *)(phy_reg + USBPHY_CTRL); | |
237 | + | |
238 | + val = readl(phy_ctrl); | |
239 | + | |
240 | + if (val & USBPHY_CTRL_OTG_ID) | |
241 | + return USB_INIT_DEVICE; | |
242 | + else | |
243 | + return USB_INIT_HOST; | |
244 | +} | |
245 | + | |
246 | +#if defined(CONFIG_MX7ULP) | |
247 | +struct usbnc_regs { | |
248 | + u32 ctrl1; | |
249 | + u32 ctrl2; | |
250 | + u32 reserve0[2]; | |
251 | + u32 hsic_ctrl; | |
252 | +}; | |
253 | +#elif defined(CONFIG_IMX8) | |
254 | +struct usbnc_regs { | |
255 | + u32 ctrl1; | |
256 | + u32 ctrl2; | |
257 | + u32 reserve1[10]; | |
258 | + u32 phy_cfg1; | |
259 | + u32 phy_cfg2; | |
260 | + u32 reserve2; | |
261 | + u32 phy_status; | |
262 | + u32 reserve3[4]; | |
263 | + u32 adp_cfg1; | |
264 | + u32 adp_cfg2; | |
265 | + u32 adp_status; | |
266 | +}; | |
267 | +#else | |
268 | +/* Base address for this IP block is 0x02184800 */ | |
269 | +struct usbnc_regs { | |
270 | + u32 ctrl[4]; /* otg/host1-3 */ | |
271 | + u32 uh2_hsic_ctrl; | |
272 | + u32 uh3_hsic_ctrl; | |
273 | + u32 otg_phy_ctrl_0; | |
274 | + u32 uh1_phy_ctrl_0; | |
275 | +}; | |
276 | +#endif | |
277 | + | |
278 | +#elif defined(CONFIG_USB_EHCI_MX7) | |
279 | +struct usbnc_regs { | |
280 | + u32 ctrl1; | |
281 | + u32 ctrl2; | |
282 | + u32 reserve1[10]; | |
283 | + u32 phy_cfg1; | |
284 | + u32 phy_cfg2; | |
285 | + u32 reserve2; | |
286 | + u32 phy_status; | |
287 | + u32 reserve3[4]; | |
288 | + u32 adp_cfg1; | |
289 | + u32 adp_cfg2; | |
290 | + u32 adp_status; | |
291 | +}; | |
292 | + | |
293 | +static void usb_power_config(int index) | |
294 | +{ | |
295 | + struct usbnc_regs *usbnc = (struct usbnc_regs *)(ulong)(USB_BASE_ADDR + | |
296 | + (0x10000 * index) + USBNC_OFFSET); | |
297 | + void __iomem *phy_cfg2 = (void __iomem *)(&usbnc->phy_cfg2); | |
298 | + | |
299 | + /* | |
300 | + * Clear the ACAENB to enable usb_otg_id detection, | |
301 | + * otherwise it is the ACA detection enabled. | |
302 | + */ | |
303 | + clrbits_le32(phy_cfg2, USBNC_PHYCFG2_ACAENB); | |
304 | +} | |
305 | + | |
306 | +int usb_phy_mode(int port) | |
307 | +{ | |
308 | + struct usbnc_regs *usbnc = (struct usbnc_regs *)(ulong)(USB_BASE_ADDR + | |
309 | + (0x10000 * port) + USBNC_OFFSET); | |
310 | + void __iomem *status = (void __iomem *)(&usbnc->phy_status); | |
311 | + u32 val; | |
312 | + | |
313 | + val = readl(status); | |
314 | + | |
315 | + if (val & USBNC_PHYSTATUS_ID_DIG) | |
316 | + return USB_INIT_DEVICE; | |
317 | + else | |
318 | + return USB_INIT_HOST; | |
319 | +} | |
320 | +#endif | |
321 | + | |
322 | +static void usb_oc_config(int index) | |
323 | +{ | |
324 | +#if defined(CONFIG_MX6) | |
325 | + struct usbnc_regs *usbnc = (struct usbnc_regs *)(USB_BASE_ADDR + | |
326 | + USB_OTHERREGS_OFFSET); | |
327 | + void __iomem *ctrl = (void __iomem *)(&usbnc->ctrl[index]); | |
328 | +#elif defined(CONFIG_USB_EHCI_MX7) || defined(CONFIG_MX7ULP) || defined(CONFIG_IMX8) | |
329 | + struct usbnc_regs *usbnc = (struct usbnc_regs *)(ulong)(USB_BASE_ADDR + | |
330 | + (0x10000 * index) + USBNC_OFFSET); | |
331 | + void __iomem *ctrl = (void __iomem *)(&usbnc->ctrl1); | |
332 | +#endif | |
333 | + | |
334 | +#if CONFIG_MACH_TYPE == MACH_TYPE_MX6Q_ARM2 | |
335 | + /* mx6qarm2 seems to required a different setting*/ | |
336 | + clrbits_le32(ctrl, UCTRL_OVER_CUR_POL); | |
337 | +#else | |
338 | + setbits_le32(ctrl, UCTRL_OVER_CUR_POL); | |
339 | +#endif | |
340 | + | |
341 | + setbits_le32(ctrl, UCTRL_OVER_CUR_DIS); | |
342 | + | |
343 | + /* Set power polarity to high active */ | |
344 | +#ifdef CONFIG_MXC_USB_OTG_HACTIVE | |
345 | + setbits_le32(ctrl, UCTRL_PWR_POL); | |
346 | +#else | |
347 | + clrbits_le32(ctrl, UCTRL_PWR_POL); | |
348 | +#endif | |
349 | +} | |
350 | + | |
351 | +/** | |
352 | + * board_ehci_hcd_init - set usb vbus voltage | |
353 | + * @port: usb otg port | |
354 | + * | |
355 | + * Target board specific, setup iomux pad to setup supply vbus voltage | |
356 | + * for usb otg port. Machine board file overrides board_ehci_hcd_init | |
357 | + * | |
358 | + * Return: 0 Success | |
359 | + */ | |
360 | +int __weak board_ehci_hcd_init(int port) | |
361 | +{ | |
362 | + return 0; | |
363 | +} | |
364 | + | |
365 | +int ehci_mx6_common_init(struct usb_ehci *ehci, int index) | |
366 | +{ | |
367 | + int ret; | |
368 | + u32 portsc; | |
369 | + | |
370 | + enable_usboh3_clk(1); | |
371 | + mdelay(1); | |
372 | + | |
373 | + portsc = readl(&ehci->portsc); | |
374 | + if (portsc & PORT_PTS_PHCD) { | |
375 | + debug("suspended: portsc %x, enabled it.\n", portsc); | |
376 | + clrbits_le32(&ehci->portsc, PORT_PTS_PHCD); | |
377 | + } | |
378 | + | |
379 | + /* Do board specific initialization */ | |
380 | + ret = board_ehci_hcd_init(index); | |
381 | + if (ret) | |
382 | + return ret; | |
383 | + | |
384 | + usb_power_config(index); | |
385 | + usb_oc_config(index); | |
386 | + | |
387 | +#if defined(CONFIG_MX6) || defined(CONFIG_MX7ULP) || defined(CONFIG_IMX8) | |
388 | + usb_internal_phy_clock_gate(index, 1); | |
389 | + usb_phy_enable(index, ehci); | |
390 | +#endif | |
391 | + | |
392 | + return 0; | |
393 | +} |
include/usb/ci_udc.h
include/usb/usb_mx6_common.h
scripts/Makefile.spl
... | ... | @@ -93,6 +93,7 @@ |
93 | 93 | libs-y += drivers/ |
94 | 94 | libs-$(CONFIG_SPL_USB_GADGET) += drivers/usb/dwc3/ |
95 | 95 | libs-$(CONFIG_SPL_USB_GADGET) += drivers/usb/cdns3/ |
96 | +libs-$(CONFIG_SPL_USB_GADGET) += drivers/usb/imx/ | |
96 | 97 | libs-y += dts/ |
97 | 98 | libs-y += fs/ |
98 | 99 | libs-$(CONFIG_SPL_POST_MEM_SUPPORT) += post/drivers/ |