diff options
author | Philippe Schenker | 2022-04-08 10:07:10 +0200 |
---|---|---|
committer | Stefano Babic | 2022-04-12 19:10:44 +0200 |
commit | f3b5100aff3a7edd53fd5d15bd6db92d294865e2 (patch) | |
tree | 33a152e89d1b2dc0df15a4d6e6acc89e2f0af017 | |
parent | 885dcc36afe80f5d0e56ee540787fee5102ac601 (diff) |
regulator: fixed: add possibility to enable by clock
This commit adds the possibility to choose the compatible
"regulator-fixed-clock" in devicetree.
This is a special case of regulator-fixed where a clock has to
be used to switch the regulator on and off.
Signed-off-by: Philippe Schenker <philippe.schenker@toradex.com>
Signed-off-by: Marcel Ziswiler <marcel.ziswiler@toradex.com>
-rw-r--r-- | drivers/power/regulator/fixed.c | 60 |
1 files changed, 59 insertions, 1 deletions
diff --git a/drivers/power/regulator/fixed.c b/drivers/power/regulator/fixed.c index d3e0fb672d9..90004d1601a 100644 --- a/drivers/power/regulator/fixed.c +++ b/drivers/power/regulator/fixed.c @@ -6,14 +6,21 @@ */ #include <common.h> +#include <clk.h> #include <errno.h> #include <dm.h> +#include <linux/delay.h> #include <log.h> #include <power/pmic.h> #include <power/regulator.h> #include "regulator_common.h" +struct fixed_clock_regulator_plat { + struct clk *enable_clock; + unsigned int clk_enable_counter; +}; + static int fixed_regulator_of_to_plat(struct udevice *dev) { struct dm_regulator_uclass_plat *uc_pdata; @@ -71,6 +78,38 @@ static int fixed_regulator_set_enable(struct udevice *dev, bool enable) return regulator_common_set_enable(dev, dev_get_plat(dev), enable); } +static int fixed_clock_regulator_get_enable(struct udevice *dev) +{ + struct fixed_clock_regulator_plat *priv = dev_get_priv(dev); + + return priv->clk_enable_counter > 0; +} + +static int fixed_clock_regulator_set_enable(struct udevice *dev, bool enable) +{ + struct fixed_clock_regulator_plat *priv = dev_get_priv(dev); + struct regulator_common_plat *dev_pdata = dev_get_plat(dev); + int ret = 0; + + if (enable) { + ret = clk_enable(priv->enable_clock); + priv->clk_enable_counter++; + } else { + ret = clk_disable(priv->enable_clock); + priv->clk_enable_counter--; + } + if (ret) + return ret; + + if (enable && dev_pdata->startup_delay_us) + udelay(dev_pdata->startup_delay_us); + + if (!enable && dev_pdata->off_on_delay_us) + udelay(dev_pdata->off_on_delay_us); + + return ret; +} + static const struct dm_regulator_ops fixed_regulator_ops = { .get_value = fixed_regulator_get_value, .get_current = fixed_regulator_get_current, @@ -78,16 +117,35 @@ static const struct dm_regulator_ops fixed_regulator_ops = { .set_enable = fixed_regulator_set_enable, }; +static const struct dm_regulator_ops fixed_clock_regulator_ops = { + .get_enable = fixed_clock_regulator_get_enable, + .set_enable = fixed_clock_regulator_set_enable, +}; + static const struct udevice_id fixed_regulator_ids[] = { { .compatible = "regulator-fixed" }, { }, }; +static const struct udevice_id fixed_clock_regulator_ids[] = { + { .compatible = "regulator-fixed-clock" }, + { }, +}; + U_BOOT_DRIVER(regulator_fixed) = { .name = "regulator_fixed", .id = UCLASS_REGULATOR, .ops = &fixed_regulator_ops, .of_match = fixed_regulator_ids, .of_to_plat = fixed_regulator_of_to_plat, - .plat_auto = sizeof(struct regulator_common_plat), + .plat_auto = sizeof(struct regulator_common_plat), +}; + +U_BOOT_DRIVER(regulator_fixed_clock) = { + .name = "regulator_fixed_clk", + .id = UCLASS_REGULATOR, + .ops = &fixed_clock_regulator_ops, + .of_match = fixed_clock_regulator_ids, + .of_to_plat = fixed_regulator_of_to_plat, + .plat_auto = sizeof(struct fixed_clock_regulator_plat), }; |