1 /* 2 * IBM PowerPC pSeries Virtual I/O Infrastructure Support. 3 * 4 * Copyright (c) 2003-2005 IBM Corp. 5 * Dave Engebretsen engebret@us.ibm.com 6 * Santiago Leon santil@us.ibm.com 7 * Hollis Blanchard <hollisb@us.ibm.com> 8 * Stephen Rothwell 9 * 10 * This program is free software; you can redistribute it and/or 11 * modify it under the terms of the GNU General Public License 12 * as published by the Free Software Foundation; either version 13 * 2 of the License, or (at your option) any later version. 14 */ 15 16 #include <linux/init.h> 17 #include <linux/module.h> 18 #include <linux/mm.h> 19 #include <linux/kobject.h> 20 #include <asm/iommu.h> 21 #include <asm/dma.h> 22 #include <asm/prom.h> 23 #include <asm/vio.h> 24 #include <asm/hvcall.h> 25 #include <asm/tce.h> 26 27 extern struct subsystem devices_subsys; /* needed for vio_find_name() */ 28 29 static void probe_bus_pseries(void) 30 { 31 struct device_node *node_vroot, *of_node; 32 33 node_vroot = find_devices("vdevice"); 34 if ((node_vroot == NULL) || (node_vroot->child == NULL)) 35 /* this machine doesn't do virtual IO, and that's ok */ 36 return; 37 38 /* 39 * Create struct vio_devices for each virtual device in the device tree. 40 * Drivers will associate with them later. 41 */ 42 for (of_node = node_vroot->child; of_node != NULL; 43 of_node = of_node->sibling) { 44 printk(KERN_DEBUG "%s: processing %p\n", __FUNCTION__, of_node); 45 vio_register_device_node(of_node); 46 } 47 } 48 49 /** 50 * vio_match_device_pseries: - Tell if a pSeries VIO device matches a 51 * vio_device_id 52 */ 53 static int vio_match_device_pseries(const struct vio_device_id *id, 54 const struct vio_dev *dev) 55 { 56 return (strncmp(dev->type, id->type, strlen(id->type)) == 0) && 57 device_is_compatible(dev->dev.platform_data, id->compat); 58 } 59 60 static void vio_release_device_pseries(struct device *dev) 61 { 62 /* XXX free TCE table */ 63 of_node_put(dev->platform_data); 64 } 65 66 static ssize_t viodev_show_devspec(struct device *dev, 67 struct device_attribute *attr, char *buf) 68 { 69 struct device_node *of_node = dev->platform_data; 70 71 return sprintf(buf, "%s\n", of_node->full_name); 72 } 73 DEVICE_ATTR(devspec, S_IRUSR | S_IRGRP | S_IROTH, viodev_show_devspec, NULL); 74 75 static void vio_unregister_device_pseries(struct vio_dev *viodev) 76 { 77 device_remove_file(&viodev->dev, &dev_attr_devspec); 78 } 79 80 static struct vio_bus_ops vio_bus_ops_pseries = { 81 .match = vio_match_device_pseries, 82 .unregister_device = vio_unregister_device_pseries, 83 .release_device = vio_release_device_pseries, 84 }; 85 86 /** 87 * vio_bus_init_pseries: - Initialize the pSeries virtual IO bus 88 */ 89 static int __init vio_bus_init_pseries(void) 90 { 91 int err; 92 93 err = vio_bus_init(&vio_bus_ops_pseries); 94 if (err == 0) 95 probe_bus_pseries(); 96 return err; 97 } 98 99 __initcall(vio_bus_init_pseries); 100 101 /** 102 * vio_build_iommu_table: - gets the dma information from OF and 103 * builds the TCE tree. 104 * @dev: the virtual device. 105 * 106 * Returns a pointer to the built tce tree, or NULL if it can't 107 * find property. 108 */ 109 static struct iommu_table *vio_build_iommu_table(struct vio_dev *dev) 110 { 111 unsigned int *dma_window; 112 struct iommu_table *newTceTable; 113 unsigned long offset; 114 int dma_window_property_size; 115 116 dma_window = (unsigned int *) get_property(dev->dev.platform_data, "ibm,my-dma-window", &dma_window_property_size); 117 if(!dma_window) { 118 return NULL; 119 } 120 121 newTceTable = (struct iommu_table *) kmalloc(sizeof(struct iommu_table), GFP_KERNEL); 122 123 /* There should be some code to extract the phys-encoded offset 124 using prom_n_addr_cells(). However, according to a comment 125 on earlier versions, it's always zero, so we don't bother */ 126 offset = dma_window[1] >> PAGE_SHIFT; 127 128 /* TCE table size - measured in tce entries */ 129 newTceTable->it_size = dma_window[4] >> PAGE_SHIFT; 130 /* offset for VIO should always be 0 */ 131 newTceTable->it_offset = offset; 132 newTceTable->it_busno = 0; 133 newTceTable->it_index = (unsigned long)dma_window[0]; 134 newTceTable->it_type = TCE_VB; 135 136 return iommu_init_table(newTceTable); 137 } 138 139 /** 140 * vio_register_device_node: - Register a new vio device. 141 * @of_node: The OF node for this device. 142 * 143 * Creates and initializes a vio_dev structure from the data in 144 * of_node (dev.platform_data) and adds it to the list of virtual devices. 145 * Returns a pointer to the created vio_dev or NULL if node has 146 * NULL device_type or compatible fields. 147 */ 148 struct vio_dev * __devinit vio_register_device_node(struct device_node *of_node) 149 { 150 struct vio_dev *viodev; 151 unsigned int *unit_address; 152 unsigned int *irq_p; 153 154 /* we need the 'device_type' property, in order to match with drivers */ 155 if ((NULL == of_node->type)) { 156 printk(KERN_WARNING 157 "%s: node %s missing 'device_type'\n", __FUNCTION__, 158 of_node->name ? of_node->name : "<unknown>"); 159 return NULL; 160 } 161 162 unit_address = (unsigned int *)get_property(of_node, "reg", NULL); 163 if (!unit_address) { 164 printk(KERN_WARNING "%s: node %s missing 'reg'\n", __FUNCTION__, 165 of_node->name ? of_node->name : "<unknown>"); 166 return NULL; 167 } 168 169 /* allocate a vio_dev for this node */ 170 viodev = kmalloc(sizeof(struct vio_dev), GFP_KERNEL); 171 if (!viodev) { 172 return NULL; 173 } 174 memset(viodev, 0, sizeof(struct vio_dev)); 175 176 viodev->dev.platform_data = of_node_get(of_node); 177 178 viodev->irq = NO_IRQ; 179 irq_p = (unsigned int *)get_property(of_node, "interrupts", NULL); 180 if (irq_p) { 181 int virq = virt_irq_create_mapping(*irq_p); 182 if (virq == NO_IRQ) { 183 printk(KERN_ERR "Unable to allocate interrupt " 184 "number for %s\n", of_node->full_name); 185 } else 186 viodev->irq = irq_offset_up(virq); 187 } 188 189 snprintf(viodev->dev.bus_id, BUS_ID_SIZE, "%x", *unit_address); 190 viodev->name = of_node->name; 191 viodev->type = of_node->type; 192 viodev->unit_address = *unit_address; 193 viodev->iommu_table = vio_build_iommu_table(viodev); 194 195 /* register with generic device framework */ 196 if (vio_register_device(viodev) == NULL) { 197 /* XXX free TCE table */ 198 kfree(viodev); 199 return NULL; 200 } 201 device_create_file(&viodev->dev, &dev_attr_devspec); 202 203 return viodev; 204 } 205 EXPORT_SYMBOL(vio_register_device_node); 206 207 /** 208 * vio_get_attribute: - get attribute for virtual device 209 * @vdev: The vio device to get property. 210 * @which: The property/attribute to be extracted. 211 * @length: Pointer to length of returned data size (unused if NULL). 212 * 213 * Calls prom.c's get_property() to return the value of the 214 * attribute specified by the preprocessor constant @which 215 */ 216 const void * vio_get_attribute(struct vio_dev *vdev, void* which, int* length) 217 { 218 return get_property(vdev->dev.platform_data, (char*)which, length); 219 } 220 EXPORT_SYMBOL(vio_get_attribute); 221 222 /* vio_find_name() - internal because only vio.c knows how we formatted the 223 * kobject name 224 * XXX once vio_bus_type.devices is actually used as a kset in 225 * drivers/base/bus.c, this function should be removed in favor of 226 * "device_find(kobj_name, &vio_bus_type)" 227 */ 228 static struct vio_dev *vio_find_name(const char *kobj_name) 229 { 230 struct kobject *found; 231 232 found = kset_find_obj(&devices_subsys.kset, kobj_name); 233 if (!found) 234 return NULL; 235 236 return to_vio_dev(container_of(found, struct device, kobj)); 237 } 238 239 /** 240 * vio_find_node - find an already-registered vio_dev 241 * @vnode: device_node of the virtual device we're looking for 242 */ 243 struct vio_dev *vio_find_node(struct device_node *vnode) 244 { 245 uint32_t *unit_address; 246 char kobj_name[BUS_ID_SIZE]; 247 248 /* construct the kobject name from the device node */ 249 unit_address = (uint32_t *)get_property(vnode, "reg", NULL); 250 if (!unit_address) 251 return NULL; 252 snprintf(kobj_name, BUS_ID_SIZE, "%x", *unit_address); 253 254 return vio_find_name(kobj_name); 255 } 256 EXPORT_SYMBOL(vio_find_node); 257 258 int vio_enable_interrupts(struct vio_dev *dev) 259 { 260 int rc = h_vio_signal(dev->unit_address, VIO_IRQ_ENABLE); 261 if (rc != H_Success) 262 printk(KERN_ERR "vio: Error 0x%x enabling interrupts\n", rc); 263 return rc; 264 } 265 EXPORT_SYMBOL(vio_enable_interrupts); 266 267 int vio_disable_interrupts(struct vio_dev *dev) 268 { 269 int rc = h_vio_signal(dev->unit_address, VIO_IRQ_DISABLE); 270 if (rc != H_Success) 271 printk(KERN_ERR "vio: Error 0x%x disabling interrupts\n", rc); 272 return rc; 273 } 274 EXPORT_SYMBOL(vio_disable_interrupts); 275