diff options
-rw-r--r-- | Documentation/devicetree/bindings/regulator/max8660.txt | 47 | ||||
-rw-r--r-- | drivers/regulator/max8660.c | 82 | ||||
-rw-r--r-- | include/linux/regulator/max8660.h | 2 |
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 @@ | |||
1 | Maxim MAX8660 voltage regulator | ||
2 | |||
3 | Required 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 | |||
8 | Example: | ||
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 | ||
317 | static const struct of_device_id max8660_dt_ids[] = { | ||
318 | { .compatible = "maxim,max8660", .data = (void *) MAX8660 }, | ||
319 | { .compatible = "maxim,max8661", .data = (void *) MAX8661 }, | ||
320 | { } | ||
321 | }; | ||
322 | MODULE_DEVICE_TABLE(of, max8660_dt_ids); | ||
323 | |||
324 | static 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 | ||
365 | static 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 | |||
313 | static int max8660_probe(struct i2c_client *client, | 373 | static 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 | */ |
40 | struct max8660_subdev_data { | 40 | struct 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 | ||