regulator: Convert tps65023 to set_voltage_sel
[linux-block.git] / drivers / regulator / da9052-regulator.c
CommitLineData
08bf1c0a
AJ
1/*
2* da9052-regulator.c: Regulator driver for DA9052
3*
4* Copyright(c) 2011 Dialog Semiconductor Ltd.
5*
6* Author: David Dajun Chen <dchen@diasemi.com>
7*
8* This program is free software; you can redistribute it and/or modify
9* it under the terms of the GNU General Public License as published by
10* the Free Software Foundation; either version 2 of the License, or
11* (at your option) any later version.
12*
13*/
14
15#include <linux/module.h>
16#include <linux/moduleparam.h>
17#include <linux/init.h>
18#include <linux/err.h>
19#include <linux/platform_device.h>
20#include <linux/regulator/driver.h>
21#include <linux/regulator/machine.h>
22
23#include <linux/mfd/da9052/da9052.h>
24#include <linux/mfd/da9052/reg.h>
25#include <linux/mfd/da9052/pdata.h>
26
27/* Buck step size */
28#define DA9052_BUCK_PERI_3uV_STEP 100000
29#define DA9052_BUCK_PERI_REG_MAP_UPTO_3uV 24
30#define DA9052_CONST_3uV 3000000
31
32#define DA9052_MIN_UA 0
33#define DA9052_MAX_UA 3
34#define DA9052_CURRENT_RANGE 4
35
36/* Bit masks */
37#define DA9052_BUCK_ILIM_MASK_EVEN 0x0c
38#define DA9052_BUCK_ILIM_MASK_ODD 0xc0
39
40static const u32 da9052_current_limits[3][4] = {
41 {700000, 800000, 1000000, 1200000}, /* DA9052-BC BUCKs */
42 {1600000, 2000000, 2400000, 3000000}, /* DA9053-AA/Bx BUCK-CORE */
43 {800000, 1000000, 1200000, 1500000}, /* DA9053-AA/Bx BUCK-PRO,
44 * BUCK-MEM and BUCK-PERI
45 */
46};
47
48struct da9052_regulator_info {
49 struct regulator_desc reg_desc;
50 int step_uV;
51 int min_uV;
52 int max_uV;
53 unsigned char volt_shift;
54 unsigned char en_bit;
55 unsigned char activate_bit;
56};
57
58struct da9052_regulator {
59 struct da9052 *da9052;
60 struct da9052_regulator_info *info;
61 struct regulator_dev *rdev;
62};
63
64static int verify_range(struct da9052_regulator_info *info,
65 int min_uV, int max_uV)
66{
67 if (min_uV > info->max_uV || max_uV < info->min_uV)
68 return -EINVAL;
69
70 return 0;
71}
72
73static int da9052_regulator_enable(struct regulator_dev *rdev)
74{
75 struct da9052_regulator *regulator = rdev_get_drvdata(rdev);
76 struct da9052_regulator_info *info = regulator->info;
77 int offset = rdev_get_id(rdev);
78
79 return da9052_reg_update(regulator->da9052,
80 DA9052_BUCKCORE_REG + offset,
81 1 << info->en_bit, 1 << info->en_bit);
82}
83
84static int da9052_regulator_disable(struct regulator_dev *rdev)
85{
86 struct da9052_regulator *regulator = rdev_get_drvdata(rdev);
87 struct da9052_regulator_info *info = regulator->info;
88 int offset = rdev_get_id(rdev);
89
90 return da9052_reg_update(regulator->da9052,
91 DA9052_BUCKCORE_REG + offset,
92 1 << info->en_bit, 0);
93}
94
95static int da9052_regulator_is_enabled(struct regulator_dev *rdev)
96{
97 struct da9052_regulator *regulator = rdev_get_drvdata(rdev);
98 struct da9052_regulator_info *info = regulator->info;
99 int offset = rdev_get_id(rdev);
100 int ret;
101
102 ret = da9052_reg_read(regulator->da9052, DA9052_BUCKCORE_REG + offset);
103 if (ret < 0)
104 return ret;
105
106 return ret & (1 << info->en_bit);
107}
108
109static int da9052_dcdc_get_current_limit(struct regulator_dev *rdev)
110{
111 struct da9052_regulator *regulator = rdev_get_drvdata(rdev);
112 int offset = rdev_get_id(rdev);
113 int ret, row = 2;
114
115 ret = da9052_reg_read(regulator->da9052, DA9052_BUCKA_REG + offset/2);
116 if (ret < 0)
117 return ret;
118
119 /* Determine the even or odd position of the buck current limit
120 * register field
121 */
122 if (offset % 2 == 0)
123 ret = (ret & DA9052_BUCK_ILIM_MASK_EVEN) >> 2;
124 else
125 ret = (ret & DA9052_BUCK_ILIM_MASK_ODD) >> 6;
126
127 /* Select the appropriate current limit range */
128 if (regulator->da9052->chip_id == DA9052)
129 row = 0;
130 else if (offset == 0)
131 row = 1;
132
133 return da9052_current_limits[row][ret];
134}
135
136static int da9052_dcdc_set_current_limit(struct regulator_dev *rdev, int min_uA,
137 int max_uA)
138{
139 struct da9052_regulator *regulator = rdev_get_drvdata(rdev);
140 int offset = rdev_get_id(rdev);
141 int reg_val = 0;
142 int i, row = 2;
143
144 /* Select the appropriate current limit range */
145 if (regulator->da9052->chip_id == DA9052)
146 row = 0;
147 else if (offset == 0)
148 row = 1;
149
150 if (min_uA > da9052_current_limits[row][DA9052_MAX_UA] ||
151 max_uA < da9052_current_limits[row][DA9052_MIN_UA])
152 return -EINVAL;
153
154 for (i = 0; i < DA9052_CURRENT_RANGE; i++) {
155 if (min_uA <= da9052_current_limits[row][i]) {
156 reg_val = i;
157 break;
158 }
159 }
160
161 /* Determine the even or odd position of the buck current limit
162 * register field
163 */
164 if (offset % 2 == 0)
165 return da9052_reg_update(regulator->da9052,
166 DA9052_BUCKA_REG + offset/2,
167 DA9052_BUCK_ILIM_MASK_EVEN,
168 reg_val << 2);
169 else
170 return da9052_reg_update(regulator->da9052,
171 DA9052_BUCKA_REG + offset/2,
172 DA9052_BUCK_ILIM_MASK_ODD,
173 reg_val << 6);
174}
175
176static int da9052_list_buckperi_voltage(struct regulator_dev *rdev,
177 unsigned int selector)
178{
179 struct da9052_regulator *regulator = rdev_get_drvdata(rdev);
180 struct da9052_regulator_info *info = regulator->info;
181 int volt_uV;
182
183 if ((regulator->da9052->chip_id == DA9052) &&
184 (selector >= DA9052_BUCK_PERI_REG_MAP_UPTO_3uV)) {
185 volt_uV = ((DA9052_BUCK_PERI_REG_MAP_UPTO_3uV * info->step_uV)
186 + info->min_uV);
187 volt_uV += (selector - DA9052_BUCK_PERI_REG_MAP_UPTO_3uV)
188 * (DA9052_BUCK_PERI_3uV_STEP);
189 } else
190 volt_uV = (selector * info->step_uV) + info->min_uV;
191
192 if (volt_uV > info->max_uV)
193 return -EINVAL;
194
195 return volt_uV;
196}
197
198static int da9052_list_voltage(struct regulator_dev *rdev,
199 unsigned int selector)
200{
201 struct da9052_regulator *regulator = rdev_get_drvdata(rdev);
202 struct da9052_regulator_info *info = regulator->info;
203 int volt_uV;
204
205 volt_uV = info->min_uV + info->step_uV * selector;
206
207 if (volt_uV > info->max_uV)
208 return -EINVAL;
209
210 return volt_uV;
211}
212
213static int da9052_regulator_set_voltage_int(struct regulator_dev *rdev,
214 int min_uV, int max_uV,
215 unsigned int *selector)
216{
217 struct da9052_regulator *regulator = rdev_get_drvdata(rdev);
218 struct da9052_regulator_info *info = regulator->info;
219 int offset = rdev_get_id(rdev);
220 int ret;
221
222 ret = verify_range(info, min_uV, max_uV);
223 if (ret < 0)
224 return ret;
225
226 if (min_uV < info->min_uV)
227 min_uV = info->min_uV;
228
93651218 229 *selector = DIV_ROUND_UP(min_uV - info->min_uV, info->step_uV);
08bf1c0a
AJ
230
231 ret = da9052_list_voltage(rdev, *selector);
232 if (ret < 0)
233 return ret;
234
235 return da9052_reg_update(regulator->da9052,
236 DA9052_BUCKCORE_REG + offset,
237 (1 << info->volt_shift) - 1, *selector);
238}
239
240static int da9052_set_ldo_voltage(struct regulator_dev *rdev,
241 int min_uV, int max_uV,
242 unsigned int *selector)
243{
244 return da9052_regulator_set_voltage_int(rdev, min_uV, max_uV, selector);
245}
246
247static int da9052_set_ldo5_6_voltage(struct regulator_dev *rdev,
248 int min_uV, int max_uV,
249 unsigned int *selector)
250{
251 struct da9052_regulator *regulator = rdev_get_drvdata(rdev);
252 struct da9052_regulator_info *info = regulator->info;
253 int ret;
254
255 ret = da9052_regulator_set_voltage_int(rdev, min_uV, max_uV, selector);
256 if (ret < 0)
257 return ret;
258
259 /* Some LDOs are DVC controlled which requires enabling of
260 * the LDO activate bit to implment the changes on the
261 * LDO output.
262 */
4adf9bed
AL
263 return da9052_reg_update(regulator->da9052, DA9052_SUPPLY_REG,
264 info->activate_bit, info->activate_bit);
08bf1c0a
AJ
265}
266
267static int da9052_set_dcdc_voltage(struct regulator_dev *rdev,
268 int min_uV, int max_uV,
269 unsigned int *selector)
270{
271 struct da9052_regulator *regulator = rdev_get_drvdata(rdev);
272 struct da9052_regulator_info *info = regulator->info;
273 int ret;
274
275 ret = da9052_regulator_set_voltage_int(rdev, min_uV, max_uV, selector);
276 if (ret < 0)
277 return ret;
278
279 /* Some DCDCs are DVC controlled which requires enabling of
280 * the DCDC activate bit to implment the changes on the
281 * DCDC output.
282 */
4adf9bed
AL
283 return da9052_reg_update(regulator->da9052, DA9052_SUPPLY_REG,
284 info->activate_bit, info->activate_bit);
08bf1c0a
AJ
285}
286
287static int da9052_get_regulator_voltage_sel(struct regulator_dev *rdev)
288{
289 struct da9052_regulator *regulator = rdev_get_drvdata(rdev);
290 struct da9052_regulator_info *info = regulator->info;
291 int offset = rdev_get_id(rdev);
292 int ret;
293
294 ret = da9052_reg_read(regulator->da9052, DA9052_BUCKCORE_REG + offset);
295 if (ret < 0)
296 return ret;
297
298 ret &= ((1 << info->volt_shift) - 1);
299
300 return ret;
301}
302
303static int da9052_set_buckperi_voltage(struct regulator_dev *rdev, int min_uV,
304 int max_uV, unsigned int *selector)
305{
306 struct da9052_regulator *regulator = rdev_get_drvdata(rdev);
307 struct da9052_regulator_info *info = regulator->info;
308 int offset = rdev_get_id(rdev);
309 int ret;
310
311 ret = verify_range(info, min_uV, max_uV);
312 if (ret < 0)
313 return ret;
314
315 if (min_uV < info->min_uV)
316 min_uV = info->min_uV;
317
318 if ((regulator->da9052->chip_id == DA9052) &&
319 (min_uV >= DA9052_CONST_3uV))
320 *selector = DA9052_BUCK_PERI_REG_MAP_UPTO_3uV +
93651218
AL
321 DIV_ROUND_UP(min_uV - DA9052_CONST_3uV,
322 DA9052_BUCK_PERI_3uV_STEP);
08bf1c0a 323 else
93651218 324 *selector = DIV_ROUND_UP(min_uV - info->min_uV, info->step_uV);
08bf1c0a
AJ
325
326 ret = da9052_list_buckperi_voltage(rdev, *selector);
327 if (ret < 0)
328 return ret;
329
330 return da9052_reg_update(regulator->da9052,
331 DA9052_BUCKCORE_REG + offset,
332 (1 << info->volt_shift) - 1, *selector);
333}
334
335static int da9052_get_buckperi_voltage_sel(struct regulator_dev *rdev)
336{
337 struct da9052_regulator *regulator = rdev_get_drvdata(rdev);
338 struct da9052_regulator_info *info = regulator->info;
339 int offset = rdev_get_id(rdev);
340 int ret;
341
342 ret = da9052_reg_read(regulator->da9052, DA9052_BUCKCORE_REG + offset);
343 if (ret < 0)
344 return ret;
345
346 ret &= ((1 << info->volt_shift) - 1);
347
348 return ret;
349}
350
351static struct regulator_ops da9052_buckperi_ops = {
352 .list_voltage = da9052_list_buckperi_voltage,
353 .get_voltage_sel = da9052_get_buckperi_voltage_sel,
354 .set_voltage = da9052_set_buckperi_voltage,
355
356 .get_current_limit = da9052_dcdc_get_current_limit,
357 .set_current_limit = da9052_dcdc_set_current_limit,
358
359 .is_enabled = da9052_regulator_is_enabled,
360 .enable = da9052_regulator_enable,
361 .disable = da9052_regulator_disable,
362};
363
364static struct regulator_ops da9052_dcdc_ops = {
365 .set_voltage = da9052_set_dcdc_voltage,
366 .get_current_limit = da9052_dcdc_get_current_limit,
367 .set_current_limit = da9052_dcdc_set_current_limit,
368
369 .list_voltage = da9052_list_voltage,
370 .get_voltage_sel = da9052_get_regulator_voltage_sel,
371 .is_enabled = da9052_regulator_is_enabled,
372 .enable = da9052_regulator_enable,
373 .disable = da9052_regulator_disable,
374};
375
376static struct regulator_ops da9052_ldo5_6_ops = {
377 .set_voltage = da9052_set_ldo5_6_voltage,
378
379 .list_voltage = da9052_list_voltage,
380 .get_voltage_sel = da9052_get_regulator_voltage_sel,
381 .is_enabled = da9052_regulator_is_enabled,
382 .enable = da9052_regulator_enable,
383 .disable = da9052_regulator_disable,
384};
385
386static struct regulator_ops da9052_ldo_ops = {
387 .set_voltage = da9052_set_ldo_voltage,
388
389 .list_voltage = da9052_list_voltage,
390 .get_voltage_sel = da9052_get_regulator_voltage_sel,
391 .is_enabled = da9052_regulator_is_enabled,
392 .enable = da9052_regulator_enable,
393 .disable = da9052_regulator_disable,
394};
395
396#define DA9052_LDO5_6(_id, step, min, max, sbits, ebits, abits) \
397{\
398 .reg_desc = {\
399 .name = "LDO" #_id,\
400 .ops = &da9052_ldo5_6_ops,\
401 .type = REGULATOR_VOLTAGE,\
402 .id = _id,\
7b957654 403 .n_voltages = (max - min) / step + 1, \
08bf1c0a
AJ
404 .owner = THIS_MODULE,\
405 },\
406 .min_uV = (min) * 1000,\
407 .max_uV = (max) * 1000,\
408 .step_uV = (step) * 1000,\
409 .volt_shift = (sbits),\
410 .en_bit = (ebits),\
411 .activate_bit = (abits),\
412}
413
414#define DA9052_LDO(_id, step, min, max, sbits, ebits, abits) \
415{\
416 .reg_desc = {\
417 .name = "LDO" #_id,\
418 .ops = &da9052_ldo_ops,\
419 .type = REGULATOR_VOLTAGE,\
420 .id = _id,\
7b957654 421 .n_voltages = (max - min) / step + 1, \
08bf1c0a
AJ
422 .owner = THIS_MODULE,\
423 },\
424 .min_uV = (min) * 1000,\
425 .max_uV = (max) * 1000,\
426 .step_uV = (step) * 1000,\
427 .volt_shift = (sbits),\
428 .en_bit = (ebits),\
429 .activate_bit = (abits),\
430}
431
432#define DA9052_DCDC(_id, step, min, max, sbits, ebits, abits) \
433{\
434 .reg_desc = {\
435 .name = "BUCK" #_id,\
436 .ops = &da9052_dcdc_ops,\
437 .type = REGULATOR_VOLTAGE,\
438 .id = _id,\
7b957654 439 .n_voltages = (max - min) / step + 1, \
08bf1c0a
AJ
440 .owner = THIS_MODULE,\
441 },\
442 .min_uV = (min) * 1000,\
443 .max_uV = (max) * 1000,\
444 .step_uV = (step) * 1000,\
445 .volt_shift = (sbits),\
446 .en_bit = (ebits),\
447 .activate_bit = (abits),\
448}
449
450#define DA9052_BUCKPERI(_id, step, min, max, sbits, ebits, abits) \
451{\
452 .reg_desc = {\
453 .name = "BUCK" #_id,\
454 .ops = &da9052_buckperi_ops,\
455 .type = REGULATOR_VOLTAGE,\
456 .id = _id,\
7b957654 457 .n_voltages = (max - min) / step + 1, \
08bf1c0a
AJ
458 .owner = THIS_MODULE,\
459 },\
460 .min_uV = (min) * 1000,\
461 .max_uV = (max) * 1000,\
462 .step_uV = (step) * 1000,\
463 .volt_shift = (sbits),\
464 .en_bit = (ebits),\
465 .activate_bit = (abits),\
466}
467
6242eae9 468static struct da9052_regulator_info da9052_regulator_info[] = {
08bf1c0a
AJ
469 /* Buck1 - 4 */
470 DA9052_DCDC(0, 25, 500, 2075, 6, 6, DA9052_SUPPLY_VBCOREGO),
471 DA9052_DCDC(1, 25, 500, 2075, 6, 6, DA9052_SUPPLY_VBPROGO),
472 DA9052_DCDC(2, 25, 925, 2500, 6, 6, DA9052_SUPPLY_VBMEMGO),
473 DA9052_BUCKPERI(3, 50, 1800, 3600, 5, 6, 0),
474 /* LD01 - LDO10 */
475 DA9052_LDO(4, 50, 600, 1800, 5, 6, 0),
476 DA9052_LDO5_6(5, 25, 600, 1800, 6, 6, DA9052_SUPPLY_VLDO2GO),
477 DA9052_LDO5_6(6, 25, 1725, 3300, 6, 6, DA9052_SUPPLY_VLDO3GO),
478 DA9052_LDO(7, 25, 1725, 3300, 6, 6, 0),
479 DA9052_LDO(8, 50, 1200, 3600, 6, 6, 0),
480 DA9052_LDO(9, 50, 1200, 3600, 6, 6, 0),
481 DA9052_LDO(10, 50, 1200, 3600, 6, 6, 0),
482 DA9052_LDO(11, 50, 1200, 3600, 6, 6, 0),
483 DA9052_LDO(12, 50, 1250, 3650, 6, 6, 0),
484 DA9052_LDO(13, 50, 1200, 3600, 6, 6, 0),
485};
486
6242eae9 487static struct da9052_regulator_info da9053_regulator_info[] = {
08bf1c0a
AJ
488 /* Buck1 - 4 */
489 DA9052_DCDC(0, 25, 500, 2075, 6, 6, DA9052_SUPPLY_VBCOREGO),
490 DA9052_DCDC(1, 25, 500, 2075, 6, 6, DA9052_SUPPLY_VBPROGO),
491 DA9052_DCDC(2, 25, 925, 2500, 6, 6, DA9052_SUPPLY_VBMEMGO),
492 DA9052_BUCKPERI(3, 25, 925, 2500, 6, 6, 0),
493 /* LD01 - LDO10 */
494 DA9052_LDO(4, 50, 600, 1800, 5, 6, 0),
495 DA9052_LDO5_6(5, 25, 600, 1800, 6, 6, DA9052_SUPPLY_VLDO2GO),
496 DA9052_LDO5_6(6, 25, 1725, 3300, 6, 6, DA9052_SUPPLY_VLDO3GO),
497 DA9052_LDO(7, 25, 1725, 3300, 6, 6, 0),
498 DA9052_LDO(8, 50, 1200, 3600, 6, 6, 0),
499 DA9052_LDO(9, 50, 1200, 3600, 6, 6, 0),
500 DA9052_LDO(10, 50, 1200, 3600, 6, 6, 0),
501 DA9052_LDO(11, 50, 1200, 3600, 6, 6, 0),
502 DA9052_LDO(12, 50, 1250, 3650, 6, 6, 0),
503 DA9052_LDO(13, 50, 1200, 3600, 6, 6, 0),
504};
505
506static inline struct da9052_regulator_info *find_regulator_info(u8 chip_id,
507 int id)
508{
509 struct da9052_regulator_info *info;
510 int i;
511
984b5a6b
AJ
512 switch (chip_id) {
513 case DA9052:
08bf1c0a
AJ
514 for (i = 0; i < ARRAY_SIZE(da9052_regulator_info); i++) {
515 info = &da9052_regulator_info[i];
516 if (info->reg_desc.id == id)
517 return info;
518 }
984b5a6b
AJ
519 break;
520 case DA9053_AA:
521 case DA9053_BA:
522 case DA9053_BB:
08bf1c0a
AJ
523 for (i = 0; i < ARRAY_SIZE(da9053_regulator_info); i++) {
524 info = &da9053_regulator_info[i];
525 if (info->reg_desc.id == id)
526 return info;
527 }
984b5a6b 528 break;
08bf1c0a
AJ
529 }
530
531 return NULL;
532}
533
534static int __devinit da9052_regulator_probe(struct platform_device *pdev)
535{
536 struct da9052_regulator *regulator;
537 struct da9052 *da9052;
538 struct da9052_pdata *pdata;
539 int ret;
540
984b5a6b
AJ
541 regulator = devm_kzalloc(&pdev->dev, sizeof(struct da9052_regulator),
542 GFP_KERNEL);
08bf1c0a
AJ
543 if (!regulator)
544 return -ENOMEM;
545
546 da9052 = dev_get_drvdata(pdev->dev.parent);
547 pdata = da9052->dev->platform_data;
548 regulator->da9052 = da9052;
549
550 regulator->info = find_regulator_info(regulator->da9052->chip_id,
551 pdev->id);
552 if (regulator->info == NULL) {
553 dev_err(&pdev->dev, "invalid regulator ID specified\n");
554 ret = -EINVAL;
555 goto err;
556 }
557 regulator->rdev = regulator_register(&regulator->info->reg_desc,
558 &pdev->dev,
559 pdata->regulators[pdev->id],
47aed92c 560 regulator, NULL);
08bf1c0a
AJ
561 if (IS_ERR(regulator->rdev)) {
562 dev_err(&pdev->dev, "failed to register regulator %s\n",
563 regulator->info->reg_desc.name);
564 ret = PTR_ERR(regulator->rdev);
565 goto err;
566 }
567
568 platform_set_drvdata(pdev, regulator);
569
570 return 0;
571err:
984b5a6b 572 devm_kfree(&pdev->dev, regulator);
08bf1c0a
AJ
573 return ret;
574}
575
576static int __devexit da9052_regulator_remove(struct platform_device *pdev)
577{
578 struct da9052_regulator *regulator = platform_get_drvdata(pdev);
579
580 regulator_unregister(regulator->rdev);
984b5a6b 581 devm_kfree(&pdev->dev, regulator);
08bf1c0a
AJ
582
583 return 0;
584}
585
586static struct platform_driver da9052_regulator_driver = {
587 .probe = da9052_regulator_probe,
588 .remove = __devexit_p(da9052_regulator_remove),
589 .driver = {
590 .name = "da9052-regulator",
591 .owner = THIS_MODULE,
592 },
593};
594
595static int __init da9052_regulator_init(void)
596{
597 return platform_driver_register(&da9052_regulator_driver);
598}
599subsys_initcall(da9052_regulator_init);
600
601static void __exit da9052_regulator_exit(void)
602{
603 platform_driver_unregister(&da9052_regulator_driver);
604}
605module_exit(da9052_regulator_exit);
606
607MODULE_AUTHOR("David Dajun Chen <dchen@diasemi.com>");
608MODULE_DESCRIPTION("Power Regulator driver for Dialog DA9052 PMIC");
609MODULE_LICENSE("GPL");
610MODULE_ALIAS("platform:da9052-regulator");