summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPeng Fan <[email protected]>2026-04-18 20:37:34 +0800
committerPeng Fan <[email protected]>2026-05-06 10:20:30 +0800
commite015bc1b8d3d9974494581eec1321e59ffe2b355 (patch)
tree67eeaa676f6900714b9bbfbf074e757cf406df1c
parentb7b7aa741f9dd37a25cf44f3a2771ec9bfd497dc (diff)
power: regulator: pfuze100: support non-independent mode
Some BUCKs could work in single/dual phase mode, not in independent mode. In single/dual phase mode, registers of both regulators, must be identically set. So configure mode and value for both BUCKs. CONF registers are not touched, leave them as default OTP settings. PFUZE100/200 SW3A/B, could work in single/dual phase mode, so introduce a new macro by adding a pointer to the SW3B descriptor. Signed-off-by: Peng Fan <[email protected]>
-rw-r--r--drivers/power/regulator/pfuze100.c49
1 files changed, 45 insertions, 4 deletions
diff --git a/drivers/power/regulator/pfuze100.c b/drivers/power/regulator/pfuze100.c
index ed69e6e14c3..77c82a00b65 100644
--- a/drivers/power/regulator/pfuze100.c
+++ b/drivers/power/regulator/pfuze100.c
@@ -33,6 +33,8 @@ struct pfuze100_high_volt_desc {
* @voltage: Current voltage for REGULATOR_TYPE_FIXED type regulator.
* @high_volt_mask: Low or High Output voltage mode mask
* @high_volt_desc: High Output voltage description
+ * @b: Some regulators could work together to provide one output when working
+ * in single phase or dual phase mode.
*/
struct pfuze100_regulator_desc {
char *name;
@@ -47,6 +49,7 @@ struct pfuze100_regulator_desc {
unsigned int voltage;
unsigned int high_volt_mask;
struct pfuze100_high_volt_desc *high_volt_desc;
+ struct pfuze100_regulator_desc *b;
};
/**
@@ -79,6 +82,21 @@ struct pfuze100_regulator_plat {
.high_volt_mask = (mask), \
}
+#define PFUZE100_SWAB_REG(_name, base, step, min, volt_desc, mask, desc) \
+ { \
+ .name = #_name, \
+ .type = REGULATOR_TYPE_BUCK, \
+ .uV_step = (step), \
+ .min_uV = (min), \
+ .vsel_reg = (base) + PFUZE100_VOL_OFFSET, \
+ .vsel_mask = 0x3F, \
+ .stby_reg = (base) + PFUZE100_STBY_OFFSET, \
+ .stby_mask = 0x3F, \
+ .high_volt_desc = (volt_desc), \
+ .high_volt_mask = (mask), \
+ .b = (desc), \
+ }
+
#define PFUZE100_SWB_REG(_name, base, mask, step, voltages) \
{ \
.name = #_name, \
@@ -184,6 +202,8 @@ static struct pfuze100_regulator_desc pfuze100_regulators[] = {
PFUZE100_SW_REG(sw1c, PFUZE100_SW1CVOL, 25000, 300000, NULL, 0),
PFUZE100_SW_REG(sw2, PFUZE100_SW2VOL, 25000, 400000, &high_desc, BIT(6)),
PFUZE100_SW_REG(sw3a, PFUZE100_SW3AVOL, 25000, 400000, &high_desc, BIT(6)),
+ PFUZE100_SWAB_REG(sw3ab, PFUZE100_SW3AVOL, 25000, 400000, &high_desc, BIT(6),
+ &pfuze100_regulators[5]),
PFUZE100_SW_REG(sw3b, PFUZE100_SW3BVOL, 25000, 400000, &high_desc, BIT(6)),
PFUZE100_SW_REG(sw4, PFUZE100_SW4VOL, 25000, 400000, &high_desc, BIT(6)),
PFUZE100_SWB_REG(swbst, PFUZE100_SWBSTCON1, 0x3, 50000, pfuze100_swbst),
@@ -202,6 +222,8 @@ static struct pfuze100_regulator_desc pfuze200_regulators[] = {
PFUZE100_SW_REG(sw1ab, PFUZE100_SW1ABVOL, 25000, 300000, NULL, 0),
PFUZE100_SW_REG(sw2, PFUZE100_SW2VOL, 25000, 400000, &high_desc, BIT(6)),
PFUZE100_SW_REG(sw3a, PFUZE100_SW3AVOL, 25000, 400000, &high_desc, BIT(6)),
+ PFUZE100_SWAB_REG(sw3ab, PFUZE100_SW3AVOL, 25000, 400000, &high_desc, BIT(6),
+ &pfuze200_regulators[4]),
PFUZE100_SW_REG(sw3b, PFUZE100_SW3BVOL, 25000, 400000, &high_desc, BIT(6)),
PFUZE100_SWB_REG(swbst, PFUZE100_SWBSTCON1, 0x3, 50000, pfuze100_swbst),
PFUZE100_SNVS_REG(vsnvs, PFUZE100_VSNVSVOL, 0x7, pfuze100_vsnvs),
@@ -380,6 +402,16 @@ static int pfuze100_regulator_mode(struct udevice *dev, int op, int *opmode)
desc->vsel_reg + PFUZE100_MODE_OFFSET,
SW_MODE_MASK,
*opmode << SW_MODE_SHIFT);
+ if (val)
+ return val;
+
+ if (desc->b) {
+ desc = desc->b;
+ val = pmic_clrsetbits(dev->parent,
+ desc->vsel_reg + PFUZE100_MODE_OFFSET,
+ SW_MODE_MASK,
+ *opmode << SW_MODE_SHIFT);
+ }
} else if (desc->type == REGULATOR_TYPE_LDO) {
val = pmic_clrsetbits(dev->parent, desc->vsel_reg,
@@ -458,7 +490,7 @@ static int pfuze100_regulator_enable(struct udevice *dev, int op, bool *enable)
static int pfuze100_regulator_val(struct udevice *dev, int op, int *uV)
{
- int i;
+ int i, ret;
int val, min_uV, uV_step;
struct pfuze100_regulator_plat *plat = dev_get_plat(dev);
struct pfuze100_regulator_desc *desc = plat->desc;
@@ -526,9 +558,18 @@ static int pfuze100_regulator_val(struct udevice *dev, int op, int *uV)
uV_step = desc->uV_step;
}
- return pmic_clrsetbits(dev->parent, desc->vsel_reg,
- desc->vsel_mask,
- (*uV - min_uV) / uV_step);
+ ret = pmic_clrsetbits(dev->parent, desc->vsel_reg,
+ desc->vsel_mask, (*uV - min_uV) / uV_step);
+ if (ret)
+ return ret;
+
+ if (desc->b) {
+ desc = desc->b;
+ ret = pmic_clrsetbits(dev->parent, desc->vsel_reg,
+ desc->vsel_mask, (*uV - min_uV) / uV_step);
+ if (ret)
+ return ret;
+ }
}
return 0;