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}
 474static DEVICE_ATTR_RO(modalias);
 475
 476static struct attribute *ps3_system_bus_dev_attrs[] = {
 477        &dev_attr_modalias.attr,
 478        NULL,
 479};
 480ATTRIBUTE_GROUPS(ps3_system_bus_dev);
 481
 482struct bus_type ps3_system_bus_type = {
 483        .name = "ps3_system_bus",
 484        .match = ps3_system_bus_match,
 485        .uevent = ps3_system_bus_uevent,
 486        .probe = ps3_system_bus_probe,
 487        .remove = ps3_system_bus_remove,
 488        .shutdown = ps3_system_bus_shutdown,
 489        .dev_groups = ps3_system_bus_dev_groups,
 490};
 491
 492static int __init ps3_system_bus_init(void)
 493{
 494        int result;
 495
 496        if (!firmware_has_feature(FW_FEATURE_PS3_LV1))
 497                return -ENODEV;
 498
 499        pr_debug(" -> %s:%d\n", __func__, __LINE__);
 500
 501        mutex_init(&usage_hack.mutex);
 502
 503        result = device_register(&ps3_system_bus);
 504        BUG_ON(result);
 505
 506        result = bus_register(&ps3_system_bus_type);
 507        BUG_ON(result);
 508
 509        pr_debug(" <- %s:%d\n", __func__, __LINE__);
 510        return result;
 511}
 512
 513core_initcall(ps3_system_bus_init);
 514
 515/* Allocates a contiguous real buffer and creates mappings over it.
 516 * Returns the virtual address of the buffer and sets dma_handle
 517 * to the dma address (mapping) of the first page.
 518 */
 519static void * ps3_alloc_coherent(struct device *_dev, size_t size,
 520                                 dma_addr_t *dma_handle, gfp_t flag,
 521                                 unsigned long attrs)
 522{
 523        int result;
 524        struct ps3_system_bus_device *dev = ps3_dev_to_system_bus_dev(_dev);
 525        unsigned long virt_addr;
 526
 527        flag &= ~(__GFP_DMA | __GFP_HIGHMEM);
 528        flag |= __GFP_ZERO;
 529
 530        virt_addr = __get_free_pages(flag, get_order(size));
 531
 532        if (!virt_addr) {
 533                pr_debug("%s:%d: get_free_pages failed\n", __func__, __LINE__);
 534                goto clean_none;
 535        }
 536
 537        result = ps3_dma_map(dev->d_region, virt_addr, size, dma_handle,
 538                             CBE_IOPTE_PP_W | CBE_IOPTE_PP_R |
 539                             CBE_IOPTE_SO_RW | CBE_IOPTE_M);
 540
 541        if (result) {
 542                pr_debug("%s:%d: ps3_dma_map failed (%d)\n",
 543                        __func__, __LINE__, result);
 544                BUG_ON("check region type");
 545                goto clean_alloc;
 546        }
 547
 548        return (void*)virt_addr;
 549
 550clean_alloc:
 551        free_pages(virt_addr, get_order(size));
 552clean_none:
 553        dma_handle = NULL;
 554        return NULL;
 555}
 556
 557static void ps3_free_coherent(struct device *_dev, size_t size, void *vaddr,
 558                              dma_addr_t dma_handle, unsigned long attrs)
 559{
 560        struct ps3_system_bus_device *dev = ps3_dev_to_system_bus_dev(_dev);
 561
 562        ps3_dma_unmap(dev->d_region, dma_handle, size);
 563        free_pages((unsigned long)vaddr, get_order(size));
 564}
 565
 566/* Creates TCEs for a user provided buffer.  The user buffer must be
 567 * contiguous real kernel storage (not vmalloc).  The address passed here
 568 * comprises a page address and offset into that page. The dma_addr_t
 569 * returned will point to the same byte within the page as was passed in.
 570 */
 571
 572static dma_addr_t ps3_sb_map_page(struct device *_dev, struct page *page,
 573        unsigned long offset, size_t size, enum dma_data_direction direction,
 574        unsigned long attrs)
 575{
 576        struct ps3_system_bus_device *dev = ps3_dev_to_system_bus_dev(_dev);
 577        int result;
 578        dma_addr_t bus_addr;
 579        void *ptr = page_address(page) + offset;
 580
 581        result = ps3_dma_map(dev->d_region, (unsigned long)ptr, size,
 582                             &bus_addr,
 583                             CBE_IOPTE_PP_R | CBE_IOPTE_PP_W |
 584                             CBE_IOPTE_SO_RW | CBE_IOPTE_M);
 585
 586        if (result) {
 587                pr_debug("%s:%d: ps3_dma_map failed (%d)\n",
 588                        __func__, __LINE__, result);
 589        }
 590
 591        return bus_addr;
 592}
 593
 594static dma_addr_t ps3_ioc0_map_page(struct device *_dev, struct page *page,
 595                                    unsigned long offset, size_t size,
 596                                    enum dma_data_direction direction,
 597                                    unsigned long attrs)
 598{
 599        struct ps3_system_bus_device *dev = ps3_dev_to_system_bus_dev(_dev);
 600        int result;
 601        dma_addr_t bus_addr;
 602        u64 iopte_flag;
 603        void *ptr = page_address(page) + offset;
 604
 605        iopte_flag = CBE_IOPTE_M;
 606        switch (direction) {
 607        case DMA_BIDIRECTIONAL:
 608                iopte_flag |= CBE_IOPTE_PP_R | CBE_IOPTE_PP_W | CBE_IOPTE_SO_RW;
 609                break;
 610        case DMA_TO_DEVICE:
 611                iopte_flag |= CBE_IOPTE_PP_R | CBE_IOPTE_SO_R;
 612                break;
 613        case DMA_FROM_DEVICE:
 614                iopte_flag |= CBE_IOPTE_PP_W | CBE_IOPTE_SO_RW;
 615                break;
 616        default:
 617                /* not happned */
 618                BUG();
 619        };
 620        result = ps3_dma_map(dev->d_region, (unsigned long)ptr, size,
 621                             &bus_addr, iopte_flag);
 622
 623        if (result) {
 624                pr_debug("%s:%d: ps3_dma_map failed (%d)\n",
 625                        __func__, __LINE__, result);
 626        }
 627        return bus_addr;
 628}
 629
 630static void ps3_unmap_page(struct device *_dev, dma_addr_t dma_addr,
 631        size_t size, enum dma_data_direction direction, unsigned long attrs)
 632{
 633        struct ps3_system_bus_device *dev = ps3_dev_to_system_bus_dev(_dev);
 634        int result;
 635
 636        result = ps3_dma_unmap(dev->d_region, dma_addr, size);
 637
 638        if (result) {
 639                pr_debug("%s:%d: ps3_dma_unmap failed (%d)\n",
 640                        __func__, __LINE__, result);
 641        }
 642}
 643
 644static int ps3_sb_map_sg(struct device *_dev, struct scatterlist *sgl,
 645        int nents, enum dma_data_direction direction, unsigned long attrs)
 646{
 647#if defined(CONFIG_PS3_DYNAMIC_DMA)
 648        BUG_ON("do");
 649        return -EPERM;
 650#else
 651        struct ps3_system_bus_device *dev = ps3_dev_to_system_bus_dev(_dev);
 652        struct scatterlist *sg;
 653        int i;
 654
 655        for_each_sg(sgl, sg, nents, i) {
 656                int result = ps3_dma_map(dev->d_region, sg_phys(sg),
 657                                        sg->length, &sg->dma_address, 0);
 658
 659                if (result) {
 660                        pr_debug("%s:%d: ps3_dma_map failed (%d)\n",
 661                                __func__, __LINE__, result);
 662                        return -EINVAL;
 663                }
 664
 665                sg->dma_length = sg->length;
 666        }
 667
 668        return nents;
 669#endif
 670}
 671
 672static int ps3_ioc0_map_sg(struct device *_dev, struct scatterlist *sg,
 673                           int nents,
 674                           enum dma_data_direction direction,
 675                           unsigned long attrs)
 676{
 677        BUG();
 678        return 0;
 679}
 680
 681static void ps3_sb_unmap_sg(struct device *_dev, struct scatterlist *sg,
 682        int nents, enum dma_data_direction direction, unsigned long attrs)
 683{
 684#if defined(CONFIG_PS3_DYNAMIC_DMA)
 685        BUG_ON("do");
 686#endif
 687}
 688
 689static void ps3_ioc0_unmap_sg(struct device *_dev, struct scatterlist *sg,
 690                            int nents, enum dma_data_direction direction,
 691                            unsigned long attrs)
 692{
 693        BUG();
 694}
 695
 696static int ps3_dma_supported(struct device *_dev, u64 mask)
 697{
 698        return mask >= DMA_BIT_MASK(32);
 699}
 700
 701static u64 ps3_dma_get_required_mask(struct device *_dev)
 702{
 703        return DMA_BIT_MASK(32);
 704}
 705
 706static const struct dma_map_ops ps3_sb_dma_ops = {
 707        .alloc = ps3_alloc_coherent,
 708        .free = ps3_free_coherent,
 709        .map_sg = ps3_sb_map_sg,
 710        .unmap_sg = ps3_sb_unmap_sg,
 711        .dma_supported = ps3_dma_supported,
 712        .get_required_mask = ps3_dma_get_required_mask,
 713        .map_page = ps3_sb_map_page,
 714        .unmap_page = ps3_unmap_page,
 715};
 716
 717static const struct dma_map_ops ps3_ioc0_dma_ops = {
 718        .alloc = ps3_alloc_coherent,
 719        .free = ps3_free_coherent,
 720        .map_sg = ps3_ioc0_map_sg,
 721        .unmap_sg = ps3_ioc0_unmap_sg,
 722        .dma_supported = ps3_dma_supported,
 723        .get_required_mask = ps3_dma_get_required_mask,
 724        .map_page = ps3_ioc0_map_page,
 725        .unmap_page = ps3_unmap_page,
 726};
 727
 728/**
 729 * ps3_system_bus_release_device - remove a device from the system bus
 730 */
 731
 732static void ps3_system_bus_release_device(struct device *_dev)
 733{
 734        struct ps3_system_bus_device *dev = ps3_dev_to_system_bus_dev(_dev);
 735        kfree(dev);
 736}
 737
 738/**
 739 * ps3_system_bus_device_register - add a device to the system bus
 740 *
 741 * ps3_system_bus_device_register() expects the dev object to be allocated
 742 * dynamically by the caller.  The system bus takes ownership of the dev
 743 * object and frees the object in ps3_system_bus_release_device().
 744 */
 745
 746int ps3_system_bus_device_register(struct ps3_system_bus_device *dev)
 747{
 748        int result;
 749        static unsigned int dev_ioc0_count;
 750        static unsigned int dev_sb_count;
 751        static unsigned int dev_vuart_count;
 752        static unsigned int dev_lpm_count;
 753
 754        if (!dev->core.parent)
 755                dev->core.parent = &ps3_system_bus;
 756        dev->core.bus = &ps3_system_bus_type;
 757        dev->core.release = ps3_system_bus_release_device;
 758
 759        switch (dev->dev_type) {
 760        case PS3_DEVICE_TYPE_IOC0:
 761                dev->core.dma_ops = &ps3_ioc0_dma_ops;
 762                dev_set_name(&dev->core, "ioc0_%02x", ++dev_ioc0_count);
 763                break;
 764        case PS3_DEVICE_TYPE_SB:
 765                dev->core.dma_ops = &ps3_sb_dma_ops;
 766                dev_set_name(&dev->core, "sb_%02x", ++dev_sb_count);
 767
 768                break;
 769        case PS3_DEVICE_TYPE_VUART:
 770                dev_set_name(&dev->core, "vuart_%02x", ++dev_vuart_count);
 771                break;
 772        case PS3_DEVICE_TYPE_LPM:
 773                dev_set_name(&dev->core, "lpm_%02x", ++dev_lpm_count);
 774                break;
 775        default:
 776                BUG();
 777        };
 778
 779        dev->core.of_node = NULL;
 780        set_dev_node(&dev->core, 0);
 781
 782        pr_debug("%s:%d add %s\n", __func__, __LINE__, dev_name(&dev->core));
 783
 784        result = device_register(&dev->core);
 785        return result;
 786}
 787
 788EXPORT_SYMBOL_GPL(ps3_system_bus_device_register);
 789
 790int ps3_system_bus_driver_register(struct ps3_system_bus_driver *drv)
 791{
 792        int result;
 793
 794        pr_debug(" -> %s:%d: %s\n", __func__, __LINE__, drv->core.name);
 795
 796        if (!firmware_has_feature(FW_FEATURE_PS3_LV1))
 797                return -ENODEV;
 798
 799        drv->core.bus = &ps3_system_bus_type;
 800
 801        result = driver_register(&drv->core);
 802        pr_debug(" <- %s:%d: %s\n", __func__, __LINE__, drv->core.name);
 803        return result;
 804}
 805
 806EXPORT_SYMBOL_GPL(ps3_system_bus_driver_register);
 807
 808void ps3_system_bus_driver_unregister(struct ps3_system_bus_driver *drv)
 809{
 810        pr_debug(" -> %s:%d: %s\n", __func__, __LINE__, drv->core.name);
 811        driver_unregister(&drv->core);
 812        pr_debug(" <- %s:%d: %s\n", __func__, __LINE__, drv->core.name);
 813}
 814
 815EXPORT_SYMBOL_GPL(ps3_system_bus_driver_unregister);
 816