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.c323
1 files changed, 283 insertions, 40 deletions
diff --git a/drivers/base/platform.c b/drivers/base/platform.c
index 349a1013603f..456594bd97bc 100644
--- a/drivers/base/platform.c
+++ b/drivers/base/platform.c
@@ -69,7 +69,8 @@ EXPORT_SYMBOL_GPL(platform_get_irq);
69 * @name: resource name 69 * @name: resource name
70 */ 70 */
71struct resource *platform_get_resource_byname(struct platform_device *dev, 71struct resource *platform_get_resource_byname(struct platform_device *dev,
72 unsigned int type, char *name) 72 unsigned int type,
73 const char *name)
73{ 74{
74 int i; 75 int i;
75 76
@@ -88,7 +89,7 @@ EXPORT_SYMBOL_GPL(platform_get_resource_byname);
88 * @dev: platform device 89 * @dev: platform device
89 * @name: IRQ name 90 * @name: IRQ name
90 */ 91 */
91int platform_get_irq_byname(struct platform_device *dev, char *name) 92int platform_get_irq_byname(struct platform_device *dev, const char *name)
92{ 93{
93 struct resource *r = platform_get_resource_byname(dev, IORESOURCE_IRQ, 94 struct resource *r = platform_get_resource_byname(dev, IORESOURCE_IRQ,
94 name); 95 name);
@@ -244,7 +245,7 @@ int platform_device_add(struct platform_device *pdev)
244 if (pdev->id != -1) 245 if (pdev->id != -1)
245 dev_set_name(&pdev->dev, "%s.%d", pdev->name, pdev->id); 246 dev_set_name(&pdev->dev, "%s.%d", pdev->name, pdev->id);
246 else 247 else
247 dev_set_name(&pdev->dev, pdev->name); 248 dev_set_name(&pdev->dev, "%s", pdev->name);
248 249
249 for (i = 0; i < pdev->num_resources; i++) { 250 for (i = 0; i < pdev->num_resources; i++) {
250 struct resource *p, *r = &pdev->resource[i]; 251 struct resource *p, *r = &pdev->resource[i];
@@ -469,22 +470,6 @@ static void platform_drv_shutdown(struct device *_dev)
469 drv->shutdown(dev); 470 drv->shutdown(dev);
470} 471}
471 472
472static int platform_drv_suspend(struct device *_dev, pm_message_t state)
473{
474 struct platform_driver *drv = to_platform_driver(_dev->driver);
475 struct platform_device *dev = to_platform_device(_dev);
476
477 return drv->suspend(dev, state);
478}
479
480static int platform_drv_resume(struct device *_dev)
481{
482 struct platform_driver *drv = to_platform_driver(_dev->driver);
483 struct platform_device *dev = to_platform_device(_dev);
484
485 return drv->resume(dev);
486}
487
488/** 473/**
489 * platform_driver_register 474 * platform_driver_register
490 * @drv: platform driver structure 475 * @drv: platform driver structure
@@ -498,10 +483,7 @@ int platform_driver_register(struct platform_driver *drv)
498 drv->driver.remove = platform_drv_remove; 483 drv->driver.remove = platform_drv_remove;
499 if (drv->shutdown) 484 if (drv->shutdown)
500 drv->driver.shutdown = platform_drv_shutdown; 485 drv->driver.shutdown = platform_drv_shutdown;
501 if (drv->suspend) 486
502 drv->driver.suspend = platform_drv_suspend;
503 if (drv->resume)
504 drv->driver.resume = platform_drv_resume;
505 return driver_register(&drv->driver); 487 return driver_register(&drv->driver);
506} 488}
507EXPORT_SYMBOL_GPL(platform_driver_register); 489EXPORT_SYMBOL_GPL(platform_driver_register);
@@ -584,10 +566,25 @@ static int platform_uevent(struct device *dev, struct kobj_uevent_env *env)
584{ 566{
585 struct platform_device *pdev = to_platform_device(dev); 567 struct platform_device *pdev = to_platform_device(dev);
586 568
587 add_uevent_var(env, "MODALIAS=platform:%s", pdev->name); 569 add_uevent_var(env, "MODALIAS=%s%s", PLATFORM_MODULE_PREFIX,
570 (pdev->id_entry) ? pdev->id_entry->name : pdev->name);
588 return 0; 571 return 0;
589} 572}
590 573
574static const struct platform_device_id *platform_match_id(
575 struct platform_device_id *id,
576 struct platform_device *pdev)
577{
578 while (id->name[0]) {
579 if (strcmp(pdev->name, id->name) == 0) {
580 pdev->id_entry = id;
581 return id;
582 }
583 id++;
584 }
585 return NULL;
586}
587
591/** 588/**
592 * platform_match - bind platform device to platform driver. 589 * platform_match - bind platform device to platform driver.
593 * @dev: device. 590 * @dev: device.
@@ -603,9 +600,14 @@ static int platform_uevent(struct device *dev, struct kobj_uevent_env *env)
603 */ 600 */
604static int platform_match(struct device *dev, struct device_driver *drv) 601static int platform_match(struct device *dev, struct device_driver *drv)
605{ 602{
606 struct platform_device *pdev; 603 struct platform_device *pdev = to_platform_device(dev);
604 struct platform_driver *pdrv = to_platform_driver(drv);
605
606 /* match against the id table first */
607 if (pdrv->id_table)
608 return platform_match_id(pdrv->id_table, pdev) != NULL;
607 609
608 pdev = container_of(dev, struct platform_device, dev); 610 /* fall-back to driver name match */
609 return (strcmp(pdev->name, drv->name) == 0); 611 return (strcmp(pdev->name, drv->name) == 0);
610} 612}
611 613
@@ -613,46 +615,48 @@ static int platform_match(struct device *dev, struct device_driver *drv)
613 615
614static int platform_legacy_suspend(struct device *dev, pm_message_t mesg) 616static int platform_legacy_suspend(struct device *dev, pm_message_t mesg)
615{ 617{
618 struct platform_driver *pdrv = to_platform_driver(dev->driver);
619 struct platform_device *pdev = to_platform_device(dev);
616 int ret = 0; 620 int ret = 0;
617 621
618 if (dev->driver && dev->driver->suspend) 622 if (dev->driver && pdrv->suspend)
619 ret = dev->driver->suspend(dev, mesg); 623 ret = pdrv->suspend(pdev, mesg);
620 624
621 return ret; 625 return ret;
622} 626}
623 627
624static int platform_legacy_suspend_late(struct device *dev, pm_message_t mesg) 628static int platform_legacy_suspend_late(struct device *dev, pm_message_t mesg)
625{ 629{
626 struct platform_driver *drv = to_platform_driver(dev->driver); 630 struct platform_driver *pdrv = to_platform_driver(dev->driver);
627 struct platform_device *pdev; 631 struct platform_device *pdev = to_platform_device(dev);
628 int ret = 0; 632 int ret = 0;
629 633
630 pdev = container_of(dev, struct platform_device, dev); 634 if (dev->driver && pdrv->suspend_late)
631 if (dev->driver && drv->suspend_late) 635 ret = pdrv->suspend_late(pdev, mesg);
632 ret = drv->suspend_late(pdev, mesg);
633 636
634 return ret; 637 return ret;
635} 638}
636 639
637static int platform_legacy_resume_early(struct device *dev) 640static int platform_legacy_resume_early(struct device *dev)
638{ 641{
639 struct platform_driver *drv = to_platform_driver(dev->driver); 642 struct platform_driver *pdrv = to_platform_driver(dev->driver);
640 struct platform_device *pdev; 643 struct platform_device *pdev = to_platform_device(dev);
641 int ret = 0; 644 int ret = 0;
642 645
643 pdev = container_of(dev, struct platform_device, dev); 646 if (dev->driver && pdrv->resume_early)
644 if (dev->driver && drv->resume_early) 647 ret = pdrv->resume_early(pdev);
645 ret = drv->resume_early(pdev);
646 648
647 return ret; 649 return ret;
648} 650}
649 651
650static int platform_legacy_resume(struct device *dev) 652static int platform_legacy_resume(struct device *dev)
651{ 653{
654 struct platform_driver *pdrv = to_platform_driver(dev->driver);
655 struct platform_device *pdev = to_platform_device(dev);
652 int ret = 0; 656 int ret = 0;
653 657
654 if (dev->driver && dev->driver->resume) 658 if (dev->driver && pdrv->resume)
655 ret = dev->driver->resume(dev); 659 ret = pdrv->resume(pdev);
656 660
657 return ret; 661 return ret;
658} 662}
@@ -956,6 +960,8 @@ int __init platform_bus_init(void)
956{ 960{
957 int error; 961 int error;
958 962
963 early_platform_cleanup();
964
959 error = device_register(&platform_bus); 965 error = device_register(&platform_bus);
960 if (error) 966 if (error)
961 return error; 967 return error;
@@ -986,3 +992,240 @@ u64 dma_get_required_mask(struct device *dev)
986} 992}
987EXPORT_SYMBOL_GPL(dma_get_required_mask); 993EXPORT_SYMBOL_GPL(dma_get_required_mask);
988#endif 994#endif
995
996static __initdata LIST_HEAD(early_platform_driver_list);
997static __initdata LIST_HEAD(early_platform_device_list);
998
999/**
1000 * early_platform_driver_register
1001 * @epdrv: early_platform driver structure
1002 * @buf: string passed from early_param()
1003 */
1004int __init early_platform_driver_register(struct early_platform_driver *epdrv,
1005 char *buf)
1006{
1007 unsigned long index;
1008 int n;
1009
1010 /* Simply add the driver to the end of the global list.
1011 * Drivers will by default be put on the list in compiled-in order.
1012 */
1013 if (!epdrv->list.next) {
1014 INIT_LIST_HEAD(&epdrv->list);
1015 list_add_tail(&epdrv->list, &early_platform_driver_list);
1016 }
1017
1018 /* If the user has specified device then make sure the driver
1019 * gets prioritized. The driver of the last device specified on
1020 * command line will be put first on the list.
1021 */
1022 n = strlen(epdrv->pdrv->driver.name);
1023 if (buf && !strncmp(buf, epdrv->pdrv->driver.name, n)) {
1024 list_move(&epdrv->list, &early_platform_driver_list);
1025
1026 if (!strcmp(buf, epdrv->pdrv->driver.name))
1027 epdrv->requested_id = -1;
1028 else if (buf[n] == '.' && strict_strtoul(&buf[n + 1], 10,
1029 &index) == 0)
1030 epdrv->requested_id = index;
1031 else
1032 epdrv->requested_id = EARLY_PLATFORM_ID_ERROR;
1033 }
1034
1035 return 0;
1036}
1037
1038/**
1039 * early_platform_add_devices - add a numbers of early platform devices
1040 * @devs: array of early platform devices to add
1041 * @num: number of early platform devices in array
1042 */
1043void __init early_platform_add_devices(struct platform_device **devs, int num)
1044{
1045 struct device *dev;
1046 int i;
1047
1048 /* simply add the devices to list */
1049 for (i = 0; i < num; i++) {
1050 dev = &devs[i]->dev;
1051
1052 if (!dev->devres_head.next) {
1053 INIT_LIST_HEAD(&dev->devres_head);
1054 list_add_tail(&dev->devres_head,
1055 &early_platform_device_list);
1056 }
1057 }
1058}
1059
1060/**
1061 * early_platform_driver_register_all
1062 * @class_str: string to identify early platform driver class
1063 */
1064void __init early_platform_driver_register_all(char *class_str)
1065{
1066 /* The "class_str" parameter may or may not be present on the kernel
1067 * command line. If it is present then there may be more than one
1068 * matching parameter.
1069 *
1070 * Since we register our early platform drivers using early_param()
1071 * we need to make sure that they also get registered in the case
1072 * when the parameter is missing from the kernel command line.
1073 *
1074 * We use parse_early_options() to make sure the early_param() gets
1075 * called at least once. The early_param() may be called more than
1076 * once since the name of the preferred device may be specified on
1077 * the kernel command line. early_platform_driver_register() handles
1078 * this case for us.
1079 */
1080 parse_early_options(class_str);
1081}
1082
1083/**
1084 * early_platform_match
1085 * @epdrv: early platform driver structure
1086 * @id: id to match against
1087 */
1088static __init struct platform_device *
1089early_platform_match(struct early_platform_driver *epdrv, int id)
1090{
1091 struct platform_device *pd;
1092
1093 list_for_each_entry(pd, &early_platform_device_list, dev.devres_head)
1094 if (platform_match(&pd->dev, &epdrv->pdrv->driver))
1095 if (pd->id == id)
1096 return pd;
1097
1098 return NULL;
1099}
1100
1101/**
1102 * early_platform_left
1103 * @epdrv: early platform driver structure
1104 * @id: return true if id or above exists
1105 */
1106static __init int early_platform_left(struct early_platform_driver *epdrv,
1107 int id)
1108{
1109 struct platform_device *pd;
1110
1111 list_for_each_entry(pd, &early_platform_device_list, dev.devres_head)
1112 if (platform_match(&pd->dev, &epdrv->pdrv->driver))
1113 if (pd->id >= id)
1114 return 1;
1115
1116 return 0;
1117}
1118
1119/**
1120 * early_platform_driver_probe_id
1121 * @class_str: string to identify early platform driver class
1122 * @id: id to match against
1123 * @nr_probe: number of platform devices to successfully probe before exiting
1124 */
1125static int __init early_platform_driver_probe_id(char *class_str,
1126 int id,
1127 int nr_probe)
1128{
1129 struct early_platform_driver *epdrv;
1130 struct platform_device *match;
1131 int match_id;
1132 int n = 0;
1133 int left = 0;
1134
1135 list_for_each_entry(epdrv, &early_platform_driver_list, list) {
1136 /* only use drivers matching our class_str */
1137 if (strcmp(class_str, epdrv->class_str))
1138 continue;
1139
1140 if (id == -2) {
1141 match_id = epdrv->requested_id;
1142 left = 1;
1143
1144 } else {
1145 match_id = id;
1146 left += early_platform_left(epdrv, id);
1147
1148 /* skip requested id */
1149 switch (epdrv->requested_id) {
1150 case EARLY_PLATFORM_ID_ERROR:
1151 case EARLY_PLATFORM_ID_UNSET:
1152 break;
1153 default:
1154 if (epdrv->requested_id == id)
1155 match_id = EARLY_PLATFORM_ID_UNSET;
1156 }
1157 }
1158
1159 switch (match_id) {
1160 case EARLY_PLATFORM_ID_ERROR:
1161 pr_warning("%s: unable to parse %s parameter\n",
1162 class_str, epdrv->pdrv->driver.name);
1163 /* fall-through */
1164 case EARLY_PLATFORM_ID_UNSET:
1165 match = NULL;
1166 break;
1167 default:
1168 match = early_platform_match(epdrv, match_id);
1169 }
1170
1171 if (match) {
1172 if (epdrv->pdrv->probe(match))
1173 pr_warning("%s: unable to probe %s early.\n",
1174 class_str, match->name);
1175 else
1176 n++;
1177 }
1178
1179 if (n >= nr_probe)
1180 break;
1181 }
1182
1183 if (left)
1184 return n;
1185 else
1186 return -ENODEV;
1187}
1188
1189/**
1190 * early_platform_driver_probe
1191 * @class_str: string to identify early platform driver class
1192 * @nr_probe: number of platform devices to successfully probe before exiting
1193 * @user_only: only probe user specified early platform devices
1194 */
1195int __init early_platform_driver_probe(char *class_str,
1196 int nr_probe,
1197 int user_only)
1198{
1199 int k, n, i;
1200
1201 n = 0;
1202 for (i = -2; n < nr_probe; i++) {
1203 k = early_platform_driver_probe_id(class_str, i, nr_probe - n);
1204
1205 if (k < 0)
1206 break;
1207
1208 n += k;
1209
1210 if (user_only)
1211 break;
1212 }
1213
1214 return n;
1215}
1216
1217/**
1218 * early_platform_cleanup - clean up early platform code
1219 */
1220void __init early_platform_cleanup(void)
1221{
1222 struct platform_device *pd, *pd2;
1223
1224 /* clean up the devres list used to chain devices */
1225 list_for_each_entry_safe(pd, pd2, &early_platform_device_list,
1226 dev.devres_head) {
1227 list_del(&pd->dev.devres_head);
1228 memset(&pd->dev.devres_head, 0, sizeof(pd->dev.devres_head));
1229 }
1230}
1231