66 67#include <arm/xscale/ixp425/ixp425reg.h> 68#include <arm/xscale/ixp425/ixp425var.h> 69 70#define EHCI_VENDORID_IXP4XX 0x42fa05 71#define EHCI_HC_DEVSTR "IXP4XX Integrated USB 2.0 controller" 72 73struct ixp_ehci_softc { 74 ehci_softc_t base; /* storage for EHCI code */ 75 bus_space_tag_t iot; 76 bus_space_handle_t ioh; 77 struct bus_space tag; /* tag for private bus space ops */ 78}; 79 80static device_attach_t ehci_ixp_attach; 81static device_detach_t ehci_ixp_detach; 82static device_shutdown_t ehci_ixp_shutdown; 83static device_suspend_t ehci_ixp_suspend; 84static device_resume_t ehci_ixp_resume; 85 86static uint8_t ehci_bs_r_1(void *, bus_space_handle_t, bus_size_t); 87static void ehci_bs_w_1(void *, bus_space_handle_t, bus_size_t, u_int8_t); 88static uint16_t ehci_bs_r_2(void *, bus_space_handle_t, bus_size_t); 89static void ehci_bs_w_2(void *, bus_space_handle_t, bus_size_t, uint16_t); 90static uint32_t ehci_bs_r_4(void *, bus_space_handle_t, bus_size_t); 91static void ehci_bs_w_4(void *, bus_space_handle_t, bus_size_t, uint32_t); 92 93static int 94ehci_ixp_suspend(device_t self) 95{ 96 ehci_softc_t *sc = device_get_softc(self); 97 int err; 98 99 err = bus_generic_suspend(self); 100 if (err) 101 return (err); 102 ehci_suspend(sc); 103 return (0); 104} 105 106static int 107ehci_ixp_resume(device_t self) 108{ 109 ehci_softc_t *sc = device_get_softc(self); 110 111 ehci_resume(sc); 112 113 bus_generic_resume(self); 114 115 return (0); 116} 117 118static int 119ehci_ixp_shutdown(device_t self) 120{ 121 ehci_softc_t *sc = device_get_softc(self); 122 int err; 123 124 err = bus_generic_shutdown(self); 125 if (err) 126 return (err); 127 ehci_shutdown(sc); 128 129 return (0); 130} 131 132static int 133ehci_ixp_probe(device_t self) 134{ 135 136 device_set_desc(self, EHCI_HC_DEVSTR); 137 138 return (BUS_PROBE_DEFAULT); 139} 140 141static int 142ehci_ixp_attach(device_t self) 143{ 144 struct ixp_ehci_softc *isc = device_get_softc(self); 145 ehci_softc_t *sc = &isc->base; 146 int err; 147 int rid; 148 149 /* initialise some bus fields */ 150 sc->sc_bus.parent = self; 151 sc->sc_bus.devices = sc->sc_devices; 152 sc->sc_bus.devices_max = EHCI_MAX_DEVICES; 153 154 /* get all DMA memory */ 155 if (usb_bus_mem_alloc_all(&sc->sc_bus, 156 USB_GET_DMA_TAG(self), &ehci_iterate_hw_softc)) { 157 return (ENOMEM); 158 } 159 160 sc->sc_bus.usbrev = USB_REV_2_0; 161 162 /* NB: hints fix the memory location and irq */ 163 164 rid = 0; 165 sc->sc_io_res = bus_alloc_resource_any(self, SYS_RES_MEMORY, &rid, RF_ACTIVE); 166 if (!sc->sc_io_res) { 167 device_printf(self, "Could not map memory\n"); 168 goto error; 169 } 170 171 /* 172 * Craft special resource for bus space ops that handle 173 * byte-alignment of non-word addresses. Also, since 174 * we're already intercepting bus space ops we handle 175 * the register window offset that could otherwise be 176 * done with bus_space_subregion. 177 */ 178 isc->iot = rman_get_bustag(sc->sc_io_res); 179 isc->tag.bs_cookie = isc->iot; 180 /* read single */ 181 isc->tag.bs_r_1 = ehci_bs_r_1, 182 isc->tag.bs_r_2 = ehci_bs_r_2, 183 isc->tag.bs_r_4 = ehci_bs_r_4, 184 /* write (single) */ 185 isc->tag.bs_w_1 = ehci_bs_w_1, 186 isc->tag.bs_w_2 = ehci_bs_w_2, 187 isc->tag.bs_w_4 = ehci_bs_w_4, 188 189 sc->sc_io_tag = &isc->tag; 190 sc->sc_io_hdl = rman_get_bushandle(sc->sc_io_res); 191 sc->sc_io_size = IXP435_USB1_SIZE - 0x100; 192 193 rid = 0; 194 sc->sc_irq_res = bus_alloc_resource_any(self, SYS_RES_IRQ, &rid, 195 RF_ACTIVE); 196 if (sc->sc_irq_res == NULL) { 197 device_printf(self, "Could not allocate irq\n"); 198 goto error; 199 } 200 sc->sc_bus.bdev = device_add_child(self, "usbus", -1); 201 if (!sc->sc_bus.bdev) { 202 device_printf(self, "Could not add USB device\n"); 203 goto error; 204 } 205 device_set_ivars(sc->sc_bus.bdev, &sc->sc_bus); 206 device_set_desc(sc->sc_bus.bdev, EHCI_HC_DEVSTR); 207 208 sprintf(sc->sc_vendor, "Intel"); 209 210 211 err = bus_setup_intr(self, sc->sc_irq_res, INTR_TYPE_BIO | INTR_MPSAFE, 212 NULL, (driver_intr_t *)ehci_interrupt, sc, &sc->sc_intr_hdl); 213 if (err) { 214 device_printf(self, "Could not setup irq, %d\n", err); 215 sc->sc_intr_hdl = NULL; 216 goto error; 217 } 218 219 /* 220 * Arrange to force Host mode, select big-endian byte alignment, 221 * and arrange to not terminate reset operations (the adapter 222 * will ignore it if we do but might as well save a reg write). 223 * Also, the controller has an embedded Transaction Translator 224 * which means port speed must be read from the Port Status 225 * register following a port enable. 226 */ 227 sc->sc_flags |= EHCI_SCFLG_TT 228 | EHCI_SCFLG_SETMODE 229 | EHCI_SCFLG_BIGEDESC 230 | EHCI_SCFLG_BIGEMMIO 231 | EHCI_SCFLG_NORESTERM 232 ; 233 (void) ehci_reset(sc); 234 235 err = ehci_init(sc); 236 if (!err) { 237 err = device_probe_and_attach(sc->sc_bus.bdev); 238 } 239 if (err) { 240 device_printf(self, "USB init failed err=%d\n", err); 241 goto error; 242 } 243 return (0); 244 245error: 246 ehci_ixp_detach(self); 247 return (ENXIO); 248} 249 250static int 251ehci_ixp_detach(device_t self) 252{ 253 struct ixp_ehci_softc *isc = device_get_softc(self); 254 ehci_softc_t *sc = &isc->base; 255 device_t bdev; 256 int err; 257 258 if (sc->sc_bus.bdev) { 259 bdev = sc->sc_bus.bdev; 260 device_detach(bdev); 261 device_delete_child(self, bdev); 262 } 263 /* during module unload there are lots of children leftover */ 264 device_delete_all_children(self); 265 266 /* 267 * disable interrupts that might have been switched on in ehci_init 268 */ 269 if (sc->sc_io_res) { 270 EWRITE4(sc, EHCI_USBINTR, 0); 271 } 272 273 if (sc->sc_irq_res && sc->sc_intr_hdl) { 274 /* 275 * only call ehci_detach() after ehci_init() 276 */ 277 ehci_detach(sc); 278 279 err = bus_teardown_intr(self, sc->sc_irq_res, sc->sc_intr_hdl); 280 281 if (err) 282 /* XXX or should we panic? */ 283 device_printf(self, "Could not tear down irq, %d\n", 284 err); 285 sc->sc_intr_hdl = NULL; 286 } 287 288 if (sc->sc_irq_res) { 289 bus_release_resource(self, SYS_RES_IRQ, 0, sc->sc_irq_res); 290 sc->sc_irq_res = NULL; 291 } 292 if (sc->sc_io_res) { 293 bus_release_resource(self, SYS_RES_MEMORY, 0, 294 sc->sc_io_res); 295 sc->sc_io_res = NULL; 296 } 297 usb_bus_mem_free_all(&sc->sc_bus, &ehci_iterate_hw_softc); 298 299 return (0); 300} 301 302/* 303 * Bus space accessors for PIO operations. 304 */ 305 306static uint8_t 307ehci_bs_r_1(void *t, bus_space_handle_t h, bus_size_t o) 308{ 309 return bus_space_read_1((bus_space_tag_t) t, h, 310 0x100 + (o &~ 3) + (3 - (o & 3))); 311} 312 313static void 314ehci_bs_w_1(void *t, bus_space_handle_t h, bus_size_t o, u_int8_t v) 315{ 316 panic("%s", __func__); 317} 318 319static uint16_t 320ehci_bs_r_2(void *t, bus_space_handle_t h, bus_size_t o) 321{ 322 return bus_space_read_2((bus_space_tag_t) t, h, 323 0x100 + (o &~ 3) + (2 - (o & 3))); 324} 325 326static void 327ehci_bs_w_2(void *t, bus_space_handle_t h, bus_size_t o, uint16_t v) 328{ 329 panic("%s", __func__); 330} 331 332static uint32_t 333ehci_bs_r_4(void *t, bus_space_handle_t h, bus_size_t o) 334{ 335 return bus_space_read_4((bus_space_tag_t) t, h, 0x100 + o); 336} 337 338static void 339ehci_bs_w_4(void *t, bus_space_handle_t h, bus_size_t o, uint32_t v) 340{ 341 bus_space_write_4((bus_space_tag_t) t, h, 0x100 + o, v); 342} 343 344static device_method_t ehci_methods[] = { 345 /* Device interface */ 346 DEVMETHOD(device_probe, ehci_ixp_probe), 347 DEVMETHOD(device_attach, ehci_ixp_attach), 348 DEVMETHOD(device_detach, ehci_ixp_detach), 349 DEVMETHOD(device_suspend, ehci_ixp_suspend), 350 DEVMETHOD(device_resume, ehci_ixp_resume), 351 DEVMETHOD(device_shutdown, ehci_ixp_shutdown), 352 353 /* Bus interface */ 354 DEVMETHOD(bus_print_child, bus_generic_print_child), 355 356 {0, 0} 357}; 358 359static driver_t ehci_driver = { 360 "ehci", 361 ehci_methods, 362 sizeof(struct ixp_ehci_softc), 363}; 364 365static devclass_t ehci_devclass; 366 367DRIVER_MODULE(ehci, ixp, ehci_driver, ehci_devclass, 0, 0); 368MODULE_DEPEND(ehci, usb, 1, 1, 1);
|