netwalker_usb.c revision 1.5 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.5 2019/07/24 11:20:55 hkenken 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 struct netwalker_usbc_softc {
55 struct imxusbc_softc sc_imxusbc; /* Must be first */
56 };
57
58 static int imxusbc_match(device_t, cfdata_t, void *);
59 static void imxusbc_attach(device_t, device_t, void *);
60 static void netwalker_usb_init(struct imxehci_softc *);
61
62 static void init_otg(struct imxehci_softc *);
63 static void init_h1(struct imxehci_softc *);
64
65 extern const struct iomux_conf iomux_usb1_config[];
66
67 /* attach structures */
68 CFATTACH_DECL_NEW(imxusbc_axi, sizeof(struct netwalker_usbc_softc),
69 imxusbc_match, imxusbc_attach, NULL, NULL);
70
71 static int
72 imxusbc_match(device_t parent, cfdata_t cf, void *aux)
73 {
74 struct axi_attach_args *aa = aux;
75
76 printf("%s\n", __func__);
77
78 if (aa->aa_addr == USBOH3_BASE)
79 return 1;
80 return 0;
81 }
82
83 static void
84 imxusbc_attach(device_t parent, device_t self, void *aux)
85 {
86 struct imxusbc_softc *sc = device_private(self);
87 struct axi_attach_args *aa = aux;
88
89 aprint_normal("\n");
90 aprint_normal(": Universal Serial Bus Controller\n");
91
92 if (aa->aa_size == AXICF_SIZE_DEFAULT)
93 aa->aa_size = USBOH3_SIZE;
94
95 sc->sc_init_md_hook = netwalker_usb_init;
96 sc->sc_intr_establish_md_hook = NULL;
97 sc->sc_setup_md_hook = NULL;
98
99 imxusbc_attach_common(parent, self, aa->aa_iot, aa->aa_addr, aa->aa_size);
100 }
101
102 static void
103 netwalker_usb_init(struct imxehci_softc *sc)
104 {
105 switch (sc->sc_unit) {
106 case 0: /* OTG controller */
107 init_otg(sc);
108 break;
109 case 1: /* EHCI Host 1 */
110 init_h1(sc);
111 break;
112 default:
113 aprint_error_dev(sc->sc_hsc.sc_dev, "unit %d not supported\n",
114 sc->sc_unit);
115 }
116 }
117
118 static void
119 init_otg(struct imxehci_softc *sc)
120 {
121 struct imxusbc_softc *usbc = sc->sc_usbc;
122 uint32_t reg;
123
124 sc->sc_iftype = IMXUSBC_IF_UTMI;
125
126 imxehci_reset(sc);
127
128 reg = bus_space_read_4(usbc->sc_iot, usbc->sc_ioh, USBOH3_PHYCTRL0);
129 reg |= PHYCTRL0_OTG_OVER_CUR_DIS;
130 bus_space_write_4(usbc->sc_iot, usbc->sc_ioh, USBOH3_PHYCTRL0, reg);
131
132 reg = bus_space_read_4(usbc->sc_iot, usbc->sc_ioh, USBOH3_USBCTRL);
133 reg &= ~(USBCTRL_OWIR|USBCTRL_OPM);
134 bus_space_write_4(usbc->sc_iot, usbc->sc_ioh, USBOH3_USBCTRL, reg);
135
136 reg = bus_space_read_4(usbc->sc_iot, usbc->sc_ioh, USBOH3_PHYCTRL1);
137 reg = (reg & ~PHYCTRL1_PLLDIVVALUE_MASK) | PHYCTRL1_PLLDIVVALUE_24MHZ;
138 bus_space_write_4(usbc->sc_iot, usbc->sc_ioh, USBOH3_PHYCTRL1, reg);
139 }
140
141 static void
142 init_h1(struct imxehci_softc *sc)
143 {
144 struct imxusbc_softc *usbc = sc->sc_usbc;
145 uint32_t reg;
146
147 /* output HIGH to USBH1_STP */
148 gpio_data_write(GPIO_NO(1, 27), 1);
149 gpio_set_direction(GPIO_NO(1, 27), GPIO_DIR_OUT);
150
151 iomux_mux_config(iomux_usb1_config);
152
153 delay(100 * 1000);
154
155 /* XXX enable USB clock */
156
157 imxehci_reset(sc);
158
159 /* select external clock for Host 1 */
160 reg = bus_space_read_4(usbc->sc_iot, usbc->sc_ioh,
161 USBOH3_USBCTRL1);
162 reg |= USBCTRL1_UH1_EXT_CLK_EN;
163 bus_space_write_4(usbc->sc_iot, usbc->sc_ioh,
164 USBOH3_USBCTRL1, reg);
165
166
167 /* select ULPI interface for Host 1 */
168 sc->sc_iftype = IMXUSBC_IF_ULPI;
169
170 reg = bus_space_read_4(usbc->sc_iot, usbc->sc_ioh,
171 USBOH3_USBCTRL);
172 reg &= ~(USBCTRL_H1PM);
173 reg |= USBCTRL_H1UIE|USBCTRL_H1WIE;
174 bus_space_write_4(usbc->sc_iot, usbc->sc_ioh,
175 USBOH3_USBCTRL, reg);
176
177 iomux_set_function(MUX_PIN(USBH1_STP), IOMUX_CONFIG_ALT0);
178
179
180 /* HUB RESET release */
181 gpio_data_write(GPIO_NO(1, 7), 1);
182 gpio_set_direction(GPIO_NO(1, 7), GPIO_DIR_OUT);
183
184 /* Drive 26M_OSC_EN line high 3_1 */
185 gpio_data_write(GPIO_NO(3, 1), 1);
186 gpio_set_direction(GPIO_NO(3, 1), GPIO_DIR_OUT);
187
188 /* Drive USB_CLK_EN_B line low 2_1 */
189 gpio_data_write(GPIO_NO(2, 1), 0);
190 gpio_set_direction(GPIO_NO(2, 1), GPIO_DIR_IN);
191
192 /* MX51_PIN_EIM_D21 - De-assert USB PHY RESETB */
193 delay(10 * 1000);
194 gpio_data_write(GPIO_NO(2, 5), 1);
195 gpio_set_direction(GPIO_NO(2, 5), GPIO_DIR_OUT);
196 iomux_set_function(MUX_PIN(EIM_D21), IOMUX_CONFIG_ALT1);
197 delay(5 * 1000);
198 }
199
200 /*
201 * IOMUX setting for USB Host1
202 * taken from Linux driver
203 */
204 const struct iomux_conf iomux_usb1_config[] = {
205
206 {
207 /* Initially setup this pin for GPIO, and change to
208 * USBH1_STP later */
209 .pin = MUX_PIN(USBH1_STP),
210 .mux = IOMUX_CONFIG_ALT2,
211 .pad = (PAD_CTL_SRE | PAD_CTL_DSE_HIGH |
212 PAD_CTL_KEEPER | PAD_CTL_HYS)
213 },
214
215 {
216 /* Clock */
217 .pin = MUX_PIN(USBH1_CLK),
218 .mux = IOMUX_CONFIG_ALT0,
219 .pad = (PAD_CTL_SRE | PAD_CTL_DSE_HIGH |
220 PAD_CTL_KEEPER | PAD_CTL_HYS)
221 },
222 {
223 /* DIR */
224 .pin = MUX_PIN(USBH1_DIR),
225 .mux = IOMUX_CONFIG_ALT0,
226 .pad = (PAD_CTL_SRE | PAD_CTL_DSE_HIGH |
227 PAD_CTL_KEEPER | PAD_CTL_HYS)
228 },
229
230 {
231 /* NXT */
232 .pin = MUX_PIN(USBH1_NXT),
233 .mux = IOMUX_CONFIG_ALT0,
234 .pad = (PAD_CTL_SRE | PAD_CTL_DSE_HIGH |
235 PAD_CTL_KEEPER | PAD_CTL_HYS)
236 },
237
238 #define USBH1_DATA_CONFIG(n) \
239 { \
240 /* DATA n */ \
241 .pin = MUX_PIN(USBH1_DATA##n), \
242 .mux = IOMUX_CONFIG_ALT0, \
243 .pad = (PAD_CTL_SRE | PAD_CTL_DSE_HIGH | \
244 PAD_CTL_KEEPER | PAD_CTL_PUS_100K_PU | \
245 PAD_CTL_HYS), \
246 /* XXX: what does 100K_PU with KEEPER ? */ \
247 }
248
249 USBH1_DATA_CONFIG(0),
250 USBH1_DATA_CONFIG(1),
251 USBH1_DATA_CONFIG(2),
252 USBH1_DATA_CONFIG(3),
253 USBH1_DATA_CONFIG(4),
254 USBH1_DATA_CONFIG(5),
255 USBH1_DATA_CONFIG(6),
256 USBH1_DATA_CONFIG(7),
257
258 {
259 /* USB_CLK_EN_B GPIO2[1]*/
260 .pin = MUX_PIN(EIM_D17),
261 .mux = IOMUX_CONFIG_ALT1,
262 .pad = (PAD_CTL_DSE_HIGH | PAD_CTL_PKE | PAD_CTL_SRE),
263 },
264
265 {
266 /* USB PHY RESETB */
267 .pin = MUX_PIN(EIM_D21),
268 .mux = IOMUX_CONFIG_ALT1,
269 .pad = (PAD_CTL_DSE_HIGH | PAD_CTL_KEEPER |
270 PAD_CTL_PUS_100K_PU | PAD_CTL_SRE)
271 },
272 {
273 /* USB HUB RESET */
274 .pin = MUX_PIN(GPIO1_7),
275 .mux = IOMUX_CONFIG_ALT0,
276 .pad = (PAD_CTL_DSE_HIGH | PAD_CTL_SRE),
277 },
278 {
279 /* 26M_OSC pin settings */
280 .pin = MUX_PIN(DI1_PIN12),
281 .mux = IOMUX_CONFIG_ALT4,
282 .pad = (PAD_CTL_DSE_HIGH | PAD_CTL_KEEPER |
283 PAD_CTL_SRE),
284 },
285
286 /* end of table */
287 {.pin = IOMUX_CONF_EOT}
288 };
289