1 // SPDX-License-Identifier: GPL-2.0-only 2 /* 3 * PS3 system bus driver. 4 * 5 * Copyright (C) 2006 Sony Computer Entertainment Inc. 6 * Copyright 2006 Sony Corp. 7 */ 8 9 #include <linux/kernel.h> 10 #include <linux/init.h> 11 #include <linux/export.h> 12 #include <linux/dma-map-ops.h> 13 #include <linux/err.h> 14 #include <linux/slab.h> 15 16 #include <asm/udbg.h> 17 #include <asm/lv1call.h> 18 #include <asm/firmware.h> 19 #include <asm/cell-regs.h> 20 21 #include "platform.h" 22 23 static struct device ps3_system_bus = { 24 .init_name = "ps3_system", 25 }; 26 27 /* FIXME: need device usage counters! */ 28 static struct { 29 struct mutex mutex; 30 int sb_11; /* usb 0 */ 31 int sb_12; /* usb 0 */ 32 int gpu; 33 } usage_hack; 34 35 static int ps3_is_device(struct ps3_system_bus_device *dev, u64 bus_id, 36 u64 dev_id) 37 { 38 return dev->bus_id == bus_id && dev->dev_id == dev_id; 39 } 40 41 static int ps3_open_hv_device_sb(struct ps3_system_bus_device *dev) 42 { 43 int result; 44 45 BUG_ON(!dev->bus_id); 46 mutex_lock(&usage_hack.mutex); 47 48 if (ps3_is_device(dev, 1, 1)) { 49 usage_hack.sb_11++; 50 if (usage_hack.sb_11 > 1) { 51 result = 0; 52 goto done; 53 } 54 } 55 56 if (ps3_is_device(dev, 1, 2)) { 57 usage_hack.sb_12++; 58 if (usage_hack.sb_12 > 1) { 59 result = 0; 60 goto done; 61 } 62 } 63 64 result = lv1_open_device(dev->bus_id, dev->dev_id, 0); 65 66 if (result) { 67 pr_warn("%s:%d: lv1_open_device dev=%u.%u(%s) failed: %s\n", 68 __func__, __LINE__, dev->match_id, dev->match_sub_id, 69 dev_name(&dev->core), ps3_result(result)); 70 result = -EPERM; 71 } 72 73 done: 74 mutex_unlock(&usage_hack.mutex); 75 return result; 76 } 77 78 static int ps3_close_hv_device_sb(struct ps3_system_bus_device *dev) 79 { 80 int result; 81 82 BUG_ON(!dev->bus_id); 83 mutex_lock(&usage_hack.mutex); 84 85 if (ps3_is_device(dev, 1, 1)) { 86 usage_hack.sb_11--; 87 if (usage_hack.sb_11) { 88 result = 0; 89 goto done; 90 } 91 } 92 93 if (ps3_is_device(dev, 1, 2)) { 94 usage_hack.sb_12--; 95 if (usage_hack.sb_12) { 96 result = 0; 97 goto done; 98 } 99 } 100 101 result = lv1_close_device(dev->bus_id, dev->dev_id); 102 BUG_ON(result); 103 104 done: 105 mutex_unlock(&usage_hack.mutex); 106 return result; 107 } 108 109 static int ps3_open_hv_device_gpu(struct ps3_system_bus_device *dev) 110 { 111 int result; 112 113 mutex_lock(&usage_hack.mutex); 114 115 usage_hack.gpu++; 116 if (usage_hack.gpu > 1) { 117 result = 0; 118 goto done; 119 } 120 121 result = lv1_gpu_open(0); 122 123 if (result) { 124 pr_warn("%s:%d: lv1_gpu_open failed: %s\n", __func__, 125 __LINE__, ps3_result(result)); 126 result = -EPERM; 127 } 128 129 done: 130 mutex_unlock(&usage_hack.mutex); 131 return result; 132 } 133 134 static int ps3_close_hv_device_gpu(struct ps3_system_bus_device *dev) 135 { 136 int result; 137 138 mutex_lock(&usage_hack.mutex); 139 140 usage_hack.gpu--; 141 if (usage_hack.gpu) { 142 result = 0; 143 goto done; 144 } 145 146 result = lv1_gpu_close(); 147 BUG_ON(result); 148 149 done: 150 mutex_unlock(&usage_hack.mutex); 151 return result; 152 } 153 154 int ps3_open_hv_device(struct ps3_system_bus_device *dev) 155 { 156 BUG_ON(!dev); 157 pr_debug("%s:%d: match_id: %u\n", __func__, __LINE__, dev->match_id); 158 159 switch (dev->match_id) { 160 case PS3_MATCH_ID_EHCI: 161 case PS3_MATCH_ID_OHCI: 162 case PS3_MATCH_ID_GELIC: 163 case PS3_MATCH_ID_STOR_DISK: 164 case PS3_MATCH_ID_STOR_ROM: 165 case PS3_MATCH_ID_STOR_FLASH: 166 return ps3_open_hv_device_sb(dev); 167 168 case PS3_MATCH_ID_SOUND: 169 case PS3_MATCH_ID_GPU: 170 return ps3_open_hv_device_gpu(dev); 171 172 case PS3_MATCH_ID_AV_SETTINGS: 173 case PS3_MATCH_ID_SYSTEM_MANAGER: 174 pr_debug("%s:%d: unsupported match_id: %u\n", __func__, 175 __LINE__, dev->match_id); 176 pr_debug("%s:%d: bus_id: %llu\n", __func__, __LINE__, 177 dev->bus_id); 178 BUG(); 179 return -EINVAL; 180 181 default: 182 break; 183 } 184 185 pr_debug("%s:%d: unknown match_id: %u\n", __func__, __LINE__, 186 dev->match_id); 187 BUG(); 188 return -ENODEV; 189 } 190 EXPORT_SYMBOL_GPL(ps3_open_hv_device); 191 192 int ps3_close_hv_device(struct ps3_system_bus_device *dev) 193 { 194 BUG_ON(!dev); 195 pr_debug("%s:%d: match_id: %u\n", __func__, __LINE__, dev->match_id); 196 197 switch (dev->match_id) { 198 case PS3_MATCH_ID_EHCI: 199 case PS3_MATCH_ID_OHCI: 200 case PS3_MATCH_ID_GELIC: 201 case PS3_MATCH_ID_STOR_DISK: 202 case PS3_MATCH_ID_STOR_ROM: 203 case PS3_MATCH_ID_STOR_FLASH: 204 return ps3_close_hv_device_sb(dev); 205 206 case PS3_MATCH_ID_SOUND: 207 case PS3_MATCH_ID_GPU: 208 return ps3_close_hv_device_gpu(dev); 209 210 case PS3_MATCH_ID_AV_SETTINGS: 211 case PS3_MATCH_ID_SYSTEM_MANAGER: 212 pr_debug("%s:%d: unsupported match_id: %u\n", __func__, 213 __LINE__, dev->match_id); 214 pr_debug("%s:%d: bus_id: %llu\n", __func__, __LINE__, 215 dev->bus_id); 216 BUG(); 217 return -EINVAL; 218 219 default: 220 break; 221 } 222 223 pr_debug("%s:%d: unknown match_id: %u\n", __func__, __LINE__, 224 dev->match_id); 225 BUG(); 226 return -ENODEV; 227 } 228 EXPORT_SYMBOL_GPL(ps3_close_hv_device); 229 230 #define dump_mmio_region(_a) _dump_mmio_region(_a, __func__, __LINE__) 231 static void _dump_mmio_region(const struct ps3_mmio_region* r, 232 const char* func, int line) 233 { 234 pr_debug("%s:%d: dev %llu:%llu\n", func, line, r->dev->bus_id, 235 r->dev->dev_id); 236 pr_debug("%s:%d: bus_addr %lxh\n", func, line, r->bus_addr); 237 pr_debug("%s:%d: len %lxh\n", func, line, r->len); 238 pr_debug("%s:%d: lpar_addr %lxh\n", func, line, r->lpar_addr); 239 } 240 241 static int ps3_sb_mmio_region_create(struct ps3_mmio_region *r) 242 { 243 int result; 244 u64 lpar_addr; 245 246 result = lv1_map_device_mmio_region(r->dev->bus_id, r->dev->dev_id, 247 r->bus_addr, r->len, r->page_size, &lpar_addr); 248 r->lpar_addr = lpar_addr; 249 250 if (result) { 251 pr_debug("%s:%d: lv1_map_device_mmio_region failed: %s\n", 252 __func__, __LINE__, ps3_result(result)); 253 r->lpar_addr = 0; 254 } 255 256 dump_mmio_region(r); 257 return result; 258 } 259 260 static int ps3_ioc0_mmio_region_create(struct ps3_mmio_region *r) 261 { 262 /* device specific; do nothing currently */ 263 return 0; 264 } 265 266 int ps3_mmio_region_create(struct ps3_mmio_region *r) 267 { 268 return r->mmio_ops->create(r); 269 } 270 EXPORT_SYMBOL_GPL(ps3_mmio_region_create); 271 272 static int ps3_sb_free_mmio_region(struct ps3_mmio_region *r) 273 { 274 int result; 275 276 dump_mmio_region(r); 277 result = lv1_unmap_device_mmio_region(r->dev->bus_id, r->dev->dev_id, 278 r->lpar_addr); 279 280 if (result) 281 pr_debug("%s:%d: lv1_unmap_device_mmio_region failed: %s\n", 282 __func__, __LINE__, ps3_result(result)); 283 284 r->lpar_addr = 0; 285 return result; 286 } 287 288 static int ps3_ioc0_free_mmio_region(struct ps3_mmio_region *r) 289 { 290 /* device specific; do nothing currently */ 291 return 0; 292 } 293 294 295 int ps3_free_mmio_region(struct ps3_mmio_region *r) 296 { 297 return r->mmio_ops->free(r); 298 } 299 300 EXPORT_SYMBOL_GPL(ps3_free_mmio_region); 301 302 static const struct ps3_mmio_region_ops ps3_mmio_sb_region_ops = { 303 .create = ps3_sb_mmio_region_create, 304 .free = ps3_sb_free_mmio_region 305 }; 306 307 static const struct ps3_mmio_region_ops ps3_mmio_ioc0_region_ops = { 308 .create = ps3_ioc0_mmio_region_create, 309 .free = ps3_ioc0_free_mmio_region 310 }; 311 312 int ps3_mmio_region_init(struct ps3_system_bus_device *dev, 313 struct ps3_mmio_region *r, unsigned long bus_addr, unsigned long len, 314 enum ps3_mmio_page_size page_size) 315 { 316 r->dev = dev; 317 r->bus_addr = bus_addr; 318 r->len = len; 319 r->page_size = page_size; 320 switch (dev->dev_type) { 321 case PS3_DEVICE_TYPE_SB: 322 r->mmio_ops = &ps3_mmio_sb_region_ops; 323 break; 324 case PS3_DEVICE_TYPE_IOC0: 325 r->mmio_ops = &ps3_mmio_ioc0_region_ops; 326 break; 327 default: 328 BUG(); 329 return -EINVAL; 330 } 331 return 0; 332 } 333 EXPORT_SYMBOL_GPL(ps3_mmio_region_init); 334 335 static int ps3_system_bus_match(struct device *_dev, 336 const struct device_driver *_drv) 337 { 338 int result; 339 const struct ps3_system_bus_driver *drv = ps3_drv_to_system_bus_drv(_drv); 340 struct ps3_system_bus_device *dev = ps3_dev_to_system_bus_dev(_dev); 341 342 if (!dev->match_sub_id) 343 result = dev->match_id == drv->match_id; 344 else 345 result = dev->match_sub_id == drv->match_sub_id && 346 dev->match_id == drv->match_id; 347 348 if (result) 349 pr_info("%s:%d: dev=%u.%u(%s), drv=%u.%u(%s): match\n", 350 __func__, __LINE__, 351 dev->match_id, dev->match_sub_id, dev_name(&dev->core), 352 drv->match_id, drv->match_sub_id, drv->core.name); 353 else 354 pr_debug("%s:%d: dev=%u.%u(%s), drv=%u.%u(%s): miss\n", 355 __func__, __LINE__, 356 dev->match_id, dev->match_sub_id, dev_name(&dev->core), 357 drv->match_id, drv->match_sub_id, drv->core.name); 358 359 return result; 360 } 361 362 static int ps3_system_bus_probe(struct device *_dev) 363 { 364 int result = 0; 365 struct ps3_system_bus_device *dev = ps3_dev_to_system_bus_dev(_dev); 366 struct ps3_system_bus_driver *drv; 367 368 BUG_ON(!dev); 369 dev_dbg(_dev, "%s:%d\n", __func__, __LINE__); 370 371 drv = ps3_system_bus_dev_to_system_bus_drv(dev); 372 BUG_ON(!drv); 373 374 if (drv->probe) 375 result = drv->probe(dev); 376 else 377 pr_debug("%s:%d: %s no probe method\n", __func__, __LINE__, 378 dev_name(&dev->core)); 379 380 pr_debug(" <- %s:%d: %s\n", __func__, __LINE__, dev_name(&dev->core)); 381 return result; 382 } 383 384 static void ps3_system_bus_remove(struct device *_dev) 385 { 386 struct ps3_system_bus_device *dev = ps3_dev_to_system_bus_dev(_dev); 387 struct ps3_system_bus_driver *drv; 388 389 BUG_ON(!dev); 390 dev_dbg(_dev, "%s:%d\n", __func__, __LINE__); 391 392 drv = ps3_system_bus_dev_to_system_bus_drv(dev); 393 BUG_ON(!drv); 394 395 if (drv->remove) 396 drv->remove(dev); 397 else 398 dev_dbg(&dev->core, "%s:%d %s: no remove method\n", 399 __func__, __LINE__, drv->core.name); 400 401 pr_debug(" <- %s:%d: %s\n", __func__, __LINE__, dev_name(&dev->core)); 402 } 403 404 static void ps3_system_bus_shutdown(struct device *_dev) 405 { 406 struct ps3_system_bus_device *dev = ps3_dev_to_system_bus_dev(_dev); 407 struct ps3_system_bus_driver *drv; 408 409 BUG_ON(!dev); 410 411 dev_dbg(&dev->core, " -> %s:%d: match_id %d\n", __func__, __LINE__, 412 dev->match_id); 413 414 if (!dev->core.driver) { 415 dev_dbg(&dev->core, "%s:%d: no driver bound\n", __func__, 416 __LINE__); 417 return; 418 } 419 420 drv = ps3_system_bus_dev_to_system_bus_drv(dev); 421 422 BUG_ON(!drv); 423 424 dev_dbg(&dev->core, "%s:%d: %s -> %s\n", __func__, __LINE__, 425 dev_name(&dev->core), drv->core.name); 426 427 if (drv->shutdown) 428 drv->shutdown(dev); 429 else if (drv->remove) { 430 dev_dbg(&dev->core, "%s:%d %s: no shutdown, calling remove\n", 431 __func__, __LINE__, drv->core.name); 432 drv->remove(dev); 433 } else { 434 dev_dbg(&dev->core, "%s:%d %s: no shutdown method\n", 435 __func__, __LINE__, drv->core.name); 436 BUG(); 437 } 438 439 dev_dbg(&dev->core, " <- %s:%d\n", __func__, __LINE__); 440 } 441 442 static int ps3_system_bus_uevent(const struct device *_dev, struct kobj_uevent_env *env) 443 { 444 struct ps3_system_bus_device *dev = ps3_dev_to_system_bus_dev(_dev); 445 446 if (add_uevent_var(env, "MODALIAS=ps3:%d:%d", dev->match_id, 447 dev->match_sub_id)) 448 return -ENOMEM; 449 return 0; 450 } 451 452 static ssize_t modalias_show(struct device *_dev, struct device_attribute *a, 453 char *buf) 454 { 455 struct ps3_system_bus_device *dev = ps3_dev_to_system_bus_dev(_dev); 456 int len = snprintf(buf, PAGE_SIZE, "ps3:%d:%d\n", dev->match_id, 457 dev->match_sub_id); 458 459 return (len >= PAGE_SIZE) ? (PAGE_SIZE - 1) : len; 460 } 461 static DEVICE_ATTR_RO(modalias); 462 463 static struct attribute *ps3_system_bus_dev_attrs[] = { 464 &dev_attr_modalias.attr, 465 NULL, 466 }; 467 ATTRIBUTE_GROUPS(ps3_system_bus_dev); 468 469 static struct bus_type ps3_system_bus_type = { 470 .name = "ps3_system_bus", 471 .match = ps3_system_bus_match, 472 .uevent = ps3_system_bus_uevent, 473 .probe = ps3_system_bus_probe, 474 .remove = ps3_system_bus_remove, 475 .shutdown = ps3_system_bus_shutdown, 476 .dev_groups = ps3_system_bus_dev_groups, 477 }; 478 479 static int __init ps3_system_bus_init(void) 480 { 481 int result; 482 483 if (!firmware_has_feature(FW_FEATURE_PS3_LV1)) 484 return -ENODEV; 485 486 pr_debug(" -> %s:%d\n", __func__, __LINE__); 487 488 mutex_init(&usage_hack.mutex); 489 490 result = device_register(&ps3_system_bus); 491 BUG_ON(result); 492 493 result = bus_register(&ps3_system_bus_type); 494 BUG_ON(result); 495 496 pr_debug(" <- %s:%d\n", __func__, __LINE__); 497 return result; 498 } 499 500 core_initcall(ps3_system_bus_init); 501 502 /* Allocates a contiguous real buffer and creates mappings over it. 503 * Returns the virtual address of the buffer and sets dma_handle 504 * to the dma address (mapping) of the first page. 505 */ 506 static void * ps3_alloc_coherent(struct device *_dev, size_t size, 507 dma_addr_t *dma_handle, gfp_t flag, 508 unsigned long attrs) 509 { 510 int result; 511 struct ps3_system_bus_device *dev = ps3_dev_to_system_bus_dev(_dev); 512 unsigned long virt_addr; 513 514 flag &= ~(__GFP_DMA | __GFP_HIGHMEM); 515 flag |= __GFP_ZERO; 516 517 virt_addr = __get_free_pages(flag, get_order(size)); 518 519 if (!virt_addr) { 520 pr_debug("%s:%d: get_free_pages failed\n", __func__, __LINE__); 521 goto clean_none; 522 } 523 524 result = ps3_dma_map(dev->d_region, virt_addr, size, dma_handle, 525 CBE_IOPTE_PP_W | CBE_IOPTE_PP_R | 526 CBE_IOPTE_SO_RW | CBE_IOPTE_M); 527 528 if (result) { 529 pr_debug("%s:%d: ps3_dma_map failed (%d)\n", 530 __func__, __LINE__, result); 531 BUG_ON("check region type"); 532 goto clean_alloc; 533 } 534 535 return (void*)virt_addr; 536 537 clean_alloc: 538 free_pages(virt_addr, get_order(size)); 539 clean_none: 540 dma_handle = NULL; 541 return NULL; 542 } 543 544 static void ps3_free_coherent(struct device *_dev, size_t size, void *vaddr, 545 dma_addr_t dma_handle, unsigned long attrs) 546 { 547 struct ps3_system_bus_device *dev = ps3_dev_to_system_bus_dev(_dev); 548 549 ps3_dma_unmap(dev->d_region, dma_handle, size); 550 free_pages((unsigned long)vaddr, get_order(size)); 551 } 552 553 /* Creates TCEs for a user provided buffer. The user buffer must be 554 * contiguous real kernel storage (not vmalloc). The address passed here 555 * comprises a page address and offset into that page. The dma_addr_t 556 * returned will point to the same byte within the page as was passed in. 557 */ 558 559 static dma_addr_t ps3_sb_map_page(struct device *_dev, struct page *page, 560 unsigned long offset, size_t size, enum dma_data_direction direction, 561 unsigned long attrs) 562 { 563 struct ps3_system_bus_device *dev = ps3_dev_to_system_bus_dev(_dev); 564 int result; 565 dma_addr_t bus_addr; 566 void *ptr = page_address(page) + offset; 567 568 result = ps3_dma_map(dev->d_region, (unsigned long)ptr, size, 569 &bus_addr, 570 CBE_IOPTE_PP_R | CBE_IOPTE_PP_W | 571 CBE_IOPTE_SO_RW | CBE_IOPTE_M); 572 573 if (result) { 574 pr_debug("%s:%d: ps3_dma_map failed (%d)\n", 575 __func__, __LINE__, result); 576 } 577 578 return bus_addr; 579 } 580 581 static dma_addr_t ps3_ioc0_map_page(struct device *_dev, struct page *page, 582 unsigned long offset, size_t size, 583 enum dma_data_direction direction, 584 unsigned long attrs) 585 { 586 struct ps3_system_bus_device *dev = ps3_dev_to_system_bus_dev(_dev); 587 int result; 588 dma_addr_t bus_addr; 589 u64 iopte_flag; 590 void *ptr = page_address(page) + offset; 591 592 iopte_flag = CBE_IOPTE_M; 593 switch (direction) { 594 case DMA_BIDIRECTIONAL: 595 iopte_flag |= CBE_IOPTE_PP_R | CBE_IOPTE_PP_W | CBE_IOPTE_SO_RW; 596 break; 597 case DMA_TO_DEVICE: 598 iopte_flag |= CBE_IOPTE_PP_R | CBE_IOPTE_SO_R; 599 break; 600 case DMA_FROM_DEVICE: 601 iopte_flag |= CBE_IOPTE_PP_W | CBE_IOPTE_SO_RW; 602 break; 603 default: 604 /* not happened */ 605 BUG(); 606 } 607 result = ps3_dma_map(dev->d_region, (unsigned long)ptr, size, 608 &bus_addr, iopte_flag); 609 610 if (result) { 611 pr_debug("%s:%d: ps3_dma_map failed (%d)\n", 612 __func__, __LINE__, result); 613 } 614 return bus_addr; 615 } 616 617 static void ps3_unmap_page(struct device *_dev, dma_addr_t dma_addr, 618 size_t size, enum dma_data_direction direction, unsigned long attrs) 619 { 620 struct ps3_system_bus_device *dev = ps3_dev_to_system_bus_dev(_dev); 621 int result; 622 623 result = ps3_dma_unmap(dev->d_region, dma_addr, size); 624 625 if (result) { 626 pr_debug("%s:%d: ps3_dma_unmap failed (%d)\n", 627 __func__, __LINE__, result); 628 } 629 } 630 631 static int ps3_sb_map_sg(struct device *_dev, struct scatterlist *sgl, 632 int nents, enum dma_data_direction direction, unsigned long attrs) 633 { 634 #if defined(CONFIG_PS3_DYNAMIC_DMA) 635 BUG_ON("do"); 636 return -EPERM; 637 #else 638 struct ps3_system_bus_device *dev = ps3_dev_to_system_bus_dev(_dev); 639 struct scatterlist *sg; 640 int i; 641 642 for_each_sg(sgl, sg, nents, i) { 643 int result = ps3_dma_map(dev->d_region, sg_phys(sg), 644 sg->length, &sg->dma_address, 0); 645 646 if (result) { 647 pr_debug("%s:%d: ps3_dma_map failed (%d)\n", 648 __func__, __LINE__, result); 649 return -EINVAL; 650 } 651 652 sg->dma_length = sg->length; 653 } 654 655 return nents; 656 #endif 657 } 658 659 static int ps3_ioc0_map_sg(struct device *_dev, struct scatterlist *sg, 660 int nents, 661 enum dma_data_direction direction, 662 unsigned long attrs) 663 { 664 BUG(); 665 return -EINVAL; 666 } 667 668 static void ps3_sb_unmap_sg(struct device *_dev, struct scatterlist *sg, 669 int nents, enum dma_data_direction direction, unsigned long attrs) 670 { 671 #if defined(CONFIG_PS3_DYNAMIC_DMA) 672 BUG_ON("do"); 673 #endif 674 } 675 676 static void ps3_ioc0_unmap_sg(struct device *_dev, struct scatterlist *sg, 677 int nents, enum dma_data_direction direction, 678 unsigned long attrs) 679 { 680 BUG(); 681 } 682 683 static int ps3_dma_supported(struct device *_dev, u64 mask) 684 { 685 return mask >= DMA_BIT_MASK(32); 686 } 687 688 static const struct dma_map_ops ps3_sb_dma_ops = { 689 .alloc = ps3_alloc_coherent, 690 .free = ps3_free_coherent, 691 .map_sg = ps3_sb_map_sg, 692 .unmap_sg = ps3_sb_unmap_sg, 693 .dma_supported = ps3_dma_supported, 694 .map_page = ps3_sb_map_page, 695 .unmap_page = ps3_unmap_page, 696 .mmap = dma_common_mmap, 697 .get_sgtable = dma_common_get_sgtable, 698 .alloc_pages_op = dma_common_alloc_pages, 699 .free_pages = dma_common_free_pages, 700 }; 701 702 static const struct dma_map_ops ps3_ioc0_dma_ops = { 703 .alloc = ps3_alloc_coherent, 704 .free = ps3_free_coherent, 705 .map_sg = ps3_ioc0_map_sg, 706 .unmap_sg = ps3_ioc0_unmap_sg, 707 .dma_supported = ps3_dma_supported, 708 .map_page = ps3_ioc0_map_page, 709 .unmap_page = ps3_unmap_page, 710 .mmap = dma_common_mmap, 711 .get_sgtable = dma_common_get_sgtable, 712 .alloc_pages_op = dma_common_alloc_pages, 713 .free_pages = dma_common_free_pages, 714 }; 715 716 /** 717 * ps3_system_bus_release_device - remove a device from the system bus 718 */ 719 720 static void ps3_system_bus_release_device(struct device *_dev) 721 { 722 struct ps3_system_bus_device *dev = ps3_dev_to_system_bus_dev(_dev); 723 kfree(dev); 724 } 725 726 /** 727 * ps3_system_bus_device_register - add a device to the system bus 728 * 729 * ps3_system_bus_device_register() expects the dev object to be allocated 730 * dynamically by the caller. The system bus takes ownership of the dev 731 * object and frees the object in ps3_system_bus_release_device(). 732 */ 733 734 int ps3_system_bus_device_register(struct ps3_system_bus_device *dev) 735 { 736 int result; 737 static unsigned int dev_ioc0_count; 738 static unsigned int dev_sb_count; 739 static unsigned int dev_vuart_count; 740 static unsigned int dev_lpm_count; 741 742 if (!dev->core.parent) 743 dev->core.parent = &ps3_system_bus; 744 dev->core.bus = &ps3_system_bus_type; 745 dev->core.release = ps3_system_bus_release_device; 746 747 switch (dev->dev_type) { 748 case PS3_DEVICE_TYPE_IOC0: 749 dev->core.dma_ops = &ps3_ioc0_dma_ops; 750 dev_set_name(&dev->core, "ioc0_%02x", ++dev_ioc0_count); 751 break; 752 case PS3_DEVICE_TYPE_SB: 753 dev->core.dma_ops = &ps3_sb_dma_ops; 754 dev_set_name(&dev->core, "sb_%02x", ++dev_sb_count); 755 756 break; 757 case PS3_DEVICE_TYPE_VUART: 758 dev_set_name(&dev->core, "vuart_%02x", ++dev_vuart_count); 759 break; 760 case PS3_DEVICE_TYPE_LPM: 761 dev_set_name(&dev->core, "lpm_%02x", ++dev_lpm_count); 762 break; 763 default: 764 BUG(); 765 } 766 767 dev->core.of_node = NULL; 768 set_dev_node(&dev->core, 0); 769 770 pr_debug("%s:%d add %s\n", __func__, __LINE__, dev_name(&dev->core)); 771 772 result = device_register(&dev->core); 773 return result; 774 } 775 776 EXPORT_SYMBOL_GPL(ps3_system_bus_device_register); 777 778 int ps3_system_bus_driver_register(struct ps3_system_bus_driver *drv) 779 { 780 int result; 781 782 pr_debug(" -> %s:%d: %s\n", __func__, __LINE__, drv->core.name); 783 784 if (!firmware_has_feature(FW_FEATURE_PS3_LV1)) 785 return -ENODEV; 786 787 drv->core.bus = &ps3_system_bus_type; 788 789 result = driver_register(&drv->core); 790 pr_debug(" <- %s:%d: %s\n", __func__, __LINE__, drv->core.name); 791 return result; 792 } 793 794 EXPORT_SYMBOL_GPL(ps3_system_bus_driver_register); 795 796 void ps3_system_bus_driver_unregister(struct ps3_system_bus_driver *drv) 797 { 798 pr_debug(" -> %s:%d: %s\n", __func__, __LINE__, drv->core.name); 799 driver_unregister(&drv->core); 800 pr_debug(" <- %s:%d: %s\n", __func__, __LINE__, drv->core.name); 801 } 802 803 EXPORT_SYMBOL_GPL(ps3_system_bus_driver_unregister); 804
Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.