netwalker_usb.c revision 1.1.10.1 1 /*
2 * Copyright (c) 2010 Genetec Corporation. All rights reserved.
3 * Written by Hiroyuki Bessho for Genetec Corporation.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 *
14 * THIS SOFTWARE IS PROVIDED BY GENETEC CORPORATION ``AS IS'' AND
15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
16 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
17 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GENETEC CORPORATION
18 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
19 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
20 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
21 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
22 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
23 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
24 * POSSIBILITY OF SUCH DAMAGE.
25 *
26 */
27 #include <sys/cdefs.h>
28 __KERNEL_RCSID(0, "$NetBSD: netwalker_usb.c,v 1.1.10.1 2012/04/17 00:06:15 yamt Exp $");
29
30 #include <sys/param.h>
31 #include <sys/systm.h>
32 #include <sys/conf.h>
33 #include <sys/kernel.h>
34 #include <sys/device.h>
35 #include <sys/intr.h>
36 #include <sys/bus.h>
37
38 #include <dev/usb/usb.h>
39 #include <dev/usb/usbdi.h>
40 #include <dev/usb/usbdivar.h>
41 #include <dev/usb/usb_mem.h>
42
43 #include <dev/usb/ehcireg.h>
44 #include <dev/usb/ehcivar.h>
45
46 #include <arm/imx/imx51reg.h>
47 #include <arm/imx/imx51var.h>
48 #include <arm/imx/imxusbreg.h>
49 #include <arm/imx/imxusbvar.h>
50 #include <arm/imx/imx51_iomuxreg.h>
51 #include <arm/imx/imxgpiovar.h>
52 #include "locators.h"
53
54
55 struct netwalker_usbc_softc {
56 struct imxusbc_softc sc_imxusbc;
57 };
58
59
60 static int imxusbc_match(device_t, cfdata_t, void *);
61 static void imxusbc_attach(device_t, device_t, void *);
62 static void netwalker_usb_init(struct imxehci_softc *);
63
64 static void init_otg(struct imxehci_softc *);
65 static void init_h1(struct imxehci_softc *);
66
67 extern const struct iomux_conf iomux_usb1_config[];
68
69 /* attach structures */
70 CFATTACH_DECL_NEW(imxusbc_axi, sizeof(struct netwalker_usbc_softc),
71 imxusbc_match, imxusbc_attach, NULL, NULL);
72
73 static int
74 imxusbc_match(device_t parent, cfdata_t cf, void *aux)
75 {
76 struct axi_attach_args *aa = aux;
77
78 printf("%s\n", __func__);
79
80 if (aa->aa_addr == USBOH3_BASE)
81 return 1;
82 return 0;
83 }
84
85 static void
86 imxusbc_attach(device_t parent, device_t self, void *aux)
87 {
88 struct axi_attach_args *aa = aux;
89 struct imxusbc_softc *sc = device_private(self);
90
91 sc->sc_init_md_hook = netwalker_usb_init;
92 sc->sc_setup_md_hook = NULL;
93
94 imxusbc_attach_common(parent, self, aa->aa_iot);
95
96 }
97
98 static void
99 netwalker_usb_init(struct imxehci_softc *sc)
100 {
101 switch (sc->sc_unit) {
102 case 0: /* OTG controller */
103 init_otg(sc);
104 break;
105 case 1: /* EHCI Host 1 */
106 init_h1(sc);
107 break;
108 default:
109 aprint_error_dev(sc->sc_hsc.sc_dev, "unit %d not supprted\n",
110 sc->sc_unit);
111 }
112 }
113
114 static void
115 init_otg(struct imxehci_softc *sc)
116 {
117 struct imxusbc_softc *usbc = sc->sc_usbc;
118 uint32_t reg;
119
120 sc->sc_iftype = IMXUSBC_IF_UTMI;
121
122 imxehci_reset(sc);
123
124 reg = bus_space_read_4(usbc->sc_iot, usbc->sc_ioh, USBOH3_PHYCTRL0);
125 reg |= PHYCTRL0_OTG_OVER_CUR_DIS;
126 bus_space_write_4(usbc->sc_iot, usbc->sc_ioh, USBOH3_PHYCTRL0, reg);
127
128 reg = bus_space_read_4(usbc->sc_iot, usbc->sc_ioh, USBOH3_USBCTRL);
129 reg &= ~(USBCTRL_OWIR|USBCTRL_OPM);
130 bus_space_write_4(usbc->sc_iot, usbc->sc_ioh, USBOH3_USBCTRL, reg);
131
132 reg = bus_space_read_4(usbc->sc_iot, usbc->sc_ioh, USBOH3_PHYCTRL1);
133 reg = (reg & ~PHYCTRL1_PLLDIVVALUE_MASK) | PHYCTRL1_PLLDIVVALUE_24MHZ;
134 bus_space_write_4(usbc->sc_iot, usbc->sc_ioh, USBOH3_PHYCTRL1, reg);
135 }
136
137
138
139
140 static void
141 init_h1(struct imxehci_softc *sc)
142 {
143 struct imxusbc_softc *usbc = sc->sc_usbc;
144 uint32_t reg;
145
146 /* output HIGH to USBH1_STP */
147 gpio_data_write(GPIO_NO(1, 27), 1);
148 gpio_set_direction(GPIO_NO(1, 27), GPIO_DIR_OUT);
149
150 iomux_mux_config(iomux_usb1_config);
151
152 delay(100 * 1000);
153
154 /* XXX enable USB clock */
155
156 imxehci_reset(sc);
157
158 /* select external clock for Host 1 */
159 reg = bus_space_read_4(usbc->sc_iot, usbc->sc_ioh,
160 USBOH3_USBCTRL1);
161 reg |= USBCTRL1_UH1_EXT_CLK_EN;
162 bus_space_write_4(usbc->sc_iot, usbc->sc_ioh,
163 USBOH3_USBCTRL1, reg);
164
165
166 /* select ULPI interface for Host 1 */
167 sc->sc_iftype = IMXUSBC_IF_ULPI;
168
169 reg = bus_space_read_4(usbc->sc_iot, usbc->sc_ioh,
170 USBOH3_USBCTRL);
171 reg &= ~(USBCTRL_H1PM);
172 reg |= USBCTRL_H1UIE|USBCTRL_H1WIE;
173 bus_space_write_4(usbc->sc_iot, usbc->sc_ioh,
174 USBOH3_USBCTRL, reg);
175
176 iomux_set_function(MUX_PIN(USBH1_STP), IOMUX_CONFIG_ALT0);
177
178
179 /* HUB RESET release */
180 gpio_data_write(GPIO_NO(1, 7), 1);
181 gpio_set_direction(GPIO_NO(1, 7), GPIO_DIR_OUT);
182
183 /* Drive 26M_OSC_EN line high 3_1 */
184 gpio_data_write(GPIO_NO(3, 1), 1);
185 gpio_set_direction(GPIO_NO(3, 1), GPIO_DIR_OUT);
186
187 /* Drive USB_CLK_EN_B line low 2_1 */
188 gpio_data_write(GPIO_NO(2, 1), 0);
189 gpio_set_direction(GPIO_NO(2, 1), GPIO_DIR_IN);
190
191 /* MX51_PIN_EIM_D21 - De-assert USB PHY RESETB */
192 delay(10 * 1000);
193 gpio_data_write(GPIO_NO(2, 5), 1);
194 gpio_set_direction(GPIO_NO(2, 5), GPIO_DIR_OUT);
195 iomux_set_function(MUX_PIN(EIM_D21), IOMUX_CONFIG_ALT1);
196 delay(5 * 1000);
197 }
198
199 /*
200 * IOMUX setting for USB Host1
201 * taken from Linux driver
202 */
203 const struct iomux_conf iomux_usb1_config[] = {
204
205 {
206 /* Initially setup this pin for GPIO, and change to
207 * USBH1_STP later */
208 .pin = MUX_PIN(USBH1_STP),
209 .mux = IOMUX_CONFIG_ALT2,
210 .pad = (PAD_CTL_SRE | PAD_CTL_DSE_HIGH |
211 PAD_CTL_KEEPER | PAD_CTL_HYS)
212 },
213
214 {
215 /* Clock */
216 .pin = MUX_PIN(USBH1_CLK),
217 .mux = IOMUX_CONFIG_ALT0,
218 .pad = (PAD_CTL_SRE | PAD_CTL_DSE_HIGH |
219 PAD_CTL_KEEPER | PAD_CTL_HYS)
220 },
221 {
222 /* DIR */
223 .pin = MUX_PIN(USBH1_DIR),
224 .mux = IOMUX_CONFIG_ALT0,
225 .pad = (PAD_CTL_SRE | PAD_CTL_DSE_HIGH |
226 PAD_CTL_KEEPER | PAD_CTL_HYS)
227 },
228
229 {
230 /* NXT */
231 .pin = MUX_PIN(USBH1_NXT),
232 .mux = IOMUX_CONFIG_ALT0,
233 .pad = (PAD_CTL_SRE | PAD_CTL_DSE_HIGH |
234 PAD_CTL_KEEPER | PAD_CTL_HYS)
235 },
236
237 #define USBH1_DATA_CONFIG(n) \
238 { \
239 /* DATA n */ \
240 .pin = MUX_PIN(USBH1_DATA##n), \
241 .mux = IOMUX_CONFIG_ALT0, \
242 .pad = (PAD_CTL_SRE | PAD_CTL_DSE_HIGH | \
243 PAD_CTL_KEEPER | PAD_CTL_PUS_100K_PU | \
244 PAD_CTL_HYS), \
245 /* XXX: what does 100K_PU with KEEPER ? */ \
246 }
247
248 USBH1_DATA_CONFIG(0),
249 USBH1_DATA_CONFIG(1),
250 USBH1_DATA_CONFIG(2),
251 USBH1_DATA_CONFIG(3),
252 USBH1_DATA_CONFIG(4),
253 USBH1_DATA_CONFIG(5),
254 USBH1_DATA_CONFIG(6),
255 USBH1_DATA_CONFIG(7),
256
257 {
258 /* USB_CLK_EN_B GPIO2[1]*/
259 .pin = MUX_PIN(EIM_D17),
260 .mux = IOMUX_CONFIG_ALT1,
261 .pad = (PAD_CTL_DSE_HIGH | PAD_CTL_PKE | PAD_CTL_SRE),
262 },
263
264 {
265 /* USB PHY RESETB */
266 .pin = MUX_PIN(EIM_D21),
267 .mux = IOMUX_CONFIG_ALT1,
268 .pad = (PAD_CTL_DSE_HIGH | PAD_CTL_KEEPER |
269 PAD_CTL_PUS_100K_PU | PAD_CTL_SRE)
270 },
271 {
272 /* USB HUB RESET */
273 .pin = MUX_PIN(GPIO1_7),
274 .mux = IOMUX_CONFIG_ALT0,
275 .pad = (PAD_CTL_DSE_HIGH | PAD_CTL_SRE),
276 },
277 {
278 /* 26M_OSC pin settings */
279 .pin = MUX_PIN(DI1_PIN12),
280 .mux = IOMUX_CONFIG_ALT4,
281 .pad = (PAD_CTL_DSE_HIGH | PAD_CTL_KEEPER |
282 PAD_CTL_SRE),
283 },
284
285 /* end of table */
286 {.pin = IOMUX_CONF_EOT}
287 };
288