Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
awilliam
GitHub Repository: awilliam/linux-vfio
Path: blob/master/arch/powerpc/platforms/ps3/system-bus.c
10818 views
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/module.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
35
static struct device ps3_system_bus = {
36
.init_name = "ps3_system",
37
};
38
39
/* FIXME: need device usage counters! */
40
struct {
41
struct mutex mutex;
42
int sb_11; /* usb 0 */
43
int sb_12; /* usb 0 */
44
int gpu;
45
} static usage_hack;
46
47
static 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
53
static 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
84
done:
85
mutex_unlock(&usage_hack.mutex);
86
return result;
87
}
88
89
static 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
115
done:
116
mutex_unlock(&usage_hack.mutex);
117
return result;
118
}
119
120
static 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
140
done:
141
mutex_unlock(&usage_hack.mutex);
142
return result;
143
}
144
145
static 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
160
done:
161
mutex_unlock(&usage_hack.mutex);
162
return result;
163
}
164
165
int 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
}
201
EXPORT_SYMBOL_GPL(ps3_open_hv_device);
202
203
int 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
}
239
EXPORT_SYMBOL_GPL(ps3_close_hv_device);
240
241
#define dump_mmio_region(_a) _dump_mmio_region(_a, __func__, __LINE__)
242
static 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
252
static 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
271
static int ps3_ioc0_mmio_region_create(struct ps3_mmio_region *r)
272
{
273
/* device specific; do nothing currently */
274
return 0;
275
}
276
277
int ps3_mmio_region_create(struct ps3_mmio_region *r)
278
{
279
return r->mmio_ops->create(r);
280
}
281
EXPORT_SYMBOL_GPL(ps3_mmio_region_create);
282
283
static 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
299
static int ps3_ioc0_free_mmio_region(struct ps3_mmio_region *r)
300
{
301
/* device specific; do nothing currently */
302
return 0;
303
}
304
305
306
int ps3_free_mmio_region(struct ps3_mmio_region *r)
307
{
308
return r->mmio_ops->free(r);
309
}
310
311
EXPORT_SYMBOL_GPL(ps3_free_mmio_region);
312
313
static 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
318
static 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
323
int 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
}
344
EXPORT_SYMBOL_GPL(ps3_mmio_region_init);
345
346
static 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
373
static 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
395
static 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
417
static 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
455
static 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
465
static 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
475
static struct device_attribute ps3_system_bus_dev_attrs[] = {
476
__ATTR_RO(modalias),
477
__ATTR_NULL,
478
};
479
480
struct 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
490
static 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
511
core_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
*/
517
static void * ps3_alloc_coherent(struct device *_dev, size_t size,
518
dma_addr_t *dma_handle, gfp_t flag)
519
{
520
int result;
521
struct ps3_system_bus_device *dev = ps3_dev_to_system_bus_dev(_dev);
522
unsigned long virt_addr;
523
524
flag &= ~(__GFP_DMA | __GFP_HIGHMEM);
525
flag |= __GFP_ZERO;
526
527
virt_addr = __get_free_pages(flag, get_order(size));
528
529
if (!virt_addr) {
530
pr_debug("%s:%d: get_free_pages failed\n", __func__, __LINE__);
531
goto clean_none;
532
}
533
534
result = ps3_dma_map(dev->d_region, virt_addr, size, dma_handle,
535
CBE_IOPTE_PP_W | CBE_IOPTE_PP_R |
536
CBE_IOPTE_SO_RW | CBE_IOPTE_M);
537
538
if (result) {
539
pr_debug("%s:%d: ps3_dma_map failed (%d)\n",
540
__func__, __LINE__, result);
541
BUG_ON("check region type");
542
goto clean_alloc;
543
}
544
545
return (void*)virt_addr;
546
547
clean_alloc:
548
free_pages(virt_addr, get_order(size));
549
clean_none:
550
dma_handle = NULL;
551
return NULL;
552
}
553
554
static void ps3_free_coherent(struct device *_dev, size_t size, void *vaddr,
555
dma_addr_t dma_handle)
556
{
557
struct ps3_system_bus_device *dev = ps3_dev_to_system_bus_dev(_dev);
558
559
ps3_dma_unmap(dev->d_region, dma_handle, size);
560
free_pages((unsigned long)vaddr, get_order(size));
561
}
562
563
/* Creates TCEs for a user provided buffer. The user buffer must be
564
* contiguous real kernel storage (not vmalloc). The address passed here
565
* comprises a page address and offset into that page. The dma_addr_t
566
* returned will point to the same byte within the page as was passed in.
567
*/
568
569
static dma_addr_t ps3_sb_map_page(struct device *_dev, struct page *page,
570
unsigned long offset, size_t size, enum dma_data_direction direction,
571
struct dma_attrs *attrs)
572
{
573
struct ps3_system_bus_device *dev = ps3_dev_to_system_bus_dev(_dev);
574
int result;
575
dma_addr_t bus_addr;
576
void *ptr = page_address(page) + offset;
577
578
result = ps3_dma_map(dev->d_region, (unsigned long)ptr, size,
579
&bus_addr,
580
CBE_IOPTE_PP_R | CBE_IOPTE_PP_W |
581
CBE_IOPTE_SO_RW | CBE_IOPTE_M);
582
583
if (result) {
584
pr_debug("%s:%d: ps3_dma_map failed (%d)\n",
585
__func__, __LINE__, result);
586
}
587
588
return bus_addr;
589
}
590
591
static dma_addr_t ps3_ioc0_map_page(struct device *_dev, struct page *page,
592
unsigned long offset, size_t size,
593
enum dma_data_direction direction,
594
struct dma_attrs *attrs)
595
{
596
struct ps3_system_bus_device *dev = ps3_dev_to_system_bus_dev(_dev);
597
int result;
598
dma_addr_t bus_addr;
599
u64 iopte_flag;
600
void *ptr = page_address(page) + offset;
601
602
iopte_flag = CBE_IOPTE_M;
603
switch (direction) {
604
case DMA_BIDIRECTIONAL:
605
iopte_flag |= CBE_IOPTE_PP_R | CBE_IOPTE_PP_W | CBE_IOPTE_SO_RW;
606
break;
607
case DMA_TO_DEVICE:
608
iopte_flag |= CBE_IOPTE_PP_R | CBE_IOPTE_SO_R;
609
break;
610
case DMA_FROM_DEVICE:
611
iopte_flag |= CBE_IOPTE_PP_W | CBE_IOPTE_SO_RW;
612
break;
613
default:
614
/* not happned */
615
BUG();
616
};
617
result = ps3_dma_map(dev->d_region, (unsigned long)ptr, size,
618
&bus_addr, iopte_flag);
619
620
if (result) {
621
pr_debug("%s:%d: ps3_dma_map failed (%d)\n",
622
__func__, __LINE__, result);
623
}
624
return bus_addr;
625
}
626
627
static void ps3_unmap_page(struct device *_dev, dma_addr_t dma_addr,
628
size_t size, enum dma_data_direction direction, struct dma_attrs *attrs)
629
{
630
struct ps3_system_bus_device *dev = ps3_dev_to_system_bus_dev(_dev);
631
int result;
632
633
result = ps3_dma_unmap(dev->d_region, dma_addr, size);
634
635
if (result) {
636
pr_debug("%s:%d: ps3_dma_unmap failed (%d)\n",
637
__func__, __LINE__, result);
638
}
639
}
640
641
static int ps3_sb_map_sg(struct device *_dev, struct scatterlist *sgl,
642
int nents, enum dma_data_direction direction, struct dma_attrs *attrs)
643
{
644
#if defined(CONFIG_PS3_DYNAMIC_DMA)
645
BUG_ON("do");
646
return -EPERM;
647
#else
648
struct ps3_system_bus_device *dev = ps3_dev_to_system_bus_dev(_dev);
649
struct scatterlist *sg;
650
int i;
651
652
for_each_sg(sgl, sg, nents, i) {
653
int result = ps3_dma_map(dev->d_region, sg_phys(sg),
654
sg->length, &sg->dma_address, 0);
655
656
if (result) {
657
pr_debug("%s:%d: ps3_dma_map failed (%d)\n",
658
__func__, __LINE__, result);
659
return -EINVAL;
660
}
661
662
sg->dma_length = sg->length;
663
}
664
665
return nents;
666
#endif
667
}
668
669
static int ps3_ioc0_map_sg(struct device *_dev, struct scatterlist *sg,
670
int nents,
671
enum dma_data_direction direction,
672
struct dma_attrs *attrs)
673
{
674
BUG();
675
return 0;
676
}
677
678
static void ps3_sb_unmap_sg(struct device *_dev, struct scatterlist *sg,
679
int nents, enum dma_data_direction direction, struct dma_attrs *attrs)
680
{
681
#if defined(CONFIG_PS3_DYNAMIC_DMA)
682
BUG_ON("do");
683
#endif
684
}
685
686
static void ps3_ioc0_unmap_sg(struct device *_dev, struct scatterlist *sg,
687
int nents, enum dma_data_direction direction,
688
struct dma_attrs *attrs)
689
{
690
BUG();
691
}
692
693
static int ps3_dma_supported(struct device *_dev, u64 mask)
694
{
695
return mask >= DMA_BIT_MASK(32);
696
}
697
698
static struct dma_map_ops ps3_sb_dma_ops = {
699
.alloc_coherent = ps3_alloc_coherent,
700
.free_coherent = ps3_free_coherent,
701
.map_sg = ps3_sb_map_sg,
702
.unmap_sg = ps3_sb_unmap_sg,
703
.dma_supported = ps3_dma_supported,
704
.map_page = ps3_sb_map_page,
705
.unmap_page = ps3_unmap_page,
706
};
707
708
static struct dma_map_ops ps3_ioc0_dma_ops = {
709
.alloc_coherent = ps3_alloc_coherent,
710
.free_coherent = ps3_free_coherent,
711
.map_sg = ps3_ioc0_map_sg,
712
.unmap_sg = ps3_ioc0_unmap_sg,
713
.dma_supported = ps3_dma_supported,
714
.map_page = ps3_ioc0_map_page,
715
.unmap_page = ps3_unmap_page,
716
};
717
718
/**
719
* ps3_system_bus_release_device - remove a device from the system bus
720
*/
721
722
static void ps3_system_bus_release_device(struct device *_dev)
723
{
724
struct ps3_system_bus_device *dev = ps3_dev_to_system_bus_dev(_dev);
725
kfree(dev);
726
}
727
728
/**
729
* ps3_system_bus_device_register - add a device to the system bus
730
*
731
* ps3_system_bus_device_register() expects the dev object to be allocated
732
* dynamically by the caller. The system bus takes ownership of the dev
733
* object and frees the object in ps3_system_bus_release_device().
734
*/
735
736
int ps3_system_bus_device_register(struct ps3_system_bus_device *dev)
737
{
738
int result;
739
static unsigned int dev_ioc0_count;
740
static unsigned int dev_sb_count;
741
static unsigned int dev_vuart_count;
742
static unsigned int dev_lpm_count;
743
744
if (!dev->core.parent)
745
dev->core.parent = &ps3_system_bus;
746
dev->core.bus = &ps3_system_bus_type;
747
dev->core.release = ps3_system_bus_release_device;
748
749
switch (dev->dev_type) {
750
case PS3_DEVICE_TYPE_IOC0:
751
dev->core.archdata.dma_ops = &ps3_ioc0_dma_ops;
752
dev_set_name(&dev->core, "ioc0_%02x", ++dev_ioc0_count);
753
break;
754
case PS3_DEVICE_TYPE_SB:
755
dev->core.archdata.dma_ops = &ps3_sb_dma_ops;
756
dev_set_name(&dev->core, "sb_%02x", ++dev_sb_count);
757
758
break;
759
case PS3_DEVICE_TYPE_VUART:
760
dev_set_name(&dev->core, "vuart_%02x", ++dev_vuart_count);
761
break;
762
case PS3_DEVICE_TYPE_LPM:
763
dev_set_name(&dev->core, "lpm_%02x", ++dev_lpm_count);
764
break;
765
default:
766
BUG();
767
};
768
769
dev->core.of_node = NULL;
770
set_dev_node(&dev->core, 0);
771
772
pr_debug("%s:%d add %s\n", __func__, __LINE__, dev_name(&dev->core));
773
774
result = device_register(&dev->core);
775
return result;
776
}
777
778
EXPORT_SYMBOL_GPL(ps3_system_bus_device_register);
779
780
int ps3_system_bus_driver_register(struct ps3_system_bus_driver *drv)
781
{
782
int result;
783
784
pr_debug(" -> %s:%d: %s\n", __func__, __LINE__, drv->core.name);
785
786
if (!firmware_has_feature(FW_FEATURE_PS3_LV1))
787
return -ENODEV;
788
789
drv->core.bus = &ps3_system_bus_type;
790
791
result = driver_register(&drv->core);
792
pr_debug(" <- %s:%d: %s\n", __func__, __LINE__, drv->core.name);
793
return result;
794
}
795
796
EXPORT_SYMBOL_GPL(ps3_system_bus_driver_register);
797
798
void ps3_system_bus_driver_unregister(struct ps3_system_bus_driver *drv)
799
{
800
pr_debug(" -> %s:%d: %s\n", __func__, __LINE__, drv->core.name);
801
driver_unregister(&drv->core);
802
pr_debug(" <- %s:%d: %s\n", __func__, __LINE__, drv->core.name);
803
}
804
805
EXPORT_SYMBOL_GPL(ps3_system_bus_driver_unregister);
806
807