diff options
author | Thierry Reding <thierry.reding@gmail.com> | 2016-07-11 08:40:23 +0200 |
---|---|---|
committer | Thierry Reding <thierry.reding@gmail.com> | 2016-07-11 08:40:23 +0200 |
commit | 6fa231b778d9cf3b18d50b594c9da1d63a6864ac (patch) | |
tree | cb84ab32b190bad36f9bcfcea54416c1830dd98a /drivers/regulator/pwm-regulator.c | |
parent | a28b2f68b64f4df1fa311c5aa1910cc1f030559b (diff) | |
parent | c2588393e6315ab68207323d37d2a73713d6bc81 (diff) |
Merge tag 'pwm-modernization' of git://git.kernel.org/pub/scm/linux/kernel/git/broonie/regulator into for-4.8/regulator
regulator: Provide a branch for moderninzation of the PWM code
There's a new, improved PWM API which allows a lot of improvements in
the PWM regulator driver. Since the bulk of the changes are in the PWM
API this is being managed in the PWM tree, merge pending regulator API
changes to allow this to be resolved more easily.
Diffstat (limited to 'drivers/regulator/pwm-regulator.c')
-rw-r--r-- | drivers/regulator/pwm-regulator.c | 40 |
1 files changed, 33 insertions, 7 deletions
diff --git a/drivers/regulator/pwm-regulator.c b/drivers/regulator/pwm-regulator.c index fafa3488e960..666bc3bb52ef 100644 --- a/drivers/regulator/pwm-regulator.c +++ b/drivers/regulator/pwm-regulator.c @@ -20,6 +20,7 @@ #include <linux/of.h> #include <linux/of_device.h> #include <linux/pwm.h> +#include <linux/gpio/consumer.h> struct pwm_regulator_data { /* Shared */ @@ -38,6 +39,9 @@ struct pwm_regulator_data { /* Continuous voltage */ int volt_uV; + + /* Enable GPIO */ + struct gpio_desc *enb_gpio; }; struct pwm_voltages { @@ -94,6 +98,9 @@ static int pwm_regulator_enable(struct regulator_dev *dev) { struct pwm_regulator_data *drvdata = rdev_get_drvdata(dev); + if (drvdata->enb_gpio) + gpiod_set_value_cansleep(drvdata->enb_gpio, 1); + return pwm_enable(drvdata->pwm); } @@ -103,6 +110,9 @@ static int pwm_regulator_disable(struct regulator_dev *dev) pwm_disable(drvdata->pwm); + if (drvdata->enb_gpio) + gpiod_set_value_cansleep(drvdata->enb_gpio, 0); + return 0; } @@ -110,6 +120,9 @@ static int pwm_regulator_is_enabled(struct regulator_dev *dev) { struct pwm_regulator_data *drvdata = rdev_get_drvdata(dev); + if (drvdata->enb_gpio && !gpiod_get_value_cansleep(drvdata->enb_gpio)) + return false; + return pwm_is_enabled(drvdata->pwm); } @@ -132,6 +145,7 @@ static int pwm_regulator_set_voltage(struct regulator_dev *rdev, unsigned int duty_pulse; u64 req_period; u32 rem; + int old_uV = pwm_regulator_get_voltage(rdev); int ret; pwm_get_args(drvdata->pwm, &pargs); @@ -159,15 +173,14 @@ static int pwm_regulator_set_voltage(struct regulator_dev *rdev, return ret; } - ret = pwm_enable(drvdata->pwm); - if (ret) { - dev_err(&rdev->dev, "Failed to enable PWM: %d\n", ret); - return ret; - } drvdata->volt_uV = min_uV; - /* Delay required by PWM regulator to settle to the new voltage */ - usleep_range(ramp_delay, ramp_delay + 1000); + if ((ramp_delay == 0) || !pwm_regulator_is_enabled(rdev)) + return 0; + + /* Ramp delay is in uV/uS. Adjust to uS and delay */ + ramp_delay = DIV_ROUND_UP(abs(min_uV - old_uV), ramp_delay); + usleep_range(ramp_delay, ramp_delay + DIV_ROUND_UP(ramp_delay, 10)); return 0; } @@ -253,6 +266,7 @@ static int pwm_regulator_probe(struct platform_device *pdev) struct regulator_dev *regulator; struct regulator_config config = { }; struct device_node *np = pdev->dev.of_node; + enum gpiod_flags gpio_flags; int ret; if (!np) { @@ -290,6 +304,18 @@ static int pwm_regulator_probe(struct platform_device *pdev) return ret; } + if (init_data->constraints.boot_on || init_data->constraints.always_on) + gpio_flags = GPIOD_OUT_HIGH; + else + gpio_flags = GPIOD_OUT_LOW; + drvdata->enb_gpio = devm_gpiod_get_optional(&pdev->dev, "enable", + gpio_flags); + if (IS_ERR(drvdata->enb_gpio)) { + ret = PTR_ERR(drvdata->enb_gpio); + dev_err(&pdev->dev, "Failed to get enable GPIO: %d\n", ret); + return ret; + } + /* * FIXME: pwm_apply_args() should be removed when switching to the * atomic PWM API. |