1 | // SPDX-License-Identifier: GPL-2.0-only |
2 | // Copyright (C) 2019 ROHM Semiconductors |
3 | // bd71828-regulator.c ROHM BD71828GW-DS1 regulator driver |
4 | // |
5 | |
6 | #include <linux/delay.h> |
7 | #include <linux/err.h> |
8 | #include <linux/interrupt.h> |
9 | #include <linux/kernel.h> |
10 | #include <linux/mfd/rohm-bd71828.h> |
11 | #include <linux/module.h> |
12 | #include <linux/of.h> |
13 | #include <linux/platform_device.h> |
14 | #include <linux/regmap.h> |
15 | #include <linux/regulator/driver.h> |
16 | #include <linux/regulator/machine.h> |
17 | #include <linux/regulator/of_regulator.h> |
18 | |
19 | struct reg_init { |
20 | unsigned int reg; |
21 | unsigned int mask; |
22 | unsigned int val; |
23 | }; |
24 | struct bd71828_regulator_data { |
25 | struct regulator_desc desc; |
26 | const struct rohm_dvs_config dvs; |
27 | const struct reg_init *reg_inits; |
28 | int reg_init_amnt; |
29 | }; |
30 | |
31 | static const struct reg_init buck1_inits[] = { |
32 | /* |
33 | * DVS Buck voltages can be changed by register values or via GPIO. |
34 | * Use register accesses by default. |
35 | */ |
36 | { |
37 | .reg = BD71828_REG_PS_CTRL_1, |
38 | .mask = BD71828_MASK_DVS_BUCK1_CTRL, |
39 | .val = BD71828_DVS_BUCK1_CTRL_I2C, |
40 | }, |
41 | }; |
42 | |
43 | static const struct reg_init buck2_inits[] = { |
44 | { |
45 | .reg = BD71828_REG_PS_CTRL_1, |
46 | .mask = BD71828_MASK_DVS_BUCK2_CTRL, |
47 | .val = BD71828_DVS_BUCK2_CTRL_I2C, |
48 | }, |
49 | }; |
50 | |
51 | static const struct reg_init buck6_inits[] = { |
52 | { |
53 | .reg = BD71828_REG_PS_CTRL_1, |
54 | .mask = BD71828_MASK_DVS_BUCK6_CTRL, |
55 | .val = BD71828_DVS_BUCK6_CTRL_I2C, |
56 | }, |
57 | }; |
58 | |
59 | static const struct reg_init buck7_inits[] = { |
60 | { |
61 | .reg = BD71828_REG_PS_CTRL_1, |
62 | .mask = BD71828_MASK_DVS_BUCK7_CTRL, |
63 | .val = BD71828_DVS_BUCK7_CTRL_I2C, |
64 | }, |
65 | }; |
66 | |
67 | static const struct linear_range bd71828_buck1267_volts[] = { |
68 | REGULATOR_LINEAR_RANGE(500000, 0x00, 0xef, 6250), |
69 | REGULATOR_LINEAR_RANGE(2000000, 0xf0, 0xff, 0), |
70 | }; |
71 | |
72 | static const struct linear_range bd71828_buck3_volts[] = { |
73 | REGULATOR_LINEAR_RANGE(1200000, 0x00, 0x0f, 50000), |
74 | REGULATOR_LINEAR_RANGE(2000000, 0x10, 0x1f, 0), |
75 | }; |
76 | |
77 | static const struct linear_range bd71828_buck4_volts[] = { |
78 | REGULATOR_LINEAR_RANGE(1000000, 0x00, 0x1f, 25000), |
79 | REGULATOR_LINEAR_RANGE(1800000, 0x20, 0x3f, 0), |
80 | }; |
81 | |
82 | static const struct linear_range bd71828_buck5_volts[] = { |
83 | REGULATOR_LINEAR_RANGE(2500000, 0x00, 0x0f, 50000), |
84 | REGULATOR_LINEAR_RANGE(3300000, 0x10, 0x1f, 0), |
85 | }; |
86 | |
87 | static const struct linear_range bd71828_ldo_volts[] = { |
88 | REGULATOR_LINEAR_RANGE(800000, 0x00, 0x31, 50000), |
89 | REGULATOR_LINEAR_RANGE(3300000, 0x32, 0x3f, 0), |
90 | }; |
91 | |
92 | static const unsigned int bd71828_ramp_delay[] = { 2500, 5000, 10000, 20000 }; |
93 | |
94 | static int buck_set_hw_dvs_levels(struct device_node *np, |
95 | const struct regulator_desc *desc, |
96 | struct regulator_config *cfg) |
97 | { |
98 | struct bd71828_regulator_data *data; |
99 | |
100 | data = container_of(desc, struct bd71828_regulator_data, desc); |
101 | |
102 | return rohm_regulator_set_dvs_levels(dvs: &data->dvs, np, desc, regmap: cfg->regmap); |
103 | } |
104 | |
105 | static int ldo6_parse_dt(struct device_node *np, |
106 | const struct regulator_desc *desc, |
107 | struct regulator_config *cfg) |
108 | { |
109 | int ret, i; |
110 | uint32_t uv = 0; |
111 | unsigned int en; |
112 | struct regmap *regmap = cfg->regmap; |
113 | static const char * const props[] = { "rohm,dvs-run-voltage" , |
114 | "rohm,dvs-idle-voltage" , |
115 | "rohm,dvs-suspend-voltage" , |
116 | "rohm,dvs-lpsr-voltage" }; |
117 | unsigned int mask[] = { BD71828_MASK_RUN_EN, BD71828_MASK_IDLE_EN, |
118 | BD71828_MASK_SUSP_EN, BD71828_MASK_LPSR_EN }; |
119 | |
120 | for (i = 0; i < ARRAY_SIZE(props); i++) { |
121 | ret = of_property_read_u32(np, propname: props[i], out_value: &uv); |
122 | if (ret) { |
123 | if (ret != -EINVAL) |
124 | return ret; |
125 | continue; |
126 | } |
127 | if (uv) |
128 | en = 0xffffffff; |
129 | else |
130 | en = 0; |
131 | |
132 | ret = regmap_update_bits(map: regmap, reg: desc->enable_reg, mask: mask[i], val: en); |
133 | if (ret) |
134 | return ret; |
135 | } |
136 | return 0; |
137 | } |
138 | |
139 | static const struct regulator_ops bd71828_buck_ops = { |
140 | .enable = regulator_enable_regmap, |
141 | .disable = regulator_disable_regmap, |
142 | .is_enabled = regulator_is_enabled_regmap, |
143 | .list_voltage = regulator_list_voltage_linear_range, |
144 | .set_voltage_sel = regulator_set_voltage_sel_regmap, |
145 | .get_voltage_sel = regulator_get_voltage_sel_regmap, |
146 | }; |
147 | |
148 | static const struct regulator_ops bd71828_dvs_buck_ops = { |
149 | .enable = regulator_enable_regmap, |
150 | .disable = regulator_disable_regmap, |
151 | .is_enabled = regulator_is_enabled_regmap, |
152 | .list_voltage = regulator_list_voltage_linear_range, |
153 | .set_voltage_sel = regulator_set_voltage_sel_regmap, |
154 | .get_voltage_sel = regulator_get_voltage_sel_regmap, |
155 | .set_voltage_time_sel = regulator_set_voltage_time_sel, |
156 | .set_ramp_delay = regulator_set_ramp_delay_regmap, |
157 | }; |
158 | |
159 | static const struct regulator_ops bd71828_ldo_ops = { |
160 | .enable = regulator_enable_regmap, |
161 | .disable = regulator_disable_regmap, |
162 | .is_enabled = regulator_is_enabled_regmap, |
163 | .list_voltage = regulator_list_voltage_linear_range, |
164 | .set_voltage_sel = regulator_set_voltage_sel_regmap, |
165 | .get_voltage_sel = regulator_get_voltage_sel_regmap, |
166 | }; |
167 | |
168 | static const struct regulator_ops bd71828_ldo6_ops = { |
169 | .enable = regulator_enable_regmap, |
170 | .disable = regulator_disable_regmap, |
171 | .is_enabled = regulator_is_enabled_regmap, |
172 | }; |
173 | |
174 | static const struct bd71828_regulator_data bd71828_rdata[] = { |
175 | { |
176 | .desc = { |
177 | .name = "buck1" , |
178 | .of_match = of_match_ptr("BUCK1" ), |
179 | .regulators_node = of_match_ptr("regulators" ), |
180 | .id = BD71828_BUCK1, |
181 | .ops = &bd71828_dvs_buck_ops, |
182 | .type = REGULATOR_VOLTAGE, |
183 | .linear_ranges = bd71828_buck1267_volts, |
184 | .n_linear_ranges = ARRAY_SIZE(bd71828_buck1267_volts), |
185 | .n_voltages = BD71828_BUCK1267_VOLTS, |
186 | .enable_reg = BD71828_REG_BUCK1_EN, |
187 | .enable_mask = BD71828_MASK_RUN_EN, |
188 | .vsel_reg = BD71828_REG_BUCK1_VOLT, |
189 | .vsel_mask = BD71828_MASK_BUCK1267_VOLT, |
190 | .ramp_delay_table = bd71828_ramp_delay, |
191 | .n_ramp_values = ARRAY_SIZE(bd71828_ramp_delay), |
192 | .ramp_reg = BD71828_REG_BUCK1_MODE, |
193 | .ramp_mask = BD71828_MASK_RAMP_DELAY, |
194 | .owner = THIS_MODULE, |
195 | .of_parse_cb = buck_set_hw_dvs_levels, |
196 | }, |
197 | .dvs = { |
198 | .level_map = ROHM_DVS_LEVEL_RUN | ROHM_DVS_LEVEL_IDLE | |
199 | ROHM_DVS_LEVEL_SUSPEND | |
200 | ROHM_DVS_LEVEL_LPSR, |
201 | .run_reg = BD71828_REG_BUCK1_VOLT, |
202 | .run_mask = BD71828_MASK_BUCK1267_VOLT, |
203 | .idle_reg = BD71828_REG_BUCK1_IDLE_VOLT, |
204 | .idle_mask = BD71828_MASK_BUCK1267_VOLT, |
205 | .idle_on_mask = BD71828_MASK_IDLE_EN, |
206 | .suspend_reg = BD71828_REG_BUCK1_SUSP_VOLT, |
207 | .suspend_mask = BD71828_MASK_BUCK1267_VOLT, |
208 | .suspend_on_mask = BD71828_MASK_SUSP_EN, |
209 | .lpsr_on_mask = BD71828_MASK_LPSR_EN, |
210 | /* |
211 | * LPSR voltage is same as SUSPEND voltage. Allow |
212 | * setting it so that regulator can be set enabled at |
213 | * LPSR state |
214 | */ |
215 | .lpsr_reg = BD71828_REG_BUCK1_SUSP_VOLT, |
216 | .lpsr_mask = BD71828_MASK_BUCK1267_VOLT, |
217 | }, |
218 | .reg_inits = buck1_inits, |
219 | .reg_init_amnt = ARRAY_SIZE(buck1_inits), |
220 | }, |
221 | { |
222 | .desc = { |
223 | .name = "buck2" , |
224 | .of_match = of_match_ptr("BUCK2" ), |
225 | .regulators_node = of_match_ptr("regulators" ), |
226 | .id = BD71828_BUCK2, |
227 | .ops = &bd71828_dvs_buck_ops, |
228 | .type = REGULATOR_VOLTAGE, |
229 | .linear_ranges = bd71828_buck1267_volts, |
230 | .n_linear_ranges = ARRAY_SIZE(bd71828_buck1267_volts), |
231 | .n_voltages = BD71828_BUCK1267_VOLTS, |
232 | .enable_reg = BD71828_REG_BUCK2_EN, |
233 | .enable_mask = BD71828_MASK_RUN_EN, |
234 | .vsel_reg = BD71828_REG_BUCK2_VOLT, |
235 | .vsel_mask = BD71828_MASK_BUCK1267_VOLT, |
236 | .ramp_delay_table = bd71828_ramp_delay, |
237 | .n_ramp_values = ARRAY_SIZE(bd71828_ramp_delay), |
238 | .ramp_reg = BD71828_REG_BUCK2_MODE, |
239 | .ramp_mask = BD71828_MASK_RAMP_DELAY, |
240 | .owner = THIS_MODULE, |
241 | .of_parse_cb = buck_set_hw_dvs_levels, |
242 | }, |
243 | .dvs = { |
244 | .level_map = ROHM_DVS_LEVEL_RUN | ROHM_DVS_LEVEL_IDLE | |
245 | ROHM_DVS_LEVEL_SUSPEND | |
246 | ROHM_DVS_LEVEL_LPSR, |
247 | .run_reg = BD71828_REG_BUCK2_VOLT, |
248 | .run_mask = BD71828_MASK_BUCK1267_VOLT, |
249 | .idle_reg = BD71828_REG_BUCK2_IDLE_VOLT, |
250 | .idle_mask = BD71828_MASK_BUCK1267_VOLT, |
251 | .idle_on_mask = BD71828_MASK_IDLE_EN, |
252 | .suspend_reg = BD71828_REG_BUCK2_SUSP_VOLT, |
253 | .suspend_mask = BD71828_MASK_BUCK1267_VOLT, |
254 | .suspend_on_mask = BD71828_MASK_SUSP_EN, |
255 | .lpsr_on_mask = BD71828_MASK_LPSR_EN, |
256 | .lpsr_reg = BD71828_REG_BUCK2_SUSP_VOLT, |
257 | .lpsr_mask = BD71828_MASK_BUCK1267_VOLT, |
258 | }, |
259 | .reg_inits = buck2_inits, |
260 | .reg_init_amnt = ARRAY_SIZE(buck2_inits), |
261 | }, |
262 | { |
263 | .desc = { |
264 | .name = "buck3" , |
265 | .of_match = of_match_ptr("BUCK3" ), |
266 | .regulators_node = of_match_ptr("regulators" ), |
267 | .id = BD71828_BUCK3, |
268 | .ops = &bd71828_buck_ops, |
269 | .type = REGULATOR_VOLTAGE, |
270 | .linear_ranges = bd71828_buck3_volts, |
271 | .n_linear_ranges = ARRAY_SIZE(bd71828_buck3_volts), |
272 | .n_voltages = BD71828_BUCK3_VOLTS, |
273 | .enable_reg = BD71828_REG_BUCK3_EN, |
274 | .enable_mask = BD71828_MASK_RUN_EN, |
275 | .vsel_reg = BD71828_REG_BUCK3_VOLT, |
276 | .vsel_mask = BD71828_MASK_BUCK3_VOLT, |
277 | .owner = THIS_MODULE, |
278 | .of_parse_cb = buck_set_hw_dvs_levels, |
279 | }, |
280 | .dvs = { |
281 | /* |
282 | * BUCK3 only supports single voltage for all states. |
283 | * voltage can be individually enabled for each state |
284 | * though => allow setting all states to support |
285 | * enabling power rail on different states. |
286 | */ |
287 | .level_map = ROHM_DVS_LEVEL_RUN | ROHM_DVS_LEVEL_IDLE | |
288 | ROHM_DVS_LEVEL_SUSPEND | |
289 | ROHM_DVS_LEVEL_LPSR, |
290 | .run_reg = BD71828_REG_BUCK3_VOLT, |
291 | .idle_reg = BD71828_REG_BUCK3_VOLT, |
292 | .suspend_reg = BD71828_REG_BUCK3_VOLT, |
293 | .lpsr_reg = BD71828_REG_BUCK3_VOLT, |
294 | .run_mask = BD71828_MASK_BUCK3_VOLT, |
295 | .idle_mask = BD71828_MASK_BUCK3_VOLT, |
296 | .suspend_mask = BD71828_MASK_BUCK3_VOLT, |
297 | .lpsr_mask = BD71828_MASK_BUCK3_VOLT, |
298 | .idle_on_mask = BD71828_MASK_IDLE_EN, |
299 | .suspend_on_mask = BD71828_MASK_SUSP_EN, |
300 | .lpsr_on_mask = BD71828_MASK_LPSR_EN, |
301 | }, |
302 | }, |
303 | { |
304 | .desc = { |
305 | .name = "buck4" , |
306 | .of_match = of_match_ptr("BUCK4" ), |
307 | .regulators_node = of_match_ptr("regulators" ), |
308 | .id = BD71828_BUCK4, |
309 | .ops = &bd71828_buck_ops, |
310 | .type = REGULATOR_VOLTAGE, |
311 | .linear_ranges = bd71828_buck4_volts, |
312 | .n_linear_ranges = ARRAY_SIZE(bd71828_buck4_volts), |
313 | .n_voltages = BD71828_BUCK4_VOLTS, |
314 | .enable_reg = BD71828_REG_BUCK4_EN, |
315 | .enable_mask = BD71828_MASK_RUN_EN, |
316 | .vsel_reg = BD71828_REG_BUCK4_VOLT, |
317 | .vsel_mask = BD71828_MASK_BUCK4_VOLT, |
318 | .owner = THIS_MODULE, |
319 | .of_parse_cb = buck_set_hw_dvs_levels, |
320 | }, |
321 | .dvs = { |
322 | /* |
323 | * BUCK4 only supports single voltage for all states. |
324 | * voltage can be individually enabled for each state |
325 | * though => allow setting all states to support |
326 | * enabling power rail on different states. |
327 | */ |
328 | .level_map = ROHM_DVS_LEVEL_RUN | ROHM_DVS_LEVEL_IDLE | |
329 | ROHM_DVS_LEVEL_SUSPEND | |
330 | ROHM_DVS_LEVEL_LPSR, |
331 | .run_reg = BD71828_REG_BUCK4_VOLT, |
332 | .idle_reg = BD71828_REG_BUCK4_VOLT, |
333 | .suspend_reg = BD71828_REG_BUCK4_VOLT, |
334 | .lpsr_reg = BD71828_REG_BUCK4_VOLT, |
335 | .run_mask = BD71828_MASK_BUCK4_VOLT, |
336 | .idle_mask = BD71828_MASK_BUCK4_VOLT, |
337 | .suspend_mask = BD71828_MASK_BUCK4_VOLT, |
338 | .lpsr_mask = BD71828_MASK_BUCK4_VOLT, |
339 | .idle_on_mask = BD71828_MASK_IDLE_EN, |
340 | .suspend_on_mask = BD71828_MASK_SUSP_EN, |
341 | .lpsr_on_mask = BD71828_MASK_LPSR_EN, |
342 | }, |
343 | }, |
344 | { |
345 | .desc = { |
346 | .name = "buck5" , |
347 | .of_match = of_match_ptr("BUCK5" ), |
348 | .regulators_node = of_match_ptr("regulators" ), |
349 | .id = BD71828_BUCK5, |
350 | .ops = &bd71828_buck_ops, |
351 | .type = REGULATOR_VOLTAGE, |
352 | .linear_ranges = bd71828_buck5_volts, |
353 | .n_linear_ranges = ARRAY_SIZE(bd71828_buck5_volts), |
354 | .n_voltages = BD71828_BUCK5_VOLTS, |
355 | .enable_reg = BD71828_REG_BUCK5_EN, |
356 | .enable_mask = BD71828_MASK_RUN_EN, |
357 | .vsel_reg = BD71828_REG_BUCK5_VOLT, |
358 | .vsel_mask = BD71828_MASK_BUCK5_VOLT, |
359 | .owner = THIS_MODULE, |
360 | .of_parse_cb = buck_set_hw_dvs_levels, |
361 | }, |
362 | .dvs = { |
363 | /* |
364 | * BUCK5 only supports single voltage for all states. |
365 | * voltage can be individually enabled for each state |
366 | * though => allow setting all states to support |
367 | * enabling power rail on different states. |
368 | */ |
369 | .level_map = ROHM_DVS_LEVEL_RUN | ROHM_DVS_LEVEL_IDLE | |
370 | ROHM_DVS_LEVEL_SUSPEND | |
371 | ROHM_DVS_LEVEL_LPSR, |
372 | .run_reg = BD71828_REG_BUCK5_VOLT, |
373 | .idle_reg = BD71828_REG_BUCK5_VOLT, |
374 | .suspend_reg = BD71828_REG_BUCK5_VOLT, |
375 | .lpsr_reg = BD71828_REG_BUCK5_VOLT, |
376 | .run_mask = BD71828_MASK_BUCK5_VOLT, |
377 | .idle_mask = BD71828_MASK_BUCK5_VOLT, |
378 | .suspend_mask = BD71828_MASK_BUCK5_VOLT, |
379 | .lpsr_mask = BD71828_MASK_BUCK5_VOLT, |
380 | .idle_on_mask = BD71828_MASK_IDLE_EN, |
381 | .suspend_on_mask = BD71828_MASK_SUSP_EN, |
382 | .lpsr_on_mask = BD71828_MASK_LPSR_EN, |
383 | }, |
384 | }, |
385 | { |
386 | .desc = { |
387 | .name = "buck6" , |
388 | .of_match = of_match_ptr("BUCK6" ), |
389 | .regulators_node = of_match_ptr("regulators" ), |
390 | .id = BD71828_BUCK6, |
391 | .ops = &bd71828_dvs_buck_ops, |
392 | .type = REGULATOR_VOLTAGE, |
393 | .linear_ranges = bd71828_buck1267_volts, |
394 | .n_linear_ranges = ARRAY_SIZE(bd71828_buck1267_volts), |
395 | .n_voltages = BD71828_BUCK1267_VOLTS, |
396 | .enable_reg = BD71828_REG_BUCK6_EN, |
397 | .enable_mask = BD71828_MASK_RUN_EN, |
398 | .vsel_reg = BD71828_REG_BUCK6_VOLT, |
399 | .vsel_mask = BD71828_MASK_BUCK1267_VOLT, |
400 | .ramp_delay_table = bd71828_ramp_delay, |
401 | .n_ramp_values = ARRAY_SIZE(bd71828_ramp_delay), |
402 | .ramp_reg = BD71828_REG_BUCK6_MODE, |
403 | .ramp_mask = BD71828_MASK_RAMP_DELAY, |
404 | .owner = THIS_MODULE, |
405 | .of_parse_cb = buck_set_hw_dvs_levels, |
406 | }, |
407 | .dvs = { |
408 | .level_map = ROHM_DVS_LEVEL_RUN | ROHM_DVS_LEVEL_IDLE | |
409 | ROHM_DVS_LEVEL_SUSPEND | |
410 | ROHM_DVS_LEVEL_LPSR, |
411 | .run_reg = BD71828_REG_BUCK6_VOLT, |
412 | .run_mask = BD71828_MASK_BUCK1267_VOLT, |
413 | .idle_reg = BD71828_REG_BUCK6_IDLE_VOLT, |
414 | .idle_mask = BD71828_MASK_BUCK1267_VOLT, |
415 | .idle_on_mask = BD71828_MASK_IDLE_EN, |
416 | .suspend_reg = BD71828_REG_BUCK6_SUSP_VOLT, |
417 | .suspend_mask = BD71828_MASK_BUCK1267_VOLT, |
418 | .suspend_on_mask = BD71828_MASK_SUSP_EN, |
419 | .lpsr_on_mask = BD71828_MASK_LPSR_EN, |
420 | .lpsr_reg = BD71828_REG_BUCK6_SUSP_VOLT, |
421 | .lpsr_mask = BD71828_MASK_BUCK1267_VOLT, |
422 | }, |
423 | .reg_inits = buck6_inits, |
424 | .reg_init_amnt = ARRAY_SIZE(buck6_inits), |
425 | }, |
426 | { |
427 | .desc = { |
428 | .name = "buck7" , |
429 | .of_match = of_match_ptr("BUCK7" ), |
430 | .regulators_node = of_match_ptr("regulators" ), |
431 | .id = BD71828_BUCK7, |
432 | .ops = &bd71828_dvs_buck_ops, |
433 | .type = REGULATOR_VOLTAGE, |
434 | .linear_ranges = bd71828_buck1267_volts, |
435 | .n_linear_ranges = ARRAY_SIZE(bd71828_buck1267_volts), |
436 | .n_voltages = BD71828_BUCK1267_VOLTS, |
437 | .enable_reg = BD71828_REG_BUCK7_EN, |
438 | .enable_mask = BD71828_MASK_RUN_EN, |
439 | .vsel_reg = BD71828_REG_BUCK7_VOLT, |
440 | .vsel_mask = BD71828_MASK_BUCK1267_VOLT, |
441 | .ramp_delay_table = bd71828_ramp_delay, |
442 | .n_ramp_values = ARRAY_SIZE(bd71828_ramp_delay), |
443 | .ramp_reg = BD71828_REG_BUCK7_MODE, |
444 | .ramp_mask = BD71828_MASK_RAMP_DELAY, |
445 | .owner = THIS_MODULE, |
446 | .of_parse_cb = buck_set_hw_dvs_levels, |
447 | }, |
448 | .dvs = { |
449 | .level_map = ROHM_DVS_LEVEL_RUN | ROHM_DVS_LEVEL_IDLE | |
450 | ROHM_DVS_LEVEL_SUSPEND | |
451 | ROHM_DVS_LEVEL_LPSR, |
452 | .run_reg = BD71828_REG_BUCK7_VOLT, |
453 | .run_mask = BD71828_MASK_BUCK1267_VOLT, |
454 | .idle_reg = BD71828_REG_BUCK7_IDLE_VOLT, |
455 | .idle_mask = BD71828_MASK_BUCK1267_VOLT, |
456 | .idle_on_mask = BD71828_MASK_IDLE_EN, |
457 | .suspend_reg = BD71828_REG_BUCK7_SUSP_VOLT, |
458 | .suspend_mask = BD71828_MASK_BUCK1267_VOLT, |
459 | .suspend_on_mask = BD71828_MASK_SUSP_EN, |
460 | .lpsr_on_mask = BD71828_MASK_LPSR_EN, |
461 | .lpsr_reg = BD71828_REG_BUCK7_SUSP_VOLT, |
462 | .lpsr_mask = BD71828_MASK_BUCK1267_VOLT, |
463 | }, |
464 | .reg_inits = buck7_inits, |
465 | .reg_init_amnt = ARRAY_SIZE(buck7_inits), |
466 | }, |
467 | { |
468 | .desc = { |
469 | .name = "ldo1" , |
470 | .of_match = of_match_ptr("LDO1" ), |
471 | .regulators_node = of_match_ptr("regulators" ), |
472 | .id = BD71828_LDO1, |
473 | .ops = &bd71828_ldo_ops, |
474 | .type = REGULATOR_VOLTAGE, |
475 | .linear_ranges = bd71828_ldo_volts, |
476 | .n_linear_ranges = ARRAY_SIZE(bd71828_ldo_volts), |
477 | .n_voltages = BD71828_LDO_VOLTS, |
478 | .enable_reg = BD71828_REG_LDO1_EN, |
479 | .enable_mask = BD71828_MASK_RUN_EN, |
480 | .vsel_reg = BD71828_REG_LDO1_VOLT, |
481 | .vsel_mask = BD71828_MASK_LDO_VOLT, |
482 | .owner = THIS_MODULE, |
483 | .of_parse_cb = buck_set_hw_dvs_levels, |
484 | }, |
485 | .dvs = { |
486 | /* |
487 | * LDO1 only supports single voltage for all states. |
488 | * voltage can be individually enabled for each state |
489 | * though => allow setting all states to support |
490 | * enabling power rail on different states. |
491 | */ |
492 | .level_map = ROHM_DVS_LEVEL_RUN | ROHM_DVS_LEVEL_IDLE | |
493 | ROHM_DVS_LEVEL_SUSPEND | |
494 | ROHM_DVS_LEVEL_LPSR, |
495 | .run_reg = BD71828_REG_LDO1_VOLT, |
496 | .idle_reg = BD71828_REG_LDO1_VOLT, |
497 | .suspend_reg = BD71828_REG_LDO1_VOLT, |
498 | .lpsr_reg = BD71828_REG_LDO1_VOLT, |
499 | .run_mask = BD71828_MASK_LDO_VOLT, |
500 | .idle_mask = BD71828_MASK_LDO_VOLT, |
501 | .suspend_mask = BD71828_MASK_LDO_VOLT, |
502 | .lpsr_mask = BD71828_MASK_LDO_VOLT, |
503 | .idle_on_mask = BD71828_MASK_IDLE_EN, |
504 | .suspend_on_mask = BD71828_MASK_SUSP_EN, |
505 | .lpsr_on_mask = BD71828_MASK_LPSR_EN, |
506 | }, |
507 | }, { |
508 | .desc = { |
509 | .name = "ldo2" , |
510 | .of_match = of_match_ptr("LDO2" ), |
511 | .regulators_node = of_match_ptr("regulators" ), |
512 | .id = BD71828_LDO2, |
513 | .ops = &bd71828_ldo_ops, |
514 | .type = REGULATOR_VOLTAGE, |
515 | .linear_ranges = bd71828_ldo_volts, |
516 | .n_linear_ranges = ARRAY_SIZE(bd71828_ldo_volts), |
517 | .n_voltages = BD71828_LDO_VOLTS, |
518 | .enable_reg = BD71828_REG_LDO2_EN, |
519 | .enable_mask = BD71828_MASK_RUN_EN, |
520 | .vsel_reg = BD71828_REG_LDO2_VOLT, |
521 | .vsel_mask = BD71828_MASK_LDO_VOLT, |
522 | .owner = THIS_MODULE, |
523 | .of_parse_cb = buck_set_hw_dvs_levels, |
524 | }, |
525 | .dvs = { |
526 | /* |
527 | * LDO2 only supports single voltage for all states. |
528 | * voltage can be individually enabled for each state |
529 | * though => allow setting all states to support |
530 | * enabling power rail on different states. |
531 | */ |
532 | .level_map = ROHM_DVS_LEVEL_RUN | ROHM_DVS_LEVEL_IDLE | |
533 | ROHM_DVS_LEVEL_SUSPEND | |
534 | ROHM_DVS_LEVEL_LPSR, |
535 | .run_reg = BD71828_REG_LDO2_VOLT, |
536 | .idle_reg = BD71828_REG_LDO2_VOLT, |
537 | .suspend_reg = BD71828_REG_LDO2_VOLT, |
538 | .lpsr_reg = BD71828_REG_LDO2_VOLT, |
539 | .run_mask = BD71828_MASK_LDO_VOLT, |
540 | .idle_mask = BD71828_MASK_LDO_VOLT, |
541 | .suspend_mask = BD71828_MASK_LDO_VOLT, |
542 | .lpsr_mask = BD71828_MASK_LDO_VOLT, |
543 | .idle_on_mask = BD71828_MASK_IDLE_EN, |
544 | .suspend_on_mask = BD71828_MASK_SUSP_EN, |
545 | .lpsr_on_mask = BD71828_MASK_LPSR_EN, |
546 | }, |
547 | }, { |
548 | .desc = { |
549 | .name = "ldo3" , |
550 | .of_match = of_match_ptr("LDO3" ), |
551 | .regulators_node = of_match_ptr("regulators" ), |
552 | .id = BD71828_LDO3, |
553 | .ops = &bd71828_ldo_ops, |
554 | .type = REGULATOR_VOLTAGE, |
555 | .linear_ranges = bd71828_ldo_volts, |
556 | .n_linear_ranges = ARRAY_SIZE(bd71828_ldo_volts), |
557 | .n_voltages = BD71828_LDO_VOLTS, |
558 | .enable_reg = BD71828_REG_LDO3_EN, |
559 | .enable_mask = BD71828_MASK_RUN_EN, |
560 | .vsel_reg = BD71828_REG_LDO3_VOLT, |
561 | .vsel_mask = BD71828_MASK_LDO_VOLT, |
562 | .owner = THIS_MODULE, |
563 | .of_parse_cb = buck_set_hw_dvs_levels, |
564 | }, |
565 | .dvs = { |
566 | /* |
567 | * LDO3 only supports single voltage for all states. |
568 | * voltage can be individually enabled for each state |
569 | * though => allow setting all states to support |
570 | * enabling power rail on different states. |
571 | */ |
572 | .level_map = ROHM_DVS_LEVEL_RUN | ROHM_DVS_LEVEL_IDLE | |
573 | ROHM_DVS_LEVEL_SUSPEND | |
574 | ROHM_DVS_LEVEL_LPSR, |
575 | .run_reg = BD71828_REG_LDO3_VOLT, |
576 | .idle_reg = BD71828_REG_LDO3_VOLT, |
577 | .suspend_reg = BD71828_REG_LDO3_VOLT, |
578 | .lpsr_reg = BD71828_REG_LDO3_VOLT, |
579 | .run_mask = BD71828_MASK_LDO_VOLT, |
580 | .idle_mask = BD71828_MASK_LDO_VOLT, |
581 | .suspend_mask = BD71828_MASK_LDO_VOLT, |
582 | .lpsr_mask = BD71828_MASK_LDO_VOLT, |
583 | .idle_on_mask = BD71828_MASK_IDLE_EN, |
584 | .suspend_on_mask = BD71828_MASK_SUSP_EN, |
585 | .lpsr_on_mask = BD71828_MASK_LPSR_EN, |
586 | }, |
587 | |
588 | }, { |
589 | .desc = { |
590 | .name = "ldo4" , |
591 | .of_match = of_match_ptr("LDO4" ), |
592 | .regulators_node = of_match_ptr("regulators" ), |
593 | .id = BD71828_LDO4, |
594 | .ops = &bd71828_ldo_ops, |
595 | .type = REGULATOR_VOLTAGE, |
596 | .linear_ranges = bd71828_ldo_volts, |
597 | .n_linear_ranges = ARRAY_SIZE(bd71828_ldo_volts), |
598 | .n_voltages = BD71828_LDO_VOLTS, |
599 | .enable_reg = BD71828_REG_LDO4_EN, |
600 | .enable_mask = BD71828_MASK_RUN_EN, |
601 | .vsel_reg = BD71828_REG_LDO4_VOLT, |
602 | .vsel_mask = BD71828_MASK_LDO_VOLT, |
603 | .owner = THIS_MODULE, |
604 | .of_parse_cb = buck_set_hw_dvs_levels, |
605 | }, |
606 | .dvs = { |
607 | /* |
608 | * LDO1 only supports single voltage for all states. |
609 | * voltage can be individually enabled for each state |
610 | * though => allow setting all states to support |
611 | * enabling power rail on different states. |
612 | */ |
613 | .level_map = ROHM_DVS_LEVEL_RUN | ROHM_DVS_LEVEL_IDLE | |
614 | ROHM_DVS_LEVEL_SUSPEND | |
615 | ROHM_DVS_LEVEL_LPSR, |
616 | .run_reg = BD71828_REG_LDO4_VOLT, |
617 | .idle_reg = BD71828_REG_LDO4_VOLT, |
618 | .suspend_reg = BD71828_REG_LDO4_VOLT, |
619 | .lpsr_reg = BD71828_REG_LDO4_VOLT, |
620 | .run_mask = BD71828_MASK_LDO_VOLT, |
621 | .idle_mask = BD71828_MASK_LDO_VOLT, |
622 | .suspend_mask = BD71828_MASK_LDO_VOLT, |
623 | .lpsr_mask = BD71828_MASK_LDO_VOLT, |
624 | .idle_on_mask = BD71828_MASK_IDLE_EN, |
625 | .suspend_on_mask = BD71828_MASK_SUSP_EN, |
626 | .lpsr_on_mask = BD71828_MASK_LPSR_EN, |
627 | }, |
628 | }, { |
629 | .desc = { |
630 | .name = "ldo5" , |
631 | .of_match = of_match_ptr("LDO5" ), |
632 | .regulators_node = of_match_ptr("regulators" ), |
633 | .id = BD71828_LDO5, |
634 | .ops = &bd71828_ldo_ops, |
635 | .type = REGULATOR_VOLTAGE, |
636 | .linear_ranges = bd71828_ldo_volts, |
637 | .n_linear_ranges = ARRAY_SIZE(bd71828_ldo_volts), |
638 | .n_voltages = BD71828_LDO_VOLTS, |
639 | .enable_reg = BD71828_REG_LDO5_EN, |
640 | .enable_mask = BD71828_MASK_RUN_EN, |
641 | .vsel_reg = BD71828_REG_LDO5_VOLT, |
642 | .vsel_mask = BD71828_MASK_LDO_VOLT, |
643 | .of_parse_cb = buck_set_hw_dvs_levels, |
644 | .owner = THIS_MODULE, |
645 | }, |
646 | /* |
647 | * LDO5 is special. It can choose vsel settings to be configured |
648 | * from 2 different registers (by GPIO). |
649 | * |
650 | * This driver supports only configuration where |
651 | * BD71828_REG_LDO5_VOLT_L is used. |
652 | */ |
653 | .dvs = { |
654 | .level_map = ROHM_DVS_LEVEL_RUN | ROHM_DVS_LEVEL_IDLE | |
655 | ROHM_DVS_LEVEL_SUSPEND | |
656 | ROHM_DVS_LEVEL_LPSR, |
657 | .run_reg = BD71828_REG_LDO5_VOLT, |
658 | .idle_reg = BD71828_REG_LDO5_VOLT, |
659 | .suspend_reg = BD71828_REG_LDO5_VOLT, |
660 | .lpsr_reg = BD71828_REG_LDO5_VOLT, |
661 | .run_mask = BD71828_MASK_LDO_VOLT, |
662 | .idle_mask = BD71828_MASK_LDO_VOLT, |
663 | .suspend_mask = BD71828_MASK_LDO_VOLT, |
664 | .lpsr_mask = BD71828_MASK_LDO_VOLT, |
665 | .idle_on_mask = BD71828_MASK_IDLE_EN, |
666 | .suspend_on_mask = BD71828_MASK_SUSP_EN, |
667 | .lpsr_on_mask = BD71828_MASK_LPSR_EN, |
668 | }, |
669 | |
670 | }, { |
671 | .desc = { |
672 | .name = "ldo6" , |
673 | .of_match = of_match_ptr("LDO6" ), |
674 | .regulators_node = of_match_ptr("regulators" ), |
675 | .id = BD71828_LDO6, |
676 | .ops = &bd71828_ldo6_ops, |
677 | .type = REGULATOR_VOLTAGE, |
678 | .fixed_uV = BD71828_LDO_6_VOLTAGE, |
679 | .n_voltages = 1, |
680 | .enable_reg = BD71828_REG_LDO6_EN, |
681 | .enable_mask = BD71828_MASK_RUN_EN, |
682 | .owner = THIS_MODULE, |
683 | /* |
684 | * LDO6 only supports enable/disable for all states. |
685 | * Voltage for LDO6 is fixed. |
686 | */ |
687 | .of_parse_cb = ldo6_parse_dt, |
688 | }, |
689 | }, { |
690 | .desc = { |
691 | /* SNVS LDO in data-sheet */ |
692 | .name = "ldo7" , |
693 | .of_match = of_match_ptr("LDO7" ), |
694 | .regulators_node = of_match_ptr("regulators" ), |
695 | .id = BD71828_LDO_SNVS, |
696 | .ops = &bd71828_ldo_ops, |
697 | .type = REGULATOR_VOLTAGE, |
698 | .linear_ranges = bd71828_ldo_volts, |
699 | .n_linear_ranges = ARRAY_SIZE(bd71828_ldo_volts), |
700 | .n_voltages = BD71828_LDO_VOLTS, |
701 | .enable_reg = BD71828_REG_LDO7_EN, |
702 | .enable_mask = BD71828_MASK_RUN_EN, |
703 | .vsel_reg = BD71828_REG_LDO7_VOLT, |
704 | .vsel_mask = BD71828_MASK_LDO_VOLT, |
705 | .owner = THIS_MODULE, |
706 | .of_parse_cb = buck_set_hw_dvs_levels, |
707 | }, |
708 | .dvs = { |
709 | /* |
710 | * LDO7 only supports single voltage for all states. |
711 | * voltage can be individually enabled for each state |
712 | * though => allow setting all states to support |
713 | * enabling power rail on different states. |
714 | */ |
715 | .level_map = ROHM_DVS_LEVEL_RUN | ROHM_DVS_LEVEL_IDLE | |
716 | ROHM_DVS_LEVEL_SUSPEND | |
717 | ROHM_DVS_LEVEL_LPSR, |
718 | .run_reg = BD71828_REG_LDO7_VOLT, |
719 | .idle_reg = BD71828_REG_LDO7_VOLT, |
720 | .suspend_reg = BD71828_REG_LDO7_VOLT, |
721 | .lpsr_reg = BD71828_REG_LDO7_VOLT, |
722 | .run_mask = BD71828_MASK_LDO_VOLT, |
723 | .idle_mask = BD71828_MASK_LDO_VOLT, |
724 | .suspend_mask = BD71828_MASK_LDO_VOLT, |
725 | .lpsr_mask = BD71828_MASK_LDO_VOLT, |
726 | .idle_on_mask = BD71828_MASK_IDLE_EN, |
727 | .suspend_on_mask = BD71828_MASK_SUSP_EN, |
728 | .lpsr_on_mask = BD71828_MASK_LPSR_EN, |
729 | }, |
730 | |
731 | }, |
732 | }; |
733 | |
734 | static int bd71828_probe(struct platform_device *pdev) |
735 | { |
736 | int i, j, ret; |
737 | struct regulator_config config = { |
738 | .dev = pdev->dev.parent, |
739 | }; |
740 | |
741 | config.regmap = dev_get_regmap(dev: pdev->dev.parent, NULL); |
742 | if (!config.regmap) |
743 | return -ENODEV; |
744 | |
745 | for (i = 0; i < ARRAY_SIZE(bd71828_rdata); i++) { |
746 | struct regulator_dev *rdev; |
747 | const struct bd71828_regulator_data *rd; |
748 | |
749 | rd = &bd71828_rdata[i]; |
750 | rdev = devm_regulator_register(dev: &pdev->dev, |
751 | regulator_desc: &rd->desc, config: &config); |
752 | if (IS_ERR(ptr: rdev)) |
753 | return dev_err_probe(dev: &pdev->dev, err: PTR_ERR(ptr: rdev), |
754 | fmt: "failed to register %s regulator\n" , |
755 | rd->desc.name); |
756 | |
757 | for (j = 0; j < rd->reg_init_amnt; j++) { |
758 | ret = regmap_update_bits(map: config.regmap, |
759 | reg: rd->reg_inits[j].reg, |
760 | mask: rd->reg_inits[j].mask, |
761 | val: rd->reg_inits[j].val); |
762 | if (ret) |
763 | return dev_err_probe(dev: &pdev->dev, err: ret, |
764 | fmt: "regulator %s init failed\n" , |
765 | rd->desc.name); |
766 | } |
767 | } |
768 | return 0; |
769 | } |
770 | |
771 | static struct platform_driver bd71828_regulator = { |
772 | .driver = { |
773 | .name = "bd71828-pmic" , |
774 | .probe_type = PROBE_PREFER_ASYNCHRONOUS, |
775 | }, |
776 | .probe = bd71828_probe, |
777 | }; |
778 | |
779 | module_platform_driver(bd71828_regulator); |
780 | |
781 | MODULE_AUTHOR("Matti Vaittinen <matti.vaittinen@fi.rohmeurope.com>" ); |
782 | MODULE_DESCRIPTION("BD71828 voltage regulator driver" ); |
783 | MODULE_LICENSE("GPL" ); |
784 | MODULE_ALIAS("platform:bd71828-pmic" ); |
785 | |