diff options
author | Grant Likely <grant.likely@secretlab.ca> | 2011-06-21 12:59:35 -0400 |
---|---|---|
committer | Grant Likely <grant.likely@secretlab.ca> | 2011-06-21 13:04:10 -0400 |
commit | 15c3597d6ea47e8f3caf068887c4666165df63ad (patch) | |
tree | 22f7b13f99898152da64f19a17f7a16b93e0187e /drivers/of | |
parent | 5de1540b7bc4c23470f86add1e517be41e7fefe2 (diff) |
dt/platform: allow device name to be overridden
Some platform code has specific requirements on the naming of devices.
This patch allows callers of of_platform_populate() to provide a
device name lookup table.
Signed-off-by: Grant Likely <grant.likely@secretlab.ca>
Diffstat (limited to 'drivers/of')
-rw-r--r-- | drivers/of/platform.c | 73 |
1 files changed, 63 insertions, 10 deletions
diff --git a/drivers/of/platform.c b/drivers/of/platform.c index 4192ddc62638..e75af391e286 100644 --- a/drivers/of/platform.c +++ b/drivers/of/platform.c | |||
@@ -177,17 +177,20 @@ struct platform_device *of_device_alloc(struct device_node *np, | |||
177 | EXPORT_SYMBOL(of_device_alloc); | 177 | EXPORT_SYMBOL(of_device_alloc); |
178 | 178 | ||
179 | /** | 179 | /** |
180 | * of_platform_device_create - Alloc, initialize and register an of_device | 180 | * of_platform_device_create_pdata - Alloc, initialize and register an of_device |
181 | * @np: pointer to node to create device for | 181 | * @np: pointer to node to create device for |
182 | * @bus_id: name to assign device | 182 | * @bus_id: name to assign device |
183 | * @platform_data: pointer to populate platform_data pointer with | ||
183 | * @parent: Linux device model parent device. | 184 | * @parent: Linux device model parent device. |
184 | * | 185 | * |
185 | * Returns pointer to created platform device, or NULL if a device was not | 186 | * Returns pointer to created platform device, or NULL if a device was not |
186 | * registered. Unavailable devices will not get registered. | 187 | * registered. Unavailable devices will not get registered. |
187 | */ | 188 | */ |
188 | struct platform_device *of_platform_device_create(struct device_node *np, | 189 | struct platform_device *of_platform_device_create_pdata( |
189 | const char *bus_id, | 190 | struct device_node *np, |
190 | struct device *parent) | 191 | const char *bus_id, |
192 | void *platform_data, | ||
193 | struct device *parent) | ||
191 | { | 194 | { |
192 | struct platform_device *dev; | 195 | struct platform_device *dev; |
193 | 196 | ||
@@ -203,6 +206,7 @@ struct platform_device *of_platform_device_create(struct device_node *np, | |||
203 | #endif | 206 | #endif |
204 | dev->dev.coherent_dma_mask = DMA_BIT_MASK(32); | 207 | dev->dev.coherent_dma_mask = DMA_BIT_MASK(32); |
205 | dev->dev.bus = &platform_bus_type; | 208 | dev->dev.bus = &platform_bus_type; |
209 | dev->dev.platform_data = platform_data; | ||
206 | 210 | ||
207 | /* We do not fill the DMA ops for platform devices by default. | 211 | /* We do not fill the DMA ops for platform devices by default. |
208 | * This is currently the responsibility of the platform code | 212 | * This is currently the responsibility of the platform code |
@@ -216,6 +220,22 @@ struct platform_device *of_platform_device_create(struct device_node *np, | |||
216 | 220 | ||
217 | return dev; | 221 | return dev; |
218 | } | 222 | } |
223 | |||
224 | /** | ||
225 | * of_platform_device_create - Alloc, initialize and register an of_device | ||
226 | * @np: pointer to node to create device for | ||
227 | * @bus_id: name to assign device | ||
228 | * @parent: Linux device model parent device. | ||
229 | * | ||
230 | * Returns pointer to created platform device, or NULL if a device was not | ||
231 | * registered. Unavailable devices will not get registered. | ||
232 | */ | ||
233 | struct platform_device *of_platform_device_create(struct device_node *np, | ||
234 | const char *bus_id, | ||
235 | struct device *parent) | ||
236 | { | ||
237 | return of_platform_device_create_pdata(np, bus_id, NULL, parent); | ||
238 | } | ||
219 | EXPORT_SYMBOL(of_platform_device_create); | 239 | EXPORT_SYMBOL(of_platform_device_create); |
220 | 240 | ||
221 | #ifdef CONFIG_ARM_AMBA | 241 | #ifdef CONFIG_ARM_AMBA |
@@ -284,6 +304,28 @@ static struct amba_device *of_amba_device_create(struct device_node *node, | |||
284 | #endif /* CONFIG_ARM_AMBA */ | 304 | #endif /* CONFIG_ARM_AMBA */ |
285 | 305 | ||
286 | /** | 306 | /** |
307 | * of_devname_lookup() - Given a device node, lookup the preferred Linux name | ||
308 | */ | ||
309 | static const struct of_dev_auxdata *of_dev_lookup(const struct of_dev_auxdata *lookup, | ||
310 | struct device_node *np) | ||
311 | { | ||
312 | struct resource res; | ||
313 | if (lookup) { | ||
314 | for(; lookup->name != NULL; lookup++) { | ||
315 | if (!of_device_is_compatible(np, lookup->compatible)) | ||
316 | continue; | ||
317 | if (of_address_to_resource(np, 0, &res)) | ||
318 | continue; | ||
319 | if (res.start != lookup->phys_addr) | ||
320 | continue; | ||
321 | pr_debug("%s: devname=%s\n", np->full_name, lookup->name); | ||
322 | return lookup; | ||
323 | } | ||
324 | } | ||
325 | return NULL; | ||
326 | } | ||
327 | |||
328 | /** | ||
287 | * of_platform_bus_create() - Create a device for a node and its children. | 329 | * of_platform_bus_create() - Create a device for a node and its children. |
288 | * @bus: device node of the bus to instantiate | 330 | * @bus: device node of the bus to instantiate |
289 | * @matches: match table for bus nodes | 331 | * @matches: match table for bus nodes |
@@ -295,10 +337,14 @@ static struct amba_device *of_amba_device_create(struct device_node *node, | |||
295 | */ | 337 | */ |
296 | static int of_platform_bus_create(struct device_node *bus, | 338 | static int of_platform_bus_create(struct device_node *bus, |
297 | const struct of_device_id *matches, | 339 | const struct of_device_id *matches, |
340 | const struct of_dev_auxdata *lookup, | ||
298 | struct device *parent, bool strict) | 341 | struct device *parent, bool strict) |
299 | { | 342 | { |
343 | const struct of_dev_auxdata *auxdata; | ||
300 | struct device_node *child; | 344 | struct device_node *child; |
301 | struct platform_device *dev; | 345 | struct platform_device *dev; |
346 | const char *bus_id = NULL; | ||
347 | void *platform_data = NULL; | ||
302 | int rc = 0; | 348 | int rc = 0; |
303 | 349 | ||
304 | /* Make sure it has a compatible property */ | 350 | /* Make sure it has a compatible property */ |
@@ -308,18 +354,24 @@ static int of_platform_bus_create(struct device_node *bus, | |||
308 | return 0; | 354 | return 0; |
309 | } | 355 | } |
310 | 356 | ||
357 | auxdata = of_dev_lookup(lookup, bus); | ||
358 | if (auxdata) { | ||
359 | bus_id = auxdata->name; | ||
360 | platform_data = auxdata->platform_data; | ||
361 | } | ||
362 | |||
311 | if (of_device_is_compatible(bus, "arm,primecell")) { | 363 | if (of_device_is_compatible(bus, "arm,primecell")) { |
312 | of_amba_device_create(bus, NULL, NULL, parent); | 364 | of_amba_device_create(bus, bus_id, platform_data, parent); |
313 | return 0; | 365 | return 0; |
314 | } | 366 | } |
315 | 367 | ||
316 | dev = of_platform_device_create(bus, NULL, parent); | 368 | dev = of_platform_device_create_pdata(bus, bus_id, platform_data, parent); |
317 | if (!dev || !of_match_node(matches, bus)) | 369 | if (!dev || !of_match_node(matches, bus)) |
318 | return 0; | 370 | return 0; |
319 | 371 | ||
320 | for_each_child_of_node(bus, child) { | 372 | for_each_child_of_node(bus, child) { |
321 | pr_debug(" create child: %s\n", child->full_name); | 373 | pr_debug(" create child: %s\n", child->full_name); |
322 | rc = of_platform_bus_create(child, matches, &dev->dev, strict); | 374 | rc = of_platform_bus_create(child, matches, lookup, &dev->dev, strict); |
323 | if (rc) { | 375 | if (rc) { |
324 | of_node_put(child); | 376 | of_node_put(child); |
325 | break; | 377 | break; |
@@ -353,11 +405,11 @@ int of_platform_bus_probe(struct device_node *root, | |||
353 | 405 | ||
354 | /* Do a self check of bus type, if there's a match, create children */ | 406 | /* Do a self check of bus type, if there's a match, create children */ |
355 | if (of_match_node(matches, root)) { | 407 | if (of_match_node(matches, root)) { |
356 | rc = of_platform_bus_create(root, matches, parent, false); | 408 | rc = of_platform_bus_create(root, matches, NULL, parent, false); |
357 | } else for_each_child_of_node(root, child) { | 409 | } else for_each_child_of_node(root, child) { |
358 | if (!of_match_node(matches, child)) | 410 | if (!of_match_node(matches, child)) |
359 | continue; | 411 | continue; |
360 | rc = of_platform_bus_create(child, matches, parent, false); | 412 | rc = of_platform_bus_create(child, matches, NULL, parent, false); |
361 | if (rc) | 413 | if (rc) |
362 | break; | 414 | break; |
363 | } | 415 | } |
@@ -387,6 +439,7 @@ EXPORT_SYMBOL(of_platform_bus_probe); | |||
387 | */ | 439 | */ |
388 | int of_platform_populate(struct device_node *root, | 440 | int of_platform_populate(struct device_node *root, |
389 | const struct of_device_id *matches, | 441 | const struct of_device_id *matches, |
442 | const struct of_dev_auxdata *lookup, | ||
390 | struct device *parent) | 443 | struct device *parent) |
391 | { | 444 | { |
392 | struct device_node *child; | 445 | struct device_node *child; |
@@ -397,7 +450,7 @@ int of_platform_populate(struct device_node *root, | |||
397 | return -EINVAL; | 450 | return -EINVAL; |
398 | 451 | ||
399 | for_each_child_of_node(root, child) { | 452 | for_each_child_of_node(root, child) { |
400 | rc = of_platform_bus_create(child, matches, parent, true); | 453 | rc = of_platform_bus_create(child, matches, lookup, parent, true); |
401 | if (rc) | 454 | if (rc) |
402 | break; | 455 | break; |
403 | } | 456 | } |