1 // SPDX-License-Identifier: GPL-2.0+
3 // pv88080-regulator.c - Regulator device driver for PV88080
4 // Copyright (C) 2016 Powerventure Semiconductor Ltd.
8 #include <linux/mod_devicetable.h>
9 #include <linux/module.h>
11 #include <linux/init.h>
12 #include <linux/slab.h>
13 #include <linux/regulator/driver.h>
14 #include <linux/regulator/machine.h>
15 #include <linux/regmap.h>
16 #include <linux/irq.h>
17 #include <linux/interrupt.h>
18 #include <linux/regulator/of_regulator.h>
19 #include "pv88080-regulator.h"
21 #define PV88080_MAX_REGULATORS 4
23 /* PV88080 REGULATOR IDs */
32 struct pv88080_regulator
{
33 struct regulator_desc desc
;
34 unsigned int mode_reg
;
41 struct regmap
*regmap
;
42 struct regulator_dev
*rdev
[PV88080_MAX_REGULATORS
];
44 const struct pv88080_compatible_regmap
*regmap_config
;
47 struct pv88080_buck_voltage
{
53 struct pv88080_buck_regmap
{
59 int buck_vdac_range_reg
;
60 int buck_vrange_gain_reg
;
67 struct pv88080_compatible_regmap
{
69 struct pv88080_buck_regmap buck_regmap
[PV88080_MAX_REGULATORS
-1];
71 int hvbuck_enable_reg
;
73 int hvbuck_enable_mask
;
77 static const struct regmap_config pv88080_regmap_config
= {
82 /* Current limits array (in uA) for BUCK1, BUCK2, BUCK3.
83 * Entry indexes corresponds to register values.
86 static const unsigned int pv88080_buck1_limits
[] = {
87 3230000, 5130000, 6960000, 8790000
90 static const unsigned int pv88080_buck23_limits
[] = {
91 1496000, 2393000, 3291000, 4189000
94 static const struct pv88080_buck_voltage pv88080_buck_vol
[2] = {
107 static const struct pv88080_compatible_regmap pv88080_aa_regs
= {
110 .buck_enable_reg
= PV88080AA_REG_BUCK1_CONF0
,
111 .buck_vsel_reg
= PV88080AA_REG_BUCK1_CONF0
,
112 .buck_mode_reg
= PV88080AA_REG_BUCK1_CONF1
,
113 .buck_limit_reg
= PV88080AA_REG_BUCK1_CONF1
,
114 .buck_vdac_range_reg
= PV88080AA_REG_BUCK1_CONF2
,
115 .buck_vrange_gain_reg
= PV88080AA_REG_BUCK1_CONF5
,
116 .buck_enable_mask
= PV88080_BUCK1_EN
,
117 .buck_vsel_mask
= PV88080_VBUCK1_MASK
,
118 .buck_limit_mask
= PV88080_BUCK1_ILIM_MASK
,
122 .buck_enable_reg
= PV88080AA_REG_BUCK2_CONF0
,
123 .buck_vsel_reg
= PV88080AA_REG_BUCK2_CONF0
,
124 .buck_mode_reg
= PV88080AA_REG_BUCK2_CONF1
,
125 .buck_limit_reg
= PV88080AA_REG_BUCK2_CONF1
,
126 .buck_vdac_range_reg
= PV88080AA_REG_BUCK2_CONF2
,
127 .buck_vrange_gain_reg
= PV88080AA_REG_BUCK2_CONF5
,
128 .buck_enable_mask
= PV88080_BUCK2_EN
,
129 .buck_vsel_mask
= PV88080_VBUCK2_MASK
,
130 .buck_limit_mask
= PV88080_BUCK2_ILIM_MASK
,
134 .buck_enable_reg
= PV88080AA_REG_BUCK3_CONF0
,
135 .buck_vsel_reg
= PV88080AA_REG_BUCK3_CONF0
,
136 .buck_mode_reg
= PV88080AA_REG_BUCK3_CONF1
,
137 .buck_limit_reg
= PV88080AA_REG_BUCK3_CONF1
,
138 .buck_vdac_range_reg
= PV88080AA_REG_BUCK3_CONF2
,
139 .buck_vrange_gain_reg
= PV88080AA_REG_BUCK3_CONF5
,
140 .buck_enable_mask
= PV88080_BUCK3_EN
,
141 .buck_vsel_mask
= PV88080_VBUCK3_MASK
,
142 .buck_limit_mask
= PV88080_BUCK3_ILIM_MASK
,
145 .hvbuck_enable_reg
= PV88080AA_REG_HVBUCK_CONF2
,
146 .hvbuck_vsel_reg
= PV88080AA_REG_HVBUCK_CONF1
,
147 .hvbuck_enable_mask
= PV88080_HVBUCK_EN
,
148 .hvbuck_vsel_mask
= PV88080_VHVBUCK_MASK
,
151 static const struct pv88080_compatible_regmap pv88080_ba_regs
= {
154 .buck_enable_reg
= PV88080BA_REG_BUCK1_CONF0
,
155 .buck_vsel_reg
= PV88080BA_REG_BUCK1_CONF0
,
156 .buck_mode_reg
= PV88080BA_REG_BUCK1_CONF1
,
157 .buck_limit_reg
= PV88080BA_REG_BUCK1_CONF1
,
158 .buck_vdac_range_reg
= PV88080BA_REG_BUCK1_CONF2
,
159 .buck_vrange_gain_reg
= PV88080BA_REG_BUCK1_CONF5
,
160 .buck_enable_mask
= PV88080_BUCK1_EN
,
161 .buck_vsel_mask
= PV88080_VBUCK1_MASK
,
162 .buck_limit_mask
= PV88080_BUCK1_ILIM_MASK
,
166 .buck_enable_reg
= PV88080BA_REG_BUCK2_CONF0
,
167 .buck_vsel_reg
= PV88080BA_REG_BUCK2_CONF0
,
168 .buck_mode_reg
= PV88080BA_REG_BUCK2_CONF1
,
169 .buck_limit_reg
= PV88080BA_REG_BUCK2_CONF1
,
170 .buck_vdac_range_reg
= PV88080BA_REG_BUCK2_CONF2
,
171 .buck_vrange_gain_reg
= PV88080BA_REG_BUCK2_CONF5
,
172 .buck_enable_mask
= PV88080_BUCK2_EN
,
173 .buck_vsel_mask
= PV88080_VBUCK2_MASK
,
174 .buck_limit_mask
= PV88080_BUCK2_ILIM_MASK
,
178 .buck_enable_reg
= PV88080BA_REG_BUCK3_CONF0
,
179 .buck_vsel_reg
= PV88080BA_REG_BUCK3_CONF0
,
180 .buck_mode_reg
= PV88080BA_REG_BUCK3_CONF1
,
181 .buck_limit_reg
= PV88080BA_REG_BUCK3_CONF1
,
182 .buck_vdac_range_reg
= PV88080BA_REG_BUCK3_CONF2
,
183 .buck_vrange_gain_reg
= PV88080BA_REG_BUCK3_CONF5
,
184 .buck_enable_mask
= PV88080_BUCK3_EN
,
185 .buck_vsel_mask
= PV88080_VBUCK3_MASK
,
186 .buck_limit_mask
= PV88080_BUCK3_ILIM_MASK
,
189 .hvbuck_enable_reg
= PV88080BA_REG_HVBUCK_CONF2
,
190 .hvbuck_vsel_reg
= PV88080BA_REG_HVBUCK_CONF1
,
191 .hvbuck_enable_mask
= PV88080_HVBUCK_EN
,
192 .hvbuck_vsel_mask
= PV88080_VHVBUCK_MASK
,
195 static unsigned int pv88080_buck_get_mode(struct regulator_dev
*rdev
)
197 struct pv88080_regulator
*info
= rdev_get_drvdata(rdev
);
201 ret
= regmap_read(rdev
->regmap
, info
->mode_reg
, &data
);
205 switch (data
& PV88080_BUCK1_MODE_MASK
) {
206 case PV88080_BUCK_MODE_SYNC
:
207 mode
= REGULATOR_MODE_FAST
;
209 case PV88080_BUCK_MODE_AUTO
:
210 mode
= REGULATOR_MODE_NORMAL
;
212 case PV88080_BUCK_MODE_SLEEP
:
213 mode
= REGULATOR_MODE_STANDBY
;
222 static int pv88080_buck_set_mode(struct regulator_dev
*rdev
,
225 struct pv88080_regulator
*info
= rdev_get_drvdata(rdev
);
229 case REGULATOR_MODE_FAST
:
230 val
= PV88080_BUCK_MODE_SYNC
;
232 case REGULATOR_MODE_NORMAL
:
233 val
= PV88080_BUCK_MODE_AUTO
;
235 case REGULATOR_MODE_STANDBY
:
236 val
= PV88080_BUCK_MODE_SLEEP
;
242 return regmap_update_bits(rdev
->regmap
, info
->mode_reg
,
243 PV88080_BUCK1_MODE_MASK
, val
);
246 static const struct regulator_ops pv88080_buck_ops
= {
247 .get_mode
= pv88080_buck_get_mode
,
248 .set_mode
= pv88080_buck_set_mode
,
249 .enable
= regulator_enable_regmap
,
250 .disable
= regulator_disable_regmap
,
251 .is_enabled
= regulator_is_enabled_regmap
,
252 .set_voltage_sel
= regulator_set_voltage_sel_regmap
,
253 .get_voltage_sel
= regulator_get_voltage_sel_regmap
,
254 .list_voltage
= regulator_list_voltage_linear
,
255 .set_current_limit
= regulator_set_current_limit_regmap
,
256 .get_current_limit
= regulator_get_current_limit_regmap
,
259 static const struct regulator_ops pv88080_hvbuck_ops
= {
260 .enable
= regulator_enable_regmap
,
261 .disable
= regulator_disable_regmap
,
262 .is_enabled
= regulator_is_enabled_regmap
,
263 .set_voltage_sel
= regulator_set_voltage_sel_regmap
,
264 .get_voltage_sel
= regulator_get_voltage_sel_regmap
,
265 .list_voltage
= regulator_list_voltage_linear
,
268 #define PV88080_BUCK(chip, regl_name, min, step, max, limits_array) \
271 .id = chip##_ID_##regl_name,\
272 .name = __stringify(chip##_##regl_name),\
273 .of_match = of_match_ptr(#regl_name),\
274 .regulators_node = of_match_ptr("regulators"),\
275 .type = REGULATOR_VOLTAGE,\
276 .owner = THIS_MODULE,\
277 .ops = &pv88080_buck_ops,\
280 .n_voltages = ((max) - (min))/(step) + 1, \
281 .curr_table = limits_array, \
282 .n_current_limits = ARRAY_SIZE(limits_array), \
286 #define PV88080_HVBUCK(chip, regl_name, min, step, max) \
289 .id = chip##_ID_##regl_name,\
290 .name = __stringify(chip##_##regl_name),\
291 .of_match = of_match_ptr(#regl_name),\
292 .regulators_node = of_match_ptr("regulators"),\
293 .type = REGULATOR_VOLTAGE,\
294 .owner = THIS_MODULE,\
295 .ops = &pv88080_hvbuck_ops,\
298 .n_voltages = ((max) - (min))/(step) + 1, \
302 static struct pv88080_regulator pv88080_regulator_info
[] = {
303 PV88080_BUCK(PV88080
, BUCK1
, 600000, 6250, 1393750,
304 pv88080_buck1_limits
),
305 PV88080_BUCK(PV88080
, BUCK2
, 600000, 6250, 1393750,
306 pv88080_buck23_limits
),
307 PV88080_BUCK(PV88080
, BUCK3
, 600000, 6250, 1393750,
308 pv88080_buck23_limits
),
309 PV88080_HVBUCK(PV88080
, HVBUCK
, 0, 5000, 1275000),
312 static irqreturn_t
pv88080_irq_handler(int irq
, void *data
)
314 struct pv88080
*chip
= data
;
315 int i
, reg_val
, err
, ret
= IRQ_NONE
;
317 err
= regmap_read(chip
->regmap
, PV88080_REG_EVENT_A
, ®_val
);
321 if (reg_val
& PV88080_E_VDD_FLT
) {
322 for (i
= 0; i
< PV88080_MAX_REGULATORS
; i
++) {
323 if (chip
->rdev
[i
] != NULL
)
324 regulator_notifier_call_chain(chip
->rdev
[i
],
325 REGULATOR_EVENT_UNDER_VOLTAGE
,
329 err
= regmap_write(chip
->regmap
, PV88080_REG_EVENT_A
,
337 if (reg_val
& PV88080_E_OVER_TEMP
) {
338 for (i
= 0; i
< PV88080_MAX_REGULATORS
; i
++) {
339 if (chip
->rdev
[i
] != NULL
)
340 regulator_notifier_call_chain(chip
->rdev
[i
],
341 REGULATOR_EVENT_OVER_TEMP
,
345 err
= regmap_write(chip
->regmap
, PV88080_REG_EVENT_A
,
346 PV88080_E_OVER_TEMP
);
356 dev_err(chip
->dev
, "I2C error : %d\n", err
);
361 * I2C driver interface functions
363 static int pv88080_i2c_probe(struct i2c_client
*i2c
)
365 struct regulator_init_data
*init_data
= dev_get_platdata(&i2c
->dev
);
366 struct pv88080
*chip
;
367 const struct pv88080_compatible_regmap
*regmap_config
;
368 struct regulator_config config
= { };
370 unsigned int conf2
, conf5
;
372 chip
= devm_kzalloc(&i2c
->dev
, sizeof(struct pv88080
), GFP_KERNEL
);
376 chip
->dev
= &i2c
->dev
;
377 chip
->regmap
= devm_regmap_init_i2c(i2c
, &pv88080_regmap_config
);
378 if (IS_ERR(chip
->regmap
)) {
379 error
= PTR_ERR(chip
->regmap
);
380 dev_err(chip
->dev
, "Failed to allocate register map: %d\n",
385 chip
->regmap_config
= i2c_get_match_data(i2c
);
386 if (!chip
->regmap_config
)
389 i2c_set_clientdata(i2c
, chip
);
392 ret
= regmap_write(chip
->regmap
, PV88080_REG_MASK_A
, 0xFF);
395 "Failed to mask A reg: %d\n", ret
);
398 ret
= regmap_write(chip
->regmap
, PV88080_REG_MASK_B
, 0xFF);
401 "Failed to mask B reg: %d\n", ret
);
404 ret
= regmap_write(chip
->regmap
, PV88080_REG_MASK_C
, 0xFF);
407 "Failed to mask C reg: %d\n", ret
);
411 ret
= devm_request_threaded_irq(&i2c
->dev
, i2c
->irq
, NULL
,
413 IRQF_TRIGGER_LOW
|IRQF_ONESHOT
,
416 dev_err(chip
->dev
, "Failed to request IRQ: %d\n",
421 ret
= regmap_update_bits(chip
->regmap
, PV88080_REG_MASK_A
,
422 PV88080_M_VDD_FLT
| PV88080_M_OVER_TEMP
, 0);
425 "Failed to update mask reg: %d\n", ret
);
429 dev_warn(chip
->dev
, "No IRQ configured\n");
432 regmap_config
= chip
->regmap_config
;
433 config
.dev
= chip
->dev
;
434 config
.regmap
= chip
->regmap
;
436 /* Registeration for BUCK1, 2, 3 */
437 for (i
= 0; i
< PV88080_MAX_REGULATORS
-1; i
++) {
439 config
.init_data
= &init_data
[i
];
441 pv88080_regulator_info
[i
].desc
.csel_reg
442 = regmap_config
->buck_regmap
[i
].buck_limit_reg
;
443 pv88080_regulator_info
[i
].desc
.csel_mask
444 = regmap_config
->buck_regmap
[i
].buck_limit_mask
;
445 pv88080_regulator_info
[i
].mode_reg
446 = regmap_config
->buck_regmap
[i
].buck_mode_reg
;
447 pv88080_regulator_info
[i
].conf2
448 = regmap_config
->buck_regmap
[i
].buck_vdac_range_reg
;
449 pv88080_regulator_info
[i
].conf5
450 = regmap_config
->buck_regmap
[i
].buck_vrange_gain_reg
;
451 pv88080_regulator_info
[i
].desc
.enable_reg
452 = regmap_config
->buck_regmap
[i
].buck_enable_reg
;
453 pv88080_regulator_info
[i
].desc
.enable_mask
454 = regmap_config
->buck_regmap
[i
].buck_enable_mask
;
455 pv88080_regulator_info
[i
].desc
.vsel_reg
456 = regmap_config
->buck_regmap
[i
].buck_vsel_reg
;
457 pv88080_regulator_info
[i
].desc
.vsel_mask
458 = regmap_config
->buck_regmap
[i
].buck_vsel_mask
;
460 ret
= regmap_read(chip
->regmap
,
461 pv88080_regulator_info
[i
].conf2
, &conf2
);
464 conf2
= ((conf2
>> PV88080_BUCK_VDAC_RANGE_SHIFT
) &
465 PV88080_BUCK_VDAC_RANGE_MASK
);
467 ret
= regmap_read(chip
->regmap
,
468 pv88080_regulator_info
[i
].conf5
, &conf5
);
471 conf5
= ((conf5
>> PV88080_BUCK_VRANGE_GAIN_SHIFT
) &
472 PV88080_BUCK_VRANGE_GAIN_MASK
);
474 pv88080_regulator_info
[i
].desc
.min_uV
=
475 pv88080_buck_vol
[conf2
].min_uV
* (conf5
+1);
476 pv88080_regulator_info
[i
].desc
.uV_step
=
477 pv88080_buck_vol
[conf2
].uV_step
* (conf5
+1);
478 pv88080_regulator_info
[i
].desc
.n_voltages
=
479 ((pv88080_buck_vol
[conf2
].max_uV
* (conf5
+1))
480 - (pv88080_regulator_info
[i
].desc
.min_uV
))
481 /(pv88080_regulator_info
[i
].desc
.uV_step
) + 1;
483 config
.driver_data
= (void *)&pv88080_regulator_info
[i
];
484 chip
->rdev
[i
] = devm_regulator_register(chip
->dev
,
485 &pv88080_regulator_info
[i
].desc
, &config
);
486 if (IS_ERR(chip
->rdev
[i
])) {
488 "Failed to register PV88080 regulator\n");
489 return PTR_ERR(chip
->rdev
[i
]);
493 pv88080_regulator_info
[PV88080_ID_HVBUCK
].desc
.enable_reg
494 = regmap_config
->hvbuck_enable_reg
;
495 pv88080_regulator_info
[PV88080_ID_HVBUCK
].desc
.enable_mask
496 = regmap_config
->hvbuck_enable_mask
;
497 pv88080_regulator_info
[PV88080_ID_HVBUCK
].desc
.vsel_reg
498 = regmap_config
->hvbuck_vsel_reg
;
499 pv88080_regulator_info
[PV88080_ID_HVBUCK
].desc
.vsel_mask
500 = regmap_config
->hvbuck_vsel_mask
;
502 /* Registeration for HVBUCK */
504 config
.init_data
= &init_data
[PV88080_ID_HVBUCK
];
506 config
.driver_data
= (void *)&pv88080_regulator_info
[PV88080_ID_HVBUCK
];
507 chip
->rdev
[PV88080_ID_HVBUCK
] = devm_regulator_register(chip
->dev
,
508 &pv88080_regulator_info
[PV88080_ID_HVBUCK
].desc
, &config
);
509 if (IS_ERR(chip
->rdev
[PV88080_ID_HVBUCK
])) {
510 dev_err(chip
->dev
, "Failed to register PV88080 regulator\n");
511 return PTR_ERR(chip
->rdev
[PV88080_ID_HVBUCK
]);
517 static const struct of_device_id pv88080_dt_ids
[] = {
518 { .compatible
= "pvs,pv88080", .data
= &pv88080_aa_regs
},
519 { .compatible
= "pvs,pv88080-aa", .data
= &pv88080_aa_regs
},
520 { .compatible
= "pvs,pv88080-ba", .data
= &pv88080_ba_regs
},
523 MODULE_DEVICE_TABLE(of
, pv88080_dt_ids
);
525 static const struct i2c_device_id pv88080_i2c_id
[] = {
526 { "pv88080", (kernel_ulong_t
)&pv88080_aa_regs
},
527 { "pv88080-aa", (kernel_ulong_t
)&pv88080_aa_regs
},
528 { "pv88080-ba", (kernel_ulong_t
)&pv88080_ba_regs
},
531 MODULE_DEVICE_TABLE(i2c
, pv88080_i2c_id
);
533 static struct i2c_driver pv88080_regulator_driver
= {
536 .probe_type
= PROBE_PREFER_ASYNCHRONOUS
,
537 .of_match_table
= pv88080_dt_ids
,
539 .probe
= pv88080_i2c_probe
,
540 .id_table
= pv88080_i2c_id
,
543 module_i2c_driver(pv88080_regulator_driver
);
545 MODULE_AUTHOR("James Ban <James.Ban.opensource@diasemi.com>");
546 MODULE_DESCRIPTION("Regulator device driver for Powerventure PV88080");
547 MODULE_LICENSE("GPL");