]> git.proxmox.com Git - mirror_ubuntu-zesty-kernel.git/blame - drivers/regulator/da9052-regulator.c
regulator: max8660: Use devm_kzalloc()
[mirror_ubuntu-zesty-kernel.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
9210f05b
AL
40/* DA9052 REGULATOR IDs */
41#define DA9052_ID_BUCK1 0
42#define DA9052_ID_BUCK2 1
43#define DA9052_ID_BUCK3 2
44#define DA9052_ID_BUCK4 3
45#define DA9052_ID_LDO1 4
46#define DA9052_ID_LDO2 5
47#define DA9052_ID_LDO3 6
48#define DA9052_ID_LDO4 7
49#define DA9052_ID_LDO5 8
50#define DA9052_ID_LDO6 9
51#define DA9052_ID_LDO7 10
52#define DA9052_ID_LDO8 11
53#define DA9052_ID_LDO9 12
54#define DA9052_ID_LDO10 13
55
08bf1c0a
AJ
56static const u32 da9052_current_limits[3][4] = {
57 {700000, 800000, 1000000, 1200000}, /* DA9052-BC BUCKs */
58 {1600000, 2000000, 2400000, 3000000}, /* DA9053-AA/Bx BUCK-CORE */
59 {800000, 1000000, 1200000, 1500000}, /* DA9053-AA/Bx BUCK-PRO,
60 * BUCK-MEM and BUCK-PERI
61 */
62};
63
64struct da9052_regulator_info {
65 struct regulator_desc reg_desc;
66 int step_uV;
67 int min_uV;
68 int max_uV;
69 unsigned char volt_shift;
70 unsigned char en_bit;
71 unsigned char activate_bit;
72};
73
74struct da9052_regulator {
75 struct da9052 *da9052;
76 struct da9052_regulator_info *info;
77 struct regulator_dev *rdev;
78};
79
80static int verify_range(struct da9052_regulator_info *info,
81 int min_uV, int max_uV)
82{
83 if (min_uV > info->max_uV || max_uV < info->min_uV)
84 return -EINVAL;
85
86 return 0;
87}
88
89static int da9052_regulator_enable(struct regulator_dev *rdev)
90{
91 struct da9052_regulator *regulator = rdev_get_drvdata(rdev);
92 struct da9052_regulator_info *info = regulator->info;
93 int offset = rdev_get_id(rdev);
94
95 return da9052_reg_update(regulator->da9052,
96 DA9052_BUCKCORE_REG + offset,
97 1 << info->en_bit, 1 << info->en_bit);
98}
99
100static int da9052_regulator_disable(struct regulator_dev *rdev)
101{
102 struct da9052_regulator *regulator = rdev_get_drvdata(rdev);
103 struct da9052_regulator_info *info = regulator->info;
104 int offset = rdev_get_id(rdev);
105
106 return da9052_reg_update(regulator->da9052,
107 DA9052_BUCKCORE_REG + offset,
108 1 << info->en_bit, 0);
109}
110
111static int da9052_regulator_is_enabled(struct regulator_dev *rdev)
112{
113 struct da9052_regulator *regulator = rdev_get_drvdata(rdev);
114 struct da9052_regulator_info *info = regulator->info;
115 int offset = rdev_get_id(rdev);
116 int ret;
117
118 ret = da9052_reg_read(regulator->da9052, DA9052_BUCKCORE_REG + offset);
119 if (ret < 0)
120 return ret;
121
122 return ret & (1 << info->en_bit);
123}
124
125static int da9052_dcdc_get_current_limit(struct regulator_dev *rdev)
126{
127 struct da9052_regulator *regulator = rdev_get_drvdata(rdev);
128 int offset = rdev_get_id(rdev);
129 int ret, row = 2;
130
131 ret = da9052_reg_read(regulator->da9052, DA9052_BUCKA_REG + offset/2);
132 if (ret < 0)
133 return ret;
134
135 /* Determine the even or odd position of the buck current limit
136 * register field
137 */
138 if (offset % 2 == 0)
139 ret = (ret & DA9052_BUCK_ILIM_MASK_EVEN) >> 2;
140 else
141 ret = (ret & DA9052_BUCK_ILIM_MASK_ODD) >> 6;
142
143 /* Select the appropriate current limit range */
144 if (regulator->da9052->chip_id == DA9052)
145 row = 0;
146 else if (offset == 0)
147 row = 1;
148
149 return da9052_current_limits[row][ret];
150}
151
152static int da9052_dcdc_set_current_limit(struct regulator_dev *rdev, int min_uA,
153 int max_uA)
154{
155 struct da9052_regulator *regulator = rdev_get_drvdata(rdev);
156 int offset = rdev_get_id(rdev);
157 int reg_val = 0;
158 int i, row = 2;
159
160 /* Select the appropriate current limit range */
161 if (regulator->da9052->chip_id == DA9052)
162 row = 0;
163 else if (offset == 0)
164 row = 1;
165
166 if (min_uA > da9052_current_limits[row][DA9052_MAX_UA] ||
167 max_uA < da9052_current_limits[row][DA9052_MIN_UA])
168 return -EINVAL;
169
170 for (i = 0; i < DA9052_CURRENT_RANGE; i++) {
171 if (min_uA <= da9052_current_limits[row][i]) {
172 reg_val = i;
173 break;
174 }
175 }
176
177 /* Determine the even or odd position of the buck current limit
178 * register field
179 */
180 if (offset % 2 == 0)
181 return da9052_reg_update(regulator->da9052,
182 DA9052_BUCKA_REG + offset/2,
183 DA9052_BUCK_ILIM_MASK_EVEN,
184 reg_val << 2);
185 else
186 return da9052_reg_update(regulator->da9052,
187 DA9052_BUCKA_REG + offset/2,
188 DA9052_BUCK_ILIM_MASK_ODD,
189 reg_val << 6);
190}
191
08bf1c0a
AJ
192static int da9052_list_voltage(struct regulator_dev *rdev,
193 unsigned int selector)
194{
195 struct da9052_regulator *regulator = rdev_get_drvdata(rdev);
196 struct da9052_regulator_info *info = regulator->info;
0ec446ea 197 int id = rdev_get_id(rdev);
08bf1c0a
AJ
198 int volt_uV;
199
0ec446ea
AL
200 if ((id == DA9052_ID_BUCK4) && (regulator->da9052->chip_id == DA9052)
201 && (selector >= DA9052_BUCK_PERI_REG_MAP_UPTO_3uV)) {
202 volt_uV = ((DA9052_BUCK_PERI_REG_MAP_UPTO_3uV * info->step_uV)
203 + info->min_uV);
204 volt_uV += (selector - DA9052_BUCK_PERI_REG_MAP_UPTO_3uV)
205 * (DA9052_BUCK_PERI_3uV_STEP);
206 } else {
207 volt_uV = (selector * info->step_uV) + info->min_uV;
208 }
08bf1c0a
AJ
209
210 if (volt_uV > info->max_uV)
211 return -EINVAL;
212
213 return volt_uV;
214}
215
0ec446ea 216static int da9052_regulator_set_voltage(struct regulator_dev *rdev,
08bf1c0a
AJ
217 int min_uV, int max_uV,
218 unsigned int *selector)
219{
220 struct da9052_regulator *regulator = rdev_get_drvdata(rdev);
221 struct da9052_regulator_info *info = regulator->info;
0ec446ea 222 int id = rdev_get_id(rdev);
08bf1c0a
AJ
223 int ret;
224
225 ret = verify_range(info, min_uV, max_uV);
226 if (ret < 0)
227 return ret;
228
229 if (min_uV < info->min_uV)
230 min_uV = info->min_uV;
231
0ec446ea
AL
232 if ((id == DA9052_ID_BUCK4) && (regulator->da9052->chip_id == DA9052)
233 && (min_uV >= DA9052_CONST_3uV)) {
234 *selector = DA9052_BUCK_PERI_REG_MAP_UPTO_3uV +
235 DIV_ROUND_UP(min_uV - DA9052_CONST_3uV,
236 DA9052_BUCK_PERI_3uV_STEP);
237 } else {
238 *selector = DIV_ROUND_UP(min_uV - info->min_uV, info->step_uV);
239 }
08bf1c0a
AJ
240
241 ret = da9052_list_voltage(rdev, *selector);
242 if (ret < 0)
243 return ret;
244
0ec446ea
AL
245 ret = da9052_reg_update(regulator->da9052,
246 DA9052_BUCKCORE_REG + id,
08bf1c0a 247 (1 << info->volt_shift) - 1, *selector);
08bf1c0a
AJ
248 if (ret < 0)
249 return ret;
250
0ec446ea
AL
251 /* Some LDOs and DCDCs are DVC controlled which requires enabling of
252 * the activate bit to implment the changes on the output.
253 */
254 switch (id) {
255 case DA9052_ID_BUCK1:
256 case DA9052_ID_BUCK2:
257 case DA9052_ID_BUCK3:
258 case DA9052_ID_LDO2:
259 case DA9052_ID_LDO3:
260 ret = da9052_reg_update(regulator->da9052, DA9052_SUPPLY_REG,
261 info->activate_bit, info->activate_bit);
262 break;
263 }
08bf1c0a
AJ
264
265 return ret;
266}
267
0ec446ea 268static int da9052_get_regulator_voltage_sel(struct regulator_dev *rdev)
08bf1c0a
AJ
269{
270 struct da9052_regulator *regulator = rdev_get_drvdata(rdev);
271 struct da9052_regulator_info *info = regulator->info;
272 int offset = rdev_get_id(rdev);
273 int ret;
274
275 ret = da9052_reg_read(regulator->da9052, DA9052_BUCKCORE_REG + offset);
276 if (ret < 0)
277 return ret;
278
279 ret &= ((1 << info->volt_shift) - 1);
280
281 return ret;
282}
283
08bf1c0a 284static struct regulator_ops da9052_dcdc_ops = {
0ec446ea 285 .set_voltage = da9052_regulator_set_voltage,
08bf1c0a
AJ
286 .get_current_limit = da9052_dcdc_get_current_limit,
287 .set_current_limit = da9052_dcdc_set_current_limit,
288
289 .list_voltage = da9052_list_voltage,
290 .get_voltage_sel = da9052_get_regulator_voltage_sel,
291 .is_enabled = da9052_regulator_is_enabled,
292 .enable = da9052_regulator_enable,
293 .disable = da9052_regulator_disable,
294};
295
08bf1c0a 296static struct regulator_ops da9052_ldo_ops = {
0ec446ea 297 .set_voltage = da9052_regulator_set_voltage,
08bf1c0a
AJ
298
299 .list_voltage = da9052_list_voltage,
300 .get_voltage_sel = da9052_get_regulator_voltage_sel,
301 .is_enabled = da9052_regulator_is_enabled,
302 .enable = da9052_regulator_enable,
303 .disable = da9052_regulator_disable,
304};
305
08bf1c0a
AJ
306#define DA9052_LDO(_id, step, min, max, sbits, ebits, abits) \
307{\
308 .reg_desc = {\
9210f05b 309 .name = #_id,\
08bf1c0a
AJ
310 .ops = &da9052_ldo_ops,\
311 .type = REGULATOR_VOLTAGE,\
9210f05b 312 .id = DA9052_ID_##_id,\
7b957654 313 .n_voltages = (max - min) / step + 1, \
08bf1c0a
AJ
314 .owner = THIS_MODULE,\
315 },\
316 .min_uV = (min) * 1000,\
317 .max_uV = (max) * 1000,\
318 .step_uV = (step) * 1000,\
319 .volt_shift = (sbits),\
320 .en_bit = (ebits),\
321 .activate_bit = (abits),\
322}
323
324#define DA9052_DCDC(_id, step, min, max, sbits, ebits, abits) \
325{\
326 .reg_desc = {\
9210f05b 327 .name = #_id,\
08bf1c0a
AJ
328 .ops = &da9052_dcdc_ops,\
329 .type = REGULATOR_VOLTAGE,\
9210f05b 330 .id = DA9052_ID_##_id,\
7b957654 331 .n_voltages = (max - min) / step + 1, \
08bf1c0a
AJ
332 .owner = THIS_MODULE,\
333 },\
334 .min_uV = (min) * 1000,\
335 .max_uV = (max) * 1000,\
336 .step_uV = (step) * 1000,\
337 .volt_shift = (sbits),\
338 .en_bit = (ebits),\
339 .activate_bit = (abits),\
340}
341
6242eae9 342static struct da9052_regulator_info da9052_regulator_info[] = {
9210f05b
AL
343 DA9052_DCDC(BUCK1, 25, 500, 2075, 6, 6, DA9052_SUPPLY_VBCOREGO),
344 DA9052_DCDC(BUCK2, 25, 500, 2075, 6, 6, DA9052_SUPPLY_VBPROGO),
345 DA9052_DCDC(BUCK3, 25, 925, 2500, 6, 6, DA9052_SUPPLY_VBMEMGO),
0ec446ea 346 DA9052_DCDC(BUCK4, 50, 1800, 3600, 5, 6, 0),
9210f05b 347 DA9052_LDO(LDO1, 50, 600, 1800, 5, 6, 0),
0ec446ea
AL
348 DA9052_LDO(LDO2, 25, 600, 1800, 6, 6, DA9052_SUPPLY_VLDO2GO),
349 DA9052_LDO(LDO3, 25, 1725, 3300, 6, 6, DA9052_SUPPLY_VLDO3GO),
9210f05b
AL
350 DA9052_LDO(LDO4, 25, 1725, 3300, 6, 6, 0),
351 DA9052_LDO(LDO5, 50, 1200, 3600, 6, 6, 0),
352 DA9052_LDO(LDO6, 50, 1200, 3600, 6, 6, 0),
353 DA9052_LDO(LDO7, 50, 1200, 3600, 6, 6, 0),
354 DA9052_LDO(LDO8, 50, 1200, 3600, 6, 6, 0),
355 DA9052_LDO(LDO9, 50, 1250, 3650, 6, 6, 0),
356 DA9052_LDO(LDO10, 50, 1200, 3600, 6, 6, 0),
08bf1c0a
AJ
357};
358
6242eae9 359static struct da9052_regulator_info da9053_regulator_info[] = {
9210f05b
AL
360 DA9052_DCDC(BUCK1, 25, 500, 2075, 6, 6, DA9052_SUPPLY_VBCOREGO),
361 DA9052_DCDC(BUCK2, 25, 500, 2075, 6, 6, DA9052_SUPPLY_VBPROGO),
362 DA9052_DCDC(BUCK3, 25, 925, 2500, 6, 6, DA9052_SUPPLY_VBMEMGO),
0ec446ea 363 DA9052_DCDC(BUCK4, 25, 925, 2500, 6, 6, 0),
9210f05b 364 DA9052_LDO(LDO1, 50, 600, 1800, 5, 6, 0),
0ec446ea
AL
365 DA9052_LDO(LDO2, 25, 600, 1800, 6, 6, DA9052_SUPPLY_VLDO2GO),
366 DA9052_LDO(LDO3, 25, 1725, 3300, 6, 6, DA9052_SUPPLY_VLDO3GO),
9210f05b
AL
367 DA9052_LDO(LDO4, 25, 1725, 3300, 6, 6, 0),
368 DA9052_LDO(LDO5, 50, 1200, 3600, 6, 6, 0),
369 DA9052_LDO(LDO6, 50, 1200, 3600, 6, 6, 0),
370 DA9052_LDO(LDO7, 50, 1200, 3600, 6, 6, 0),
371 DA9052_LDO(LDO8, 50, 1200, 3600, 6, 6, 0),
372 DA9052_LDO(LDO9, 50, 1250, 3650, 6, 6, 0),
373 DA9052_LDO(LDO10, 50, 1200, 3600, 6, 6, 0),
08bf1c0a
AJ
374};
375
376static inline struct da9052_regulator_info *find_regulator_info(u8 chip_id,
377 int id)
378{
379 struct da9052_regulator_info *info;
380 int i;
381
984b5a6b
AJ
382 switch (chip_id) {
383 case DA9052:
08bf1c0a
AJ
384 for (i = 0; i < ARRAY_SIZE(da9052_regulator_info); i++) {
385 info = &da9052_regulator_info[i];
386 if (info->reg_desc.id == id)
387 return info;
388 }
984b5a6b
AJ
389 break;
390 case DA9053_AA:
391 case DA9053_BA:
392 case DA9053_BB:
08bf1c0a
AJ
393 for (i = 0; i < ARRAY_SIZE(da9053_regulator_info); i++) {
394 info = &da9053_regulator_info[i];
395 if (info->reg_desc.id == id)
396 return info;
397 }
984b5a6b 398 break;
08bf1c0a
AJ
399 }
400
401 return NULL;
402}
403
404static int __devinit da9052_regulator_probe(struct platform_device *pdev)
405{
c172708d 406 struct regulator_config config = { };
08bf1c0a
AJ
407 struct da9052_regulator *regulator;
408 struct da9052 *da9052;
409 struct da9052_pdata *pdata;
08bf1c0a 410
984b5a6b
AJ
411 regulator = devm_kzalloc(&pdev->dev, sizeof(struct da9052_regulator),
412 GFP_KERNEL);
08bf1c0a
AJ
413 if (!regulator)
414 return -ENOMEM;
415
416 da9052 = dev_get_drvdata(pdev->dev.parent);
417 pdata = da9052->dev->platform_data;
418 regulator->da9052 = da9052;
419
420 regulator->info = find_regulator_info(regulator->da9052->chip_id,
421 pdev->id);
422 if (regulator->info == NULL) {
423 dev_err(&pdev->dev, "invalid regulator ID specified\n");
7eb6444f 424 return -EINVAL;
08bf1c0a 425 }
c172708d
MB
426
427 config.dev = &pdev->dev;
428 config.init_data = pdata->regulators[pdev->id];
429 config.driver_data = regulator;
430
08bf1c0a 431 regulator->rdev = regulator_register(&regulator->info->reg_desc,
c172708d 432 &config);
08bf1c0a
AJ
433 if (IS_ERR(regulator->rdev)) {
434 dev_err(&pdev->dev, "failed to register regulator %s\n",
435 regulator->info->reg_desc.name);
7eb6444f 436 return PTR_ERR(regulator->rdev);
08bf1c0a
AJ
437 }
438
439 platform_set_drvdata(pdev, regulator);
440
441 return 0;
08bf1c0a
AJ
442}
443
444static int __devexit da9052_regulator_remove(struct platform_device *pdev)
445{
446 struct da9052_regulator *regulator = platform_get_drvdata(pdev);
447
448 regulator_unregister(regulator->rdev);
08bf1c0a
AJ
449 return 0;
450}
451
452static struct platform_driver da9052_regulator_driver = {
453 .probe = da9052_regulator_probe,
454 .remove = __devexit_p(da9052_regulator_remove),
455 .driver = {
456 .name = "da9052-regulator",
457 .owner = THIS_MODULE,
458 },
459};
460
461static int __init da9052_regulator_init(void)
462{
463 return platform_driver_register(&da9052_regulator_driver);
464}
465subsys_initcall(da9052_regulator_init);
466
467static void __exit da9052_regulator_exit(void)
468{
469 platform_driver_unregister(&da9052_regulator_driver);
470}
471module_exit(da9052_regulator_exit);
472
473MODULE_AUTHOR("David Dajun Chen <dchen@diasemi.com>");
474MODULE_DESCRIPTION("Power Regulator driver for Dialog DA9052 PMIC");
475MODULE_LICENSE("GPL");
476MODULE_ALIAS("platform:da9052-regulator");