diff options
Diffstat (limited to 'drivers/regulator/pwm-regulator.c')
-rw-r--r-- | drivers/regulator/pwm-regulator.c | 73 |
1 files changed, 55 insertions, 18 deletions
diff --git a/drivers/regulator/pwm-regulator.c b/drivers/regulator/pwm-regulator.c index 698c420e0869..7434b6b22d32 100644 --- a/drivers/regulator/pwm-regulator.c +++ b/drivers/regulator/pwm-regulator.c @@ -157,7 +157,17 @@ static int pwm_regulator_get_voltage(struct regulator_dev *rdev) pwm_get_state(drvdata->pwm, &pstate); + if (!pstate.enabled) { + if (pstate.polarity == PWM_POLARITY_INVERSED) + pstate.duty_cycle = pstate.period; + else + pstate.duty_cycle = 0; + } + voltage = pwm_get_relative_duty_cycle(&pstate, duty_unit); + if (voltage < min(max_uV_duty, min_uV_duty) || + voltage > max(max_uV_duty, min_uV_duty)) + return -ENOTRECOVERABLE; /* * The dutycycle for min_uV might be greater than the one for max_uV. @@ -261,11 +271,10 @@ static int pwm_regulator_init_table(struct platform_device *pdev, of_find_property(np, "voltage-table", &length); if ((length < sizeof(*duty_cycle_table)) || - (length % sizeof(*duty_cycle_table))) { - dev_err(&pdev->dev, "voltage-table length(%d) is invalid\n", - length); - return -EINVAL; - } + (length % sizeof(*duty_cycle_table))) + return dev_err_probe(&pdev->dev, -EINVAL, + "voltage-table length(%d) is invalid\n", + length); duty_cycle_table = devm_kzalloc(&pdev->dev, length, GFP_KERNEL); if (!duty_cycle_table) @@ -274,10 +283,9 @@ static int pwm_regulator_init_table(struct platform_device *pdev, ret = of_property_read_u32_array(np, "voltage-table", (u32 *)duty_cycle_table, length / sizeof(u32)); - if (ret) { - dev_err(&pdev->dev, "Failed to read voltage-table: %d\n", ret); - return ret; - } + if (ret) + return dev_err_probe(&pdev->dev, ret, + "Failed to read voltage-table\n"); drvdata->state = -ENOTRECOVERABLE; drvdata->duty_cycle_table = duty_cycle_table; @@ -313,6 +321,32 @@ static int pwm_regulator_init_continuous(struct platform_device *pdev, return 0; } +static int pwm_regulator_init_boot_on(struct platform_device *pdev, + struct pwm_regulator_data *drvdata, + const struct regulator_init_data *init_data) +{ + struct pwm_state pstate; + + if (!init_data->constraints.boot_on || drvdata->enb_gpio) + return 0; + + pwm_get_state(drvdata->pwm, &pstate); + if (pstate.enabled) + return 0; + + /* + * Update the duty cycle so the output does not change + * when the regulator core enables the regulator (and + * thus the PWM channel). + */ + if (pstate.polarity == PWM_POLARITY_INVERSED) + pstate.duty_cycle = pstate.period; + else + pstate.duty_cycle = 0; + + return pwm_apply_might_sleep(drvdata->pwm, &pstate); +} + static int pwm_regulator_probe(struct platform_device *pdev) { const struct regulator_init_data *init_data; @@ -323,10 +357,9 @@ static int pwm_regulator_probe(struct platform_device *pdev) enum gpiod_flags gpio_flags; int ret; - if (!np) { - dev_err(&pdev->dev, "Device Tree node missing\n"); - return -EINVAL; - } + if (!np) + return dev_err_probe(&pdev->dev, -EINVAL, + "Device Tree node missing\n"); drvdata = devm_kzalloc(&pdev->dev, sizeof(*drvdata), GFP_KERNEL); if (!drvdata) @@ -364,21 +397,25 @@ static int pwm_regulator_probe(struct platform_device *pdev) 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; + return dev_err_probe(&pdev->dev, ret, "Failed to get enable GPIO\n"); } ret = pwm_adjust_config(drvdata->pwm); if (ret) return ret; + ret = pwm_regulator_init_boot_on(pdev, drvdata, init_data); + if (ret) + return dev_err_probe(&pdev->dev, ret, + "Failed to apply boot_on settings\n"); + regulator = devm_regulator_register(&pdev->dev, &drvdata->desc, &config); if (IS_ERR(regulator)) { ret = PTR_ERR(regulator); - dev_err(&pdev->dev, "Failed to register regulator %s: %d\n", - drvdata->desc.name, ret); - return ret; + return dev_err_probe(&pdev->dev, ret, + "Failed to register regulator %s\n", + drvdata->desc.name); } return 0; |