common: Drop linux/delay.h from common header
[oweals/u-boot.git] / drivers / usb / host / ehci-omap.c
1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3  * (C) Copyright 2011 Ilya Yanok, Emcraft Systems
4  * (C) Copyright 2004-2008
5  * Texas Instruments, <www.ti.com>
6  *
7  * Derived from Beagle Board code by
8  *      Sunil Kumar <sunilsaini05@gmail.com>
9  *      Shashi Ranjan <shashiranjanmca05@gmail.com>
10  *
11  */
12
13 #include <common.h>
14 #include <log.h>
15 #include <usb.h>
16 #include <linux/delay.h>
17 #include <usb/ulpi.h>
18 #include <errno.h>
19 #include <asm/io.h>
20 #include <asm/gpio.h>
21 #include <asm/arch/ehci.h>
22 #include <asm/ehci-omap.h>
23
24 #include "ehci.h"
25
26 static struct omap_uhh *const uhh = (struct omap_uhh *)OMAP_UHH_BASE;
27 static struct omap_usbtll *const usbtll = (struct omap_usbtll *)OMAP_USBTLL_BASE;
28 static struct omap_ehci *const ehci = (struct omap_ehci *)OMAP_EHCI_BASE;
29
30 static int omap_uhh_reset(void)
31 {
32         int timeout = 0;
33         u32 rev;
34
35         rev = readl(&uhh->rev);
36
37         /* Soft RESET */
38         writel(OMAP_UHH_SYSCONFIG_SOFTRESET, &uhh->sysc);
39
40         switch (rev) {
41         case OMAP_USBHS_REV1:
42                 /* Wait for soft RESET to complete */
43                 while (!(readl(&uhh->syss) & 0x1)) {
44                         if (timeout > 100) {
45                                 printf("%s: RESET timeout\n", __func__);
46                                 return -1;
47                         }
48                         udelay(10);
49                         timeout++;
50                 }
51
52                 /* Set No-Idle, No-Standby */
53                 writel(OMAP_UHH_SYSCONFIG_VAL, &uhh->sysc);
54                 break;
55
56         default:        /* Rev. 2 onwards */
57
58                 udelay(2); /* Need to wait before accessing SYSCONFIG back */
59
60                 /* Wait for soft RESET to complete */
61                 while ((readl(&uhh->sysc) & 0x1)) {
62                         if (timeout > 100) {
63                                 printf("%s: RESET timeout\n", __func__);
64                                 return -1;
65                         }
66                         udelay(10);
67                         timeout++;
68                 }
69
70                 writel(OMAP_UHH_SYSCONFIG_VAL, &uhh->sysc);
71                 break;
72         }
73
74         return 0;
75 }
76
77 static int omap_ehci_tll_reset(void)
78 {
79         unsigned long init = get_timer(0);
80
81         /* perform TLL soft reset, and wait until reset is complete */
82         writel(OMAP_USBTLL_SYSCONFIG_SOFTRESET, &usbtll->sysc);
83
84         /* Wait for TLL reset to complete */
85         while (!(readl(&usbtll->syss) & OMAP_USBTLL_SYSSTATUS_RESETDONE))
86                 if (get_timer(init) > CONFIG_SYS_HZ) {
87                         debug("OMAP EHCI error: timeout resetting TLL\n");
88                         return -EL3RST;
89         }
90
91         return 0;
92 }
93
94 static void omap_usbhs_hsic_init(int port)
95 {
96         unsigned int reg;
97
98         /* Enable channels now */
99         reg = readl(&usbtll->channel_conf + port);
100
101         setbits_le32(&reg, (OMAP_TLL_CHANNEL_CONF_CHANMODE_TRANSPARENT_UTMI
102                 | OMAP_TLL_CHANNEL_CONF_ULPINOBITSTUFF
103                 | OMAP_TLL_CHANNEL_CONF_DRVVBUS
104                 | OMAP_TLL_CHANNEL_CONF_CHRGVBUS
105                 | OMAP_TLL_CHANNEL_CONF_CHANEN));
106
107         writel(reg, &usbtll->channel_conf + port);
108 }
109
110 #ifdef CONFIG_USB_ULPI
111 static void omap_ehci_soft_phy_reset(int port)
112 {
113         struct ulpi_viewport ulpi_vp;
114
115         ulpi_vp.viewport_addr = (u32)&ehci->insreg05_utmi_ulpi;
116         ulpi_vp.port_num = port;
117
118         ulpi_reset(&ulpi_vp);
119 }
120 #else
121 static void omap_ehci_soft_phy_reset(int port)
122 {
123         return;
124 }
125 #endif
126
127 #if defined(CONFIG_OMAP_EHCI_PHY1_RESET_GPIO) || \
128         defined(CONFIG_OMAP_EHCI_PHY2_RESET_GPIO) || \
129         defined(CONFIG_OMAP_EHCI_PHY3_RESET_GPIO)
130 /* controls PHY(s) reset signal(s) */
131 static inline void omap_ehci_phy_reset(int on, int delay)
132 {
133         /*
134          * Refer ISSUE1:
135          * Hold the PHY in RESET for enough time till
136          * PHY is settled and ready
137          */
138         if (delay && !on)
139                 udelay(delay);
140 #ifdef CONFIG_OMAP_EHCI_PHY1_RESET_GPIO
141         gpio_request(CONFIG_OMAP_EHCI_PHY1_RESET_GPIO, "USB PHY1 reset");
142         gpio_direction_output(CONFIG_OMAP_EHCI_PHY1_RESET_GPIO, !on);
143 #endif
144 #ifdef CONFIG_OMAP_EHCI_PHY2_RESET_GPIO
145         gpio_request(CONFIG_OMAP_EHCI_PHY2_RESET_GPIO, "USB PHY2 reset");
146         gpio_direction_output(CONFIG_OMAP_EHCI_PHY2_RESET_GPIO, !on);
147 #endif
148 #ifdef CONFIG_OMAP_EHCI_PHY3_RESET_GPIO
149         gpio_request(CONFIG_OMAP_EHCI_PHY3_RESET_GPIO, "USB PHY3 reset");
150         gpio_direction_output(CONFIG_OMAP_EHCI_PHY3_RESET_GPIO, !on);
151 #endif
152
153         /* Hold the PHY in RESET for enough time till DIR is high */
154         /* Refer: ISSUE1 */
155         if (delay && on)
156                 udelay(delay);
157 }
158 #else
159 #define omap_ehci_phy_reset(on, delay)  do {} while (0)
160 #endif
161
162 /* Reset is needed otherwise the kernel-driver will throw an error. */
163 int omap_ehci_hcd_stop(void)
164 {
165         debug("Resetting OMAP EHCI\n");
166         omap_ehci_phy_reset(1, 0);
167
168         if (omap_uhh_reset() < 0)
169                 return -1;
170
171         if (omap_ehci_tll_reset() < 0)
172                 return -1;
173
174         return 0;
175 }
176
177 /*
178  * Initialize the OMAP EHCI controller and PHY.
179  * Based on "drivers/usb/host/ehci-omap.c" from Linux 3.1
180  * See there for additional Copyrights.
181  */
182 int omap_ehci_hcd_init(int index, struct omap_usbhs_board_data *usbhs_pdata,
183                        struct ehci_hccr **hccr, struct ehci_hcor **hcor)
184 {
185         int ret;
186         unsigned int i, reg = 0, rev = 0;
187
188         debug("Initializing OMAP EHCI\n");
189
190         ret = board_usb_init(index, USB_INIT_HOST);
191         if (ret < 0)
192                 return ret;
193
194         /* Put the PHY in RESET */
195         omap_ehci_phy_reset(1, 10);
196
197         ret = omap_uhh_reset();
198         if (ret < 0)
199                 return ret;
200
201         ret = omap_ehci_tll_reset();
202         if (ret)
203                 return ret;
204
205         writel(OMAP_USBTLL_SYSCONFIG_ENAWAKEUP |
206                 OMAP_USBTLL_SYSCONFIG_SIDLEMODE |
207                 OMAP_USBTLL_SYSCONFIG_CACTIVITY, &usbtll->sysc);
208
209         /* Put UHH in NoIdle/NoStandby mode */
210         writel(OMAP_UHH_SYSCONFIG_VAL, &uhh->sysc);
211
212         /* setup ULPI bypass and burst configurations */
213         clrsetbits_le32(&reg, OMAP_UHH_HOSTCONFIG_INCRX_ALIGN_EN,
214                 (OMAP_UHH_HOSTCONFIG_INCR4_BURST_EN |
215                 OMAP_UHH_HOSTCONFIG_INCR8_BURST_EN |
216                 OMAP_UHH_HOSTCONFIG_INCR16_BURST_EN));
217
218         rev = readl(&uhh->rev);
219         if (rev == OMAP_USBHS_REV1) {
220                 if (is_ehci_phy_mode(usbhs_pdata->port_mode[0]))
221                         clrbits_le32(&reg, OMAP_UHH_HOSTCONFIG_ULPI_P1_BYPASS);
222                 else
223                         setbits_le32(&reg, OMAP_UHH_HOSTCONFIG_ULPI_P1_BYPASS);
224
225                 if (is_ehci_phy_mode(usbhs_pdata->port_mode[1]))
226                         clrbits_le32(&reg, OMAP_UHH_HOSTCONFIG_ULPI_P2_BYPASS);
227                 else
228                         setbits_le32(&reg, OMAP_UHH_HOSTCONFIG_ULPI_P2_BYPASS);
229
230                 if (is_ehci_phy_mode(usbhs_pdata->port_mode[2]))
231                         clrbits_le32(&reg, OMAP_UHH_HOSTCONFIG_ULPI_P3_BYPASS);
232                 else
233                         setbits_le32(&reg, OMAP_UHH_HOSTCONFIG_ULPI_P3_BYPASS);
234         } else if (rev == OMAP_USBHS_REV2) {
235
236                 clrsetbits_le32(&reg, (OMAP_P1_MODE_CLEAR | OMAP_P2_MODE_CLEAR),
237                                         OMAP4_UHH_HOSTCONFIG_APP_START_CLK);
238
239                 /* Clear port mode fields for PHY mode */
240
241                 if (is_ehci_hsic_mode(usbhs_pdata->port_mode[0]))
242                         setbits_le32(&reg, OMAP_P1_MODE_HSIC);
243
244                 if (is_ehci_hsic_mode(usbhs_pdata->port_mode[1]))
245                         setbits_le32(&reg, OMAP_P2_MODE_HSIC);
246
247         } else if (rev == OMAP_USBHS_REV2_1) {
248
249                 clrsetbits_le32(&reg,
250                                 (OMAP_P1_MODE_CLEAR |
251                                  OMAP_P2_MODE_CLEAR |
252                                  OMAP_P3_MODE_CLEAR),
253                                 OMAP4_UHH_HOSTCONFIG_APP_START_CLK);
254
255                 /* Clear port mode fields for PHY mode */
256
257                 if (is_ehci_hsic_mode(usbhs_pdata->port_mode[0]))
258                         setbits_le32(&reg, OMAP_P1_MODE_HSIC);
259
260                 if (is_ehci_hsic_mode(usbhs_pdata->port_mode[1]))
261                         setbits_le32(&reg, OMAP_P2_MODE_HSIC);
262
263                 if (is_ehci_hsic_mode(usbhs_pdata->port_mode[2]))
264                         setbits_le32(&reg, OMAP_P3_MODE_HSIC);
265         }
266
267         debug("OMAP UHH_REVISION 0x%x\n", rev);
268         writel(reg, &uhh->hostconfig);
269
270         for (i = 0; i < OMAP_HS_USB_PORTS; i++)
271                 if (is_ehci_hsic_mode(usbhs_pdata->port_mode[i]))
272                         omap_usbhs_hsic_init(i);
273
274         omap_ehci_phy_reset(0, 10);
275
276         /*
277          * An undocumented "feature" in the OMAP3 EHCI controller,
278          * causes suspended ports to be taken out of suspend when
279          * the USBCMD.Run/Stop bit is cleared (for example when
280          * we do ehci_bus_suspend).
281          * This breaks suspend-resume if the root-hub is allowed
282          * to suspend. Writing 1 to this undocumented register bit
283          * disables this feature and restores normal behavior.
284          */
285         writel(EHCI_INSNREG04_DISABLE_UNSUSPEND, &ehci->insreg04);
286
287         for (i = 0; i < OMAP_HS_USB_PORTS; i++)
288                 if (is_ehci_phy_mode(usbhs_pdata->port_mode[i]))
289                         omap_ehci_soft_phy_reset(i);
290
291         *hccr = (struct ehci_hccr *)(OMAP_EHCI_BASE);
292         *hcor = (struct ehci_hcor *)(OMAP_EHCI_BASE + 0x10);
293
294         debug("OMAP EHCI init done\n");
295         return 0;
296 }