1 /*- 2 * Copyright (C) 2010 Nathan Whitehorn 3 * All rights reserved. 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 THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 15 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 16 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 17 * IN NO EVENT SHALL TOOLS GMBH BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 18 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 19 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 20 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 21 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 22 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 23 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24 * 25 * $FreeBSD$ 26 */ 27 28 #include <sys/param.h> 29 #include <sys/systm.h> 30 #include <sys/kernel.h> 31 #include <sys/module.h> 32 #include <sys/malloc.h> 33 #include <sys/bus.h> 34 #include <sys/cpu.h> 35 #include <sys/resource.h> 36 #include <sys/rman.h> 37 38 #include <vm/vm.h> 39 #include <vm/pmap.h> 40 41 #include <machine/bus.h> 42 #include <machine/platform.h> 43 #include <machine/pmap.h> 44 #include <machine/resource.h> 45 46 #include "ps3bus.h" 47 #include "ps3-hvcall.h" 48 #include "iommu_if.h" 49 50 static void ps3bus_identify(driver_t *, device_t); 51 static int ps3bus_probe(device_t); 52 static int ps3bus_attach(device_t); 53 static int ps3bus_print_child(device_t dev, device_t child); 54 static int ps3bus_read_ivar(device_t bus, device_t child, int which, 55 uintptr_t *result); 56 static struct resource *ps3bus_alloc_resource(device_t bus, device_t child, 57 int type, int *rid, u_long start, u_long end, 58 u_long count, u_int flags); 59 static int ps3bus_activate_resource(device_t bus, device_t child, int type, 60 int rid, struct resource *res); 61 static bus_dma_tag_t ps3bus_get_dma_tag(device_t dev, device_t child); 62 static int ps3_iommu_map(device_t dev, bus_dma_segment_t *segs, int *nsegs, bus_addr_t min, bus_addr_t max, bus_size_t alignment, 63 bus_size_t boundary, void *cookie); 64 static int ps3_iommu_unmap(device_t dev, bus_dma_segment_t *segs, 65 int nsegs, void *cookie); 66 67 struct ps3bus_devinfo { 68 int bus; 69 int dev; 70 uint64_t bustype; 71 uint64_t devtype; 72 73 struct resource_list resources; 74 bus_dma_tag_t dma_tag; 75 76 struct mtx iommu_mtx; 77 bus_addr_t dma_base[4]; 78 }; 79 80 static MALLOC_DEFINE(M_PS3BUS, "ps3bus", "PS3 system bus device information"); 81 82 enum ps3bus_irq_type { 83 SB_IRQ = 2, 84 OHCI_IRQ = 3, 85 EHCI_IRQ = 4, 86 }; 87 88 static device_method_t ps3bus_methods[] = { 89 /* Device interface */ 90 DEVMETHOD(device_identify, ps3bus_identify), 91 DEVMETHOD(device_probe, ps3bus_probe), 92 DEVMETHOD(device_attach, ps3bus_attach), 93 94 /* Bus interface */ 95 DEVMETHOD(bus_driver_added, bus_generic_driver_added), 96 DEVMETHOD(bus_add_child, bus_generic_add_child), 97 DEVMETHOD(bus_get_dma_tag, ps3bus_get_dma_tag), 98 DEVMETHOD(bus_print_child, ps3bus_print_child), 99 DEVMETHOD(bus_read_ivar, ps3bus_read_ivar), 100 DEVMETHOD(bus_alloc_resource, ps3bus_alloc_resource), 101 DEVMETHOD(bus_activate_resource, ps3bus_activate_resource), 102 DEVMETHOD(bus_setup_intr, bus_generic_setup_intr), 103 DEVMETHOD(bus_teardown_intr, bus_generic_teardown_intr), 104 105 /* IOMMU interface */ 106 DEVMETHOD(iommu_map, ps3_iommu_map), 107 DEVMETHOD(iommu_unmap, ps3_iommu_unmap), 108 109 { 0, 0 } 110 }; 111 112 struct ps3bus_softc { 113 struct rman sc_mem_rman; 114 struct mem_region *regions; 115 int rcount; 116 }; 117 118 static driver_t ps3bus_driver = { 119 "ps3bus", 120 ps3bus_methods, 121 sizeof(struct ps3bus_softc) 122 }; 123 124 static devclass_t ps3bus_devclass; 125 126 DRIVER_MODULE(ps3bus, nexus, ps3bus_driver, ps3bus_devclass, 0, 0); 127 128 static void 129 ps3bus_identify(driver_t *driver, device_t parent) 130 { 131 if (strcmp(installed_platform(), "ps3") != 0) 132 return; 133 134 if (device_find_child(parent, "ps3bus", -1) == NULL) 135 BUS_ADD_CHILD(parent, 0, "ps3bus", 0); 136 } 137 138 static int 139 ps3bus_probe(device_t dev) 140 { 141 /* Do not attach to any OF nodes that may be present */ 142 143 device_set_desc(dev, "Playstation 3 System Bus"); 144 145 return (BUS_PROBE_NOWILDCARD); 146 } 147 148 static void 149 ps3bus_resources_init(struct rman *rm, int bus_index, int dev_index, 150 struct ps3bus_devinfo *dinfo) 151 { 152 uint64_t irq_type, irq, outlet; 153 uint64_t reg_type, paddr, len; 154 uint64_t ppe, junk; 155 int i, result; 156 int thread; 157 158 resource_list_init(&dinfo->resources); 159 160 lv1_get_logical_ppe_id(&ppe); 161 thread = 32 - fls(mfctrl()); 162 163 /* Scan for interrupts */ 164 for (i = 0; i < 10; i++) { 165 result = lv1_get_repository_node_value(PS3_LPAR_ID_PME, 166 (lv1_repository_string("bus") >> 32) | bus_index, 167 lv1_repository_string("dev") | dev_index, 168 lv1_repository_string("intr") | i, 0, &irq_type, &irq); 169 170 if (result != 0) 171 break; 172 173 switch (irq_type) { 174 case SB_IRQ: 175 lv1_construct_event_receive_port(&outlet); 176 lv1_connect_irq_plug_ext(ppe, thread, outlet, outlet, 177 0); 178 lv1_connect_interrupt_event_receive_port(dinfo->bus, 179 dinfo->dev, outlet, irq); 180 break; 181 case OHCI_IRQ: 182 case EHCI_IRQ: 183 lv1_construct_io_irq_outlet(irq, &outlet); 184 lv1_connect_irq_plug_ext(ppe, thread, outlet, outlet, 185 0); 186 break; 187 default: 188 printf("Unknown IRQ type %ld for device %d.%d\n", 189 irq_type, dinfo->bus, dinfo->dev); 190 break; 191 } 192 193 resource_list_add(&dinfo->resources, SYS_RES_IRQ, i, 194 outlet, outlet, 1); 195 } 196 197 /* Scan for registers */ 198 for (i = 0; i < 10; i++) { 199 result = lv1_get_repository_node_value(PS3_LPAR_ID_PME, 200 (lv1_repository_string("bus") >> 32) | bus_index, 201 lv1_repository_string("dev") | dev_index, 202 lv1_repository_string("reg") | i, 203 lv1_repository_string("type"), ®_type, &junk); 204 205 if (result != 0) 206 break; 207 208 result = lv1_get_repository_node_value(PS3_LPAR_ID_PME, 209 (lv1_repository_string("bus") >> 32) | bus_index, 210 lv1_repository_string("dev") | dev_index, 211 lv1_repository_string("reg") | i, 212 lv1_repository_string("data"), &paddr, &len); 213 214 result = lv1_map_device_mmio_region(dinfo->bus, dinfo->dev, 215 paddr, len, 12 /* log_2(4 KB) */, &paddr); 216 217 if (result != 0) { 218 printf("Mapping registers failed for device " 219 "%d.%d (%ld.%ld): %d\n", dinfo->bus, dinfo->dev, 220 dinfo->bustype, dinfo->devtype, result); 221 continue; 222 } 223 224 rman_manage_region(rm, paddr, paddr + len - 1); 225 resource_list_add(&dinfo->resources, SYS_RES_MEMORY, i, 226 paddr, paddr + len, len); 227 } 228 } 229 230 static int 231 ps3bus_attach(device_t self) 232 { 233 struct ps3bus_softc *sc; 234 struct ps3bus_devinfo *dinfo; 235 int bus_index, dev_index, result; 236 uint64_t bustype, bus, devs; 237 uint64_t dev, devtype; 238 uint64_t junk; 239 device_t cdev; 240 241 sc = device_get_softc(self); 242 sc->sc_mem_rman.rm_type = RMAN_ARRAY; 243 sc->sc_mem_rman.rm_descr = "PS3Bus Memory Mapped I/O"; 244 rman_init(&sc->sc_mem_rman); 245 246 /* Get memory regions for DMA */ 247 mem_regions(&sc->regions, &sc->rcount, &sc->regions, &sc->rcount); 248 249 /* 250 * Probe all the PS3's buses. 251 */ 252 253 for (bus_index = 0; bus_index < 5; bus_index++) { 254 result = lv1_get_repository_node_value(PS3_LPAR_ID_PME, 255 (lv1_repository_string("bus") >> 32) | bus_index, 256 lv1_repository_string("type"), 0, 0, &bustype, &junk); 257 258 if (result != 0) 259 continue; 260 261 result = lv1_get_repository_node_value(PS3_LPAR_ID_PME, 262 (lv1_repository_string("bus") >> 32) | bus_index, 263 lv1_repository_string("id"), 0, 0, &bus, &junk); 264 265 if (result != 0) 266 continue; 267 268 result = lv1_get_repository_node_value(PS3_LPAR_ID_PME, 269 (lv1_repository_string("bus") >> 32) | bus_index, 270 lv1_repository_string("num_dev"), 0, 0, &devs, &junk); 271 272 for (dev_index = 0; dev_index < devs; dev_index++) { 273 result = lv1_get_repository_node_value(PS3_LPAR_ID_PME, 274 (lv1_repository_string("bus") >> 32) | bus_index, 275 lv1_repository_string("dev") | dev_index, 276 lv1_repository_string("type"), 0, &devtype, &junk); 277 278 if (result != 0) 279 continue; 280 281 result = lv1_get_repository_node_value(PS3_LPAR_ID_PME, 282 (lv1_repository_string("bus") >> 32) | bus_index, 283 lv1_repository_string("dev") | dev_index, 284 lv1_repository_string("id"), 0, &dev, &junk); 285 286 if (result != 0) 287 continue; 288 289 dinfo = malloc(sizeof(*dinfo), M_PS3BUS, 290 M_WAITOK | M_ZERO); 291 292 dinfo->bus = bus; 293 dinfo->dev = dev; 294 dinfo->bustype = bustype; 295 dinfo->devtype = devtype; 296 297 if (dinfo->bustype == PS3_BUSTYPE_SYSBUS) 298 lv1_open_device(bus, dev, 0); 299 300 ps3bus_resources_init(&sc->sc_mem_rman, bus_index, 301 dev_index, dinfo); 302 303 cdev = device_add_child(self, NULL, -1); 304 if (cdev == NULL) { 305 device_printf(self, 306 "device_add_child failed\n"); 307 free(dinfo, M_PS3BUS); 308 continue; 309 } 310 311 mtx_init(&dinfo->iommu_mtx, "iommu", NULL, MTX_DEF); 312 device_set_ivars(cdev, dinfo); 313 } 314 } 315 316 return (bus_generic_attach(self)); 317 } 318 319 static int 320 ps3bus_print_child(device_t dev, device_t child) 321 { 322 struct ps3bus_devinfo *dinfo = device_get_ivars(child); 323 int retval = 0; 324 325 retval += bus_print_child_header(dev, child); 326 retval += resource_list_print_type(&dinfo->resources, "mem", 327 SYS_RES_MEMORY, "%#lx"); 328 retval += resource_list_print_type(&dinfo->resources, "irq", 329 SYS_RES_IRQ, "%ld"); 330 331 retval += bus_print_child_footer(dev, child); 332 333 return (retval); 334 } 335 336 static int 337 ps3bus_read_ivar(device_t bus, device_t child, int which, uintptr_t *result) 338 { 339 struct ps3bus_devinfo *dinfo = device_get_ivars(child); 340 341 switch (which) { 342 case PS3BUS_IVAR_BUS: 343 *result = dinfo->bus; 344 break; 345 case PS3BUS_IVAR_DEVICE: 346 *result = dinfo->dev; 347 break; 348 case PS3BUS_IVAR_BUSTYPE: 349 *result = dinfo->bustype; 350 break; 351 case PS3BUS_IVAR_DEVTYPE: 352 *result = dinfo->devtype; 353 break; 354 default: 355 return (EINVAL); 356 } 357 358 return (0); 359 } 360 361 static struct resource * 362 ps3bus_alloc_resource(device_t bus, device_t child, int type, int *rid, 363 u_long start, u_long end, u_long count, u_int flags) 364 { 365 struct ps3bus_devinfo *dinfo; 366 struct ps3bus_softc *sc; 367 int needactivate; 368 struct resource *rv; 369 struct rman *rm; 370 u_long adjstart, adjend, adjcount; 371 struct resource_list_entry *rle; 372 373 sc = device_get_softc(bus); 374 dinfo = device_get_ivars(child); 375 needactivate = flags & RF_ACTIVE; 376 flags &= ~RF_ACTIVE; 377 378 switch (type) { 379 case SYS_RES_MEMORY: 380 rle = resource_list_find(&dinfo->resources, SYS_RES_MEMORY, 381 *rid); 382 if (rle == NULL) { 383 device_printf(bus, "no rle for %s memory %d\n", 384 device_get_nameunit(child), *rid); 385 return (NULL); 386 } 387 388 if (start < rle->start) 389 adjstart = rle->start; 390 else if (start > rle->end) 391 adjstart = rle->end; 392 else 393 adjstart = start; 394 395 if (end < rle->start) 396 adjend = rle->start; 397 else if (end > rle->end) 398 adjend = rle->end; 399 else 400 adjend = end; 401 402 adjcount = adjend - adjstart; 403 404 rm = &sc->sc_mem_rman; 405 break; 406 case SYS_RES_IRQ: 407 return (resource_list_alloc(&dinfo->resources, bus, child, 408 type, rid, start, end, count, flags)); 409 default: 410 device_printf(bus, "unknown resource request from %s\n", 411 device_get_nameunit(child)); 412 return (NULL); 413 } 414 415 rv = rman_reserve_resource(rm, adjstart, adjend, adjcount, flags, 416 child); 417 if (rv == NULL) { 418 device_printf(bus, 419 "failed to reserve resource %#lx - %#lx (%#lx)" 420 " for %s\n", adjstart, adjend, adjcount, 421 device_get_nameunit(child)); 422 return (NULL); 423 } 424 425 rman_set_rid(rv, *rid); 426 427 if (needactivate) { 428 if (bus_activate_resource(child, type, *rid, rv) != 0) { 429 device_printf(bus, 430 "failed to activate resource for %s\n", 431 device_get_nameunit(child)); 432 rman_release_resource(rv); 433 return (NULL); 434 } 435 } 436 437 return (rv); 438 } 439 440 static int 441 ps3bus_activate_resource(device_t bus, device_t child, int type, int rid, 442 struct resource *res) 443 { 444 void *p; 445 446 if (type == SYS_RES_IRQ) 447 return (bus_activate_resource(bus, type, rid, res)); 448 449 if (type == SYS_RES_MEMORY) { 450 vm_offset_t start; 451 452 start = (vm_offset_t) rman_get_start(res); 453 454 if (bootverbose) 455 printf("ps3 mapdev: start %zx, len %ld\n", start, 456 rman_get_size(res)); 457 458 p = pmap_mapdev(start, (vm_size_t) rman_get_size(res)); 459 if (p == NULL) 460 return (ENOMEM); 461 rman_set_virtual(res, p); 462 rman_set_bustag(res, &bs_be_tag); 463 rman_set_bushandle(res, (u_long)p); 464 } 465 466 return (rman_activate_resource(res)); 467 } 468 469 static bus_dma_tag_t 470 ps3bus_get_dma_tag(device_t dev, device_t child) 471 { 472 struct ps3bus_devinfo *dinfo = device_get_ivars(child); 473 struct ps3bus_softc *sc = device_get_softc(dev); 474 int i, err, flags; 475 476 if (dinfo->bustype != PS3_BUSTYPE_SYSBUS) 477 return (bus_get_dma_tag(dev)); 478 479 mtx_lock(&dinfo->iommu_mtx); 480 if (dinfo->dma_tag != NULL) { 481 mtx_unlock(&dinfo->iommu_mtx); 482 return (dinfo->dma_tag); 483 } 484 485 flags = 0; /* 32-bit mode */ 486 if (dinfo->bustype == PS3_BUSTYPE_SYSBUS && 487 dinfo->devtype == PS3_DEVTYPE_USB) 488 flags = 2; /* 8-bit mode */ 489 490 for (i = 0; i < sc->rcount; i++) { 491 err = lv1_allocate_device_dma_region(dinfo->bus, dinfo->dev, 492 sc->regions[i].mr_size, 24 /* log_2(16 MB) */, flags, 493 &dinfo->dma_base[i]); 494 if (err != 0) { 495 device_printf(child, 496 "could not allocate DMA region %d: %d\n", i, err); 497 goto fail; 498 } 499 500 err = lv1_map_device_dma_region(dinfo->bus, dinfo->dev, 501 sc->regions[i].mr_start, dinfo->dma_base[i], 502 sc->regions[i].mr_size, 503 0xf800000000000800UL /* Cell Handbook Figure 7.3.4.1 */); 504 if (err != 0) { 505 device_printf(child, 506 "could not map DMA region %d: %d\n", i, err); 507 goto fail; 508 } 509 } 510 511 err = bus_dma_tag_create(bus_get_dma_tag(dev), 512 1, 0, BUS_SPACE_MAXADDR, BUS_SPACE_MAXADDR, 513 NULL, NULL, BUS_SPACE_MAXSIZE, 0, BUS_SPACE_MAXSIZE, 514 0, NULL, NULL, &dinfo->dma_tag); 515 516 bus_dma_tag_set_iommu(dinfo->dma_tag, dev, dinfo); 517 518 fail: 519 mtx_unlock(&dinfo->iommu_mtx); 520 521 if (err) 522 return (NULL); 523 524 return (dinfo->dma_tag); 525 } 526 527 static int 528 ps3_iommu_map(device_t dev, bus_dma_segment_t *segs, int *nsegs, 529 bus_addr_t min, bus_addr_t max, bus_size_t alignment, bus_size_t boundary, 530 void *cookie) 531 { 532 struct ps3bus_devinfo *dinfo = cookie; 533 struct ps3bus_softc *sc = device_get_softc(dev); 534 int i, j; 535 536 for (i = 0; i < *nsegs; i++) { 537 for (j = 0; j < sc->rcount; j++) { 538 if (segs[i].ds_addr >= sc->regions[j].mr_start && 539 segs[i].ds_addr < sc->regions[j].mr_start + 540 sc->regions[j].mr_size) 541 break; 542 } 543 KASSERT(j < sc->rcount, 544 ("Trying to map address %#lx not in physical memory", 545 segs[i].ds_addr)); 546 547 segs[i].ds_addr = dinfo->dma_base[j] + 548 (segs[i].ds_addr - sc->regions[j].mr_start); 549 } 550 551 return (0); 552 } 553 554 555 static int 556 ps3_iommu_unmap(device_t dev, bus_dma_segment_t *segs, int nsegs, void *cookie) 557 { 558 559 return (0); 560 } 561 562