diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2018-04-13 15:46:21 -0700 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2018-04-13 15:46:21 -0700 |
commit | daf3ef6e965d1d51d6ec604a8fc9919b75d5ec3c (patch) | |
tree | 643eeb6adc04a5e0a038d1a1dcbb2f6c8169c47e /drivers/pwm/pwm-rcar.c | |
parent | 41531f58a6513b86f8f379117eca82502022b4a9 (diff) | |
parent | 6873842235d678a245a378669f35e145df2441b9 (diff) |
Merge tag 'pwm/for-4.17-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/thierry.reding/linux-pwm
Pull pwm updates from Thierry Reding:
"This set of changes adds support for more generations of the RCar
controller as well as runtime PM support. The JZ4740 driver gains
support for device tree and can now be used on all Ingenic SoCs.
Rounding things off is a random assortment of fixes and cleanups all
across the board"
* tag 'pwm/for-4.17-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/thierry.reding/linux-pwm: (29 commits)
pwm: rcar: Add suspend/resume support
pwm: rcar: Use PM Runtime to control module clock
dt-bindings: pwm: rcar: Add bindings for R-Car M3N support
pwm: rcar: Fix a condition to prevent mismatch value setting to duty
pwm: sysfs: Use put_device() instead of kfree()
dt-bindings: pwm: sunxi: Add new compatible strings
pwm: sun4i: Simplify controller mapping
pwm: sun4i: Drop unused .has_rdy member
pwm: sun4i: Properly check current state
pwm: Remove depends on AVR32
pwm: stm32: LPTimer: Use 3 cells ->of_xlate()
dt-bindings: pwm-stm32-lp: Add #pwm-cells
pwm: stm32: Protect common prescaler for all channels
pwm: stm32: Remove unused struct device
pwm: mediatek: Improve precision in rate calculation
pwm: mediatek: Remove redundant MODULE_ALIAS entries
pwm: mediatek: Fix up PWM4 and PWM5 malfunction on MT7623
pwm: jz4740: Enable for all Ingenic SoCs
pwm: jz4740: Add support for devicetree
pwm: jz4740: Implement ->set_polarity()
...
Diffstat (limited to 'drivers/pwm/pwm-rcar.c')
-rw-r--r-- | drivers/pwm/pwm-rcar.c | 58 |
1 files changed, 50 insertions, 8 deletions
diff --git a/drivers/pwm/pwm-rcar.c b/drivers/pwm/pwm-rcar.c index 1c85ecc9e7ac..91d11f2e2fef 100644 --- a/drivers/pwm/pwm-rcar.c +++ b/drivers/pwm/pwm-rcar.c @@ -134,16 +134,12 @@ static int rcar_pwm_set_counter(struct rcar_pwm_chip *rp, int div, int duty_ns, static int rcar_pwm_request(struct pwm_chip *chip, struct pwm_device *pwm) { - struct rcar_pwm_chip *rp = to_rcar_pwm_chip(chip); - - return clk_prepare_enable(rp->clk); + return pm_runtime_get_sync(chip->dev); } static void rcar_pwm_free(struct pwm_chip *chip, struct pwm_device *pwm) { - struct rcar_pwm_chip *rp = to_rcar_pwm_chip(chip); - - clk_disable_unprepare(rp->clk); + pm_runtime_put(chip->dev); } static int rcar_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm, @@ -156,8 +152,12 @@ static int rcar_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm, if (div < 0) return div; - /* Let the core driver set pwm->period if disabled and duty_ns == 0 */ - if (!pwm_is_enabled(pwm) && !duty_ns) + /* + * Let the core driver set pwm->period if disabled and duty_ns == 0. + * But, this driver should prevent to set the new duty_ns if current + * duty_cycle is not set + */ + if (!pwm_is_enabled(pwm) && !duty_ns && !pwm->state.duty_cycle) return 0; rcar_pwm_update(rp, RCAR_PWMCR_SYNC, RCAR_PWMCR_SYNC, RCAR_PWMCR); @@ -258,11 +258,53 @@ static const struct of_device_id rcar_pwm_of_table[] = { }; MODULE_DEVICE_TABLE(of, rcar_pwm_of_table); +#ifdef CONFIG_PM_SLEEP +static struct pwm_device *rcar_pwm_dev_to_pwm_dev(struct device *dev) +{ + struct platform_device *pdev = to_platform_device(dev); + struct rcar_pwm_chip *rcar_pwm = platform_get_drvdata(pdev); + struct pwm_chip *chip = &rcar_pwm->chip; + + return &chip->pwms[0]; +} + +static int rcar_pwm_suspend(struct device *dev) +{ + struct pwm_device *pwm = rcar_pwm_dev_to_pwm_dev(dev); + + if (!test_bit(PWMF_REQUESTED, &pwm->flags)) + return 0; + + pm_runtime_put(dev); + + return 0; +} + +static int rcar_pwm_resume(struct device *dev) +{ + struct pwm_device *pwm = rcar_pwm_dev_to_pwm_dev(dev); + + if (!test_bit(PWMF_REQUESTED, &pwm->flags)) + return 0; + + pm_runtime_get_sync(dev); + + rcar_pwm_config(pwm->chip, pwm, pwm->state.duty_cycle, + pwm->state.period); + if (pwm_is_enabled(pwm)) + rcar_pwm_enable(pwm->chip, pwm); + + return 0; +} +#endif /* CONFIG_PM_SLEEP */ +static SIMPLE_DEV_PM_OPS(rcar_pwm_pm_ops, rcar_pwm_suspend, rcar_pwm_resume); + static struct platform_driver rcar_pwm_driver = { .probe = rcar_pwm_probe, .remove = rcar_pwm_remove, .driver = { .name = "pwm-rcar", + .pm = &rcar_pwm_pm_ops, .of_match_table = of_match_ptr(rcar_pwm_of_table), } }; |