Tue Jun 18 15:23:18 2013 UTC ()
Add OMAP4 support.  (Incomplete).


(matt)
diff -r1.8 -r1.9 src/sys/arch/arm/omap/omap3_ehci.c

cvs diff -r1.8 -r1.9 src/sys/arch/arm/omap/Attic/omap3_ehci.c (expand / switch to unified diff)

--- src/sys/arch/arm/omap/Attic/omap3_ehci.c 2013/06/16 17:47:54 1.8
+++ src/sys/arch/arm/omap/Attic/omap3_ehci.c 2013/06/18 15:23:18 1.9
@@ -1,14 +1,14 @@ @@ -1,14 +1,14 @@
1/* $NetBSD: omap3_ehci.c,v 1.8 2013/06/16 17:47:54 matt Exp $ */ 1/* $NetBSD: omap3_ehci.c,v 1.9 2013/06/18 15:23:18 matt Exp $ */
2 2
3/*- 3/*-
4 * Copyright (c) 2010-2012 Jared D. McNeill <jmcneill@invisible.ca> 4 * Copyright (c) 2010-2012 Jared D. McNeill <jmcneill@invisible.ca>
5 * All rights reserved. 5 * All rights reserved.
6 * 6 *
7 * Redistribution and use in source and binary forms, with or without 7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions 8 * modification, are permitted provided that the following conditions
9 * are met: 9 * are met:
10 * 1. Redistributions of source code must retain the above copyright 10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer. 11 * notice, this list of conditions and the following disclaimer.
12 * 2. The name of the author may not be used to endorse or promote products 12 * 2. The name of the author may not be used to endorse or promote products
13 * derived from this software without specific prior written permission. 13 * derived from this software without specific prior written permission.
14 * 14 *
@@ -16,27 +16,27 @@ @@ -16,27 +16,27 @@
16 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 16 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
17 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 17 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
18 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 18 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
19 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 19 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
20 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 20 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
21 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 21 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
22 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 22 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
23 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25 * SUCH DAMAGE. 25 * SUCH DAMAGE.
26 */ 26 */
27 27
28#include <sys/cdefs.h> 28#include <sys/cdefs.h>
29__KERNEL_RCSID(0, "$NetBSD: omap3_ehci.c,v 1.8 2013/06/16 17:47:54 matt Exp $"); 29__KERNEL_RCSID(0, "$NetBSD: omap3_ehci.c,v 1.9 2013/06/18 15:23:18 matt Exp $");
30 30
31#include "locators.h" 31#include "locators.h"
32 32
33#include "opt_omap.h" 33#include "opt_omap.h"
34 34
35#include <sys/param.h> 35#include <sys/param.h>
36#include <sys/systm.h> 36#include <sys/systm.h>
37#include <sys/kernel.h> 37#include <sys/kernel.h>
38#include <sys/device.h> 38#include <sys/device.h>
39#include <sys/bus.h> 39#include <sys/bus.h>
40#include <sys/gpio.h> 40#include <sys/gpio.h>
41 41
42#include <machine/intr.h> 42#include <machine/intr.h>
@@ -98,61 +98,73 @@ __KERNEL_RCSID(0, "$NetBSD: omap3_ehci.c @@ -98,61 +98,73 @@ __KERNEL_RCSID(0, "$NetBSD: omap3_ehci.c
98/* USBHOST_CM registers */ 98/* USBHOST_CM registers */
99#define CM_FCLKEN_USBHOST 0x00 99#define CM_FCLKEN_USBHOST 0x00
100#define EN_USBHOST1 1 /* USB HOST 48 MHz clock enable */ 100#define EN_USBHOST1 1 /* USB HOST 48 MHz clock enable */
101#define EN_USBHOST2 2 /* USB HOST 120 MHz clock enable */ 101#define EN_USBHOST2 2 /* USB HOST 120 MHz clock enable */
102#define CM_ICLKEN_USBHOST 0x10 102#define CM_ICLKEN_USBHOST 0x10
103#define EN_USBHOST 1 /* USB HOST clock enable */ 103#define EN_USBHOST 1 /* USB HOST clock enable */
104#define CM_IDLEST_USBHOST 0x20 104#define CM_IDLEST_USBHOST 0x20
105#define CM_AUTOIDLE_USBHOST 0x30 105#define CM_AUTOIDLE_USBHOST 0x30
106#define CM_SLEEPDEP_USBHOST 0x44 106#define CM_SLEEPDEP_USBHOST 0x44
107#define CM_CLKSTCTRL_USBHOST 0x48 107#define CM_CLKSTCTRL_USBHOST 0x48
108#define CM_CLKSTST_USBHOST 0x4c 108#define CM_CLKSTST_USBHOST 0x4c
109 109
110/* USBTLL module */ 110/* USBTLL module */
 111#ifdef OMAP_3XXX
111#define USBTLL_BASE 0x48062000 112#define USBTLL_BASE 0x48062000
 113#elif defined(OMAP4)
 114#define USBTLL_BASE 0x4a062000
 115#endif
112#define USBTLL_SIZE 0x1000 116#define USBTLL_SIZE 0x1000
113 117
114/* HS USB HOST module */ 118/* HS USB HOST module */
 119#ifdef OMAP_3XXX
115#define UHH_BASE 0x48064000 120#define UHH_BASE 0x48064000
 121#elif defined(OMAP4)
 122#define UHH_BASE 0x4a064000
 123#endif
116#define UHH_SIZE 0x1000 124#define UHH_SIZE 0x1000
117 125
118enum omap3_ehci_port_mode { 126enum omap3_ehci_port_mode {
119 OMAP3_EHCI_PORT_MODE_NONE, 127 OMAP3_EHCI_PORT_MODE_NONE,
120 OMAP3_EHCI_PORT_MODE_PHY, 128 OMAP3_EHCI_PORT_MODE_PHY,
121 OMAP3_EHCI_PORT_MODE_TLL, 129 OMAP3_EHCI_PORT_MODE_TLL,
122}; 130};
123 131
124struct omap3_ehci_softc { 132struct omap3_ehci_softc {
125 ehci_softc_t sc; 133 ehci_softc_t sc;
126 void *sc_ih; 134 void *sc_ih;
127 135
128 bus_space_handle_t sc_ioh_usbtll; 136 bus_space_handle_t sc_ioh_usbtll;
129 bus_size_t sc_usbtll_size; 137 bus_size_t sc_usbtll_size;
130 138
131 bus_space_handle_t sc_ioh_uhh; 139 bus_space_handle_t sc_ioh_uhh;
132 bus_size_t sc_uhh_size; 140 bus_size_t sc_uhh_size;
133 141
 142 uint16_t sc_nports;
134 bool sc_phy_reset; 143 bool sc_phy_reset;
135 struct { 144 struct {
136 enum omap3_ehci_port_mode mode; 145 enum omap3_ehci_port_mode mode;
137 int gpio; 146 int gpio;
 147 bool value;
138 } sc_portconfig[3]; 148 } sc_portconfig[3];
139 struct { 149 struct {
140 uint16_t m, n, m2; 150 uint16_t m, n, m2;
141 } sc_dpll5; 151 } sc_dpll5;
142}; 152};
143 153
144static void dpll5_init(struct omap3_ehci_softc *); 154#ifdef OMAP_3XXX
145static void usbhost_init(struct omap3_ehci_softc *, int); 155static void omap3_dpll5_init(struct omap3_ehci_softc *);
 156static void omap3_usbhost_init(struct omap3_ehci_softc *, int);
 157#endif
146static void usbtll_reset(struct omap3_ehci_softc *); 158static void usbtll_reset(struct omap3_ehci_softc *);
147static void usbtll_power(struct omap3_ehci_softc *, bool); 159static void usbtll_power(struct omap3_ehci_softc *, bool);
148static void usbtll_init(struct omap3_ehci_softc *, int); 160static void usbtll_init(struct omap3_ehci_softc *, int);
149static void uhh_power(struct omap3_ehci_softc *, bool); 161static void uhh_power(struct omap3_ehci_softc *, bool);
150static void uhh_portconfig(struct omap3_ehci_softc *); 162static void uhh_portconfig(struct omap3_ehci_softc *);
151 163
152#define USBTLL_READ4(sc, reg) bus_space_read_4((sc)->sc.iot, (sc)->sc_ioh_usbtll, (reg)) 164#define USBTLL_READ4(sc, reg) bus_space_read_4((sc)->sc.iot, (sc)->sc_ioh_usbtll, (reg))
153#define USBTLL_WRITE4(sc, reg, v) bus_space_write_4((sc)->sc.iot, (sc)->sc_ioh_usbtll, (reg), (v)) 165#define USBTLL_WRITE4(sc, reg, v) bus_space_write_4((sc)->sc.iot, (sc)->sc_ioh_usbtll, (reg), (v))
154#define UHH_READ4(sc, reg) bus_space_read_4((sc)->sc.iot, (sc)->sc_ioh_uhh, (reg)) 166#define UHH_READ4(sc, reg) bus_space_read_4((sc)->sc.iot, (sc)->sc_ioh_uhh, (reg))
155#define UHH_WRITE4(sc, reg, v) bus_space_write_4((sc)->sc.iot, (sc)->sc_ioh_uhh, (reg), (v)) 167#define UHH_WRITE4(sc, reg, v) bus_space_write_4((sc)->sc.iot, (sc)->sc_ioh_uhh, (reg), (v))
156 168
157/* Table 23-55 "EHCI Registers Mapping Summary" */ 169/* Table 23-55 "EHCI Registers Mapping Summary" */
158#define EHCI_INSNREG00 0x90 170#define EHCI_INSNREG00 0x90
@@ -198,158 +210,175 @@ omap3_ehci_phy_reset(struct omap3_ehci_s @@ -198,158 +210,175 @@ omap3_ehci_phy_reset(struct omap3_ehci_s
198 210
199static void 211static void
200omap3_ehci_find_companions(struct omap3_ehci_softc *sc) 212omap3_ehci_find_companions(struct omap3_ehci_softc *sc)
201{ 213{
202 device_t dv; 214 device_t dv;
203 deviter_t di; 215 deviter_t di;
204 216
205 sc->sc.sc_ncomp = 0; 217 sc->sc.sc_ncomp = 0;
206 for (dv = deviter_first(&di, DEVITER_F_ROOT_FIRST); 218 for (dv = deviter_first(&di, DEVITER_F_ROOT_FIRST);
207 dv != NULL; 219 dv != NULL;
208 dv = deviter_next(&di)) { 220 dv = deviter_next(&di)) {
209 if (device_is_a(dv, "ohci") && 221 if (device_is_a(dv, "ohci") &&
210 device_parent(dv) == device_parent(sc->sc.sc_dev)) { 222 device_parent(dv) == device_parent(sc->sc.sc_dev)) {
211 printf(" adding companion '%s'\n", device_xname(dv)); 223#ifdef OMAP3_EHCI_DEBUG
 224 aprint_normal(" adding companion '%s'\n", device_xname(dv));
 225#endif
212 sc->sc.sc_comps[sc->sc.sc_ncomp++] = dv; 226 sc->sc.sc_comps[sc->sc.sc_ncomp++] = dv;
213 } 227 }
214 } 228 }
215 deviter_release(&di); 229 deviter_release(&di);
216} 230}
217 231
218static void 232static void
219omap3_ehci_attach1(device_t self) 233omap3_ehci_attach1(device_t self)
220{ 234{
221 struct omap3_ehci_softc *sc = device_private(self); 235 struct omap3_ehci_softc *sc = device_private(self);
222 usbd_status err; 236 usbd_status err;
223 int i; 
224 237
225 for (i = 0; sc->sc_phy_reset && i < 3; i++) { 238 for (u_int i = 0; sc->sc_phy_reset && i < sc->sc_nports; i++) {
226 if (sc->sc_portconfig[i].gpio != -1) { 239 if (sc->sc_portconfig[i].gpio != -1) {
227 if (!omap2_gpio_has_pin(sc->sc_portconfig[i].gpio)) { 240 if (!omap2_gpio_has_pin(sc->sc_portconfig[i].gpio)) {
228 aprint_error_dev(self, "WARNING: " 241 aprint_error_dev(self, "WARNING: "
229 "gpio pin %d not available\n", 242 "gpio pin %d not available\n",
230 sc->sc_portconfig[i].gpio); 243 sc->sc_portconfig[i].gpio);
231 continue; 244 continue;
232 } 245 }
233 omap2_gpio_ctl(sc->sc_portconfig[i].gpio, GPIO_PIN_OUTPUT); 246 omap2_gpio_ctl(sc->sc_portconfig[i].gpio, GPIO_PIN_OUTPUT);
234 omap2_gpio_write(sc->sc_portconfig[i].gpio, 0); 247 omap2_gpio_write(sc->sc_portconfig[i].gpio,
 248 !sc->sc_portconfig[i].value); // off
235 delay(10); 249 delay(10);
236 } 250 }
237 } 251 }
238 252
239 usbtll_power(sc, true); 253 usbtll_power(sc, true);
240 usbtll_init(sc, 3); 254 usbtll_init(sc, 3);
241 255
242 uhh_power(sc, true); 256 uhh_power(sc, true);
243 uhh_portconfig(sc); 257 uhh_portconfig(sc);
244 258
245 for (i = 0; i < 3; i++) { 259 for (u_int i = 0; i < sc->sc_nports; i++) {
246 if (sc->sc_portconfig[i].mode == OMAP3_EHCI_PORT_MODE_PHY) { 260 if (sc->sc_portconfig[i].mode == OMAP3_EHCI_PORT_MODE_PHY) {
247 omap3_ehci_phy_reset(sc, i); 261 omap3_ehci_phy_reset(sc, i);
248 } 262 }
249 } 263 }
250 264
251 delay(10); 265 delay(10);
252 266
253 for (i = 0; sc->sc_phy_reset && i < 3; i++) { 267 for (u_int i = 0; sc->sc_phy_reset && i < sc->sc_nports; i++) {
254 if (sc->sc_portconfig[i].gpio != -1) { 268 if (sc->sc_portconfig[i].gpio != -1) {
255 if (!omap2_gpio_has_pin(sc->sc_portconfig[i].gpio)) 269 if (!omap2_gpio_has_pin(sc->sc_portconfig[i].gpio))
256 continue; 270 continue;
257 omap2_gpio_ctl(sc->sc_portconfig[i].gpio, GPIO_PIN_OUTPUT); 271 omap2_gpio_ctl(sc->sc_portconfig[i].gpio, GPIO_PIN_OUTPUT);
258 omap2_gpio_write(sc->sc_portconfig[i].gpio, 1); 272 omap2_gpio_write(sc->sc_portconfig[i].gpio,
 273 sc->sc_portconfig[i].value);
259 delay(10); 274 delay(10);
260 } 275 }
261 } 276 }
262 277
263 omap3_ehci_find_companions(sc); 278 omap3_ehci_find_companions(sc);
264 279
265 err = ehci_init(&sc->sc); 280 err = ehci_init(&sc->sc);
266 if (err != USBD_NORMAL_COMPLETION) { 281 if (err != USBD_NORMAL_COMPLETION) {
267 aprint_error_dev(self, "init failed, error = %d\n", err); 282 aprint_error_dev(self, "init failed, error = %d\n", err);
268 return; 283 return;
269 } 284 }
270 285
271 sc->sc.sc_child = config_found(self, &sc->sc.sc_bus, usbctlprint); 286 sc->sc.sc_child = config_found(self, &sc->sc.sc_bus, usbctlprint);
272} 287}
273 288
274static int 289static int
275omap3_ehci_match(device_t parent, cfdata_t match, void *opaque) 290omap3_ehci_match(device_t parent, cfdata_t match, void *opaque)
276{ 291{
277#ifdef OMAP3 292#ifdef OMAP3
278 struct obio_attach_args *obio = opaque; 293 struct obio_attach_args *obio = opaque;
279#endif 294#endif
280 295
281#if defined(OMAP3) && !defined(OMAP4) 296#ifdef OMAP_3XXX
282 if (obio->obio_addr == EHCI1_BASE_OMAP3) 297 if (obio->obio_addr == EHCI1_BASE_OMAP3)
283 return 1; 298 return 1;
284#endif 299#endif
285#ifdef OMAP4 300#ifdef OMAP4
286 if (obio->obio_addr == EHCI1_BASE_OMAP4) 301 if (obio->obio_addr == EHCI1_BASE_OMAP4)
287 return 1; 302 return 1;
288#endif 303#endif
289 304
290 return 0; 305 return 0;
291} 306}
292 307
293static enum omap3_ehci_port_mode 308static enum omap3_ehci_port_mode
294omap3_ehci_get_port_mode(prop_dictionary_t prop, const char *key) 309omap3_ehci_get_port_mode(prop_dictionary_t prop, const char *key)
295{ 310{
296 const char *s = NULL; 311 const char *s = NULL;
297 enum omap3_ehci_port_mode mode = OMAP3_EHCI_PORT_MODE_NONE; 312 enum omap3_ehci_port_mode mode = OMAP3_EHCI_PORT_MODE_NONE;
298 313
299 if (prop_dictionary_get_cstring_nocopy(prop, key, &s) && s != NULL) { 314 if (prop_dictionary_get_cstring_nocopy(prop, key, &s) && s != NULL) {
300 if (strcmp(s, "phy") == 0) { 315 if (strcmp(s, "phy") == 0) {
301 mode = OMAP3_EHCI_PORT_MODE_PHY; 316 mode = OMAP3_EHCI_PORT_MODE_PHY;
 317#ifdef OMAP_3XXX
302 } else if (strcmp(s, "tll") == 0) { 318 } else if (strcmp(s, "tll") == 0) {
303 mode = OMAP3_EHCI_PORT_MODE_TLL; 319 mode = OMAP3_EHCI_PORT_MODE_TLL;
 320#endif
304 } 321 }
305 } 322 }
306 323
307 return mode; 324 return mode;
308} 325}
309 326
310static int 327static int
311omap3_ehci_get_port_gpio(prop_dictionary_t prop, const char *key) 328omap3_ehci_get_port_gpio(prop_dictionary_t prop, const char *key)
312{ 329{
313 int16_t gpio; 330 int16_t gpio;
314 331
315 if (prop_dictionary_get_int16(prop, key, &gpio) == false) 332 if (prop_dictionary_get_int16(prop, key, &gpio) == false)
316 gpio = -1; 333 gpio = -1;
317 334
318 return gpio; 335 return gpio;
319} 336}
320 337
321static void 338static void
322omap3_ehci_parse_properties(struct omap3_ehci_softc *sc, prop_dictionary_t prop) 339omap3_ehci_parse_properties(struct omap3_ehci_softc *sc, prop_dictionary_t prop)
323{ 340{
 341 prop_dictionary_get_uint16(prop, "nports", &sc->sc_nports);
324 prop_dictionary_get_bool(prop, "phy-reset", &sc->sc_phy_reset); 342 prop_dictionary_get_bool(prop, "phy-reset", &sc->sc_phy_reset);
325 sc->sc_portconfig[0].mode = omap3_ehci_get_port_mode(prop, "port0-mode"); 343 sc->sc_portconfig[0].mode = omap3_ehci_get_port_mode(prop, "port0-mode");
326 sc->sc_portconfig[0].gpio = omap3_ehci_get_port_gpio(prop, "port0-gpio"); 344 sc->sc_portconfig[0].gpio = omap3_ehci_get_port_gpio(prop, "port0-gpio");
327 sc->sc_portconfig[1].mode = omap3_ehci_get_port_mode(prop, "port1-mode"); 345 prop_dictionary_get_bool(prop, "port0-gpioval", &sc->sc_portconfig[0].value);
328 sc->sc_portconfig[1].gpio = omap3_ehci_get_port_gpio(prop, "port1-gpio"); 346 if (sc->sc_nports > 1) {
329 sc->sc_portconfig[2].mode = omap3_ehci_get_port_mode(prop, "port2-mode"); 347 sc->sc_portconfig[1].mode = omap3_ehci_get_port_mode(prop, "port1-mode");
330 sc->sc_portconfig[2].gpio = omap3_ehci_get_port_gpio(prop, "port2-gpio"); 348 sc->sc_portconfig[1].gpio = omap3_ehci_get_port_gpio(prop, "port1-gpio");
 349 prop_dictionary_get_bool(prop, "port1-gpioval", &sc->sc_portconfig[1].value);
 350 }
 351 if (sc->sc_nports > 2) {
 352 sc->sc_portconfig[2].mode = omap3_ehci_get_port_mode(prop, "port2-mode");
 353 sc->sc_portconfig[2].gpio = omap3_ehci_get_port_gpio(prop, "port2-gpio");
 354 prop_dictionary_get_bool(prop, "port2-gpioval", &sc->sc_portconfig[2].value);
 355 }
331 356
 357#ifdef OMAP_3XXX
332 prop_dictionary_get_uint16(prop, "dpll5-m", &sc->sc_dpll5.m); 358 prop_dictionary_get_uint16(prop, "dpll5-m", &sc->sc_dpll5.m);
333 prop_dictionary_get_uint16(prop, "dpll5-n", &sc->sc_dpll5.n); 359 prop_dictionary_get_uint16(prop, "dpll5-n", &sc->sc_dpll5.n);
334 prop_dictionary_get_uint16(prop, "dpll5-m2", &sc->sc_dpll5.m2); 360 prop_dictionary_get_uint16(prop, "dpll5-m2", &sc->sc_dpll5.m2);
 361#endif
335 362
336#ifdef OMAP3_EHCI_DEBUG 363#ifdef OMAP3_EHCI_DEBUG
337 printf(" GPIO PHY reset: %d\n", sc->sc_phy_reset); 364 printf(" GPIO PHY reset: %d\n", sc->sc_phy_reset);
338 printf(" Port #0: mode %d, gpio %d\n", sc->sc_portconfig[0].mode, sc->sc_portconfig[0].gpio); 365 printf(" Port #0: mode %d, gpio %d\n", sc->sc_portconfig[0].mode, sc->sc_portconfig[0].gpio);
339 printf(" Port #1: mode %d, gpio %d\n", sc->sc_portconfig[1].mode, sc->sc_portconfig[1].gpio); 366 printf(" Port #1: mode %d, gpio %d\n", sc->sc_portconfig[1].mode, sc->sc_portconfig[1].gpio);
340 printf(" Port #2: mode %d, gpio %d\n", sc->sc_portconfig[2].mode, sc->sc_portconfig[2].gpio); 367 printf(" Port #2: mode %d, gpio %d\n", sc->sc_portconfig[2].mode, sc->sc_portconfig[2].gpio);
 368#ifdef OMAP_3XXX
341 printf(" DPLL5: m=%d n=%d m2=%d\n", sc->sc_dpll5.m, sc->sc_dpll5.n, sc->sc_dpll5.m2); 369 printf(" DPLL5: m=%d n=%d m2=%d\n", sc->sc_dpll5.m, sc->sc_dpll5.n, sc->sc_dpll5.m2);
342#endif 370#endif
 371#endif
343} 372}
344 373
345static void 374static void
346omap3_ehci_attach(device_t parent, device_t self, void *opaque) 375omap3_ehci_attach(device_t parent, device_t self, void *opaque)
347{ 376{
348 struct omap3_ehci_softc *sc = device_private(self); 377 struct omap3_ehci_softc *sc = device_private(self);
349 struct obio_attach_args *obio = opaque; 378 struct obio_attach_args *obio = opaque;
350 int rv; 379 int rv;
351 380
352 sc->sc.sc_dev = self; 381 sc->sc.sc_dev = self;
353 sc->sc.sc_bus.hci_private = sc; 382 sc->sc.sc_bus.hci_private = sc;
354 383
355 aprint_naive("\n"); 384 aprint_naive("\n");
@@ -371,29 +400,31 @@ omap3_ehci_attach(device_t parent, devic @@ -371,29 +400,31 @@ omap3_ehci_attach(device_t parent, devic
371 } 400 }
372 sc->sc_usbtll_size = USBTLL_SIZE; 401 sc->sc_usbtll_size = USBTLL_SIZE;
373 rv = bus_space_map(obio->obio_iot, UHH_BASE, UHH_SIZE, 0, &sc->sc_ioh_uhh); 402 rv = bus_space_map(obio->obio_iot, UHH_BASE, UHH_SIZE, 0, &sc->sc_ioh_uhh);
374 if (rv) { 403 if (rv) {
375 aprint_error_dev(self, "couldn't map uhh memory space\n"); 404 aprint_error_dev(self, "couldn't map uhh memory space\n");
376 return; 405 return;
377 } 406 }
378 sc->sc_uhh_size = UHH_SIZE; 407 sc->sc_uhh_size = UHH_SIZE;
379 sc->sc.sc_bus.dmatag = obio->obio_dmat; 408 sc->sc.sc_bus.dmatag = obio->obio_dmat;
380 sc->sc.sc_bus.usbrev = USBREV_2_0; 409 sc->sc.sc_bus.usbrev = USBREV_2_0;
381 sc->sc.sc_id_vendor = PCI_VENDOR_TI; 410 sc->sc.sc_id_vendor = PCI_VENDOR_TI;
382 strlcpy(sc->sc.sc_vendor, "OMAP3", sizeof(sc->sc.sc_vendor)); 411 strlcpy(sc->sc.sc_vendor, "OMAP3", sizeof(sc->sc.sc_vendor));
383 412
384 dpll5_init(sc); 413#ifdef OMAP_3XXX
 414 omap3_dpll5_init(sc);
385 415
386 usbhost_init(sc, 1); 416 omap3_usbhost_init(sc, 1);
 417#endif /* OMAP_3XXX */
387 418
388 sc->sc.sc_offs = EREAD1(&sc->sc, EHCI_CAPLENGTH); 419 sc->sc.sc_offs = EREAD1(&sc->sc, EHCI_CAPLENGTH);
389 420
390 //EOWRITE4(&sc->sc, EHCI_INSNREG04, 1 << 5); 421 //EOWRITE4(&sc->sc, EHCI_INSNREG04, 1 << 5);
391 422
392 sc->sc_ih = intr_establish(obio->obio_intr, IPL_USB, IST_LEVEL, ehci_intr, &sc->sc); 423 sc->sc_ih = intr_establish(obio->obio_intr, IPL_USB, IST_LEVEL, ehci_intr, &sc->sc);
393 424
394 //config_interrupts(self, omap3_ehci_attach1); 425 //config_interrupts(self, omap3_ehci_attach1);
395 omap3_ehci_attach1(self); 426 omap3_ehci_attach1(self);
396} 427}
397 428
398static int 429static int
399omap3_ehci_detach(device_t self, int flags) 430omap3_ehci_detach(device_t self, int flags)
@@ -423,43 +454,42 @@ omap3_ehci_detach(device_t self, int fla @@ -423,43 +454,42 @@ omap3_ehci_detach(device_t self, int fla
423 if (sc->sc_uhh_size) { 454 if (sc->sc_uhh_size) {
424 bus_space_unmap(sc->sc.iot, sc->sc_ioh_uhh, sc->sc_uhh_size); 455 bus_space_unmap(sc->sc.iot, sc->sc_ioh_uhh, sc->sc_uhh_size);
425 sc->sc_uhh_size = 0; 456 sc->sc_uhh_size = 0;
426 } 457 }
427 458
428 if (sc->sc.sc_size) { 459 if (sc->sc.sc_size) {
429 bus_space_unmap(sc->sc.iot, sc->sc.ioh, sc->sc.sc_size); 460 bus_space_unmap(sc->sc.iot, sc->sc.ioh, sc->sc.sc_size);
430 sc->sc.sc_size = 0; 461 sc->sc.sc_size = 0;
431 } 462 }
432 463
433 return 0; 464 return 0;
434} 465}
435 466
 467#ifdef OMAP_3XXX
436static void 468static void
437dpll5_init(struct omap3_ehci_softc *sc) 469omap3_dpll5_init(struct omap3_ehci_softc *sc)
438{ 470{
439 bus_space_tag_t iot = sc->sc.iot; 471 bus_space_tag_t iot = sc->sc.iot;
440 bus_space_handle_t ioh; 472 bus_space_handle_t ioh;
441 int err; 473 int err;
442 474
443 if (sc->sc_dpll5.m == 0 || sc->sc_dpll5.n == 0 || sc->sc_dpll5.m2 == 0) 475 if (sc->sc_dpll5.m == 0 || sc->sc_dpll5.n == 0 || sc->sc_dpll5.m2 == 0)
444 return; 476 return;
445 477
446 err = bus_space_map(iot, CCR_CM_BASE, CCR_CM_SIZE, 0, &ioh); 478 err = bus_space_map(iot, CCR_CM_BASE, CCR_CM_SIZE, 0, &ioh);
447 if (err) 479 if (err)
448 panic("%s: cannot map CCR_CM_BASE at %#x, error %d\n", 480 panic("%s: cannot map CCR_CM_BASE at %#x, error %d\n",
449 __func__, CCR_CM_BASE, err); 481 __func__, CCR_CM_BASE, err);
450 482
451 
452#if defined(OMAP_3530) || defined(OMAP_3540) 
453 /* set the multiplier and divider values for the desired CLKOUT freq */ 483 /* set the multiplier and divider values for the desired CLKOUT freq */
454 uint32_t m = sc->sc_dpll5.m; 484 uint32_t m = sc->sc_dpll5.m;
455 uint32_t n = sc->sc_dpll5.n; 485 uint32_t n = sc->sc_dpll5.n;
456 /* set the corresponding output dividers */ 486 /* set the corresponding output dividers */
457 uint32_t m2 = sc->sc_dpll5.m2; 487 uint32_t m2 = sc->sc_dpll5.m2;
458 488
459 KASSERTMSG(479900000 <= 2 * m * (omap_sys_clk / ((n + 1) * m2)), 489 KASSERTMSG(479900000 <= 2 * m * (omap_sys_clk / ((n + 1) * m2)),
460 "m=%u n=%u m2=%u freq=%u", 490 "m=%u n=%u m2=%u freq=%u",
461 m, n, m2, 2 * m * (omap_sys_clk / ((n + 1) * m2))); 491 m, n, m2, 2 * m * (omap_sys_clk / ((n + 1) * m2)));
462 KASSERTMSG(2 * m * (omap_sys_clk / ((n + 1) * m2)) <= 480100000, 492 KASSERTMSG(2 * m * (omap_sys_clk / ((n + 1) * m2)) <= 480100000,
463 "m=%u n=%u m2=%u freq=%u", 493 "m=%u n=%u m2=%u freq=%u",
464 m, n, m2, 2 * m * (omap_sys_clk / ((n + 1) * m2))); 494 m, n, m2, 2 * m * (omap_sys_clk / ((n + 1) * m2)));
465 495
@@ -469,33 +499,32 @@ dpll5_init(struct omap3_ehci_softc *sc) @@ -469,33 +499,32 @@ dpll5_init(struct omap3_ehci_softc *sc)
469 * factor N are programmed so that the new value is taken into 499 * factor N are programmed so that the new value is taken into
470 * account during current DPLL relock. 500 * account during current DPLL relock.
471 */ 501 */
472 bus_space_write_4(iot, ioh, CM_CLKEN2_PLL, (0x4 << 4) | 0x7); 502 bus_space_write_4(iot, ioh, CM_CLKEN2_PLL, (0x4 << 4) | 0x7);
473 503
474 bus_space_write_4(iot, ioh, CM_CLKSEL4_PLL, (m << 8) | n); 504 bus_space_write_4(iot, ioh, CM_CLKSEL4_PLL, (m << 8) | n);
475 bus_space_write_4(iot, ioh, CM_CLKSEL5_PLL, m2); 505 bus_space_write_4(iot, ioh, CM_CLKSEL5_PLL, m2);
476 506
477 /* 507 /*
478 * Put DPLL5 into low power stop mode when the 120MHz clock 508 * Put DPLL5 into low power stop mode when the 120MHz clock
479 * is not required (restarted automatically) 509 * is not required (restarted automatically)
480 */ 510 */
481 bus_space_write_4(iot, ioh, CM_AUTOIDLE2_PLL, AUTO_PERIPH2_DPLL); 511 bus_space_write_4(iot, ioh, CM_AUTOIDLE2_PLL, AUTO_PERIPH2_DPLL);
482#endif /* OMAP_3540 || OMAP_3530 */ 
483 512
484 bus_space_unmap(iot, ioh, CCR_CM_SIZE); 513 bus_space_unmap(iot, ioh, CCR_CM_SIZE);
485} 514}
486 515
487static void 516static void
488usbhost_init(struct omap3_ehci_softc *sc, int enable) 517omap3_usbhost_init(struct omap3_ehci_softc *sc, int enable)
489{ 518{
490 bus_space_tag_t iot = sc->sc.iot; 519 bus_space_tag_t iot = sc->sc.iot;
491 bus_space_handle_t ioh; 520 bus_space_handle_t ioh;
492 uint32_t r; 521 uint32_t r;
493 int err; 522 int err;
494 523
495 /* 524 /*
496 * USBHOST 525 * USBHOST
497 */ 526 */
498 err = bus_space_map(iot, USBHOST_CM_BASE, USBHOST_CM_SIZE, 0, &ioh); 527 err = bus_space_map(iot, USBHOST_CM_BASE, USBHOST_CM_SIZE, 0, &ioh);
499 if (err) 528 if (err)
500 panic("%s: cannot map USBHOST_CM_BASE at %#x, error %d\n", 529 panic("%s: cannot map USBHOST_CM_BASE at %#x, error %d\n",
501 __func__, USBHOST_CM_BASE, err); 530 __func__, USBHOST_CM_BASE, err);
@@ -546,26 +575,27 @@ usbhost_init(struct omap3_ehci_softc *sc @@ -546,26 +575,27 @@ usbhost_init(struct omap3_ehci_softc *sc
546 else 575 else
547 r |= AUTO_USBTLL; 576 r |= AUTO_USBTLL;
548 bus_space_write_4(iot, ioh, CM_AUTOIDLE3_CORE, r); 577 bus_space_write_4(iot, ioh, CM_AUTOIDLE3_CORE, r);
549 578
550 bus_space_unmap(iot, ioh, CORE_CM_SIZE); 579 bus_space_unmap(iot, ioh, CORE_CM_SIZE);
551 580
552 delay(10000); 581 delay(10000);
553 582
554#undef USBHOST_CM_SIZE 583#undef USBHOST_CM_SIZE
555#undef USBHOST_CM_BASE 584#undef USBHOST_CM_BASE
556#undef CORE_CM_SIZE 585#undef CORE_CM_SIZE
557#undef CORE_CM_BASE 586#undef CORE_CM_BASE
558} 587}
 588#endif /* OMAP_3XXX */
559 589
560static void 590static void
561usbtll_reset(struct omap3_ehci_softc *sc) 591usbtll_reset(struct omap3_ehci_softc *sc)
562{ 592{
563 uint32_t v; 593 uint32_t v;
564 int retry = 5000; 594 int retry = 5000;
565 595
566 USBTLL_WRITE4(sc, USBTLL_SYSCONFIG, USBTLL_SYSCONFIG_SOFTRESET); 596 USBTLL_WRITE4(sc, USBTLL_SYSCONFIG, USBTLL_SYSCONFIG_SOFTRESET);
567 do { 597 do {
568 v = USBTLL_READ4(sc, USBTLL_SYSSTATUS); 598 v = USBTLL_READ4(sc, USBTLL_SYSSTATUS);
569 if (v & USBTLL_SYSSTATUS_RESETDONE) 599 if (v & USBTLL_SYSSTATUS_RESETDONE)
570 break; 600 break;
571 delay(10); 601 delay(10);
@@ -584,36 +614,35 @@ usbtll_power(struct omap3_ehci_softc *sc @@ -584,36 +614,35 @@ usbtll_power(struct omap3_ehci_softc *sc
584 614
585 if (on) { 615 if (on) {
586 v = USBTLL_SYSCONFIG_ENAWAKEUP | 616 v = USBTLL_SYSCONFIG_ENAWAKEUP |
587 USBTLL_SYSCONFIG_AUTOIDLE | 617 USBTLL_SYSCONFIG_AUTOIDLE |
588 USBTLL_SYSCONFIG_SIDLEMODE | 618 USBTLL_SYSCONFIG_SIDLEMODE |
589 USBTLL_SYSCONFIG_CLOCKACTIVITY; 619 USBTLL_SYSCONFIG_CLOCKACTIVITY;
590 USBTLL_WRITE4(sc, USBTLL_SYSCONFIG, v); 620 USBTLL_WRITE4(sc, USBTLL_SYSCONFIG, v);
591 } 621 }
592} 622}
593 623
594static void 624static void
595usbtll_init(struct omap3_ehci_softc *sc, int chmask) 625usbtll_init(struct omap3_ehci_softc *sc, int chmask)
596{ 626{
597 int i; 
598 uint32_t v; 627 uint32_t v;
599 628
600 v = USBTLL_READ4(sc, USBTLL_SHARED_CONF); 629 v = USBTLL_READ4(sc, USBTLL_SHARED_CONF);
601 v |= (USBTLL_SHARED_CONF_FCLK_IS_ON | (1 << 2)/*divration*/); 630 v |= (USBTLL_SHARED_CONF_FCLK_IS_ON | (1 << 2)/*divration*/);
602 v &= ~USBTLL_SHARED_CONF_USB_90D_DDR_EN; 631 v &= ~USBTLL_SHARED_CONF_USB_90D_DDR_EN;
603 v &= ~USBTLL_SHARED_CONF_USB_180D_SDR_EN; 632 v &= ~USBTLL_SHARED_CONF_USB_180D_SDR_EN;
604 USBTLL_WRITE4(sc, USBTLL_SHARED_CONF, v); 633 USBTLL_WRITE4(sc, USBTLL_SHARED_CONF, v);
605 634
606 for (i = 0; i < 3; i++) { 635 for (u_int i = 0; i < sc->sc_nports; i++) {
607 if (sc->sc_portconfig[i].mode == OMAP3_EHCI_PORT_MODE_NONE) 636 if (sc->sc_portconfig[i].mode == OMAP3_EHCI_PORT_MODE_NONE)
608 continue; 637 continue;
609 v = USBTLL_READ4(sc, USBTLL_CHANNEL_CONF(i)); 638 v = USBTLL_READ4(sc, USBTLL_CHANNEL_CONF(i));
610 v &= ~(USBTLL_CHANNEL_CONF_ULPINOBITSTUFF| 639 v &= ~(USBTLL_CHANNEL_CONF_ULPINOBITSTUFF|
611 USBTLL_CHANNEL_CONF_ULPIAUTOIDLE| 640 USBTLL_CHANNEL_CONF_ULPIAUTOIDLE|
612 USBTLL_CHANNEL_CONF_ULPIDDRMODE); 641 USBTLL_CHANNEL_CONF_ULPIDDRMODE);
613 //v |= USBTLL_CHANNEL_CONF_FSLSMODE; 642 //v |= USBTLL_CHANNEL_CONF_FSLSMODE;
614 v |= USBTLL_CHANNEL_CONF_CHANEN; 643 v |= USBTLL_CHANNEL_CONF_CHANEN;
615 USBTLL_WRITE4(sc, USBTLL_CHANNEL_CONF(i), v); 644 USBTLL_WRITE4(sc, USBTLL_CHANNEL_CONF(i), v);
616 } 645 }
617} 646}
618 647
619static void 648static void
@@ -653,44 +682,44 @@ static void @@ -653,44 +682,44 @@ static void
653uhh_portconfig(struct omap3_ehci_softc *sc) 682uhh_portconfig(struct omap3_ehci_softc *sc)
654{ 683{
655 uint32_t v; 684 uint32_t v;
656 685
657 v = UHH_READ4(sc, UHH_HOSTCONFIG); 686 v = UHH_READ4(sc, UHH_HOSTCONFIG);
658 v |= UHH_HOSTCONFIG_ENA_INCR16; 687 v |= UHH_HOSTCONFIG_ENA_INCR16;
659 v |= UHH_HOSTCONFIG_ENA_INCR8; 688 v |= UHH_HOSTCONFIG_ENA_INCR8;
660 v |= UHH_HOSTCONFIG_ENA_INCR4; 689 v |= UHH_HOSTCONFIG_ENA_INCR4;
661 v |= UHH_HOSTCONFIG_APP_START_CLK; 690 v |= UHH_HOSTCONFIG_APP_START_CLK;
662 v &= ~UHH_HOSTCONFIG_ENA_INCR_ALIGN; 691 v &= ~UHH_HOSTCONFIG_ENA_INCR_ALIGN;
663 692
664 if (sc->sc_portconfig[0].mode == OMAP3_EHCI_PORT_MODE_NONE) 693 if (sc->sc_portconfig[0].mode == OMAP3_EHCI_PORT_MODE_NONE)
665 v &= ~UHH_HOSTCONFIG_P1_CONNECT_STATUS; 694 v &= ~UHH_HOSTCONFIG_P1_CONNECT_STATUS;
666 if (sc->sc_portconfig[1].mode == OMAP3_EHCI_PORT_MODE_NONE) 695 if (sc->sc_nports > 1
 696 && sc->sc_portconfig[1].mode == OMAP3_EHCI_PORT_MODE_NONE)
667 v &= ~UHH_HOSTCONFIG_P2_CONNECT_STATUS; 697 v &= ~UHH_HOSTCONFIG_P2_CONNECT_STATUS;
668 if (sc->sc_portconfig[2].mode == OMAP3_EHCI_PORT_MODE_NONE) 698 if (sc->sc_nports > 2
 699 && sc->sc_portconfig[2].mode == OMAP3_EHCI_PORT_MODE_NONE)
669 v &= ~UHH_HOSTCONFIG_P3_CONNECT_STATUS; 700 v &= ~UHH_HOSTCONFIG_P3_CONNECT_STATUS;
670 701
671 if (sc->sc_portconfig[0].mode == OMAP3_EHCI_PORT_MODE_PHY) 702 v &= ~(UHH_HOSTCONFIG_P1_ULPI_BYPASS |UHH_HOSTCONFIG_P2_ULPI_BYPASS
672 v &= ~UHH_HOSTCONFIG_P1_ULPI_BYPASS; 703 |UHH_HOSTCONFIG_P2_ULPI_BYPASS);
673 else 704 if (sc->sc_portconfig[0].mode != OMAP3_EHCI_PORT_MODE_PHY)
674 v |= UHH_HOSTCONFIG_P1_ULPI_BYPASS; 705 v |= UHH_HOSTCONFIG_P1_ULPI_BYPASS;
675 706
676 if (sc->sc_portconfig[1].mode == OMAP3_EHCI_PORT_MODE_PHY) 707 if (sc->sc_nports > 1
677 v &= ~UHH_HOSTCONFIG_P2_ULPI_BYPASS; 708 && sc->sc_portconfig[1].mode != OMAP3_EHCI_PORT_MODE_PHY)
678 else 
679 v |= UHH_HOSTCONFIG_P2_ULPI_BYPASS; 709 v |= UHH_HOSTCONFIG_P2_ULPI_BYPASS;
680 710
681 if (sc->sc_portconfig[2].mode == OMAP3_EHCI_PORT_MODE_PHY) 711 if (sc->sc_nports > 2
682 v &= ~UHH_HOSTCONFIG_P3_ULPI_BYPASS; 712 && sc->sc_portconfig[2].mode == OMAP3_EHCI_PORT_MODE_PHY)
683 else 
684 v |= UHH_HOSTCONFIG_P3_ULPI_BYPASS; 713 v |= UHH_HOSTCONFIG_P3_ULPI_BYPASS;
685 714
686 UHH_WRITE4(sc, UHH_HOSTCONFIG, v); 715 UHH_WRITE4(sc, UHH_HOSTCONFIG, v);
687} 716}
688 717
689CFATTACH_DECL2_NEW(omap3_ehci, sizeof(struct omap3_ehci_softc), 718CFATTACH_DECL2_NEW(omap3_ehci, sizeof(struct omap3_ehci_softc),
690 omap3_ehci_match, 719 omap3_ehci_match,
691 omap3_ehci_attach, 720 omap3_ehci_attach,
692 omap3_ehci_detach, 721 omap3_ehci_detach,
693 ehci_activate, 722 ehci_activate,
694 NULL, 723 NULL,
695 ehci_childdet 724 ehci_childdet
696); 725);