Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
torvalds
GitHub Repository: torvalds/linux
Path: blob/master/arch/powerpc/platforms/pseries/ibmebus.c
51704 views
1
/*
2
* IBM PowerPC IBM eBus Infrastructure Support.
3
*
4
* Copyright (c) 2005 IBM Corporation
5
* Joachim Fenkes <[email protected]>
6
* Heiko J Schick <[email protected]>
7
*
8
* All rights reserved.
9
*
10
* This source code is distributed under a dual license of GPL v2.0 and OpenIB
11
* BSD.
12
*
13
* OpenIB BSD License
14
*
15
* Redistribution and use in source and binary forms, with or without
16
* modification, are permitted provided that the following conditions are met:
17
*
18
* Redistributions of source code must retain the above copyright notice, this
19
* list of conditions and the following disclaimer.
20
*
21
* Redistributions in binary form must reproduce the above copyright notice,
22
* this list of conditions and the following disclaimer in the documentation
23
* and/or other materials
24
* provided with the distribution.
25
*
26
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
27
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
28
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
29
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
30
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
31
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
32
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
33
* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
34
* IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
35
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
36
* POSSIBILITY OF SUCH DAMAGE.
37
*/
38
39
#include <linux/init.h>
40
#include <linux/export.h>
41
#include <linux/console.h>
42
#include <linux/kobject.h>
43
#include <linux/dma-map-ops.h>
44
#include <linux/interrupt.h>
45
#include <linux/irqdomain.h>
46
#include <linux/of.h>
47
#include <linux/slab.h>
48
#include <linux/stat.h>
49
#include <linux/of_platform.h>
50
#include <linux/platform_device.h>
51
#include <asm/ibmebus.h>
52
#include <asm/machdep.h>
53
54
static struct device ibmebus_bus_device = { /* fake "parent" device */
55
.init_name = "ibmebus",
56
};
57
58
const struct bus_type ibmebus_bus_type;
59
60
/* These devices will automatically be added to the bus during init */
61
static const struct of_device_id ibmebus_matches[] __initconst = {
62
{ .compatible = "IBM,lhca" },
63
{ .compatible = "IBM,lhea" },
64
{},
65
};
66
67
static void *ibmebus_alloc_coherent(struct device *dev,
68
size_t size,
69
dma_addr_t *dma_handle,
70
gfp_t flag,
71
unsigned long attrs)
72
{
73
void *mem;
74
75
mem = kmalloc(size, flag);
76
*dma_handle = (dma_addr_t)mem;
77
78
return mem;
79
}
80
81
static void ibmebus_free_coherent(struct device *dev,
82
size_t size, void *vaddr,
83
dma_addr_t dma_handle,
84
unsigned long attrs)
85
{
86
kfree(vaddr);
87
}
88
89
static dma_addr_t ibmebus_map_phys(struct device *dev, phys_addr_t phys,
90
size_t size,
91
enum dma_data_direction direction,
92
unsigned long attrs)
93
{
94
if (attrs & DMA_ATTR_MMIO)
95
return DMA_MAPPING_ERROR;
96
97
return (dma_addr_t)(phys_to_virt(phys));
98
}
99
100
static void ibmebus_unmap_phys(struct device *dev,
101
dma_addr_t dma_addr,
102
size_t size,
103
enum dma_data_direction direction,
104
unsigned long attrs)
105
{
106
return;
107
}
108
109
static int ibmebus_map_sg(struct device *dev,
110
struct scatterlist *sgl,
111
int nents, enum dma_data_direction direction,
112
unsigned long attrs)
113
{
114
struct scatterlist *sg;
115
int i;
116
117
for_each_sg(sgl, sg, nents, i) {
118
sg->dma_address = (dma_addr_t) sg_virt(sg);
119
sg->dma_length = sg->length;
120
}
121
122
return nents;
123
}
124
125
static void ibmebus_unmap_sg(struct device *dev,
126
struct scatterlist *sg,
127
int nents, enum dma_data_direction direction,
128
unsigned long attrs)
129
{
130
return;
131
}
132
133
static int ibmebus_dma_supported(struct device *dev, u64 mask)
134
{
135
return mask == DMA_BIT_MASK(64);
136
}
137
138
static u64 ibmebus_dma_get_required_mask(struct device *dev)
139
{
140
return DMA_BIT_MASK(64);
141
}
142
143
static const struct dma_map_ops ibmebus_dma_ops = {
144
.alloc = ibmebus_alloc_coherent,
145
.free = ibmebus_free_coherent,
146
.map_sg = ibmebus_map_sg,
147
.unmap_sg = ibmebus_unmap_sg,
148
.dma_supported = ibmebus_dma_supported,
149
.get_required_mask = ibmebus_dma_get_required_mask,
150
.map_phys = ibmebus_map_phys,
151
.unmap_phys = ibmebus_unmap_phys,
152
};
153
154
static int ibmebus_match_path(struct device *dev, const void *data)
155
{
156
struct device_node *dn = to_platform_device(dev)->dev.of_node;
157
struct device_node *tn = of_find_node_by_path(data);
158
159
of_node_put(tn);
160
161
return (tn == dn);
162
}
163
164
static int ibmebus_match_node(struct device *dev, const void *data)
165
{
166
return to_platform_device(dev)->dev.of_node == data;
167
}
168
169
static int ibmebus_create_device(struct device_node *dn)
170
{
171
struct platform_device *dev;
172
int ret;
173
174
dev = of_device_alloc(dn, NULL, &ibmebus_bus_device);
175
if (!dev)
176
return -ENOMEM;
177
178
dev->dev.bus = &ibmebus_bus_type;
179
dev->dev.dma_ops = &ibmebus_dma_ops;
180
181
ret = of_device_add(dev);
182
if (ret)
183
platform_device_put(dev);
184
return ret;
185
}
186
187
static int ibmebus_create_devices(const struct of_device_id *matches)
188
{
189
struct device_node *root, *child;
190
struct device *dev;
191
int ret = 0;
192
193
root = of_find_node_by_path("/");
194
195
for_each_child_of_node(root, child) {
196
if (!of_match_node(matches, child))
197
continue;
198
199
dev = bus_find_device(&ibmebus_bus_type, NULL, child,
200
ibmebus_match_node);
201
if (dev) {
202
put_device(dev);
203
continue;
204
}
205
206
ret = ibmebus_create_device(child);
207
if (ret) {
208
printk(KERN_ERR "%s: failed to create device (%i)",
209
__func__, ret);
210
of_node_put(child);
211
break;
212
}
213
}
214
215
of_node_put(root);
216
return ret;
217
}
218
219
int ibmebus_register_driver(struct platform_driver *drv)
220
{
221
/* If the driver uses devices that ibmebus doesn't know, add them */
222
ibmebus_create_devices(drv->driver.of_match_table);
223
224
drv->driver.bus = &ibmebus_bus_type;
225
return driver_register(&drv->driver);
226
}
227
EXPORT_SYMBOL(ibmebus_register_driver);
228
229
void ibmebus_unregister_driver(struct platform_driver *drv)
230
{
231
driver_unregister(&drv->driver);
232
}
233
EXPORT_SYMBOL(ibmebus_unregister_driver);
234
235
int ibmebus_request_irq(u32 ist, irq_handler_t handler,
236
unsigned long irq_flags, const char *devname,
237
void *dev_id)
238
{
239
unsigned int irq = irq_create_mapping(NULL, ist);
240
241
if (!irq)
242
return -EINVAL;
243
244
return request_irq(irq, handler, irq_flags, devname, dev_id);
245
}
246
EXPORT_SYMBOL(ibmebus_request_irq);
247
248
void ibmebus_free_irq(u32 ist, void *dev_id)
249
{
250
unsigned int irq = irq_find_mapping(NULL, ist);
251
252
free_irq(irq, dev_id);
253
irq_dispose_mapping(irq);
254
}
255
EXPORT_SYMBOL(ibmebus_free_irq);
256
257
static char *ibmebus_chomp(const char *in, size_t count)
258
{
259
char *out = kmalloc(count + 1, GFP_KERNEL);
260
261
if (!out)
262
return NULL;
263
264
memcpy(out, in, count);
265
out[count] = '\0';
266
if (out[count - 1] == '\n')
267
out[count - 1] = '\0';
268
269
return out;
270
}
271
272
static ssize_t probe_store(const struct bus_type *bus, const char *buf, size_t count)
273
{
274
struct device_node *dn = NULL;
275
struct device *dev;
276
char *path;
277
ssize_t rc = 0;
278
279
path = ibmebus_chomp(buf, count);
280
if (!path)
281
return -ENOMEM;
282
283
dev = bus_find_device(&ibmebus_bus_type, NULL, path,
284
ibmebus_match_path);
285
if (dev) {
286
put_device(dev);
287
printk(KERN_WARNING "%s: %s has already been probed\n",
288
__func__, path);
289
rc = -EEXIST;
290
goto out;
291
}
292
293
if ((dn = of_find_node_by_path(path))) {
294
rc = ibmebus_create_device(dn);
295
of_node_put(dn);
296
} else {
297
printk(KERN_WARNING "%s: no such device node: %s\n",
298
__func__, path);
299
rc = -ENODEV;
300
}
301
302
out:
303
kfree(path);
304
if (rc)
305
return rc;
306
return count;
307
}
308
static BUS_ATTR_WO(probe);
309
310
static ssize_t remove_store(const struct bus_type *bus, const char *buf, size_t count)
311
{
312
struct device *dev;
313
char *path;
314
315
path = ibmebus_chomp(buf, count);
316
if (!path)
317
return -ENOMEM;
318
319
if ((dev = bus_find_device(&ibmebus_bus_type, NULL, path,
320
ibmebus_match_path))) {
321
of_device_unregister(to_platform_device(dev));
322
put_device(dev);
323
324
kfree(path);
325
return count;
326
} else {
327
printk(KERN_WARNING "%s: %s not on the bus\n",
328
__func__, path);
329
330
kfree(path);
331
return -ENODEV;
332
}
333
}
334
static BUS_ATTR_WO(remove);
335
336
static struct attribute *ibmbus_bus_attrs[] = {
337
&bus_attr_probe.attr,
338
&bus_attr_remove.attr,
339
NULL,
340
};
341
ATTRIBUTE_GROUPS(ibmbus_bus);
342
343
static int ibmebus_bus_bus_match(struct device *dev, const struct device_driver *drv)
344
{
345
const struct of_device_id *matches = drv->of_match_table;
346
347
if (!matches)
348
return 0;
349
350
return of_match_device(matches, dev) != NULL;
351
}
352
353
static int ibmebus_bus_device_probe(struct device *dev)
354
{
355
int error = -ENODEV;
356
struct platform_driver *drv;
357
struct platform_device *of_dev;
358
359
drv = to_platform_driver(dev->driver);
360
of_dev = to_platform_device(dev);
361
362
if (!drv->probe)
363
return error;
364
365
get_device(dev);
366
367
if (of_driver_match_device(dev, dev->driver))
368
error = drv->probe(of_dev);
369
if (error)
370
put_device(dev);
371
372
return error;
373
}
374
375
static void ibmebus_bus_device_remove(struct device *dev)
376
{
377
struct platform_device *of_dev = to_platform_device(dev);
378
struct platform_driver *drv = to_platform_driver(dev->driver);
379
380
if (dev->driver && drv->remove)
381
drv->remove(of_dev);
382
}
383
384
static void ibmebus_bus_device_shutdown(struct device *dev)
385
{
386
struct platform_device *of_dev = to_platform_device(dev);
387
struct platform_driver *drv = to_platform_driver(dev->driver);
388
389
if (dev->driver && drv->shutdown)
390
drv->shutdown(of_dev);
391
}
392
393
/*
394
* ibmebus_bus_device_attrs
395
*/
396
static ssize_t devspec_show(struct device *dev,
397
struct device_attribute *attr, char *buf)
398
{
399
struct platform_device *ofdev;
400
401
ofdev = to_platform_device(dev);
402
return sprintf(buf, "%pOF\n", ofdev->dev.of_node);
403
}
404
static DEVICE_ATTR_RO(devspec);
405
406
static ssize_t name_show(struct device *dev,
407
struct device_attribute *attr, char *buf)
408
{
409
struct platform_device *ofdev;
410
411
ofdev = to_platform_device(dev);
412
return sprintf(buf, "%pOFn\n", ofdev->dev.of_node);
413
}
414
static DEVICE_ATTR_RO(name);
415
416
static ssize_t modalias_show(struct device *dev,
417
struct device_attribute *attr, char *buf)
418
{
419
return of_device_modalias(dev, buf, PAGE_SIZE);
420
}
421
static DEVICE_ATTR_RO(modalias);
422
423
static struct attribute *ibmebus_bus_device_attrs[] = {
424
&dev_attr_devspec.attr,
425
&dev_attr_name.attr,
426
&dev_attr_modalias.attr,
427
NULL,
428
};
429
ATTRIBUTE_GROUPS(ibmebus_bus_device);
430
431
static int ibmebus_bus_modalias(const struct device *dev, struct kobj_uevent_env *env)
432
{
433
return of_device_uevent_modalias(dev, env);
434
}
435
436
const struct bus_type ibmebus_bus_type = {
437
.name = "ibmebus",
438
.uevent = ibmebus_bus_modalias,
439
.bus_groups = ibmbus_bus_groups,
440
.match = ibmebus_bus_bus_match,
441
.probe = ibmebus_bus_device_probe,
442
.remove = ibmebus_bus_device_remove,
443
.shutdown = ibmebus_bus_device_shutdown,
444
.dev_groups = ibmebus_bus_device_groups,
445
};
446
EXPORT_SYMBOL(ibmebus_bus_type);
447
448
static int __init ibmebus_bus_init(void)
449
{
450
int err;
451
452
printk(KERN_INFO "IBM eBus Device Driver\n");
453
454
err = bus_register(&ibmebus_bus_type);
455
if (err) {
456
printk(KERN_ERR "%s: failed to register IBM eBus.\n",
457
__func__);
458
return err;
459
}
460
461
err = device_register(&ibmebus_bus_device);
462
if (err) {
463
printk(KERN_WARNING "%s: device_register returned %i\n",
464
__func__, err);
465
put_device(&ibmebus_bus_device);
466
bus_unregister(&ibmebus_bus_type);
467
468
return err;
469
}
470
471
err = ibmebus_create_devices(ibmebus_matches);
472
if (err) {
473
device_unregister(&ibmebus_bus_device);
474
bus_unregister(&ibmebus_bus_type);
475
return err;
476
}
477
478
return 0;
479
}
480
machine_postcore_initcall(pseries, ibmebus_bus_init);
481
482