diff options
Diffstat (limited to 'drivers/base/platform.c')
| -rw-r--r-- | drivers/base/platform.c | 147 |
1 files changed, 122 insertions, 25 deletions
diff --git a/drivers/base/platform.c b/drivers/base/platform.c index 58efaf2f1259..4d99c8bdfedc 100644 --- a/drivers/base/platform.c +++ b/drivers/base/platform.c | |||
| @@ -128,7 +128,7 @@ struct platform_object { | |||
| 128 | }; | 128 | }; |
| 129 | 129 | ||
| 130 | /** | 130 | /** |
| 131 | * platform_device_put | 131 | * platform_device_put - destroy a platform device |
| 132 | * @pdev: platform device to free | 132 | * @pdev: platform device to free |
| 133 | * | 133 | * |
| 134 | * Free all memory associated with a platform device. This function must | 134 | * Free all memory associated with a platform device. This function must |
| @@ -152,7 +152,7 @@ static void platform_device_release(struct device *dev) | |||
| 152 | } | 152 | } |
| 153 | 153 | ||
| 154 | /** | 154 | /** |
| 155 | * platform_device_alloc | 155 | * platform_device_alloc - create a platform device |
| 156 | * @name: base name of the device we're adding | 156 | * @name: base name of the device we're adding |
| 157 | * @id: instance id | 157 | * @id: instance id |
| 158 | * | 158 | * |
| @@ -177,7 +177,7 @@ struct platform_device *platform_device_alloc(const char *name, int id) | |||
| 177 | EXPORT_SYMBOL_GPL(platform_device_alloc); | 177 | EXPORT_SYMBOL_GPL(platform_device_alloc); |
| 178 | 178 | ||
| 179 | /** | 179 | /** |
| 180 | * platform_device_add_resources | 180 | * platform_device_add_resources - add resources to a platform device |
| 181 | * @pdev: platform device allocated by platform_device_alloc to add resources to | 181 | * @pdev: platform device allocated by platform_device_alloc to add resources to |
| 182 | * @res: set of resources that needs to be allocated for the device | 182 | * @res: set of resources that needs to be allocated for the device |
| 183 | * @num: number of resources | 183 | * @num: number of resources |
| @@ -187,7 +187,7 @@ EXPORT_SYMBOL_GPL(platform_device_alloc); | |||
| 187 | * released. | 187 | * released. |
| 188 | */ | 188 | */ |
| 189 | int platform_device_add_resources(struct platform_device *pdev, | 189 | int platform_device_add_resources(struct platform_device *pdev, |
| 190 | struct resource *res, unsigned int num) | 190 | const struct resource *res, unsigned int num) |
| 191 | { | 191 | { |
| 192 | struct resource *r; | 192 | struct resource *r; |
| 193 | 193 | ||
| @@ -202,7 +202,7 @@ int platform_device_add_resources(struct platform_device *pdev, | |||
| 202 | EXPORT_SYMBOL_GPL(platform_device_add_resources); | 202 | EXPORT_SYMBOL_GPL(platform_device_add_resources); |
| 203 | 203 | ||
| 204 | /** | 204 | /** |
| 205 | * platform_device_add_data | 205 | * platform_device_add_data - add platform-specific data to a platform device |
| 206 | * @pdev: platform device allocated by platform_device_alloc to add resources to | 206 | * @pdev: platform device allocated by platform_device_alloc to add resources to |
| 207 | * @data: platform specific data for this platform device | 207 | * @data: platform specific data for this platform device |
| 208 | * @size: size of platform specific data | 208 | * @size: size of platform specific data |
| @@ -344,7 +344,7 @@ void platform_device_unregister(struct platform_device *pdev) | |||
| 344 | EXPORT_SYMBOL_GPL(platform_device_unregister); | 344 | EXPORT_SYMBOL_GPL(platform_device_unregister); |
| 345 | 345 | ||
| 346 | /** | 346 | /** |
| 347 | * platform_device_register_simple | 347 | * platform_device_register_simple - add a platform-level device and its resources |
| 348 | * @name: base name of the device we're adding | 348 | * @name: base name of the device we're adding |
| 349 | * @id: instance id | 349 | * @id: instance id |
| 350 | * @res: set of resources that needs to be allocated for the device | 350 | * @res: set of resources that needs to be allocated for the device |
| @@ -362,10 +362,12 @@ EXPORT_SYMBOL_GPL(platform_device_unregister); | |||
| 362 | * enumeration tasks, they don't fully conform to the Linux driver model. | 362 | * enumeration tasks, they don't fully conform to the Linux driver model. |
| 363 | * In particular, when such drivers are built as modules, they can't be | 363 | * In particular, when such drivers are built as modules, they can't be |
| 364 | * "hotplugged". | 364 | * "hotplugged". |
| 365 | * | ||
| 366 | * Returns &struct platform_device pointer on success, or ERR_PTR() on error. | ||
| 365 | */ | 367 | */ |
| 366 | struct platform_device *platform_device_register_simple(const char *name, | 368 | struct platform_device *platform_device_register_simple(const char *name, |
| 367 | int id, | 369 | int id, |
| 368 | struct resource *res, | 370 | const struct resource *res, |
| 369 | unsigned int num) | 371 | unsigned int num) |
| 370 | { | 372 | { |
| 371 | struct platform_device *pdev; | 373 | struct platform_device *pdev; |
| @@ -396,7 +398,7 @@ error: | |||
| 396 | EXPORT_SYMBOL_GPL(platform_device_register_simple); | 398 | EXPORT_SYMBOL_GPL(platform_device_register_simple); |
| 397 | 399 | ||
| 398 | /** | 400 | /** |
| 399 | * platform_device_register_data | 401 | * platform_device_register_data - add a platform-level device with platform-specific data |
| 400 | * @parent: parent device for the device we're adding | 402 | * @parent: parent device for the device we're adding |
| 401 | * @name: base name of the device we're adding | 403 | * @name: base name of the device we're adding |
| 402 | * @id: instance id | 404 | * @id: instance id |
| @@ -408,6 +410,8 @@ EXPORT_SYMBOL_GPL(platform_device_register_simple); | |||
| 408 | * allocated for the device allows drivers using such devices to be | 410 | * allocated for the device allows drivers using such devices to be |
| 409 | * unloaded without waiting for the last reference to the device to be | 411 | * unloaded without waiting for the last reference to the device to be |
| 410 | * dropped. | 412 | * dropped. |
| 413 | * | ||
| 414 | * Returns &struct platform_device pointer on success, or ERR_PTR() on error. | ||
| 411 | */ | 415 | */ |
| 412 | struct platform_device *platform_device_register_data( | 416 | struct platform_device *platform_device_register_data( |
| 413 | struct device *parent, | 417 | struct device *parent, |
| @@ -473,7 +477,7 @@ static void platform_drv_shutdown(struct device *_dev) | |||
| 473 | } | 477 | } |
| 474 | 478 | ||
| 475 | /** | 479 | /** |
| 476 | * platform_driver_register | 480 | * platform_driver_register - register a driver for platform-level devices |
| 477 | * @drv: platform driver structure | 481 | * @drv: platform driver structure |
| 478 | */ | 482 | */ |
| 479 | int platform_driver_register(struct platform_driver *drv) | 483 | int platform_driver_register(struct platform_driver *drv) |
| @@ -491,7 +495,7 @@ int platform_driver_register(struct platform_driver *drv) | |||
| 491 | EXPORT_SYMBOL_GPL(platform_driver_register); | 495 | EXPORT_SYMBOL_GPL(platform_driver_register); |
| 492 | 496 | ||
| 493 | /** | 497 | /** |
| 494 | * platform_driver_unregister | 498 | * platform_driver_unregister - unregister a driver for platform-level devices |
| 495 | * @drv: platform driver structure | 499 | * @drv: platform driver structure |
| 496 | */ | 500 | */ |
| 497 | void platform_driver_unregister(struct platform_driver *drv) | 501 | void platform_driver_unregister(struct platform_driver *drv) |
| @@ -548,6 +552,66 @@ int __init_or_module platform_driver_probe(struct platform_driver *drv, | |||
| 548 | } | 552 | } |
| 549 | EXPORT_SYMBOL_GPL(platform_driver_probe); | 553 | EXPORT_SYMBOL_GPL(platform_driver_probe); |
| 550 | 554 | ||
| 555 | /** | ||
| 556 | * platform_create_bundle - register driver and create corresponding device | ||
| 557 | * @driver: platform driver structure | ||
| 558 | * @probe: the driver probe routine, probably from an __init section | ||
| 559 | * @res: set of resources that needs to be allocated for the device | ||
| 560 | * @n_res: number of resources | ||
| 561 | * @data: platform specific data for this platform device | ||
| 562 | * @size: size of platform specific data | ||
| 563 | * | ||
| 564 | * Use this in legacy-style modules that probe hardware directly and | ||
| 565 | * register a single platform device and corresponding platform driver. | ||
| 566 | * | ||
| 567 | * Returns &struct platform_device pointer on success, or ERR_PTR() on error. | ||
| 568 | */ | ||
| 569 | struct platform_device * __init_or_module platform_create_bundle( | ||
| 570 | struct platform_driver *driver, | ||
| 571 | int (*probe)(struct platform_device *), | ||
| 572 | struct resource *res, unsigned int n_res, | ||
| 573 | const void *data, size_t size) | ||
| 574 | { | ||
| 575 | struct platform_device *pdev; | ||
| 576 | int error; | ||
| 577 | |||
| 578 | pdev = platform_device_alloc(driver->driver.name, -1); | ||
| 579 | if (!pdev) { | ||
| 580 | error = -ENOMEM; | ||
| 581 | goto err_out; | ||
| 582 | } | ||
| 583 | |||
| 584 | if (res) { | ||
| 585 | error = platform_device_add_resources(pdev, res, n_res); | ||
| 586 | if (error) | ||
| 587 | goto err_pdev_put; | ||
| 588 | } | ||
| 589 | |||
| 590 | if (data) { | ||
| 591 | error = platform_device_add_data(pdev, data, size); | ||
| 592 | if (error) | ||
| 593 | goto err_pdev_put; | ||
| 594 | } | ||
| 595 | |||
| 596 | error = platform_device_add(pdev); | ||
| 597 | if (error) | ||
| 598 | goto err_pdev_put; | ||
| 599 | |||
| 600 | error = platform_driver_probe(driver, probe); | ||
| 601 | if (error) | ||
| 602 | goto err_pdev_del; | ||
| 603 | |||
| 604 | return pdev; | ||
| 605 | |||
| 606 | err_pdev_del: | ||
| 607 | platform_device_del(pdev); | ||
| 608 | err_pdev_put: | ||
| 609 | platform_device_put(pdev); | ||
| 610 | err_out: | ||
| 611 | return ERR_PTR(error); | ||
| 612 | } | ||
| 613 | EXPORT_SYMBOL_GPL(platform_create_bundle); | ||
| 614 | |||
| 551 | /* modalias support enables more hands-off userspace setup: | 615 | /* modalias support enables more hands-off userspace setup: |
| 552 | * (a) environment variable lets new-style hotplug events work once system is | 616 | * (a) environment variable lets new-style hotplug events work once system is |
| 553 | * fully running: "modprobe $MODALIAS" | 617 | * fully running: "modprobe $MODALIAS" |
| @@ -578,7 +642,7 @@ static int platform_uevent(struct device *dev, struct kobj_uevent_env *env) | |||
| 578 | } | 642 | } |
| 579 | 643 | ||
| 580 | static const struct platform_device_id *platform_match_id( | 644 | static const struct platform_device_id *platform_match_id( |
| 581 | struct platform_device_id *id, | 645 | const struct platform_device_id *id, |
| 582 | struct platform_device *pdev) | 646 | struct platform_device *pdev) |
| 583 | { | 647 | { |
| 584 | while (id->name[0]) { | 648 | while (id->name[0]) { |
| @@ -671,7 +735,7 @@ static void platform_pm_complete(struct device *dev) | |||
| 671 | 735 | ||
| 672 | #ifdef CONFIG_SUSPEND | 736 | #ifdef CONFIG_SUSPEND |
| 673 | 737 | ||
| 674 | static int platform_pm_suspend(struct device *dev) | 738 | int __weak platform_pm_suspend(struct device *dev) |
| 675 | { | 739 | { |
| 676 | struct device_driver *drv = dev->driver; | 740 | struct device_driver *drv = dev->driver; |
| 677 | int ret = 0; | 741 | int ret = 0; |
| @@ -689,7 +753,7 @@ static int platform_pm_suspend(struct device *dev) | |||
| 689 | return ret; | 753 | return ret; |
| 690 | } | 754 | } |
| 691 | 755 | ||
| 692 | static int platform_pm_suspend_noirq(struct device *dev) | 756 | int __weak platform_pm_suspend_noirq(struct device *dev) |
| 693 | { | 757 | { |
| 694 | struct device_driver *drv = dev->driver; | 758 | struct device_driver *drv = dev->driver; |
| 695 | int ret = 0; | 759 | int ret = 0; |
| @@ -705,7 +769,7 @@ static int platform_pm_suspend_noirq(struct device *dev) | |||
| 705 | return ret; | 769 | return ret; |
| 706 | } | 770 | } |
| 707 | 771 | ||
| 708 | static int platform_pm_resume(struct device *dev) | 772 | int __weak platform_pm_resume(struct device *dev) |
| 709 | { | 773 | { |
| 710 | struct device_driver *drv = dev->driver; | 774 | struct device_driver *drv = dev->driver; |
| 711 | int ret = 0; | 775 | int ret = 0; |
| @@ -723,7 +787,7 @@ static int platform_pm_resume(struct device *dev) | |||
| 723 | return ret; | 787 | return ret; |
| 724 | } | 788 | } |
| 725 | 789 | ||
| 726 | static int platform_pm_resume_noirq(struct device *dev) | 790 | int __weak platform_pm_resume_noirq(struct device *dev) |
| 727 | { | 791 | { |
| 728 | struct device_driver *drv = dev->driver; | 792 | struct device_driver *drv = dev->driver; |
| 729 | int ret = 0; | 793 | int ret = 0; |
| @@ -903,17 +967,17 @@ static int platform_pm_restore_noirq(struct device *dev) | |||
| 903 | 967 | ||
| 904 | int __weak platform_pm_runtime_suspend(struct device *dev) | 968 | int __weak platform_pm_runtime_suspend(struct device *dev) |
| 905 | { | 969 | { |
| 906 | return -ENOSYS; | 970 | return pm_generic_runtime_suspend(dev); |
| 907 | }; | 971 | }; |
| 908 | 972 | ||
| 909 | int __weak platform_pm_runtime_resume(struct device *dev) | 973 | int __weak platform_pm_runtime_resume(struct device *dev) |
| 910 | { | 974 | { |
| 911 | return -ENOSYS; | 975 | return pm_generic_runtime_resume(dev); |
| 912 | }; | 976 | }; |
| 913 | 977 | ||
| 914 | int __weak platform_pm_runtime_idle(struct device *dev) | 978 | int __weak platform_pm_runtime_idle(struct device *dev) |
| 915 | { | 979 | { |
| 916 | return -ENOSYS; | 980 | return pm_generic_runtime_idle(dev); |
| 917 | }; | 981 | }; |
| 918 | 982 | ||
| 919 | #else /* !CONFIG_PM_RUNTIME */ | 983 | #else /* !CONFIG_PM_RUNTIME */ |
| @@ -994,9 +1058,11 @@ static __initdata LIST_HEAD(early_platform_driver_list); | |||
| 994 | static __initdata LIST_HEAD(early_platform_device_list); | 1058 | static __initdata LIST_HEAD(early_platform_device_list); |
| 995 | 1059 | ||
| 996 | /** | 1060 | /** |
| 997 | * early_platform_driver_register | 1061 | * early_platform_driver_register - register early platform driver |
| 998 | * @epdrv: early_platform driver structure | 1062 | * @epdrv: early_platform driver structure |
| 999 | * @buf: string passed from early_param() | 1063 | * @buf: string passed from early_param() |
| 1064 | * | ||
| 1065 | * Helper function for early_platform_init() / early_platform_init_buffer() | ||
| 1000 | */ | 1066 | */ |
| 1001 | int __init early_platform_driver_register(struct early_platform_driver *epdrv, | 1067 | int __init early_platform_driver_register(struct early_platform_driver *epdrv, |
| 1002 | char *buf) | 1068 | char *buf) |
| @@ -1048,9 +1114,12 @@ int __init early_platform_driver_register(struct early_platform_driver *epdrv, | |||
| 1048 | } | 1114 | } |
| 1049 | 1115 | ||
| 1050 | /** | 1116 | /** |
| 1051 | * early_platform_add_devices - add a numbers of early platform devices | 1117 | * early_platform_add_devices - adds a number of early platform devices |
| 1052 | * @devs: array of early platform devices to add | 1118 | * @devs: array of early platform devices to add |
| 1053 | * @num: number of early platform devices in array | 1119 | * @num: number of early platform devices in array |
| 1120 | * | ||
| 1121 | * Used by early architecture code to register early platform devices and | ||
| 1122 | * their platform data. | ||
| 1054 | */ | 1123 | */ |
| 1055 | void __init early_platform_add_devices(struct platform_device **devs, int num) | 1124 | void __init early_platform_add_devices(struct platform_device **devs, int num) |
| 1056 | { | 1125 | { |
| @@ -1070,8 +1139,12 @@ void __init early_platform_add_devices(struct platform_device **devs, int num) | |||
| 1070 | } | 1139 | } |
| 1071 | 1140 | ||
| 1072 | /** | 1141 | /** |
| 1073 | * early_platform_driver_register_all | 1142 | * early_platform_driver_register_all - register early platform drivers |
| 1074 | * @class_str: string to identify early platform driver class | 1143 | * @class_str: string to identify early platform driver class |
| 1144 | * | ||
| 1145 | * Used by architecture code to register all early platform drivers | ||
| 1146 | * for a certain class. If omitted then only early platform drivers | ||
| 1147 | * with matching kernel command line class parameters will be registered. | ||
| 1075 | */ | 1148 | */ |
| 1076 | void __init early_platform_driver_register_all(char *class_str) | 1149 | void __init early_platform_driver_register_all(char *class_str) |
| 1077 | { | 1150 | { |
| @@ -1093,7 +1166,7 @@ void __init early_platform_driver_register_all(char *class_str) | |||
| 1093 | } | 1166 | } |
| 1094 | 1167 | ||
| 1095 | /** | 1168 | /** |
| 1096 | * early_platform_match | 1169 | * early_platform_match - find early platform device matching driver |
| 1097 | * @epdrv: early platform driver structure | 1170 | * @epdrv: early platform driver structure |
| 1098 | * @id: id to match against | 1171 | * @id: id to match against |
| 1099 | */ | 1172 | */ |
| @@ -1111,7 +1184,7 @@ early_platform_match(struct early_platform_driver *epdrv, int id) | |||
| 1111 | } | 1184 | } |
| 1112 | 1185 | ||
| 1113 | /** | 1186 | /** |
| 1114 | * early_platform_left | 1187 | * early_platform_left - check if early platform driver has matching devices |
| 1115 | * @epdrv: early platform driver structure | 1188 | * @epdrv: early platform driver structure |
| 1116 | * @id: return true if id or above exists | 1189 | * @id: return true if id or above exists |
| 1117 | */ | 1190 | */ |
| @@ -1129,7 +1202,7 @@ static __init int early_platform_left(struct early_platform_driver *epdrv, | |||
| 1129 | } | 1202 | } |
| 1130 | 1203 | ||
| 1131 | /** | 1204 | /** |
| 1132 | * early_platform_driver_probe_id | 1205 | * early_platform_driver_probe_id - probe drivers matching class_str and id |
| 1133 | * @class_str: string to identify early platform driver class | 1206 | * @class_str: string to identify early platform driver class |
| 1134 | * @id: id to match against | 1207 | * @id: id to match against |
| 1135 | * @nr_probe: number of platform devices to successfully probe before exiting | 1208 | * @nr_probe: number of platform devices to successfully probe before exiting |
| @@ -1181,6 +1254,26 @@ static int __init early_platform_driver_probe_id(char *class_str, | |||
| 1181 | } | 1254 | } |
| 1182 | 1255 | ||
| 1183 | if (match) { | 1256 | if (match) { |
| 1257 | /* | ||
| 1258 | * Set up a sensible init_name to enable | ||
| 1259 | * dev_name() and others to be used before the | ||
| 1260 | * rest of the driver core is initialized. | ||
| 1261 | */ | ||
| 1262 | if (!match->dev.init_name && slab_is_available()) { | ||
| 1263 | if (match->id != -1) | ||
| 1264 | match->dev.init_name = | ||
| 1265 | kasprintf(GFP_KERNEL, "%s.%d", | ||
| 1266 | match->name, | ||
| 1267 | match->id); | ||
| 1268 | else | ||
| 1269 | match->dev.init_name = | ||
| 1270 | kasprintf(GFP_KERNEL, "%s", | ||
| 1271 | match->name); | ||
| 1272 | |||
| 1273 | if (!match->dev.init_name) | ||
| 1274 | return -ENOMEM; | ||
| 1275 | } | ||
| 1276 | |||
| 1184 | if (epdrv->pdrv->probe(match)) | 1277 | if (epdrv->pdrv->probe(match)) |
| 1185 | pr_warning("%s: unable to probe %s early.\n", | 1278 | pr_warning("%s: unable to probe %s early.\n", |
| 1186 | class_str, match->name); | 1279 | class_str, match->name); |
| @@ -1199,10 +1292,14 @@ static int __init early_platform_driver_probe_id(char *class_str, | |||
| 1199 | } | 1292 | } |
| 1200 | 1293 | ||
| 1201 | /** | 1294 | /** |
| 1202 | * early_platform_driver_probe | 1295 | * early_platform_driver_probe - probe a class of registered drivers |
| 1203 | * @class_str: string to identify early platform driver class | 1296 | * @class_str: string to identify early platform driver class |
| 1204 | * @nr_probe: number of platform devices to successfully probe before exiting | 1297 | * @nr_probe: number of platform devices to successfully probe before exiting |
| 1205 | * @user_only: only probe user specified early platform devices | 1298 | * @user_only: only probe user specified early platform devices |
| 1299 | * | ||
| 1300 | * Used by architecture code to probe registered early platform drivers | ||
| 1301 | * within a certain class. For probe to happen a registered early platform | ||
| 1302 | * device matching a registered early platform driver is needed. | ||
| 1206 | */ | 1303 | */ |
| 1207 | int __init early_platform_driver_probe(char *class_str, | 1304 | int __init early_platform_driver_probe(char *class_str, |
| 1208 | int nr_probe, | 1305 | int nr_probe, |
