hung_task-allow-hung_task_panic-when-hung_task_warnings-is-0-fix
[deliverable/linux.git] / drivers / regulator / 88pm8607.c
CommitLineData
be0e2d3e
HZ
1/*
2 * Regulators driver for Marvell 88PM8607
3 *
4 * Copyright (C) 2009 Marvell International Ltd.
e54f19bf 5 * Haojian Zhuang <haojian.zhuang@marvell.com>
be0e2d3e
HZ
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License version 2 as
9 * published by the Free Software Foundation.
10 */
11#include <linux/kernel.h>
12#include <linux/init.h>
13#include <linux/err.h>
53dbab7a 14#include <linux/i2c.h>
2e57d567
HZ
15#include <linux/of.h>
16#include <linux/regulator/of_regulator.h>
be0e2d3e
HZ
17#include <linux/platform_device.h>
18#include <linux/regulator/driver.h>
19#include <linux/regulator/machine.h>
53dbab7a 20#include <linux/mfd/88pm860x.h>
65602c32 21#include <linux/module.h>
be0e2d3e
HZ
22
23struct pm8607_regulator_info {
24 struct regulator_desc desc;
53dbab7a 25 struct pm860x_chip *chip;
be0e2d3e 26 struct regulator_dev *regulator;
53dbab7a 27 struct i2c_client *i2c;
e7a7810a 28 struct i2c_client *i2c_8606;
be0e2d3e 29
9f79e9db
HZ
30 unsigned int *vol_table;
31 unsigned int *vol_suspend;
32
be0e2d3e
HZ
33 int slope_double;
34};
35
9f79e9db
HZ
36static const unsigned int BUCK1_table[] = {
37 725000, 750000, 775000, 800000, 825000, 850000, 875000, 900000,
38 925000, 950000, 975000, 1000000, 1025000, 1050000, 1075000, 1100000,
39 1125000, 1150000, 1175000, 1200000, 1225000, 1250000, 1275000, 1300000,
40 1325000, 1350000, 1375000, 1400000, 1425000, 1450000, 1475000, 1500000,
41 0, 25000, 50000, 75000, 100000, 125000, 150000, 175000,
42 200000, 225000, 250000, 275000, 300000, 325000, 350000, 375000,
43 400000, 425000, 450000, 475000, 500000, 525000, 550000, 575000,
44 600000, 625000, 650000, 675000, 700000, 725000, 750000, 775000,
45};
be0e2d3e 46
9f79e9db
HZ
47static const unsigned int BUCK1_suspend_table[] = {
48 0, 25000, 50000, 75000, 100000, 125000, 150000, 175000,
49 200000, 225000, 250000, 275000, 300000, 325000, 350000, 375000,
50 400000, 425000, 450000, 475000, 500000, 525000, 550000, 575000,
51 600000, 625000, 650000, 675000, 700000, 725000, 750000, 775000,
52 800000, 825000, 850000, 875000, 900000, 925000, 950000, 975000,
53 1000000, 1025000, 1050000, 1075000, 1100000, 1125000, 1150000, 1175000,
54 1200000, 1225000, 1250000, 1275000, 1300000, 1325000, 1350000, 1375000,
55 1400000, 1425000, 1450000, 1475000, 1500000, 1500000, 1500000, 1500000,
56};
57
58static const unsigned int BUCK2_table[] = {
59 0, 50000, 100000, 150000, 200000, 250000, 300000, 350000,
60 400000, 450000, 500000, 550000, 600000, 650000, 700000, 750000,
61 800000, 850000, 900000, 950000, 1000000, 1050000, 1100000, 1150000,
62 1200000, 1250000, 1300000, 1350000, 1400000, 1450000, 1500000, 1550000,
63 1600000, 1650000, 1700000, 1750000, 1800000, 1850000, 1900000, 1950000,
64 2000000, 2050000, 2100000, 2150000, 2200000, 2250000, 2300000, 2350000,
65 2400000, 2450000, 2500000, 2550000, 2600000, 2650000, 2700000, 2750000,
66 2800000, 2850000, 2900000, 2950000, 3000000, 3000000, 3000000, 3000000,
67};
68
69static const unsigned int BUCK2_suspend_table[] = {
70 0, 50000, 100000, 150000, 200000, 250000, 300000, 350000,
71 400000, 450000, 500000, 550000, 600000, 650000, 700000, 750000,
72 800000, 850000, 900000, 950000, 1000000, 1050000, 1100000, 1150000,
73 1200000, 1250000, 1300000, 1350000, 1400000, 1450000, 1500000, 1550000,
74 1600000, 1650000, 1700000, 1750000, 1800000, 1850000, 1900000, 1950000,
75 2000000, 2050000, 2100000, 2150000, 2200000, 2250000, 2300000, 2350000,
76 2400000, 2450000, 2500000, 2550000, 2600000, 2650000, 2700000, 2750000,
77 2800000, 2850000, 2900000, 2950000, 3000000, 3000000, 3000000, 3000000,
78};
79
80static const unsigned int BUCK3_table[] = {
e54f19bf 81 0, 25000, 50000, 75000, 100000, 125000, 150000, 175000,
9f79e9db
HZ
82 200000, 225000, 250000, 275000, 300000, 325000, 350000, 375000,
83 400000, 425000, 450000, 475000, 500000, 525000, 550000, 575000,
84 600000, 625000, 650000, 675000, 700000, 725000, 750000, 775000,
85 800000, 825000, 850000, 875000, 900000, 925000, 950000, 975000,
86 1000000, 1025000, 1050000, 1075000, 1100000, 1125000, 1150000, 1175000,
87 1200000, 1225000, 1250000, 1275000, 1300000, 1325000, 1350000, 1375000,
88 1400000, 1425000, 1450000, 1475000, 1500000, 1500000, 1500000, 1500000,
89};
90
91static const unsigned int BUCK3_suspend_table[] = {
e54f19bf 92 0, 25000, 50000, 75000, 100000, 125000, 150000, 175000,
9f79e9db
HZ
93 200000, 225000, 250000, 275000, 300000, 325000, 350000, 375000,
94 400000, 425000, 450000, 475000, 500000, 525000, 550000, 575000,
95 600000, 625000, 650000, 675000, 700000, 725000, 750000, 775000,
96 800000, 825000, 850000, 875000, 900000, 925000, 950000, 975000,
97 1000000, 1025000, 1050000, 1075000, 1100000, 1125000, 1150000, 1175000,
98 1200000, 1225000, 1250000, 1275000, 1300000, 1325000, 1350000, 1375000,
99 1400000, 1425000, 1450000, 1475000, 1500000, 1500000, 1500000, 1500000,
100};
101
102static const unsigned int LDO1_table[] = {
103 1800000, 1200000, 2800000, 0,
104};
105
106static const unsigned int LDO1_suspend_table[] = {
107 1800000, 1200000, 0, 0,
108};
109
110static const unsigned int LDO2_table[] = {
111 1800000, 1850000, 1900000, 2700000, 2750000, 2800000, 2850000, 3300000,
112};
113
114static const unsigned int LDO2_suspend_table[] = {
115 1800000, 1850000, 1900000, 2700000, 2750000, 2800000, 2850000, 2900000,
116};
117
118static const unsigned int LDO3_table[] = {
119 1800000, 1850000, 1900000, 2700000, 2750000, 2800000, 2850000, 3300000,
120};
121
122static const unsigned int LDO3_suspend_table[] = {
123 1800000, 1850000, 1900000, 2700000, 2750000, 2800000, 2850000, 2900000,
124};
125
126static const unsigned int LDO4_table[] = {
127 1800000, 1850000, 1900000, 2700000, 2750000, 2800000, 2900000, 3300000,
128};
129
130static const unsigned int LDO4_suspend_table[] = {
131 1800000, 1850000, 1900000, 2700000, 2750000, 2800000, 2900000, 2900000,
132};
133
134static const unsigned int LDO5_table[] = {
135 2900000, 3000000, 3100000, 3300000,
136};
137
138static const unsigned int LDO5_suspend_table[] = {
139 2900000, 0, 0, 0,
140};
141
142static const unsigned int LDO6_table[] = {
143 1800000, 1850000, 2600000, 2650000, 2700000, 2750000, 2800000, 3300000,
144};
145
146static const unsigned int LDO6_suspend_table[] = {
147 1800000, 1850000, 2600000, 2650000, 2700000, 2750000, 2800000, 2900000,
148};
149
150static const unsigned int LDO7_table[] = {
151 1800000, 1850000, 1900000, 2700000, 2750000, 2800000, 2850000, 2900000,
152};
153
154static const unsigned int LDO7_suspend_table[] = {
155 1800000, 1850000, 1900000, 2700000, 2750000, 2800000, 2850000, 2900000,
156};
157
158static const unsigned int LDO8_table[] = {
159 1800000, 1850000, 1900000, 2700000, 2750000, 2800000, 2850000, 2900000,
160};
161
162static const unsigned int LDO8_suspend_table[] = {
163 1800000, 1850000, 1900000, 2700000, 2750000, 2800000, 2850000, 2900000,
164};
165
166static const unsigned int LDO9_table[] = {
167 1800000, 1850000, 1900000, 2700000, 2750000, 2800000, 2850000, 3300000,
168};
169
170static const unsigned int LDO9_suspend_table[] = {
171 1800000, 1850000, 1900000, 2700000, 2750000, 2800000, 2850000, 2900000,
172};
173
174static const unsigned int LDO10_table[] = {
175 1800000, 1850000, 1900000, 2700000, 2750000, 2800000, 2850000, 3300000,
176 1200000, 1200000, 1200000, 1200000, 1200000, 1200000, 1200000, 1200000,
177};
178
179static const unsigned int LDO10_suspend_table[] = {
180 1800000, 1850000, 1900000, 2700000, 2750000, 2800000, 2850000, 2900000,
181 1200000, 1200000, 1200000, 1200000, 1200000, 1200000, 1200000, 1200000,
182};
183
184static const unsigned int LDO12_table[] = {
185 1800000, 1900000, 2700000, 2800000, 2900000, 3000000, 3100000, 3300000,
186 1200000, 1200000, 1200000, 1200000, 1200000, 1200000, 1200000, 1200000,
187};
188
189static const unsigned int LDO12_suspend_table[] = {
190 1800000, 1900000, 2700000, 2800000, 2900000, 2900000, 2900000, 2900000,
191 1200000, 1200000, 1200000, 1200000, 1200000, 1200000, 1200000, 1200000,
192};
193
194static const unsigned int LDO13_table[] = {
3380643b 195 1200000, 1300000, 1800000, 2000000, 2500000, 2800000, 3000000, 0,
9f79e9db
HZ
196};
197
198static const unsigned int LDO13_suspend_table[] = {
199 0,
200};
201
202static const unsigned int LDO14_table[] = {
203 1800000, 1850000, 2700000, 2750000, 2800000, 2850000, 2900000, 3300000,
204};
205
206static const unsigned int LDO14_suspend_table[] = {
207 1800000, 1850000, 2700000, 2750000, 2800000, 2850000, 2900000, 2900000,
208};
be0e2d3e
HZ
209
210static int pm8607_list_voltage(struct regulator_dev *rdev, unsigned index)
211{
212 struct pm8607_regulator_info *info = rdev_get_drvdata(rdev);
be0e2d3e
HZ
213 int ret = -EINVAL;
214
53b6949e 215 if (info->vol_table && (index < rdev->desc->n_voltages)) {
9f79e9db 216 ret = info->vol_table[index];
be0e2d3e
HZ
217 if (info->slope_double)
218 ret <<= 1;
be0e2d3e
HZ
219 }
220 return ret;
221}
222
be0e2d3e 223static struct regulator_ops pm8607_regulator_ops = {
d3d7bccc 224 .list_voltage = pm8607_list_voltage,
c6f0a0ef 225 .set_voltage_sel = regulator_set_voltage_sel_regmap,
c006b21f 226 .get_voltage_sel = regulator_get_voltage_sel_regmap,
ef26e0db
AL
227 .enable = regulator_enable_regmap,
228 .disable = regulator_disable_regmap,
229 .is_enabled = regulator_is_enabled_regmap,
be0e2d3e
HZ
230};
231
e7a7810a 232static struct regulator_ops pm8606_preg_ops = {
318c658b
AL
233 .enable = regulator_enable_regmap,
234 .disable = regulator_disable_regmap,
235 .is_enabled = regulator_is_enabled_regmap,
e7a7810a
JZ
236};
237
238#define PM8606_PREG(ereg, ebit) \
239{ \
240 .desc = { \
241 .name = "PREG", \
242 .ops = &pm8606_preg_ops, \
243 .type = REGULATOR_CURRENT, \
244 .id = PM8606_ID_PREG, \
245 .owner = THIS_MODULE, \
246 .enable_reg = PM8606_##ereg, \
247 .enable_mask = (ebit), \
318c658b 248 .enable_is_inverted = true, \
e7a7810a
JZ
249 }, \
250}
251
53b6949e 252#define PM8607_DVC(vreg, ureg, ubit, ereg, ebit) \
be0e2d3e
HZ
253{ \
254 .desc = { \
9f79e9db 255 .name = #vreg, \
be0e2d3e
HZ
256 .ops = &pm8607_regulator_ops, \
257 .type = REGULATOR_VOLTAGE, \
9f79e9db 258 .id = PM8607_ID_##vreg, \
be0e2d3e 259 .owner = THIS_MODULE, \
53b6949e 260 .n_voltages = ARRAY_SIZE(vreg##_table), \
c006b21f
AL
261 .vsel_reg = PM8607_##vreg, \
262 .vsel_mask = ARRAY_SIZE(vreg##_table) - 1, \
c6f0a0ef
AL
263 .apply_reg = PM8607_##ureg, \
264 .apply_bit = (ubit), \
ef26e0db
AL
265 .enable_reg = PM8607_##ereg, \
266 .enable_mask = 1 << (ebit), \
be0e2d3e 267 }, \
be0e2d3e 268 .slope_double = (0), \
9f79e9db
HZ
269 .vol_table = (unsigned int *)&vreg##_table, \
270 .vol_suspend = (unsigned int *)&vreg##_suspend_table, \
be0e2d3e
HZ
271}
272
53b6949e 273#define PM8607_LDO(_id, vreg, shift, ereg, ebit) \
be0e2d3e
HZ
274{ \
275 .desc = { \
276 .name = "LDO" #_id, \
277 .ops = &pm8607_regulator_ops, \
278 .type = REGULATOR_VOLTAGE, \
279 .id = PM8607_ID_LDO##_id, \
280 .owner = THIS_MODULE, \
53b6949e 281 .n_voltages = ARRAY_SIZE(LDO##_id##_table), \
c006b21f
AL
282 .vsel_reg = PM8607_##vreg, \
283 .vsel_mask = (ARRAY_SIZE(LDO##_id##_table) - 1) << (shift), \
ef26e0db
AL
284 .enable_reg = PM8607_##ereg, \
285 .enable_mask = 1 << (ebit), \
be0e2d3e 286 }, \
be0e2d3e 287 .slope_double = (0), \
9f79e9db
HZ
288 .vol_table = (unsigned int *)&LDO##_id##_table, \
289 .vol_suspend = (unsigned int *)&LDO##_id##_suspend_table, \
be0e2d3e
HZ
290}
291
292static struct pm8607_regulator_info pm8607_regulator_info[] = {
c6f0a0ef
AL
293 PM8607_DVC(BUCK1, GO, BIT(0), SUPPLIES_EN11, 0),
294 PM8607_DVC(BUCK2, GO, BIT(1), SUPPLIES_EN11, 1),
295 PM8607_DVC(BUCK3, GO, BIT(2), SUPPLIES_EN11, 2),
53b6949e
AL
296
297 PM8607_LDO(1, LDO1, 0, SUPPLIES_EN11, 3),
298 PM8607_LDO(2, LDO2, 0, SUPPLIES_EN11, 4),
299 PM8607_LDO(3, LDO3, 0, SUPPLIES_EN11, 5),
300 PM8607_LDO(4, LDO4, 0, SUPPLIES_EN11, 6),
301 PM8607_LDO(5, LDO5, 0, SUPPLIES_EN11, 7),
302 PM8607_LDO(6, LDO6, 0, SUPPLIES_EN12, 0),
303 PM8607_LDO(7, LDO7, 0, SUPPLIES_EN12, 1),
304 PM8607_LDO(8, LDO8, 0, SUPPLIES_EN12, 2),
305 PM8607_LDO(9, LDO9, 0, SUPPLIES_EN12, 3),
306 PM8607_LDO(10, LDO10, 0, SUPPLIES_EN12, 4),
307 PM8607_LDO(12, LDO12, 0, SUPPLIES_EN12, 5),
308 PM8607_LDO(13, VIBRATOR_SET, 1, VIBRATOR_SET, 0),
309 PM8607_LDO(14, LDO14, 0, SUPPLIES_EN12, 6),
ff13e9e2 310};
e7a7810a 311
ff13e9e2 312static struct pm8607_regulator_info pm8606_regulator_info[] = {
e7a7810a 313 PM8606_PREG(PREREGULATORB, 5),
be0e2d3e
HZ
314};
315
2e57d567
HZ
316#ifdef CONFIG_OF
317static int pm8607_regulator_dt_init(struct platform_device *pdev,
318 struct pm8607_regulator_info *info,
319 struct regulator_config *config)
320{
321 struct device_node *nproot, *np;
b8b27a44 322 nproot = pdev->dev.parent->of_node;
2e57d567
HZ
323 if (!nproot)
324 return -ENODEV;
ca1e3f33 325 nproot = of_get_child_by_name(nproot, "regulators");
2e57d567
HZ
326 if (!nproot) {
327 dev_err(&pdev->dev, "failed to find regulators node\n");
328 return -ENODEV;
329 }
330 for_each_child_of_node(nproot, np) {
331 if (!of_node_cmp(np->name, info->desc.name)) {
332 config->init_data =
072e78b1
JMC
333 of_get_regulator_init_data(&pdev->dev, np,
334 &info->desc);
2e57d567
HZ
335 config->of_node = np;
336 break;
337 }
338 }
c92f5dd2 339 of_node_put(nproot);
2e57d567
HZ
340 return 0;
341}
342#else
343#define pm8607_regulator_dt_init(x, y, z) (-1)
344#endif
345
a5023574 346static int pm8607_regulator_probe(struct platform_device *pdev)
be0e2d3e 347{
22aad001
HZ
348 struct pm860x_chip *chip = dev_get_drvdata(pdev->dev.parent);
349 struct pm8607_regulator_info *info = NULL;
dff91d0b 350 struct regulator_init_data *pdata = dev_get_platdata(&pdev->dev);
c172708d 351 struct regulator_config config = { };
586e1a17 352 struct resource *res;
be0e2d3e
HZ
353 int i;
354
02367029 355 res = platform_get_resource(pdev, IORESOURCE_REG, 0);
ff13e9e2
HZ
356 if (res) {
357 /* There're resources in 88PM8607 regulator driver */
358 for (i = 0; i < ARRAY_SIZE(pm8607_regulator_info); i++) {
359 info = &pm8607_regulator_info[i];
360 if (info->desc.vsel_reg == res->start)
361 break;
362 }
363 if (i == ARRAY_SIZE(pm8607_regulator_info)) {
364 dev_err(&pdev->dev, "Failed to find regulator %llu\n",
365 (unsigned long long)res->start);
366 return -EINVAL;
367 }
368 } else {
369 /* There's no resource in 88PM8606 PREG regulator driver */
370 info = &pm8606_regulator_info[0];
371 /* i is used to check regulator ID */
372 i = -1;
be0e2d3e 373 }
53dbab7a 374 info->i2c = (chip->id == CHIP_PM8607) ? chip->client : chip->companion;
e7a7810a
JZ
375 info->i2c_8606 = (chip->id == CHIP_PM8607) ? chip->companion :
376 chip->client;
be0e2d3e
HZ
377 info->chip = chip;
378
22aad001 379 /* check DVC ramp slope double */
586e1a17
HZ
380 if ((i == PM8607_ID_BUCK3) && info->chip->buck3_double)
381 info->slope_double = 1;
22aad001 382
c172708d 383 config.dev = &pdev->dev;
c172708d
MB
384 config.driver_data = info;
385
2e57d567
HZ
386 if (pm8607_regulator_dt_init(pdev, info, &config))
387 if (pdata)
388 config.init_data = pdata;
389
ef26e0db
AL
390 if (chip->id == CHIP_PM8607)
391 config.regmap = chip->regmap;
392 else
393 config.regmap = chip->regmap_companion;
394
bcb5fe44
AL
395 info->regulator = devm_regulator_register(&pdev->dev, &info->desc,
396 &config);
be0e2d3e
HZ
397 if (IS_ERR(info->regulator)) {
398 dev_err(&pdev->dev, "failed to register regulator %s\n",
399 info->desc.name);
400 return PTR_ERR(info->regulator);
401 }
402
be0e2d3e
HZ
403 platform_set_drvdata(pdev, info);
404 return 0;
405}
406
0cfeddbd 407static const struct platform_device_id pm8607_regulator_driver_ids[] = {
e7a7810a
JZ
408 {
409 .name = "88pm860x-regulator",
410 .driver_data = 0,
411 }, {
412 .name = "88pm860x-preg",
413 .driver_data = 0,
414 },
415 { },
416};
417MODULE_DEVICE_TABLE(platform, pm8607_regulator_driver_ids);
418
192bbb95
HZ
419static struct platform_driver pm8607_regulator_driver = {
420 .driver = {
421 .name = "88pm860x-regulator",
192bbb95
HZ
422 },
423 .probe = pm8607_regulator_probe,
e7a7810a 424 .id_table = pm8607_regulator_driver_ids,
be0e2d3e
HZ
425};
426
427static int __init pm8607_regulator_init(void)
428{
192bbb95 429 return platform_driver_register(&pm8607_regulator_driver);
be0e2d3e
HZ
430}
431subsys_initcall(pm8607_regulator_init);
432
433static void __exit pm8607_regulator_exit(void)
434{
192bbb95 435 platform_driver_unregister(&pm8607_regulator_driver);
be0e2d3e
HZ
436}
437module_exit(pm8607_regulator_exit);
438
439MODULE_LICENSE("GPL");
440MODULE_AUTHOR("Haojian Zhuang <haojian.zhuang@marvell.com>");
441MODULE_DESCRIPTION("Regulator Driver for Marvell 88PM8607 PMIC");
442MODULE_ALIAS("platform:88pm8607-regulator");
This page took 0.40509 seconds and 5 git commands to generate.