diff options
Diffstat (limited to 'drivers/regulator/of_regulator.c')
-rw-r--r-- | drivers/regulator/of_regulator.c | 68 |
1 files changed, 43 insertions, 25 deletions
diff --git a/drivers/regulator/of_regulator.c b/drivers/regulator/of_regulator.c index ea4f36f2cbe2..ee5e67bc8d5b 100644 --- a/drivers/regulator/of_regulator.c +++ b/drivers/regulator/of_regulator.c | |||
@@ -19,9 +19,7 @@ | |||
19 | static void of_get_regulation_constraints(struct device_node *np, | 19 | static void of_get_regulation_constraints(struct device_node *np, |
20 | struct regulator_init_data **init_data) | 20 | struct regulator_init_data **init_data) |
21 | { | 21 | { |
22 | const __be32 *min_uV, *max_uV, *uV_offset; | 22 | const __be32 *min_uV, *max_uV; |
23 | const __be32 *min_uA, *max_uA, *ramp_delay; | ||
24 | struct property *prop; | ||
25 | struct regulation_constraints *constraints = &(*init_data)->constraints; | 23 | struct regulation_constraints *constraints = &(*init_data)->constraints; |
26 | int ret; | 24 | int ret; |
27 | u32 pval; | 25 | u32 pval; |
@@ -42,36 +40,29 @@ static void of_get_regulation_constraints(struct device_node *np, | |||
42 | if (min_uV && max_uV && constraints->min_uV == constraints->max_uV) | 40 | if (min_uV && max_uV && constraints->min_uV == constraints->max_uV) |
43 | constraints->apply_uV = true; | 41 | constraints->apply_uV = true; |
44 | 42 | ||
45 | uV_offset = of_get_property(np, "regulator-microvolt-offset", NULL); | 43 | if (!of_property_read_u32(np, "regulator-microvolt-offset", &pval)) |
46 | if (uV_offset) | 44 | constraints->uV_offset = pval; |
47 | constraints->uV_offset = be32_to_cpu(*uV_offset); | 45 | if (!of_property_read_u32(np, "regulator-min-microamp", &pval)) |
48 | min_uA = of_get_property(np, "regulator-min-microamp", NULL); | 46 | constraints->min_uA = pval; |
49 | if (min_uA) | 47 | if (!of_property_read_u32(np, "regulator-max-microamp", &pval)) |
50 | constraints->min_uA = be32_to_cpu(*min_uA); | 48 | constraints->max_uA = pval; |
51 | max_uA = of_get_property(np, "regulator-max-microamp", NULL); | ||
52 | if (max_uA) | ||
53 | constraints->max_uA = be32_to_cpu(*max_uA); | ||
54 | 49 | ||
55 | /* Current change possible? */ | 50 | /* Current change possible? */ |
56 | if (constraints->min_uA != constraints->max_uA) | 51 | if (constraints->min_uA != constraints->max_uA) |
57 | constraints->valid_ops_mask |= REGULATOR_CHANGE_CURRENT; | 52 | constraints->valid_ops_mask |= REGULATOR_CHANGE_CURRENT; |
58 | 53 | ||
59 | if (of_find_property(np, "regulator-boot-on", NULL)) | 54 | constraints->boot_on = of_property_read_bool(np, "regulator-boot-on"); |
60 | constraints->boot_on = true; | 55 | constraints->always_on = of_property_read_bool(np, "regulator-always-on"); |
61 | 56 | if (!constraints->always_on) /* status change should be possible. */ | |
62 | if (of_find_property(np, "regulator-always-on", NULL)) | ||
63 | constraints->always_on = true; | ||
64 | else /* status change should be possible if not always on. */ | ||
65 | constraints->valid_ops_mask |= REGULATOR_CHANGE_STATUS; | 57 | constraints->valid_ops_mask |= REGULATOR_CHANGE_STATUS; |
66 | 58 | ||
67 | if (of_property_read_bool(np, "regulator-allow-bypass")) | 59 | if (of_property_read_bool(np, "regulator-allow-bypass")) |
68 | constraints->valid_ops_mask |= REGULATOR_CHANGE_BYPASS; | 60 | constraints->valid_ops_mask |= REGULATOR_CHANGE_BYPASS; |
69 | 61 | ||
70 | prop = of_find_property(np, "regulator-ramp-delay", NULL); | 62 | ret = of_property_read_u32(np, "regulator-ramp-delay", &pval); |
71 | if (prop && prop->value) { | 63 | if (!ret) { |
72 | ramp_delay = prop->value; | 64 | if (pval) |
73 | if (*ramp_delay) | 65 | constraints->ramp_delay = pval; |
74 | constraints->ramp_delay = be32_to_cpu(*ramp_delay); | ||
75 | else | 66 | else |
76 | constraints->ramp_disable = true; | 67 | constraints->ramp_disable = true; |
77 | } | 68 | } |
@@ -106,6 +97,20 @@ struct regulator_init_data *of_get_regulator_init_data(struct device *dev, | |||
106 | } | 97 | } |
107 | EXPORT_SYMBOL_GPL(of_get_regulator_init_data); | 98 | EXPORT_SYMBOL_GPL(of_get_regulator_init_data); |
108 | 99 | ||
100 | struct devm_of_regulator_matches { | ||
101 | struct of_regulator_match *matches; | ||
102 | unsigned int num_matches; | ||
103 | }; | ||
104 | |||
105 | static void devm_of_regulator_put_matches(struct device *dev, void *res) | ||
106 | { | ||
107 | struct devm_of_regulator_matches *devm_matches = res; | ||
108 | int i; | ||
109 | |||
110 | for (i = 0; i < devm_matches->num_matches; i++) | ||
111 | of_node_put(devm_matches->matches[i].of_node); | ||
112 | } | ||
113 | |||
109 | /** | 114 | /** |
110 | * of_regulator_match - extract multiple regulator init data from device tree. | 115 | * of_regulator_match - extract multiple regulator init data from device tree. |
111 | * @dev: device requesting the data | 116 | * @dev: device requesting the data |
@@ -119,7 +124,8 @@ EXPORT_SYMBOL_GPL(of_get_regulator_init_data); | |||
119 | * regulator. The data parsed from a child node will be matched to a regulator | 124 | * regulator. The data parsed from a child node will be matched to a regulator |
120 | * based on either the deprecated property regulator-compatible if present, | 125 | * based on either the deprecated property regulator-compatible if present, |
121 | * or otherwise the child node's name. Note that the match table is modified | 126 | * or otherwise the child node's name. Note that the match table is modified |
122 | * in place. | 127 | * in place and an additional of_node reference is taken for each matched |
128 | * regulator. | ||
123 | * | 129 | * |
124 | * Returns the number of matches found or a negative error code on failure. | 130 | * Returns the number of matches found or a negative error code on failure. |
125 | */ | 131 | */ |
@@ -131,10 +137,22 @@ int of_regulator_match(struct device *dev, struct device_node *node, | |||
131 | unsigned int i; | 137 | unsigned int i; |
132 | const char *name; | 138 | const char *name; |
133 | struct device_node *child; | 139 | struct device_node *child; |
140 | struct devm_of_regulator_matches *devm_matches; | ||
134 | 141 | ||
135 | if (!dev || !node) | 142 | if (!dev || !node) |
136 | return -EINVAL; | 143 | return -EINVAL; |
137 | 144 | ||
145 | devm_matches = devres_alloc(devm_of_regulator_put_matches, | ||
146 | sizeof(struct devm_of_regulator_matches), | ||
147 | GFP_KERNEL); | ||
148 | if (!devm_matches) | ||
149 | return -ENOMEM; | ||
150 | |||
151 | devm_matches->matches = matches; | ||
152 | devm_matches->num_matches = num_matches; | ||
153 | |||
154 | devres_add(dev, devm_matches); | ||
155 | |||
138 | for (i = 0; i < num_matches; i++) { | 156 | for (i = 0; i < num_matches; i++) { |
139 | struct of_regulator_match *match = &matches[i]; | 157 | struct of_regulator_match *match = &matches[i]; |
140 | match->init_data = NULL; | 158 | match->init_data = NULL; |
@@ -162,7 +180,7 @@ int of_regulator_match(struct device *dev, struct device_node *node, | |||
162 | child->name); | 180 | child->name); |
163 | return -EINVAL; | 181 | return -EINVAL; |
164 | } | 182 | } |
165 | match->of_node = child; | 183 | match->of_node = of_node_get(child); |
166 | count++; | 184 | count++; |
167 | break; | 185 | break; |
168 | } | 186 | } |