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