Skip to content

Commit 548d770

Browse files
martijndegouwbroonie
authored andcommitted
regulator: pca9450: Add support for mode operations
Make the PWM mode on the buck controllers configurable from devicetree. Some boards require forced PWM mode to keep the supply ripple within acceptable limits under light load conditions. Signed-off-by: Martijn de Gouw <[email protected]> Link: https://patch.msgid.link/20250525071823.819342-2-martijn.de.gouw@prodrive-technologies.com Signed-off-by: Mark Brown <[email protected]>
1 parent d7181a2 commit 548d770

File tree

1 file changed

+116
-4
lines changed

1 file changed

+116
-4
lines changed

drivers/regulator/pca9450-regulator.c

Lines changed: 116 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -17,12 +17,18 @@
1717
#include <linux/regulator/machine.h>
1818
#include <linux/regulator/of_regulator.h>
1919
#include <linux/regulator/pca9450.h>
20+
#include <dt-bindings/regulator/nxp,pca9450-regulator.h>
21+
22+
static unsigned int pca9450_buck_get_mode(struct regulator_dev *rdev);
23+
static int pca9450_buck_set_mode(struct regulator_dev *rdev, unsigned int mode);
2024

2125
struct pc9450_dvs_config {
2226
unsigned int run_reg; /* dvs0 */
2327
unsigned int run_mask;
2428
unsigned int standby_reg; /* dvs1 */
2529
unsigned int standby_mask;
30+
unsigned int mode_reg; /* ctrl */
31+
unsigned int mode_mask;
2632
};
2733

2834
struct pca9450_regulator_desc {
@@ -80,6 +86,8 @@ static const struct regulator_ops pca9450_dvs_buck_regulator_ops = {
8086
.get_voltage_sel = regulator_get_voltage_sel_regmap,
8187
.set_voltage_time_sel = regulator_set_voltage_time_sel,
8288
.set_ramp_delay = regulator_set_ramp_delay_regmap,
89+
.set_mode = pca9450_buck_set_mode,
90+
.get_mode = pca9450_buck_get_mode,
8391
};
8492

8593
static const struct regulator_ops pca9450_buck_regulator_ops = {
@@ -90,6 +98,8 @@ static const struct regulator_ops pca9450_buck_regulator_ops = {
9098
.set_voltage_sel = regulator_set_voltage_sel_regmap,
9199
.get_voltage_sel = regulator_get_voltage_sel_regmap,
92100
.set_voltage_time_sel = regulator_set_voltage_time_sel,
101+
.set_mode = pca9450_buck_set_mode,
102+
.get_mode = pca9450_buck_get_mode,
93103
};
94104

95105
static const struct regulator_ops pca9450_ldo_regulator_ops = {
@@ -285,7 +295,64 @@ static int pca9450_set_dvs_levels(struct device_node *np,
285295
return ret;
286296
}
287297

288-
static const struct pca9450_regulator_desc pca9450a_regulators[] = {
298+
static inline unsigned int pca9450_map_mode(unsigned int mode)
299+
{
300+
switch (mode) {
301+
case PCA9450_BUCK_MODE_AUTO:
302+
return REGULATOR_MODE_NORMAL;
303+
case PCA9450_BUCK_MODE_FORCE_PWM:
304+
return REGULATOR_MODE_FAST;
305+
default:
306+
return REGULATOR_MODE_INVALID;
307+
}
308+
}
309+
310+
static int pca9450_buck_set_mode(struct regulator_dev *rdev, unsigned int mode)
311+
{
312+
struct pca9450_regulator_desc *desc = container_of(rdev->desc,
313+
struct pca9450_regulator_desc, desc);
314+
const struct pc9450_dvs_config *dvs = &desc->dvs;
315+
int val;
316+
317+
switch (mode) {
318+
case REGULATOR_MODE_FAST:
319+
val = dvs->mode_mask;
320+
break;
321+
case REGULATOR_MODE_NORMAL:
322+
val = 0;
323+
break;
324+
default:
325+
return -EINVAL;
326+
}
327+
328+
dev_dbg(&rdev->dev, "pca9450 buck set_mode %#x, %#x, %#x\n",
329+
dvs->mode_reg, dvs->mode_mask, val);
330+
331+
return regmap_update_bits(rdev->regmap, dvs->mode_reg,
332+
dvs->mode_mask, val);
333+
}
334+
335+
static unsigned int pca9450_buck_get_mode(struct regulator_dev *rdev)
336+
{
337+
struct pca9450_regulator_desc *desc = container_of(rdev->desc,
338+
struct pca9450_regulator_desc, desc);
339+
const struct pc9450_dvs_config *dvs = &desc->dvs;
340+
int ret = 0, regval;
341+
342+
ret = regmap_read(rdev->regmap, dvs->mode_reg, &regval);
343+
if (ret != 0) {
344+
dev_err(&rdev->dev,
345+
"Failed to get pca9450 buck mode: %d\n", ret);
346+
return ret;
347+
}
348+
349+
if ((regval & dvs->mode_mask) == dvs->mode_mask)
350+
return REGULATOR_MODE_FAST;
351+
352+
return REGULATOR_MODE_NORMAL;
353+
}
354+
355+
static struct pca9450_regulator_desc pca9450a_regulators[] = {
289356
{
290357
.desc = {
291358
.name = "buck1",
@@ -308,12 +375,15 @@ static const struct pca9450_regulator_desc pca9450a_regulators[] = {
308375
.enable_val = BUCK_ENMODE_ONREQ,
309376
.owner = THIS_MODULE,
310377
.of_parse_cb = pca9450_set_dvs_levels,
378+
.of_map_mode = pca9450_map_mode,
311379
},
312380
.dvs = {
313381
.run_reg = PCA9450_REG_BUCK1OUT_DVS0,
314382
.run_mask = BUCK1OUT_DVS0_MASK,
315383
.standby_reg = PCA9450_REG_BUCK1OUT_DVS1,
316384
.standby_mask = BUCK1OUT_DVS1_MASK,
385+
.mode_reg = PCA9450_REG_BUCK1CTRL,
386+
.mode_mask = BUCK1_FPWM,
317387
},
318388
},
319389
{
@@ -338,12 +408,15 @@ static const struct pca9450_regulator_desc pca9450a_regulators[] = {
338408
.n_ramp_values = ARRAY_SIZE(pca9450_dvs_buck_ramp_table),
339409
.owner = THIS_MODULE,
340410
.of_parse_cb = pca9450_set_dvs_levels,
411+
.of_map_mode = pca9450_map_mode,
341412
},
342413
.dvs = {
343414
.run_reg = PCA9450_REG_BUCK2OUT_DVS0,
344415
.run_mask = BUCK2OUT_DVS0_MASK,
345416
.standby_reg = PCA9450_REG_BUCK2OUT_DVS1,
346417
.standby_mask = BUCK2OUT_DVS1_MASK,
418+
.mode_reg = PCA9450_REG_BUCK2CTRL,
419+
.mode_mask = BUCK2_FPWM,
347420
},
348421
},
349422
{
@@ -368,12 +441,15 @@ static const struct pca9450_regulator_desc pca9450a_regulators[] = {
368441
.n_ramp_values = ARRAY_SIZE(pca9450_dvs_buck_ramp_table),
369442
.owner = THIS_MODULE,
370443
.of_parse_cb = pca9450_set_dvs_levels,
444+
.of_map_mode = pca9450_map_mode,
371445
},
372446
.dvs = {
373447
.run_reg = PCA9450_REG_BUCK3OUT_DVS0,
374448
.run_mask = BUCK3OUT_DVS0_MASK,
375449
.standby_reg = PCA9450_REG_BUCK3OUT_DVS1,
376450
.standby_mask = BUCK3OUT_DVS1_MASK,
451+
.mode_reg = PCA9450_REG_BUCK3CTRL,
452+
.mode_mask = BUCK3_FPWM,
377453
},
378454
},
379455
{
@@ -393,6 +469,11 @@ static const struct pca9450_regulator_desc pca9450a_regulators[] = {
393469
.enable_mask = BUCK4_ENMODE_MASK,
394470
.enable_val = BUCK_ENMODE_ONREQ,
395471
.owner = THIS_MODULE,
472+
.of_map_mode = pca9450_map_mode,
473+
},
474+
.dvs = {
475+
.mode_reg = PCA9450_REG_BUCK4CTRL,
476+
.mode_mask = BUCK4_FPWM,
396477
},
397478
},
398479
{
@@ -412,6 +493,11 @@ static const struct pca9450_regulator_desc pca9450a_regulators[] = {
412493
.enable_mask = BUCK5_ENMODE_MASK,
413494
.enable_val = BUCK_ENMODE_ONREQ,
414495
.owner = THIS_MODULE,
496+
.of_map_mode = pca9450_map_mode,
497+
},
498+
.dvs = {
499+
.mode_reg = PCA9450_REG_BUCK5CTRL,
500+
.mode_mask = BUCK5_FPWM,
415501
},
416502
},
417503
{
@@ -431,6 +517,11 @@ static const struct pca9450_regulator_desc pca9450a_regulators[] = {
431517
.enable_mask = BUCK6_ENMODE_MASK,
432518
.enable_val = BUCK_ENMODE_ONREQ,
433519
.owner = THIS_MODULE,
520+
.of_map_mode = pca9450_map_mode,
521+
},
522+
.dvs = {
523+
.mode_reg = PCA9450_REG_BUCK6CTRL,
524+
.mode_mask = BUCK6_FPWM,
434525
},
435526
},
436527
{
@@ -529,7 +620,7 @@ static const struct pca9450_regulator_desc pca9450a_regulators[] = {
529620
* Buck3 removed on PCA9450B and connected with Buck1 internal for dual phase
530621
* on PCA9450C as no Buck3.
531622
*/
532-
static const struct pca9450_regulator_desc pca9450bc_regulators[] = {
623+
static struct pca9450_regulator_desc pca9450bc_regulators[] = {
533624
{
534625
.desc = {
535626
.name = "buck1",
@@ -552,12 +643,15 @@ static const struct pca9450_regulator_desc pca9450bc_regulators[] = {
552643
.n_ramp_values = ARRAY_SIZE(pca9450_dvs_buck_ramp_table),
553644
.owner = THIS_MODULE,
554645
.of_parse_cb = pca9450_set_dvs_levels,
646+
.of_map_mode = pca9450_map_mode,
555647
},
556648
.dvs = {
557649
.run_reg = PCA9450_REG_BUCK1OUT_DVS0,
558650
.run_mask = BUCK1OUT_DVS0_MASK,
559651
.standby_reg = PCA9450_REG_BUCK1OUT_DVS1,
560652
.standby_mask = BUCK1OUT_DVS1_MASK,
653+
.mode_reg = PCA9450_REG_BUCK1CTRL,
654+
.mode_mask = BUCK1_FPWM,
561655
},
562656
},
563657
{
@@ -582,12 +676,15 @@ static const struct pca9450_regulator_desc pca9450bc_regulators[] = {
582676
.n_ramp_values = ARRAY_SIZE(pca9450_dvs_buck_ramp_table),
583677
.owner = THIS_MODULE,
584678
.of_parse_cb = pca9450_set_dvs_levels,
679+
.of_map_mode = pca9450_map_mode,
585680
},
586681
.dvs = {
587682
.run_reg = PCA9450_REG_BUCK2OUT_DVS0,
588683
.run_mask = BUCK2OUT_DVS0_MASK,
589684
.standby_reg = PCA9450_REG_BUCK2OUT_DVS1,
590685
.standby_mask = BUCK2OUT_DVS1_MASK,
686+
.mode_reg = PCA9450_REG_BUCK2CTRL,
687+
.mode_mask = BUCK2_FPWM,
591688
},
592689
},
593690
{
@@ -607,6 +704,11 @@ static const struct pca9450_regulator_desc pca9450bc_regulators[] = {
607704
.enable_mask = BUCK4_ENMODE_MASK,
608705
.enable_val = BUCK_ENMODE_ONREQ,
609706
.owner = THIS_MODULE,
707+
.of_map_mode = pca9450_map_mode,
708+
},
709+
.dvs = {
710+
.mode_reg = PCA9450_REG_BUCK4CTRL,
711+
.mode_mask = BUCK4_FPWM,
610712
},
611713
},
612714
{
@@ -626,6 +728,11 @@ static const struct pca9450_regulator_desc pca9450bc_regulators[] = {
626728
.enable_mask = BUCK5_ENMODE_MASK,
627729
.enable_val = BUCK_ENMODE_ONREQ,
628730
.owner = THIS_MODULE,
731+
.of_map_mode = pca9450_map_mode,
732+
},
733+
.dvs = {
734+
.mode_reg = PCA9450_REG_BUCK5CTRL,
735+
.mode_mask = BUCK5_FPWM,
629736
},
630737
},
631738
{
@@ -645,6 +752,11 @@ static const struct pca9450_regulator_desc pca9450bc_regulators[] = {
645752
.enable_mask = BUCK6_ENMODE_MASK,
646753
.enable_val = BUCK_ENMODE_ONREQ,
647754
.owner = THIS_MODULE,
755+
.of_map_mode = pca9450_map_mode,
756+
},
757+
.dvs = {
758+
.mode_reg = PCA9450_REG_BUCK6CTRL,
759+
.mode_mask = BUCK6_FPWM,
648760
},
649761
},
650762
{
@@ -739,7 +851,7 @@ static const struct pca9450_regulator_desc pca9450bc_regulators[] = {
739851
},
740852
};
741853

742-
static const struct pca9450_regulator_desc pca9451a_regulators[] = {
854+
static struct pca9450_regulator_desc pca9451a_regulators[] = {
743855
{
744856
.desc = {
745857
.name = "buck1",
@@ -990,7 +1102,7 @@ static int pca9450_i2c_probe(struct i2c_client *i2c)
9901102
{
9911103
enum pca9450_chip_type type = (unsigned int)(uintptr_t)
9921104
of_device_get_match_data(&i2c->dev);
993-
const struct pca9450_regulator_desc *regulator_desc;
1105+
const struct pca9450_regulator_desc *regulator_desc;
9941106
struct regulator_config config = { };
9951107
struct regulator_dev *ldo5;
9961108
struct pca9450 *pca9450;

0 commit comments

Comments
 (0)