diff options
| author | Michal Marek <mmarek@suse.cz> | 2010-08-04 07:59:13 -0400 | 
|---|---|---|
| committer | Michal Marek <mmarek@suse.cz> | 2010-08-04 07:59:13 -0400 | 
| commit | 772320e84588dcbe1600ffb83e5f328f2209ac2a (patch) | |
| tree | a7de21b79340aeaa17c58126f6b801b82c77b53a /drivers/base/platform.c | |
| parent | 1ce53adf13a54375d2a5c7cdbe341b2558389615 (diff) | |
| parent | 9fe6206f400646a2322096b56c59891d530e8d51 (diff) | |
Merge commit 'v2.6.35' into kbuild/kbuild
Conflicts:
	arch/powerpc/Makefile
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, | 
