dt-bindings: regulator: add DT bindings for max77650
[linux-2.6-block.git] / drivers / regulator / max77650-regulator.c
CommitLineData
bcc61f1c
BG
1// SPDX-License-Identifier: GPL-2.0
2//
3// Copyright (C) 2018 BayLibre SAS
4// Author: Bartosz Golaszewski <bgolaszewski@baylibre.com>
5//
6// Regulator driver for MAXIM 77650/77651 charger/power-supply.
7
8#include <linux/i2c.h>
9#include <linux/mfd/max77650.h>
10#include <linux/module.h>
11#include <linux/platform_device.h>
12#include <linux/regmap.h>
13#include <linux/regulator/driver.h>
14
15#define MAX77650_REGULATOR_EN_CTRL_MASK GENMASK(3, 0)
16#define MAX77650_REGULATOR_EN_CTRL_BITS(_reg) \
17 ((_reg) & MAX77650_REGULATOR_EN_CTRL_MASK)
18#define MAX77650_REGULATOR_ENABLED GENMASK(2, 1)
19#define MAX77650_REGULATOR_DISABLED BIT(2)
20
21#define MAX77650_REGULATOR_V_LDO_MASK GENMASK(6, 0)
22#define MAX77650_REGULATOR_V_SBB_MASK GENMASK(5, 0)
23
24#define MAX77650_REGULATOR_AD_MASK BIT(3)
25#define MAX77650_REGULATOR_AD_DISABLED 0x00
26#define MAX77650_REGULATOR_AD_ENABLED BIT(3)
27
28#define MAX77650_REGULATOR_CURR_LIM_MASK GENMASK(7, 6)
29#define MAX77650_REGULATOR_CURR_LIM_BITS(_reg) \
30 (((_reg) & MAX77650_REGULATOR_CURR_LIM_MASK) >> 6)
31#define MAX77650_REGULATOR_CURR_LIM_SHIFT(_val) ((_val) << 6)
32
33enum {
34 MAX77650_REGULATOR_ID_LDO = 0,
35 MAX77650_REGULATOR_ID_SBB0,
36 MAX77650_REGULATOR_ID_SBB1,
37 MAX77650_REGULATOR_ID_SBB2,
38 MAX77650_REGULATOR_NUM_REGULATORS,
39};
40
41struct max77650_regulator_desc {
42 struct regulator_desc desc;
43 unsigned int regA;
44 unsigned int regB;
45};
46
47static const u32 max77651_sbb1_regulator_volt_table[] = {
48 2400000, 3200000, 4000000, 4800000,
49 2450000, 3250000, 4050000, 4850000,
50 2500000, 3300000, 4100000, 4900000,
51 2550000, 3350000, 4150000, 4950000,
52 2600000, 3400000, 4200000, 5000000,
53 2650000, 3450000, 4250000, 5050000,
54 2700000, 3500000, 4300000, 5100000,
55 2750000, 3550000, 4350000, 5150000,
56 2800000, 3600000, 4400000, 5200000,
57 2850000, 3650000, 4450000, 5250000,
58 2900000, 3700000, 4500000, 0,
59 2950000, 3750000, 4550000, 0,
60 3000000, 3800000, 4600000, 0,
61 3050000, 3850000, 4650000, 0,
62 3100000, 3900000, 4700000, 0,
63 3150000, 3950000, 4750000, 0,
64};
65
66#define MAX77651_REGULATOR_SBB1_SEL_DEC(_val) \
67 (((_val & 0x3c) >> 2) | ((_val & 0x03) << 4))
68#define MAX77651_REGULATOR_SBB1_SEL_ENC(_val) \
69 (((_val & 0x30) >> 4) | ((_val & 0x0f) << 2))
70
71#define MAX77650_REGULATOR_SBB1_SEL_DECR(_val) \
72 do { \
73 _val = MAX77651_REGULATOR_SBB1_SEL_DEC(_val); \
74 _val--; \
75 _val = MAX77651_REGULATOR_SBB1_SEL_ENC(_val); \
76 } while (0)
77
78#define MAX77650_REGULATOR_SBB1_SEL_INCR(_val) \
79 do { \
80 _val = MAX77651_REGULATOR_SBB1_SEL_DEC(_val); \
81 _val++; \
82 _val = MAX77651_REGULATOR_SBB1_SEL_ENC(_val); \
83 } while (0)
84
85static const int max77650_current_limit_table[] = {
86 1000000, 866000, 707000, 500000,
87};
88
89static int max77650_regulator_is_enabled(struct regulator_dev *rdev)
90{
91 struct max77650_regulator_desc *rdesc;
92 struct regmap *map;
93 int val, rv, en;
94
95 rdesc = rdev_get_drvdata(rdev);
96 map = rdev_get_regmap(rdev);
97
98 rv = regmap_read(map, rdesc->regB, &val);
99 if (rv)
100 return rv;
101
102 en = MAX77650_REGULATOR_EN_CTRL_BITS(val);
103
104 return en != MAX77650_REGULATOR_DISABLED;
105}
106
107static int max77650_regulator_enable(struct regulator_dev *rdev)
108{
109 struct max77650_regulator_desc *rdesc;
110 struct regmap *map;
111
112 rdesc = rdev_get_drvdata(rdev);
113 map = rdev_get_regmap(rdev);
114
115 return regmap_update_bits(map, rdesc->regB,
116 MAX77650_REGULATOR_EN_CTRL_MASK,
117 MAX77650_REGULATOR_ENABLED);
118}
119
120static int max77650_regulator_disable(struct regulator_dev *rdev)
121{
122 struct max77650_regulator_desc *rdesc;
123 struct regmap *map;
124
125 rdesc = rdev_get_drvdata(rdev);
126 map = rdev_get_regmap(rdev);
127
128 return regmap_update_bits(map, rdesc->regB,
129 MAX77650_REGULATOR_EN_CTRL_MASK,
130 MAX77650_REGULATOR_DISABLED);
131}
132
133static int max77650_regulator_set_voltage_sel(struct regulator_dev *rdev,
134 unsigned int sel)
135{
136 int rv = 0, curr, diff;
137 bool ascending;
138
139 /*
140 * If the regulator is disabled, we can program the desired
141 * voltage right away.
142 */
143 if (!max77650_regulator_is_enabled(rdev))
144 return regulator_set_voltage_sel_regmap(rdev, sel);
145
146 /*
147 * Otherwise we need to manually ramp the output voltage up/down
148 * one step at a time.
149 */
150
151 curr = regulator_get_voltage_sel_regmap(rdev);
152 if (curr < 0)
153 return curr;
154
155 diff = curr - sel;
156 if (diff == 0)
157 return 0; /* Already there. */
158 else if (diff > 0)
159 ascending = false;
160 else
161 ascending = true;
162
163 /*
164 * Make sure we'll get to the right voltage and break the loop even if
165 * the selector equals 0.
166 */
167 for (ascending ? curr++ : curr--;; ascending ? curr++ : curr--) {
168 rv = regulator_set_voltage_sel_regmap(rdev, curr);
169 if (rv)
170 return rv;
171
172 if (curr == sel)
173 break;
174 }
175
176 return 0;
177}
178
179/*
180 * Special case: non-linear voltage table for max77651 SBB1 - software
181 * must ensure the voltage is ramped in 50mV increments.
182 */
183static int max77651_regulator_sbb1_set_voltage_sel(struct regulator_dev *rdev,
184 unsigned int sel)
185{
186 int rv = 0, curr, vcurr, vdest, vdiff;
187
188 /*
189 * If the regulator is disabled, we can program the desired
190 * voltage right away.
191 */
192 if (!max77650_regulator_is_enabled(rdev))
193 return regulator_set_voltage_sel_regmap(rdev, sel);
194
195 curr = regulator_get_voltage_sel_regmap(rdev);
196 if (curr < 0)
197 return curr;
198
199 if (curr == sel)
200 return 0; /* Already there. */
201
202 vcurr = max77651_sbb1_regulator_volt_table[curr];
203 vdest = max77651_sbb1_regulator_volt_table[sel];
204 vdiff = vcurr - vdest;
205
206 for (;;) {
207 if (vdiff > 0)
208 MAX77650_REGULATOR_SBB1_SEL_DECR(curr);
209 else
210 MAX77650_REGULATOR_SBB1_SEL_INCR(curr);
211
212 rv = regulator_set_voltage_sel_regmap(rdev, curr);
213 if (rv)
214 return rv;
215
216 if (curr == sel)
217 break;
218 };
219
220 return 0;
221}
222
223static int max77650_regulator_get_current_limit(struct regulator_dev *rdev)
224{
225 struct max77650_regulator_desc *rdesc;
226 struct regmap *map;
227 int val, rv, limit;
228
229 rdesc = rdev_get_drvdata(rdev);
230 map = rdev_get_regmap(rdev);
231
232 rv = regmap_read(map, rdesc->regA, &val);
233 if (rv)
234 return rv;
235
236 limit = MAX77650_REGULATOR_CURR_LIM_BITS(val);
237
238 return max77650_current_limit_table[limit];
239}
240
241static int max77650_regulator_set_current_limit(struct regulator_dev *rdev,
242 int min_uA, int max_uA)
243{
244 struct max77650_regulator_desc *rdesc;
245 struct regmap *map;
246 int rv, i, limit;
247
248 rdesc = rdev_get_drvdata(rdev);
249 map = rdev_get_regmap(rdev);
250
251 for (i = 0; i < ARRAY_SIZE(max77650_current_limit_table); i++) {
252 limit = max77650_current_limit_table[i];
253
254 if (limit >= min_uA && limit <= max_uA) {
255 rv = regmap_update_bits(map, rdesc->regA,
256 MAX77650_REGULATOR_CURR_LIM_MASK,
257 MAX77650_REGULATOR_CURR_LIM_SHIFT(i));
258 if (rv)
259 return rv;
260 }
261 }
262
263 return -EINVAL;
264}
265
266static const struct regulator_ops max77650_regulator_LDO_ops = {
267 .is_enabled = max77650_regulator_is_enabled,
268 .enable = max77650_regulator_enable,
269 .disable = max77650_regulator_disable,
270 .list_voltage = regulator_list_voltage_linear,
271 .map_voltage = regulator_map_voltage_linear,
272 .get_voltage_sel = regulator_get_voltage_sel_regmap,
273 .set_voltage_sel = max77650_regulator_set_voltage_sel,
274 .set_active_discharge = regulator_set_active_discharge_regmap,
275};
276
277static const struct regulator_ops max77650_regulator_SBB_ops = {
278 .is_enabled = max77650_regulator_is_enabled,
279 .enable = max77650_regulator_enable,
280 .disable = max77650_regulator_disable,
281 .list_voltage = regulator_list_voltage_linear,
282 .map_voltage = regulator_map_voltage_linear,
283 .get_voltage_sel = regulator_get_voltage_sel_regmap,
284 .set_voltage_sel = max77650_regulator_set_voltage_sel,
285 .get_current_limit = max77650_regulator_get_current_limit,
286 .set_current_limit = max77650_regulator_set_current_limit,
287 .set_active_discharge = regulator_set_active_discharge_regmap,
288};
289
290/* Special case for max77651 SBB1 - non-linear voltage mapping. */
291static const struct regulator_ops max77651_SBB1_regulator_ops = {
292 .is_enabled = max77650_regulator_is_enabled,
293 .enable = max77650_regulator_enable,
294 .disable = max77650_regulator_disable,
295 .list_voltage = regulator_list_voltage_table,
296 .get_voltage_sel = regulator_get_voltage_sel_regmap,
297 .set_voltage_sel = max77651_regulator_sbb1_set_voltage_sel,
298 .get_current_limit = max77650_regulator_get_current_limit,
299 .set_current_limit = max77650_regulator_set_current_limit,
300 .set_active_discharge = regulator_set_active_discharge_regmap,
301};
302
303static struct max77650_regulator_desc max77650_LDO_desc = {
304 .desc = {
305 .name = "ldo",
306 .of_match = of_match_ptr("ldo"),
307 .regulators_node = of_match_ptr("regulators"),
308 .supply_name = "in-ldo",
309 .id = MAX77650_REGULATOR_ID_LDO,
310 .ops = &max77650_regulator_LDO_ops,
311 .min_uV = 1350000,
312 .uV_step = 12500,
313 .n_voltages = 128,
314 .vsel_mask = MAX77650_REGULATOR_V_LDO_MASK,
315 .vsel_reg = MAX77650_REG_CNFG_LDO_A,
316 .active_discharge_off = MAX77650_REGULATOR_AD_DISABLED,
317 .active_discharge_on = MAX77650_REGULATOR_AD_ENABLED,
318 .active_discharge_mask = MAX77650_REGULATOR_AD_MASK,
319 .active_discharge_reg = MAX77650_REG_CNFG_LDO_B,
320 .enable_time = 100,
321 .type = REGULATOR_VOLTAGE,
322 },
323 .regA = MAX77650_REG_CNFG_LDO_A,
324 .regB = MAX77650_REG_CNFG_LDO_B,
325};
326
327static struct max77650_regulator_desc max77650_SBB0_desc = {
328 .desc = {
329 .name = "sbb0",
330 .of_match = of_match_ptr("sbb0"),
331 .regulators_node = of_match_ptr("regulators"),
332 .supply_name = "in-sbb0",
333 .id = MAX77650_REGULATOR_ID_SBB0,
334 .ops = &max77650_regulator_SBB_ops,
335 .min_uV = 800000,
336 .uV_step = 25000,
337 .n_voltages = 64,
338 .vsel_mask = MAX77650_REGULATOR_V_SBB_MASK,
339 .vsel_reg = MAX77650_REG_CNFG_SBB0_A,
340 .active_discharge_off = MAX77650_REGULATOR_AD_DISABLED,
341 .active_discharge_on = MAX77650_REGULATOR_AD_ENABLED,
342 .active_discharge_mask = MAX77650_REGULATOR_AD_MASK,
343 .active_discharge_reg = MAX77650_REG_CNFG_SBB0_B,
344 .enable_time = 100,
345 .type = REGULATOR_VOLTAGE,
346 },
347 .regA = MAX77650_REG_CNFG_SBB0_A,
348 .regB = MAX77650_REG_CNFG_SBB0_B,
349};
350
351static struct max77650_regulator_desc max77650_SBB1_desc = {
352 .desc = {
353 .name = "sbb1",
354 .of_match = of_match_ptr("sbb1"),
355 .regulators_node = of_match_ptr("regulators"),
356 .supply_name = "in-sbb1",
357 .id = MAX77650_REGULATOR_ID_SBB1,
358 .ops = &max77650_regulator_SBB_ops,
359 .min_uV = 800000,
360 .uV_step = 12500,
361 .n_voltages = 64,
362 .vsel_mask = MAX77650_REGULATOR_V_SBB_MASK,
363 .vsel_reg = MAX77650_REG_CNFG_SBB1_A,
364 .active_discharge_off = MAX77650_REGULATOR_AD_DISABLED,
365 .active_discharge_on = MAX77650_REGULATOR_AD_ENABLED,
366 .active_discharge_mask = MAX77650_REGULATOR_AD_MASK,
367 .active_discharge_reg = MAX77650_REG_CNFG_SBB1_B,
368 .enable_time = 100,
369 .type = REGULATOR_VOLTAGE,
370 },
371 .regA = MAX77650_REG_CNFG_SBB1_A,
372 .regB = MAX77650_REG_CNFG_SBB1_B,
373};
374
375static struct max77650_regulator_desc max77651_SBB1_desc = {
376 .desc = {
377 .name = "sbb1",
378 .of_match = of_match_ptr("sbb1"),
379 .regulators_node = of_match_ptr("regulators"),
380 .supply_name = "in-sbb1",
381 .id = MAX77650_REGULATOR_ID_SBB1,
382 .ops = &max77651_SBB1_regulator_ops,
383 .volt_table = max77651_sbb1_regulator_volt_table,
384 .n_voltages = ARRAY_SIZE(max77651_sbb1_regulator_volt_table),
385 .vsel_mask = MAX77650_REGULATOR_V_SBB_MASK,
386 .vsel_reg = MAX77650_REG_CNFG_SBB1_A,
387 .active_discharge_off = MAX77650_REGULATOR_AD_DISABLED,
388 .active_discharge_on = MAX77650_REGULATOR_AD_ENABLED,
389 .active_discharge_mask = MAX77650_REGULATOR_AD_MASK,
390 .active_discharge_reg = MAX77650_REG_CNFG_SBB1_B,
391 .enable_time = 100,
392 .type = REGULATOR_VOLTAGE,
393 },
394 .regA = MAX77650_REG_CNFG_SBB1_A,
395 .regB = MAX77650_REG_CNFG_SBB1_B,
396};
397
398static struct max77650_regulator_desc max77650_SBB2_desc = {
399 .desc = {
400 .name = "sbb2",
401 .of_match = of_match_ptr("sbb2"),
402 .regulators_node = of_match_ptr("regulators"),
403 .supply_name = "in-sbb0",
404 .id = MAX77650_REGULATOR_ID_SBB2,
405 .ops = &max77650_regulator_SBB_ops,
406 .min_uV = 800000,
407 .uV_step = 50000,
408 .n_voltages = 64,
409 .vsel_mask = MAX77650_REGULATOR_V_SBB_MASK,
410 .vsel_reg = MAX77650_REG_CNFG_SBB2_A,
411 .active_discharge_off = MAX77650_REGULATOR_AD_DISABLED,
412 .active_discharge_on = MAX77650_REGULATOR_AD_ENABLED,
413 .active_discharge_mask = MAX77650_REGULATOR_AD_MASK,
414 .active_discharge_reg = MAX77650_REG_CNFG_SBB2_B,
415 .enable_time = 100,
416 .type = REGULATOR_VOLTAGE,
417 },
418 .regA = MAX77650_REG_CNFG_SBB2_A,
419 .regB = MAX77650_REG_CNFG_SBB2_B,
420};
421
422static struct max77650_regulator_desc max77651_SBB2_desc = {
423 .desc = {
424 .name = "sbb2",
425 .of_match = of_match_ptr("sbb2"),
426 .regulators_node = of_match_ptr("regulators"),
427 .supply_name = "in-sbb0",
428 .id = MAX77650_REGULATOR_ID_SBB2,
429 .ops = &max77650_regulator_SBB_ops,
430 .min_uV = 2400000,
431 .uV_step = 50000,
432 .n_voltages = 64,
433 .vsel_mask = MAX77650_REGULATOR_V_SBB_MASK,
434 .vsel_reg = MAX77650_REG_CNFG_SBB2_A,
435 .active_discharge_off = MAX77650_REGULATOR_AD_DISABLED,
436 .active_discharge_on = MAX77650_REGULATOR_AD_ENABLED,
437 .active_discharge_mask = MAX77650_REGULATOR_AD_MASK,
438 .active_discharge_reg = MAX77650_REG_CNFG_SBB2_B,
439 .enable_time = 100,
440 .type = REGULATOR_VOLTAGE,
441 },
442 .regA = MAX77650_REG_CNFG_SBB2_A,
443 .regB = MAX77650_REG_CNFG_SBB2_B,
444};
445
446static int max77650_regulator_probe(struct platform_device *pdev)
447{
448 struct max77650_regulator_desc **rdescs;
449 struct max77650_regulator_desc *rdesc;
450 struct regulator_config config = { };
451 struct device *dev, *parent;
452 struct regulator_dev *rdev;
453 struct regmap *map;
454 unsigned int val;
455 int i, rv;
456
457 dev = &pdev->dev;
458 parent = dev->parent;
459
460 if (!dev->of_node)
461 dev->of_node = parent->of_node;
462
463 rdescs = devm_kcalloc(dev, MAX77650_REGULATOR_NUM_REGULATORS,
464 sizeof(*rdescs), GFP_KERNEL);
465 if (!rdescs)
466 return -ENOMEM;
467
468 map = dev_get_regmap(parent, NULL);
469 if (!map)
470 return -ENODEV;
471
472 rv = regmap_read(map, MAX77650_REG_CID, &val);
473 if (rv)
474 return rv;
475
476 rdescs[MAX77650_REGULATOR_ID_LDO] = &max77650_LDO_desc;
477 rdescs[MAX77650_REGULATOR_ID_SBB0] = &max77650_SBB0_desc;
478
479 switch (MAX77650_CID_BITS(val)) {
480 case MAX77650_CID_77650A:
481 case MAX77650_CID_77650C:
482 rdescs[MAX77650_REGULATOR_ID_SBB1] = &max77650_SBB1_desc;
483 rdescs[MAX77650_REGULATOR_ID_SBB2] = &max77650_SBB2_desc;
484 break;
485 case MAX77650_CID_77651A:
486 case MAX77650_CID_77651B:
487 rdescs[MAX77650_REGULATOR_ID_SBB1] = &max77651_SBB1_desc;
488 rdescs[MAX77650_REGULATOR_ID_SBB2] = &max77651_SBB2_desc;
489 break;
490 default:
491 return -ENODEV;
492 }
493
494 config.dev = parent;
495
496 for (i = 0; i < MAX77650_REGULATOR_NUM_REGULATORS; i++) {
497 rdesc = rdescs[i];
498 config.driver_data = rdesc;
499
500 rdev = devm_regulator_register(dev, &rdesc->desc, &config);
501 if (IS_ERR(rdev))
502 return PTR_ERR(rdev);
503 }
504
505 return 0;
506}
507
508static struct platform_driver max77650_regulator_driver = {
509 .driver = {
510 .name = "max77650-regulator",
511 },
512 .probe = max77650_regulator_probe,
513};
514module_platform_driver(max77650_regulator_driver);
515
516MODULE_DESCRIPTION("MAXIM 77650/77651 regulator driver");
517MODULE_AUTHOR("Bartosz Golaszewski <bgolaszewski@baylibre.com>");
518MODULE_LICENSE("GPL v2");