diff options
author | Daniel Mack <zonque@gmail.com> | 2013-08-02 06:59:44 -0400 |
---|---|---|
committer | Mark Brown <broonie@linaro.org> | 2013-08-02 12:29:54 -0400 |
commit | abe4c51afda02423c81da6f1eaaa50b733f1ecc2 (patch) | |
tree | d4c2e2303ab360ac7773caca54ce9d36884ab176 /drivers/regulator/max8660.c | |
parent | de492e8de8d05f29cc496871d42763d0a8a74610 (diff) |
regulators: max8660: add DT bindings
This patch adds devicetree bindings for max8660, along with some
documentation.
Signed-off-by: Daniel Mack <zonque@gmail.com>
Signed-off-by: Mark Brown <broonie@linaro.org>
Diffstat (limited to 'drivers/regulator/max8660.c')
-rw-r--r-- | drivers/regulator/max8660.c | 82 |
1 files changed, 81 insertions, 1 deletions
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); |