From 005547e0828ce9064afebb1e6d56a18efd80e7a3 Mon Sep 17 00:00:00 2001 From: James Ban Date: Fri, 8 Aug 2014 14:27:04 +0900 Subject: regulator: da9211: support DA9213 This is a patch for supporting DA9213. Signed-off-by: James Ban Signed-off-by: Mark Brown --- drivers/regulator/da9211-regulator.c | 95 ++++++++++++++++++++++++++++-------- 1 file changed, 75 insertions(+), 20 deletions(-) (limited to 'drivers/regulator/da9211-regulator.c') diff --git a/drivers/regulator/da9211-regulator.c b/drivers/regulator/da9211-regulator.c index 1482ada..ccc2e36 100644 --- a/drivers/regulator/da9211-regulator.c +++ b/drivers/regulator/da9211-regulator.c @@ -1,5 +1,5 @@ /* - * da9211-regulator.c - Regulator device driver for DA9211 + * da9211-regulator.c - Regulator device driver for DA9211/DA9213 * Copyright (C) 2014 Dialog Semiconductor Ltd. * * This library is free software; you can redistribute it and/or @@ -27,6 +27,10 @@ #include #include "da9211-regulator.h" +/* DEVICE IDs */ +#define DA9211_DEVICE_ID 0x22 +#define DA9213_DEVICE_ID 0x23 + #define DA9211_BUCK_MODE_SLEEP 1 #define DA9211_BUCK_MODE_SYNC 2 #define DA9211_BUCK_MODE_AUTO 3 @@ -42,6 +46,7 @@ struct da9211 { struct regulator_dev *rdev[DA9211_MAX_REGULATORS]; int num_regulator; int chip_irq; + int chip_id; }; static const struct regmap_range_cfg da9211_regmap_range[] = { @@ -52,14 +57,14 @@ static const struct regmap_range_cfg da9211_regmap_range[] = { .window_start = 0, .window_len = 256, .range_min = 0, - .range_max = 2*256, + .range_max = 5*128, }, }; static const struct regmap_config da9211_regmap_config = { .reg_bits = 8, .val_bits = 8, - .max_register = 2 * 256, + .max_register = 5 * 128, .ranges = da9211_regmap_range, .num_ranges = ARRAY_SIZE(da9211_regmap_range), }; @@ -69,11 +74,20 @@ static const struct regmap_config da9211_regmap_config = { #define DA9211_MAX_MV 1570 #define DA9211_STEP_MV 10 -/* Current limits for buck (uA) indices corresponds with register values */ +/* Current limits for DA9211 buck (uA) indices + * corresponds with register values + */ static const int da9211_current_limits[] = { 2000000, 2200000, 2400000, 2600000, 2800000, 3000000, 3200000, 3400000, 3600000, 3800000, 4000000, 4200000, 4400000, 4600000, 4800000, 5000000 }; +/* Current limits for DA9213 buck (uA) indices + * corresponds with register values + */ +static const int da9213_current_limits[] = { + 3000000, 3200000, 3400000, 3600000, 3800000, 4000000, 4200000, 4400000, + 4600000, 4800000, 5000000, 5200000, 5400000, 5600000, 5800000, 6000000 +}; static unsigned int da9211_buck_get_mode(struct regulator_dev *rdev) { @@ -129,12 +143,26 @@ static int da9211_set_current_limit(struct regulator_dev *rdev, int min, { int id = rdev_get_id(rdev); struct da9211 *chip = rdev_get_drvdata(rdev); - int i; + int i, max_size; + const int *current_limits; + + switch (chip->chip_id) { + case DA9211: + current_limits = da9211_current_limits; + max_size = ARRAY_SIZE(da9211_current_limits)-1; + break; + case DA9213: + current_limits = da9213_current_limits; + max_size = ARRAY_SIZE(da9213_current_limits)-1; + break; + default: + return -EINVAL; + } /* search for closest to maximum */ - for (i = ARRAY_SIZE(da9211_current_limits)-1; i >= 0; i--) { - if (min <= da9211_current_limits[i] && - max >= da9211_current_limits[i]) { + for (i = max_size; i >= 0; i--) { + if (min <= current_limits[i] && + max >= current_limits[i]) { return regmap_update_bits(chip->regmap, DA9211_REG_BUCK_ILIM, (0x0F << id*4), (i << id*4)); @@ -150,14 +178,28 @@ static int da9211_get_current_limit(struct regulator_dev *rdev) struct da9211 *chip = rdev_get_drvdata(rdev); unsigned int data; int ret; + const int *current_limits; + + switch (chip->chip_id) { + case DA9211: + current_limits = da9211_current_limits; + break; + case DA9213: + current_limits = da9213_current_limits; + break; + default: + return -EINVAL; + } ret = regmap_read(chip->regmap, DA9211_REG_BUCK_ILIM, &data); if (ret < 0) return ret; - /* select one of 16 values: 0000 (2000mA) to 1111 (5000mA) */ + /* select one of 16 values: 0000 (2000mA or 3000mA) + * to 1111 (5000mA or 6000mA). + */ data = (data >> id*4) & 0x0F; - return da9211_current_limits[data]; + return current_limits[data]; } static struct regulator_ops da9211_buck_ops = { @@ -264,10 +306,7 @@ static int da9211_regulator_init(struct da9211 *chip) } for (i = 0; i < chip->num_regulator; i++) { - if (chip->pdata) - config.init_data = - &(chip->pdata->init_data[i]); - + config.init_data = &(chip->pdata->init_data[i]); config.dev = chip->dev; config.driver_data = chip; config.regmap = chip->regmap; @@ -301,6 +340,7 @@ static int da9211_i2c_probe(struct i2c_client *i2c, { struct da9211 *chip; int error, ret; + unsigned int data; chip = devm_kzalloc(&i2c->dev, sizeof(struct da9211), GFP_KERNEL); @@ -308,7 +348,7 @@ static int da9211_i2c_probe(struct i2c_client *i2c, chip->regmap = devm_regmap_init_i2c(i2c, &da9211_regmap_config); if (IS_ERR(chip->regmap)) { error = PTR_ERR(chip->regmap); - dev_err(&i2c->dev, "Failed to allocate register map: %d\n", + dev_err(chip->dev, "Failed to allocate register map: %d\n", error); return error; } @@ -316,8 +356,22 @@ static int da9211_i2c_probe(struct i2c_client *i2c, i2c_set_clientdata(i2c, chip); chip->pdata = i2c->dev.platform_data; - if (!chip->pdata) { - dev_err(&i2c->dev, "No platform init data supplied\n"); + + ret = regmap_read(chip->regmap, DA9211_REG_DEVICE_ID, &data); + if (ret < 0) { + dev_err(chip->dev, "Failed to read DEVICE_ID reg: %d\n", ret); + return ret; + } + + switch (data) { + case DA9211_DEVICE_ID: + chip->chip_id = DA9211; + break; + case DA9213_DEVICE_ID: + chip->chip_id = DA9213; + break; + default: + dev_err(chip->dev, "Unsupported device id = 0x%x.\n", data); return -ENODEV; } @@ -340,13 +394,14 @@ static int da9211_i2c_probe(struct i2c_client *i2c, ret = da9211_regulator_init(chip); if (ret < 0) - dev_err(&i2c->dev, "Failed to initialize regulator: %d\n", ret); + dev_err(chip->dev, "Failed to initialize regulator: %d\n", ret); return ret; } static const struct i2c_device_id da9211_i2c_id[] = { - {"da9211", 0}, + {"da9211", DA9211}, + {"da9213", DA9213}, {}, }; @@ -364,5 +419,5 @@ static struct i2c_driver da9211_regulator_driver = { module_i2c_driver(da9211_regulator_driver); MODULE_AUTHOR("James Ban "); -MODULE_DESCRIPTION("Regulator device driver for Dialog DA9211"); +MODULE_DESCRIPTION("Regulator device driver for Dialog DA9211/DA9213"); MODULE_LICENSE("GPL v2"); -- cgit v1.1 From 1d3e6a6985c14f0510ebbd81fb9e8c02b24f8791 Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Sun, 17 Aug 2014 18:34:48 +0800 Subject: regulator: da9211: Check return value of devm_kzalloc() Signed-off-by: Axel Lin Signed-off-by: Mark Brown --- drivers/regulator/da9211-regulator.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers/regulator/da9211-regulator.c') diff --git a/drivers/regulator/da9211-regulator.c b/drivers/regulator/da9211-regulator.c index ccc2e36..a26f1d2 100644 --- a/drivers/regulator/da9211-regulator.c +++ b/drivers/regulator/da9211-regulator.c @@ -343,6 +343,8 @@ static int da9211_i2c_probe(struct i2c_client *i2c, unsigned int data; chip = devm_kzalloc(&i2c->dev, sizeof(struct da9211), GFP_KERNEL); + if (!chip) + return -ENOMEM; chip->dev = &i2c->dev; chip->regmap = devm_regmap_init_i2c(i2c, &da9211_regmap_config); -- cgit v1.1 From bf3baca6c54ce8a2f51687296f868dfe20d33f13 Mon Sep 17 00:00:00 2001 From: James Ban Date: Wed, 27 Aug 2014 11:47:07 +0900 Subject: regulator: da9211: support device tree This is a patch for supporting device tree of DA9211/DA9213. Signed-off-by: James Ban Signed-off-by: Mark Brown --- drivers/regulator/da9211-regulator.c | 85 +++++++++++++++++++++++++++++++++--- 1 file changed, 78 insertions(+), 7 deletions(-) (limited to 'drivers/regulator/da9211-regulator.c') diff --git a/drivers/regulator/da9211-regulator.c b/drivers/regulator/da9211-regulator.c index a26f1d2..5aabbac 100644 --- a/drivers/regulator/da9211-regulator.c +++ b/drivers/regulator/da9211-regulator.c @@ -24,6 +24,7 @@ #include #include #include +#include #include #include "da9211-regulator.h" @@ -236,6 +237,59 @@ static struct regulator_desc da9211_regulators[] = { DA9211_BUCK(BUCKB), }; +#ifdef CONFIG_OF +static struct of_regulator_match da9211_matches[] = { + [DA9211_ID_BUCKA] = { .name = "BUCKA" }, + [DA9211_ID_BUCKB] = { .name = "BUCKB" }, + }; + +static struct da9211_pdata *da9211_parse_regulators_dt( + struct device *dev) +{ + struct da9211_pdata *pdata; + struct device_node *node; + int i, num, n; + + node = of_get_child_by_name(dev->of_node, "regulators"); + if (!node) { + dev_err(dev, "regulators node not found\n"); + return ERR_PTR(-ENODEV); + } + + num = of_regulator_match(dev, node, da9211_matches, + ARRAY_SIZE(da9211_matches)); + of_node_put(node); + if (num < 0) { + dev_err(dev, "Failed to match regulators\n"); + return ERR_PTR(-EINVAL); + } + + pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL); + if (!pdata) + return ERR_PTR(-ENOMEM); + + pdata->num_buck = num; + + n = 0; + for (i = 0; i < ARRAY_SIZE(da9211_matches); i++) { + if (!da9211_matches[i].init_data) + continue; + + pdata->init_data[n] = da9211_matches[i].init_data; + + n++; + }; + + return pdata; +} +#else +static struct da9211_pdata *da9211_parse_regulators_dt( + struct device *dev) +{ + return ERR_PTR(-ENODEV); +} +#endif + static irqreturn_t da9211_irq_handler(int irq, void *data) { struct da9211 *chip = data; @@ -306,7 +360,7 @@ static int da9211_regulator_init(struct da9211 *chip) } for (i = 0; i < chip->num_regulator; i++) { - config.init_data = &(chip->pdata->init_data[i]); + config.init_data = chip->pdata->init_data[i]; config.dev = chip->dev; config.driver_data = chip; config.regmap = chip->regmap; @@ -332,6 +386,21 @@ static int da9211_regulator_init(struct da9211 *chip) return 0; } + +static const struct i2c_device_id da9211_i2c_id[] = { + {"da9211", DA9211}, + {"da9213", DA9213}, + {}, +}; + +#ifdef CONFIG_OF +static const struct of_device_id da9211_dt_ids[] = { + { .compatible = "dlg,da9211", .data = &da9211_i2c_id[0] }, + { .compatible = "dlg,da9213", .data = &da9211_i2c_id[1] }, + {}, +}; +#endif + /* * I2C driver interface functions */ @@ -377,6 +446,14 @@ static int da9211_i2c_probe(struct i2c_client *i2c, return -ENODEV; } + if (!chip->pdata) + chip->pdata = da9211_parse_regulators_dt(chip->dev); + + if (IS_ERR(chip->pdata)) { + dev_err(chip->dev, "No regulators defined for the platform\n"); + return PTR_ERR(chip->pdata); + } + chip->chip_irq = i2c->irq; if (chip->chip_irq != 0) { @@ -401,12 +478,6 @@ static int da9211_i2c_probe(struct i2c_client *i2c, return ret; } -static const struct i2c_device_id da9211_i2c_id[] = { - {"da9211", DA9211}, - {"da9213", DA9213}, - {}, -}; - MODULE_DEVICE_TABLE(i2c, da9211_i2c_id); static struct i2c_driver da9211_regulator_driver = { -- cgit v1.1 From c2a946e07f9776ba5a73c37087c02e0e1830b5ce Mon Sep 17 00:00:00 2001 From: Fengguang Wu Date: Fri, 29 Aug 2014 12:41:59 +0100 Subject: regulator: da9211: fix coccinelle warnings drivers/regulator/da9211-regulator.c:281:2-3: Unneeded semicolon Removes unneeded semicolon. Generated by: scripts/coccinelle/misc/semicolon.cocci Signed-off-by: Fengguang Wu Signed-off-by: Mark Brown --- drivers/regulator/da9211-regulator.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/regulator/da9211-regulator.c') diff --git a/drivers/regulator/da9211-regulator.c b/drivers/regulator/da9211-regulator.c index 5aabbac..9722728 100644 --- a/drivers/regulator/da9211-regulator.c +++ b/drivers/regulator/da9211-regulator.c @@ -278,7 +278,7 @@ static struct da9211_pdata *da9211_parse_regulators_dt( pdata->init_data[n] = da9211_matches[i].init_data; n++; - }; + } return pdata; } -- cgit v1.1 From 67c866cfcb7cfe74d66645aa4c1e983d22e0001a Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Wed, 3 Sep 2014 09:15:30 +0800 Subject: regulator: da9211: Fix missing config.of_node setting Signed-off-by: Axel Lin Signed-off-by: Mark Brown --- drivers/regulator/da9211-regulator.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers/regulator/da9211-regulator.c') diff --git a/drivers/regulator/da9211-regulator.c b/drivers/regulator/da9211-regulator.c index 9722728..044c36c 100644 --- a/drivers/regulator/da9211-regulator.c +++ b/drivers/regulator/da9211-regulator.c @@ -364,6 +364,7 @@ static int da9211_regulator_init(struct da9211 *chip) config.dev = chip->dev; config.driver_data = chip; config.regmap = chip->regmap; + config.of_node = chip->dev->of_node; chip->rdev[i] = devm_regulator_register(chip->dev, &da9211_regulators[i], &config); -- cgit v1.1 From 6a52f5633944f075bcc403d66164b5b90b42a751 Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Fri, 5 Sep 2014 09:12:55 +0800 Subject: regulator: da9211: Set of_match_table and export device table Also move da9211_i2c_id and da9211_dt_ids close to the user for better readability. Signed-off-by: Axel Lin Signed-off-by: Mark Brown --- drivers/regulator/da9211-regulator.c | 29 +++++++++++++++-------------- 1 file changed, 15 insertions(+), 14 deletions(-) (limited to 'drivers/regulator/da9211-regulator.c') diff --git a/drivers/regulator/da9211-regulator.c b/drivers/regulator/da9211-regulator.c index 044c36c..f47adf3 100644 --- a/drivers/regulator/da9211-regulator.c +++ b/drivers/regulator/da9211-regulator.c @@ -388,20 +388,6 @@ static int da9211_regulator_init(struct da9211 *chip) return 0; } -static const struct i2c_device_id da9211_i2c_id[] = { - {"da9211", DA9211}, - {"da9213", DA9213}, - {}, -}; - -#ifdef CONFIG_OF -static const struct of_device_id da9211_dt_ids[] = { - { .compatible = "dlg,da9211", .data = &da9211_i2c_id[0] }, - { .compatible = "dlg,da9213", .data = &da9211_i2c_id[1] }, - {}, -}; -#endif - /* * I2C driver interface functions */ @@ -479,12 +465,27 @@ static int da9211_i2c_probe(struct i2c_client *i2c, return ret; } +static const struct i2c_device_id da9211_i2c_id[] = { + {"da9211", DA9211}, + {"da9213", DA9213}, + {}, +}; MODULE_DEVICE_TABLE(i2c, da9211_i2c_id); +#ifdef CONFIG_OF +static const struct of_device_id da9211_dt_ids[] = { + { .compatible = "dlg,da9211", .data = &da9211_i2c_id[0] }, + { .compatible = "dlg,da9213", .data = &da9211_i2c_id[1] }, + {}, +}; +MODULE_DEVICE_TABLE(of, da9211_dt_ids); +#endif + static struct i2c_driver da9211_regulator_driver = { .driver = { .name = "da9211", .owner = THIS_MODULE, + .of_match_table = of_match_ptr(da9211_dt_ids), }, .probe = da9211_i2c_probe, .id_table = da9211_i2c_id, -- cgit v1.1