From 0eddcf0267f913cb6336af64cadaf5acf6b19b7b Mon Sep 17 00:00:00 2001 From: Jisheng Zhang Date: Wed, 29 Jul 2020 13:09:13 +0800 Subject: regulator: mp886x: implement set_ramp_delay Implement the .set_ramp_delay for MP8867 and MP8869. MP8867 and MP8869 could share the implementation, the only difference is the slew_rates array. Signed-off-by: Jisheng Zhang Link: https://lore.kernel.org/r/20200729130913.3ac38b32@xhacker Signed-off-by: Mark Brown --- drivers/regulator/mp886x.c | 67 +++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 64 insertions(+), 3 deletions(-) diff --git a/drivers/regulator/mp886x.c b/drivers/regulator/mp886x.c index d3d475f717f4..1305bf217df1 100644 --- a/drivers/regulator/mp886x.c +++ b/drivers/regulator/mp886x.c @@ -18,18 +18,48 @@ #define MP886X_V_BOOT (1 << 7) #define MP886X_SYSCNTLREG1 0x01 #define MP886X_MODE (1 << 0) +#define MP886X_SLEW_SHIFT 3 +#define MP886X_SLEW_MASK (0x7 << MP886X_SLEW_SHIFT) #define MP886X_GO (1 << 6) #define MP886X_EN (1 << 7) +struct mp886x_cfg_info { + const struct regulator_ops *rops; + const int slew_rates[8]; +}; + struct mp886x_device_info { struct device *dev; struct regulator_desc desc; struct regulator_init_data *regulator; struct gpio_desc *en_gpio; + const struct mp886x_cfg_info *ci; u32 r[2]; unsigned int sel; }; +static int mp886x_set_ramp(struct regulator_dev *rdev, int ramp) +{ + struct mp886x_device_info *di = rdev_get_drvdata(rdev); + const struct mp886x_cfg_info *ci = di->ci; + int reg = -1, i; + + for (i = 0; i < ARRAY_SIZE(ci->slew_rates); i++) { + if (ramp <= ci->slew_rates[i]) + reg = i; + else + break; + } + + if (reg < 0) { + dev_err(di->dev, "unsupported ramp value %d\n", ramp); + return -EINVAL; + } + + return regmap_update_bits(rdev->regmap, MP886X_SYSCNTLREG1, + MP886X_SLEW_MASK, reg << MP886X_SLEW_SHIFT); +} + static int mp886x_set_mode(struct regulator_dev *rdev, unsigned int mode) { switch (mode) { @@ -117,6 +147,21 @@ static const struct regulator_ops mp8869_regulator_ops = { .is_enabled = regulator_is_enabled_regmap, .set_mode = mp886x_set_mode, .get_mode = mp886x_get_mode, + .set_ramp_delay = mp886x_set_ramp, +}; + +static const struct mp886x_cfg_info mp8869_ci = { + .rops = &mp8869_regulator_ops, + .slew_rates = { + 40000, + 30000, + 20000, + 10000, + 5000, + 2500, + 1250, + 625, + }, }; static int mp8867_set_voltage_sel(struct regulator_dev *rdev, unsigned int sel) @@ -173,6 +218,21 @@ static const struct regulator_ops mp8867_regulator_ops = { .is_enabled = regulator_is_enabled_regmap, .set_mode = mp886x_set_mode, .get_mode = mp886x_get_mode, + .set_ramp_delay = mp886x_set_ramp, +}; + +static const struct mp886x_cfg_info mp8867_ci = { + .rops = &mp8867_regulator_ops, + .slew_rates = { + 64000, + 32000, + 16000, + 8000, + 4000, + 2000, + 1000, + 500, + }, }; static int mp886x_regulator_register(struct mp886x_device_info *di, @@ -183,7 +243,7 @@ static int mp886x_regulator_register(struct mp886x_device_info *di, rdesc->name = "mp886x-reg"; rdesc->supply_name = "vin"; - rdesc->ops = of_device_get_match_data(di->dev); + rdesc->ops = di->ci->rops; rdesc->type = REGULATOR_VOLTAGE; rdesc->n_voltages = 128; rdesc->enable_reg = MP886X_SYSCNTLREG1; @@ -234,6 +294,7 @@ static int mp886x_i2c_probe(struct i2c_client *client) if (IS_ERR(di->en_gpio)) return PTR_ERR(di->en_gpio); + di->ci = of_device_get_match_data(dev); di->dev = dev; regmap = devm_regmap_init_i2c(client, &mp886x_regmap_config); @@ -258,11 +319,11 @@ static int mp886x_i2c_probe(struct i2c_client *client) static const struct of_device_id mp886x_dt_ids[] = { { .compatible = "mps,mp8867", - .data = &mp8867_regulator_ops + .data = &mp8867_ci }, { .compatible = "mps,mp8869", - .data = &mp8869_regulator_ops + .data = &mp8869_ci }, { } }; -- cgit v1.2.3 From ee6ad5a24575071b66bd37ffb2d8747a64fcb45f Mon Sep 17 00:00:00 2001 From: Jisheng Zhang Date: Wed, 29 Jul 2020 13:10:23 +0800 Subject: regulator: mp886x: support setting switch freq Both MP8867 and MP8869 support different switch frequency. Signed-off-by: Jisheng Zhang Link: https://lore.kernel.org/r/20200729131023.77cc1dd2@xhacker Signed-off-by: Mark Brown --- drivers/regulator/mp886x.c | 42 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 42 insertions(+) diff --git a/drivers/regulator/mp886x.c b/drivers/regulator/mp886x.c index 1305bf217df1..97dc44c0d663 100644 --- a/drivers/regulator/mp886x.c +++ b/drivers/regulator/mp886x.c @@ -22,10 +22,14 @@ #define MP886X_SLEW_MASK (0x7 << MP886X_SLEW_SHIFT) #define MP886X_GO (1 << 6) #define MP886X_EN (1 << 7) +#define MP8869_SYSCNTLREG2 0x02 struct mp886x_cfg_info { const struct regulator_ops *rops; const int slew_rates[8]; + const int switch_freq[4]; + const u8 fs_reg; + const u8 fs_shift; }; struct mp886x_device_info { @@ -60,6 +64,24 @@ static int mp886x_set_ramp(struct regulator_dev *rdev, int ramp) MP886X_SLEW_MASK, reg << MP886X_SLEW_SHIFT); } +static void mp886x_set_switch_freq(struct mp886x_device_info *di, + struct regmap *regmap, + u32 freq) +{ + const struct mp886x_cfg_info *ci = di->ci; + int i; + + for (i = 0; i < ARRAY_SIZE(ci->switch_freq); i++) { + if (freq == ci->switch_freq[i]) { + regmap_update_bits(regmap, ci->fs_reg, + 0x3 << ci->fs_shift, i << ci->fs_shift); + return; + } + } + + dev_err(di->dev, "invalid frequency %d\n", freq); +} + static int mp886x_set_mode(struct regulator_dev *rdev, unsigned int mode) { switch (mode) { @@ -162,6 +184,14 @@ static const struct mp886x_cfg_info mp8869_ci = { 1250, 625, }, + .switch_freq = { + 500000, + 750000, + 1000000, + 1250000, + }, + .fs_reg = MP8869_SYSCNTLREG2, + .fs_shift = 4, }; static int mp8867_set_voltage_sel(struct regulator_dev *rdev, unsigned int sel) @@ -233,6 +263,14 @@ static const struct mp886x_cfg_info mp8867_ci = { 1000, 500, }, + .switch_freq = { + 500000, + 750000, + 1000000, + 1500000, + }, + .fs_reg = MP886X_SYSCNTLREG1, + .fs_shift = 1, }; static int mp886x_regulator_register(struct mp886x_device_info *di, @@ -273,6 +311,7 @@ static int mp886x_i2c_probe(struct i2c_client *client) struct mp886x_device_info *di; struct regulator_config config = { }; struct regmap *regmap; + u32 freq; int ret; di = devm_kzalloc(dev, sizeof(struct mp886x_device_info), GFP_KERNEL); @@ -310,6 +349,9 @@ static int mp886x_i2c_probe(struct i2c_client *client) config.driver_data = di; config.of_node = np; + if (!of_property_read_u32(np, "mps,switch-frequency", &freq)) + mp886x_set_switch_freq(di, regmap, freq); + ret = mp886x_regulator_register(di, &config); if (ret < 0) dev_err(dev, "Failed to register regulator!\n"); -- cgit v1.2.3 From b4b85af052f434bc3be5ee18462164986618feb1 Mon Sep 17 00:00:00 2001 From: Jisheng Zhang Date: Wed, 29 Jul 2020 13:09:52 +0800 Subject: regulator: mp886x: support mps,switch-frequency Both MP8867 and MP8869 support different switch frequency. Signed-off-by: Jisheng Zhang Link: https://lore.kernel.org/r/20200729130952.260671f1@xhacker Signed-off-by: Mark Brown --- Documentation/devicetree/bindings/regulator/mp886x.txt | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/Documentation/devicetree/bindings/regulator/mp886x.txt b/Documentation/devicetree/bindings/regulator/mp886x.txt index 551867829459..e747000cebba 100644 --- a/Documentation/devicetree/bindings/regulator/mp886x.txt +++ b/Documentation/devicetree/bindings/regulator/mp886x.txt @@ -9,6 +9,10 @@ Required properties: - mps,fb-voltage-divider: An array of two integers containing the resistor values R1 and R2 of the feedback voltage divider in kilo ohms. +Optional properties: +- mps,switch-frequency: The valid switch frequency in Hertz. Available values + are: 500000, 750000, 1000000, 1250000, 1500000 + Any property defined as part of the core regulator binding, defined in ./regulator.txt, can also be used. -- cgit v1.2.3