at v2.6.32 113 lines 2.7 kB view raw
1#include <linux/string.h> 2#include <linux/kernel.h> 3#include <linux/of.h> 4#include <linux/init.h> 5#include <linux/module.h> 6#include <linux/mod_devicetable.h> 7#include <linux/slab.h> 8#include <linux/of_device.h> 9 10#include <linux/errno.h> 11 12void of_device_make_bus_id(struct of_device *dev) 13{ 14 static atomic_t bus_no_reg_magic; 15 struct device_node *node = dev->node; 16 const u32 *reg; 17 u64 addr; 18 int magic; 19 20 /* 21 * For MMIO, get the physical address 22 */ 23 reg = of_get_property(node, "reg", NULL); 24 if (reg) { 25 addr = of_translate_address(node, reg); 26 if (addr != OF_BAD_ADDR) { 27 dev_set_name(&dev->dev, "%llx.%s", 28 (unsigned long long)addr, node->name); 29 return; 30 } 31 } 32 33 /* 34 * No BusID, use the node name and add a globally incremented 35 * counter (and pray...) 36 */ 37 magic = atomic_add_return(1, &bus_no_reg_magic); 38 dev_set_name(&dev->dev, "%s.%d", node->name, magic - 1); 39} 40EXPORT_SYMBOL(of_device_make_bus_id); 41 42struct of_device *of_device_alloc(struct device_node *np, 43 const char *bus_id, 44 struct device *parent) 45{ 46 struct of_device *dev; 47 48 dev = kzalloc(sizeof(*dev), GFP_KERNEL); 49 if (!dev) 50 return NULL; 51 52 dev->node = of_node_get(np); 53 dev->dev.dma_mask = &dev->dma_mask; 54 dev->dev.parent = parent; 55 dev->dev.release = of_release_dev; 56 dev->dev.archdata.of_node = np; 57 58 if (bus_id) 59 dev_set_name(&dev->dev, bus_id); 60 else 61 of_device_make_bus_id(dev); 62 63 return dev; 64} 65EXPORT_SYMBOL(of_device_alloc); 66 67int of_device_uevent(struct device *dev, struct kobj_uevent_env *env) 68{ 69 struct of_device *ofdev; 70 const char *compat; 71 int seen = 0, cplen, sl; 72 73 if (!dev) 74 return -ENODEV; 75 76 ofdev = to_of_device(dev); 77 78 if (add_uevent_var(env, "OF_NAME=%s", ofdev->node->name)) 79 return -ENOMEM; 80 81 if (add_uevent_var(env, "OF_TYPE=%s", ofdev->node->type)) 82 return -ENOMEM; 83 84 /* Since the compatible field can contain pretty much anything 85 * it's not really legal to split it out with commas. We split it 86 * up using a number of environment variables instead. */ 87 88 compat = of_get_property(ofdev->node, "compatible", &cplen); 89 while (compat && *compat && cplen > 0) { 90 if (add_uevent_var(env, "OF_COMPATIBLE_%d=%s", seen, compat)) 91 return -ENOMEM; 92 93 sl = strlen(compat) + 1; 94 compat += sl; 95 cplen -= sl; 96 seen++; 97 } 98 99 if (add_uevent_var(env, "OF_COMPATIBLE_N=%d", seen)) 100 return -ENOMEM; 101 102 /* modalias is trickier, we add it in 2 steps */ 103 if (add_uevent_var(env, "MODALIAS=")) 104 return -ENOMEM; 105 sl = of_device_get_modalias(ofdev, &env->buf[env->buflen-1], 106 sizeof(env->buf) - env->buflen); 107 if (sl >= (sizeof(env->buf) - env->buflen)) 108 return -ENOMEM; 109 env->buflen += sl; 110 111 return 0; 112} 113EXPORT_SYMBOL(of_device_uevent);