1 | // SPDX-License-Identifier: GPL-2.0 |
2 | /* |
3 | * Copyright 2020 NXP. |
4 | * NXP PCA9450 pmic driver |
5 | */ |
6 | |
7 | #include <linux/err.h> |
8 | #include <linux/gpio/consumer.h> |
9 | #include <linux/i2c.h> |
10 | #include <linux/interrupt.h> |
11 | #include <linux/kernel.h> |
12 | #include <linux/module.h> |
13 | #include <linux/of.h> |
14 | #include <linux/platform_device.h> |
15 | #include <linux/regulator/driver.h> |
16 | #include <linux/regulator/machine.h> |
17 | #include <linux/regulator/of_regulator.h> |
18 | #include <linux/regulator/pca9450.h> |
19 | |
20 | struct pc9450_dvs_config { |
21 | unsigned int run_reg; /* dvs0 */ |
22 | unsigned int run_mask; |
23 | unsigned int standby_reg; /* dvs1 */ |
24 | unsigned int standby_mask; |
25 | }; |
26 | |
27 | struct pca9450_regulator_desc { |
28 | struct regulator_desc desc; |
29 | const struct pc9450_dvs_config dvs; |
30 | }; |
31 | |
32 | struct pca9450 { |
33 | struct device *dev; |
34 | struct regmap *regmap; |
35 | struct gpio_desc *sd_vsel_gpio; |
36 | enum pca9450_chip_type type; |
37 | unsigned int rcnt; |
38 | int irq; |
39 | }; |
40 | |
41 | static const struct regmap_range pca9450_status_range = { |
42 | .range_min = PCA9450_REG_INT1, |
43 | .range_max = PCA9450_REG_PWRON_STAT, |
44 | }; |
45 | |
46 | static const struct regmap_access_table pca9450_volatile_regs = { |
47 | .yes_ranges = &pca9450_status_range, |
48 | .n_yes_ranges = 1, |
49 | }; |
50 | |
51 | static const struct regmap_config pca9450_regmap_config = { |
52 | .reg_bits = 8, |
53 | .val_bits = 8, |
54 | .volatile_table = &pca9450_volatile_regs, |
55 | .max_register = PCA9450_MAX_REGISTER - 1, |
56 | .cache_type = REGCACHE_RBTREE, |
57 | }; |
58 | |
59 | /* |
60 | * BUCK1/2/3 |
61 | * BUCK1RAM[1:0] BUCK1 DVS ramp rate setting |
62 | * 00: 25mV/1usec |
63 | * 01: 25mV/2usec |
64 | * 10: 25mV/4usec |
65 | * 11: 25mV/8usec |
66 | */ |
67 | static const unsigned int pca9450_dvs_buck_ramp_table[] = { |
68 | 25000, 12500, 6250, 3125 |
69 | }; |
70 | |
71 | static const struct regulator_ops pca9450_dvs_buck_regulator_ops = { |
72 | .enable = regulator_enable_regmap, |
73 | .disable = regulator_disable_regmap, |
74 | .is_enabled = regulator_is_enabled_regmap, |
75 | .list_voltage = regulator_list_voltage_linear_range, |
76 | .set_voltage_sel = regulator_set_voltage_sel_regmap, |
77 | .get_voltage_sel = regulator_get_voltage_sel_regmap, |
78 | .set_voltage_time_sel = regulator_set_voltage_time_sel, |
79 | .set_ramp_delay = regulator_set_ramp_delay_regmap, |
80 | }; |
81 | |
82 | static const struct regulator_ops pca9450_buck_regulator_ops = { |
83 | .enable = regulator_enable_regmap, |
84 | .disable = regulator_disable_regmap, |
85 | .is_enabled = regulator_is_enabled_regmap, |
86 | .list_voltage = regulator_list_voltage_linear_range, |
87 | .set_voltage_sel = regulator_set_voltage_sel_regmap, |
88 | .get_voltage_sel = regulator_get_voltage_sel_regmap, |
89 | .set_voltage_time_sel = regulator_set_voltage_time_sel, |
90 | }; |
91 | |
92 | static const struct regulator_ops pca9450_ldo_regulator_ops = { |
93 | .enable = regulator_enable_regmap, |
94 | .disable = regulator_disable_regmap, |
95 | .is_enabled = regulator_is_enabled_regmap, |
96 | .list_voltage = regulator_list_voltage_linear_range, |
97 | .set_voltage_sel = regulator_set_voltage_sel_regmap, |
98 | .get_voltage_sel = regulator_get_voltage_sel_regmap, |
99 | }; |
100 | |
101 | /* |
102 | * BUCK1/2/3 |
103 | * 0.60 to 2.1875V (12.5mV step) |
104 | */ |
105 | static const struct linear_range pca9450_dvs_buck_volts[] = { |
106 | REGULATOR_LINEAR_RANGE(600000, 0x00, 0x7F, 12500), |
107 | }; |
108 | |
109 | /* |
110 | * BUCK4/5/6 |
111 | * 0.6V to 3.4V (25mV step) |
112 | */ |
113 | static const struct linear_range pca9450_buck_volts[] = { |
114 | REGULATOR_LINEAR_RANGE(600000, 0x00, 0x70, 25000), |
115 | REGULATOR_LINEAR_RANGE(3400000, 0x71, 0x7F, 0), |
116 | }; |
117 | |
118 | /* |
119 | * LDO1 |
120 | * 1.6 to 3.3V () |
121 | */ |
122 | static const struct linear_range pca9450_ldo1_volts[] = { |
123 | REGULATOR_LINEAR_RANGE(1600000, 0x00, 0x03, 100000), |
124 | REGULATOR_LINEAR_RANGE(3000000, 0x04, 0x07, 100000), |
125 | }; |
126 | |
127 | /* |
128 | * LDO2 |
129 | * 0.8 to 1.15V (50mV step) |
130 | */ |
131 | static const struct linear_range pca9450_ldo2_volts[] = { |
132 | REGULATOR_LINEAR_RANGE(800000, 0x00, 0x07, 50000), |
133 | }; |
134 | |
135 | /* |
136 | * LDO3/4 |
137 | * 0.8 to 3.3V (100mV step) |
138 | */ |
139 | static const struct linear_range pca9450_ldo34_volts[] = { |
140 | REGULATOR_LINEAR_RANGE(800000, 0x00, 0x19, 100000), |
141 | REGULATOR_LINEAR_RANGE(3300000, 0x1A, 0x1F, 0), |
142 | }; |
143 | |
144 | /* |
145 | * LDO5 |
146 | * 1.8 to 3.3V (100mV step) |
147 | */ |
148 | static const struct linear_range pca9450_ldo5_volts[] = { |
149 | REGULATOR_LINEAR_RANGE(1800000, 0x00, 0x0F, 100000), |
150 | }; |
151 | |
152 | static int buck_set_dvs(const struct regulator_desc *desc, |
153 | struct device_node *np, struct regmap *regmap, |
154 | char *prop, unsigned int reg, unsigned int mask) |
155 | { |
156 | int ret, i; |
157 | uint32_t uv; |
158 | |
159 | ret = of_property_read_u32(np, propname: prop, out_value: &uv); |
160 | if (ret == -EINVAL) |
161 | return 0; |
162 | else if (ret) |
163 | return ret; |
164 | |
165 | for (i = 0; i < desc->n_voltages; i++) { |
166 | ret = regulator_desc_list_voltage_linear_range(desc, selector: i); |
167 | if (ret < 0) |
168 | continue; |
169 | if (ret == uv) { |
170 | i <<= ffs(desc->vsel_mask) - 1; |
171 | ret = regmap_update_bits(map: regmap, reg, mask, val: i); |
172 | break; |
173 | } |
174 | } |
175 | |
176 | if (ret == 0) { |
177 | struct pca9450_regulator_desc *regulator = container_of(desc, |
178 | struct pca9450_regulator_desc, desc); |
179 | |
180 | /* Enable DVS control through PMIC_STBY_REQ for this BUCK */ |
181 | ret = regmap_update_bits(map: regmap, reg: regulator->desc.enable_reg, |
182 | BUCK1_DVS_CTRL, BUCK1_DVS_CTRL); |
183 | } |
184 | return ret; |
185 | } |
186 | |
187 | static int pca9450_set_dvs_levels(struct device_node *np, |
188 | const struct regulator_desc *desc, |
189 | struct regulator_config *cfg) |
190 | { |
191 | struct pca9450_regulator_desc *data = container_of(desc, |
192 | struct pca9450_regulator_desc, desc); |
193 | const struct pc9450_dvs_config *dvs = &data->dvs; |
194 | unsigned int reg, mask; |
195 | char *prop; |
196 | int i, ret = 0; |
197 | |
198 | for (i = 0; i < PCA9450_DVS_LEVEL_MAX; i++) { |
199 | switch (i) { |
200 | case PCA9450_DVS_LEVEL_RUN: |
201 | prop = "nxp,dvs-run-voltage" ; |
202 | reg = dvs->run_reg; |
203 | mask = dvs->run_mask; |
204 | break; |
205 | case PCA9450_DVS_LEVEL_STANDBY: |
206 | prop = "nxp,dvs-standby-voltage" ; |
207 | reg = dvs->standby_reg; |
208 | mask = dvs->standby_mask; |
209 | break; |
210 | default: |
211 | return -EINVAL; |
212 | } |
213 | |
214 | ret = buck_set_dvs(desc, np, regmap: cfg->regmap, prop, reg, mask); |
215 | if (ret) |
216 | break; |
217 | } |
218 | |
219 | return ret; |
220 | } |
221 | |
222 | static const struct pca9450_regulator_desc pca9450a_regulators[] = { |
223 | { |
224 | .desc = { |
225 | .name = "buck1" , |
226 | .of_match = of_match_ptr("BUCK1" ), |
227 | .regulators_node = of_match_ptr("regulators" ), |
228 | .id = PCA9450_BUCK1, |
229 | .ops = &pca9450_dvs_buck_regulator_ops, |
230 | .type = REGULATOR_VOLTAGE, |
231 | .n_voltages = PCA9450_BUCK1_VOLTAGE_NUM, |
232 | .linear_ranges = pca9450_dvs_buck_volts, |
233 | .n_linear_ranges = ARRAY_SIZE(pca9450_dvs_buck_volts), |
234 | .vsel_reg = PCA9450_REG_BUCK1OUT_DVS0, |
235 | .vsel_mask = BUCK1OUT_DVS0_MASK, |
236 | .enable_reg = PCA9450_REG_BUCK1CTRL, |
237 | .enable_mask = BUCK1_ENMODE_MASK, |
238 | .ramp_reg = PCA9450_REG_BUCK1CTRL, |
239 | .ramp_mask = BUCK1_RAMP_MASK, |
240 | .ramp_delay_table = pca9450_dvs_buck_ramp_table, |
241 | .n_ramp_values = ARRAY_SIZE(pca9450_dvs_buck_ramp_table), |
242 | .owner = THIS_MODULE, |
243 | .of_parse_cb = pca9450_set_dvs_levels, |
244 | }, |
245 | .dvs = { |
246 | .run_reg = PCA9450_REG_BUCK1OUT_DVS0, |
247 | .run_mask = BUCK1OUT_DVS0_MASK, |
248 | .standby_reg = PCA9450_REG_BUCK1OUT_DVS1, |
249 | .standby_mask = BUCK1OUT_DVS1_MASK, |
250 | }, |
251 | }, |
252 | { |
253 | .desc = { |
254 | .name = "buck2" , |
255 | .of_match = of_match_ptr("BUCK2" ), |
256 | .regulators_node = of_match_ptr("regulators" ), |
257 | .id = PCA9450_BUCK2, |
258 | .ops = &pca9450_dvs_buck_regulator_ops, |
259 | .type = REGULATOR_VOLTAGE, |
260 | .n_voltages = PCA9450_BUCK2_VOLTAGE_NUM, |
261 | .linear_ranges = pca9450_dvs_buck_volts, |
262 | .n_linear_ranges = ARRAY_SIZE(pca9450_dvs_buck_volts), |
263 | .vsel_reg = PCA9450_REG_BUCK2OUT_DVS0, |
264 | .vsel_mask = BUCK2OUT_DVS0_MASK, |
265 | .enable_reg = PCA9450_REG_BUCK2CTRL, |
266 | .enable_mask = BUCK2_ENMODE_MASK, |
267 | .ramp_reg = PCA9450_REG_BUCK2CTRL, |
268 | .ramp_mask = BUCK2_RAMP_MASK, |
269 | .ramp_delay_table = pca9450_dvs_buck_ramp_table, |
270 | .n_ramp_values = ARRAY_SIZE(pca9450_dvs_buck_ramp_table), |
271 | .owner = THIS_MODULE, |
272 | .of_parse_cb = pca9450_set_dvs_levels, |
273 | }, |
274 | .dvs = { |
275 | .run_reg = PCA9450_REG_BUCK2OUT_DVS0, |
276 | .run_mask = BUCK2OUT_DVS0_MASK, |
277 | .standby_reg = PCA9450_REG_BUCK2OUT_DVS1, |
278 | .standby_mask = BUCK2OUT_DVS1_MASK, |
279 | }, |
280 | }, |
281 | { |
282 | .desc = { |
283 | .name = "buck3" , |
284 | .of_match = of_match_ptr("BUCK3" ), |
285 | .regulators_node = of_match_ptr("regulators" ), |
286 | .id = PCA9450_BUCK3, |
287 | .ops = &pca9450_dvs_buck_regulator_ops, |
288 | .type = REGULATOR_VOLTAGE, |
289 | .n_voltages = PCA9450_BUCK3_VOLTAGE_NUM, |
290 | .linear_ranges = pca9450_dvs_buck_volts, |
291 | .n_linear_ranges = ARRAY_SIZE(pca9450_dvs_buck_volts), |
292 | .vsel_reg = PCA9450_REG_BUCK3OUT_DVS0, |
293 | .vsel_mask = BUCK3OUT_DVS0_MASK, |
294 | .enable_reg = PCA9450_REG_BUCK3CTRL, |
295 | .enable_mask = BUCK3_ENMODE_MASK, |
296 | .ramp_reg = PCA9450_REG_BUCK3CTRL, |
297 | .ramp_mask = BUCK3_RAMP_MASK, |
298 | .ramp_delay_table = pca9450_dvs_buck_ramp_table, |
299 | .n_ramp_values = ARRAY_SIZE(pca9450_dvs_buck_ramp_table), |
300 | .owner = THIS_MODULE, |
301 | .of_parse_cb = pca9450_set_dvs_levels, |
302 | }, |
303 | .dvs = { |
304 | .run_reg = PCA9450_REG_BUCK3OUT_DVS0, |
305 | .run_mask = BUCK3OUT_DVS0_MASK, |
306 | .standby_reg = PCA9450_REG_BUCK3OUT_DVS1, |
307 | .standby_mask = BUCK3OUT_DVS1_MASK, |
308 | }, |
309 | }, |
310 | { |
311 | .desc = { |
312 | .name = "buck4" , |
313 | .of_match = of_match_ptr("BUCK4" ), |
314 | .regulators_node = of_match_ptr("regulators" ), |
315 | .id = PCA9450_BUCK4, |
316 | .ops = &pca9450_buck_regulator_ops, |
317 | .type = REGULATOR_VOLTAGE, |
318 | .n_voltages = PCA9450_BUCK4_VOLTAGE_NUM, |
319 | .linear_ranges = pca9450_buck_volts, |
320 | .n_linear_ranges = ARRAY_SIZE(pca9450_buck_volts), |
321 | .vsel_reg = PCA9450_REG_BUCK4OUT, |
322 | .vsel_mask = BUCK4OUT_MASK, |
323 | .enable_reg = PCA9450_REG_BUCK4CTRL, |
324 | .enable_mask = BUCK4_ENMODE_MASK, |
325 | .owner = THIS_MODULE, |
326 | }, |
327 | }, |
328 | { |
329 | .desc = { |
330 | .name = "buck5" , |
331 | .of_match = of_match_ptr("BUCK5" ), |
332 | .regulators_node = of_match_ptr("regulators" ), |
333 | .id = PCA9450_BUCK5, |
334 | .ops = &pca9450_buck_regulator_ops, |
335 | .type = REGULATOR_VOLTAGE, |
336 | .n_voltages = PCA9450_BUCK5_VOLTAGE_NUM, |
337 | .linear_ranges = pca9450_buck_volts, |
338 | .n_linear_ranges = ARRAY_SIZE(pca9450_buck_volts), |
339 | .vsel_reg = PCA9450_REG_BUCK5OUT, |
340 | .vsel_mask = BUCK5OUT_MASK, |
341 | .enable_reg = PCA9450_REG_BUCK5CTRL, |
342 | .enable_mask = BUCK5_ENMODE_MASK, |
343 | .owner = THIS_MODULE, |
344 | }, |
345 | }, |
346 | { |
347 | .desc = { |
348 | .name = "buck6" , |
349 | .of_match = of_match_ptr("BUCK6" ), |
350 | .regulators_node = of_match_ptr("regulators" ), |
351 | .id = PCA9450_BUCK6, |
352 | .ops = &pca9450_buck_regulator_ops, |
353 | .type = REGULATOR_VOLTAGE, |
354 | .n_voltages = PCA9450_BUCK6_VOLTAGE_NUM, |
355 | .linear_ranges = pca9450_buck_volts, |
356 | .n_linear_ranges = ARRAY_SIZE(pca9450_buck_volts), |
357 | .vsel_reg = PCA9450_REG_BUCK6OUT, |
358 | .vsel_mask = BUCK6OUT_MASK, |
359 | .enable_reg = PCA9450_REG_BUCK6CTRL, |
360 | .enable_mask = BUCK6_ENMODE_MASK, |
361 | .owner = THIS_MODULE, |
362 | }, |
363 | }, |
364 | { |
365 | .desc = { |
366 | .name = "ldo1" , |
367 | .of_match = of_match_ptr("LDO1" ), |
368 | .regulators_node = of_match_ptr("regulators" ), |
369 | .id = PCA9450_LDO1, |
370 | .ops = &pca9450_ldo_regulator_ops, |
371 | .type = REGULATOR_VOLTAGE, |
372 | .n_voltages = PCA9450_LDO1_VOLTAGE_NUM, |
373 | .linear_ranges = pca9450_ldo1_volts, |
374 | .n_linear_ranges = ARRAY_SIZE(pca9450_ldo1_volts), |
375 | .vsel_reg = PCA9450_REG_LDO1CTRL, |
376 | .vsel_mask = LDO1OUT_MASK, |
377 | .enable_reg = PCA9450_REG_LDO1CTRL, |
378 | .enable_mask = LDO1_EN_MASK, |
379 | .owner = THIS_MODULE, |
380 | }, |
381 | }, |
382 | { |
383 | .desc = { |
384 | .name = "ldo2" , |
385 | .of_match = of_match_ptr("LDO2" ), |
386 | .regulators_node = of_match_ptr("regulators" ), |
387 | .id = PCA9450_LDO2, |
388 | .ops = &pca9450_ldo_regulator_ops, |
389 | .type = REGULATOR_VOLTAGE, |
390 | .n_voltages = PCA9450_LDO2_VOLTAGE_NUM, |
391 | .linear_ranges = pca9450_ldo2_volts, |
392 | .n_linear_ranges = ARRAY_SIZE(pca9450_ldo2_volts), |
393 | .vsel_reg = PCA9450_REG_LDO2CTRL, |
394 | .vsel_mask = LDO2OUT_MASK, |
395 | .enable_reg = PCA9450_REG_LDO2CTRL, |
396 | .enable_mask = LDO2_EN_MASK, |
397 | .owner = THIS_MODULE, |
398 | }, |
399 | }, |
400 | { |
401 | .desc = { |
402 | .name = "ldo3" , |
403 | .of_match = of_match_ptr("LDO3" ), |
404 | .regulators_node = of_match_ptr("regulators" ), |
405 | .id = PCA9450_LDO3, |
406 | .ops = &pca9450_ldo_regulator_ops, |
407 | .type = REGULATOR_VOLTAGE, |
408 | .n_voltages = PCA9450_LDO3_VOLTAGE_NUM, |
409 | .linear_ranges = pca9450_ldo34_volts, |
410 | .n_linear_ranges = ARRAY_SIZE(pca9450_ldo34_volts), |
411 | .vsel_reg = PCA9450_REG_LDO3CTRL, |
412 | .vsel_mask = LDO3OUT_MASK, |
413 | .enable_reg = PCA9450_REG_LDO3CTRL, |
414 | .enable_mask = LDO3_EN_MASK, |
415 | .owner = THIS_MODULE, |
416 | }, |
417 | }, |
418 | { |
419 | .desc = { |
420 | .name = "ldo4" , |
421 | .of_match = of_match_ptr("LDO4" ), |
422 | .regulators_node = of_match_ptr("regulators" ), |
423 | .id = PCA9450_LDO4, |
424 | .ops = &pca9450_ldo_regulator_ops, |
425 | .type = REGULATOR_VOLTAGE, |
426 | .n_voltages = PCA9450_LDO4_VOLTAGE_NUM, |
427 | .linear_ranges = pca9450_ldo34_volts, |
428 | .n_linear_ranges = ARRAY_SIZE(pca9450_ldo34_volts), |
429 | .vsel_reg = PCA9450_REG_LDO4CTRL, |
430 | .vsel_mask = LDO4OUT_MASK, |
431 | .enable_reg = PCA9450_REG_LDO4CTRL, |
432 | .enable_mask = LDO4_EN_MASK, |
433 | .owner = THIS_MODULE, |
434 | }, |
435 | }, |
436 | { |
437 | .desc = { |
438 | .name = "ldo5" , |
439 | .of_match = of_match_ptr("LDO5" ), |
440 | .regulators_node = of_match_ptr("regulators" ), |
441 | .id = PCA9450_LDO5, |
442 | .ops = &pca9450_ldo_regulator_ops, |
443 | .type = REGULATOR_VOLTAGE, |
444 | .n_voltages = PCA9450_LDO5_VOLTAGE_NUM, |
445 | .linear_ranges = pca9450_ldo5_volts, |
446 | .n_linear_ranges = ARRAY_SIZE(pca9450_ldo5_volts), |
447 | .vsel_reg = PCA9450_REG_LDO5CTRL_H, |
448 | .vsel_mask = LDO5HOUT_MASK, |
449 | .enable_reg = PCA9450_REG_LDO5CTRL_H, |
450 | .enable_mask = LDO5H_EN_MASK, |
451 | .owner = THIS_MODULE, |
452 | }, |
453 | }, |
454 | }; |
455 | |
456 | /* |
457 | * Buck3 removed on PCA9450B and connected with Buck1 internal for dual phase |
458 | * on PCA9450C as no Buck3. |
459 | */ |
460 | static const struct pca9450_regulator_desc pca9450bc_regulators[] = { |
461 | { |
462 | .desc = { |
463 | .name = "buck1" , |
464 | .of_match = of_match_ptr("BUCK1" ), |
465 | .regulators_node = of_match_ptr("regulators" ), |
466 | .id = PCA9450_BUCK1, |
467 | .ops = &pca9450_dvs_buck_regulator_ops, |
468 | .type = REGULATOR_VOLTAGE, |
469 | .n_voltages = PCA9450_BUCK1_VOLTAGE_NUM, |
470 | .linear_ranges = pca9450_dvs_buck_volts, |
471 | .n_linear_ranges = ARRAY_SIZE(pca9450_dvs_buck_volts), |
472 | .vsel_reg = PCA9450_REG_BUCK1OUT_DVS0, |
473 | .vsel_mask = BUCK1OUT_DVS0_MASK, |
474 | .enable_reg = PCA9450_REG_BUCK1CTRL, |
475 | .enable_mask = BUCK1_ENMODE_MASK, |
476 | .ramp_reg = PCA9450_REG_BUCK1CTRL, |
477 | .ramp_mask = BUCK1_RAMP_MASK, |
478 | .ramp_delay_table = pca9450_dvs_buck_ramp_table, |
479 | .n_ramp_values = ARRAY_SIZE(pca9450_dvs_buck_ramp_table), |
480 | .owner = THIS_MODULE, |
481 | .of_parse_cb = pca9450_set_dvs_levels, |
482 | }, |
483 | .dvs = { |
484 | .run_reg = PCA9450_REG_BUCK1OUT_DVS0, |
485 | .run_mask = BUCK1OUT_DVS0_MASK, |
486 | .standby_reg = PCA9450_REG_BUCK1OUT_DVS1, |
487 | .standby_mask = BUCK1OUT_DVS1_MASK, |
488 | }, |
489 | }, |
490 | { |
491 | .desc = { |
492 | .name = "buck2" , |
493 | .of_match = of_match_ptr("BUCK2" ), |
494 | .regulators_node = of_match_ptr("regulators" ), |
495 | .id = PCA9450_BUCK2, |
496 | .ops = &pca9450_dvs_buck_regulator_ops, |
497 | .type = REGULATOR_VOLTAGE, |
498 | .n_voltages = PCA9450_BUCK2_VOLTAGE_NUM, |
499 | .linear_ranges = pca9450_dvs_buck_volts, |
500 | .n_linear_ranges = ARRAY_SIZE(pca9450_dvs_buck_volts), |
501 | .vsel_reg = PCA9450_REG_BUCK2OUT_DVS0, |
502 | .vsel_mask = BUCK2OUT_DVS0_MASK, |
503 | .enable_reg = PCA9450_REG_BUCK2CTRL, |
504 | .enable_mask = BUCK2_ENMODE_MASK, |
505 | .ramp_reg = PCA9450_REG_BUCK2CTRL, |
506 | .ramp_mask = BUCK2_RAMP_MASK, |
507 | .ramp_delay_table = pca9450_dvs_buck_ramp_table, |
508 | .n_ramp_values = ARRAY_SIZE(pca9450_dvs_buck_ramp_table), |
509 | .owner = THIS_MODULE, |
510 | .of_parse_cb = pca9450_set_dvs_levels, |
511 | }, |
512 | .dvs = { |
513 | .run_reg = PCA9450_REG_BUCK2OUT_DVS0, |
514 | .run_mask = BUCK2OUT_DVS0_MASK, |
515 | .standby_reg = PCA9450_REG_BUCK2OUT_DVS1, |
516 | .standby_mask = BUCK2OUT_DVS1_MASK, |
517 | }, |
518 | }, |
519 | { |
520 | .desc = { |
521 | .name = "buck4" , |
522 | .of_match = of_match_ptr("BUCK4" ), |
523 | .regulators_node = of_match_ptr("regulators" ), |
524 | .id = PCA9450_BUCK4, |
525 | .ops = &pca9450_buck_regulator_ops, |
526 | .type = REGULATOR_VOLTAGE, |
527 | .n_voltages = PCA9450_BUCK4_VOLTAGE_NUM, |
528 | .linear_ranges = pca9450_buck_volts, |
529 | .n_linear_ranges = ARRAY_SIZE(pca9450_buck_volts), |
530 | .vsel_reg = PCA9450_REG_BUCK4OUT, |
531 | .vsel_mask = BUCK4OUT_MASK, |
532 | .enable_reg = PCA9450_REG_BUCK4CTRL, |
533 | .enable_mask = BUCK4_ENMODE_MASK, |
534 | .owner = THIS_MODULE, |
535 | }, |
536 | }, |
537 | { |
538 | .desc = { |
539 | .name = "buck5" , |
540 | .of_match = of_match_ptr("BUCK5" ), |
541 | .regulators_node = of_match_ptr("regulators" ), |
542 | .id = PCA9450_BUCK5, |
543 | .ops = &pca9450_buck_regulator_ops, |
544 | .type = REGULATOR_VOLTAGE, |
545 | .n_voltages = PCA9450_BUCK5_VOLTAGE_NUM, |
546 | .linear_ranges = pca9450_buck_volts, |
547 | .n_linear_ranges = ARRAY_SIZE(pca9450_buck_volts), |
548 | .vsel_reg = PCA9450_REG_BUCK5OUT, |
549 | .vsel_mask = BUCK5OUT_MASK, |
550 | .enable_reg = PCA9450_REG_BUCK5CTRL, |
551 | .enable_mask = BUCK5_ENMODE_MASK, |
552 | .owner = THIS_MODULE, |
553 | }, |
554 | }, |
555 | { |
556 | .desc = { |
557 | .name = "buck6" , |
558 | .of_match = of_match_ptr("BUCK6" ), |
559 | .regulators_node = of_match_ptr("regulators" ), |
560 | .id = PCA9450_BUCK6, |
561 | .ops = &pca9450_buck_regulator_ops, |
562 | .type = REGULATOR_VOLTAGE, |
563 | .n_voltages = PCA9450_BUCK6_VOLTAGE_NUM, |
564 | .linear_ranges = pca9450_buck_volts, |
565 | .n_linear_ranges = ARRAY_SIZE(pca9450_buck_volts), |
566 | .vsel_reg = PCA9450_REG_BUCK6OUT, |
567 | .vsel_mask = BUCK6OUT_MASK, |
568 | .enable_reg = PCA9450_REG_BUCK6CTRL, |
569 | .enable_mask = BUCK6_ENMODE_MASK, |
570 | .owner = THIS_MODULE, |
571 | }, |
572 | }, |
573 | { |
574 | .desc = { |
575 | .name = "ldo1" , |
576 | .of_match = of_match_ptr("LDO1" ), |
577 | .regulators_node = of_match_ptr("regulators" ), |
578 | .id = PCA9450_LDO1, |
579 | .ops = &pca9450_ldo_regulator_ops, |
580 | .type = REGULATOR_VOLTAGE, |
581 | .n_voltages = PCA9450_LDO1_VOLTAGE_NUM, |
582 | .linear_ranges = pca9450_ldo1_volts, |
583 | .n_linear_ranges = ARRAY_SIZE(pca9450_ldo1_volts), |
584 | .vsel_reg = PCA9450_REG_LDO1CTRL, |
585 | .vsel_mask = LDO1OUT_MASK, |
586 | .enable_reg = PCA9450_REG_LDO1CTRL, |
587 | .enable_mask = LDO1_EN_MASK, |
588 | .owner = THIS_MODULE, |
589 | }, |
590 | }, |
591 | { |
592 | .desc = { |
593 | .name = "ldo2" , |
594 | .of_match = of_match_ptr("LDO2" ), |
595 | .regulators_node = of_match_ptr("regulators" ), |
596 | .id = PCA9450_LDO2, |
597 | .ops = &pca9450_ldo_regulator_ops, |
598 | .type = REGULATOR_VOLTAGE, |
599 | .n_voltages = PCA9450_LDO2_VOLTAGE_NUM, |
600 | .linear_ranges = pca9450_ldo2_volts, |
601 | .n_linear_ranges = ARRAY_SIZE(pca9450_ldo2_volts), |
602 | .vsel_reg = PCA9450_REG_LDO2CTRL, |
603 | .vsel_mask = LDO2OUT_MASK, |
604 | .enable_reg = PCA9450_REG_LDO2CTRL, |
605 | .enable_mask = LDO2_EN_MASK, |
606 | .owner = THIS_MODULE, |
607 | }, |
608 | }, |
609 | { |
610 | .desc = { |
611 | .name = "ldo3" , |
612 | .of_match = of_match_ptr("LDO3" ), |
613 | .regulators_node = of_match_ptr("regulators" ), |
614 | .id = PCA9450_LDO3, |
615 | .ops = &pca9450_ldo_regulator_ops, |
616 | .type = REGULATOR_VOLTAGE, |
617 | .n_voltages = PCA9450_LDO3_VOLTAGE_NUM, |
618 | .linear_ranges = pca9450_ldo34_volts, |
619 | .n_linear_ranges = ARRAY_SIZE(pca9450_ldo34_volts), |
620 | .vsel_reg = PCA9450_REG_LDO3CTRL, |
621 | .vsel_mask = LDO3OUT_MASK, |
622 | .enable_reg = PCA9450_REG_LDO3CTRL, |
623 | .enable_mask = LDO3_EN_MASK, |
624 | .owner = THIS_MODULE, |
625 | }, |
626 | }, |
627 | { |
628 | .desc = { |
629 | .name = "ldo4" , |
630 | .of_match = of_match_ptr("LDO4" ), |
631 | .regulators_node = of_match_ptr("regulators" ), |
632 | .id = PCA9450_LDO4, |
633 | .ops = &pca9450_ldo_regulator_ops, |
634 | .type = REGULATOR_VOLTAGE, |
635 | .n_voltages = PCA9450_LDO4_VOLTAGE_NUM, |
636 | .linear_ranges = pca9450_ldo34_volts, |
637 | .n_linear_ranges = ARRAY_SIZE(pca9450_ldo34_volts), |
638 | .vsel_reg = PCA9450_REG_LDO4CTRL, |
639 | .vsel_mask = LDO4OUT_MASK, |
640 | .enable_reg = PCA9450_REG_LDO4CTRL, |
641 | .enable_mask = LDO4_EN_MASK, |
642 | .owner = THIS_MODULE, |
643 | }, |
644 | }, |
645 | { |
646 | .desc = { |
647 | .name = "ldo5" , |
648 | .of_match = of_match_ptr("LDO5" ), |
649 | .regulators_node = of_match_ptr("regulators" ), |
650 | .id = PCA9450_LDO5, |
651 | .ops = &pca9450_ldo_regulator_ops, |
652 | .type = REGULATOR_VOLTAGE, |
653 | .n_voltages = PCA9450_LDO5_VOLTAGE_NUM, |
654 | .linear_ranges = pca9450_ldo5_volts, |
655 | .n_linear_ranges = ARRAY_SIZE(pca9450_ldo5_volts), |
656 | .vsel_reg = PCA9450_REG_LDO5CTRL_H, |
657 | .vsel_mask = LDO5HOUT_MASK, |
658 | .enable_reg = PCA9450_REG_LDO5CTRL_H, |
659 | .enable_mask = LDO5H_EN_MASK, |
660 | .owner = THIS_MODULE, |
661 | }, |
662 | }, |
663 | }; |
664 | |
665 | static irqreturn_t pca9450_irq_handler(int irq, void *data) |
666 | { |
667 | struct pca9450 *pca9450 = data; |
668 | struct regmap *regmap = pca9450->regmap; |
669 | unsigned int status; |
670 | int ret; |
671 | |
672 | ret = regmap_read(map: regmap, reg: PCA9450_REG_INT1, val: &status); |
673 | if (ret < 0) { |
674 | dev_err(pca9450->dev, |
675 | "Failed to read INT1(%d)\n" , ret); |
676 | return IRQ_NONE; |
677 | } |
678 | |
679 | if (status & IRQ_PWRON) |
680 | dev_warn(pca9450->dev, "PWRON interrupt.\n" ); |
681 | |
682 | if (status & IRQ_WDOGB) |
683 | dev_warn(pca9450->dev, "WDOGB interrupt.\n" ); |
684 | |
685 | if (status & IRQ_VR_FLT1) |
686 | dev_warn(pca9450->dev, "VRFLT1 interrupt.\n" ); |
687 | |
688 | if (status & IRQ_VR_FLT2) |
689 | dev_warn(pca9450->dev, "VRFLT2 interrupt.\n" ); |
690 | |
691 | if (status & IRQ_LOWVSYS) |
692 | dev_warn(pca9450->dev, "LOWVSYS interrupt.\n" ); |
693 | |
694 | if (status & IRQ_THERM_105) |
695 | dev_warn(pca9450->dev, "IRQ_THERM_105 interrupt.\n" ); |
696 | |
697 | if (status & IRQ_THERM_125) |
698 | dev_warn(pca9450->dev, "IRQ_THERM_125 interrupt.\n" ); |
699 | |
700 | return IRQ_HANDLED; |
701 | } |
702 | |
703 | static int pca9450_i2c_probe(struct i2c_client *i2c) |
704 | { |
705 | enum pca9450_chip_type type = (unsigned int)(uintptr_t) |
706 | of_device_get_match_data(dev: &i2c->dev); |
707 | const struct pca9450_regulator_desc *regulator_desc; |
708 | struct regulator_config config = { }; |
709 | struct pca9450 *pca9450; |
710 | unsigned int device_id, i; |
711 | unsigned int reset_ctrl; |
712 | int ret; |
713 | |
714 | if (!i2c->irq) { |
715 | dev_err(&i2c->dev, "No IRQ configured?\n" ); |
716 | return -EINVAL; |
717 | } |
718 | |
719 | pca9450 = devm_kzalloc(dev: &i2c->dev, size: sizeof(struct pca9450), GFP_KERNEL); |
720 | if (!pca9450) |
721 | return -ENOMEM; |
722 | |
723 | switch (type) { |
724 | case PCA9450_TYPE_PCA9450A: |
725 | regulator_desc = pca9450a_regulators; |
726 | pca9450->rcnt = ARRAY_SIZE(pca9450a_regulators); |
727 | break; |
728 | case PCA9450_TYPE_PCA9450BC: |
729 | regulator_desc = pca9450bc_regulators; |
730 | pca9450->rcnt = ARRAY_SIZE(pca9450bc_regulators); |
731 | break; |
732 | default: |
733 | dev_err(&i2c->dev, "Unknown device type" ); |
734 | return -EINVAL; |
735 | } |
736 | |
737 | pca9450->irq = i2c->irq; |
738 | pca9450->type = type; |
739 | pca9450->dev = &i2c->dev; |
740 | |
741 | dev_set_drvdata(dev: &i2c->dev, data: pca9450); |
742 | |
743 | pca9450->regmap = devm_regmap_init_i2c(i2c, |
744 | &pca9450_regmap_config); |
745 | if (IS_ERR(ptr: pca9450->regmap)) { |
746 | dev_err(&i2c->dev, "regmap initialization failed\n" ); |
747 | return PTR_ERR(ptr: pca9450->regmap); |
748 | } |
749 | |
750 | ret = regmap_read(map: pca9450->regmap, reg: PCA9450_REG_DEV_ID, val: &device_id); |
751 | if (ret) { |
752 | dev_err(&i2c->dev, "Read device id error\n" ); |
753 | return ret; |
754 | } |
755 | |
756 | /* Check your board and dts for match the right pmic */ |
757 | if (((device_id >> 4) != 0x1 && type == PCA9450_TYPE_PCA9450A) || |
758 | ((device_id >> 4) != 0x3 && type == PCA9450_TYPE_PCA9450BC)) { |
759 | dev_err(&i2c->dev, "Device id(%x) mismatched\n" , |
760 | device_id >> 4); |
761 | return -EINVAL; |
762 | } |
763 | |
764 | for (i = 0; i < pca9450->rcnt; i++) { |
765 | const struct regulator_desc *desc; |
766 | struct regulator_dev *rdev; |
767 | const struct pca9450_regulator_desc *r; |
768 | |
769 | r = ®ulator_desc[i]; |
770 | desc = &r->desc; |
771 | |
772 | config.regmap = pca9450->regmap; |
773 | config.dev = pca9450->dev; |
774 | |
775 | rdev = devm_regulator_register(dev: pca9450->dev, regulator_desc: desc, config: &config); |
776 | if (IS_ERR(ptr: rdev)) { |
777 | ret = PTR_ERR(ptr: rdev); |
778 | dev_err(pca9450->dev, |
779 | "Failed to register regulator(%s): %d\n" , |
780 | desc->name, ret); |
781 | return ret; |
782 | } |
783 | } |
784 | |
785 | ret = devm_request_threaded_irq(dev: pca9450->dev, irq: pca9450->irq, NULL, |
786 | thread_fn: pca9450_irq_handler, |
787 | irqflags: (IRQF_TRIGGER_FALLING | IRQF_ONESHOT), |
788 | devname: "pca9450-irq" , dev_id: pca9450); |
789 | if (ret != 0) { |
790 | dev_err(pca9450->dev, "Failed to request IRQ: %d\n" , |
791 | pca9450->irq); |
792 | return ret; |
793 | } |
794 | /* Unmask all interrupt except PWRON/WDOG/RSVD */ |
795 | ret = regmap_update_bits(map: pca9450->regmap, reg: PCA9450_REG_INT1_MSK, |
796 | IRQ_VR_FLT1 | IRQ_VR_FLT2 | IRQ_LOWVSYS | |
797 | IRQ_THERM_105 | IRQ_THERM_125, |
798 | IRQ_PWRON | IRQ_WDOGB | IRQ_RSVD); |
799 | if (ret) { |
800 | dev_err(&i2c->dev, "Unmask irq error\n" ); |
801 | return ret; |
802 | } |
803 | |
804 | /* Clear PRESET_EN bit in BUCK123_DVS to use DVS registers */ |
805 | ret = regmap_clear_bits(map: pca9450->regmap, reg: PCA9450_REG_BUCK123_DVS, |
806 | BUCK123_PRESET_EN); |
807 | if (ret) { |
808 | dev_err(&i2c->dev, "Failed to clear PRESET_EN bit: %d\n" , ret); |
809 | return ret; |
810 | } |
811 | |
812 | if (of_property_read_bool(np: i2c->dev.of_node, propname: "nxp,wdog_b-warm-reset" )) |
813 | reset_ctrl = WDOG_B_CFG_WARM; |
814 | else |
815 | reset_ctrl = WDOG_B_CFG_COLD_LDO12; |
816 | |
817 | /* Set reset behavior on assertion of WDOG_B signal */ |
818 | ret = regmap_update_bits(map: pca9450->regmap, reg: PCA9450_REG_RESET_CTRL, |
819 | WDOG_B_CFG_MASK, val: reset_ctrl); |
820 | if (ret) { |
821 | dev_err(&i2c->dev, "Failed to set WDOG_B reset behavior\n" ); |
822 | return ret; |
823 | } |
824 | |
825 | if (of_property_read_bool(np: i2c->dev.of_node, propname: "nxp,i2c-lt-enable" )) { |
826 | /* Enable I2C Level Translator */ |
827 | ret = regmap_update_bits(map: pca9450->regmap, reg: PCA9450_REG_CONFIG2, |
828 | I2C_LT_MASK, I2C_LT_ON_STANDBY_RUN); |
829 | if (ret) { |
830 | dev_err(&i2c->dev, |
831 | "Failed to enable I2C level translator\n" ); |
832 | return ret; |
833 | } |
834 | } |
835 | |
836 | /* |
837 | * The driver uses the LDO5CTRL_H register to control the LDO5 regulator. |
838 | * This is only valid if the SD_VSEL input of the PMIC is high. Let's |
839 | * check if the pin is available as GPIO and set it to high. |
840 | */ |
841 | pca9450->sd_vsel_gpio = gpiod_get_optional(dev: pca9450->dev, con_id: "sd-vsel" , flags: GPIOD_OUT_HIGH); |
842 | |
843 | if (IS_ERR(ptr: pca9450->sd_vsel_gpio)) { |
844 | dev_err(&i2c->dev, "Failed to get SD_VSEL GPIO\n" ); |
845 | return PTR_ERR(ptr: pca9450->sd_vsel_gpio); |
846 | } |
847 | |
848 | dev_info(&i2c->dev, "%s probed.\n" , |
849 | type == PCA9450_TYPE_PCA9450A ? "pca9450a" : "pca9450bc" ); |
850 | |
851 | return 0; |
852 | } |
853 | |
854 | static const struct of_device_id pca9450_of_match[] = { |
855 | { |
856 | .compatible = "nxp,pca9450a" , |
857 | .data = (void *)PCA9450_TYPE_PCA9450A, |
858 | }, |
859 | { |
860 | .compatible = "nxp,pca9450b" , |
861 | .data = (void *)PCA9450_TYPE_PCA9450BC, |
862 | }, |
863 | { |
864 | .compatible = "nxp,pca9450c" , |
865 | .data = (void *)PCA9450_TYPE_PCA9450BC, |
866 | }, |
867 | { } |
868 | }; |
869 | MODULE_DEVICE_TABLE(of, pca9450_of_match); |
870 | |
871 | static struct i2c_driver pca9450_i2c_driver = { |
872 | .driver = { |
873 | .name = "nxp-pca9450" , |
874 | .probe_type = PROBE_PREFER_ASYNCHRONOUS, |
875 | .of_match_table = pca9450_of_match, |
876 | }, |
877 | .probe = pca9450_i2c_probe, |
878 | }; |
879 | |
880 | module_i2c_driver(pca9450_i2c_driver); |
881 | |
882 | MODULE_AUTHOR("Robin Gong <yibin.gong@nxp.com>" ); |
883 | MODULE_DESCRIPTION("NXP PCA9450 Power Management IC driver" ); |
884 | MODULE_LICENSE("GPL" ); |
885 | |