1// SPDX-License-Identifier: GPL-2.0-only
2//
3// Copyright 2014 Embest Technology Co. Ltd. Inc.
4// bd71815-regulator.c ROHM BD71815 regulator driver
5//
6// Author: Tony Luo <luofc@embedinfo.com>
7//
8// Partially rewritten at 2021 by
9// Matti Vaittinen <matti.vaitinen@fi.rohmeurope.com>
10
11#include <linux/kernel.h>
12#include <linux/module.h>
13#include <linux/init.h>
14#include <linux/err.h>
15#include <linux/platform_device.h>
16#include <linux/of.h>
17#include <linux/gpio/consumer.h>
18#include <linux/regulator/driver.h>
19#include <linux/delay.h>
20#include <linux/slab.h>
21#include <linux/mfd/rohm-generic.h>
22#include <linux/mfd/rohm-bd71815.h>
23#include <linux/regulator/of_regulator.h>
24
25struct bd71815_regulator {
26 struct regulator_desc desc;
27 const struct rohm_dvs_config *dvs;
28};
29
30static const int bd7181x_wled_currents[] = {
31 10, 20, 30, 50, 70, 100, 200, 300, 500, 700, 1000, 2000, 3000, 4000,
32 5000, 6000, 7000, 8000, 9000, 10000, 11000, 12000, 13000, 14000, 15000,
33 16000, 17000, 18000, 19000, 20000, 21000, 22000, 23000, 24000, 25000,
34};
35
36static const struct rohm_dvs_config buck1_dvs = {
37 .level_map = ROHM_DVS_LEVEL_RUN | ROHM_DVS_LEVEL_SNVS |
38 ROHM_DVS_LEVEL_SUSPEND | ROHM_DVS_LEVEL_LPSR,
39 .run_reg = BD71815_REG_BUCK1_VOLT_H,
40 .run_mask = BD71815_VOLT_MASK,
41 .run_on_mask = BD71815_BUCK_RUN_ON,
42 .snvs_on_mask = BD71815_BUCK_SNVS_ON,
43 .suspend_reg = BD71815_REG_BUCK1_VOLT_L,
44 .suspend_mask = BD71815_VOLT_MASK,
45 .suspend_on_mask = BD71815_BUCK_SUSP_ON,
46 .lpsr_reg = BD71815_REG_BUCK1_VOLT_L,
47 .lpsr_mask = BD71815_VOLT_MASK,
48 .lpsr_on_mask = BD71815_BUCK_LPSR_ON,
49};
50
51static const struct rohm_dvs_config buck2_dvs = {
52 .level_map = ROHM_DVS_LEVEL_RUN | ROHM_DVS_LEVEL_SNVS |
53 ROHM_DVS_LEVEL_SUSPEND | ROHM_DVS_LEVEL_LPSR,
54 .run_reg = BD71815_REG_BUCK2_VOLT_H,
55 .run_mask = BD71815_VOLT_MASK,
56 .run_on_mask = BD71815_BUCK_RUN_ON,
57 .snvs_on_mask = BD71815_BUCK_SNVS_ON,
58 .suspend_reg = BD71815_REG_BUCK2_VOLT_L,
59 .suspend_mask = BD71815_VOLT_MASK,
60 .suspend_on_mask = BD71815_BUCK_SUSP_ON,
61 .lpsr_reg = BD71815_REG_BUCK2_VOLT_L,
62 .lpsr_mask = BD71815_VOLT_MASK,
63 .lpsr_on_mask = BD71815_BUCK_LPSR_ON,
64};
65
66static const struct rohm_dvs_config buck3_dvs = {
67 .level_map = ROHM_DVS_LEVEL_RUN | ROHM_DVS_LEVEL_SNVS |
68 ROHM_DVS_LEVEL_SUSPEND | ROHM_DVS_LEVEL_LPSR,
69 .run_reg = BD71815_REG_BUCK3_VOLT,
70 .run_mask = BD71815_VOLT_MASK,
71 .run_on_mask = BD71815_BUCK_RUN_ON,
72 .snvs_on_mask = BD71815_BUCK_SNVS_ON,
73 .suspend_on_mask = BD71815_BUCK_SUSP_ON,
74 .lpsr_on_mask = BD71815_BUCK_LPSR_ON,
75};
76
77static const struct rohm_dvs_config buck4_dvs = {
78 .level_map = ROHM_DVS_LEVEL_RUN | ROHM_DVS_LEVEL_SNVS |
79 ROHM_DVS_LEVEL_SUSPEND | ROHM_DVS_LEVEL_LPSR,
80 .run_reg = BD71815_REG_BUCK4_VOLT,
81 .run_mask = BD71815_VOLT_MASK,
82 .run_on_mask = BD71815_BUCK_RUN_ON,
83 .snvs_on_mask = BD71815_BUCK_SNVS_ON,
84 .suspend_on_mask = BD71815_BUCK_SUSP_ON,
85 .lpsr_on_mask = BD71815_BUCK_LPSR_ON,
86};
87
88static const struct rohm_dvs_config ldo1_dvs = {
89 .level_map = ROHM_DVS_LEVEL_RUN | ROHM_DVS_LEVEL_SNVS |
90 ROHM_DVS_LEVEL_SUSPEND | ROHM_DVS_LEVEL_LPSR,
91 .run_reg = BD71815_REG_LDO_MODE1,
92 .run_mask = BD71815_VOLT_MASK,
93 .run_on_mask = LDO1_RUN_ON,
94 .snvs_on_mask = LDO1_SNVS_ON,
95 .suspend_on_mask = LDO1_SUSP_ON,
96 .lpsr_on_mask = LDO1_LPSR_ON,
97};
98
99static const struct rohm_dvs_config ldo2_dvs = {
100 .level_map = ROHM_DVS_LEVEL_RUN | ROHM_DVS_LEVEL_SNVS |
101 ROHM_DVS_LEVEL_SUSPEND | ROHM_DVS_LEVEL_LPSR,
102 .run_reg = BD71815_REG_LDO_MODE2,
103 .run_mask = BD71815_VOLT_MASK,
104 .run_on_mask = LDO2_RUN_ON,
105 .snvs_on_mask = LDO2_SNVS_ON,
106 .suspend_on_mask = LDO2_SUSP_ON,
107 .lpsr_on_mask = LDO2_LPSR_ON,
108};
109
110static const struct rohm_dvs_config ldo3_dvs = {
111 .level_map = ROHM_DVS_LEVEL_RUN | ROHM_DVS_LEVEL_SNVS |
112 ROHM_DVS_LEVEL_SUSPEND | ROHM_DVS_LEVEL_LPSR,
113 .run_reg = BD71815_REG_LDO_MODE2,
114 .run_mask = BD71815_VOLT_MASK,
115 .run_on_mask = LDO3_RUN_ON,
116 .snvs_on_mask = LDO3_SNVS_ON,
117 .suspend_on_mask = LDO3_SUSP_ON,
118 .lpsr_on_mask = LDO3_LPSR_ON,
119};
120
121static const struct rohm_dvs_config ldo4_dvs = {
122 .level_map = ROHM_DVS_LEVEL_RUN | ROHM_DVS_LEVEL_SNVS |
123 ROHM_DVS_LEVEL_SUSPEND | ROHM_DVS_LEVEL_LPSR,
124 .run_reg = BD71815_REG_LDO_MODE3,
125 .run_mask = BD71815_VOLT_MASK,
126 .run_on_mask = LDO4_RUN_ON,
127 .snvs_on_mask = LDO4_SNVS_ON,
128 .suspend_on_mask = LDO4_SUSP_ON,
129 .lpsr_on_mask = LDO4_LPSR_ON,
130};
131
132static const struct rohm_dvs_config ldo5_dvs = {
133 .level_map = ROHM_DVS_LEVEL_RUN | ROHM_DVS_LEVEL_SNVS |
134 ROHM_DVS_LEVEL_SUSPEND | ROHM_DVS_LEVEL_LPSR,
135 .run_reg = BD71815_REG_LDO_MODE3,
136 .run_mask = BD71815_VOLT_MASK,
137 .run_on_mask = LDO5_RUN_ON,
138 .snvs_on_mask = LDO5_SNVS_ON,
139 .suspend_on_mask = LDO5_SUSP_ON,
140 .lpsr_on_mask = LDO5_LPSR_ON,
141};
142
143static const struct rohm_dvs_config dvref_dvs = {
144 .level_map = ROHM_DVS_LEVEL_RUN | ROHM_DVS_LEVEL_SNVS |
145 ROHM_DVS_LEVEL_SUSPEND | ROHM_DVS_LEVEL_LPSR,
146 .run_on_mask = DVREF_RUN_ON,
147 .snvs_on_mask = DVREF_SNVS_ON,
148 .suspend_on_mask = DVREF_SUSP_ON,
149 .lpsr_on_mask = DVREF_LPSR_ON,
150};
151
152static const struct rohm_dvs_config ldolpsr_dvs = {
153 .level_map = ROHM_DVS_LEVEL_RUN | ROHM_DVS_LEVEL_SNVS |
154 ROHM_DVS_LEVEL_SUSPEND | ROHM_DVS_LEVEL_LPSR,
155 .run_on_mask = DVREF_RUN_ON,
156 .snvs_on_mask = DVREF_SNVS_ON,
157 .suspend_on_mask = DVREF_SUSP_ON,
158 .lpsr_on_mask = DVREF_LPSR_ON,
159};
160
161static const struct rohm_dvs_config buck5_dvs = {
162 .level_map = ROHM_DVS_LEVEL_RUN | ROHM_DVS_LEVEL_SNVS |
163 ROHM_DVS_LEVEL_SUSPEND | ROHM_DVS_LEVEL_LPSR,
164 .run_reg = BD71815_REG_BUCK5_VOLT,
165 .run_mask = BD71815_VOLT_MASK,
166 .run_on_mask = BD71815_BUCK_RUN_ON,
167 .snvs_on_mask = BD71815_BUCK_SNVS_ON,
168 .suspend_on_mask = BD71815_BUCK_SUSP_ON,
169 .lpsr_on_mask = BD71815_BUCK_LPSR_ON,
170};
171
172static int set_hw_dvs_levels(struct device_node *np,
173 const struct regulator_desc *desc,
174 struct regulator_config *cfg)
175{
176 struct bd71815_regulator *data;
177
178 data = container_of(desc, struct bd71815_regulator, desc);
179 return rohm_regulator_set_dvs_levels(dvs: data->dvs, np, desc, regmap: cfg->regmap);
180}
181
182/*
183 * Bucks 1 and 2 have two voltage selection registers where selected
184 * voltage can be set. Which of the registers is used can be either controlled
185 * by a control bit in register - or by HW state. If HW state specific voltages
186 * are given - then we assume HW state based control should be used.
187 *
188 * If volatge value is updated to currently selected register - then output
189 * voltage is immediately changed no matter what is set as ramp rate. Thus we
190 * default changing voltage by writing new value to inactive register and
191 * then updating the 'register selection' bit. This naturally only works when
192 * HW state machine is not used to select the voltage.
193 */
194static int buck12_set_hw_dvs_levels(struct device_node *np,
195 const struct regulator_desc *desc,
196 struct regulator_config *cfg)
197{
198 struct bd71815_regulator *data;
199 int ret = 0, val;
200
201 data = container_of(desc, struct bd71815_regulator, desc);
202
203 if (of_property_present(np, propname: "rohm,dvs-run-voltage") ||
204 of_property_present(np, propname: "rohm,dvs-suspend-voltage") ||
205 of_property_present(np, propname: "rohm,dvs-lpsr-voltage") ||
206 of_property_present(np, propname: "rohm,dvs-snvs-voltage")) {
207 ret = regmap_read(map: cfg->regmap, reg: desc->vsel_reg, val: &val);
208 if (ret)
209 return ret;
210
211 if (!(BD71815_BUCK_STBY_DVS & val) &&
212 !(BD71815_BUCK_DVSSEL & val)) {
213 int val2;
214
215 /*
216 * We are currently using voltage from _L.
217 * We'd better copy it to _H and switch to it to
218 * avoid shutting us down if LPSR or SUSPEND is set to
219 * disabled. _L value is at reg _H + 1
220 */
221 ret = regmap_read(map: cfg->regmap, reg: desc->vsel_reg + 1,
222 val: &val2);
223 if (ret)
224 return ret;
225
226 ret = regmap_update_bits(map: cfg->regmap, reg: desc->vsel_reg,
227 BD71815_VOLT_MASK |
228 BD71815_BUCK_DVSSEL,
229 val: val2 | BD71815_BUCK_DVSSEL);
230 if (ret)
231 return ret;
232 }
233 ret = rohm_regulator_set_dvs_levels(dvs: data->dvs, np, desc,
234 regmap: cfg->regmap);
235 if (ret)
236 return ret;
237 /*
238 * DVS levels were given => use HW-state machine for voltage
239 * controls. NOTE: AFAIK, This means that if voltage is changed
240 * by SW the ramp-rate is not respected. Should we disable
241 * SW voltage control when the HW state machine is used?
242 */
243 ret = regmap_update_bits(map: cfg->regmap, reg: desc->vsel_reg,
244 BD71815_BUCK_STBY_DVS,
245 BD71815_BUCK_STBY_DVS);
246 }
247
248 return ret;
249}
250
251/*
252 * BUCK1/2
253 * BUCK1RAMPRATE[1:0] BUCK1 DVS ramp rate setting
254 * 00: 10.00mV/usec 10mV 1uS
255 * 01: 5.00mV/usec 10mV 2uS
256 * 10: 2.50mV/usec 10mV 4uS
257 * 11: 1.25mV/usec 10mV 8uS
258 */
259static const unsigned int bd7181x_ramp_table[] = { 1250, 2500, 5000, 10000 };
260
261static int bd7181x_led_set_current_limit(struct regulator_dev *rdev,
262 int min_uA, int max_uA)
263{
264 int ret;
265 int onstatus;
266
267 onstatus = regulator_is_enabled_regmap(rdev);
268
269 ret = regulator_set_current_limit_regmap(rdev, min_uA, max_uA);
270 if (!ret) {
271 int newstatus;
272
273 newstatus = regulator_is_enabled_regmap(rdev);
274 if (onstatus != newstatus) {
275 /*
276 * HW FIX: spurious led status change detected. Toggle
277 * state as a workaround
278 */
279 if (onstatus)
280 ret = regulator_enable_regmap(rdev);
281 else
282 ret = regulator_disable_regmap(rdev);
283
284 if (ret)
285 dev_err(rdev_get_dev(rdev),
286 "failed to revert the LED state (%d)\n",
287 ret);
288 }
289 }
290
291 return ret;
292}
293
294static int bd7181x_buck12_get_voltage_sel(struct regulator_dev *rdev)
295{
296 int rid = rdev_get_id(rdev);
297 int ret, regh, regl, val;
298
299 regh = BD71815_REG_BUCK1_VOLT_H + rid * 0x2;
300 regl = BD71815_REG_BUCK1_VOLT_L + rid * 0x2;
301
302 ret = regmap_read(map: rdev->regmap, reg: regh, val: &val);
303 if (ret)
304 return ret;
305
306 /*
307 * If we use HW state machine based voltage reg selection - then we
308 * return BD71815_REG_BUCK1_VOLT_H which is used at RUN.
309 * Else we do return the BD71815_REG_BUCK1_VOLT_H or
310 * BD71815_REG_BUCK1_VOLT_L depending on which is selected to be used
311 * by BD71815_BUCK_DVSSEL bit
312 */
313 if ((!(val & BD71815_BUCK_STBY_DVS)) && (!(val & BD71815_BUCK_DVSSEL)))
314 ret = regmap_read(map: rdev->regmap, reg: regl, val: &val);
315
316 if (ret)
317 return ret;
318
319 return val & BD71815_VOLT_MASK;
320}
321
322/*
323 * For Buck 1/2.
324 */
325static int bd7181x_buck12_set_voltage_sel(struct regulator_dev *rdev,
326 unsigned int sel)
327{
328 int rid = rdev_get_id(rdev);
329 int ret, val, reg, regh, regl;
330
331 regh = BD71815_REG_BUCK1_VOLT_H + rid*0x2;
332 regl = BD71815_REG_BUCK1_VOLT_L + rid*0x2;
333
334 ret = regmap_read(map: rdev->regmap, reg: regh, val: &val);
335 if (ret)
336 return ret;
337
338 /*
339 * If bucks 1 & 2 are controlled by state machine - then the RUN state
340 * voltage is set to BD71815_REG_BUCK1_VOLT_H. Changing SUSPEND/LPSR
341 * voltages at runtime is not supported by this driver.
342 */
343 if (((val & BD71815_BUCK_STBY_DVS))) {
344 return regmap_update_bits(map: rdev->regmap, reg: regh, BD71815_VOLT_MASK,
345 val: sel);
346 }
347 /* Update new voltage to the register which is not selected now */
348 if (val & BD71815_BUCK_DVSSEL)
349 reg = regl;
350 else
351 reg = regh;
352
353 ret = regmap_update_bits(map: rdev->regmap, reg, BD71815_VOLT_MASK, val: sel);
354 if (ret)
355 return ret;
356
357 /* Select the other DVS register to be used */
358 return regmap_update_bits(map: rdev->regmap, reg: regh, BD71815_BUCK_DVSSEL,
359 val: ~val);
360}
361
362static const struct regulator_ops bd7181x_ldo_regulator_ops = {
363 .enable = regulator_enable_regmap,
364 .disable = regulator_disable_regmap,
365 .is_enabled = regulator_is_enabled_regmap,
366 .list_voltage = regulator_list_voltage_linear,
367 .set_voltage_sel = regulator_set_voltage_sel_regmap,
368 .get_voltage_sel = regulator_get_voltage_sel_regmap,
369};
370
371static const struct regulator_ops bd7181x_fixed_regulator_ops = {
372 .enable = regulator_enable_regmap,
373 .disable = regulator_disable_regmap,
374 .is_enabled = regulator_is_enabled_regmap,
375 .list_voltage = regulator_list_voltage_linear,
376};
377
378static const struct regulator_ops bd7181x_buck_regulator_ops = {
379 .enable = regulator_enable_regmap,
380 .disable = regulator_disable_regmap,
381 .is_enabled = regulator_is_enabled_regmap,
382 .list_voltage = regulator_list_voltage_linear,
383 .set_voltage_sel = regulator_set_voltage_sel_regmap,
384 .get_voltage_sel = regulator_get_voltage_sel_regmap,
385 .set_voltage_time_sel = regulator_set_voltage_time_sel,
386};
387
388static const struct regulator_ops bd7181x_buck12_regulator_ops = {
389 .enable = regulator_enable_regmap,
390 .disable = regulator_disable_regmap,
391 .is_enabled = regulator_is_enabled_regmap,
392 .list_voltage = regulator_list_voltage_linear,
393 .set_voltage_sel = bd7181x_buck12_set_voltage_sel,
394 .get_voltage_sel = bd7181x_buck12_get_voltage_sel,
395 .set_voltage_time_sel = regulator_set_voltage_time_sel,
396 .set_ramp_delay = regulator_set_ramp_delay_regmap,
397};
398
399static const struct regulator_ops bd7181x_led_regulator_ops = {
400 .enable = regulator_enable_regmap,
401 .disable = regulator_disable_regmap,
402 .is_enabled = regulator_is_enabled_regmap,
403 .set_current_limit = bd7181x_led_set_current_limit,
404 .get_current_limit = regulator_get_current_limit_regmap,
405};
406
407#define BD71815_FIXED_REG(_name, _id, ereg, emsk, voltage, _dvs) \
408 [(_id)] = { \
409 .desc = { \
410 .name = #_name, \
411 .of_match = of_match_ptr(#_name), \
412 .regulators_node = of_match_ptr("regulators"), \
413 .n_voltages = 1, \
414 .ops = &bd7181x_fixed_regulator_ops, \
415 .type = REGULATOR_VOLTAGE, \
416 .id = (_id), \
417 .owner = THIS_MODULE, \
418 .min_uV = (voltage), \
419 .enable_reg = (ereg), \
420 .enable_mask = (emsk), \
421 .of_parse_cb = set_hw_dvs_levels, \
422 }, \
423 .dvs = (_dvs), \
424 }
425
426#define BD71815_BUCK_REG(_name, _id, vsel, ereg, min, max, step, _dvs) \
427 [(_id)] = { \
428 .desc = { \
429 .name = #_name, \
430 .of_match = of_match_ptr(#_name), \
431 .regulators_node = of_match_ptr("regulators"), \
432 .n_voltages = ((max) - (min)) / (step) + 1, \
433 .ops = &bd7181x_buck_regulator_ops, \
434 .type = REGULATOR_VOLTAGE, \
435 .id = (_id), \
436 .owner = THIS_MODULE, \
437 .min_uV = (min), \
438 .uV_step = (step), \
439 .vsel_reg = (vsel), \
440 .vsel_mask = BD71815_VOLT_MASK, \
441 .enable_reg = (ereg), \
442 .enable_mask = BD71815_BUCK_RUN_ON, \
443 .of_parse_cb = set_hw_dvs_levels, \
444 }, \
445 .dvs = (_dvs), \
446 }
447
448#define BD71815_BUCK12_REG(_name, _id, vsel, ereg, min, max, step, \
449 _dvs) \
450 [(_id)] = { \
451 .desc = { \
452 .name = #_name, \
453 .of_match = of_match_ptr(#_name), \
454 .regulators_node = of_match_ptr("regulators"), \
455 .n_voltages = ((max) - (min)) / (step) + 1, \
456 .ops = &bd7181x_buck12_regulator_ops, \
457 .type = REGULATOR_VOLTAGE, \
458 .id = (_id), \
459 .owner = THIS_MODULE, \
460 .min_uV = (min), \
461 .uV_step = (step), \
462 .vsel_reg = (vsel), \
463 .vsel_mask = BD71815_VOLT_MASK, \
464 .enable_reg = (ereg), \
465 .enable_mask = BD71815_BUCK_RUN_ON, \
466 .ramp_reg = (ereg), \
467 .ramp_mask = BD71815_BUCK_RAMPRATE_MASK, \
468 .ramp_delay_table = bd7181x_ramp_table, \
469 .n_ramp_values = ARRAY_SIZE(bd7181x_ramp_table),\
470 .of_parse_cb = buck12_set_hw_dvs_levels, \
471 }, \
472 .dvs = (_dvs), \
473 }
474
475#define BD71815_LED_REG(_name, _id, csel, mask, ereg, emsk, currents) \
476 [(_id)] = { \
477 .desc = { \
478 .name = #_name, \
479 .of_match = of_match_ptr(#_name), \
480 .regulators_node = of_match_ptr("regulators"), \
481 .n_current_limits = ARRAY_SIZE(currents), \
482 .ops = &bd7181x_led_regulator_ops, \
483 .type = REGULATOR_CURRENT, \
484 .id = (_id), \
485 .owner = THIS_MODULE, \
486 .curr_table = currents, \
487 .csel_reg = (csel), \
488 .csel_mask = (mask), \
489 .enable_reg = (ereg), \
490 .enable_mask = (emsk), \
491 }, \
492 }
493
494#define BD71815_LDO_REG(_name, _id, vsel, ereg, emsk, min, max, step, \
495 _dvs) \
496 [(_id)] = { \
497 .desc = { \
498 .name = #_name, \
499 .of_match = of_match_ptr(#_name), \
500 .regulators_node = of_match_ptr("regulators"), \
501 .n_voltages = ((max) - (min)) / (step) + 1, \
502 .ops = &bd7181x_ldo_regulator_ops, \
503 .type = REGULATOR_VOLTAGE, \
504 .id = (_id), \
505 .owner = THIS_MODULE, \
506 .min_uV = (min), \
507 .uV_step = (step), \
508 .vsel_reg = (vsel), \
509 .vsel_mask = BD71815_VOLT_MASK, \
510 .enable_reg = (ereg), \
511 .enable_mask = (emsk), \
512 .of_parse_cb = set_hw_dvs_levels, \
513 }, \
514 .dvs = (_dvs), \
515 }
516
517static const struct bd71815_regulator bd71815_regulators[] = {
518 BD71815_BUCK12_REG(buck1, BD71815_BUCK1, BD71815_REG_BUCK1_VOLT_H,
519 BD71815_REG_BUCK1_MODE, 800000, 2000000, 25000,
520 &buck1_dvs),
521 BD71815_BUCK12_REG(buck2, BD71815_BUCK2, BD71815_REG_BUCK2_VOLT_H,
522 BD71815_REG_BUCK2_MODE, 800000, 2000000, 25000,
523 &buck2_dvs),
524 BD71815_BUCK_REG(buck3, BD71815_BUCK3, BD71815_REG_BUCK3_VOLT,
525 BD71815_REG_BUCK3_MODE, 1200000, 2700000, 50000,
526 &buck3_dvs),
527 BD71815_BUCK_REG(buck4, BD71815_BUCK4, BD71815_REG_BUCK4_VOLT,
528 BD71815_REG_BUCK4_MODE, 1100000, 1850000, 25000,
529 &buck4_dvs),
530 BD71815_BUCK_REG(buck5, BD71815_BUCK5, BD71815_REG_BUCK5_VOLT,
531 BD71815_REG_BUCK5_MODE, 1800000, 3300000, 50000,
532 &buck5_dvs),
533 BD71815_LDO_REG(ldo1, BD71815_LDO1, BD71815_REG_LDO1_VOLT,
534 BD71815_REG_LDO_MODE1, LDO1_RUN_ON, 800000, 3300000,
535 50000, &ldo1_dvs),
536 BD71815_LDO_REG(ldo2, BD71815_LDO2, BD71815_REG_LDO2_VOLT,
537 BD71815_REG_LDO_MODE2, LDO2_RUN_ON, 800000, 3300000,
538 50000, &ldo2_dvs),
539 /*
540 * Let's default LDO3 to be enabled by SW. We can override ops if DT
541 * says LDO3 should be enabled by HW when DCIN is connected.
542 */
543 BD71815_LDO_REG(ldo3, BD71815_LDO3, BD71815_REG_LDO3_VOLT,
544 BD71815_REG_LDO_MODE2, LDO3_RUN_ON, 800000, 3300000,
545 50000, &ldo3_dvs),
546 BD71815_LDO_REG(ldo4, BD71815_LDO4, BD71815_REG_LDO4_VOLT,
547 BD71815_REG_LDO_MODE3, LDO4_RUN_ON, 800000, 3300000,
548 50000, &ldo4_dvs),
549 BD71815_LDO_REG(ldo5, BD71815_LDO5, BD71815_REG_LDO5_VOLT_H,
550 BD71815_REG_LDO_MODE3, LDO5_RUN_ON, 800000, 3300000,
551 50000, &ldo5_dvs),
552 BD71815_FIXED_REG(ldodvref, BD71815_LDODVREF, BD71815_REG_LDO_MODE4,
553 DVREF_RUN_ON, 3000000, &dvref_dvs),
554 BD71815_FIXED_REG(ldolpsr, BD71815_LDOLPSR, BD71815_REG_LDO_MODE4,
555 LDO_LPSR_RUN_ON, 1800000, &ldolpsr_dvs),
556 BD71815_LED_REG(wled, BD71815_WLED, BD71815_REG_LED_DIMM, LED_DIMM_MASK,
557 BD71815_REG_LED_CTRL, LED_RUN_ON,
558 bd7181x_wled_currents),
559};
560
561static int bd7181x_probe(struct platform_device *pdev)
562{
563 struct regulator_config config = {};
564 int i, ret;
565 struct gpio_desc *ldo4_en;
566 struct regmap *regmap;
567
568 regmap = dev_get_regmap(dev: pdev->dev.parent, NULL);
569 if (!regmap) {
570 dev_err(&pdev->dev, "No parent regmap\n");
571 return -ENODEV;
572 }
573
574 ldo4_en = devm_fwnode_gpiod_get(dev: &pdev->dev,
575 dev_fwnode(pdev->dev.parent),
576 con_id: "rohm,vsel", flags: GPIOD_ASIS, label: "ldo4-en");
577 if (IS_ERR(ptr: ldo4_en)) {
578 ret = PTR_ERR(ptr: ldo4_en);
579 if (ret != -ENOENT)
580 return ret;
581 ldo4_en = NULL;
582 }
583
584 /* Disable to go to ship-mode */
585 ret = regmap_update_bits(map: regmap, reg: BD71815_REG_PWRCTRL, RESTARTEN, val: 0);
586 if (ret)
587 return ret;
588
589 config.dev = pdev->dev.parent;
590 config.regmap = regmap;
591
592 for (i = 0; i < BD71815_REGULATOR_CNT; i++) {
593 const struct regulator_desc *desc;
594 struct regulator_dev *rdev;
595
596 desc = &bd71815_regulators[i].desc;
597
598 if (i == BD71815_LDO4)
599 config.ena_gpiod = ldo4_en;
600 else
601 config.ena_gpiod = NULL;
602
603 rdev = devm_regulator_register(dev: &pdev->dev, regulator_desc: desc, config: &config);
604 if (IS_ERR(ptr: rdev))
605 return dev_err_probe(dev: &pdev->dev, err: PTR_ERR(ptr: rdev),
606 fmt: "failed to register %s regulator\n",
607 desc->name);
608 }
609 return 0;
610}
611
612static const struct platform_device_id bd7181x_pmic_id[] = {
613 { "bd71815-pmic", ROHM_CHIP_TYPE_BD71815 },
614 { },
615};
616MODULE_DEVICE_TABLE(platform, bd7181x_pmic_id);
617
618static struct platform_driver bd7181x_regulator = {
619 .driver = {
620 .name = "bd7181x-pmic",
621 .probe_type = PROBE_PREFER_ASYNCHRONOUS,
622 },
623 .probe = bd7181x_probe,
624 .id_table = bd7181x_pmic_id,
625};
626module_platform_driver(bd7181x_regulator);
627
628MODULE_AUTHOR("Tony Luo <luofc@embedinfo.com>");
629MODULE_DESCRIPTION("BD71815 voltage regulator driver");
630MODULE_LICENSE("GPL v2");
631MODULE_ALIAS("platform:bd7181x-pmic");
632

source code of linux/drivers/regulator/bd71815-regulator.c