u-boot 2011.06: add tftpboot support for pandaboard
[glsdk/meta-ti-glsdk.git] / recipes-bsp / u-boot / u-boot / 2011.06 / 0032-omap4-add-support-for-EHCI.patch
1 From a2536d64065297279726a71e0af04a5f677f675c Mon Sep 17 00:00:00 2001
2 From: Gilles Chanteperdrix <gilles.chanteperdrix@xenomai.org>
3 Date: Mon, 9 May 2011 23:04:50 +0200
4 Subject: [PATCH 32/35] omap4: add support for EHCI
6 As board may need some specific support, implement inner functions
7 to be called by the boards implementaions of ehci_hcd_start,
8 ehci_hcd_stop.
10 Signed-off-by: Gilles Chanteperdrix <gilles.chanteperdrix@xenomai.org>
11 Signed-off-by: Koen Kooi <koen@dominion.thruhere.net>
12 ---
13  arch/arm/include/asm/arch-omap4/ehci.h |    8 +
14  drivers/usb/host/Makefile              |    1 +
15  drivers/usb/host/ehci-omap4.c          |  268 ++++++++++++++++++++++++++++++++
16  3 files changed, 277 insertions(+), 0 deletions(-)
17  create mode 100644 arch/arm/include/asm/arch-omap4/ehci.h
18  create mode 100644 drivers/usb/host/ehci-omap4.c
20 diff --git a/arch/arm/include/asm/arch-omap4/ehci.h b/arch/arm/include/asm/arch-omap4/ehci.h
21 new file mode 100644
22 index 0000000..fc84f6a
23 --- /dev/null
24 +++ b/arch/arm/include/asm/arch-omap4/ehci.h
25 @@ -0,0 +1,8 @@
26 +#ifndef EHCI_H
27 +#define EHCI_H
28 +
29 +int omap4_ehci_hcd_init(void);
30 +
31 +int omap4_ehci_hcd_stop(void);
32 +
33 +#endif /* EHCI_H */
34 diff --git a/drivers/usb/host/Makefile b/drivers/usb/host/Makefile
35 index 51b2494..5a5b971 100644
36 --- a/drivers/usb/host/Makefile
37 +++ b/drivers/usb/host/Makefile
38 @@ -46,6 +46,7 @@ COBJS-$(CONFIG_USB_EHCI_IXP4XX) += ehci-ixp.o
39  COBJS-$(CONFIG_USB_EHCI_KIRKWOOD) += ehci-kirkwood.o
40  COBJS-$(CONFIG_USB_EHCI_PCI) += ehci-pci.o
41  COBJS-$(CONFIG_USB_EHCI_VCT) += ehci-vct.o
42 +COBJS-$(CONFIG_USB_EHCI_OMAP4) += ehci-omap4.o
43  
44  COBJS  := $(COBJS-y)
45  SRCS   := $(COBJS:.o=.c)
46 diff --git a/drivers/usb/host/ehci-omap4.c b/drivers/usb/host/ehci-omap4.c
47 new file mode 100644
48 index 0000000..19cd286
49 --- /dev/null
50 +++ b/drivers/usb/host/ehci-omap4.c
51 @@ -0,0 +1,268 @@
52 +/*
53 + * OMAP4 EHCI port, copied from linux/drivers/usb/host/ehci-omap.c
54 + *
55 + * Copyright (C) 2007-2010 Texas Instruments, Inc.
56 + *     Author: Vikram Pandita <vikram.pandita@ti.com>
57 + *     Author: Anand Gadiyar <gadiyar@ti.com>
58 + */
59 +
60 +#include <common.h>
61 +#include <usb.h>
62 +#include <errno.h>
63 +#include <asm/io.h>
64 +#include <asm/arch/gpio.h>
65 +#include <asm/arch/omap4.h>
66 +#include <asm/arch/sys_proto.h>
67 +
68 +#include "ehci.h"
69 +#include "ehci-core.h"
70 +
71 +#define EHCI_BASE (OMAP44XX_L4_CORE_BASE + 0x64C00)
72 +#define UHH_BASE (OMAP44XX_L4_CORE_BASE + 0x64000)
73 +#define TLL_BASE (OMAP44XX_L4_CORE_BASE + 0x62000)
74 +
75 +/* ULPI */
76 +#define ULPI_SET(a)                            (a + 1)
77 +#define ULPI_CLR(a)                            (a + 2)
78 +
79 +#define ULPI_FUNC_CTRL                         0x04
80 +
81 +#define ULPI_FUNC_CTRL_RESET                   (1 << 5)
82 +
83 +/* TLL Register Set */
84 +#define        OMAP_USBTLL_REVISION                            (0x00)
85 +#define        OMAP_USBTLL_SYSCONFIG                           (0x10)
86 +#define        OMAP_USBTLL_SYSCONFIG_CACTIVITY                 (1 << 8)
87 +#define        OMAP_USBTLL_SYSCONFIG_SIDLEMODE                 (1 << 3)
88 +#define        OMAP_USBTLL_SYSCONFIG_ENAWAKEUP                 (1 << 2)
89 +#define        OMAP_USBTLL_SYSCONFIG_SOFTRESET                 (1 << 1)
90 +#define        OMAP_USBTLL_SYSCONFIG_AUTOIDLE                  (1 << 0)
91 +
92 +#define        OMAP_USBTLL_SYSSTATUS                           (0x14)
93 +#define        OMAP_USBTLL_SYSSTATUS_RESETDONE                 (1 << 0)
94 +
95 +#define        OMAP_USBTLL_IRQSTATUS                           (0x18)
96 +#define        OMAP_USBTLL_IRQENABLE                           (0x1C)
97 +
98 +#define        OMAP_TLL_SHARED_CONF                            (0x30)
99 +#define        OMAP_TLL_SHARED_CONF_USB_90D_DDR_EN             (1 << 6)
100 +#define        OMAP_TLL_SHARED_CONF_USB_180D_SDR_EN            (1 << 5)
101 +#define        OMAP_TLL_SHARED_CONF_USB_DIVRATION              (1 << 2)
102 +#define        OMAP_TLL_SHARED_CONF_FCLK_REQ                   (1 << 1)
103 +#define        OMAP_TLL_SHARED_CONF_FCLK_IS_ON                 (1 << 0)
105 +#define        OMAP_TLL_CHANNEL_CONF(num)                      (0x040 + 0x004 * num)
106 +#define        OMAP_TLL_CHANNEL_CONF_ULPINOBITSTUFF            (1 << 11)
107 +#define        OMAP_TLL_CHANNEL_CONF_ULPI_ULPIAUTOIDLE         (1 << 10)
108 +#define        OMAP_TLL_CHANNEL_CONF_UTMIAUTOIDLE              (1 << 9)
109 +#define        OMAP_TLL_CHANNEL_CONF_ULPIDDRMODE               (1 << 8)
110 +#define        OMAP_TLL_CHANNEL_CONF_CHANEN                    (1 << 0)
112 +#define        OMAP_TLL_ULPI_FUNCTION_CTRL(num)                (0x804 + 0x100 * num)
113 +#define        OMAP_TLL_ULPI_INTERFACE_CTRL(num)               (0x807 + 0x100 * num)
114 +#define        OMAP_TLL_ULPI_OTG_CTRL(num)                     (0x80A + 0x100 * num)
115 +#define        OMAP_TLL_ULPI_INT_EN_RISE(num)                  (0x80D + 0x100 * num)
116 +#define        OMAP_TLL_ULPI_INT_EN_FALL(num)                  (0x810 + 0x100 * num)
117 +#define        OMAP_TLL_ULPI_INT_STATUS(num)                   (0x813 + 0x100 * num)
118 +#define        OMAP_TLL_ULPI_INT_LATCH(num)                    (0x814 + 0x100 * num)
119 +#define        OMAP_TLL_ULPI_DEBUG(num)                        (0x815 + 0x100 * num)
120 +#define        OMAP_TLL_ULPI_SCRATCH_REGISTER(num)             (0x816 + 0x100 * num)
122 +#define OMAP_TLL_CHANNEL_COUNT                         3
123 +#define OMAP_TLL_CHANNEL_1_EN_MASK                     (1 << 1)
124 +#define OMAP_TLL_CHANNEL_2_EN_MASK                     (1 << 2)
125 +#define OMAP_TLL_CHANNEL_3_EN_MASK                     (1 << 4)
127 +/* UHH Register Set */
128 +#define        OMAP_UHH_REVISION                               (0x00)
129 +#define        OMAP_UHH_SYSCONFIG                              (0x10)
130 +#define        OMAP_UHH_SYSCONFIG_MIDLEMODE                    (1 << 12)
131 +#define        OMAP_UHH_SYSCONFIG_CACTIVITY                    (1 << 8)
132 +#define        OMAP_UHH_SYSCONFIG_SIDLEMODE                    (1 << 3)
133 +#define        OMAP_UHH_SYSCONFIG_ENAWAKEUP                    (1 << 2)
134 +#define        OMAP_UHH_SYSCONFIG_SOFTRESET                    (1 << 1)
135 +#define        OMAP_UHH_SYSCONFIG_AUTOIDLE                     (1 << 0)
137 +#define        OMAP_UHH_SYSSTATUS                              (0x14)
138 +#define        OMAP_UHH_HOSTCONFIG                             (0x40)
139 +#define        OMAP_UHH_HOSTCONFIG_ULPI_BYPASS                 (1 << 0)
140 +#define        OMAP_UHH_HOSTCONFIG_ULPI_P1_BYPASS              (1 << 0)
141 +#define        OMAP_UHH_HOSTCONFIG_ULPI_P2_BYPASS              (1 << 11)
142 +#define        OMAP_UHH_HOSTCONFIG_ULPI_P3_BYPASS              (1 << 12)
143 +#define OMAP_UHH_HOSTCONFIG_INCR4_BURST_EN             (1 << 2)
144 +#define OMAP_UHH_HOSTCONFIG_INCR8_BURST_EN             (1 << 3)
145 +#define OMAP_UHH_HOSTCONFIG_INCR16_BURST_EN            (1 << 4)
146 +#define OMAP_UHH_HOSTCONFIG_INCRX_ALIGN_EN             (1 << 5)
147 +#define OMAP_UHH_HOSTCONFIG_P1_CONNECT_STATUS          (1 << 8)
148 +#define OMAP_UHH_HOSTCONFIG_P2_CONNECT_STATUS          (1 << 9)
149 +#define OMAP_UHH_HOSTCONFIG_P3_CONNECT_STATUS          (1 << 10)
151 +/* OMAP4-specific defines */
152 +#define OMAP4_UHH_SYSCONFIG_IDLEMODE_CLEAR             (3 << 2)
153 +#define OMAP4_UHH_SYSCONFIG_NOIDLE                     (1 << 2)
155 +#define OMAP4_UHH_SYSCONFIG_STDBYMODE_CLEAR            (3 << 4)
156 +#define OMAP4_UHH_SYSCONFIG_NOSTDBY                    (1 << 4)
157 +#define OMAP4_UHH_SYSCONFIG_SOFTRESET                  (1 << 0)
159 +#define OMAP4_P1_MODE_CLEAR                            (3 << 16)
160 +#define OMAP4_P1_MODE_TLL                              (1 << 16)
161 +#define OMAP4_P1_MODE_HSIC                             (3 << 16)
162 +#define OMAP4_P2_MODE_CLEAR                            (3 << 18)
163 +#define OMAP4_P2_MODE_TLL                              (1 << 18)
164 +#define OMAP4_P2_MODE_HSIC                             (3 << 18)
166 +#define OMAP_REV2_TLL_CHANNEL_COUNT                    2
168 +#define        OMAP_UHH_DEBUG_CSR                              (0x44)
170 +/* EHCI Register Set */
171 +#define EHCI_INSNREG04                                 (0xA0)
172 +#define EHCI_INSNREG04_DISABLE_UNSUSPEND               (1 << 5)
173 +#define        EHCI_INSNREG05_ULPI                             (0xA4)
174 +#define        EHCI_INSNREG05_ULPI_CONTROL_SHIFT               31
175 +#define        EHCI_INSNREG05_ULPI_PORTSEL_SHIFT               24
176 +#define        EHCI_INSNREG05_ULPI_OPSEL_SHIFT                 22
177 +#define        EHCI_INSNREG05_ULPI_REGADD_SHIFT                16
178 +#define        EHCI_INSNREG05_ULPI_EXTREGADD_SHIFT             8
179 +#define        EHCI_INSNREG05_ULPI_WRDATA_SHIFT                0
181 +int omap4_ehci_hcd_init(void)
182 +{
183 +       unsigned long base = get_timer(0);
184 +       unsigned reg = 0, port = 0;
185 +       int rc;
187 +       /* USB host, with clock from external phy as port 1 UTMI clock */
188 +       sr32((void *)0x4A009358, 0, 32, 0x01000002);
190 +       /* FSUSB clk */
191 +       sr32((void *)0x4a0093d0, 0, 32, 0x2);
193 +       /* USB TLL clock */
194 +       sr32((void *)0x4a009368, 0, 32, 0x1);
196 +       /* enable the 32K, 48M optional clocks and enable the module */
197 +       sr32((void *)0x4a0093e0, 0, 32, 0x301);
199 +       /* perform TLL soft reset, and wait until reset is complete */
200 +       writel(OMAP_USBTLL_SYSCONFIG_SOFTRESET,
201 +              TLL_BASE + OMAP_USBTLL_SYSCONFIG);
203 +       /* Wait for TLL reset to complete */
204 +       while (!(readl(TLL_BASE + OMAP_USBTLL_SYSSTATUS)
205 +                & OMAP_USBTLL_SYSSTATUS_RESETDONE))
206 +               if (get_timer(base) > CONFIG_SYS_HZ) {
207 +                       printf("OMAP4 EHCI error: timeout resetting TLL\n");
208 +                       return -1;
209 +               }
211 +       writel(OMAP_USBTLL_SYSCONFIG_ENAWAKEUP |
212 +              OMAP_USBTLL_SYSCONFIG_SIDLEMODE |
213 +              OMAP_USBTLL_SYSCONFIG_CACTIVITY,
214 +              TLL_BASE + OMAP_USBTLL_SYSCONFIG);
216 +       /* Put UHH in NoIdle/NoStandby mode */
217 +       reg = readl(UHH_BASE + OMAP_UHH_SYSCONFIG);
218 +       reg &= ~OMAP4_UHH_SYSCONFIG_IDLEMODE_CLEAR;
219 +       reg |= OMAP4_UHH_SYSCONFIG_NOIDLE;
220 +       reg &= ~OMAP4_UHH_SYSCONFIG_STDBYMODE_CLEAR;
221 +       reg |= OMAP4_UHH_SYSCONFIG_NOSTDBY;
222 +       writel(reg, UHH_BASE + OMAP_UHH_SYSCONFIG);
224 +       reg = readl(UHH_BASE + OMAP_UHH_HOSTCONFIG);
226 +       /* setup ULPI bypass and burst configurations */
227 +       reg |= (OMAP_UHH_HOSTCONFIG_INCR4_BURST_EN
228 +                       | OMAP_UHH_HOSTCONFIG_INCR8_BURST_EN
229 +                       | OMAP_UHH_HOSTCONFIG_INCR16_BURST_EN);
230 +       reg &= ~OMAP_UHH_HOSTCONFIG_INCRX_ALIGN_EN;
232 +       /* Clear port mode fields for PHY mode*/
233 +       reg &= ~OMAP4_P1_MODE_CLEAR;
234 +       reg &= ~OMAP4_P2_MODE_CLEAR;
235 +       writel(reg, UHH_BASE + OMAP_UHH_HOSTCONFIG);
237 +       /*
238 +        * An undocumented "feature" in the OMAP3 EHCI controller,
239 +        * causes suspended ports to be taken out of suspend when
240 +        * the USBCMD.Run/Stop bit is cleared (for example when
241 +        * we do ehci_bus_suspend).
242 +        * This breaks suspend-resume if the root-hub is allowed
243 +        * to suspend. Writing 1 to this undocumented register bit
244 +        * disables this feature and restores normal behavior.
245 +        */
246 +       writel(EHCI_INSNREG04_DISABLE_UNSUSPEND, EHCI_BASE + EHCI_INSNREG04);
248 +       reg = ULPI_FUNC_CTRL_RESET
249 +               /* FUNCTION_CTRL_SET register */
250 +               | (ULPI_SET(ULPI_FUNC_CTRL) << EHCI_INSNREG05_ULPI_REGADD_SHIFT)
251 +               /* Write */
252 +               | (2 << EHCI_INSNREG05_ULPI_OPSEL_SHIFT)
253 +               /* PORTn */
254 +               | ((port + 1) << EHCI_INSNREG05_ULPI_PORTSEL_SHIFT)
255 +               /* start ULPI access*/
256 +               | (1 << EHCI_INSNREG05_ULPI_CONTROL_SHIFT);
258 +       base = get_timer(0);
260 +       writel(reg, EHCI_BASE + EHCI_INSNREG05_ULPI);
262 +       /* Wait for ULPI access completion */
263 +       while ((readl(EHCI_BASE + EHCI_INSNREG05_ULPI)
264 +               & (1 << EHCI_INSNREG05_ULPI_CONTROL_SHIFT)))
265 +               if (get_timer(base) > CONFIG_SYS_HZ) {
266 +                       printf("OMAP4 EHCI error: timeout resetting phy\n");
267 +                       return -1;
268 +               }
270 +       hccr = (struct ehci_hccr *)(EHCI_BASE);
271 +       hcor = (struct ehci_hcor *)((uint32_t) hccr
272 +                       + HC_LENGTH(ehci_readl(&hccr->cr_capbase)));
273 +       return 0;
274 +}
276 +int omap4_ehci_hcd_stop(void)
277 +{
278 +       unsigned base = get_timer(0);
280 +       writel(OMAP4_UHH_SYSCONFIG_SOFTRESET, UHH_BASE + OMAP_UHH_SYSCONFIG);
282 +#if 0
283 +       /* We get timeout here */
284 +       while (!(readl(UHH_BASE + OMAP_UHH_SYSSTATUS) & (1 << 0)))
285 +               if (get_timer(base) > CONFIG_SYS_HZ) {
286 +                       printf("OMAP4 EHCI error: reset UHH 0 timeout\n");
287 +                       return -ETIMEDOUT;
288 +               }
290 +       while (!(readl(UHH_BASE + OMAP_UHH_SYSSTATUS) & (1 << 1)))
291 +               if (get_timer(base) > CONFIG_SYS_HZ) {
292 +                       printf("OMAP4 EHCI error: reset UHH 1 timeout\n");
293 +                       return -ETIMEDOUT;
294 +               }
296 +       while (!(readl(UHH_BASE + OMAP_UHH_SYSSTATUS) & (1 << 2)))
297 +               if (get_timer(base) > CONFIG_SYS_HZ) {
298 +                       printf("OMAP4 EHCI error: reset UHH 2 timeout\n");
299 +                       return -ETIMEDOUT;
300 +               }
301 +#endif
304 +       writel((1 << 1), TLL_BASE + OMAP_USBTLL_SYSCONFIG);
306 +       while (!(readl(TLL_BASE + OMAP_USBTLL_SYSSTATUS) & (1 << 0)))
307 +               if (get_timer(base) > CONFIG_SYS_HZ) {
308 +                       printf("OMAP4 EHCI error: reset TLL timeout\n");
309 +                       return -ETIMEDOUT;
310 +               }
312 +       /* Disable clocks */
313 +       sr32((void *)0x4a0093e0, 0, 32, 0);
314 +       sr32((void *)0x4a009368, 0, 32, 0);
315 +       sr32((void *)0x4a0093d0, 0, 32, 0);
316 +       sr32((void *)0x4A009358, 0, 32, 0);
318 +       return 0;
319 +}
320 -- 
321 1.6.6.1