diff options
Diffstat (limited to 'drivers/regulator')
-rw-r--r-- | drivers/regulator/core.c | 62 |
1 files changed, 48 insertions, 14 deletions
diff --git a/drivers/regulator/core.c b/drivers/regulator/core.c index 91ba9bfaa706..24e05b7607b4 100644 --- a/drivers/regulator/core.c +++ b/drivers/regulator/core.c | |||
@@ -37,7 +37,7 @@ static int has_full_constraints; | |||
37 | */ | 37 | */ |
38 | struct regulator_map { | 38 | struct regulator_map { |
39 | struct list_head list; | 39 | struct list_head list; |
40 | struct device *dev; | 40 | const char *dev_name; /* The dev_name() for the consumer */ |
41 | const char *supply; | 41 | const char *supply; |
42 | struct regulator_dev *regulator; | 42 | struct regulator_dev *regulator; |
43 | }; | 43 | }; |
@@ -857,23 +857,33 @@ out: | |||
857 | * set_consumer_device_supply: Bind a regulator to a symbolic supply | 857 | * set_consumer_device_supply: Bind a regulator to a symbolic supply |
858 | * @rdev: regulator source | 858 | * @rdev: regulator source |
859 | * @consumer_dev: device the supply applies to | 859 | * @consumer_dev: device the supply applies to |
860 | * @consumer_dev_name: dev_name() string for device supply applies to | ||
860 | * @supply: symbolic name for supply | 861 | * @supply: symbolic name for supply |
861 | * | 862 | * |
862 | * Allows platform initialisation code to map physical regulator | 863 | * Allows platform initialisation code to map physical regulator |
863 | * sources to symbolic names for supplies for use by devices. Devices | 864 | * sources to symbolic names for supplies for use by devices. Devices |
864 | * should use these symbolic names to request regulators, avoiding the | 865 | * should use these symbolic names to request regulators, avoiding the |
865 | * need to provide board-specific regulator names as platform data. | 866 | * need to provide board-specific regulator names as platform data. |
867 | * | ||
868 | * Only one of consumer_dev and consumer_dev_name may be specified. | ||
866 | */ | 869 | */ |
867 | static int set_consumer_device_supply(struct regulator_dev *rdev, | 870 | static int set_consumer_device_supply(struct regulator_dev *rdev, |
868 | struct device *consumer_dev, const char *supply) | 871 | struct device *consumer_dev, const char *consumer_dev_name, |
872 | const char *supply) | ||
869 | { | 873 | { |
870 | struct regulator_map *node; | 874 | struct regulator_map *node; |
871 | 875 | ||
876 | if (consumer_dev && consumer_dev_name) | ||
877 | return -EINVAL; | ||
878 | |||
879 | if (!consumer_dev_name && consumer_dev) | ||
880 | consumer_dev_name = dev_name(consumer_dev); | ||
881 | |||
872 | if (supply == NULL) | 882 | if (supply == NULL) |
873 | return -EINVAL; | 883 | return -EINVAL; |
874 | 884 | ||
875 | list_for_each_entry(node, ®ulator_map_list, list) { | 885 | list_for_each_entry(node, ®ulator_map_list, list) { |
876 | if (consumer_dev != node->dev) | 886 | if (consumer_dev_name != node->dev_name) |
877 | continue; | 887 | continue; |
878 | if (strcmp(node->supply, supply) != 0) | 888 | if (strcmp(node->supply, supply) != 0) |
879 | continue; | 889 | continue; |
@@ -891,25 +901,38 @@ static int set_consumer_device_supply(struct regulator_dev *rdev, | |||
891 | return -ENOMEM; | 901 | return -ENOMEM; |
892 | 902 | ||
893 | node->regulator = rdev; | 903 | node->regulator = rdev; |
894 | node->dev = consumer_dev; | 904 | node->dev_name = kstrdup(consumer_dev_name, GFP_KERNEL); |
895 | node->supply = supply; | 905 | node->supply = supply; |
896 | 906 | ||
907 | if (node->dev_name == NULL) { | ||
908 | kfree(node); | ||
909 | return -ENOMEM; | ||
910 | } | ||
911 | |||
897 | list_add(&node->list, ®ulator_map_list); | 912 | list_add(&node->list, ®ulator_map_list); |
898 | return 0; | 913 | return 0; |
899 | } | 914 | } |
900 | 915 | ||
901 | static void unset_consumer_device_supply(struct regulator_dev *rdev, | 916 | static void unset_consumer_device_supply(struct regulator_dev *rdev, |
902 | struct device *consumer_dev) | 917 | const char *consumer_dev_name, struct device *consumer_dev) |
903 | { | 918 | { |
904 | struct regulator_map *node, *n; | 919 | struct regulator_map *node, *n; |
905 | 920 | ||
921 | if (consumer_dev && !consumer_dev_name) | ||
922 | consumer_dev_name = dev_name(consumer_dev); | ||
923 | |||
906 | list_for_each_entry_safe(node, n, ®ulator_map_list, list) { | 924 | list_for_each_entry_safe(node, n, ®ulator_map_list, list) { |
907 | if (rdev == node->regulator && | 925 | if (rdev != node->regulator) |
908 | consumer_dev == node->dev) { | 926 | continue; |
909 | list_del(&node->list); | 927 | |
910 | kfree(node); | 928 | if (consumer_dev_name && node->dev_name && |
911 | return; | 929 | strcmp(consumer_dev_name, node->dev_name)) |
912 | } | 930 | continue; |
931 | |||
932 | list_del(&node->list); | ||
933 | kfree(node->dev_name); | ||
934 | kfree(node); | ||
935 | return; | ||
913 | } | 936 | } |
914 | } | 937 | } |
915 | 938 | ||
@@ -920,6 +943,7 @@ static void unset_regulator_supplies(struct regulator_dev *rdev) | |||
920 | list_for_each_entry_safe(node, n, ®ulator_map_list, list) { | 943 | list_for_each_entry_safe(node, n, ®ulator_map_list, list) { |
921 | if (rdev == node->regulator) { | 944 | if (rdev == node->regulator) { |
922 | list_del(&node->list); | 945 | list_del(&node->list); |
946 | kfree(node->dev_name); | ||
923 | kfree(node); | 947 | kfree(node); |
924 | return; | 948 | return; |
925 | } | 949 | } |
@@ -1019,17 +1043,25 @@ struct regulator *regulator_get(struct device *dev, const char *id) | |||
1019 | struct regulator_dev *rdev; | 1043 | struct regulator_dev *rdev; |
1020 | struct regulator_map *map; | 1044 | struct regulator_map *map; |
1021 | struct regulator *regulator = ERR_PTR(-ENODEV); | 1045 | struct regulator *regulator = ERR_PTR(-ENODEV); |
1046 | const char *devname = NULL; | ||
1022 | 1047 | ||
1023 | if (id == NULL) { | 1048 | if (id == NULL) { |
1024 | printk(KERN_ERR "regulator: get() with no identifier\n"); | 1049 | printk(KERN_ERR "regulator: get() with no identifier\n"); |
1025 | return regulator; | 1050 | return regulator; |
1026 | } | 1051 | } |
1027 | 1052 | ||
1053 | if (dev) | ||
1054 | devname = dev_name(dev); | ||
1055 | |||
1028 | mutex_lock(®ulator_list_mutex); | 1056 | mutex_lock(®ulator_list_mutex); |
1029 | 1057 | ||
1030 | list_for_each_entry(map, ®ulator_map_list, list) { | 1058 | list_for_each_entry(map, ®ulator_map_list, list) { |
1031 | if (dev == map->dev && | 1059 | /* If the mapping has a device set up it must match */ |
1032 | strcmp(map->supply, id) == 0) { | 1060 | if (map->dev_name && |
1061 | (!devname || strcmp(map->dev_name, devname))) | ||
1062 | continue; | ||
1063 | |||
1064 | if (strcmp(map->supply, id) == 0) { | ||
1033 | rdev = map->regulator; | 1065 | rdev = map->regulator; |
1034 | goto found; | 1066 | goto found; |
1035 | } | 1067 | } |
@@ -2091,11 +2123,13 @@ struct regulator_dev *regulator_register(struct regulator_desc *regulator_desc, | |||
2091 | for (i = 0; i < init_data->num_consumer_supplies; i++) { | 2123 | for (i = 0; i < init_data->num_consumer_supplies; i++) { |
2092 | ret = set_consumer_device_supply(rdev, | 2124 | ret = set_consumer_device_supply(rdev, |
2093 | init_data->consumer_supplies[i].dev, | 2125 | init_data->consumer_supplies[i].dev, |
2126 | init_data->consumer_supplies[i].dev_name, | ||
2094 | init_data->consumer_supplies[i].supply); | 2127 | init_data->consumer_supplies[i].supply); |
2095 | if (ret < 0) { | 2128 | if (ret < 0) { |
2096 | for (--i; i >= 0; i--) | 2129 | for (--i; i >= 0; i--) |
2097 | unset_consumer_device_supply(rdev, | 2130 | unset_consumer_device_supply(rdev, |
2098 | init_data->consumer_supplies[i].dev); | 2131 | init_data->consumer_supplies[i].dev_name, |
2132 | init_data->consumer_supplies[i].dev); | ||
2099 | goto scrub; | 2133 | goto scrub; |
2100 | } | 2134 | } |
2101 | } | 2135 | } |