at v2.6.14 276 lines 6.5 kB view raw
1#include <linux/config.h> 2#include <linux/string.h> 3#include <linux/kernel.h> 4#include <linux/init.h> 5#include <linux/module.h> 6#include <linux/mod_devicetable.h> 7#include <asm/errno.h> 8#include <asm/of_device.h> 9 10/** 11 * of_match_device - Tell if an of_device structure has a matching 12 * of_match structure 13 * @ids: array of of device match structures to search in 14 * @dev: the of device structure to match against 15 * 16 * Used by a driver to check whether an of_device present in the 17 * system is in its list of supported devices. 18 */ 19const struct of_device_id * of_match_device(const struct of_device_id *matches, 20 const struct of_device *dev) 21{ 22 if (!dev->node) 23 return NULL; 24 while (matches->name[0] || matches->type[0] || matches->compatible[0]) { 25 int match = 1; 26 if (matches->name[0]) 27 match &= dev->node->name 28 && !strcmp(matches->name, dev->node->name); 29 if (matches->type[0]) 30 match &= dev->node->type 31 && !strcmp(matches->type, dev->node->type); 32 if (matches->compatible[0]) 33 match &= device_is_compatible(dev->node, 34 matches->compatible); 35 if (match) 36 return matches; 37 matches++; 38 } 39 return NULL; 40} 41 42static int of_platform_bus_match(struct device *dev, struct device_driver *drv) 43{ 44 struct of_device * of_dev = to_of_device(dev); 45 struct of_platform_driver * of_drv = to_of_platform_driver(drv); 46 const struct of_device_id * matches = of_drv->match_table; 47 48 if (!matches) 49 return 0; 50 51 return of_match_device(matches, of_dev) != NULL; 52} 53 54struct of_device *of_dev_get(struct of_device *dev) 55{ 56 struct device *tmp; 57 58 if (!dev) 59 return NULL; 60 tmp = get_device(&dev->dev); 61 if (tmp) 62 return to_of_device(tmp); 63 else 64 return NULL; 65} 66 67void of_dev_put(struct of_device *dev) 68{ 69 if (dev) 70 put_device(&dev->dev); 71} 72 73 74static int of_device_probe(struct device *dev) 75{ 76 int error = -ENODEV; 77 struct of_platform_driver *drv; 78 struct of_device *of_dev; 79 const struct of_device_id *match; 80 81 drv = to_of_platform_driver(dev->driver); 82 of_dev = to_of_device(dev); 83 84 if (!drv->probe) 85 return error; 86 87 of_dev_get(of_dev); 88 89 match = of_match_device(drv->match_table, of_dev); 90 if (match) 91 error = drv->probe(of_dev, match); 92 if (error) 93 of_dev_put(of_dev); 94 95 return error; 96} 97 98static int of_device_remove(struct device *dev) 99{ 100 struct of_device * of_dev = to_of_device(dev); 101 struct of_platform_driver * drv = to_of_platform_driver(dev->driver); 102 103 if (dev->driver && drv->remove) 104 drv->remove(of_dev); 105 return 0; 106} 107 108static int of_device_suspend(struct device *dev, pm_message_t state) 109{ 110 struct of_device * of_dev = to_of_device(dev); 111 struct of_platform_driver * drv = to_of_platform_driver(dev->driver); 112 int error = 0; 113 114 if (dev->driver && drv->suspend) 115 error = drv->suspend(of_dev, state); 116 return error; 117} 118 119static int of_device_resume(struct device * dev) 120{ 121 struct of_device * of_dev = to_of_device(dev); 122 struct of_platform_driver * drv = to_of_platform_driver(dev->driver); 123 int error = 0; 124 125 if (dev->driver && drv->resume) 126 error = drv->resume(of_dev); 127 return error; 128} 129 130struct bus_type of_platform_bus_type = { 131 .name = "of_platform", 132 .match = of_platform_bus_match, 133 .suspend = of_device_suspend, 134 .resume = of_device_resume, 135}; 136 137static int __init of_bus_driver_init(void) 138{ 139 return bus_register(&of_platform_bus_type); 140} 141 142postcore_initcall(of_bus_driver_init); 143 144int of_register_driver(struct of_platform_driver *drv) 145{ 146 int count = 0; 147 148 /* initialize common driver fields */ 149 drv->driver.name = drv->name; 150 drv->driver.bus = &of_platform_bus_type; 151 drv->driver.probe = of_device_probe; 152 drv->driver.remove = of_device_remove; 153 154 /* register with core */ 155 count = driver_register(&drv->driver); 156 return count ? count : 1; 157} 158 159void of_unregister_driver(struct of_platform_driver *drv) 160{ 161 driver_unregister(&drv->driver); 162} 163 164 165static ssize_t dev_show_devspec(struct device *dev, struct device_attribute *attr, char *buf) 166{ 167 struct of_device *ofdev; 168 169 ofdev = to_of_device(dev); 170 return sprintf(buf, "%s", ofdev->node->full_name); 171} 172 173static DEVICE_ATTR(devspec, S_IRUGO, dev_show_devspec, NULL); 174 175/** 176 * of_release_dev - free an of device structure when all users of it are finished. 177 * @dev: device that's been disconnected 178 * 179 * Will be called only by the device core when all users of this of device are 180 * done. 181 */ 182void of_release_dev(struct device *dev) 183{ 184 struct of_device *ofdev; 185 186 ofdev = to_of_device(dev); 187 of_node_put(ofdev->node); 188 kfree(ofdev); 189} 190 191int of_device_register(struct of_device *ofdev) 192{ 193 int rc; 194 struct of_device **odprop; 195 196 BUG_ON(ofdev->node == NULL); 197 198 odprop = (struct of_device **)get_property(ofdev->node, "linux,device", NULL); 199 if (!odprop) { 200 struct property *new_prop; 201 202 new_prop = kmalloc(sizeof(struct property) + sizeof(struct of_device *), 203 GFP_KERNEL); 204 if (new_prop == NULL) 205 return -ENOMEM; 206 new_prop->name = "linux,device"; 207 new_prop->length = sizeof(sizeof(struct of_device *)); 208 new_prop->value = (unsigned char *)&new_prop[1]; 209 odprop = (struct of_device **)new_prop->value; 210 *odprop = NULL; 211 prom_add_property(ofdev->node, new_prop); 212 } 213 *odprop = ofdev; 214 215 rc = device_register(&ofdev->dev); 216 if (rc) 217 return rc; 218 219 device_create_file(&ofdev->dev, &dev_attr_devspec); 220 221 return 0; 222} 223 224void of_device_unregister(struct of_device *ofdev) 225{ 226 struct of_device **odprop; 227 228 device_remove_file(&ofdev->dev, &dev_attr_devspec); 229 230 odprop = (struct of_device **)get_property(ofdev->node, "linux,device", NULL); 231 if (odprop) 232 *odprop = NULL; 233 234 device_unregister(&ofdev->dev); 235} 236 237struct of_device* of_platform_device_create(struct device_node *np, 238 const char *bus_id, 239 struct device *parent) 240{ 241 struct of_device *dev; 242 u32 *reg; 243 244 dev = kmalloc(sizeof(*dev), GFP_KERNEL); 245 if (!dev) 246 return NULL; 247 memset(dev, 0, sizeof(*dev)); 248 249 dev->node = of_node_get(np); 250 dev->dma_mask = 0xffffffffUL; 251 dev->dev.dma_mask = &dev->dma_mask; 252 dev->dev.parent = parent; 253 dev->dev.bus = &of_platform_bus_type; 254 dev->dev.release = of_release_dev; 255 256 reg = (u32 *)get_property(np, "reg", NULL); 257 strlcpy(dev->dev.bus_id, bus_id, BUS_ID_SIZE); 258 259 if (of_device_register(dev) != 0) { 260 kfree(dev); 261 return NULL; 262 } 263 264 return dev; 265} 266 267EXPORT_SYMBOL(of_match_device); 268EXPORT_SYMBOL(of_platform_bus_type); 269EXPORT_SYMBOL(of_register_driver); 270EXPORT_SYMBOL(of_unregister_driver); 271EXPORT_SYMBOL(of_device_register); 272EXPORT_SYMBOL(of_device_unregister); 273EXPORT_SYMBOL(of_dev_get); 274EXPORT_SYMBOL(of_dev_put); 275EXPORT_SYMBOL(of_platform_device_create); 276EXPORT_SYMBOL(of_release_dev);