aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/base/platform.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/base/platform.c')
-rw-r--r--drivers/base/platform.c139
1 files changed, 116 insertions, 23 deletions
diff --git a/drivers/base/platform.c b/drivers/base/platform.c
index 4fa954b07ac4..4b4b565c835f 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)
177EXPORT_SYMBOL_GPL(platform_device_alloc); 177EXPORT_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
@@ -202,7 +202,7 @@ int platform_device_add_resources(struct platform_device *pdev,
202EXPORT_SYMBOL_GPL(platform_device_add_resources); 202EXPORT_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)
344EXPORT_SYMBOL_GPL(platform_device_unregister); 344EXPORT_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,6 +362,8 @@ 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 */
366struct platform_device *platform_device_register_simple(const char *name, 368struct platform_device *platform_device_register_simple(const char *name,
367 int id, 369 int id,
@@ -396,7 +398,7 @@ error:
396EXPORT_SYMBOL_GPL(platform_device_register_simple); 398EXPORT_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 */
412struct platform_device *platform_device_register_data( 416struct platform_device *platform_device_register_data(
413 struct device *parent, 417 struct device *parent,
@@ -441,6 +445,7 @@ error:
441 platform_device_put(pdev); 445 platform_device_put(pdev);
442 return ERR_PTR(retval); 446 return ERR_PTR(retval);
443} 447}
448EXPORT_SYMBOL_GPL(platform_device_register_data);
444 449
445static int platform_drv_probe(struct device *_dev) 450static int platform_drv_probe(struct device *_dev)
446{ 451{
@@ -472,7 +477,7 @@ static void platform_drv_shutdown(struct device *_dev)
472} 477}
473 478
474/** 479/**
475 * platform_driver_register 480 * platform_driver_register - register a driver for platform-level devices
476 * @drv: platform driver structure 481 * @drv: platform driver structure
477 */ 482 */
478int platform_driver_register(struct platform_driver *drv) 483int platform_driver_register(struct platform_driver *drv)
@@ -490,7 +495,7 @@ int platform_driver_register(struct platform_driver *drv)
490EXPORT_SYMBOL_GPL(platform_driver_register); 495EXPORT_SYMBOL_GPL(platform_driver_register);
491 496
492/** 497/**
493 * platform_driver_unregister 498 * platform_driver_unregister - unregister a driver for platform-level devices
494 * @drv: platform driver structure 499 * @drv: platform driver structure
495 */ 500 */
496void platform_driver_unregister(struct platform_driver *drv) 501void platform_driver_unregister(struct platform_driver *drv)
@@ -547,6 +552,66 @@ int __init_or_module platform_driver_probe(struct platform_driver *drv,
547} 552}
548EXPORT_SYMBOL_GPL(platform_driver_probe); 553EXPORT_SYMBOL_GPL(platform_driver_probe);
549 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 */
569struct 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
606err_pdev_del:
607 platform_device_del(pdev);
608err_pdev_put:
609 platform_device_put(pdev);
610err_out:
611 return ERR_PTR(error);
612}
613EXPORT_SYMBOL_GPL(platform_create_bundle);
614
550/* modalias support enables more hands-off userspace setup: 615/* modalias support enables more hands-off userspace setup:
551 * (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
552 * fully running: "modprobe $MODALIAS" 617 * fully running: "modprobe $MODALIAS"
@@ -577,7 +642,7 @@ static int platform_uevent(struct device *dev, struct kobj_uevent_env *env)
577} 642}
578 643
579static const struct platform_device_id *platform_match_id( 644static const struct platform_device_id *platform_match_id(
580 struct platform_device_id *id, 645 const struct platform_device_id *id,
581 struct platform_device *pdev) 646 struct platform_device *pdev)
582{ 647{
583 while (id->name[0]) { 648 while (id->name[0]) {
@@ -993,14 +1058,16 @@ static __initdata LIST_HEAD(early_platform_driver_list);
993static __initdata LIST_HEAD(early_platform_device_list); 1058static __initdata LIST_HEAD(early_platform_device_list);
994 1059
995/** 1060/**
996 * early_platform_driver_register 1061 * early_platform_driver_register - register early platform driver
997 * @epdrv: early_platform driver structure 1062 * @epdrv: early_platform driver structure
998 * @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()
999 */ 1066 */
1000int __init early_platform_driver_register(struct early_platform_driver *epdrv, 1067int __init early_platform_driver_register(struct early_platform_driver *epdrv,
1001 char *buf) 1068 char *buf)
1002{ 1069{
1003 unsigned long index; 1070 char *tmp;
1004 int n; 1071 int n;
1005 1072
1006 /* Simply add the driver to the end of the global list. 1073 /* Simply add the driver to the end of the global list.
@@ -1019,22 +1086,40 @@ int __init early_platform_driver_register(struct early_platform_driver *epdrv,
1019 if (buf && !strncmp(buf, epdrv->pdrv->driver.name, n)) { 1086 if (buf && !strncmp(buf, epdrv->pdrv->driver.name, n)) {
1020 list_move(&epdrv->list, &early_platform_driver_list); 1087 list_move(&epdrv->list, &early_platform_driver_list);
1021 1088
1022 if (!strcmp(buf, epdrv->pdrv->driver.name)) 1089 /* Allow passing parameters after device name */
1090 if (buf[n] == '\0' || buf[n] == ',')
1023 epdrv->requested_id = -1; 1091 epdrv->requested_id = -1;
1024 else if (buf[n] == '.' && strict_strtoul(&buf[n + 1], 10, 1092 else {
1025 &index) == 0) 1093 epdrv->requested_id = simple_strtoul(&buf[n + 1],
1026 epdrv->requested_id = index; 1094 &tmp, 10);
1027 else 1095
1028 epdrv->requested_id = EARLY_PLATFORM_ID_ERROR; 1096 if (buf[n] != '.' || (tmp == &buf[n + 1])) {
1097 epdrv->requested_id = EARLY_PLATFORM_ID_ERROR;
1098 n = 0;
1099 } else
1100 n += strcspn(&buf[n + 1], ",") + 1;
1101 }
1102
1103 if (buf[n] == ',')
1104 n++;
1105
1106 if (epdrv->bufsize) {
1107 memcpy(epdrv->buffer, &buf[n],
1108 min_t(int, epdrv->bufsize, strlen(&buf[n]) + 1));
1109 epdrv->buffer[epdrv->bufsize - 1] = '\0';
1110 }
1029 } 1111 }
1030 1112
1031 return 0; 1113 return 0;
1032} 1114}
1033 1115
1034/** 1116/**
1035 * early_platform_add_devices - add a numbers of early platform devices 1117 * early_platform_add_devices - adds a number of early platform devices
1036 * @devs: array of early platform devices to add 1118 * @devs: array of early platform devices to add
1037 * @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.
1038 */ 1123 */
1039void __init early_platform_add_devices(struct platform_device **devs, int num) 1124void __init early_platform_add_devices(struct platform_device **devs, int num)
1040{ 1125{
@@ -1054,8 +1139,12 @@ void __init early_platform_add_devices(struct platform_device **devs, int num)
1054} 1139}
1055 1140
1056/** 1141/**
1057 * early_platform_driver_register_all 1142 * early_platform_driver_register_all - register early platform drivers
1058 * @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.
1059 */ 1148 */
1060void __init early_platform_driver_register_all(char *class_str) 1149void __init early_platform_driver_register_all(char *class_str)
1061{ 1150{
@@ -1077,7 +1166,7 @@ void __init early_platform_driver_register_all(char *class_str)
1077} 1166}
1078 1167
1079/** 1168/**
1080 * early_platform_match 1169 * early_platform_match - find early platform device matching driver
1081 * @epdrv: early platform driver structure 1170 * @epdrv: early platform driver structure
1082 * @id: id to match against 1171 * @id: id to match against
1083 */ 1172 */
@@ -1095,7 +1184,7 @@ early_platform_match(struct early_platform_driver *epdrv, int id)
1095} 1184}
1096 1185
1097/** 1186/**
1098 * early_platform_left 1187 * early_platform_left - check if early platform driver has matching devices
1099 * @epdrv: early platform driver structure 1188 * @epdrv: early platform driver structure
1100 * @id: return true if id or above exists 1189 * @id: return true if id or above exists
1101 */ 1190 */
@@ -1113,7 +1202,7 @@ static __init int early_platform_left(struct early_platform_driver *epdrv,
1113} 1202}
1114 1203
1115/** 1204/**
1116 * early_platform_driver_probe_id 1205 * early_platform_driver_probe_id - probe drivers matching class_str and id
1117 * @class_str: string to identify early platform driver class 1206 * @class_str: string to identify early platform driver class
1118 * @id: id to match against 1207 * @id: id to match against
1119 * @nr_probe: number of platform devices to successfully probe before exiting 1208 * @nr_probe: number of platform devices to successfully probe before exiting
@@ -1183,10 +1272,14 @@ static int __init early_platform_driver_probe_id(char *class_str,
1183} 1272}
1184 1273
1185/** 1274/**
1186 * early_platform_driver_probe 1275 * early_platform_driver_probe - probe a class of registered drivers
1187 * @class_str: string to identify early platform driver class 1276 * @class_str: string to identify early platform driver class
1188 * @nr_probe: number of platform devices to successfully probe before exiting 1277 * @nr_probe: number of platform devices to successfully probe before exiting
1189 * @user_only: only probe user specified early platform devices 1278 * @user_only: only probe user specified early platform devices
1279 *
1280 * Used by architecture code to probe registered early platform drivers
1281 * within a certain class. For probe to happen a registered early platform
1282 * device matching a registered early platform driver is needed.
1190 */ 1283 */
1191int __init early_platform_driver_probe(char *class_str, 1284int __init early_platform_driver_probe(char *class_str,
1192 int nr_probe, 1285 int nr_probe,