From: Kaustabh Chakraborty Date: Fri, 17 Oct 2025 15:28:19 +0000 (+0530) Subject: power: regulator: s2mps11: declaratively get/set regulator mode X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=3d4143ac3aefe54ad77151378f44df94de7e10da;p=thirdparty%2Fu-boot.git power: regulator: s2mps11: declaratively get/set regulator mode The functions s2mps11_{buck,ldo}_mode use the s2mps11_{buck,ldo}_modes arrays directly in order to extract the mode of a certain register. This approach does not allow similar devices of other variants (which may support a different set of modes) to work with the same driver. Instead of using these arrays hardcoded, extract them from the device's uclass platform data. Now the responsibility of setting these arrays properly is done by functions s2mps11_{buck,ldo}_probe, by implementing a switch-case block which can support modes of multiple variants if and when added. Signed-off-by: Kaustabh Chakraborty Reviewed-by: Peng Fan Signed-off-by: Peng Fan --- diff --git a/drivers/power/regulator/s2mps11_regulator.c b/drivers/power/regulator/s2mps11_regulator.c index db981df53ae..17a0a4d7ce6 100644 --- a/drivers/power/regulator/s2mps11_regulator.c +++ b/drivers/power/regulator/s2mps11_regulator.c @@ -204,10 +204,11 @@ static int s2mps11_buck_val(struct udevice *dev, int op, int *uV) static int s2mps11_buck_mode(struct udevice *dev, int op, int *opmode) { + struct dm_regulator_uclass_plat *uc_pdata = dev_get_uclass_plat(dev); const struct sec_regulator_desc *buck_desc; unsigned int addr, mode; unsigned char val; - int num_bucks, buck, ret; + int num_bucks, buck, ret, i; switch (s2mps11_get_variant(dev)) { case VARIANT_S2MPS11: @@ -233,42 +234,29 @@ static int s2mps11_buck_mode(struct udevice *dev, int op, int *opmode) if (op == PMIC_OP_GET) { val &= buck_desc[buck].mode_mask; - switch (val) { - case S2MPS11_BUCK_MODE_OFF: - *opmode = OP_OFF; - break; - case S2MPS11_BUCK_MODE_STANDBY: - *opmode = OP_STANDBY; - break; - case S2MPS11_BUCK_MODE_ON: - *opmode = OP_ON; - break; - default: - return -EINVAL; + for (i = 0; i < uc_pdata->mode_count; i++) { + if (uc_pdata->mode[i].register_value != val) + continue; + + *opmode = uc_pdata->mode[i].id; + return 0; } - return 0; - } - switch (*opmode) { - case OP_OFF: - mode = S2MPS11_BUCK_MODE_OFF; - break; - case OP_STANDBY: - mode = S2MPS11_BUCK_MODE_STANDBY; - break; - case OP_ON: - mode = S2MPS11_BUCK_MODE_ON; - break; - default: - pr_err("Wrong mode: %d for buck: %d\n", *opmode, buck); return -EINVAL; } - val &= ~buck_desc[buck].mode_mask; - val |= mode; - ret = pmic_write(dev->parent, addr, &val, 1); + for (i = 0; i < uc_pdata->mode_count; i++) { + if (uc_pdata->mode[i].id != *opmode) + continue; - return ret; + mode = uc_pdata->mode[i].register_value; + val &= ~buck_desc[buck].mode_mask; + val |= mode; + return pmic_write(dev->parent, addr, &val, 1); + } + + pr_err("Wrong mode: %d for buck: %d\n", *opmode, buck); + return -EINVAL; } static int s2mps11_buck_enable(struct udevice *dev, int op, bool *enable) @@ -357,10 +345,17 @@ static int s2mps11_buck_probe(struct udevice *dev) struct dm_regulator_uclass_plat *uc_pdata; uc_pdata = dev_get_uclass_plat(dev); - uc_pdata->type = REGULATOR_TYPE_BUCK; - uc_pdata->mode = s2mps11_buck_modes; - uc_pdata->mode_count = ARRAY_SIZE(s2mps11_buck_modes); + + switch (s2mps11_get_variant(dev)) { + case VARIANT_S2MPS11: + uc_pdata->mode = s2mps11_buck_modes; + uc_pdata->mode_count = ARRAY_SIZE(s2mps11_buck_modes); + break; + default: + pr_err("Unknown device type\n"); + return -EINVAL; + } return 0; } @@ -434,10 +429,11 @@ static int s2mps11_ldo_val(struct udevice *dev, int op, int *uV) static int s2mps11_ldo_mode(struct udevice *dev, int op, int *opmode) { + struct dm_regulator_uclass_plat *uc_pdata = dev_get_uclass_plat(dev); const struct sec_regulator_desc *ldo_desc; unsigned int addr, mode; unsigned char val; - int num_ldos, ldo, ret; + int num_ldos, ldo, ret, i; switch (s2mps11_get_variant(dev)) { case VARIANT_S2MPS11: @@ -463,48 +459,30 @@ static int s2mps11_ldo_mode(struct udevice *dev, int op, int *opmode) if (op == PMIC_OP_GET) { val &= ldo_desc[ldo].mode_mask; - switch (val) { - case S2MPS11_LDO_MODE_OFF: - *opmode = OP_OFF; - break; - case S2MPS11_LDO_MODE_STANDBY: - *opmode = OP_STANDBY; - break; - case S2MPS11_LDO_MODE_STANDBY_LPM: - *opmode = OP_STANDBY_LPM; - break; - case S2MPS11_LDO_MODE_ON: - *opmode = OP_ON; - break; - default: - return -EINVAL; + + for (i = 0; i < uc_pdata->mode_count; i++) { + if (uc_pdata->mode[i].register_value != val) + continue; + + *opmode = uc_pdata->mode[i].id; + return 0; } - return 0; - } - switch (*opmode) { - case OP_OFF: - mode = S2MPS11_LDO_MODE_OFF; - break; - case OP_STANDBY: - mode = S2MPS11_LDO_MODE_STANDBY; - break; - case OP_STANDBY_LPM: - mode = S2MPS11_LDO_MODE_STANDBY_LPM; - break; - case OP_ON: - mode = S2MPS11_LDO_MODE_ON; - break; - default: - pr_err("Wrong mode: %d for ldo: %d\n", *opmode, ldo); return -EINVAL; } - val &= ~ldo_desc[ldo].mode_mask; - val |= mode; - ret = pmic_write(dev->parent, addr, &val, 1); + for (i = 0; i < uc_pdata->mode_count; i++) { + if (uc_pdata->mode[i].id != *opmode) + continue; - return ret; + mode = uc_pdata->mode[i].register_value; + val &= ~ldo_desc[ldo].mode_mask; + val |= mode; + return pmic_write(dev->parent, addr, &val, 1); + } + + pr_err("Wrong mode: %d for ldo: %d\n", *opmode, ldo); + return -EINVAL; } static int s2mps11_ldo_enable(struct udevice *dev, int op, bool *enable) @@ -602,8 +580,16 @@ static int s2mps11_ldo_probe(struct udevice *dev) uc_pdata = dev_get_uclass_plat(dev); uc_pdata->type = REGULATOR_TYPE_LDO; - uc_pdata->mode = s2mps11_ldo_modes; - uc_pdata->mode_count = ARRAY_SIZE(s2mps11_ldo_modes); + + switch (s2mps11_get_variant(dev)) { + case VARIANT_S2MPS11: + uc_pdata->mode = s2mps11_ldo_modes; + uc_pdata->mode_count = ARRAY_SIZE(s2mps11_ldo_modes); + break; + default: + pr_err("Unknown device type\n"); + return -EINVAL; + } return 0; }