aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/regulator/gpio-regulator.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/regulator/gpio-regulator.c')
-rw-r--r--drivers/regulator/gpio-regulator.c104
1 files changed, 102 insertions, 2 deletions
diff --git a/drivers/regulator/gpio-regulator.c b/drivers/regulator/gpio-regulator.c
index 8b5944f2d7d1..5ffee5ec3660 100644
--- a/drivers/regulator/gpio-regulator.c
+++ b/drivers/regulator/gpio-regulator.c
@@ -28,9 +28,12 @@
28#include <linux/platform_device.h> 28#include <linux/platform_device.h>
29#include <linux/regulator/driver.h> 29#include <linux/regulator/driver.h>
30#include <linux/regulator/machine.h> 30#include <linux/regulator/machine.h>
31#include <linux/regulator/of_regulator.h>
31#include <linux/regulator/gpio-regulator.h> 32#include <linux/regulator/gpio-regulator.h>
32#include <linux/gpio.h> 33#include <linux/gpio.h>
33#include <linux/slab.h> 34#include <linux/slab.h>
35#include <linux/of.h>
36#include <linux/of_gpio.h>
34 37
35struct gpio_regulator_data { 38struct gpio_regulator_data {
36 struct regulator_desc desc; 39 struct regulator_desc desc;
@@ -129,18 +132,108 @@ static struct regulator_ops gpio_regulator_voltage_ops = {
129 .list_voltage = gpio_regulator_list_voltage, 132 .list_voltage = gpio_regulator_list_voltage,
130}; 133};
131 134
135struct gpio_regulator_config *
136of_get_gpio_regulator_config(struct device *dev, struct device_node *np)
137{
138 struct gpio_regulator_config *config;
139 struct property *prop;
140 const char *regtype;
141 int proplen, gpio, i;
142
143 config = devm_kzalloc(dev,
144 sizeof(struct gpio_regulator_config),
145 GFP_KERNEL);
146 if (!config)
147 return ERR_PTR(-ENOMEM);
148
149 config->init_data = of_get_regulator_init_data(dev, np);
150 if (!config->init_data)
151 return ERR_PTR(-EINVAL);
152
153 config->supply_name = config->init_data->constraints.name;
154
155 if (of_property_read_bool(np, "enable-active-high"))
156 config->enable_high = true;
157
158 if (of_property_read_bool(np, "enable-at-boot"))
159 config->enabled_at_boot = true;
160
161 of_property_read_u32(np, "startup-delay-us", &config->startup_delay);
162
163 config->enable_gpio = of_get_named_gpio(np, "enable-gpio", 0);
164
165 /* Fetch GPIOs. */
166 for (i = 0; ; i++)
167 if (of_get_named_gpio(np, "gpios", i) < 0)
168 break;
169 config->nr_gpios = i;
170
171 config->gpios = devm_kzalloc(dev,
172 sizeof(struct gpio) * config->nr_gpios,
173 GFP_KERNEL);
174 if (!config->gpios)
175 return ERR_PTR(-ENOMEM);
176
177 for (i = 0; config->nr_gpios; i++) {
178 gpio = of_get_named_gpio(np, "gpios", i);
179 if (gpio < 0)
180 break;
181 config->gpios[i].gpio = gpio;
182 }
183
184 /* Fetch states. */
185 prop = of_find_property(np, "states", NULL);
186 if (!prop) {
187 dev_err(dev, "No 'states' property found\n");
188 return ERR_PTR(-EINVAL);
189 }
190
191 proplen = prop->length / sizeof(int);
192
193 config->states = devm_kzalloc(dev,
194 sizeof(struct gpio_regulator_state)
195 * (proplen / 2),
196 GFP_KERNEL);
197 if (!config->states)
198 return ERR_PTR(-ENOMEM);
199
200 for (i = 0; i < proplen / 2; i++) {
201 config->states[i].value =
202 be32_to_cpup((int *)prop->value + (i * 2));
203 config->states[i].gpios =
204 be32_to_cpup((int *)prop->value + (i * 2 + 1));
205 }
206 config->nr_states = i;
207
208 of_property_read_string(np, "regulator-type", &regtype);
209
210 if (!strncmp("voltage", regtype, 7))
211 config->type = REGULATOR_VOLTAGE;
212 else if (!strncmp("current", regtype, 7))
213 config->type = REGULATOR_CURRENT;
214
215 return config;
216}
217
132static struct regulator_ops gpio_regulator_current_ops = { 218static struct regulator_ops gpio_regulator_current_ops = {
133 .get_current_limit = gpio_regulator_get_value, 219 .get_current_limit = gpio_regulator_get_value,
134 .set_current_limit = gpio_regulator_set_current_limit, 220 .set_current_limit = gpio_regulator_set_current_limit,
135}; 221};
136 222
137static int __devinit gpio_regulator_probe(struct platform_device *pdev) 223static int gpio_regulator_probe(struct platform_device *pdev)
138{ 224{
139 struct gpio_regulator_config *config = pdev->dev.platform_data; 225 struct gpio_regulator_config *config = pdev->dev.platform_data;
226 struct device_node *np = pdev->dev.of_node;
140 struct gpio_regulator_data *drvdata; 227 struct gpio_regulator_data *drvdata;
141 struct regulator_config cfg = { }; 228 struct regulator_config cfg = { };
142 int ptr, ret, state; 229 int ptr, ret, state;
143 230
231 if (np) {
232 config = of_get_gpio_regulator_config(&pdev->dev, np);
233 if (IS_ERR(config))
234 return PTR_ERR(config);
235 }
236
144 drvdata = devm_kzalloc(&pdev->dev, sizeof(struct gpio_regulator_data), 237 drvdata = devm_kzalloc(&pdev->dev, sizeof(struct gpio_regulator_data),
145 GFP_KERNEL); 238 GFP_KERNEL);
146 if (drvdata == NULL) { 239 if (drvdata == NULL) {
@@ -215,6 +308,7 @@ static int __devinit gpio_regulator_probe(struct platform_device *pdev)
215 cfg.dev = &pdev->dev; 308 cfg.dev = &pdev->dev;
216 cfg.init_data = config->init_data; 309 cfg.init_data = config->init_data;
217 cfg.driver_data = drvdata; 310 cfg.driver_data = drvdata;
311 cfg.of_node = np;
218 312
219 if (config->enable_gpio >= 0) 313 if (config->enable_gpio >= 0)
220 cfg.ena_gpio = config->enable_gpio; 314 cfg.ena_gpio = config->enable_gpio;
@@ -270,12 +364,18 @@ static int __devexit gpio_regulator_remove(struct platform_device *pdev)
270 return 0; 364 return 0;
271} 365}
272 366
367static const struct of_device_id regulator_gpio_of_match[] __devinitconst = {
368 { .compatible = "regulator-gpio", },
369 {},
370};
371
273static struct platform_driver gpio_regulator_driver = { 372static struct platform_driver gpio_regulator_driver = {
274 .probe = gpio_regulator_probe, 373 .probe = gpio_regulator_probe,
275 .remove = __devexit_p(gpio_regulator_remove), 374 .remove = gpio_regulator_remove,
276 .driver = { 375 .driver = {
277 .name = "gpio-regulator", 376 .name = "gpio-regulator",
278 .owner = THIS_MODULE, 377 .owner = THIS_MODULE,
378 .of_match_table = regulator_gpio_of_match,
279 }, 379 },
280}; 380};
281 381