blob: 3ca1c98d6f3a68e1d49467ec0dcec9c8daed9d33 [file] [log] [blame]
Mike Rapoport49610232010-07-27 14:03:01 +03001/*
2 * Regulator driver for TI TPS6586x
3 *
4 * Copyright (C) 2010 Compulab Ltd.
5 * Author: Mike Rapoport <mike@compulab.co.il>
6 *
7 * Based on da903x
8 * Copyright (C) 2006-2008 Marvell International Ltd.
9 * Copyright (C) 2008 Compulab Ltd.
10 *
11 * This program is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License version 2 as
13 * published by the Free Software Foundation.
14 */
15
Mike Rapoport49610232010-07-27 14:03:01 +030016#include <linux/kernel.h>
Paul Gortmaker65602c32011-07-17 16:28:23 -040017#include <linux/module.h>
Mike Rapoport49610232010-07-27 14:03:01 +030018#include <linux/init.h>
19#include <linux/err.h>
20#include <linux/slab.h>
21#include <linux/platform_device.h>
22#include <linux/regulator/driver.h>
23#include <linux/regulator/machine.h>
24#include <linux/mfd/tps6586x.h>
25
26/* supply control and voltage setting */
27#define TPS6586X_SUPPLYENA 0x10
28#define TPS6586X_SUPPLYENB 0x11
29#define TPS6586X_SUPPLYENC 0x12
30#define TPS6586X_SUPPLYEND 0x13
31#define TPS6586X_SUPPLYENE 0x14
32#define TPS6586X_VCC1 0x20
33#define TPS6586X_VCC2 0x21
34#define TPS6586X_SM1V1 0x23
35#define TPS6586X_SM1V2 0x24
36#define TPS6586X_SM1SL 0x25
37#define TPS6586X_SM0V1 0x26
38#define TPS6586X_SM0V2 0x27
39#define TPS6586X_SM0SL 0x28
40#define TPS6586X_LDO2AV1 0x29
41#define TPS6586X_LDO2AV2 0x2A
42#define TPS6586X_LDO2BV1 0x2F
43#define TPS6586X_LDO2BV2 0x30
44#define TPS6586X_LDO4V1 0x32
45#define TPS6586X_LDO4V2 0x33
46
47/* converter settings */
48#define TPS6586X_SUPPLYV1 0x41
49#define TPS6586X_SUPPLYV2 0x42
50#define TPS6586X_SUPPLYV3 0x43
51#define TPS6586X_SUPPLYV4 0x44
52#define TPS6586X_SUPPLYV5 0x45
53#define TPS6586X_SUPPLYV6 0x46
54#define TPS6586X_SMODE1 0x47
55#define TPS6586X_SMODE2 0x48
56
57struct tps6586x_regulator {
58 struct regulator_desc desc;
59
60 int volt_reg;
61 int volt_shift;
62 int volt_nbits;
63 int enable_bit[2];
64 int enable_reg[2];
65
66 int *voltages;
67
68 /* for DVM regulators */
69 int go_reg;
70 int go_bit;
71};
72
73static inline struct device *to_tps6586x_dev(struct regulator_dev *rdev)
74{
75 return rdev_get_dev(rdev)->parent->parent;
76}
77
78static int tps6586x_ldo_list_voltage(struct regulator_dev *rdev,
79 unsigned selector)
80{
81 struct tps6586x_regulator *info = rdev_get_drvdata(rdev);
82
Gary King4cc2e392010-07-30 22:58:58 +030083 return info->voltages[selector] * 1000;
Mike Rapoport49610232010-07-27 14:03:01 +030084}
85
86
Axel Lineed06512012-03-24 09:42:26 +080087static int tps6586x_set_voltage_sel(struct regulator_dev *rdev,
88 unsigned selector)
Mike Rapoport49610232010-07-27 14:03:01 +030089{
90 struct tps6586x_regulator *ri = rdev_get_drvdata(rdev);
91 struct device *parent = to_tps6586x_dev(rdev);
Axel Lineed06512012-03-24 09:42:26 +080092 int ret, val, rid = rdev_get_id(rdev);
93 uint8_t mask;
Mike Rapoport49610232010-07-27 14:03:01 +030094
Axel Lineed06512012-03-24 09:42:26 +080095 val = selector << ri->volt_shift;
96 mask = ((1 << ri->volt_nbits) - 1) << ri->volt_shift;
97
98 ret = tps6586x_update(parent, ri->volt_reg, val, mask);
99 if (ret)
100 return ret;
101
102 /* Update go bit for DVM regulators */
103 switch (rid) {
104 case TPS6586X_ID_LDO_2:
105 case TPS6586X_ID_LDO_4:
106 case TPS6586X_ID_SM_0:
107 case TPS6586X_ID_SM_1:
108 ret = tps6586x_set_bits(parent, ri->go_reg, 1 << ri->go_bit);
109 break;
110 }
111 return ret;
Mike Rapoport49610232010-07-27 14:03:01 +0300112}
113
Axel Lin44a7cda2012-03-24 09:38:30 +0800114static int tps6586x_get_voltage_sel(struct regulator_dev *rdev)
Mike Rapoport49610232010-07-27 14:03:01 +0300115{
116 struct tps6586x_regulator *ri = rdev_get_drvdata(rdev);
117 struct device *parent = to_tps6586x_dev(rdev);
118 uint8_t val, mask;
119 int ret;
120
121 ret = tps6586x_read(parent, ri->volt_reg, &val);
122 if (ret)
123 return ret;
124
125 mask = ((1 << ri->volt_nbits) - 1) << ri->volt_shift;
126 val = (val & mask) >> ri->volt_shift;
127
Axel Lin327531b2010-08-22 22:38:15 +0800128 if (val >= ri->desc.n_voltages)
Mike Rapoport49610232010-07-27 14:03:01 +0300129 BUG();
130
Axel Lin44a7cda2012-03-24 09:38:30 +0800131 return val;
Mike Rapoport49610232010-07-27 14:03:01 +0300132}
133
Mike Rapoport49610232010-07-27 14:03:01 +0300134static int tps6586x_regulator_enable(struct regulator_dev *rdev)
135{
136 struct tps6586x_regulator *ri = rdev_get_drvdata(rdev);
137 struct device *parent = to_tps6586x_dev(rdev);
138
139 return tps6586x_set_bits(parent, ri->enable_reg[0],
140 1 << ri->enable_bit[0]);
141}
142
143static int tps6586x_regulator_disable(struct regulator_dev *rdev)
144{
145 struct tps6586x_regulator *ri = rdev_get_drvdata(rdev);
146 struct device *parent = to_tps6586x_dev(rdev);
147
148 return tps6586x_clr_bits(parent, ri->enable_reg[0],
149 1 << ri->enable_bit[0]);
150}
151
152static int tps6586x_regulator_is_enabled(struct regulator_dev *rdev)
153{
154 struct tps6586x_regulator *ri = rdev_get_drvdata(rdev);
155 struct device *parent = to_tps6586x_dev(rdev);
156 uint8_t reg_val;
157 int ret;
158
159 ret = tps6586x_read(parent, ri->enable_reg[0], &reg_val);
160 if (ret)
161 return ret;
162
163 return !!(reg_val & (1 << ri->enable_bit[0]));
164}
165
166static struct regulator_ops tps6586x_regulator_ldo_ops = {
167 .list_voltage = tps6586x_ldo_list_voltage,
Axel Lin44a7cda2012-03-24 09:38:30 +0800168 .get_voltage_sel = tps6586x_get_voltage_sel,
Axel Lineed06512012-03-24 09:42:26 +0800169 .set_voltage_sel = tps6586x_set_voltage_sel,
Mike Rapoport49610232010-07-27 14:03:01 +0300170
171 .is_enabled = tps6586x_regulator_is_enabled,
172 .enable = tps6586x_regulator_enable,
173 .disable = tps6586x_regulator_disable,
174};
175
176static struct regulator_ops tps6586x_regulator_dvm_ops = {
177 .list_voltage = tps6586x_ldo_list_voltage,
Axel Lin44a7cda2012-03-24 09:38:30 +0800178 .get_voltage_sel = tps6586x_get_voltage_sel,
Axel Lineed06512012-03-24 09:42:26 +0800179 .set_voltage_sel = tps6586x_set_voltage_sel,
Mike Rapoport49610232010-07-27 14:03:01 +0300180
181 .is_enabled = tps6586x_regulator_is_enabled,
182 .enable = tps6586x_regulator_enable,
183 .disable = tps6586x_regulator_disable,
184};
185
186static int tps6586x_ldo_voltages[] = {
187 1250, 1500, 1800, 2500, 2700, 2850, 3100, 3300,
188};
189
190static int tps6586x_ldo4_voltages[] = {
191 1700, 1725, 1750, 1775, 1800, 1825, 1850, 1875,
192 1900, 1925, 1950, 1975, 2000, 2025, 2050, 2075,
193 2100, 2125, 2150, 2175, 2200, 2225, 2250, 2275,
194 2300, 2325, 2350, 2375, 2400, 2425, 2450, 2475,
195};
196
Gary King4cc2e392010-07-30 22:58:58 +0300197static int tps6586x_sm2_voltages[] = {
198 3000, 3050, 3100, 3150, 3200, 3250, 3300, 3350,
199 3400, 3450, 3500, 3550, 3600, 3650, 3700, 3750,
200 3800, 3850, 3900, 3950, 4000, 4050, 4100, 4150,
201 4200, 4250, 4300, 4350, 4400, 4450, 4500, 4550,
202};
203
Mike Rapoport49610232010-07-27 14:03:01 +0300204static int tps6586x_dvm_voltages[] = {
205 725, 750, 775, 800, 825, 850, 875, 900,
206 925, 950, 975, 1000, 1025, 1050, 1075, 1100,
207 1125, 1150, 1175, 1200, 1225, 1250, 1275, 1300,
208 1325, 1350, 1375, 1400, 1425, 1450, 1475, 1500,
209};
210
211#define TPS6586X_REGULATOR(_id, vdata, _ops, vreg, shift, nbits, \
Danny Huang64db6572010-12-01 13:37:29 -0700212 ereg0, ebit0, ereg1, ebit1) \
Mike Rapoport49610232010-07-27 14:03:01 +0300213 .desc = { \
214 .name = "REG-" #_id, \
215 .ops = &tps6586x_regulator_##_ops, \
216 .type = REGULATOR_VOLTAGE, \
217 .id = TPS6586X_ID_##_id, \
218 .n_voltages = ARRAY_SIZE(tps6586x_##vdata##_voltages), \
219 .owner = THIS_MODULE, \
220 }, \
221 .volt_reg = TPS6586X_##vreg, \
222 .volt_shift = (shift), \
223 .volt_nbits = (nbits), \
224 .enable_reg[0] = TPS6586X_SUPPLY##ereg0, \
225 .enable_bit[0] = (ebit0), \
226 .enable_reg[1] = TPS6586X_SUPPLY##ereg1, \
227 .enable_bit[1] = (ebit1), \
Danny Huang64db6572010-12-01 13:37:29 -0700228 .voltages = tps6586x_##vdata##_voltages,
229
230#define TPS6586X_REGULATOR_DVM_GOREG(goreg, gobit) \
231 .go_reg = TPS6586X_##goreg, \
232 .go_bit = (gobit),
Mike Rapoport49610232010-07-27 14:03:01 +0300233
234#define TPS6586X_LDO(_id, vdata, vreg, shift, nbits, \
235 ereg0, ebit0, ereg1, ebit1) \
Danny Huang64db6572010-12-01 13:37:29 -0700236{ \
Mike Rapoport49610232010-07-27 14:03:01 +0300237 TPS6586X_REGULATOR(_id, vdata, ldo_ops, vreg, shift, nbits, \
Danny Huang64db6572010-12-01 13:37:29 -0700238 ereg0, ebit0, ereg1, ebit1) \
239}
Mike Rapoport49610232010-07-27 14:03:01 +0300240
241#define TPS6586X_DVM(_id, vdata, vreg, shift, nbits, \
242 ereg0, ebit0, ereg1, ebit1, goreg, gobit) \
Danny Huang64db6572010-12-01 13:37:29 -0700243{ \
Mike Rapoport49610232010-07-27 14:03:01 +0300244 TPS6586X_REGULATOR(_id, vdata, dvm_ops, vreg, shift, nbits, \
Danny Huang64db6572010-12-01 13:37:29 -0700245 ereg0, ebit0, ereg1, ebit1) \
246 TPS6586X_REGULATOR_DVM_GOREG(goreg, gobit) \
247}
Mike Rapoport49610232010-07-27 14:03:01 +0300248
249static struct tps6586x_regulator tps6586x_regulator[] = {
250 TPS6586X_LDO(LDO_0, ldo, SUPPLYV1, 5, 3, ENC, 0, END, 0),
251 TPS6586X_LDO(LDO_3, ldo, SUPPLYV4, 0, 3, ENC, 2, END, 2),
252 TPS6586X_LDO(LDO_5, ldo, SUPPLYV6, 0, 3, ENE, 6, ENE, 6),
253 TPS6586X_LDO(LDO_6, ldo, SUPPLYV3, 0, 3, ENC, 4, END, 4),
254 TPS6586X_LDO(LDO_7, ldo, SUPPLYV3, 3, 3, ENC, 5, END, 5),
Danny Huang1b39ed02010-12-01 13:37:31 -0700255 TPS6586X_LDO(LDO_8, ldo, SUPPLYV2, 5, 3, ENC, 6, END, 6),
Mike Rapoport49610232010-07-27 14:03:01 +0300256 TPS6586X_LDO(LDO_9, ldo, SUPPLYV6, 3, 3, ENE, 7, ENE, 7),
Danny Huang1b39ed02010-12-01 13:37:31 -0700257 TPS6586X_LDO(LDO_RTC, ldo, SUPPLYV4, 3, 3, V4, 7, V4, 7),
Mike Rapoport49610232010-07-27 14:03:01 +0300258 TPS6586X_LDO(LDO_1, dvm, SUPPLYV1, 0, 5, ENC, 1, END, 1),
Danny Huang1b39ed02010-12-01 13:37:31 -0700259 TPS6586X_LDO(SM_2, sm2, SUPPLYV2, 0, 5, ENC, 7, END, 7),
Mike Rapoport49610232010-07-27 14:03:01 +0300260
261 TPS6586X_DVM(LDO_2, dvm, LDO2BV1, 0, 5, ENA, 3, ENB, 3, VCC2, 6),
262 TPS6586X_DVM(LDO_4, ldo4, LDO4V1, 0, 5, ENC, 3, END, 3, VCC1, 6),
263 TPS6586X_DVM(SM_0, dvm, SM0V1, 0, 5, ENA, 1, ENB, 1, VCC1, 2),
264 TPS6586X_DVM(SM_1, dvm, SM1V1, 0, 5, ENA, 0, ENB, 0, VCC1, 0),
265};
266
267/*
268 * TPS6586X has 2 enable bits that are OR'ed to determine the actual
269 * regulator state. Clearing one of this bits allows switching
270 * regulator on and of with single register write.
271 */
272static inline int tps6586x_regulator_preinit(struct device *parent,
273 struct tps6586x_regulator *ri)
274{
275 uint8_t val1, val2;
276 int ret;
277
Danny Huang1dbcf352010-12-01 13:37:30 -0700278 if (ri->enable_reg[0] == ri->enable_reg[1] &&
279 ri->enable_bit[0] == ri->enable_bit[1])
280 return 0;
281
Mike Rapoport49610232010-07-27 14:03:01 +0300282 ret = tps6586x_read(parent, ri->enable_reg[0], &val1);
283 if (ret)
284 return ret;
285
286 ret = tps6586x_read(parent, ri->enable_reg[1], &val2);
287 if (ret)
288 return ret;
289
Danny Huang4f5867072010-12-01 13:37:28 -0700290 if (!(val2 & (1 << ri->enable_bit[1])))
Mike Rapoport49610232010-07-27 14:03:01 +0300291 return 0;
292
293 /*
294 * The regulator is on, but it's enabled with the bit we don't
295 * want to use, so we switch the enable bits
296 */
Danny Huang4f5867072010-12-01 13:37:28 -0700297 if (!(val1 & (1 << ri->enable_bit[0]))) {
Mike Rapoport49610232010-07-27 14:03:01 +0300298 ret = tps6586x_set_bits(parent, ri->enable_reg[0],
299 1 << ri->enable_bit[0]);
300 if (ret)
301 return ret;
302 }
303
304 return tps6586x_clr_bits(parent, ri->enable_reg[1],
305 1 << ri->enable_bit[1]);
306}
307
Xin Xie500c5242011-08-09 18:47:50 +0800308static int tps6586x_regulator_set_slew_rate(struct platform_device *pdev)
309{
310 struct device *parent = pdev->dev.parent;
311 struct regulator_init_data *p = pdev->dev.platform_data;
312 struct tps6586x_settings *setting = p->driver_data;
313 uint8_t reg;
314
315 if (setting == NULL)
316 return 0;
317
318 if (!(setting->slew_rate & TPS6586X_SLEW_RATE_SET))
319 return 0;
320
321 /* only SM0 and SM1 can have the slew rate settings */
322 switch (pdev->id) {
323 case TPS6586X_ID_SM_0:
324 reg = TPS6586X_SM0SL;
325 break;
326 case TPS6586X_ID_SM_1:
327 reg = TPS6586X_SM1SL;
328 break;
329 default:
330 dev_warn(&pdev->dev, "Only SM0/SM1 can set slew rate\n");
331 return -EINVAL;
332 }
333
334 return tps6586x_write(parent, reg,
335 setting->slew_rate & TPS6586X_SLEW_RATE_MASK);
336}
337
Mike Rapoport49610232010-07-27 14:03:01 +0300338static inline struct tps6586x_regulator *find_regulator_info(int id)
339{
340 struct tps6586x_regulator *ri;
341 int i;
342
343 for (i = 0; i < ARRAY_SIZE(tps6586x_regulator); i++) {
344 ri = &tps6586x_regulator[i];
345 if (ri->desc.id == id)
346 return ri;
347 }
348 return NULL;
349}
350
351static int __devinit tps6586x_regulator_probe(struct platform_device *pdev)
352{
353 struct tps6586x_regulator *ri = NULL;
354 struct regulator_dev *rdev;
355 int id = pdev->id;
356 int err;
357
Thierry Reding394ee3d2012-03-08 15:51:24 +0100358 dev_dbg(&pdev->dev, "Probing regulator %d\n", id);
Mike Rapoport49610232010-07-27 14:03:01 +0300359
360 ri = find_regulator_info(id);
361 if (ri == NULL) {
362 dev_err(&pdev->dev, "invalid regulator ID specified\n");
363 return -EINVAL;
364 }
365
366 err = tps6586x_regulator_preinit(pdev->dev.parent, ri);
367 if (err)
368 return err;
369
370 rdev = regulator_register(&ri->desc, &pdev->dev,
Rajendra Nayak2c043bc2011-11-18 16:47:19 +0530371 pdev->dev.platform_data, ri, NULL);
Mike Rapoport49610232010-07-27 14:03:01 +0300372 if (IS_ERR(rdev)) {
373 dev_err(&pdev->dev, "failed to register regulator %s\n",
374 ri->desc.name);
375 return PTR_ERR(rdev);
376 }
377
Axel Line7973c32010-08-09 15:58:06 +0800378 platform_set_drvdata(pdev, rdev);
Mike Rapoport49610232010-07-27 14:03:01 +0300379
Xin Xie500c5242011-08-09 18:47:50 +0800380 return tps6586x_regulator_set_slew_rate(pdev);
Mike Rapoport49610232010-07-27 14:03:01 +0300381}
382
383static int __devexit tps6586x_regulator_remove(struct platform_device *pdev)
384{
Axel Line7973c32010-08-09 15:58:06 +0800385 struct regulator_dev *rdev = platform_get_drvdata(pdev);
386
387 regulator_unregister(rdev);
Mike Rapoport49610232010-07-27 14:03:01 +0300388 return 0;
389}
390
391static struct platform_driver tps6586x_regulator_driver = {
392 .driver = {
393 .name = "tps6586x-regulator",
394 .owner = THIS_MODULE,
395 },
396 .probe = tps6586x_regulator_probe,
397 .remove = __devexit_p(tps6586x_regulator_remove),
398};
399
400static int __init tps6586x_regulator_init(void)
401{
402 return platform_driver_register(&tps6586x_regulator_driver);
403}
404subsys_initcall(tps6586x_regulator_init);
405
406static void __exit tps6586x_regulator_exit(void)
407{
408 platform_driver_unregister(&tps6586x_regulator_driver);
409}
410module_exit(tps6586x_regulator_exit);
411
412MODULE_LICENSE("GPL");
413MODULE_AUTHOR("Mike Rapoport <mike@compulab.co.il>");
414MODULE_DESCRIPTION("Regulator Driver for TI TPS6586X PMIC");
415MODULE_ALIAS("platform:tps6586x-regulator");