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