1 // SPDX-License-Identifier: GPL-2.0+
2 //
3 // pv88080-regulator.c - Regulator device driver for PV88080
4 // Copyright (C) 2016 Powerventure Semiconductor Ltd.
5
6 #include <linux/err.h>
7 #include <linux/i2c.h>
8 #include <linux/module.h>
9 #include <linux/of.h>
10 #include <linux/init.h>
11 #include <linux/slab.h>
12 #include <linux/regulator/driver.h>
13 #include <linux/regulator/machine.h>
14 #include <linux/regmap.h>
15 #include <linux/irq.h>
16 #include <linux/interrupt.h>
17 #include <linux/regulator/of_regulator.h>
18 #include "pv88080-regulator.h"
19
20 #define PV88080_MAX_REGULATORS 4
21
22 /* PV88080 REGULATOR IDs */
23 enum {
24 /* BUCKs */
25 PV88080_ID_BUCK1,
26 PV88080_ID_BUCK2,
27 PV88080_ID_BUCK3,
28 PV88080_ID_HVBUCK,
29 };
30
31 struct pv88080_regulator {
32 struct regulator_desc desc;
33 unsigned int mode_reg;
34 unsigned int conf2;
35 unsigned int conf5;
36 };
37
38 struct pv88080 {
39 struct device *dev;
40 struct regmap *regmap;
41 struct regulator_dev *rdev[PV88080_MAX_REGULATORS];
42 unsigned long type;
43 const struct pv88080_compatible_regmap *regmap_config;
44 };
45
46 struct pv88080_buck_voltage {
47 int min_uV;
48 int max_uV;
49 int uV_step;
50 };
51
52 struct pv88080_buck_regmap {
53 /* REGS */
54 int buck_enable_reg;
55 int buck_vsel_reg;
56 int buck_mode_reg;
57 int buck_limit_reg;
58 int buck_vdac_range_reg;
59 int buck_vrange_gain_reg;
60 /* MASKS */
61 int buck_enable_mask;
62 int buck_vsel_mask;
63 int buck_limit_mask;
64 };
65
66 struct pv88080_compatible_regmap {
67 /* BUCK1, 2, 3 */
68 struct pv88080_buck_regmap buck_regmap[PV88080_MAX_REGULATORS-1];
69 /* HVBUCK */
70 int hvbuck_enable_reg;
71 int hvbuck_vsel_reg;
72 int hvbuck_enable_mask;
73 int hvbuck_vsel_mask;
74 };
75
76 static const struct regmap_config pv88080_regmap_config = {
77 .reg_bits = 8,
78 .val_bits = 8,
79 };
80
81 /* Current limits array (in uA) for BUCK1, BUCK2, BUCK3.
82 * Entry indexes corresponds to register values.
83 */
84
85 static const unsigned int pv88080_buck1_limits[] = {
86 3230000, 5130000, 6960000, 8790000
87 };
88
89 static const unsigned int pv88080_buck23_limits[] = {
90 1496000, 2393000, 3291000, 4189000
91 };
92
93 static const struct pv88080_buck_voltage pv88080_buck_vol[2] = {
94 {
95 .min_uV = 600000,
96 .max_uV = 1393750,
97 .uV_step = 6250,
98 },
99 {
100 .min_uV = 1400000,
101 .max_uV = 2193750,
102 .uV_step = 6250,
103 },
104 };
105
106 static const struct pv88080_compatible_regmap pv88080_aa_regs = {
107 /* BUCK1 */
108 .buck_regmap[0] = {
109 .buck_enable_reg = PV88080AA_REG_BUCK1_CONF0,
110 .buck_vsel_reg = PV88080AA_REG_BUCK1_CONF0,
111 .buck_mode_reg = PV88080AA_REG_BUCK1_CONF1,
112 .buck_limit_reg = PV88080AA_REG_BUCK1_CONF1,
113 .buck_vdac_range_reg = PV88080AA_REG_BUCK1_CONF2,
114 .buck_vrange_gain_reg = PV88080AA_REG_BUCK1_CONF5,
115 .buck_enable_mask = PV88080_BUCK1_EN,
116 .buck_vsel_mask = PV88080_VBUCK1_MASK,
117 .buck_limit_mask = PV88080_BUCK1_ILIM_MASK,
118 },
119 /* BUCK2 */
120 .buck_regmap[1] = {
121 .buck_enable_reg = PV88080AA_REG_BUCK2_CONF0,
122 .buck_vsel_reg = PV88080AA_REG_BUCK2_CONF0,
123 .buck_mode_reg = PV88080AA_REG_BUCK2_CONF1,
124 .buck_limit_reg = PV88080AA_REG_BUCK2_CONF1,
125 .buck_vdac_range_reg = PV88080AA_REG_BUCK2_CONF2,
126 .buck_vrange_gain_reg = PV88080AA_REG_BUCK2_CONF5,
127 .buck_enable_mask = PV88080_BUCK2_EN,
128 .buck_vsel_mask = PV88080_VBUCK2_MASK,
129 .buck_limit_mask = PV88080_BUCK2_ILIM_MASK,
130 },
131 /* BUCK3 */
132 .buck_regmap[2] = {
133 .buck_enable_reg = PV88080AA_REG_BUCK3_CONF0,
134 .buck_vsel_reg = PV88080AA_REG_BUCK3_CONF0,
135 .buck_mode_reg = PV88080AA_REG_BUCK3_CONF1,
136 .buck_limit_reg = PV88080AA_REG_BUCK3_CONF1,
137 .buck_vdac_range_reg = PV88080AA_REG_BUCK3_CONF2,
138 .buck_vrange_gain_reg = PV88080AA_REG_BUCK3_CONF5,
139 .buck_enable_mask = PV88080_BUCK3_EN,
140 .buck_vsel_mask = PV88080_VBUCK3_MASK,
141 .buck_limit_mask = PV88080_BUCK3_ILIM_MASK,
142 },
143 /* HVBUCK */
144 .hvbuck_enable_reg = PV88080AA_REG_HVBUCK_CONF2,
145 .hvbuck_vsel_reg = PV88080AA_REG_HVBUCK_CONF1,
146 .hvbuck_enable_mask = PV88080_HVBUCK_EN,
147 .hvbuck_vsel_mask = PV88080_VHVBUCK_MASK,
148 };
149
150 static const struct pv88080_compatible_regmap pv88080_ba_regs = {
151 /* BUCK1 */
152 .buck_regmap[0] = {
153 .buck_enable_reg = PV88080BA_REG_BUCK1_CONF0,
154 .buck_vsel_reg = PV88080BA_REG_BUCK1_CONF0,
155 .buck_mode_reg = PV88080BA_REG_BUCK1_CONF1,
156 .buck_limit_reg = PV88080BA_REG_BUCK1_CONF1,
157 .buck_vdac_range_reg = PV88080BA_REG_BUCK1_CONF2,
158 .buck_vrange_gain_reg = PV88080BA_REG_BUCK1_CONF5,
159 .buck_enable_mask = PV88080_BUCK1_EN,
160 .buck_vsel_mask = PV88080_VBUCK1_MASK,
161 .buck_limit_mask = PV88080_BUCK1_ILIM_MASK,
162 },
163 /* BUCK2 */
164 .buck_regmap[1] = {
165 .buck_enable_reg = PV88080BA_REG_BUCK2_CONF0,
166 .buck_vsel_reg = PV88080BA_REG_BUCK2_CONF0,
167 .buck_mode_reg = PV88080BA_REG_BUCK2_CONF1,
168 .buck_limit_reg = PV88080BA_REG_BUCK2_CONF1,
169 .buck_vdac_range_reg = PV88080BA_REG_BUCK2_CONF2,
170 .buck_vrange_gain_reg = PV88080BA_REG_BUCK2_CONF5,
171 .buck_enable_mask = PV88080_BUCK2_EN,
172 .buck_vsel_mask = PV88080_VBUCK2_MASK,
173 .buck_limit_mask = PV88080_BUCK2_ILIM_MASK,
174 },
175 /* BUCK3 */
176 .buck_regmap[2] = {
177 .buck_enable_reg = PV88080BA_REG_BUCK3_CONF0,
178 .buck_vsel_reg = PV88080BA_REG_BUCK3_CONF0,
179 .buck_mode_reg = PV88080BA_REG_BUCK3_CONF1,
180 .buck_limit_reg = PV88080BA_REG_BUCK3_CONF1,
181 .buck_vdac_range_reg = PV88080BA_REG_BUCK3_CONF2,
182 .buck_vrange_gain_reg = PV88080BA_REG_BUCK3_CONF5,
183 .buck_enable_mask = PV88080_BUCK3_EN,
184 .buck_vsel_mask = PV88080_VBUCK3_MASK,
185 .buck_limit_mask = PV88080_BUCK3_ILIM_MASK,
186 },
187 /* HVBUCK */
188 .hvbuck_enable_reg = PV88080BA_REG_HVBUCK_CONF2,
189 .hvbuck_vsel_reg = PV88080BA_REG_HVBUCK_CONF1,
190 .hvbuck_enable_mask = PV88080_HVBUCK_EN,
191 .hvbuck_vsel_mask = PV88080_VHVBUCK_MASK,
192 };
193
pv88080_buck_get_mode(struct regulator_dev * rdev)194 static unsigned int pv88080_buck_get_mode(struct regulator_dev *rdev)
195 {
196 struct pv88080_regulator *info = rdev_get_drvdata(rdev);
197 unsigned int data;
198 int ret, mode = 0;
199
200 ret = regmap_read(rdev->regmap, info->mode_reg, &data);
201 if (ret < 0)
202 return ret;
203
204 switch (data & PV88080_BUCK1_MODE_MASK) {
205 case PV88080_BUCK_MODE_SYNC:
206 mode = REGULATOR_MODE_FAST;
207 break;
208 case PV88080_BUCK_MODE_AUTO:
209 mode = REGULATOR_MODE_NORMAL;
210 break;
211 case PV88080_BUCK_MODE_SLEEP:
212 mode = REGULATOR_MODE_STANDBY;
213 break;
214 default:
215 return -EINVAL;
216 }
217
218 return mode;
219 }
220
pv88080_buck_set_mode(struct regulator_dev * rdev,unsigned int mode)221 static int pv88080_buck_set_mode(struct regulator_dev *rdev,
222 unsigned int mode)
223 {
224 struct pv88080_regulator *info = rdev_get_drvdata(rdev);
225 int val = 0;
226
227 switch (mode) {
228 case REGULATOR_MODE_FAST:
229 val = PV88080_BUCK_MODE_SYNC;
230 break;
231 case REGULATOR_MODE_NORMAL:
232 val = PV88080_BUCK_MODE_AUTO;
233 break;
234 case REGULATOR_MODE_STANDBY:
235 val = PV88080_BUCK_MODE_SLEEP;
236 break;
237 default:
238 return -EINVAL;
239 }
240
241 return regmap_update_bits(rdev->regmap, info->mode_reg,
242 PV88080_BUCK1_MODE_MASK, val);
243 }
244
245 static const struct regulator_ops pv88080_buck_ops = {
246 .get_mode = pv88080_buck_get_mode,
247 .set_mode = pv88080_buck_set_mode,
248 .enable = regulator_enable_regmap,
249 .disable = regulator_disable_regmap,
250 .is_enabled = regulator_is_enabled_regmap,
251 .set_voltage_sel = regulator_set_voltage_sel_regmap,
252 .get_voltage_sel = regulator_get_voltage_sel_regmap,
253 .list_voltage = regulator_list_voltage_linear,
254 .set_current_limit = regulator_set_current_limit_regmap,
255 .get_current_limit = regulator_get_current_limit_regmap,
256 };
257
258 static const struct regulator_ops pv88080_hvbuck_ops = {
259 .enable = regulator_enable_regmap,
260 .disable = regulator_disable_regmap,
261 .is_enabled = regulator_is_enabled_regmap,
262 .set_voltage_sel = regulator_set_voltage_sel_regmap,
263 .get_voltage_sel = regulator_get_voltage_sel_regmap,
264 .list_voltage = regulator_list_voltage_linear,
265 };
266
267 #define PV88080_BUCK(chip, regl_name, min, step, max, limits_array) \
268 {\
269 .desc = {\
270 .id = chip##_ID_##regl_name,\
271 .name = __stringify(chip##_##regl_name),\
272 .of_match = of_match_ptr(#regl_name),\
273 .regulators_node = of_match_ptr("regulators"),\
274 .type = REGULATOR_VOLTAGE,\
275 .owner = THIS_MODULE,\
276 .ops = &pv88080_buck_ops,\
277 .min_uV = min, \
278 .uV_step = step, \
279 .n_voltages = ((max) - (min))/(step) + 1, \
280 .curr_table = limits_array, \
281 .n_current_limits = ARRAY_SIZE(limits_array), \
282 },\
283 }
284
285 #define PV88080_HVBUCK(chip, regl_name, min, step, max) \
286 {\
287 .desc = {\
288 .id = chip##_ID_##regl_name,\
289 .name = __stringify(chip##_##regl_name),\
290 .of_match = of_match_ptr(#regl_name),\
291 .regulators_node = of_match_ptr("regulators"),\
292 .type = REGULATOR_VOLTAGE,\
293 .owner = THIS_MODULE,\
294 .ops = &pv88080_hvbuck_ops,\
295 .min_uV = min, \
296 .uV_step = step, \
297 .n_voltages = ((max) - (min))/(step) + 1, \
298 },\
299 }
300
301 static struct pv88080_regulator pv88080_regulator_info[] = {
302 PV88080_BUCK(PV88080, BUCK1, 600000, 6250, 1393750,
303 pv88080_buck1_limits),
304 PV88080_BUCK(PV88080, BUCK2, 600000, 6250, 1393750,
305 pv88080_buck23_limits),
306 PV88080_BUCK(PV88080, BUCK3, 600000, 6250, 1393750,
307 pv88080_buck23_limits),
308 PV88080_HVBUCK(PV88080, HVBUCK, 0, 5000, 1275000),
309 };
310
pv88080_irq_handler(int irq,void * data)311 static irqreturn_t pv88080_irq_handler(int irq, void *data)
312 {
313 struct pv88080 *chip = data;
314 int i, reg_val, err, ret = IRQ_NONE;
315
316 err = regmap_read(chip->regmap, PV88080_REG_EVENT_A, ®_val);
317 if (err < 0)
318 goto error_i2c;
319
320 if (reg_val & PV88080_E_VDD_FLT) {
321 for (i = 0; i < PV88080_MAX_REGULATORS; i++) {
322 if (chip->rdev[i] != NULL)
323 regulator_notifier_call_chain(chip->rdev[i],
324 REGULATOR_EVENT_UNDER_VOLTAGE,
325 NULL);
326 }
327
328 err = regmap_write(chip->regmap, PV88080_REG_EVENT_A,
329 PV88080_E_VDD_FLT);
330 if (err < 0)
331 goto error_i2c;
332
333 ret = IRQ_HANDLED;
334 }
335
336 if (reg_val & PV88080_E_OVER_TEMP) {
337 for (i = 0; i < PV88080_MAX_REGULATORS; i++) {
338 if (chip->rdev[i] != NULL)
339 regulator_notifier_call_chain(chip->rdev[i],
340 REGULATOR_EVENT_OVER_TEMP,
341 NULL);
342 }
343
344 err = regmap_write(chip->regmap, PV88080_REG_EVENT_A,
345 PV88080_E_OVER_TEMP);
346 if (err < 0)
347 goto error_i2c;
348
349 ret = IRQ_HANDLED;
350 }
351
352 return ret;
353
354 error_i2c:
355 dev_err(chip->dev, "I2C error : %d\n", err);
356 return IRQ_NONE;
357 }
358
359 /*
360 * I2C driver interface functions
361 */
pv88080_i2c_probe(struct i2c_client * i2c)362 static int pv88080_i2c_probe(struct i2c_client *i2c)
363 {
364 struct regulator_init_data *init_data = dev_get_platdata(&i2c->dev);
365 struct pv88080 *chip;
366 const struct pv88080_compatible_regmap *regmap_config;
367 struct regulator_config config = { };
368 int i, error, ret;
369 unsigned int conf2, conf5;
370
371 chip = devm_kzalloc(&i2c->dev, sizeof(struct pv88080), GFP_KERNEL);
372 if (!chip)
373 return -ENOMEM;
374
375 chip->dev = &i2c->dev;
376 chip->regmap = devm_regmap_init_i2c(i2c, &pv88080_regmap_config);
377 if (IS_ERR(chip->regmap)) {
378 error = PTR_ERR(chip->regmap);
379 dev_err(chip->dev, "Failed to allocate register map: %d\n",
380 error);
381 return error;
382 }
383
384 chip->regmap_config = i2c_get_match_data(i2c);
385 if (!chip->regmap_config)
386 return -ENODEV;
387
388 i2c_set_clientdata(i2c, chip);
389
390 if (i2c->irq != 0) {
391 ret = regmap_write(chip->regmap, PV88080_REG_MASK_A, 0xFF);
392 if (ret < 0) {
393 dev_err(chip->dev,
394 "Failed to mask A reg: %d\n", ret);
395 return ret;
396 }
397 ret = regmap_write(chip->regmap, PV88080_REG_MASK_B, 0xFF);
398 if (ret < 0) {
399 dev_err(chip->dev,
400 "Failed to mask B reg: %d\n", ret);
401 return ret;
402 }
403 ret = regmap_write(chip->regmap, PV88080_REG_MASK_C, 0xFF);
404 if (ret < 0) {
405 dev_err(chip->dev,
406 "Failed to mask C reg: %d\n", ret);
407 return ret;
408 }
409
410 ret = devm_request_threaded_irq(&i2c->dev, i2c->irq, NULL,
411 pv88080_irq_handler,
412 IRQF_TRIGGER_LOW|IRQF_ONESHOT,
413 "pv88080", chip);
414 if (ret != 0) {
415 dev_err(chip->dev, "Failed to request IRQ: %d\n",
416 i2c->irq);
417 return ret;
418 }
419
420 ret = regmap_update_bits(chip->regmap, PV88080_REG_MASK_A,
421 PV88080_M_VDD_FLT | PV88080_M_OVER_TEMP, 0);
422 if (ret < 0) {
423 dev_err(chip->dev,
424 "Failed to update mask reg: %d\n", ret);
425 return ret;
426 }
427 } else {
428 dev_warn(chip->dev, "No IRQ configured\n");
429 }
430
431 regmap_config = chip->regmap_config;
432 config.dev = chip->dev;
433 config.regmap = chip->regmap;
434
435 /* Registeration for BUCK1, 2, 3 */
436 for (i = 0; i < PV88080_MAX_REGULATORS-1; i++) {
437 if (init_data)
438 config.init_data = &init_data[i];
439
440 pv88080_regulator_info[i].desc.csel_reg
441 = regmap_config->buck_regmap[i].buck_limit_reg;
442 pv88080_regulator_info[i].desc.csel_mask
443 = regmap_config->buck_regmap[i].buck_limit_mask;
444 pv88080_regulator_info[i].mode_reg
445 = regmap_config->buck_regmap[i].buck_mode_reg;
446 pv88080_regulator_info[i].conf2
447 = regmap_config->buck_regmap[i].buck_vdac_range_reg;
448 pv88080_regulator_info[i].conf5
449 = regmap_config->buck_regmap[i].buck_vrange_gain_reg;
450 pv88080_regulator_info[i].desc.enable_reg
451 = regmap_config->buck_regmap[i].buck_enable_reg;
452 pv88080_regulator_info[i].desc.enable_mask
453 = regmap_config->buck_regmap[i].buck_enable_mask;
454 pv88080_regulator_info[i].desc.vsel_reg
455 = regmap_config->buck_regmap[i].buck_vsel_reg;
456 pv88080_regulator_info[i].desc.vsel_mask
457 = regmap_config->buck_regmap[i].buck_vsel_mask;
458
459 ret = regmap_read(chip->regmap,
460 pv88080_regulator_info[i].conf2, &conf2);
461 if (ret < 0)
462 return ret;
463 conf2 = ((conf2 >> PV88080_BUCK_VDAC_RANGE_SHIFT) &
464 PV88080_BUCK_VDAC_RANGE_MASK);
465
466 ret = regmap_read(chip->regmap,
467 pv88080_regulator_info[i].conf5, &conf5);
468 if (ret < 0)
469 return ret;
470 conf5 = ((conf5 >> PV88080_BUCK_VRANGE_GAIN_SHIFT) &
471 PV88080_BUCK_VRANGE_GAIN_MASK);
472
473 pv88080_regulator_info[i].desc.min_uV =
474 pv88080_buck_vol[conf2].min_uV * (conf5+1);
475 pv88080_regulator_info[i].desc.uV_step =
476 pv88080_buck_vol[conf2].uV_step * (conf5+1);
477 pv88080_regulator_info[i].desc.n_voltages =
478 ((pv88080_buck_vol[conf2].max_uV * (conf5+1))
479 - (pv88080_regulator_info[i].desc.min_uV))
480 /(pv88080_regulator_info[i].desc.uV_step) + 1;
481
482 config.driver_data = (void *)&pv88080_regulator_info[i];
483 chip->rdev[i] = devm_regulator_register(chip->dev,
484 &pv88080_regulator_info[i].desc, &config);
485 if (IS_ERR(chip->rdev[i])) {
486 dev_err(chip->dev,
487 "Failed to register PV88080 regulator\n");
488 return PTR_ERR(chip->rdev[i]);
489 }
490 }
491
492 pv88080_regulator_info[PV88080_ID_HVBUCK].desc.enable_reg
493 = regmap_config->hvbuck_enable_reg;
494 pv88080_regulator_info[PV88080_ID_HVBUCK].desc.enable_mask
495 = regmap_config->hvbuck_enable_mask;
496 pv88080_regulator_info[PV88080_ID_HVBUCK].desc.vsel_reg
497 = regmap_config->hvbuck_vsel_reg;
498 pv88080_regulator_info[PV88080_ID_HVBUCK].desc.vsel_mask
499 = regmap_config->hvbuck_vsel_mask;
500
501 /* Registeration for HVBUCK */
502 if (init_data)
503 config.init_data = &init_data[PV88080_ID_HVBUCK];
504
505 config.driver_data = (void *)&pv88080_regulator_info[PV88080_ID_HVBUCK];
506 chip->rdev[PV88080_ID_HVBUCK] = devm_regulator_register(chip->dev,
507 &pv88080_regulator_info[PV88080_ID_HVBUCK].desc, &config);
508 if (IS_ERR(chip->rdev[PV88080_ID_HVBUCK])) {
509 dev_err(chip->dev, "Failed to register PV88080 regulator\n");
510 return PTR_ERR(chip->rdev[PV88080_ID_HVBUCK]);
511 }
512
513 return 0;
514 }
515
516 static const struct of_device_id pv88080_dt_ids[] = {
517 { .compatible = "pvs,pv88080", .data = &pv88080_aa_regs },
518 { .compatible = "pvs,pv88080-aa", .data = &pv88080_aa_regs },
519 { .compatible = "pvs,pv88080-ba", .data = &pv88080_ba_regs },
520 {}
521 };
522 MODULE_DEVICE_TABLE(of, pv88080_dt_ids);
523
524 static const struct i2c_device_id pv88080_i2c_id[] = {
525 { .name = "pv88080", .driver_data = (kernel_ulong_t)&pv88080_aa_regs },
526 { .name = "pv88080-aa", .driver_data = (kernel_ulong_t)&pv88080_aa_regs },
527 { .name = "pv88080-ba", .driver_data = (kernel_ulong_t)&pv88080_ba_regs },
528 { }
529 };
530 MODULE_DEVICE_TABLE(i2c, pv88080_i2c_id);
531
532 static struct i2c_driver pv88080_regulator_driver = {
533 .driver = {
534 .name = "pv88080",
535 .probe_type = PROBE_PREFER_ASYNCHRONOUS,
536 .of_match_table = pv88080_dt_ids,
537 },
538 .probe = pv88080_i2c_probe,
539 .id_table = pv88080_i2c_id,
540 };
541
542 module_i2c_driver(pv88080_regulator_driver);
543
544 MODULE_AUTHOR("James Ban <James.Ban.opensource@diasemi.com>");
545 MODULE_DESCRIPTION("Regulator device driver for Powerventure PV88080");
546 MODULE_LICENSE("GPL");
547