diff options
Diffstat (limited to 'drivers/base/platform.c')
-rw-r--r-- | drivers/base/platform.c | 59 |
1 files changed, 54 insertions, 5 deletions
diff --git a/drivers/base/platform.c b/drivers/base/platform.c index 1dd6d3bf1098..f437afa17f2b 100644 --- a/drivers/base/platform.c +++ b/drivers/base/platform.c | |||
@@ -26,6 +26,7 @@ | |||
26 | #include <linux/acpi.h> | 26 | #include <linux/acpi.h> |
27 | #include <linux/clk/clk-conf.h> | 27 | #include <linux/clk/clk-conf.h> |
28 | #include <linux/limits.h> | 28 | #include <linux/limits.h> |
29 | #include <linux/property.h> | ||
29 | 30 | ||
30 | #include "base.h" | 31 | #include "base.h" |
31 | #include "power/power.h" | 32 | #include "power/power.h" |
@@ -117,6 +118,26 @@ int platform_get_irq(struct platform_device *dev, unsigned int num) | |||
117 | EXPORT_SYMBOL_GPL(platform_get_irq); | 118 | EXPORT_SYMBOL_GPL(platform_get_irq); |
118 | 119 | ||
119 | /** | 120 | /** |
121 | * platform_irq_count - Count the number of IRQs a platform device uses | ||
122 | * @dev: platform device | ||
123 | * | ||
124 | * Return: Number of IRQs a platform device uses or EPROBE_DEFER | ||
125 | */ | ||
126 | int platform_irq_count(struct platform_device *dev) | ||
127 | { | ||
128 | int ret, nr = 0; | ||
129 | |||
130 | while ((ret = platform_get_irq(dev, nr)) >= 0) | ||
131 | nr++; | ||
132 | |||
133 | if (ret == -EPROBE_DEFER) | ||
134 | return ret; | ||
135 | |||
136 | return nr; | ||
137 | } | ||
138 | EXPORT_SYMBOL_GPL(platform_irq_count); | ||
139 | |||
140 | /** | ||
120 | * platform_get_resource_byname - get a resource for a device by name | 141 | * platform_get_resource_byname - get a resource for a device by name |
121 | * @dev: platform device | 142 | * @dev: platform device |
122 | * @type: resource type | 143 | * @type: resource type |
@@ -299,6 +320,22 @@ int platform_device_add_data(struct platform_device *pdev, const void *data, | |||
299 | EXPORT_SYMBOL_GPL(platform_device_add_data); | 320 | EXPORT_SYMBOL_GPL(platform_device_add_data); |
300 | 321 | ||
301 | /** | 322 | /** |
323 | * platform_device_add_properties - add built-in properties to a platform device | ||
324 | * @pdev: platform device to add properties to | ||
325 | * @pset: properties to add | ||
326 | * | ||
327 | * The function will take deep copy of the properties in @pset and attach | ||
328 | * the copy to the platform device. The memory associated with properties | ||
329 | * will be freed when the platform device is released. | ||
330 | */ | ||
331 | int platform_device_add_properties(struct platform_device *pdev, | ||
332 | const struct property_set *pset) | ||
333 | { | ||
334 | return device_add_property_set(&pdev->dev, pset); | ||
335 | } | ||
336 | EXPORT_SYMBOL_GPL(platform_device_add_properties); | ||
337 | |||
338 | /** | ||
302 | * platform_device_add - add a platform device to device hierarchy | 339 | * platform_device_add - add a platform device to device hierarchy |
303 | * @pdev: platform device we're adding | 340 | * @pdev: platform device we're adding |
304 | * | 341 | * |
@@ -409,6 +446,8 @@ void platform_device_del(struct platform_device *pdev) | |||
409 | if (r->parent) | 446 | if (r->parent) |
410 | release_resource(r); | 447 | release_resource(r); |
411 | } | 448 | } |
449 | |||
450 | device_remove_property_set(&pdev->dev); | ||
412 | } | 451 | } |
413 | } | 452 | } |
414 | EXPORT_SYMBOL_GPL(platform_device_del); | 453 | EXPORT_SYMBOL_GPL(platform_device_del); |
@@ -487,6 +526,12 @@ struct platform_device *platform_device_register_full( | |||
487 | if (ret) | 526 | if (ret) |
488 | goto err; | 527 | goto err; |
489 | 528 | ||
529 | if (pdevinfo->pset) { | ||
530 | ret = platform_device_add_properties(pdev, pdevinfo->pset); | ||
531 | if (ret) | ||
532 | goto err; | ||
533 | } | ||
534 | |||
490 | ret = platform_device_add(pdev); | 535 | ret = platform_device_add(pdev); |
491 | if (ret) { | 536 | if (ret) { |
492 | err: | 537 | err: |
@@ -513,10 +558,15 @@ static int platform_drv_probe(struct device *_dev) | |||
513 | return ret; | 558 | return ret; |
514 | 559 | ||
515 | ret = dev_pm_domain_attach(_dev, true); | 560 | ret = dev_pm_domain_attach(_dev, true); |
516 | if (ret != -EPROBE_DEFER && drv->probe) { | 561 | if (ret != -EPROBE_DEFER) { |
517 | ret = drv->probe(dev); | 562 | if (drv->probe) { |
518 | if (ret) | 563 | ret = drv->probe(dev); |
519 | dev_pm_domain_detach(_dev, true); | 564 | if (ret) |
565 | dev_pm_domain_detach(_dev, true); | ||
566 | } else { | ||
567 | /* don't fail if just dev_pm_domain_attach failed */ | ||
568 | ret = 0; | ||
569 | } | ||
520 | } | 570 | } |
521 | 571 | ||
522 | if (drv->prevent_deferred_probe && ret == -EPROBE_DEFER) { | 572 | if (drv->prevent_deferred_probe && ret == -EPROBE_DEFER) { |
@@ -552,7 +602,6 @@ static void platform_drv_shutdown(struct device *_dev) | |||
552 | 602 | ||
553 | if (drv->shutdown) | 603 | if (drv->shutdown) |
554 | drv->shutdown(dev); | 604 | drv->shutdown(dev); |
555 | dev_pm_domain_detach(_dev, true); | ||
556 | } | 605 | } |
557 | 606 | ||
558 | /** | 607 | /** |