Commit dd2cdd82b87202f26f50415381acef29c801de88
1 parent
6b8bafd46a
Exists in
smarc-imx_v2018.03_4.14.78_1.0.0_ga
MLK-20569 usb: ehci-mx6: configure usb out of suspend state
When moving to support partition reboot or android auto on XEN, linux kernel will runs into runtime suspend state, and the usb will be configured to low power suspend state by Linux. Then we reboot and runs into U-Boot, however the usb already in suspended state and uboot not able to lock the phy pll, after clearing PHCD to out of suspended state, the phy pll could be locked and fastboot works. Signed-off-by: Peng Fan <peng.fan@nxp.com> Suggested-by: Li Jun <jun.li@nxp.com> Reviewed-by: Ye Li <ye.li@nxp.com> (cherry picked from commit 999ae3e37bc8fea05ac984eb043dd925d80f1208)
Showing 1 changed file with 7 additions and 0 deletions Inline Diff
drivers/usb/host/ehci-mx6.c
1 | /* | 1 | /* |
2 | * Copyright (c) 2009 Daniel Mack <daniel@caiaq.de> | 2 | * Copyright (c) 2009 Daniel Mack <daniel@caiaq.de> |
3 | * Copyright (C) 2010 Freescale Semiconductor, Inc. | 3 | * Copyright (C) 2010 Freescale Semiconductor, Inc. |
4 | * Copyright 2017 NXP | 4 | * Copyright 2017 NXP |
5 | * | 5 | * |
6 | * SPDX-License-Identifier: GPL-2.0+ | 6 | * SPDX-License-Identifier: GPL-2.0+ |
7 | */ | 7 | */ |
8 | 8 | ||
9 | #include <common.h> | 9 | #include <common.h> |
10 | #include <usb.h> | 10 | #include <usb.h> |
11 | #include <errno.h> | 11 | #include <errno.h> |
12 | #include <wait_bit.h> | 12 | #include <wait_bit.h> |
13 | #include <linux/compiler.h> | 13 | #include <linux/compiler.h> |
14 | #include <usb/ehci-ci.h> | 14 | #include <usb/ehci-ci.h> |
15 | #include <asm/io.h> | 15 | #include <asm/io.h> |
16 | #include <asm/arch/imx-regs.h> | 16 | #include <asm/arch/imx-regs.h> |
17 | #include <asm/arch/clock.h> | 17 | #include <asm/arch/clock.h> |
18 | #include <asm/mach-imx/iomux-v3.h> | 18 | #include <asm/mach-imx/iomux-v3.h> |
19 | #include <asm/mach-imx/sys_proto.h> | 19 | #include <asm/mach-imx/sys_proto.h> |
20 | #include <dm.h> | 20 | #include <dm.h> |
21 | #include <asm/mach-types.h> | 21 | #include <asm/mach-types.h> |
22 | #include <power/regulator.h> | 22 | #include <power/regulator.h> |
23 | #include <asm/arch/sys_proto.h> | 23 | #include <asm/arch/sys_proto.h> |
24 | 24 | ||
25 | #include "ehci.h" | 25 | #include "ehci.h" |
26 | #if CONFIG_IS_ENABLED(POWER_DOMAIN) | 26 | #if CONFIG_IS_ENABLED(POWER_DOMAIN) |
27 | #include <power-domain.h> | 27 | #include <power-domain.h> |
28 | #endif | 28 | #endif |
29 | 29 | ||
30 | DECLARE_GLOBAL_DATA_PTR; | 30 | DECLARE_GLOBAL_DATA_PTR; |
31 | 31 | ||
32 | #define USB_OTGREGS_OFFSET 0x000 | 32 | #define USB_OTGREGS_OFFSET 0x000 |
33 | #define USB_H1REGS_OFFSET 0x200 | 33 | #define USB_H1REGS_OFFSET 0x200 |
34 | #define USB_H2REGS_OFFSET 0x400 | 34 | #define USB_H2REGS_OFFSET 0x400 |
35 | #define USB_H3REGS_OFFSET 0x600 | 35 | #define USB_H3REGS_OFFSET 0x600 |
36 | #define USB_OTHERREGS_OFFSET 0x800 | 36 | #define USB_OTHERREGS_OFFSET 0x800 |
37 | 37 | ||
38 | #define USB_H1_CTRL_OFFSET 0x04 | 38 | #define USB_H1_CTRL_OFFSET 0x04 |
39 | 39 | ||
40 | #define USBPHY_CTRL 0x00000030 | 40 | #define USBPHY_CTRL 0x00000030 |
41 | #define USBPHY_CTRL_SET 0x00000034 | 41 | #define USBPHY_CTRL_SET 0x00000034 |
42 | #define USBPHY_CTRL_CLR 0x00000038 | 42 | #define USBPHY_CTRL_CLR 0x00000038 |
43 | #define USBPHY_CTRL_TOG 0x0000003c | 43 | #define USBPHY_CTRL_TOG 0x0000003c |
44 | 44 | ||
45 | #define USBPHY_PWD 0x00000000 | 45 | #define USBPHY_PWD 0x00000000 |
46 | #define USBPHY_CTRL_SFTRST 0x80000000 | 46 | #define USBPHY_CTRL_SFTRST 0x80000000 |
47 | #define USBPHY_CTRL_CLKGATE 0x40000000 | 47 | #define USBPHY_CTRL_CLKGATE 0x40000000 |
48 | #define USBPHY_CTRL_ENUTMILEVEL3 0x00008000 | 48 | #define USBPHY_CTRL_ENUTMILEVEL3 0x00008000 |
49 | #define USBPHY_CTRL_ENUTMILEVEL2 0x00004000 | 49 | #define USBPHY_CTRL_ENUTMILEVEL2 0x00004000 |
50 | #define USBPHY_CTRL_OTG_ID 0x08000000 | 50 | #define USBPHY_CTRL_OTG_ID 0x08000000 |
51 | 51 | ||
52 | #define ANADIG_USB2_CHRG_DETECT_EN_B 0x00100000 | 52 | #define ANADIG_USB2_CHRG_DETECT_EN_B 0x00100000 |
53 | #define ANADIG_USB2_CHRG_DETECT_CHK_CHRG_B 0x00080000 | 53 | #define ANADIG_USB2_CHRG_DETECT_CHK_CHRG_B 0x00080000 |
54 | 54 | ||
55 | #define ANADIG_USB2_PLL_480_CTRL_BYPASS 0x00010000 | 55 | #define ANADIG_USB2_PLL_480_CTRL_BYPASS 0x00010000 |
56 | #define ANADIG_USB2_PLL_480_CTRL_ENABLE 0x00002000 | 56 | #define ANADIG_USB2_PLL_480_CTRL_ENABLE 0x00002000 |
57 | #define ANADIG_USB2_PLL_480_CTRL_POWER 0x00001000 | 57 | #define ANADIG_USB2_PLL_480_CTRL_POWER 0x00001000 |
58 | #define ANADIG_USB2_PLL_480_CTRL_EN_USB_CLKS 0x00000040 | 58 | #define ANADIG_USB2_PLL_480_CTRL_EN_USB_CLKS 0x00000040 |
59 | 59 | ||
60 | #define USBNC_OFFSET 0x200 | 60 | #define USBNC_OFFSET 0x200 |
61 | #define USBNC_PHY_STATUS_OFFSET 0x23C | 61 | #define USBNC_PHY_STATUS_OFFSET 0x23C |
62 | #define USBNC_PHYSTATUS_ID_DIG (1 << 4) /* otg_id status */ | 62 | #define USBNC_PHYSTATUS_ID_DIG (1 << 4) /* otg_id status */ |
63 | #define USBNC_PHYCFG2_ACAENB (1 << 4) /* otg_id detection enable */ | 63 | #define USBNC_PHYCFG2_ACAENB (1 << 4) /* otg_id detection enable */ |
64 | #define UCTRL_PWR_POL (1 << 9) /* OTG Polarity of Power Pin */ | 64 | #define UCTRL_PWR_POL (1 << 9) /* OTG Polarity of Power Pin */ |
65 | #define UCTRL_OVER_CUR_POL (1 << 8) /* OTG Polarity of Overcurrent */ | 65 | #define UCTRL_OVER_CUR_POL (1 << 8) /* OTG Polarity of Overcurrent */ |
66 | #define UCTRL_OVER_CUR_DIS (1 << 7) /* Disable OTG Overcurrent Detection */ | 66 | #define UCTRL_OVER_CUR_DIS (1 << 7) /* Disable OTG Overcurrent Detection */ |
67 | 67 | ||
68 | #define PLL_USB_EN_USB_CLKS_MASK (0x01 << 6) | 68 | #define PLL_USB_EN_USB_CLKS_MASK (0x01 << 6) |
69 | #define PLL_USB_PWR_MASK (0x01 << 12) | 69 | #define PLL_USB_PWR_MASK (0x01 << 12) |
70 | #define PLL_USB_ENABLE_MASK (0x01 << 13) | 70 | #define PLL_USB_ENABLE_MASK (0x01 << 13) |
71 | #define PLL_USB_BYPASS_MASK (0x01 << 16) | 71 | #define PLL_USB_BYPASS_MASK (0x01 << 16) |
72 | #define PLL_USB_REG_ENABLE_MASK (0x01 << 21) | 72 | #define PLL_USB_REG_ENABLE_MASK (0x01 << 21) |
73 | #define PLL_USB_DIV_SEL_MASK (0x07 << 22) | 73 | #define PLL_USB_DIV_SEL_MASK (0x07 << 22) |
74 | #define PLL_USB_LOCK_MASK (0x01 << 31) | 74 | #define PLL_USB_LOCK_MASK (0x01 << 31) |
75 | 75 | ||
76 | /* USBCMD */ | 76 | /* USBCMD */ |
77 | #define UCMD_RUN_STOP (1 << 0) /* controller run/stop */ | 77 | #define UCMD_RUN_STOP (1 << 0) /* controller run/stop */ |
78 | #define UCMD_RESET (1 << 1) /* controller reset */ | 78 | #define UCMD_RESET (1 << 1) /* controller reset */ |
79 | 79 | ||
80 | #if defined(CONFIG_MX6) || defined(CONFIG_MX7ULP) || defined(CONFIG_IMX8) | 80 | #if defined(CONFIG_MX6) || defined(CONFIG_MX7ULP) || defined(CONFIG_IMX8) |
81 | static const ulong phy_bases[] = { | 81 | static const ulong phy_bases[] = { |
82 | USB_PHY0_BASE_ADDR, | 82 | USB_PHY0_BASE_ADDR, |
83 | #if defined(USB_PHY1_BASE_ADDR) | 83 | #if defined(USB_PHY1_BASE_ADDR) |
84 | USB_PHY1_BASE_ADDR, | 84 | USB_PHY1_BASE_ADDR, |
85 | #endif | 85 | #endif |
86 | }; | 86 | }; |
87 | 87 | ||
88 | static void usb_internal_phy_clock_gate(int index, int on) | 88 | static void usb_internal_phy_clock_gate(int index, int on) |
89 | { | 89 | { |
90 | void __iomem *phy_reg; | 90 | void __iomem *phy_reg; |
91 | 91 | ||
92 | if (index >= ARRAY_SIZE(phy_bases)) | 92 | if (index >= ARRAY_SIZE(phy_bases)) |
93 | return; | 93 | return; |
94 | 94 | ||
95 | phy_reg = (void __iomem *)phy_bases[index]; | 95 | phy_reg = (void __iomem *)phy_bases[index]; |
96 | phy_reg += on ? USBPHY_CTRL_CLR : USBPHY_CTRL_SET; | 96 | phy_reg += on ? USBPHY_CTRL_CLR : USBPHY_CTRL_SET; |
97 | writel(USBPHY_CTRL_CLKGATE, phy_reg); | 97 | writel(USBPHY_CTRL_CLKGATE, phy_reg); |
98 | } | 98 | } |
99 | 99 | ||
100 | static void usb_power_config(int index) | 100 | static void usb_power_config(int index) |
101 | { | 101 | { |
102 | #if defined(CONFIG_MX7ULP) | 102 | #if defined(CONFIG_MX7ULP) |
103 | struct usbphy_regs __iomem *usbphy = | 103 | struct usbphy_regs __iomem *usbphy = |
104 | (struct usbphy_regs __iomem *)USB_PHY0_BASE_ADDR; | 104 | (struct usbphy_regs __iomem *)USB_PHY0_BASE_ADDR; |
105 | 105 | ||
106 | if (index > 0) | 106 | if (index > 0) |
107 | return; | 107 | return; |
108 | 108 | ||
109 | writel(ANADIG_USB2_CHRG_DETECT_EN_B | | 109 | writel(ANADIG_USB2_CHRG_DETECT_EN_B | |
110 | ANADIG_USB2_CHRG_DETECT_CHK_CHRG_B, | 110 | ANADIG_USB2_CHRG_DETECT_CHK_CHRG_B, |
111 | &usbphy->usb1_chrg_detect); | 111 | &usbphy->usb1_chrg_detect); |
112 | 112 | ||
113 | scg_enable_usb_pll(true); | 113 | scg_enable_usb_pll(true); |
114 | 114 | ||
115 | #elif defined(CONFIG_IMX8) | 115 | #elif defined(CONFIG_IMX8) |
116 | struct usbphy_regs __iomem *usbphy = | 116 | struct usbphy_regs __iomem *usbphy = |
117 | (struct usbphy_regs __iomem *)USB_PHY0_BASE_ADDR; | 117 | (struct usbphy_regs __iomem *)USB_PHY0_BASE_ADDR; |
118 | int timeout = 1000000; | 118 | int timeout = 1000000; |
119 | 119 | ||
120 | if (index > 0) | 120 | if (index > 0) |
121 | return; | 121 | return; |
122 | 122 | ||
123 | writel(ANADIG_USB2_CHRG_DETECT_EN_B | | 123 | writel(ANADIG_USB2_CHRG_DETECT_EN_B | |
124 | ANADIG_USB2_CHRG_DETECT_CHK_CHRG_B, | 124 | ANADIG_USB2_CHRG_DETECT_CHK_CHRG_B, |
125 | &usbphy->usb1_chrg_detect); | 125 | &usbphy->usb1_chrg_detect); |
126 | 126 | ||
127 | if (!(readl(&usbphy->usb1_pll_480_ctrl) & PLL_USB_LOCK_MASK)) { | 127 | if (!(readl(&usbphy->usb1_pll_480_ctrl) & PLL_USB_LOCK_MASK)) { |
128 | 128 | ||
129 | /* Enable the regulator first */ | 129 | /* Enable the regulator first */ |
130 | writel(PLL_USB_REG_ENABLE_MASK, | 130 | writel(PLL_USB_REG_ENABLE_MASK, |
131 | &usbphy->usb1_pll_480_ctrl_set); | 131 | &usbphy->usb1_pll_480_ctrl_set); |
132 | 132 | ||
133 | /* Wait at least 25us */ | 133 | /* Wait at least 25us */ |
134 | udelay(25); | 134 | udelay(25); |
135 | 135 | ||
136 | /* Enable the power */ | 136 | /* Enable the power */ |
137 | writel(PLL_USB_PWR_MASK, &usbphy->usb1_pll_480_ctrl_set); | 137 | writel(PLL_USB_PWR_MASK, &usbphy->usb1_pll_480_ctrl_set); |
138 | 138 | ||
139 | /* Wait lock */ | 139 | /* Wait lock */ |
140 | while (timeout--) { | 140 | while (timeout--) { |
141 | if (readl(&usbphy->usb1_pll_480_ctrl) & | 141 | if (readl(&usbphy->usb1_pll_480_ctrl) & |
142 | PLL_USB_LOCK_MASK) | 142 | PLL_USB_LOCK_MASK) |
143 | break; | 143 | break; |
144 | udelay(10); | 144 | udelay(10); |
145 | } | 145 | } |
146 | 146 | ||
147 | if (timeout <= 0) { | 147 | if (timeout <= 0) { |
148 | /* If timeout, we power down the pll */ | 148 | /* If timeout, we power down the pll */ |
149 | writel(PLL_USB_PWR_MASK, | 149 | writel(PLL_USB_PWR_MASK, |
150 | &usbphy->usb1_pll_480_ctrl_clr); | 150 | &usbphy->usb1_pll_480_ctrl_clr); |
151 | return; | 151 | return; |
152 | } | 152 | } |
153 | } | 153 | } |
154 | 154 | ||
155 | /* Clear the bypass */ | 155 | /* Clear the bypass */ |
156 | writel(PLL_USB_BYPASS_MASK, &usbphy->usb1_pll_480_ctrl_clr); | 156 | writel(PLL_USB_BYPASS_MASK, &usbphy->usb1_pll_480_ctrl_clr); |
157 | 157 | ||
158 | /* Enable the PLL clock out to USB */ | 158 | /* Enable the PLL clock out to USB */ |
159 | writel((PLL_USB_EN_USB_CLKS_MASK | PLL_USB_ENABLE_MASK), | 159 | writel((PLL_USB_EN_USB_CLKS_MASK | PLL_USB_ENABLE_MASK), |
160 | &usbphy->usb1_pll_480_ctrl_set); | 160 | &usbphy->usb1_pll_480_ctrl_set); |
161 | 161 | ||
162 | #else | 162 | #else |
163 | struct anatop_regs __iomem *anatop = | 163 | struct anatop_regs __iomem *anatop = |
164 | (struct anatop_regs __iomem *)ANATOP_BASE_ADDR; | 164 | (struct anatop_regs __iomem *)ANATOP_BASE_ADDR; |
165 | void __iomem *chrg_detect; | 165 | void __iomem *chrg_detect; |
166 | void __iomem *pll_480_ctrl_clr; | 166 | void __iomem *pll_480_ctrl_clr; |
167 | void __iomem *pll_480_ctrl_set; | 167 | void __iomem *pll_480_ctrl_set; |
168 | 168 | ||
169 | switch (index) { | 169 | switch (index) { |
170 | case 0: | 170 | case 0: |
171 | chrg_detect = &anatop->usb1_chrg_detect; | 171 | chrg_detect = &anatop->usb1_chrg_detect; |
172 | pll_480_ctrl_clr = &anatop->usb1_pll_480_ctrl_clr; | 172 | pll_480_ctrl_clr = &anatop->usb1_pll_480_ctrl_clr; |
173 | pll_480_ctrl_set = &anatop->usb1_pll_480_ctrl_set; | 173 | pll_480_ctrl_set = &anatop->usb1_pll_480_ctrl_set; |
174 | break; | 174 | break; |
175 | case 1: | 175 | case 1: |
176 | chrg_detect = &anatop->usb2_chrg_detect; | 176 | chrg_detect = &anatop->usb2_chrg_detect; |
177 | pll_480_ctrl_clr = &anatop->usb2_pll_480_ctrl_clr; | 177 | pll_480_ctrl_clr = &anatop->usb2_pll_480_ctrl_clr; |
178 | pll_480_ctrl_set = &anatop->usb2_pll_480_ctrl_set; | 178 | pll_480_ctrl_set = &anatop->usb2_pll_480_ctrl_set; |
179 | break; | 179 | break; |
180 | default: | 180 | default: |
181 | return; | 181 | return; |
182 | } | 182 | } |
183 | /* | 183 | /* |
184 | * Some phy and power's special controls | 184 | * Some phy and power's special controls |
185 | * 1. The external charger detector needs to be disabled | 185 | * 1. The external charger detector needs to be disabled |
186 | * or the signal at DP will be poor | 186 | * or the signal at DP will be poor |
187 | * 2. The PLL's power and output to usb | 187 | * 2. The PLL's power and output to usb |
188 | * is totally controlled by IC, so the Software only needs | 188 | * is totally controlled by IC, so the Software only needs |
189 | * to enable them at initializtion. | 189 | * to enable them at initializtion. |
190 | */ | 190 | */ |
191 | writel(ANADIG_USB2_CHRG_DETECT_EN_B | | 191 | writel(ANADIG_USB2_CHRG_DETECT_EN_B | |
192 | ANADIG_USB2_CHRG_DETECT_CHK_CHRG_B, | 192 | ANADIG_USB2_CHRG_DETECT_CHK_CHRG_B, |
193 | chrg_detect); | 193 | chrg_detect); |
194 | 194 | ||
195 | writel(ANADIG_USB2_PLL_480_CTRL_BYPASS, | 195 | writel(ANADIG_USB2_PLL_480_CTRL_BYPASS, |
196 | pll_480_ctrl_clr); | 196 | pll_480_ctrl_clr); |
197 | 197 | ||
198 | writel(ANADIG_USB2_PLL_480_CTRL_ENABLE | | 198 | writel(ANADIG_USB2_PLL_480_CTRL_ENABLE | |
199 | ANADIG_USB2_PLL_480_CTRL_POWER | | 199 | ANADIG_USB2_PLL_480_CTRL_POWER | |
200 | ANADIG_USB2_PLL_480_CTRL_EN_USB_CLKS, | 200 | ANADIG_USB2_PLL_480_CTRL_EN_USB_CLKS, |
201 | pll_480_ctrl_set); | 201 | pll_480_ctrl_set); |
202 | 202 | ||
203 | #endif | 203 | #endif |
204 | } | 204 | } |
205 | 205 | ||
206 | /* Return 0 : host node, <>0 : device mode */ | 206 | /* Return 0 : host node, <>0 : device mode */ |
207 | static int usb_phy_enable(int index, struct usb_ehci *ehci) | 207 | static int usb_phy_enable(int index, struct usb_ehci *ehci) |
208 | { | 208 | { |
209 | void __iomem *phy_reg; | 209 | void __iomem *phy_reg; |
210 | void __iomem *phy_ctrl; | 210 | void __iomem *phy_ctrl; |
211 | void __iomem *usb_cmd; | 211 | void __iomem *usb_cmd; |
212 | int ret; | 212 | int ret; |
213 | 213 | ||
214 | if (index >= ARRAY_SIZE(phy_bases)) | 214 | if (index >= ARRAY_SIZE(phy_bases)) |
215 | return 0; | 215 | return 0; |
216 | 216 | ||
217 | phy_reg = (void __iomem *)phy_bases[index]; | 217 | phy_reg = (void __iomem *)phy_bases[index]; |
218 | phy_ctrl = (void __iomem *)(phy_reg + USBPHY_CTRL); | 218 | phy_ctrl = (void __iomem *)(phy_reg + USBPHY_CTRL); |
219 | usb_cmd = (void __iomem *)&ehci->usbcmd; | 219 | usb_cmd = (void __iomem *)&ehci->usbcmd; |
220 | 220 | ||
221 | /* Stop then Reset */ | 221 | /* Stop then Reset */ |
222 | clrbits_le32(usb_cmd, UCMD_RUN_STOP); | 222 | clrbits_le32(usb_cmd, UCMD_RUN_STOP); |
223 | ret = wait_for_bit_le32(usb_cmd, UCMD_RUN_STOP, false, 10000, false); | 223 | ret = wait_for_bit_le32(usb_cmd, UCMD_RUN_STOP, false, 10000, false); |
224 | if (ret) | 224 | if (ret) |
225 | return ret; | 225 | return ret; |
226 | 226 | ||
227 | setbits_le32(usb_cmd, UCMD_RESET); | 227 | setbits_le32(usb_cmd, UCMD_RESET); |
228 | ret = wait_for_bit_le32(usb_cmd, UCMD_RESET, false, 10000, false); | 228 | ret = wait_for_bit_le32(usb_cmd, UCMD_RESET, false, 10000, false); |
229 | if (ret) | 229 | if (ret) |
230 | return ret; | 230 | return ret; |
231 | 231 | ||
232 | /* Reset USBPHY module */ | 232 | /* Reset USBPHY module */ |
233 | setbits_le32(phy_ctrl, USBPHY_CTRL_SFTRST); | 233 | setbits_le32(phy_ctrl, USBPHY_CTRL_SFTRST); |
234 | udelay(10); | 234 | udelay(10); |
235 | 235 | ||
236 | /* Remove CLKGATE and SFTRST */ | 236 | /* Remove CLKGATE and SFTRST */ |
237 | clrbits_le32(phy_ctrl, USBPHY_CTRL_CLKGATE | USBPHY_CTRL_SFTRST); | 237 | clrbits_le32(phy_ctrl, USBPHY_CTRL_CLKGATE | USBPHY_CTRL_SFTRST); |
238 | udelay(10); | 238 | udelay(10); |
239 | 239 | ||
240 | /* Power up the PHY */ | 240 | /* Power up the PHY */ |
241 | writel(0, phy_reg + USBPHY_PWD); | 241 | writel(0, phy_reg + USBPHY_PWD); |
242 | /* enable FS/LS device */ | 242 | /* enable FS/LS device */ |
243 | setbits_le32(phy_ctrl, USBPHY_CTRL_ENUTMILEVEL2 | | 243 | setbits_le32(phy_ctrl, USBPHY_CTRL_ENUTMILEVEL2 | |
244 | USBPHY_CTRL_ENUTMILEVEL3); | 244 | USBPHY_CTRL_ENUTMILEVEL3); |
245 | 245 | ||
246 | return 0; | 246 | return 0; |
247 | } | 247 | } |
248 | 248 | ||
249 | int usb_phy_mode(int port) | 249 | int usb_phy_mode(int port) |
250 | { | 250 | { |
251 | void __iomem *phy_reg; | 251 | void __iomem *phy_reg; |
252 | void __iomem *phy_ctrl; | 252 | void __iomem *phy_ctrl; |
253 | u32 val; | 253 | u32 val; |
254 | 254 | ||
255 | phy_reg = (void __iomem *)phy_bases[port]; | 255 | phy_reg = (void __iomem *)phy_bases[port]; |
256 | phy_ctrl = (void __iomem *)(phy_reg + USBPHY_CTRL); | 256 | phy_ctrl = (void __iomem *)(phy_reg + USBPHY_CTRL); |
257 | 257 | ||
258 | val = readl(phy_ctrl); | 258 | val = readl(phy_ctrl); |
259 | 259 | ||
260 | if (val & USBPHY_CTRL_OTG_ID) | 260 | if (val & USBPHY_CTRL_OTG_ID) |
261 | return USB_INIT_DEVICE; | 261 | return USB_INIT_DEVICE; |
262 | else | 262 | else |
263 | return USB_INIT_HOST; | 263 | return USB_INIT_HOST; |
264 | } | 264 | } |
265 | 265 | ||
266 | #if defined(CONFIG_MX7ULP) | 266 | #if defined(CONFIG_MX7ULP) |
267 | struct usbnc_regs { | 267 | struct usbnc_regs { |
268 | u32 ctrl1; | 268 | u32 ctrl1; |
269 | u32 ctrl2; | 269 | u32 ctrl2; |
270 | u32 reserve0[2]; | 270 | u32 reserve0[2]; |
271 | u32 hsic_ctrl; | 271 | u32 hsic_ctrl; |
272 | }; | 272 | }; |
273 | #elif defined(CONFIG_IMX8) | 273 | #elif defined(CONFIG_IMX8) |
274 | struct usbnc_regs { | 274 | struct usbnc_regs { |
275 | u32 ctrl1; | 275 | u32 ctrl1; |
276 | u32 ctrl2; | 276 | u32 ctrl2; |
277 | u32 reserve1[10]; | 277 | u32 reserve1[10]; |
278 | u32 phy_cfg1; | 278 | u32 phy_cfg1; |
279 | u32 phy_cfg2; | 279 | u32 phy_cfg2; |
280 | u32 reserve2; | 280 | u32 reserve2; |
281 | u32 phy_status; | 281 | u32 phy_status; |
282 | u32 reserve3[4]; | 282 | u32 reserve3[4]; |
283 | u32 adp_cfg1; | 283 | u32 adp_cfg1; |
284 | u32 adp_cfg2; | 284 | u32 adp_cfg2; |
285 | u32 adp_status; | 285 | u32 adp_status; |
286 | }; | 286 | }; |
287 | #else | 287 | #else |
288 | /* Base address for this IP block is 0x02184800 */ | 288 | /* Base address for this IP block is 0x02184800 */ |
289 | struct usbnc_regs { | 289 | struct usbnc_regs { |
290 | u32 ctrl[4]; /* otg/host1-3 */ | 290 | u32 ctrl[4]; /* otg/host1-3 */ |
291 | u32 uh2_hsic_ctrl; | 291 | u32 uh2_hsic_ctrl; |
292 | u32 uh3_hsic_ctrl; | 292 | u32 uh3_hsic_ctrl; |
293 | u32 otg_phy_ctrl_0; | 293 | u32 otg_phy_ctrl_0; |
294 | u32 uh1_phy_ctrl_0; | 294 | u32 uh1_phy_ctrl_0; |
295 | }; | 295 | }; |
296 | #endif | 296 | #endif |
297 | 297 | ||
298 | #elif defined(CONFIG_USB_EHCI_MX7) | 298 | #elif defined(CONFIG_USB_EHCI_MX7) |
299 | struct usbnc_regs { | 299 | struct usbnc_regs { |
300 | u32 ctrl1; | 300 | u32 ctrl1; |
301 | u32 ctrl2; | 301 | u32 ctrl2; |
302 | u32 reserve1[10]; | 302 | u32 reserve1[10]; |
303 | u32 phy_cfg1; | 303 | u32 phy_cfg1; |
304 | u32 phy_cfg2; | 304 | u32 phy_cfg2; |
305 | u32 reserve2; | 305 | u32 reserve2; |
306 | u32 phy_status; | 306 | u32 phy_status; |
307 | u32 reserve3[4]; | 307 | u32 reserve3[4]; |
308 | u32 adp_cfg1; | 308 | u32 adp_cfg1; |
309 | u32 adp_cfg2; | 309 | u32 adp_cfg2; |
310 | u32 adp_status; | 310 | u32 adp_status; |
311 | }; | 311 | }; |
312 | 312 | ||
313 | static void usb_power_config(int index) | 313 | static void usb_power_config(int index) |
314 | { | 314 | { |
315 | struct usbnc_regs *usbnc = (struct usbnc_regs *)(ulong)(USB_BASE_ADDR + | 315 | struct usbnc_regs *usbnc = (struct usbnc_regs *)(ulong)(USB_BASE_ADDR + |
316 | (0x10000 * index) + USBNC_OFFSET); | 316 | (0x10000 * index) + USBNC_OFFSET); |
317 | void __iomem *phy_cfg2 = (void __iomem *)(&usbnc->phy_cfg2); | 317 | void __iomem *phy_cfg2 = (void __iomem *)(&usbnc->phy_cfg2); |
318 | 318 | ||
319 | /* | 319 | /* |
320 | * Clear the ACAENB to enable usb_otg_id detection, | 320 | * Clear the ACAENB to enable usb_otg_id detection, |
321 | * otherwise it is the ACA detection enabled. | 321 | * otherwise it is the ACA detection enabled. |
322 | */ | 322 | */ |
323 | clrbits_le32(phy_cfg2, USBNC_PHYCFG2_ACAENB); | 323 | clrbits_le32(phy_cfg2, USBNC_PHYCFG2_ACAENB); |
324 | } | 324 | } |
325 | 325 | ||
326 | int usb_phy_mode(int port) | 326 | int usb_phy_mode(int port) |
327 | { | 327 | { |
328 | struct usbnc_regs *usbnc = (struct usbnc_regs *)(ulong)(USB_BASE_ADDR + | 328 | struct usbnc_regs *usbnc = (struct usbnc_regs *)(ulong)(USB_BASE_ADDR + |
329 | (0x10000 * port) + USBNC_OFFSET); | 329 | (0x10000 * port) + USBNC_OFFSET); |
330 | void __iomem *status = (void __iomem *)(&usbnc->phy_status); | 330 | void __iomem *status = (void __iomem *)(&usbnc->phy_status); |
331 | u32 val; | 331 | u32 val; |
332 | 332 | ||
333 | val = readl(status); | 333 | val = readl(status); |
334 | 334 | ||
335 | if (val & USBNC_PHYSTATUS_ID_DIG) | 335 | if (val & USBNC_PHYSTATUS_ID_DIG) |
336 | return USB_INIT_DEVICE; | 336 | return USB_INIT_DEVICE; |
337 | else | 337 | else |
338 | return USB_INIT_HOST; | 338 | return USB_INIT_HOST; |
339 | } | 339 | } |
340 | #endif | 340 | #endif |
341 | 341 | ||
342 | static void ehci_mx6_powerup_fixup(struct ehci_ctrl *ctrl, uint32_t *status_reg, | 342 | static void ehci_mx6_powerup_fixup(struct ehci_ctrl *ctrl, uint32_t *status_reg, |
343 | uint32_t *reg) | 343 | uint32_t *reg) |
344 | { | 344 | { |
345 | uint32_t result; | 345 | uint32_t result; |
346 | int usec = 2000; | 346 | int usec = 2000; |
347 | 347 | ||
348 | mdelay(50); | 348 | mdelay(50); |
349 | 349 | ||
350 | do { | 350 | do { |
351 | result = ehci_readl(status_reg); | 351 | result = ehci_readl(status_reg); |
352 | udelay(5); | 352 | udelay(5); |
353 | if (!(result & EHCI_PS_PR)) | 353 | if (!(result & EHCI_PS_PR)) |
354 | break; | 354 | break; |
355 | usec--; | 355 | usec--; |
356 | } while (usec > 0); | 356 | } while (usec > 0); |
357 | 357 | ||
358 | *reg = ehci_readl(status_reg); | 358 | *reg = ehci_readl(status_reg); |
359 | } | 359 | } |
360 | 360 | ||
361 | static void usb_oc_config(int index) | 361 | static void usb_oc_config(int index) |
362 | { | 362 | { |
363 | #if defined(CONFIG_MX6) | 363 | #if defined(CONFIG_MX6) |
364 | struct usbnc_regs *usbnc = (struct usbnc_regs *)(USB_BASE_ADDR + | 364 | struct usbnc_regs *usbnc = (struct usbnc_regs *)(USB_BASE_ADDR + |
365 | USB_OTHERREGS_OFFSET); | 365 | USB_OTHERREGS_OFFSET); |
366 | void __iomem *ctrl = (void __iomem *)(&usbnc->ctrl[index]); | 366 | void __iomem *ctrl = (void __iomem *)(&usbnc->ctrl[index]); |
367 | #elif defined(CONFIG_USB_EHCI_MX7) || defined(CONFIG_MX7ULP) || defined(CONFIG_IMX8) | 367 | #elif defined(CONFIG_USB_EHCI_MX7) || defined(CONFIG_MX7ULP) || defined(CONFIG_IMX8) |
368 | struct usbnc_regs *usbnc = (struct usbnc_regs *)(ulong)(USB_BASE_ADDR + | 368 | struct usbnc_regs *usbnc = (struct usbnc_regs *)(ulong)(USB_BASE_ADDR + |
369 | (0x10000 * index) + USBNC_OFFSET); | 369 | (0x10000 * index) + USBNC_OFFSET); |
370 | void __iomem *ctrl = (void __iomem *)(&usbnc->ctrl1); | 370 | void __iomem *ctrl = (void __iomem *)(&usbnc->ctrl1); |
371 | #endif | 371 | #endif |
372 | 372 | ||
373 | #if CONFIG_MACH_TYPE == MACH_TYPE_MX6Q_ARM2 | 373 | #if CONFIG_MACH_TYPE == MACH_TYPE_MX6Q_ARM2 |
374 | /* mx6qarm2 seems to required a different setting*/ | 374 | /* mx6qarm2 seems to required a different setting*/ |
375 | clrbits_le32(ctrl, UCTRL_OVER_CUR_POL); | 375 | clrbits_le32(ctrl, UCTRL_OVER_CUR_POL); |
376 | #else | 376 | #else |
377 | setbits_le32(ctrl, UCTRL_OVER_CUR_POL); | 377 | setbits_le32(ctrl, UCTRL_OVER_CUR_POL); |
378 | #endif | 378 | #endif |
379 | 379 | ||
380 | setbits_le32(ctrl, UCTRL_OVER_CUR_DIS); | 380 | setbits_le32(ctrl, UCTRL_OVER_CUR_DIS); |
381 | 381 | ||
382 | /* Set power polarity to high active */ | 382 | /* Set power polarity to high active */ |
383 | #ifdef CONFIG_MXC_USB_OTG_HACTIVE | 383 | #ifdef CONFIG_MXC_USB_OTG_HACTIVE |
384 | setbits_le32(ctrl, UCTRL_PWR_POL); | 384 | setbits_le32(ctrl, UCTRL_PWR_POL); |
385 | #else | 385 | #else |
386 | clrbits_le32(ctrl, UCTRL_PWR_POL); | 386 | clrbits_le32(ctrl, UCTRL_PWR_POL); |
387 | #endif | 387 | #endif |
388 | } | 388 | } |
389 | 389 | ||
390 | /** | 390 | /** |
391 | * board_usb_phy_mode - override usb phy mode | 391 | * board_usb_phy_mode - override usb phy mode |
392 | * @port: usb host/otg port | 392 | * @port: usb host/otg port |
393 | * | 393 | * |
394 | * Target board specific, override usb_phy_mode. | 394 | * Target board specific, override usb_phy_mode. |
395 | * When usb-otg is used as usb host port, iomux pad usb_otg_id can be | 395 | * When usb-otg is used as usb host port, iomux pad usb_otg_id can be |
396 | * left disconnected in this case usb_phy_mode will not be able to identify | 396 | * left disconnected in this case usb_phy_mode will not be able to identify |
397 | * the phy mode that usb port is used. | 397 | * the phy mode that usb port is used. |
398 | * Machine file overrides board_usb_phy_mode. | 398 | * Machine file overrides board_usb_phy_mode. |
399 | * | 399 | * |
400 | * Return: USB_INIT_DEVICE or USB_INIT_HOST | 400 | * Return: USB_INIT_DEVICE or USB_INIT_HOST |
401 | */ | 401 | */ |
402 | int __weak board_usb_phy_mode(int port) | 402 | int __weak board_usb_phy_mode(int port) |
403 | { | 403 | { |
404 | return usb_phy_mode(port); | 404 | return usb_phy_mode(port); |
405 | } | 405 | } |
406 | 406 | ||
407 | /** | 407 | /** |
408 | * board_ehci_hcd_init - set usb vbus voltage | 408 | * board_ehci_hcd_init - set usb vbus voltage |
409 | * @port: usb otg port | 409 | * @port: usb otg port |
410 | * | 410 | * |
411 | * Target board specific, setup iomux pad to setup supply vbus voltage | 411 | * Target board specific, setup iomux pad to setup supply vbus voltage |
412 | * for usb otg port. Machine board file overrides board_ehci_hcd_init | 412 | * for usb otg port. Machine board file overrides board_ehci_hcd_init |
413 | * | 413 | * |
414 | * Return: 0 Success | 414 | * Return: 0 Success |
415 | */ | 415 | */ |
416 | int __weak board_ehci_hcd_init(int port) | 416 | int __weak board_ehci_hcd_init(int port) |
417 | { | 417 | { |
418 | return 0; | 418 | return 0; |
419 | } | 419 | } |
420 | 420 | ||
421 | /** | 421 | /** |
422 | * board_ehci_power - enables/disables usb vbus voltage | 422 | * board_ehci_power - enables/disables usb vbus voltage |
423 | * @port: usb otg port | 423 | * @port: usb otg port |
424 | * @on: on/off vbus voltage | 424 | * @on: on/off vbus voltage |
425 | * | 425 | * |
426 | * Enables/disables supply vbus voltage for usb otg port. | 426 | * Enables/disables supply vbus voltage for usb otg port. |
427 | * Machine board file overrides board_ehci_power | 427 | * Machine board file overrides board_ehci_power |
428 | * | 428 | * |
429 | * Return: 0 Success | 429 | * Return: 0 Success |
430 | */ | 430 | */ |
431 | int __weak board_ehci_power(int port, int on) | 431 | int __weak board_ehci_power(int port, int on) |
432 | { | 432 | { |
433 | return 0; | 433 | return 0; |
434 | } | 434 | } |
435 | 435 | ||
436 | int ehci_mx6_common_init(struct usb_ehci *ehci, int index) | 436 | int ehci_mx6_common_init(struct usb_ehci *ehci, int index) |
437 | { | 437 | { |
438 | int ret; | 438 | int ret; |
439 | u32 portsc; | ||
439 | 440 | ||
440 | enable_usboh3_clk(1); | 441 | enable_usboh3_clk(1); |
441 | mdelay(1); | 442 | mdelay(1); |
443 | |||
444 | portsc = readl(&ehci->portsc); | ||
445 | if (portsc & PORT_PTS_PHCD) { | ||
446 | debug("suspended: portsc %x, enabled it.\n", portsc); | ||
447 | clrbits_le32(&ehci->portsc, PORT_PTS_PHCD); | ||
448 | } | ||
442 | 449 | ||
443 | /* Do board specific initialization */ | 450 | /* Do board specific initialization */ |
444 | ret = board_ehci_hcd_init(index); | 451 | ret = board_ehci_hcd_init(index); |
445 | if (ret) | 452 | if (ret) |
446 | return ret; | 453 | return ret; |
447 | 454 | ||
448 | usb_power_config(index); | 455 | usb_power_config(index); |
449 | usb_oc_config(index); | 456 | usb_oc_config(index); |
450 | 457 | ||
451 | #if defined(CONFIG_MX6) || defined(CONFIG_MX7ULP) || defined(CONFIG_IMX8) | 458 | #if defined(CONFIG_MX6) || defined(CONFIG_MX7ULP) || defined(CONFIG_IMX8) |
452 | usb_internal_phy_clock_gate(index, 1); | 459 | usb_internal_phy_clock_gate(index, 1); |
453 | usb_phy_enable(index, ehci); | 460 | usb_phy_enable(index, ehci); |
454 | #endif | 461 | #endif |
455 | 462 | ||
456 | return 0; | 463 | return 0; |
457 | } | 464 | } |
458 | 465 | ||
459 | #ifndef CONFIG_DM_USB | 466 | #ifndef CONFIG_DM_USB |
460 | static const struct ehci_ops mx6_ehci_ops = { | 467 | static const struct ehci_ops mx6_ehci_ops = { |
461 | .powerup_fixup = ehci_mx6_powerup_fixup, | 468 | .powerup_fixup = ehci_mx6_powerup_fixup, |
462 | }; | 469 | }; |
463 | 470 | ||
464 | int ehci_hcd_init(int index, enum usb_init_type init, | 471 | int ehci_hcd_init(int index, enum usb_init_type init, |
465 | struct ehci_hccr **hccr, struct ehci_hcor **hcor) | 472 | struct ehci_hccr **hccr, struct ehci_hcor **hcor) |
466 | { | 473 | { |
467 | enum usb_init_type type; | 474 | enum usb_init_type type; |
468 | #if defined(CONFIG_MX6) | 475 | #if defined(CONFIG_MX6) |
469 | u32 controller_spacing = 0x200; | 476 | u32 controller_spacing = 0x200; |
470 | #elif defined(CONFIG_USB_EHCI_MX7) || defined(CONFIG_MX7ULP) || defined(CONFIG_IMX8) | 477 | #elif defined(CONFIG_USB_EHCI_MX7) || defined(CONFIG_MX7ULP) || defined(CONFIG_IMX8) |
471 | u32 controller_spacing = 0x10000; | 478 | u32 controller_spacing = 0x10000; |
472 | #endif | 479 | #endif |
473 | struct usb_ehci *ehci = (struct usb_ehci *)(ulong)(USB_BASE_ADDR + | 480 | struct usb_ehci *ehci = (struct usb_ehci *)(ulong)(USB_BASE_ADDR + |
474 | (controller_spacing * index)); | 481 | (controller_spacing * index)); |
475 | int ret; | 482 | int ret; |
476 | 483 | ||
477 | if (index > 3) | 484 | if (index > 3) |
478 | return -EINVAL; | 485 | return -EINVAL; |
479 | 486 | ||
480 | #if defined(CONFIG_MX6) | 487 | #if defined(CONFIG_MX6) |
481 | if (mx6_usb_fused((u32)ehci)) { | 488 | if (mx6_usb_fused((u32)ehci)) { |
482 | printf("USB@0x%x is fused, disable it\n", (u32)ehci); | 489 | printf("USB@0x%x is fused, disable it\n", (u32)ehci); |
483 | return -ENODEV; | 490 | return -ENODEV; |
484 | } | 491 | } |
485 | #endif | 492 | #endif |
486 | 493 | ||
487 | ret = ehci_mx6_common_init(ehci, index); | 494 | ret = ehci_mx6_common_init(ehci, index); |
488 | if (ret) | 495 | if (ret) |
489 | return ret; | 496 | return ret; |
490 | 497 | ||
491 | ehci_set_controller_priv(index, NULL, &mx6_ehci_ops); | 498 | ehci_set_controller_priv(index, NULL, &mx6_ehci_ops); |
492 | 499 | ||
493 | type = board_usb_phy_mode(index); | 500 | type = board_usb_phy_mode(index); |
494 | 501 | ||
495 | if (hccr && hcor) { | 502 | if (hccr && hcor) { |
496 | *hccr = (struct ehci_hccr *)((ulong)&ehci->caplength); | 503 | *hccr = (struct ehci_hccr *)((ulong)&ehci->caplength); |
497 | *hcor = (struct ehci_hcor *)((ulong)*hccr + | 504 | *hcor = (struct ehci_hcor *)((ulong)*hccr + |
498 | HC_LENGTH(ehci_readl(&(*hccr)->cr_capbase))); | 505 | HC_LENGTH(ehci_readl(&(*hccr)->cr_capbase))); |
499 | } | 506 | } |
500 | 507 | ||
501 | if ((type == init) || (type == USB_INIT_DEVICE)) | 508 | if ((type == init) || (type == USB_INIT_DEVICE)) |
502 | board_ehci_power(index, (type == USB_INIT_DEVICE) ? 0 : 1); | 509 | board_ehci_power(index, (type == USB_INIT_DEVICE) ? 0 : 1); |
503 | if (type != init) | 510 | if (type != init) |
504 | return -ENODEV; | 511 | return -ENODEV; |
505 | if (type == USB_INIT_DEVICE) | 512 | if (type == USB_INIT_DEVICE) |
506 | return 0; | 513 | return 0; |
507 | 514 | ||
508 | setbits_le32(&ehci->usbmode, CM_HOST); | 515 | setbits_le32(&ehci->usbmode, CM_HOST); |
509 | writel(CONFIG_MXC_USB_PORTSC, &ehci->portsc); | 516 | writel(CONFIG_MXC_USB_PORTSC, &ehci->portsc); |
510 | setbits_le32(&ehci->portsc, USB_EN); | 517 | setbits_le32(&ehci->portsc, USB_EN); |
511 | 518 | ||
512 | mdelay(10); | 519 | mdelay(10); |
513 | 520 | ||
514 | return 0; | 521 | return 0; |
515 | } | 522 | } |
516 | 523 | ||
517 | int ehci_hcd_stop(int index) | 524 | int ehci_hcd_stop(int index) |
518 | { | 525 | { |
519 | return 0; | 526 | return 0; |
520 | } | 527 | } |
521 | #else | 528 | #else |
522 | #define USB_INIT_UNKNOWN (USB_INIT_DEVICE + 1) | 529 | #define USB_INIT_UNKNOWN (USB_INIT_DEVICE + 1) |
523 | 530 | ||
524 | struct ehci_mx6_priv_data { | 531 | struct ehci_mx6_priv_data { |
525 | struct ehci_ctrl ctrl; | 532 | struct ehci_ctrl ctrl; |
526 | struct usb_ehci *ehci; | 533 | struct usb_ehci *ehci; |
527 | struct udevice *vbus_supply; | 534 | struct udevice *vbus_supply; |
528 | enum usb_init_type init_type; | 535 | enum usb_init_type init_type; |
529 | void *__iomem phy_base; | 536 | void *__iomem phy_base; |
530 | int portnr; | 537 | int portnr; |
531 | }; | 538 | }; |
532 | 539 | ||
533 | static int mx6_init_after_reset(struct ehci_ctrl *dev) | 540 | static int mx6_init_after_reset(struct ehci_ctrl *dev) |
534 | { | 541 | { |
535 | struct ehci_mx6_priv_data *priv = dev->priv; | 542 | struct ehci_mx6_priv_data *priv = dev->priv; |
536 | enum usb_init_type type = priv->init_type; | 543 | enum usb_init_type type = priv->init_type; |
537 | struct usb_ehci *ehci = priv->ehci; | 544 | struct usb_ehci *ehci = priv->ehci; |
538 | int ret; | 545 | int ret; |
539 | 546 | ||
540 | ret = board_usb_init(priv->portnr, priv->init_type); | 547 | ret = board_usb_init(priv->portnr, priv->init_type); |
541 | if (ret) { | 548 | if (ret) { |
542 | printf("Failed to initialize board for USB\n"); | 549 | printf("Failed to initialize board for USB\n"); |
543 | return ret; | 550 | return ret; |
544 | } | 551 | } |
545 | 552 | ||
546 | ret = ehci_mx6_common_init(priv->ehci, priv->portnr); | 553 | ret = ehci_mx6_common_init(priv->ehci, priv->portnr); |
547 | if (ret) | 554 | if (ret) |
548 | return ret; | 555 | return ret; |
549 | 556 | ||
550 | if (priv->vbus_supply) { | 557 | if (priv->vbus_supply) { |
551 | ret = regulator_set_enable(priv->vbus_supply, | 558 | ret = regulator_set_enable(priv->vbus_supply, |
552 | (type == USB_INIT_DEVICE) ? | 559 | (type == USB_INIT_DEVICE) ? |
553 | false : true); | 560 | false : true); |
554 | if (ret) { | 561 | if (ret) { |
555 | puts("Error enabling VBUS supply\n"); | 562 | puts("Error enabling VBUS supply\n"); |
556 | return ret; | 563 | return ret; |
557 | } | 564 | } |
558 | } | 565 | } |
559 | 566 | ||
560 | if (type == USB_INIT_DEVICE) | 567 | if (type == USB_INIT_DEVICE) |
561 | return 0; | 568 | return 0; |
562 | 569 | ||
563 | setbits_le32(&ehci->usbmode, CM_HOST); | 570 | setbits_le32(&ehci->usbmode, CM_HOST); |
564 | writel(CONFIG_MXC_USB_PORTSC, &ehci->portsc); | 571 | writel(CONFIG_MXC_USB_PORTSC, &ehci->portsc); |
565 | setbits_le32(&ehci->portsc, USB_EN); | 572 | setbits_le32(&ehci->portsc, USB_EN); |
566 | 573 | ||
567 | mdelay(10); | 574 | mdelay(10); |
568 | 575 | ||
569 | return 0; | 576 | return 0; |
570 | } | 577 | } |
571 | 578 | ||
572 | static const struct ehci_ops mx6_ehci_ops = { | 579 | static const struct ehci_ops mx6_ehci_ops = { |
573 | .powerup_fixup = ehci_mx6_powerup_fixup, | 580 | .powerup_fixup = ehci_mx6_powerup_fixup, |
574 | .init_after_reset = mx6_init_after_reset | 581 | .init_after_reset = mx6_init_after_reset |
575 | }; | 582 | }; |
576 | 583 | ||
577 | /** | 584 | /** |
578 | * board_ehci_usb_phy_mode - override usb phy mode | 585 | * board_ehci_usb_phy_mode - override usb phy mode |
579 | * @port: usb host/otg port | 586 | * @port: usb host/otg port |
580 | * | 587 | * |
581 | * Target board specific, override usb_phy_mode. | 588 | * Target board specific, override usb_phy_mode. |
582 | * When usb-otg is used as usb host port, iomux pad usb_otg_id can be | 589 | * When usb-otg is used as usb host port, iomux pad usb_otg_id can be |
583 | * left disconnected in this case usb_phy_mode will not be able to identify | 590 | * left disconnected in this case usb_phy_mode will not be able to identify |
584 | * the phy mode that usb port is used. | 591 | * the phy mode that usb port is used. |
585 | * Machine file overrides board_usb_phy_mode. | 592 | * Machine file overrides board_usb_phy_mode. |
586 | * When the extcon property is set in DTB, machine must provide this function, otherwise | 593 | * When the extcon property is set in DTB, machine must provide this function, otherwise |
587 | * it will default return HOST. | 594 | * it will default return HOST. |
588 | * | 595 | * |
589 | * Return: USB_INIT_DEVICE or USB_INIT_HOST | 596 | * Return: USB_INIT_DEVICE or USB_INIT_HOST |
590 | */ | 597 | */ |
591 | int __weak board_ehci_usb_phy_mode(struct udevice *dev) | 598 | int __weak board_ehci_usb_phy_mode(struct udevice *dev) |
592 | { | 599 | { |
593 | return USB_INIT_HOST; | 600 | return USB_INIT_HOST; |
594 | } | 601 | } |
595 | 602 | ||
596 | static int ehci_usb_phy_mode(struct udevice *dev) | 603 | static int ehci_usb_phy_mode(struct udevice *dev) |
597 | { | 604 | { |
598 | struct ehci_mx6_priv_data *priv = dev_get_priv(dev); | 605 | struct ehci_mx6_priv_data *priv = dev_get_priv(dev); |
599 | void *__iomem phy_ctrl, *__iomem phy_status; | 606 | void *__iomem phy_ctrl, *__iomem phy_status; |
600 | u32 val; | 607 | u32 val; |
601 | 608 | ||
602 | if (is_mx6() || is_mx7ulp() || is_imx8()) { | 609 | if (is_mx6() || is_mx7ulp() || is_imx8()) { |
603 | phy_ctrl = (void __iomem *)(priv->phy_base + USBPHY_CTRL); | 610 | phy_ctrl = (void __iomem *)(priv->phy_base + USBPHY_CTRL); |
604 | val = readl(phy_ctrl); | 611 | val = readl(phy_ctrl); |
605 | 612 | ||
606 | if (val & USBPHY_CTRL_OTG_ID) | 613 | if (val & USBPHY_CTRL_OTG_ID) |
607 | priv->init_type = USB_INIT_DEVICE; | 614 | priv->init_type = USB_INIT_DEVICE; |
608 | else | 615 | else |
609 | priv->init_type = USB_INIT_HOST; | 616 | priv->init_type = USB_INIT_HOST; |
610 | } else if (is_mx7() || is_imx8mm()) { | 617 | } else if (is_mx7() || is_imx8mm()) { |
611 | phy_status = (void __iomem *)(priv->phy_base + | 618 | phy_status = (void __iomem *)(priv->phy_base + |
612 | USBNC_PHY_STATUS_OFFSET); | 619 | USBNC_PHY_STATUS_OFFSET); |
613 | val = readl(phy_status); | 620 | val = readl(phy_status); |
614 | 621 | ||
615 | if (val & USBNC_PHYSTATUS_ID_DIG) | 622 | if (val & USBNC_PHYSTATUS_ID_DIG) |
616 | priv->init_type = USB_INIT_DEVICE; | 623 | priv->init_type = USB_INIT_DEVICE; |
617 | else | 624 | else |
618 | priv->init_type = USB_INIT_HOST; | 625 | priv->init_type = USB_INIT_HOST; |
619 | } else { | 626 | } else { |
620 | return -EINVAL; | 627 | return -EINVAL; |
621 | } | 628 | } |
622 | 629 | ||
623 | return 0; | 630 | return 0; |
624 | } | 631 | } |
625 | 632 | ||
626 | static int ehci_get_usb_phy(struct udevice *dev) | 633 | static int ehci_get_usb_phy(struct udevice *dev) |
627 | { | 634 | { |
628 | struct ehci_mx6_priv_data *priv = dev_get_priv(dev); | 635 | struct ehci_mx6_priv_data *priv = dev_get_priv(dev); |
629 | void *__iomem addr = (void *__iomem)devfdt_get_addr(dev); | 636 | void *__iomem addr = (void *__iomem)devfdt_get_addr(dev); |
630 | const void *blob = gd->fdt_blob; | 637 | const void *blob = gd->fdt_blob; |
631 | int offset = dev_of_offset(dev), phy_off; | 638 | int offset = dev_of_offset(dev), phy_off; |
632 | 639 | ||
633 | /* | 640 | /* |
634 | * About fsl,usbphy, Refer to | 641 | * About fsl,usbphy, Refer to |
635 | * Documentation/devicetree/bindings/usb/ci-hdrc-usb2.txt. | 642 | * Documentation/devicetree/bindings/usb/ci-hdrc-usb2.txt. |
636 | */ | 643 | */ |
637 | if (is_mx6() || is_mx7ulp() || is_imx8()) { | 644 | if (is_mx6() || is_mx7ulp() || is_imx8()) { |
638 | phy_off = fdtdec_lookup_phandle(blob, | 645 | phy_off = fdtdec_lookup_phandle(blob, |
639 | offset, | 646 | offset, |
640 | "fsl,usbphy"); | 647 | "fsl,usbphy"); |
641 | if (phy_off < 0) | 648 | if (phy_off < 0) |
642 | return -EINVAL; | 649 | return -EINVAL; |
643 | 650 | ||
644 | addr = (void __iomem *)fdtdec_get_addr(blob, phy_off, | 651 | addr = (void __iomem *)fdtdec_get_addr(blob, phy_off, |
645 | "reg"); | 652 | "reg"); |
646 | if ((fdt_addr_t)addr == FDT_ADDR_T_NONE) | 653 | if ((fdt_addr_t)addr == FDT_ADDR_T_NONE) |
647 | return -EINVAL; | 654 | return -EINVAL; |
648 | 655 | ||
649 | /* Need to power on the PHY before access it */ | 656 | /* Need to power on the PHY before access it */ |
650 | #if CONFIG_IS_ENABLED(POWER_DOMAIN) | 657 | #if CONFIG_IS_ENABLED(POWER_DOMAIN) |
651 | struct udevice phy_dev; | 658 | struct udevice phy_dev; |
652 | struct power_domain pd; | 659 | struct power_domain pd; |
653 | 660 | ||
654 | phy_dev.node = offset_to_ofnode(phy_off); | 661 | phy_dev.node = offset_to_ofnode(phy_off); |
655 | if (!power_domain_get(&phy_dev, &pd)) { | 662 | if (!power_domain_get(&phy_dev, &pd)) { |
656 | if (power_domain_on(&pd)) | 663 | if (power_domain_on(&pd)) |
657 | return -EINVAL; | 664 | return -EINVAL; |
658 | } | 665 | } |
659 | #endif | 666 | #endif |
660 | priv->phy_base = addr; | 667 | priv->phy_base = addr; |
661 | } else if (is_mx7() || is_imx8mm()) { | 668 | } else if (is_mx7() || is_imx8mm()) { |
662 | priv->phy_base = addr; | 669 | priv->phy_base = addr; |
663 | } else { | 670 | } else { |
664 | return -EINVAL; | 671 | return -EINVAL; |
665 | } | 672 | } |
666 | 673 | ||
667 | return 0; | 674 | return 0; |
668 | } | 675 | } |
669 | 676 | ||
670 | static int ehci_usb_ofdata_to_platdata(struct udevice *dev) | 677 | static int ehci_usb_ofdata_to_platdata(struct udevice *dev) |
671 | { | 678 | { |
672 | struct usb_platdata *plat = dev_get_platdata(dev); | 679 | struct usb_platdata *plat = dev_get_platdata(dev); |
673 | struct ehci_mx6_priv_data *priv = dev_get_priv(dev); | 680 | struct ehci_mx6_priv_data *priv = dev_get_priv(dev); |
674 | const char *mode; | 681 | const char *mode; |
675 | const struct fdt_property *extcon; | 682 | const struct fdt_property *extcon; |
676 | 683 | ||
677 | mode = fdt_getprop(gd->fdt_blob, dev_of_offset(dev), "dr_mode", NULL); | 684 | mode = fdt_getprop(gd->fdt_blob, dev_of_offset(dev), "dr_mode", NULL); |
678 | if (mode) { | 685 | if (mode) { |
679 | if (strcmp(mode, "peripheral") == 0) | 686 | if (strcmp(mode, "peripheral") == 0) |
680 | priv->init_type = USB_INIT_DEVICE; | 687 | priv->init_type = USB_INIT_DEVICE; |
681 | else if (strcmp(mode, "host") == 0) | 688 | else if (strcmp(mode, "host") == 0) |
682 | priv->init_type = USB_INIT_HOST; | 689 | priv->init_type = USB_INIT_HOST; |
683 | else if (strcmp(mode, "otg") == 0) | 690 | else if (strcmp(mode, "otg") == 0) |
684 | priv->init_type = USB_INIT_UNKNOWN; | 691 | priv->init_type = USB_INIT_UNKNOWN; |
685 | else | 692 | else |
686 | return -EINVAL; | 693 | return -EINVAL; |
687 | } else { | 694 | } else { |
688 | extcon = fdt_get_property(gd->fdt_blob, dev_of_offset(dev), | 695 | extcon = fdt_get_property(gd->fdt_blob, dev_of_offset(dev), |
689 | "extcon", NULL); | 696 | "extcon", NULL); |
690 | if (extcon) | 697 | if (extcon) |
691 | priv->init_type = board_ehci_usb_phy_mode(dev); | 698 | priv->init_type = board_ehci_usb_phy_mode(dev); |
692 | else | 699 | else |
693 | priv->init_type = USB_INIT_UNKNOWN; | 700 | priv->init_type = USB_INIT_UNKNOWN; |
694 | } | 701 | } |
695 | 702 | ||
696 | if (priv->init_type != USB_INIT_UNKNOWN && priv->init_type != plat->init_type) { | 703 | if (priv->init_type != USB_INIT_UNKNOWN && priv->init_type != plat->init_type) { |
697 | debug("Request USB type is %u, board forced type is %u\n", | 704 | debug("Request USB type is %u, board forced type is %u\n", |
698 | plat->init_type, priv->init_type); | 705 | plat->init_type, priv->init_type); |
699 | return -ENODEV; | 706 | return -ENODEV; |
700 | } | 707 | } |
701 | 708 | ||
702 | return 0; | 709 | return 0; |
703 | } | 710 | } |
704 | 711 | ||
705 | static int ehci_usb_probe(struct udevice *dev) | 712 | static int ehci_usb_probe(struct udevice *dev) |
706 | { | 713 | { |
707 | struct usb_platdata *plat = dev_get_platdata(dev); | 714 | struct usb_platdata *plat = dev_get_platdata(dev); |
708 | struct usb_ehci *ehci = (struct usb_ehci *)devfdt_get_addr(dev); | 715 | struct usb_ehci *ehci = (struct usb_ehci *)devfdt_get_addr(dev); |
709 | struct ehci_mx6_priv_data *priv = dev_get_priv(dev); | 716 | struct ehci_mx6_priv_data *priv = dev_get_priv(dev); |
710 | enum usb_init_type type = plat->init_type; | 717 | enum usb_init_type type = plat->init_type; |
711 | struct ehci_hccr *hccr; | 718 | struct ehci_hccr *hccr; |
712 | struct ehci_hcor *hcor; | 719 | struct ehci_hcor *hcor; |
713 | int ret; | 720 | int ret; |
714 | 721 | ||
715 | #if defined(CONFIG_MX6) | 722 | #if defined(CONFIG_MX6) |
716 | if (mx6_usb_fused((u32)ehci)) { | 723 | if (mx6_usb_fused((u32)ehci)) { |
717 | printf("USB@0x%x is fused, disable it\n", (u32)ehci); | 724 | printf("USB@0x%x is fused, disable it\n", (u32)ehci); |
718 | return -ENODEV; | 725 | return -ENODEV; |
719 | } | 726 | } |
720 | #endif | 727 | #endif |
721 | 728 | ||
722 | priv->ehci = ehci; | 729 | priv->ehci = ehci; |
723 | priv->portnr = dev->seq; | 730 | priv->portnr = dev->seq; |
724 | 731 | ||
725 | /* Init usb board level according to the requested init type */ | 732 | /* Init usb board level according to the requested init type */ |
726 | ret = board_usb_init(priv->portnr, type); | 733 | ret = board_usb_init(priv->portnr, type); |
727 | if (ret) { | 734 | if (ret) { |
728 | printf("Failed to initialize board for USB\n"); | 735 | printf("Failed to initialize board for USB\n"); |
729 | return ret; | 736 | return ret; |
730 | } | 737 | } |
731 | 738 | ||
732 | ret = device_get_supply_regulator(dev, "vbus-supply", | 739 | ret = device_get_supply_regulator(dev, "vbus-supply", |
733 | &priv->vbus_supply); | 740 | &priv->vbus_supply); |
734 | if (ret) | 741 | if (ret) |
735 | debug("%s: No vbus supply\n", dev->name); | 742 | debug("%s: No vbus supply\n", dev->name); |
736 | 743 | ||
737 | ret = ehci_get_usb_phy(dev); | 744 | ret = ehci_get_usb_phy(dev); |
738 | if (ret) { | 745 | if (ret) { |
739 | debug("%s: fail to get USB PHY base\n", dev->name); | 746 | debug("%s: fail to get USB PHY base\n", dev->name); |
740 | return ret; | 747 | return ret; |
741 | } | 748 | } |
742 | 749 | ||
743 | ret = ehci_mx6_common_init(ehci, priv->portnr); | 750 | ret = ehci_mx6_common_init(ehci, priv->portnr); |
744 | if (ret) | 751 | if (ret) |
745 | return ret; | 752 | return ret; |
746 | 753 | ||
747 | /* If the init_type is unknown due to it is not forced in DTB, we use USB ID to detect */ | 754 | /* If the init_type is unknown due to it is not forced in DTB, we use USB ID to detect */ |
748 | if (priv->init_type == USB_INIT_UNKNOWN) { | 755 | if (priv->init_type == USB_INIT_UNKNOWN) { |
749 | ret = ehci_usb_phy_mode(dev); | 756 | ret = ehci_usb_phy_mode(dev); |
750 | if (ret) | 757 | if (ret) |
751 | return ret; | 758 | return ret; |
752 | if (priv->init_type != type) | 759 | if (priv->init_type != type) |
753 | return -ENODEV; | 760 | return -ENODEV; |
754 | } | 761 | } |
755 | 762 | ||
756 | if (priv->vbus_supply) { | 763 | if (priv->vbus_supply) { |
757 | ret = regulator_set_enable(priv->vbus_supply, | 764 | ret = regulator_set_enable(priv->vbus_supply, |
758 | (priv->init_type == USB_INIT_DEVICE) ? | 765 | (priv->init_type == USB_INIT_DEVICE) ? |
759 | false : true); | 766 | false : true); |
760 | if (ret) { | 767 | if (ret) { |
761 | puts("Error enabling VBUS supply\n"); | 768 | puts("Error enabling VBUS supply\n"); |
762 | return ret; | 769 | return ret; |
763 | } | 770 | } |
764 | } | 771 | } |
765 | 772 | ||
766 | if (priv->init_type == USB_INIT_HOST) { | 773 | if (priv->init_type == USB_INIT_HOST) { |
767 | setbits_le32(&ehci->usbmode, CM_HOST); | 774 | setbits_le32(&ehci->usbmode, CM_HOST); |
768 | writel(CONFIG_MXC_USB_PORTSC, &ehci->portsc); | 775 | writel(CONFIG_MXC_USB_PORTSC, &ehci->portsc); |
769 | setbits_le32(&ehci->portsc, USB_EN); | 776 | setbits_le32(&ehci->portsc, USB_EN); |
770 | } | 777 | } |
771 | 778 | ||
772 | mdelay(10); | 779 | mdelay(10); |
773 | 780 | ||
774 | hccr = (struct ehci_hccr *)((ulong)&ehci->caplength); | 781 | hccr = (struct ehci_hccr *)((ulong)&ehci->caplength); |
775 | hcor = (struct ehci_hcor *)((ulong)hccr + | 782 | hcor = (struct ehci_hcor *)((ulong)hccr + |
776 | HC_LENGTH(ehci_readl(&(hccr)->cr_capbase))); | 783 | HC_LENGTH(ehci_readl(&(hccr)->cr_capbase))); |
777 | 784 | ||
778 | return ehci_register(dev, hccr, hcor, &mx6_ehci_ops, 0, priv->init_type); | 785 | return ehci_register(dev, hccr, hcor, &mx6_ehci_ops, 0, priv->init_type); |
779 | } | 786 | } |
780 | 787 | ||
781 | int ehci_usb_remove(struct udevice *dev) | 788 | int ehci_usb_remove(struct udevice *dev) |
782 | { | 789 | { |
783 | struct ehci_mx6_priv_data *priv = dev_get_priv(dev); | 790 | struct ehci_mx6_priv_data *priv = dev_get_priv(dev); |
784 | struct usb_platdata *plat = dev_get_platdata(dev); | 791 | struct usb_platdata *plat = dev_get_platdata(dev); |
785 | 792 | ||
786 | ehci_deregister(dev); | 793 | ehci_deregister(dev); |
787 | 794 | ||
788 | plat->init_type = 0; /* Clean the requested usb type to host mode */ | 795 | plat->init_type = 0; /* Clean the requested usb type to host mode */ |
789 | 796 | ||
790 | return board_usb_cleanup(dev->seq, priv->init_type); | 797 | return board_usb_cleanup(dev->seq, priv->init_type); |
791 | } | 798 | } |
792 | 799 | ||
793 | static const struct udevice_id mx6_usb_ids[] = { | 800 | static const struct udevice_id mx6_usb_ids[] = { |
794 | { .compatible = "fsl,imx27-usb" }, | 801 | { .compatible = "fsl,imx27-usb" }, |
795 | { } | 802 | { } |
796 | }; | 803 | }; |
797 | 804 | ||
798 | U_BOOT_DRIVER(usb_mx6) = { | 805 | U_BOOT_DRIVER(usb_mx6) = { |
799 | .name = "ehci_mx6", | 806 | .name = "ehci_mx6", |
800 | .id = UCLASS_USB, | 807 | .id = UCLASS_USB, |
801 | .of_match = mx6_usb_ids, | 808 | .of_match = mx6_usb_ids, |
802 | .ofdata_to_platdata = ehci_usb_ofdata_to_platdata, | 809 | .ofdata_to_platdata = ehci_usb_ofdata_to_platdata, |
803 | .probe = ehci_usb_probe, | 810 | .probe = ehci_usb_probe, |
804 | .remove = ehci_usb_remove, | 811 | .remove = ehci_usb_remove, |
805 | .ops = &ehci_usb_ops, | 812 | .ops = &ehci_usb_ops, |
806 | .platdata_auto_alloc_size = sizeof(struct usb_platdata), | 813 | .platdata_auto_alloc_size = sizeof(struct usb_platdata), |
807 | .priv_auto_alloc_size = sizeof(struct ehci_mx6_priv_data), | 814 | .priv_auto_alloc_size = sizeof(struct ehci_mx6_priv_data), |
808 | .flags = DM_FLAG_ALLOC_PRIV_DMA, | 815 | .flags = DM_FLAG_ALLOC_PRIV_DMA, |
809 | }; | 816 | }; |
810 | #endif | 817 | #endif |
811 | 818 |