aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Documentation/devicetree/bindings/regulator/max8660.txt47
-rw-r--r--drivers/regulator/max8660.c82
-rw-r--r--include/linux/regulator/max8660.h2
3 files changed, 129 insertions, 2 deletions
diff --git a/Documentation/devicetree/bindings/regulator/max8660.txt b/Documentation/devicetree/bindings/regulator/max8660.txt
new file mode 100644
index 000000000000..8ba994d8a142
--- /dev/null
+++ b/Documentation/devicetree/bindings/regulator/max8660.txt
@@ -0,0 +1,47 @@
1Maxim MAX8660 voltage regulator
2
3Required properties:
4- compatible: must be one of "maxim,max8660", "maxim,max8661"
5- reg: I2C slave address, usually 0x34
6- any required generic properties defined in regulator.txt
7
8Example:
9
10 i2c_master {
11 max8660@34 {
12 compatible = "maxim,max8660";
13 reg = <0x34>;
14
15 regulators {
16 regulator@0 {
17 regulator-compatible= "V3(DCDC)";
18 regulator-min-microvolt = <725000>;
19 regulator-max-microvolt = <1800000>;
20 };
21
22 regulator@1 {
23 regulator-compatible= "V4(DCDC)";
24 regulator-min-microvolt = <725000>;
25 regulator-max-microvolt = <1800000>;
26 };
27
28 regulator@2 {
29 regulator-compatible= "V5(LDO)";
30 regulator-min-microvolt = <1700000>;
31 regulator-max-microvolt = <2000000>;
32 };
33
34 regulator@3 {
35 regulator-compatible= "V6(LDO)";
36 regulator-min-microvolt = <1800000>;
37 regulator-max-microvolt = <3300000>;
38 };
39
40 regulator@4 {
41 regulator-compatible= "V7(LDO)";
42 regulator-min-microvolt = <1800000>;
43 regulator-max-microvolt = <3300000>;
44 };
45 };
46 };
47 };
diff --git a/drivers/regulator/max8660.c b/drivers/regulator/max8660.c
index 74c11aa00c8a..a4f2f1a38342 100644
--- a/drivers/regulator/max8660.c
+++ b/drivers/regulator/max8660.c
@@ -44,6 +44,9 @@
44#include <linux/regulator/driver.h> 44#include <linux/regulator/driver.h>
45#include <linux/slab.h> 45#include <linux/slab.h>
46#include <linux/regulator/max8660.h> 46#include <linux/regulator/max8660.h>
47#include <linux/of.h>
48#include <linux/of_device.h>
49#include <linux/regulator/of_regulator.h>
47 50
48#define MAX8660_DCDC_MIN_UV 725000 51#define MAX8660_DCDC_MIN_UV 725000
49#define MAX8660_DCDC_MAX_UV 1800000 52#define MAX8660_DCDC_MAX_UV 1800000
@@ -310,6 +313,63 @@ enum {
310 MAX8661 = 1, 313 MAX8661 = 1,
311}; 314};
312 315
316#ifdef CONFIG_OF
317static const struct of_device_id max8660_dt_ids[] = {
318 { .compatible = "maxim,max8660", .data = (void *) MAX8660 },
319 { .compatible = "maxim,max8661", .data = (void *) MAX8661 },
320 { }
321};
322MODULE_DEVICE_TABLE(of, max8660_dt_ids);
323
324static int max8660_pdata_from_dt(struct device *dev,
325 struct device_node **of_node,
326 struct max8660_platform_data *pdata)
327{
328 int matched, i;
329 struct device_node *np;
330 struct max8660_subdev_data *sub;
331 struct of_regulator_match rmatch[ARRAY_SIZE(max8660_reg)];
332
333 np = of_find_node_by_name(dev->of_node, "regulators");
334 if (!np) {
335 dev_err(dev, "missing 'regulators' subnode in DT\n");
336 return -EINVAL;
337 }
338
339 for (i = 0; i < ARRAY_SIZE(rmatch); i++)
340 rmatch[i].name = max8660_reg[i].name;
341
342 matched = of_regulator_match(dev, np, rmatch, ARRAY_SIZE(rmatch));
343 if (matched <= 0)
344 return matched;
345
346 pdata->subdevs = devm_kzalloc(dev, sizeof(struct max8660_subdev_data) *
347 matched, GFP_KERNEL);
348 if (!pdata->subdevs)
349 return -ENOMEM;
350
351 pdata->num_subdevs = matched;
352 sub = pdata->subdevs;
353
354 for (i = 0; i < matched; i++) {
355 sub->id = i;
356 sub->name = rmatch[i].name;
357 sub->platform_data = rmatch[i].init_data;
358 of_node[i] = rmatch[i].of_node;
359 sub++;
360 }
361
362 return 0;
363}
364#else
365static inline int max8660_pdata_from_dt(struct device *dev,
366 struct device_node **of_node,
367 struct max8660_platform_data **pdata)
368{
369 return 0;
370}
371#endif
372
313static int max8660_probe(struct i2c_client *client, 373static int max8660_probe(struct i2c_client *client,
314 const struct i2c_device_id *i2c_id) 374 const struct i2c_device_id *i2c_id)
315{ 375{
@@ -319,8 +379,28 @@ static int max8660_probe(struct i2c_client *client,
319 struct regulator_config config = { }; 379 struct regulator_config config = { };
320 struct max8660 *max8660; 380 struct max8660 *max8660;
321 int boot_on, i, id, ret = -EINVAL; 381 int boot_on, i, id, ret = -EINVAL;
382 struct device_node *of_node[MAX8660_V_END];
322 unsigned int type; 383 unsigned int type;
323 384
385 if (dev->of_node && !pdata) {
386 const struct of_device_id *id;
387 struct max8660_platform_data pdata_of;
388
389 id = of_match_device(of_match_ptr(max8660_dt_ids), dev);
390 if (!id)
391 return -ENODEV;
392
393 ret = max8660_pdata_from_dt(dev, of_node, &pdata_of);
394 if (ret < 0)
395 return ret;
396
397 pdata = &pdata_of;
398 type = (unsigned int) id->data;
399 } else {
400 type = i2c_id->driver_data;
401 memset(of_node, 0, sizeof(of_node));
402 }
403
324 if (pdata->num_subdevs > MAX8660_V_END) { 404 if (pdata->num_subdevs > MAX8660_V_END) {
325 dev_err(dev, "Too many regulators found!\n"); 405 dev_err(dev, "Too many regulators found!\n");
326 return -EINVAL; 406 return -EINVAL;
@@ -334,7 +414,6 @@ static int max8660_probe(struct i2c_client *client,
334 414
335 max8660->client = client; 415 max8660->client = client;
336 rdev = max8660->rdev; 416 rdev = max8660->rdev;
337 type = i2c_id->driver_data;
338 417
339 if (pdata->en34_is_high) { 418 if (pdata->en34_is_high) {
340 /* Simulate always on */ 419 /* Simulate always on */
@@ -407,6 +486,7 @@ static int max8660_probe(struct i2c_client *client,
407 486
408 config.dev = dev; 487 config.dev = dev;
409 config.init_data = pdata->subdevs[i].platform_data; 488 config.init_data = pdata->subdevs[i].platform_data;
489 config.of_node = of_node[i];
410 config.driver_data = max8660; 490 config.driver_data = max8660;
411 491
412 rdev[i] = regulator_register(&max8660_reg[id], &config); 492 rdev[i] = regulator_register(&max8660_reg[id], &config);
diff --git a/include/linux/regulator/max8660.h b/include/linux/regulator/max8660.h
index 9936763621c7..f8a6a4844864 100644
--- a/include/linux/regulator/max8660.h
+++ b/include/linux/regulator/max8660.h
@@ -39,7 +39,7 @@ enum {
39 */ 39 */
40struct max8660_subdev_data { 40struct max8660_subdev_data {
41 int id; 41 int id;
42 char *name; 42 const char *name;
43 struct regulator_init_data *platform_data; 43 struct regulator_init_data *platform_data;
44}; 44};
45 45