diff options
author | James Ban <james.ban.opensource@diasemi.com> | 2014-08-08 01:27:04 -0400 |
---|---|---|
committer | Mark Brown <broonie@linaro.org> | 2014-08-16 17:46:22 -0400 |
commit | 005547e0828ce9064afebb1e6d56a18efd80e7a3 (patch) | |
tree | e862fd217711306c4dcaa260dda9fbca9a7685ff /drivers/regulator/da9211-regulator.c | |
parent | 7d1311b93e58ed55f3a31cc8f94c4b8fe988a2b9 (diff) |
regulator: da9211: support DA9213
This is a patch for supporting DA9213.
Signed-off-by: James Ban <james.ban.opensource@diasemi.com>
Signed-off-by: Mark Brown <broonie@linaro.org>
Diffstat (limited to 'drivers/regulator/da9211-regulator.c')
-rw-r--r-- | drivers/regulator/da9211-regulator.c | 95 |
1 files changed, 75 insertions, 20 deletions
diff --git a/drivers/regulator/da9211-regulator.c b/drivers/regulator/da9211-regulator.c index 1482adafa1ad..ccc2e362d751 100644 --- a/drivers/regulator/da9211-regulator.c +++ b/drivers/regulator/da9211-regulator.c | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * da9211-regulator.c - Regulator device driver for DA9211 | 2 | * da9211-regulator.c - Regulator device driver for DA9211/DA9213 |
3 | * Copyright (C) 2014 Dialog Semiconductor Ltd. | 3 | * Copyright (C) 2014 Dialog Semiconductor Ltd. |
4 | * | 4 | * |
5 | * This library is free software; you can redistribute it and/or | 5 | * This library is free software; you can redistribute it and/or |
@@ -27,6 +27,10 @@ | |||
27 | #include <linux/regulator/da9211.h> | 27 | #include <linux/regulator/da9211.h> |
28 | #include "da9211-regulator.h" | 28 | #include "da9211-regulator.h" |
29 | 29 | ||
30 | /* DEVICE IDs */ | ||
31 | #define DA9211_DEVICE_ID 0x22 | ||
32 | #define DA9213_DEVICE_ID 0x23 | ||
33 | |||
30 | #define DA9211_BUCK_MODE_SLEEP 1 | 34 | #define DA9211_BUCK_MODE_SLEEP 1 |
31 | #define DA9211_BUCK_MODE_SYNC 2 | 35 | #define DA9211_BUCK_MODE_SYNC 2 |
32 | #define DA9211_BUCK_MODE_AUTO 3 | 36 | #define DA9211_BUCK_MODE_AUTO 3 |
@@ -42,6 +46,7 @@ struct da9211 { | |||
42 | struct regulator_dev *rdev[DA9211_MAX_REGULATORS]; | 46 | struct regulator_dev *rdev[DA9211_MAX_REGULATORS]; |
43 | int num_regulator; | 47 | int num_regulator; |
44 | int chip_irq; | 48 | int chip_irq; |
49 | int chip_id; | ||
45 | }; | 50 | }; |
46 | 51 | ||
47 | static const struct regmap_range_cfg da9211_regmap_range[] = { | 52 | static const struct regmap_range_cfg da9211_regmap_range[] = { |
@@ -52,14 +57,14 @@ static const struct regmap_range_cfg da9211_regmap_range[] = { | |||
52 | .window_start = 0, | 57 | .window_start = 0, |
53 | .window_len = 256, | 58 | .window_len = 256, |
54 | .range_min = 0, | 59 | .range_min = 0, |
55 | .range_max = 2*256, | 60 | .range_max = 5*128, |
56 | }, | 61 | }, |
57 | }; | 62 | }; |
58 | 63 | ||
59 | static const struct regmap_config da9211_regmap_config = { | 64 | static const struct regmap_config da9211_regmap_config = { |
60 | .reg_bits = 8, | 65 | .reg_bits = 8, |
61 | .val_bits = 8, | 66 | .val_bits = 8, |
62 | .max_register = 2 * 256, | 67 | .max_register = 5 * 128, |
63 | .ranges = da9211_regmap_range, | 68 | .ranges = da9211_regmap_range, |
64 | .num_ranges = ARRAY_SIZE(da9211_regmap_range), | 69 | .num_ranges = ARRAY_SIZE(da9211_regmap_range), |
65 | }; | 70 | }; |
@@ -69,11 +74,20 @@ static const struct regmap_config da9211_regmap_config = { | |||
69 | #define DA9211_MAX_MV 1570 | 74 | #define DA9211_MAX_MV 1570 |
70 | #define DA9211_STEP_MV 10 | 75 | #define DA9211_STEP_MV 10 |
71 | 76 | ||
72 | /* Current limits for buck (uA) indices corresponds with register values */ | 77 | /* Current limits for DA9211 buck (uA) indices |
78 | * corresponds with register values | ||
79 | */ | ||
73 | static const int da9211_current_limits[] = { | 80 | static const int da9211_current_limits[] = { |
74 | 2000000, 2200000, 2400000, 2600000, 2800000, 3000000, 3200000, 3400000, | 81 | 2000000, 2200000, 2400000, 2600000, 2800000, 3000000, 3200000, 3400000, |
75 | 3600000, 3800000, 4000000, 4200000, 4400000, 4600000, 4800000, 5000000 | 82 | 3600000, 3800000, 4000000, 4200000, 4400000, 4600000, 4800000, 5000000 |
76 | }; | 83 | }; |
84 | /* Current limits for DA9213 buck (uA) indices | ||
85 | * corresponds with register values | ||
86 | */ | ||
87 | static const int da9213_current_limits[] = { | ||
88 | 3000000, 3200000, 3400000, 3600000, 3800000, 4000000, 4200000, 4400000, | ||
89 | 4600000, 4800000, 5000000, 5200000, 5400000, 5600000, 5800000, 6000000 | ||
90 | }; | ||
77 | 91 | ||
78 | static unsigned int da9211_buck_get_mode(struct regulator_dev *rdev) | 92 | static unsigned int da9211_buck_get_mode(struct regulator_dev *rdev) |
79 | { | 93 | { |
@@ -129,12 +143,26 @@ static int da9211_set_current_limit(struct regulator_dev *rdev, int min, | |||
129 | { | 143 | { |
130 | int id = rdev_get_id(rdev); | 144 | int id = rdev_get_id(rdev); |
131 | struct da9211 *chip = rdev_get_drvdata(rdev); | 145 | struct da9211 *chip = rdev_get_drvdata(rdev); |
132 | int i; | 146 | int i, max_size; |
147 | const int *current_limits; | ||
148 | |||
149 | switch (chip->chip_id) { | ||
150 | case DA9211: | ||
151 | current_limits = da9211_current_limits; | ||
152 | max_size = ARRAY_SIZE(da9211_current_limits)-1; | ||
153 | break; | ||
154 | case DA9213: | ||
155 | current_limits = da9213_current_limits; | ||
156 | max_size = ARRAY_SIZE(da9213_current_limits)-1; | ||
157 | break; | ||
158 | default: | ||
159 | return -EINVAL; | ||
160 | } | ||
133 | 161 | ||
134 | /* search for closest to maximum */ | 162 | /* search for closest to maximum */ |
135 | for (i = ARRAY_SIZE(da9211_current_limits)-1; i >= 0; i--) { | 163 | for (i = max_size; i >= 0; i--) { |
136 | if (min <= da9211_current_limits[i] && | 164 | if (min <= current_limits[i] && |
137 | max >= da9211_current_limits[i]) { | 165 | max >= current_limits[i]) { |
138 | return regmap_update_bits(chip->regmap, | 166 | return regmap_update_bits(chip->regmap, |
139 | DA9211_REG_BUCK_ILIM, | 167 | DA9211_REG_BUCK_ILIM, |
140 | (0x0F << id*4), (i << id*4)); | 168 | (0x0F << id*4), (i << id*4)); |
@@ -150,14 +178,28 @@ static int da9211_get_current_limit(struct regulator_dev *rdev) | |||
150 | struct da9211 *chip = rdev_get_drvdata(rdev); | 178 | struct da9211 *chip = rdev_get_drvdata(rdev); |
151 | unsigned int data; | 179 | unsigned int data; |
152 | int ret; | 180 | int ret; |
181 | const int *current_limits; | ||
182 | |||
183 | switch (chip->chip_id) { | ||
184 | case DA9211: | ||
185 | current_limits = da9211_current_limits; | ||
186 | break; | ||
187 | case DA9213: | ||
188 | current_limits = da9213_current_limits; | ||
189 | break; | ||
190 | default: | ||
191 | return -EINVAL; | ||
192 | } | ||
153 | 193 | ||
154 | ret = regmap_read(chip->regmap, DA9211_REG_BUCK_ILIM, &data); | 194 | ret = regmap_read(chip->regmap, DA9211_REG_BUCK_ILIM, &data); |
155 | if (ret < 0) | 195 | if (ret < 0) |
156 | return ret; | 196 | return ret; |
157 | 197 | ||
158 | /* select one of 16 values: 0000 (2000mA) to 1111 (5000mA) */ | 198 | /* select one of 16 values: 0000 (2000mA or 3000mA) |
199 | * to 1111 (5000mA or 6000mA). | ||
200 | */ | ||
159 | data = (data >> id*4) & 0x0F; | 201 | data = (data >> id*4) & 0x0F; |
160 | return da9211_current_limits[data]; | 202 | return current_limits[data]; |
161 | } | 203 | } |
162 | 204 | ||
163 | static struct regulator_ops da9211_buck_ops = { | 205 | static struct regulator_ops da9211_buck_ops = { |
@@ -264,10 +306,7 @@ static int da9211_regulator_init(struct da9211 *chip) | |||
264 | } | 306 | } |
265 | 307 | ||
266 | for (i = 0; i < chip->num_regulator; i++) { | 308 | for (i = 0; i < chip->num_regulator; i++) { |
267 | if (chip->pdata) | 309 | config.init_data = &(chip->pdata->init_data[i]); |
268 | config.init_data = | ||
269 | &(chip->pdata->init_data[i]); | ||
270 | |||
271 | config.dev = chip->dev; | 310 | config.dev = chip->dev; |
272 | config.driver_data = chip; | 311 | config.driver_data = chip; |
273 | config.regmap = chip->regmap; | 312 | config.regmap = chip->regmap; |
@@ -301,6 +340,7 @@ static int da9211_i2c_probe(struct i2c_client *i2c, | |||
301 | { | 340 | { |
302 | struct da9211 *chip; | 341 | struct da9211 *chip; |
303 | int error, ret; | 342 | int error, ret; |
343 | unsigned int data; | ||
304 | 344 | ||
305 | chip = devm_kzalloc(&i2c->dev, sizeof(struct da9211), GFP_KERNEL); | 345 | chip = devm_kzalloc(&i2c->dev, sizeof(struct da9211), GFP_KERNEL); |
306 | 346 | ||
@@ -308,7 +348,7 @@ static int da9211_i2c_probe(struct i2c_client *i2c, | |||
308 | chip->regmap = devm_regmap_init_i2c(i2c, &da9211_regmap_config); | 348 | chip->regmap = devm_regmap_init_i2c(i2c, &da9211_regmap_config); |
309 | if (IS_ERR(chip->regmap)) { | 349 | if (IS_ERR(chip->regmap)) { |
310 | error = PTR_ERR(chip->regmap); | 350 | error = PTR_ERR(chip->regmap); |
311 | dev_err(&i2c->dev, "Failed to allocate register map: %d\n", | 351 | dev_err(chip->dev, "Failed to allocate register map: %d\n", |
312 | error); | 352 | error); |
313 | return error; | 353 | return error; |
314 | } | 354 | } |
@@ -316,8 +356,22 @@ static int da9211_i2c_probe(struct i2c_client *i2c, | |||
316 | i2c_set_clientdata(i2c, chip); | 356 | i2c_set_clientdata(i2c, chip); |
317 | 357 | ||
318 | chip->pdata = i2c->dev.platform_data; | 358 | chip->pdata = i2c->dev.platform_data; |
319 | if (!chip->pdata) { | 359 | |
320 | dev_err(&i2c->dev, "No platform init data supplied\n"); | 360 | ret = regmap_read(chip->regmap, DA9211_REG_DEVICE_ID, &data); |
361 | if (ret < 0) { | ||
362 | dev_err(chip->dev, "Failed to read DEVICE_ID reg: %d\n", ret); | ||
363 | return ret; | ||
364 | } | ||
365 | |||
366 | switch (data) { | ||
367 | case DA9211_DEVICE_ID: | ||
368 | chip->chip_id = DA9211; | ||
369 | break; | ||
370 | case DA9213_DEVICE_ID: | ||
371 | chip->chip_id = DA9213; | ||
372 | break; | ||
373 | default: | ||
374 | dev_err(chip->dev, "Unsupported device id = 0x%x.\n", data); | ||
321 | return -ENODEV; | 375 | return -ENODEV; |
322 | } | 376 | } |
323 | 377 | ||
@@ -340,13 +394,14 @@ static int da9211_i2c_probe(struct i2c_client *i2c, | |||
340 | ret = da9211_regulator_init(chip); | 394 | ret = da9211_regulator_init(chip); |
341 | 395 | ||
342 | if (ret < 0) | 396 | if (ret < 0) |
343 | dev_err(&i2c->dev, "Failed to initialize regulator: %d\n", ret); | 397 | dev_err(chip->dev, "Failed to initialize regulator: %d\n", ret); |
344 | 398 | ||
345 | return ret; | 399 | return ret; |
346 | } | 400 | } |
347 | 401 | ||
348 | static const struct i2c_device_id da9211_i2c_id[] = { | 402 | static const struct i2c_device_id da9211_i2c_id[] = { |
349 | {"da9211", 0}, | 403 | {"da9211", DA9211}, |
404 | {"da9213", DA9213}, | ||
350 | {}, | 405 | {}, |
351 | }; | 406 | }; |
352 | 407 | ||
@@ -364,5 +419,5 @@ static struct i2c_driver da9211_regulator_driver = { | |||
364 | module_i2c_driver(da9211_regulator_driver); | 419 | module_i2c_driver(da9211_regulator_driver); |
365 | 420 | ||
366 | MODULE_AUTHOR("James Ban <James.Ban.opensource@diasemi.com>"); | 421 | MODULE_AUTHOR("James Ban <James.Ban.opensource@diasemi.com>"); |
367 | MODULE_DESCRIPTION("Regulator device driver for Dialog DA9211"); | 422 | MODULE_DESCRIPTION("Regulator device driver for Dialog DA9211/DA9213"); |
368 | MODULE_LICENSE("GPL v2"); | 423 | MODULE_LICENSE("GPL v2"); |