Warning: That file was not part of the compilation database. It may have many parsing errors.

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

Warning: That file was not part of the compilation database. It may have many parsing errors.