diff options
-rw-r--r-- | Documentation/devicetree/bindings/regulator/tps62360-regulator.txt | 45 | ||||
-rw-r--r-- | drivers/regulator/tps62360-regulator.c | 73 |
2 files changed, 117 insertions, 1 deletions
diff --git a/Documentation/devicetree/bindings/regulator/tps62360-regulator.txt b/Documentation/devicetree/bindings/regulator/tps62360-regulator.txt new file mode 100644 index 000000000000..f411b57c7751 --- /dev/null +++ b/Documentation/devicetree/bindings/regulator/tps62360-regulator.txt | |||
@@ -0,0 +1,45 @@ | |||
1 | TPS62360 Voltage regulators | ||
2 | |||
3 | Required properties: | ||
4 | - compatible: Must be one of the following. | ||
5 | "ti,tps62360" | ||
6 | "ti,tps62361", | ||
7 | "ti,tps62362", | ||
8 | "ti,tps62363", | ||
9 | - reg: I2C slave address | ||
10 | |||
11 | Optional properties: | ||
12 | - ti,enable-force-pwm: Enable force PWM mode. This is boolean value. | ||
13 | - ti,enable-vout-discharge: Enable output discharge. This is boolean value. | ||
14 | - ti,enable-pull-down: Enable pull down. This is boolean value. | ||
15 | - ti,vsel0-gpio: GPIO for controlling VSEL0 line. | ||
16 | If this property is missing, then assume that there is no GPIO | ||
17 | for vsel0 control. | ||
18 | - ti,vsel1-gpio: Gpio for controlling VSEL1 line. | ||
19 | If this property is missing, then assume that there is no GPIO | ||
20 | for vsel1 control. | ||
21 | - ti,vsel0-state-high: Inital state of vsel0 input is high. | ||
22 | If this property is missing, then assume the state as low (0). | ||
23 | - ti,vsel1-state-high: Inital state of vsel1 input is high. | ||
24 | If this property is missing, then assume the state as low (0). | ||
25 | |||
26 | Any property defined as part of the core regulator binding, defined in | ||
27 | regulator.txt, can also be used. | ||
28 | |||
29 | Example: | ||
30 | |||
31 | abc: tps62360 { | ||
32 | compatible = "ti,tps62361"; | ||
33 | reg = <0x60>; | ||
34 | regulator-name = "tps62361-vout"; | ||
35 | regulator-min-microvolt = <500000>; | ||
36 | regulator-max-microvolt = <1500000>; | ||
37 | regulator-boot-on | ||
38 | ti,vsel0-gpio = <&gpio1 16 0>; | ||
39 | ti,vsel1-gpio = <&gpio1 17 0>; | ||
40 | ti,vsel0-state-high; | ||
41 | ti,vsel1-state-high; | ||
42 | ti,enable-pull-down; | ||
43 | ti,enable-force-pwm; | ||
44 | ti,enable-vout-discharge; | ||
45 | }; | ||
diff --git a/drivers/regulator/tps62360-regulator.c b/drivers/regulator/tps62360-regulator.c index 3506900043aa..60765ccd25f5 100644 --- a/drivers/regulator/tps62360-regulator.c +++ b/drivers/regulator/tps62360-regulator.c | |||
@@ -26,6 +26,10 @@ | |||
26 | #include <linux/module.h> | 26 | #include <linux/module.h> |
27 | #include <linux/init.h> | 27 | #include <linux/init.h> |
28 | #include <linux/err.h> | 28 | #include <linux/err.h> |
29 | #include <linux/of.h> | ||
30 | #include <linux/of_device.h> | ||
31 | #include <linux/of_gpio.h> | ||
32 | #include <linux/regulator/of_regulator.h> | ||
29 | #include <linux/platform_device.h> | 33 | #include <linux/platform_device.h> |
30 | #include <linux/regulator/driver.h> | 34 | #include <linux/regulator/driver.h> |
31 | #include <linux/regulator/machine.h> | 35 | #include <linux/regulator/machine.h> |
@@ -297,6 +301,56 @@ static const struct regmap_config tps62360_regmap_config = { | |||
297 | .cache_type = REGCACHE_RBTREE, | 301 | .cache_type = REGCACHE_RBTREE, |
298 | }; | 302 | }; |
299 | 303 | ||
304 | static struct tps62360_regulator_platform_data * | ||
305 | of_get_tps62360_platform_data(struct device *dev) | ||
306 | { | ||
307 | struct tps62360_regulator_platform_data *pdata; | ||
308 | struct device_node *np = dev->of_node; | ||
309 | |||
310 | pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL); | ||
311 | if (!pdata) { | ||
312 | dev_err(dev, "Memory alloc failed for platform data\n"); | ||
313 | return NULL; | ||
314 | } | ||
315 | |||
316 | pdata->reg_init_data = of_get_regulator_init_data(dev, dev->of_node); | ||
317 | if (!pdata->reg_init_data) { | ||
318 | dev_err(dev, "Not able to get OF regulator init data\n"); | ||
319 | return NULL; | ||
320 | } | ||
321 | |||
322 | pdata->vsel0_gpio = of_get_named_gpio(np, "vsel0-gpio", 0); | ||
323 | pdata->vsel1_gpio = of_get_named_gpio(np, "vsel1-gpio", 0); | ||
324 | |||
325 | if (of_find_property(np, "ti,vsel0-state-high", NULL)) | ||
326 | pdata->vsel0_def_state = 1; | ||
327 | |||
328 | if (of_find_property(np, "ti,vsel1-state-high", NULL)) | ||
329 | pdata->vsel1_def_state = 1; | ||
330 | |||
331 | if (of_find_property(np, "ti,enable-pull-down", NULL)) | ||
332 | pdata->en_internal_pulldn = true; | ||
333 | |||
334 | if (of_find_property(np, "ti,enable-force-pwm", NULL)) | ||
335 | pdata->en_force_pwm = true; | ||
336 | |||
337 | if (of_find_property(np, "ti,enable-vout-discharge", NULL)) | ||
338 | pdata->en_discharge = true; | ||
339 | |||
340 | return pdata; | ||
341 | } | ||
342 | |||
343 | #if defined(CONFIG_OF) | ||
344 | static const struct of_device_id tps62360_of_match[] = { | ||
345 | { .compatible = "ti,tps62360", .data = (void *)TPS62360}, | ||
346 | { .compatible = "ti,tps62361", .data = (void *)TPS62361}, | ||
347 | { .compatible = "ti,tps62362", .data = (void *)TPS62362}, | ||
348 | { .compatible = "ti,tps62363", .data = (void *)TPS62363}, | ||
349 | {}, | ||
350 | } | ||
351 | MODULE_DEVICE_TABLE(of, tps62360_of_match); | ||
352 | #endif | ||
353 | |||
300 | static int __devinit tps62360_probe(struct i2c_client *client, | 354 | static int __devinit tps62360_probe(struct i2c_client *client, |
301 | const struct i2c_device_id *id) | 355 | const struct i2c_device_id *id) |
302 | { | 356 | { |
@@ -306,8 +360,24 @@ static int __devinit tps62360_probe(struct i2c_client *client, | |||
306 | struct tps62360_chip *tps; | 360 | struct tps62360_chip *tps; |
307 | int ret; | 361 | int ret; |
308 | int i; | 362 | int i; |
363 | int chip_id; | ||
309 | 364 | ||
310 | pdata = client->dev.platform_data; | 365 | pdata = client->dev.platform_data; |
366 | chip_id = id->driver_data; | ||
367 | |||
368 | if (client->dev.of_node) { | ||
369 | const struct of_device_id *match; | ||
370 | match = of_match_device(of_match_ptr(tps62360_of_match), | ||
371 | &client->dev); | ||
372 | if (!match) { | ||
373 | dev_err(&client->dev, "Error: No device match found\n"); | ||
374 | return -ENODEV; | ||
375 | } | ||
376 | chip_id = (int)match->data; | ||
377 | if (!pdata) | ||
378 | pdata = of_get_tps62360_platform_data(&client->dev); | ||
379 | } | ||
380 | |||
311 | if (!pdata) { | 381 | if (!pdata) { |
312 | dev_err(&client->dev, "%s(): Platform data not found\n", | 382 | dev_err(&client->dev, "%s(): Platform data not found\n", |
313 | __func__); | 383 | __func__); |
@@ -328,7 +398,7 @@ static int __devinit tps62360_probe(struct i2c_client *client, | |||
328 | tps->vsel1_gpio = pdata->vsel1_gpio; | 398 | tps->vsel1_gpio = pdata->vsel1_gpio; |
329 | tps->dev = &client->dev; | 399 | tps->dev = &client->dev; |
330 | 400 | ||
331 | switch (id->driver_data) { | 401 | switch (chip_id) { |
332 | case TPS62360: | 402 | case TPS62360: |
333 | case TPS62362: | 403 | case TPS62362: |
334 | tps->voltage_base = TPS62360_BASE_VOLTAGE; | 404 | tps->voltage_base = TPS62360_BASE_VOLTAGE; |
@@ -484,6 +554,7 @@ static struct i2c_driver tps62360_i2c_driver = { | |||
484 | .driver = { | 554 | .driver = { |
485 | .name = "tps62360", | 555 | .name = "tps62360", |
486 | .owner = THIS_MODULE, | 556 | .owner = THIS_MODULE, |
557 | .of_match_table = of_match_ptr(tps62360_of_match), | ||
487 | }, | 558 | }, |
488 | .probe = tps62360_probe, | 559 | .probe = tps62360_probe, |
489 | .remove = __devexit_p(tps62360_remove), | 560 | .remove = __devexit_p(tps62360_remove), |