cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

system-bus.c (19446B)


      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
     23static struct device ps3_system_bus = {
     24	.init_name = "ps3_system",
     25};
     26
     27/* FIXME: need device usage counters! */
     28static struct {
     29	struct mutex mutex;
     30	int sb_11; /* usb 0 */
     31	int sb_12; /* usb 0 */
     32	int gpu;
     33} usage_hack;
     34
     35static 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
     41static 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
     73done:
     74	mutex_unlock(&usage_hack.mutex);
     75	return result;
     76}
     77
     78static 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
    104done:
    105	mutex_unlock(&usage_hack.mutex);
    106	return result;
    107}
    108
    109static 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
    129done:
    130	mutex_unlock(&usage_hack.mutex);
    131	return result;
    132}
    133
    134static 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
    149done:
    150	mutex_unlock(&usage_hack.mutex);
    151	return result;
    152}
    153
    154int 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}
    190EXPORT_SYMBOL_GPL(ps3_open_hv_device);
    191
    192int 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}
    228EXPORT_SYMBOL_GPL(ps3_close_hv_device);
    229
    230#define dump_mmio_region(_a) _dump_mmio_region(_a, __func__, __LINE__)
    231static 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
    241static 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
    260static int ps3_ioc0_mmio_region_create(struct ps3_mmio_region *r)
    261{
    262	/* device specific; do nothing currently */
    263	return 0;
    264}
    265
    266int ps3_mmio_region_create(struct ps3_mmio_region *r)
    267{
    268	return r->mmio_ops->create(r);
    269}
    270EXPORT_SYMBOL_GPL(ps3_mmio_region_create);
    271
    272static 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
    288static int ps3_ioc0_free_mmio_region(struct ps3_mmio_region *r)
    289{
    290	/* device specific; do nothing currently */
    291	return 0;
    292}
    293
    294
    295int ps3_free_mmio_region(struct ps3_mmio_region *r)
    296{
    297	return r->mmio_ops->free(r);
    298}
    299
    300EXPORT_SYMBOL_GPL(ps3_free_mmio_region);
    301
    302static 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
    307static 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
    312int 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}
    333EXPORT_SYMBOL_GPL(ps3_mmio_region_init);
    334
    335static int ps3_system_bus_match(struct device *_dev,
    336	struct device_driver *_drv)
    337{
    338	int result;
    339	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
    362static 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
    384static 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
    404static 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
    442static int ps3_system_bus_uevent(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
    452static 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}
    461static DEVICE_ATTR_RO(modalias);
    462
    463static struct attribute *ps3_system_bus_dev_attrs[] = {
    464	&dev_attr_modalias.attr,
    465	NULL,
    466};
    467ATTRIBUTE_GROUPS(ps3_system_bus_dev);
    468
    469struct 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
    479static 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
    500core_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 */
    506static 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
    537clean_alloc:
    538	free_pages(virt_addr, get_order(size));
    539clean_none:
    540	dma_handle = NULL;
    541	return NULL;
    542}
    543
    544static 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
    559static 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
    581static 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
    617static 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
    631static 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
    659static 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
    668static 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
    676static 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
    683static int ps3_dma_supported(struct device *_dev, u64 mask)
    684{
    685	return mask >= DMA_BIT_MASK(32);
    686}
    687
    688static 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 = dma_common_alloc_pages,
    699	.free_pages = dma_common_free_pages,
    700};
    701
    702static 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 = 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
    720static 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
    734int 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
    776EXPORT_SYMBOL_GPL(ps3_system_bus_device_register);
    777
    778int 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
    794EXPORT_SYMBOL_GPL(ps3_system_bus_driver_register);
    795
    796void 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
    803EXPORT_SYMBOL_GPL(ps3_system_bus_driver_unregister);