diff options
Diffstat (limited to 'drivers/of/device.c')
-rw-r--r-- | drivers/of/device.c | 91 |
1 files changed, 70 insertions, 21 deletions
diff --git a/drivers/of/device.c b/drivers/of/device.c index 7d18f8e0b013..0d8a0644f540 100644 --- a/drivers/of/device.c +++ b/drivers/of/device.c | |||
@@ -20,13 +20,13 @@ | |||
20 | const struct of_device_id *of_match_device(const struct of_device_id *matches, | 20 | const struct of_device_id *of_match_device(const struct of_device_id *matches, |
21 | const struct device *dev) | 21 | const struct device *dev) |
22 | { | 22 | { |
23 | if (!dev->of_node) | 23 | if ((!matches) || (!dev->of_node)) |
24 | return NULL; | 24 | return NULL; |
25 | return of_match_node(matches, dev->of_node); | 25 | return of_match_node(matches, dev->of_node); |
26 | } | 26 | } |
27 | EXPORT_SYMBOL(of_match_device); | 27 | EXPORT_SYMBOL(of_match_device); |
28 | 28 | ||
29 | struct of_device *of_dev_get(struct of_device *dev) | 29 | struct platform_device *of_dev_get(struct platform_device *dev) |
30 | { | 30 | { |
31 | struct device *tmp; | 31 | struct device *tmp; |
32 | 32 | ||
@@ -34,13 +34,13 @@ struct of_device *of_dev_get(struct of_device *dev) | |||
34 | return NULL; | 34 | return NULL; |
35 | tmp = get_device(&dev->dev); | 35 | tmp = get_device(&dev->dev); |
36 | if (tmp) | 36 | if (tmp) |
37 | return to_of_device(tmp); | 37 | return to_platform_device(tmp); |
38 | else | 38 | else |
39 | return NULL; | 39 | return NULL; |
40 | } | 40 | } |
41 | EXPORT_SYMBOL(of_dev_get); | 41 | EXPORT_SYMBOL(of_dev_get); |
42 | 42 | ||
43 | void of_dev_put(struct of_device *dev) | 43 | void of_dev_put(struct platform_device *dev) |
44 | { | 44 | { |
45 | if (dev) | 45 | if (dev) |
46 | put_device(&dev->dev); | 46 | put_device(&dev->dev); |
@@ -50,28 +50,25 @@ EXPORT_SYMBOL(of_dev_put); | |||
50 | static ssize_t devspec_show(struct device *dev, | 50 | static ssize_t devspec_show(struct device *dev, |
51 | struct device_attribute *attr, char *buf) | 51 | struct device_attribute *attr, char *buf) |
52 | { | 52 | { |
53 | struct of_device *ofdev; | 53 | struct platform_device *ofdev; |
54 | 54 | ||
55 | ofdev = to_of_device(dev); | 55 | ofdev = to_platform_device(dev); |
56 | return sprintf(buf, "%s\n", ofdev->dev.of_node->full_name); | 56 | return sprintf(buf, "%s\n", ofdev->dev.of_node->full_name); |
57 | } | 57 | } |
58 | 58 | ||
59 | static ssize_t name_show(struct device *dev, | 59 | static ssize_t name_show(struct device *dev, |
60 | struct device_attribute *attr, char *buf) | 60 | struct device_attribute *attr, char *buf) |
61 | { | 61 | { |
62 | struct of_device *ofdev; | 62 | struct platform_device *ofdev; |
63 | 63 | ||
64 | ofdev = to_of_device(dev); | 64 | ofdev = to_platform_device(dev); |
65 | return sprintf(buf, "%s\n", ofdev->dev.of_node->name); | 65 | return sprintf(buf, "%s\n", ofdev->dev.of_node->name); |
66 | } | 66 | } |
67 | 67 | ||
68 | static ssize_t modalias_show(struct device *dev, | 68 | static ssize_t modalias_show(struct device *dev, |
69 | struct device_attribute *attr, char *buf) | 69 | struct device_attribute *attr, char *buf) |
70 | { | 70 | { |
71 | struct of_device *ofdev = to_of_device(dev); | 71 | ssize_t len = of_device_get_modalias(dev, buf, PAGE_SIZE - 2); |
72 | ssize_t len = 0; | ||
73 | |||
74 | len = of_device_get_modalias(ofdev, buf, PAGE_SIZE - 2); | ||
75 | buf[len] = '\n'; | 72 | buf[len] = '\n'; |
76 | buf[len+1] = 0; | 73 | buf[len+1] = 0; |
77 | return len+1; | 74 | return len+1; |
@@ -93,20 +90,25 @@ struct device_attribute of_platform_device_attrs[] = { | |||
93 | */ | 90 | */ |
94 | void of_release_dev(struct device *dev) | 91 | void of_release_dev(struct device *dev) |
95 | { | 92 | { |
96 | struct of_device *ofdev; | 93 | struct platform_device *ofdev; |
97 | 94 | ||
98 | ofdev = to_of_device(dev); | 95 | ofdev = to_platform_device(dev); |
99 | of_node_put(ofdev->dev.of_node); | 96 | of_node_put(ofdev->dev.of_node); |
100 | kfree(ofdev); | 97 | kfree(ofdev); |
101 | } | 98 | } |
102 | EXPORT_SYMBOL(of_release_dev); | 99 | EXPORT_SYMBOL(of_release_dev); |
103 | 100 | ||
104 | int of_device_register(struct of_device *ofdev) | 101 | int of_device_register(struct platform_device *ofdev) |
105 | { | 102 | { |
106 | BUG_ON(ofdev->dev.of_node == NULL); | 103 | BUG_ON(ofdev->dev.of_node == NULL); |
107 | 104 | ||
108 | device_initialize(&ofdev->dev); | 105 | device_initialize(&ofdev->dev); |
109 | 106 | ||
107 | /* name and id have to be set so that the platform bus doesn't get | ||
108 | * confused on matching */ | ||
109 | ofdev->name = dev_name(&ofdev->dev); | ||
110 | ofdev->id = -1; | ||
111 | |||
110 | /* device_add will assume that this device is on the same node as | 112 | /* device_add will assume that this device is on the same node as |
111 | * the parent. If there is no parent defined, set the node | 113 | * the parent. If there is no parent defined, set the node |
112 | * explicitly */ | 114 | * explicitly */ |
@@ -117,25 +119,24 @@ int of_device_register(struct of_device *ofdev) | |||
117 | } | 119 | } |
118 | EXPORT_SYMBOL(of_device_register); | 120 | EXPORT_SYMBOL(of_device_register); |
119 | 121 | ||
120 | void of_device_unregister(struct of_device *ofdev) | 122 | void of_device_unregister(struct platform_device *ofdev) |
121 | { | 123 | { |
122 | device_unregister(&ofdev->dev); | 124 | device_unregister(&ofdev->dev); |
123 | } | 125 | } |
124 | EXPORT_SYMBOL(of_device_unregister); | 126 | EXPORT_SYMBOL(of_device_unregister); |
125 | 127 | ||
126 | ssize_t of_device_get_modalias(struct of_device *ofdev, | 128 | ssize_t of_device_get_modalias(struct device *dev, char *str, ssize_t len) |
127 | char *str, ssize_t len) | ||
128 | { | 129 | { |
129 | const char *compat; | 130 | const char *compat; |
130 | int cplen, i; | 131 | int cplen, i; |
131 | ssize_t tsize, csize, repend; | 132 | ssize_t tsize, csize, repend; |
132 | 133 | ||
133 | /* Name & Type */ | 134 | /* Name & Type */ |
134 | csize = snprintf(str, len, "of:N%sT%s", ofdev->dev.of_node->name, | 135 | csize = snprintf(str, len, "of:N%sT%s", dev->of_node->name, |
135 | ofdev->dev.of_node->type); | 136 | dev->of_node->type); |
136 | 137 | ||
137 | /* Get compatible property if any */ | 138 | /* Get compatible property if any */ |
138 | compat = of_get_property(ofdev->dev.of_node, "compatible", &cplen); | 139 | compat = of_get_property(dev->of_node, "compatible", &cplen); |
139 | if (!compat) | 140 | if (!compat) |
140 | return csize; | 141 | return csize; |
141 | 142 | ||
@@ -170,3 +171,51 @@ ssize_t of_device_get_modalias(struct of_device *ofdev, | |||
170 | 171 | ||
171 | return tsize; | 172 | return tsize; |
172 | } | 173 | } |
174 | |||
175 | /** | ||
176 | * of_device_uevent - Display OF related uevent information | ||
177 | */ | ||
178 | int of_device_uevent(struct device *dev, struct kobj_uevent_env *env) | ||
179 | { | ||
180 | const char *compat; | ||
181 | int seen = 0, cplen, sl; | ||
182 | |||
183 | if ((!dev) || (!dev->of_node)) | ||
184 | return -ENODEV; | ||
185 | |||
186 | if (add_uevent_var(env, "OF_NAME=%s", dev->of_node->name)) | ||
187 | return -ENOMEM; | ||
188 | |||
189 | if (add_uevent_var(env, "OF_TYPE=%s", dev->of_node->type)) | ||
190 | return -ENOMEM; | ||
191 | |||
192 | /* Since the compatible field can contain pretty much anything | ||
193 | * it's not really legal to split it out with commas. We split it | ||
194 | * up using a number of environment variables instead. */ | ||
195 | |||
196 | compat = of_get_property(dev->of_node, "compatible", &cplen); | ||
197 | while (compat && *compat && cplen > 0) { | ||
198 | if (add_uevent_var(env, "OF_COMPATIBLE_%d=%s", seen, compat)) | ||
199 | return -ENOMEM; | ||
200 | |||
201 | sl = strlen(compat) + 1; | ||
202 | compat += sl; | ||
203 | cplen -= sl; | ||
204 | seen++; | ||
205 | } | ||
206 | |||
207 | if (add_uevent_var(env, "OF_COMPATIBLE_N=%d", seen)) | ||
208 | return -ENOMEM; | ||
209 | |||
210 | /* modalias is trickier, we add it in 2 steps */ | ||
211 | if (add_uevent_var(env, "MODALIAS=")) | ||
212 | return -ENOMEM; | ||
213 | |||
214 | sl = of_device_get_modalias(dev, &env->buf[env->buflen-1], | ||
215 | sizeof(env->buf) - env->buflen); | ||
216 | if (sl >= (sizeof(env->buf) - env->buflen)) | ||
217 | return -ENOMEM; | ||
218 | env->buflen += sl; | ||
219 | |||
220 | return 0; | ||
221 | } | ||