blob: 4b9e3712e38419e9ae76b1c953293f3ce8c02bdb [file] [log] [blame]
Linus Torvalds1da177e2005-04-16 15:20:36 -07001/*
2 * IBM PowerPC Virtual I/O Infrastructure Support.
3 *
4 * Copyright (c) 2003 IBM Corp.
5 * Dave Engebretsen engebret@us.ibm.com
6 * Santiago Leon santil@us.ibm.com
7 * Hollis Blanchard <hollisb@us.ibm.com>
8 *
9 * This program is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU General Public License
11 * as published by the Free Software Foundation; either version
12 * 2 of the License, or (at your option) any later version.
13 */
14
15#include <linux/init.h>
16#include <linux/console.h>
17#include <linux/version.h>
18#include <linux/module.h>
19#include <linux/kobject.h>
20#include <linux/mm.h>
21#include <linux/dma-mapping.h>
22#include <asm/rtas.h>
23#include <asm/iommu.h>
24#include <asm/dma.h>
25#include <asm/ppcdebug.h>
26#include <asm/vio.h>
27#include <asm/hvcall.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070028
29#define DBGENTER() pr_debug("%s entered\n", __FUNCTION__)
30
31extern struct subsystem devices_subsys; /* needed for vio_find_name() */
32
33static const struct vio_device_id *vio_match_device(
34 const struct vio_device_id *, const struct vio_dev *);
35
36#ifdef CONFIG_PPC_PSERIES
37static struct iommu_table *vio_build_iommu_table(struct vio_dev *);
38static int vio_num_address_cells;
39#endif
Stephen Rothwell3e494c82005-07-12 17:40:17 +100040struct vio_dev vio_bus_device = { /* fake "parent" device */
Stephen Rothwellac5b33c2005-06-21 17:15:54 -070041 .name = vio_bus_device.dev.bus_id,
42 .type = "",
Stephen Rothwellac5b33c2005-06-21 17:15:54 -070043 .dev.bus_id = "vio",
44 .dev.bus = &vio_bus_type,
45};
Linus Torvalds1da177e2005-04-16 15:20:36 -070046
47#ifdef CONFIG_PPC_ISERIES
Linus Torvalds1da177e2005-04-16 15:20:36 -070048
49#define device_is_compatible(a, b) 1
50
51#endif
52
53/* convert from struct device to struct vio_dev and pass to driver.
54 * dev->driver has already been set by generic code because vio_bus_match
55 * succeeded. */
56static int vio_bus_probe(struct device *dev)
57{
58 struct vio_dev *viodev = to_vio_dev(dev);
59 struct vio_driver *viodrv = to_vio_driver(dev->driver);
60 const struct vio_device_id *id;
61 int error = -ENODEV;
62
63 DBGENTER();
64
65 if (!viodrv->probe)
66 return error;
67
68 id = vio_match_device(viodrv->id_table, viodev);
69 if (id) {
70 error = viodrv->probe(viodev, id);
71 }
72
73 return error;
74}
75
76/* convert from struct device to struct vio_dev and pass to driver. */
77static int vio_bus_remove(struct device *dev)
78{
79 struct vio_dev *viodev = to_vio_dev(dev);
80 struct vio_driver *viodrv = to_vio_driver(dev->driver);
81
82 DBGENTER();
83
84 if (viodrv->remove) {
85 return viodrv->remove(viodev);
86 }
87
88 /* driver can't remove */
89 return 1;
90}
91
92/**
93 * vio_register_driver: - Register a new vio driver
94 * @drv: The vio_driver structure to be registered.
95 */
96int vio_register_driver(struct vio_driver *viodrv)
97{
98 printk(KERN_DEBUG "%s: driver %s registering\n", __FUNCTION__,
99 viodrv->name);
100
101 /* fill in 'struct driver' fields */
102 viodrv->driver.name = viodrv->name;
103 viodrv->driver.bus = &vio_bus_type;
104 viodrv->driver.probe = vio_bus_probe;
105 viodrv->driver.remove = vio_bus_remove;
106
107 return driver_register(&viodrv->driver);
108}
109EXPORT_SYMBOL(vio_register_driver);
110
111/**
112 * vio_unregister_driver - Remove registration of vio driver.
113 * @driver: The vio_driver struct to be removed form registration
114 */
115void vio_unregister_driver(struct vio_driver *viodrv)
116{
117 driver_unregister(&viodrv->driver);
118}
119EXPORT_SYMBOL(vio_unregister_driver);
120
121/**
122 * vio_match_device: - Tell if a VIO device has a matching VIO device id structure.
123 * @ids: array of VIO device id structures to search in
124 * @dev: the VIO device structure to match against
125 *
126 * Used by a driver to check whether a VIO device present in the
127 * system is in its list of supported devices. Returns the matching
128 * vio_device_id structure or NULL if there is no match.
129 */
130static const struct vio_device_id * vio_match_device(const struct vio_device_id *ids,
131 const struct vio_dev *dev)
132{
133 DBGENTER();
134
135 while (ids->type) {
136 if ((strncmp(dev->type, ids->type, strlen(ids->type)) == 0) &&
137 device_is_compatible(dev->dev.platform_data, ids->compat))
138 return ids;
139 ids++;
140 }
141 return NULL;
142}
143
Linus Torvalds1da177e2005-04-16 15:20:36 -0700144#ifdef CONFIG_PPC_PSERIES
145static void probe_bus_pseries(void)
146{
147 struct device_node *node_vroot, *of_node;
148
149 node_vroot = find_devices("vdevice");
150 if ((node_vroot == NULL) || (node_vroot->child == NULL))
151 /* this machine doesn't do virtual IO, and that's ok */
152 return;
153
154 vio_num_address_cells = prom_n_addr_cells(node_vroot->child);
155
156 /*
157 * Create struct vio_devices for each virtual device in the device tree.
158 * Drivers will associate with them later.
159 */
160 for (of_node = node_vroot->child; of_node != NULL;
161 of_node = of_node->sibling) {
162 printk(KERN_DEBUG "%s: processing %p\n", __FUNCTION__, of_node);
163 vio_register_device_node(of_node);
164 }
165}
166#endif
167
Linus Torvalds1da177e2005-04-16 15:20:36 -0700168/**
169 * vio_bus_init: - Initialize the virtual IO bus
170 */
Stephen Rothwell3e494c82005-07-12 17:40:17 +1000171int __init vio_bus_init(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700172{
173 int err;
174
175 err = bus_register(&vio_bus_type);
176 if (err) {
177 printk(KERN_ERR "failed to register VIO bus\n");
178 return err;
179 }
180
Stephen Rothwell3e494c82005-07-12 17:40:17 +1000181 /* the fake parent of all vio devices, just to give us
182 * a nice directory
183 */
Stephen Rothwellac5b33c2005-06-21 17:15:54 -0700184 err = device_register(&vio_bus_device.dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700185 if (err) {
Stephen Rothwell3e494c82005-07-12 17:40:17 +1000186 printk(KERN_WARNING "%s: device_register returned %i\n",
187 __FUNCTION__, err);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700188 return err;
189 }
190
Linus Torvalds1da177e2005-04-16 15:20:36 -0700191 return 0;
192}
193
Stephen Rothwell3e494c82005-07-12 17:40:17 +1000194#ifdef CONFIG_PPC_PSERIES
195/**
196 * vio_bus_init_pseries: - Initialize the pSeries virtual IO bus
197 */
198static int __init vio_bus_init_pseries(void)
199{
200 int err;
201
202 err = vio_bus_init();
203 if (err == 0)
204 probe_bus_pseries();
205 return err;
206}
207
208__initcall(vio_bus_init_pseries);
209#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -0700210
211/* vio_dev refcount hit 0 */
212static void __devinit vio_dev_release(struct device *dev)
213{
214 DBGENTER();
215
216#ifdef CONFIG_PPC_PSERIES
217 /* XXX free TCE table */
218 of_node_put(dev->platform_data);
219#endif
220 kfree(to_vio_dev(dev));
221}
222
223#ifdef CONFIG_PPC_PSERIES
Yani Ioannouff381d22005-05-17 06:40:51 -0400224static ssize_t viodev_show_devspec(struct device *dev, struct device_attribute *attr, char *buf)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700225{
226 struct device_node *of_node = dev->platform_data;
227
228 return sprintf(buf, "%s\n", of_node->full_name);
229}
230DEVICE_ATTR(devspec, S_IRUSR | S_IRGRP | S_IROTH, viodev_show_devspec, NULL);
231#endif
232
Yani Ioannouff381d22005-05-17 06:40:51 -0400233static ssize_t viodev_show_name(struct device *dev, struct device_attribute *attr, char *buf)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700234{
235 return sprintf(buf, "%s\n", to_vio_dev(dev)->name);
236}
237DEVICE_ATTR(name, S_IRUSR | S_IRGRP | S_IROTH, viodev_show_name, NULL);
238
Stephen Rothwell3e494c82005-07-12 17:40:17 +1000239struct vio_dev * __devinit vio_register_device_common(
Linus Torvalds1da177e2005-04-16 15:20:36 -0700240 struct vio_dev *viodev, char *name, char *type,
241 uint32_t unit_address, struct iommu_table *iommu_table)
242{
243 DBGENTER();
244
245 viodev->name = name;
246 viodev->type = type;
247 viodev->unit_address = unit_address;
248 viodev->iommu_table = iommu_table;
249 /* init generic 'struct device' fields: */
Stephen Rothwellac5b33c2005-06-21 17:15:54 -0700250 viodev->dev.parent = &vio_bus_device.dev;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700251 viodev->dev.bus = &vio_bus_type;
252 viodev->dev.release = vio_dev_release;
253
254 /* register with generic device framework */
255 if (device_register(&viodev->dev)) {
256 printk(KERN_ERR "%s: failed to register device %s\n",
257 __FUNCTION__, viodev->dev.bus_id);
258 return NULL;
259 }
260 device_create_file(&viodev->dev, &dev_attr_name);
261
262 return viodev;
263}
264
265#ifdef CONFIG_PPC_PSERIES
266/**
267 * vio_register_device_node: - Register a new vio device.
268 * @of_node: The OF node for this device.
269 *
270 * Creates and initializes a vio_dev structure from the data in
271 * of_node (dev.platform_data) and adds it to the list of virtual devices.
272 * Returns a pointer to the created vio_dev or NULL if node has
273 * NULL device_type or compatible fields.
274 */
275struct vio_dev * __devinit vio_register_device_node(struct device_node *of_node)
276{
277 struct vio_dev *viodev;
278 unsigned int *unit_address;
279 unsigned int *irq_p;
280
281 DBGENTER();
282
283 /* we need the 'device_type' property, in order to match with drivers */
284 if ((NULL == of_node->type)) {
285 printk(KERN_WARNING
286 "%s: node %s missing 'device_type'\n", __FUNCTION__,
287 of_node->name ? of_node->name : "<unknown>");
288 return NULL;
289 }
290
291 unit_address = (unsigned int *)get_property(of_node, "reg", NULL);
292 if (!unit_address) {
293 printk(KERN_WARNING "%s: node %s missing 'reg'\n", __FUNCTION__,
294 of_node->name ? of_node->name : "<unknown>");
295 return NULL;
296 }
297
298 /* allocate a vio_dev for this node */
299 viodev = kmalloc(sizeof(struct vio_dev), GFP_KERNEL);
300 if (!viodev) {
301 return NULL;
302 }
303 memset(viodev, 0, sizeof(struct vio_dev));
304
305 viodev->dev.platform_data = of_node_get(of_node);
306
307 viodev->irq = NO_IRQ;
308 irq_p = (unsigned int *)get_property(of_node, "interrupts", NULL);
309 if (irq_p) {
310 int virq = virt_irq_create_mapping(*irq_p);
311 if (virq == NO_IRQ) {
312 printk(KERN_ERR "Unable to allocate interrupt "
313 "number for %s\n", of_node->full_name);
314 } else
315 viodev->irq = irq_offset_up(virq);
316 }
317
318 snprintf(viodev->dev.bus_id, BUS_ID_SIZE, "%x", *unit_address);
319
320 /* register with generic device framework */
321 if (vio_register_device_common(viodev, of_node->name, of_node->type,
322 *unit_address, vio_build_iommu_table(viodev))
323 == NULL) {
324 /* XXX free TCE table */
325 kfree(viodev);
326 return NULL;
327 }
328 device_create_file(&viodev->dev, &dev_attr_devspec);
329
330 return viodev;
331}
332EXPORT_SYMBOL(vio_register_device_node);
333#endif
334
Linus Torvalds1da177e2005-04-16 15:20:36 -0700335void __devinit vio_unregister_device(struct vio_dev *viodev)
336{
337 DBGENTER();
338#ifdef CONFIG_PPC_PSERIES
339 device_remove_file(&viodev->dev, &dev_attr_devspec);
340#endif
341 device_remove_file(&viodev->dev, &dev_attr_name);
342 device_unregister(&viodev->dev);
343}
344EXPORT_SYMBOL(vio_unregister_device);
345
346#ifdef CONFIG_PPC_PSERIES
347/**
348 * vio_get_attribute: - get attribute for virtual device
349 * @vdev: The vio device to get property.
350 * @which: The property/attribute to be extracted.
351 * @length: Pointer to length of returned data size (unused if NULL).
352 *
353 * Calls prom.c's get_property() to return the value of the
354 * attribute specified by the preprocessor constant @which
355*/
356const void * vio_get_attribute(struct vio_dev *vdev, void* which, int* length)
357{
358 return get_property(vdev->dev.platform_data, (char*)which, length);
359}
360EXPORT_SYMBOL(vio_get_attribute);
361
362/* vio_find_name() - internal because only vio.c knows how we formatted the
363 * kobject name
364 * XXX once vio_bus_type.devices is actually used as a kset in
365 * drivers/base/bus.c, this function should be removed in favor of
366 * "device_find(kobj_name, &vio_bus_type)"
367 */
368static struct vio_dev *vio_find_name(const char *kobj_name)
369{
370 struct kobject *found;
371
372 found = kset_find_obj(&devices_subsys.kset, kobj_name);
373 if (!found)
374 return NULL;
375
376 return to_vio_dev(container_of(found, struct device, kobj));
377}
378
379/**
380 * vio_find_node - find an already-registered vio_dev
381 * @vnode: device_node of the virtual device we're looking for
382 */
383struct vio_dev *vio_find_node(struct device_node *vnode)
384{
385 uint32_t *unit_address;
386 char kobj_name[BUS_ID_SIZE];
387
388 /* construct the kobject name from the device node */
389 unit_address = (uint32_t *)get_property(vnode, "reg", NULL);
390 if (!unit_address)
391 return NULL;
392 snprintf(kobj_name, BUS_ID_SIZE, "%x", *unit_address);
393
394 return vio_find_name(kobj_name);
395}
396EXPORT_SYMBOL(vio_find_node);
397
398/**
399 * vio_build_iommu_table: - gets the dma information from OF and builds the TCE tree.
400 * @dev: the virtual device.
401 *
402 * Returns a pointer to the built tce tree, or NULL if it can't
403 * find property.
404*/
405static struct iommu_table * vio_build_iommu_table(struct vio_dev *dev)
406{
407 unsigned int *dma_window;
408 struct iommu_table *newTceTable;
409 unsigned long offset;
410 int dma_window_property_size;
411
412 dma_window = (unsigned int *) get_property(dev->dev.platform_data, "ibm,my-dma-window", &dma_window_property_size);
413 if(!dma_window) {
414 return NULL;
415 }
416
417 newTceTable = (struct iommu_table *) kmalloc(sizeof(struct iommu_table), GFP_KERNEL);
418
419 /* There should be some code to extract the phys-encoded offset
420 using prom_n_addr_cells(). However, according to a comment
421 on earlier versions, it's always zero, so we don't bother */
422 offset = dma_window[1] >> PAGE_SHIFT;
423
424 /* TCE table size - measured in tce entries */
425 newTceTable->it_size = dma_window[4] >> PAGE_SHIFT;
426 /* offset for VIO should always be 0 */
427 newTceTable->it_offset = offset;
428 newTceTable->it_busno = 0;
429 newTceTable->it_index = (unsigned long)dma_window[0];
430 newTceTable->it_type = TCE_VB;
431
432 return iommu_init_table(newTceTable);
433}
434
435int vio_enable_interrupts(struct vio_dev *dev)
436{
437 int rc = h_vio_signal(dev->unit_address, VIO_IRQ_ENABLE);
438 if (rc != H_Success) {
439 printk(KERN_ERR "vio: Error 0x%x enabling interrupts\n", rc);
440 }
441 return rc;
442}
443EXPORT_SYMBOL(vio_enable_interrupts);
444
445int vio_disable_interrupts(struct vio_dev *dev)
446{
447 int rc = h_vio_signal(dev->unit_address, VIO_IRQ_DISABLE);
448 if (rc != H_Success) {
449 printk(KERN_ERR "vio: Error 0x%x disabling interrupts\n", rc);
450 }
451 return rc;
452}
453EXPORT_SYMBOL(vio_disable_interrupts);
454#endif
455
456static dma_addr_t vio_map_single(struct device *dev, void *vaddr,
457 size_t size, enum dma_data_direction direction)
458{
459 return iommu_map_single(to_vio_dev(dev)->iommu_table, vaddr, size,
460 direction);
461}
462
463static void vio_unmap_single(struct device *dev, dma_addr_t dma_handle,
464 size_t size, enum dma_data_direction direction)
465{
466 iommu_unmap_single(to_vio_dev(dev)->iommu_table, dma_handle, size,
467 direction);
468}
469
470static int vio_map_sg(struct device *dev, struct scatterlist *sglist,
471 int nelems, enum dma_data_direction direction)
472{
473 return iommu_map_sg(dev, to_vio_dev(dev)->iommu_table, sglist,
474 nelems, direction);
475}
476
477static void vio_unmap_sg(struct device *dev, struct scatterlist *sglist,
478 int nelems, enum dma_data_direction direction)
479{
480 iommu_unmap_sg(to_vio_dev(dev)->iommu_table, sglist, nelems, direction);
481}
482
483static void *vio_alloc_coherent(struct device *dev, size_t size,
484 dma_addr_t *dma_handle, unsigned int __nocast flag)
485{
486 return iommu_alloc_coherent(to_vio_dev(dev)->iommu_table, size,
487 dma_handle, flag);
488}
489
490static void vio_free_coherent(struct device *dev, size_t size,
491 void *vaddr, dma_addr_t dma_handle)
492{
493 iommu_free_coherent(to_vio_dev(dev)->iommu_table, size, vaddr,
494 dma_handle);
495}
496
497static int vio_dma_supported(struct device *dev, u64 mask)
498{
499 return 1;
500}
501
502struct dma_mapping_ops vio_dma_ops = {
503 .alloc_coherent = vio_alloc_coherent,
504 .free_coherent = vio_free_coherent,
505 .map_single = vio_map_single,
506 .unmap_single = vio_unmap_single,
507 .map_sg = vio_map_sg,
508 .unmap_sg = vio_unmap_sg,
509 .dma_supported = vio_dma_supported,
510};
511
512static int vio_bus_match(struct device *dev, struct device_driver *drv)
513{
514 const struct vio_dev *vio_dev = to_vio_dev(dev);
515 struct vio_driver *vio_drv = to_vio_driver(drv);
516 const struct vio_device_id *ids = vio_drv->id_table;
517 const struct vio_device_id *found_id;
518
519 DBGENTER();
520
521 if (!ids)
522 return 0;
523
524 found_id = vio_match_device(ids, vio_dev);
525 if (found_id)
526 return 1;
527
528 return 0;
529}
530
531struct bus_type vio_bus_type = {
532 .name = "vio",
533 .match = vio_bus_match,
534};