1 /*- 2 * Copyright (c) 2016 Jared McNeill <jmcneill@invisible.ca> 3 * Copyright (c) 2018 Andrew Turner <andrew@FreeBSD.org> 4 * All rights reserved. 5 * 6 * This software was developed by SRI International and the University of 7 * Cambridge Computer Laboratory under DARPA/AFRL contract FA8750-10-C-0237 8 * ("CTSRD"), as part of the DARPA CRASH research programme. 9 * 10 * Redistribution and use in source and binary forms, with or without 11 * modification, are permitted provided that the following conditions 12 * are met: 13 * 1. Redistributions of source code must retain the above copyright 14 * notice, this list of conditions and the following disclaimer. 15 * 2. Redistributions in binary form must reproduce the above copyright 16 * notice, this list of conditions and the following disclaimer in the 17 * documentation and/or other materials provided with the distribution. 18 * 19 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 20 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 21 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 22 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 23 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 24 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 25 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 26 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 27 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 29 * SUCH DAMAGE. 30 * 31 * $FreeBSD$ 32 */ 33 34 /* 35 * Allwinner USB Dual-Role Device (DRD) controller 36 */ 37 38 #include <sys/cdefs.h> 39 __FBSDID("$FreeBSD$"); 40 41 #include <sys/param.h> 42 #include <sys/systm.h> 43 #include <sys/bus.h> 44 #include <sys/rman.h> 45 #include <sys/kernel.h> 46 #include <sys/condvar.h> 47 #include <sys/module.h> 48 #include <machine/bus.h> 49 50 #include <dev/ofw/ofw_bus.h> 51 #include <dev/ofw/ofw_bus_subr.h> 52 53 #include <dev/usb/usb.h> 54 #include <dev/usb/usbdi.h> 55 56 #include <dev/usb/usb_core.h> 57 #include <dev/usb/usb_busdma.h> 58 #include <dev/usb/usb_process.h> 59 #include <dev/usb/usb_util.h> 60 61 #include <dev/usb/usb_controller.h> 62 #include <dev/usb/usb_bus.h> 63 #include <dev/usb/controller/musb_otg.h> 64 65 #include <dev/extres/clk/clk.h> 66 #include <dev/extres/hwreset/hwreset.h> 67 68 #ifdef __arm__ 69 #include <arm/allwinner/aw_machdep.h> 70 #include <arm/allwinner/a10_sramc.h> 71 #endif 72 73 #define DRD_EP_MAX 5 74 75 #define MUSB2_REG_AWIN_VEND0 0x0043 76 #define VEND0_PIO_MODE 0 77 78 #if defined(__arm__) 79 #define bs_parent_space(bs) ((bs)->bs_parent) 80 typedef bus_space_tag_t awusb_bs_tag; 81 #elif defined(__aarch64__) 82 #define bs_parent_space(bs) (bs) 83 typedef void * awusb_bs_tag; 84 #endif 85 86 #define AWUSB_OKAY 0x01 87 #define AWUSB_NO_CONFDATA 0x02 88 static struct ofw_compat_data compat_data[] = { 89 { "allwinner,sun4i-a10-musb", AWUSB_OKAY }, 90 { "allwinner,sun6i-a31-musb", AWUSB_OKAY }, 91 { "allwinner,sun8i-a33-musb", AWUSB_OKAY | AWUSB_NO_CONFDATA }, 92 { NULL, 0 } 93 }; 94 95 static const struct musb_otg_ep_cfg musbotg_ep_allwinner[] = { 96 { 97 .ep_end = 5, 98 .ep_fifosz_shift = 9, 99 .ep_fifosz_reg = MUSB2_VAL_FIFOSZ_512, 100 }, 101 { 102 .ep_end = -1, 103 }, 104 }; 105 106 struct awusbdrd_softc { 107 struct musbotg_softc sc; 108 struct resource *res[2]; 109 clk_t clk; 110 hwreset_t reset; 111 struct bus_space bs; 112 int flags; 113 }; 114 115 static struct resource_spec awusbdrd_spec[] = { 116 { SYS_RES_MEMORY, 0, RF_ACTIVE }, 117 { SYS_RES_IRQ, 0, RF_ACTIVE }, 118 { -1, 0 } 119 }; 120 121 #define REMAPFLAG 0x8000 122 #define REGDECL(a, b) [(a)] = ((b) | REMAPFLAG) 123 124 /* Allwinner USB DRD register mappings */ 125 static const uint16_t awusbdrd_regmap[] = { 126 REGDECL(MUSB2_REG_EPFIFO(0), 0x0000), 127 REGDECL(MUSB2_REG_EPFIFO(1), 0x0004), 128 REGDECL(MUSB2_REG_EPFIFO(2), 0x0008), 129 REGDECL(MUSB2_REG_EPFIFO(3), 0x000c), 130 REGDECL(MUSB2_REG_EPFIFO(4), 0x0010), 131 REGDECL(MUSB2_REG_EPFIFO(5), 0x0014), 132 REGDECL(MUSB2_REG_POWER, 0x0040), 133 REGDECL(MUSB2_REG_DEVCTL, 0x0041), 134 REGDECL(MUSB2_REG_EPINDEX, 0x0042), 135 REGDECL(MUSB2_REG_INTTX, 0x0044), 136 REGDECL(MUSB2_REG_INTRX, 0x0046), 137 REGDECL(MUSB2_REG_INTTXE, 0x0048), 138 REGDECL(MUSB2_REG_INTRXE, 0x004a), 139 REGDECL(MUSB2_REG_INTUSB, 0x004c), 140 REGDECL(MUSB2_REG_INTUSBE, 0x0050), 141 REGDECL(MUSB2_REG_FRAME, 0x0054), 142 REGDECL(MUSB2_REG_TESTMODE, 0x007c), 143 REGDECL(MUSB2_REG_TXMAXP, 0x0080), 144 REGDECL(MUSB2_REG_TXCSRL, 0x0082), 145 REGDECL(MUSB2_REG_TXCSRH, 0x0083), 146 REGDECL(MUSB2_REG_RXMAXP, 0x0084), 147 REGDECL(MUSB2_REG_RXCSRL, 0x0086), 148 REGDECL(MUSB2_REG_RXCSRH, 0x0087), 149 REGDECL(MUSB2_REG_RXCOUNT, 0x0088), 150 REGDECL(MUSB2_REG_TXTI, 0x008c), 151 REGDECL(MUSB2_REG_TXNAKLIMIT, 0x008d), 152 REGDECL(MUSB2_REG_RXNAKLIMIT, 0x008f), 153 REGDECL(MUSB2_REG_RXTI, 0x008e), 154 REGDECL(MUSB2_REG_TXFIFOSZ, 0x0090), 155 REGDECL(MUSB2_REG_TXFIFOADD, 0x0092), 156 REGDECL(MUSB2_REG_RXFIFOSZ, 0x0094), 157 REGDECL(MUSB2_REG_RXFIFOADD, 0x0096), 158 REGDECL(MUSB2_REG_FADDR, 0x0098), 159 REGDECL(MUSB2_REG_TXFADDR(0), 0x0098), 160 REGDECL(MUSB2_REG_TXHADDR(0), 0x009a), 161 REGDECL(MUSB2_REG_TXHUBPORT(0), 0x009b), 162 REGDECL(MUSB2_REG_RXFADDR(0), 0x009c), 163 REGDECL(MUSB2_REG_RXHADDR(0), 0x009e), 164 REGDECL(MUSB2_REG_RXHUBPORT(0), 0x009f), 165 REGDECL(MUSB2_REG_TXFADDR(1), 0x0098), 166 REGDECL(MUSB2_REG_TXHADDR(1), 0x009a), 167 REGDECL(MUSB2_REG_TXHUBPORT(1), 0x009b), 168 REGDECL(MUSB2_REG_RXFADDR(1), 0x009c), 169 REGDECL(MUSB2_REG_RXHADDR(1), 0x009e), 170 REGDECL(MUSB2_REG_RXHUBPORT(1), 0x009f), 171 REGDECL(MUSB2_REG_TXFADDR(2), 0x0098), 172 REGDECL(MUSB2_REG_TXHADDR(2), 0x009a), 173 REGDECL(MUSB2_REG_TXHUBPORT(2), 0x009b), 174 REGDECL(MUSB2_REG_RXFADDR(2), 0x009c), 175 REGDECL(MUSB2_REG_RXHADDR(2), 0x009e), 176 REGDECL(MUSB2_REG_RXHUBPORT(2), 0x009f), 177 REGDECL(MUSB2_REG_TXFADDR(3), 0x0098), 178 REGDECL(MUSB2_REG_TXHADDR(3), 0x009a), 179 REGDECL(MUSB2_REG_TXHUBPORT(3), 0x009b), 180 REGDECL(MUSB2_REG_RXFADDR(3), 0x009c), 181 REGDECL(MUSB2_REG_RXHADDR(3), 0x009e), 182 REGDECL(MUSB2_REG_RXHUBPORT(3), 0x009f), 183 REGDECL(MUSB2_REG_TXFADDR(4), 0x0098), 184 REGDECL(MUSB2_REG_TXHADDR(4), 0x009a), 185 REGDECL(MUSB2_REG_TXHUBPORT(4), 0x009b), 186 REGDECL(MUSB2_REG_RXFADDR(4), 0x009c), 187 REGDECL(MUSB2_REG_RXHADDR(4), 0x009e), 188 REGDECL(MUSB2_REG_RXHUBPORT(4), 0x009f), 189 REGDECL(MUSB2_REG_TXFADDR(5), 0x0098), 190 REGDECL(MUSB2_REG_TXHADDR(5), 0x009a), 191 REGDECL(MUSB2_REG_TXHUBPORT(5), 0x009b), 192 REGDECL(MUSB2_REG_RXFADDR(5), 0x009c), 193 REGDECL(MUSB2_REG_RXHADDR(5), 0x009e), 194 REGDECL(MUSB2_REG_RXHUBPORT(5), 0x009f), 195 REGDECL(MUSB2_REG_CONFDATA, 0x00c0), 196 }; 197 198 static bus_size_t 199 awusbdrd_reg(bus_size_t o) 200 { 201 bus_size_t v; 202 203 KASSERT(o < nitems(awusbdrd_regmap), 204 ("%s: Invalid register %#lx", __func__, o)); 205 if (o >= nitems(awusbdrd_regmap)) 206 return (o); 207 208 v = awusbdrd_regmap[o]; 209 210 KASSERT((v & REMAPFLAG) != 0, ("%s: reg %#lx not in regmap", 211 __func__, o)); 212 213 return (v & ~REMAPFLAG); 214 } 215 216 static int 217 awusbdrd_filt(bus_size_t o) 218 { 219 switch (o) { 220 case MUSB2_REG_MISC: 221 case MUSB2_REG_RXDBDIS: 222 case MUSB2_REG_TXDBDIS: 223 return (1); 224 default: 225 return (0); 226 } 227 } 228 229 static uint8_t 230 awusbdrd_bs_r_1(awusb_bs_tag t, bus_space_handle_t h, bus_size_t o) 231 { 232 const struct bus_space *bs = t; 233 234 switch (o) { 235 case MUSB2_REG_HWVERS: 236 return (0); /* no known equivalent */ 237 } 238 239 return (bus_space_read_1(bs_parent_space(bs), h, awusbdrd_reg(o))); 240 } 241 242 static uint8_t 243 awusbdrd_bs_r_1_noconf(awusb_bs_tag t, bus_space_handle_t h, bus_size_t o) 244 { 245 246 /* 247 * There is no confdata register on some SoCs, return the same 248 * magic value as Linux. 249 */ 250 if (o == MUSB2_REG_CONFDATA) 251 return (0xde); 252 253 return (awusbdrd_bs_r_1(t, h, o)); 254 } 255 256 257 static uint16_t 258 awusbdrd_bs_r_2(awusb_bs_tag t, bus_space_handle_t h, bus_size_t o) 259 { 260 const struct bus_space *bs = t; 261 262 if (awusbdrd_filt(o) != 0) 263 return (0); 264 return bus_space_read_2(bs_parent_space(bs), h, awusbdrd_reg(o)); 265 } 266 267 static void 268 awusbdrd_bs_w_1(awusb_bs_tag t, bus_space_handle_t h, bus_size_t o, 269 uint8_t v) 270 { 271 const struct bus_space *bs = t; 272 273 if (awusbdrd_filt(o) != 0) 274 return; 275 276 bus_space_write_1(bs_parent_space(bs), h, awusbdrd_reg(o), v); 277 } 278 279 static void 280 awusbdrd_bs_w_2(awusb_bs_tag t, bus_space_handle_t h, bus_size_t o, 281 uint16_t v) 282 { 283 const struct bus_space *bs = t; 284 285 if (awusbdrd_filt(o) != 0) 286 return; 287 288 bus_space_write_2(bs_parent_space(bs), h, awusbdrd_reg(o), v); 289 } 290 291 static void 292 awusbdrd_bs_rm_1(awusb_bs_tag t, bus_space_handle_t h, bus_size_t o, 293 uint8_t *d, bus_size_t c) 294 { 295 const struct bus_space *bs = t; 296 297 bus_space_read_multi_1(bs_parent_space(bs), h, awusbdrd_reg(o), d, c); 298 } 299 300 static void 301 awusbdrd_bs_rm_4(awusb_bs_tag t, bus_space_handle_t h, bus_size_t o, 302 uint32_t *d, bus_size_t c) 303 { 304 const struct bus_space *bs = t; 305 306 bus_space_read_multi_4(bs_parent_space(bs), h, awusbdrd_reg(o), d, c); 307 } 308 309 static void 310 awusbdrd_bs_wm_1(awusb_bs_tag t, bus_space_handle_t h, bus_size_t o, 311 const uint8_t *d, bus_size_t c) 312 { 313 const struct bus_space *bs = t; 314 315 if (awusbdrd_filt(o) != 0) 316 return; 317 318 bus_space_write_multi_1(bs_parent_space(bs), h, awusbdrd_reg(o), d, c); 319 } 320 321 static void 322 awusbdrd_bs_wm_4(awusb_bs_tag t, bus_space_handle_t h, bus_size_t o, 323 const uint32_t *d, bus_size_t c) 324 { 325 const struct bus_space *bs = t; 326 327 if (awusbdrd_filt(o) != 0) 328 return; 329 330 bus_space_write_multi_4(bs_parent_space(bs), h, awusbdrd_reg(o), d, c); 331 } 332 333 static void 334 awusbdrd_intr(void *arg) 335 { 336 struct awusbdrd_softc *sc = arg; 337 uint8_t intusb; 338 uint16_t inttx, intrx; 339 340 intusb = MUSB2_READ_1(&sc->sc, MUSB2_REG_INTUSB); 341 inttx = MUSB2_READ_2(&sc->sc, MUSB2_REG_INTTX); 342 intrx = MUSB2_READ_2(&sc->sc, MUSB2_REG_INTRX); 343 if (intusb == 0 && inttx == 0 && intrx == 0) 344 return; 345 346 if (intusb) 347 MUSB2_WRITE_1(&sc->sc, MUSB2_REG_INTUSB, intusb); 348 if (inttx) 349 MUSB2_WRITE_2(&sc->sc, MUSB2_REG_INTTX, inttx); 350 if (intrx) 351 MUSB2_WRITE_2(&sc->sc, MUSB2_REG_INTRX, intrx); 352 353 musbotg_interrupt(arg, intrx, inttx, intusb); 354 } 355 356 static int 357 awusbdrd_probe(device_t dev) 358 { 359 if (!ofw_bus_status_okay(dev)) 360 return (ENXIO); 361 362 if (ofw_bus_search_compatible(dev, compat_data)->ocd_data == 0) 363 return (ENXIO); 364 365 device_set_desc(dev, "Allwinner USB DRD"); 366 return (BUS_PROBE_DEFAULT); 367 } 368 369 static int 370 awusbdrd_attach(device_t dev) 371 { 372 struct awusbdrd_softc *sc; 373 int error; 374 375 sc = device_get_softc(dev); 376 sc->flags = ofw_bus_search_compatible(dev, compat_data)->ocd_data; 377 378 error = bus_alloc_resources(dev, awusbdrd_spec, sc->res); 379 if (error != 0) 380 return (error); 381 382 /* AHB gate clock is required */ 383 error = clk_get_by_ofw_index(dev, 0, 0, &sc->clk); 384 if (error != 0) 385 goto fail; 386 387 /* AHB reset is only present on some SoCs */ 388 (void)hwreset_get_by_ofw_idx(dev, 0, 0, &sc->reset); 389 390 /* Enable clocks */ 391 error = clk_enable(sc->clk); 392 if (error != 0) { 393 device_printf(dev, "failed to enable clock: %d\n", error); 394 goto fail; 395 } 396 if (sc->reset != NULL) { 397 error = hwreset_deassert(sc->reset); 398 if (error != 0) { 399 device_printf(dev, "failed to de-assert reset: %d\n", 400 error); 401 goto fail; 402 } 403 } 404 405 sc->sc.sc_bus.parent = dev; 406 sc->sc.sc_bus.devices = sc->sc.sc_devices; 407 sc->sc.sc_bus.devices_max = MUSB2_MAX_DEVICES; 408 sc->sc.sc_bus.dma_bits = 32; 409 410 error = usb_bus_mem_alloc_all(&sc->sc.sc_bus, USB_GET_DMA_TAG(dev), 411 NULL); 412 if (error != 0) { 413 error = ENOMEM; 414 goto fail; 415 } 416 417 #if defined(__arm__) 418 sc->bs.bs_parent = rman_get_bustag(sc->res[0]); 419 #elif defined(__aarch64__) 420 sc->bs.bs_cookie = rman_get_bustag(sc->res[0]); 421 #endif 422 423 if ((sc->flags & AWUSB_NO_CONFDATA) == AWUSB_NO_CONFDATA) 424 sc->bs.bs_r_1 = awusbdrd_bs_r_1_noconf; 425 else 426 sc->bs.bs_r_1 = awusbdrd_bs_r_1; 427 sc->bs.bs_r_2 = awusbdrd_bs_r_2; 428 sc->bs.bs_w_1 = awusbdrd_bs_w_1; 429 sc->bs.bs_w_2 = awusbdrd_bs_w_2; 430 sc->bs.bs_rm_1 = awusbdrd_bs_rm_1; 431 sc->bs.bs_rm_4 = awusbdrd_bs_rm_4; 432 sc->bs.bs_wm_1 = awusbdrd_bs_wm_1; 433 sc->bs.bs_wm_4 = awusbdrd_bs_wm_4; 434 435 sc->sc.sc_io_tag = &sc->bs; 436 sc->sc.sc_io_hdl = rman_get_bushandle(sc->res[0]); 437 sc->sc.sc_io_size = rman_get_size(sc->res[0]); 438 439 sc->sc.sc_bus.bdev = device_add_child(dev, "usbus", -1); 440 if (sc->sc.sc_bus.bdev == NULL) { 441 error = ENXIO; 442 goto fail; 443 } 444 device_set_ivars(sc->sc.sc_bus.bdev, &sc->sc.sc_bus); 445 sc->sc.sc_id = 0; 446 sc->sc.sc_platform_data = sc; 447 sc->sc.sc_mode = MUSB2_HOST_MODE; /* XXX HOST vs DEVICE mode */ 448 sc->sc.sc_ep_max = DRD_EP_MAX; 449 sc->sc.sc_ep_cfg = musbotg_ep_allwinner; 450 451 error = bus_setup_intr(dev, sc->res[1], INTR_MPSAFE | INTR_TYPE_BIO, 452 NULL, awusbdrd_intr, sc, &sc->sc.sc_intr_hdl); 453 if (error != 0) 454 goto fail; 455 456 /* Enable PIO mode */ 457 bus_write_1(sc->res[0], MUSB2_REG_AWIN_VEND0, VEND0_PIO_MODE); 458 459 #ifdef __arm__ 460 /* Map SRAMD area to USB0 (sun4i/sun7i only) */ 461 switch (allwinner_soc_family()) { 462 case ALLWINNERSOC_SUN4I: 463 case ALLWINNERSOC_SUN7I: 464 a10_map_to_otg(); 465 break; 466 } 467 #endif 468 469 error = musbotg_init(&sc->sc); 470 if (error != 0) 471 goto fail; 472 473 error = device_probe_and_attach(sc->sc.sc_bus.bdev); 474 if (error != 0) 475 goto fail; 476 477 musbotg_vbus_interrupt(&sc->sc, 1); /* XXX VBUS */ 478 479 return (0); 480 481 fail: 482 if (sc->reset != NULL) 483 hwreset_release(sc->reset); 484 if (sc->clk != NULL) 485 clk_release(sc->clk); 486 bus_release_resources(dev, awusbdrd_spec, sc->res); 487 return (error); 488 } 489 490 static int 491 awusbdrd_detach(device_t dev) 492 { 493 struct awusbdrd_softc *sc; 494 device_t bdev; 495 int error; 496 497 sc = device_get_softc(dev); 498 499 if (sc->sc.sc_bus.bdev != NULL) { 500 bdev = sc->sc.sc_bus.bdev; 501 device_detach(bdev); 502 device_delete_child(dev, bdev); 503 } 504 505 musbotg_uninit(&sc->sc); 506 error = bus_teardown_intr(dev, sc->res[1], sc->sc.sc_intr_hdl); 507 if (error != 0) 508 return (error); 509 510 usb_bus_mem_free_all(&sc->sc.sc_bus, NULL); 511 512 if (sc->reset != NULL) 513 hwreset_release(sc->reset); 514 if (sc->clk != NULL) 515 clk_release(sc->clk); 516 517 bus_release_resources(dev, awusbdrd_spec, sc->res); 518 519 device_delete_children(dev); 520 521 return (0); 522 } 523 524 static device_method_t awusbdrd_methods[] = { 525 /* Device interface */ 526 DEVMETHOD(device_probe, awusbdrd_probe), 527 DEVMETHOD(device_attach, awusbdrd_attach), 528 DEVMETHOD(device_detach, awusbdrd_detach), 529 DEVMETHOD(device_suspend, bus_generic_suspend), 530 DEVMETHOD(device_resume, bus_generic_resume), 531 DEVMETHOD(device_shutdown, bus_generic_shutdown), 532 533 DEVMETHOD_END 534 }; 535 536 static driver_t awusbdrd_driver = { 537 .name = "musbotg", 538 .methods = awusbdrd_methods, 539 .size = sizeof(struct awusbdrd_softc), 540 }; 541 542 static devclass_t awusbdrd_devclass; 543 544 DRIVER_MODULE(musbotg, simplebus, awusbdrd_driver, awusbdrd_devclass, 0, 0); 545 MODULE_DEPEND(musbotg, usb, 1, 1, 1); 546