diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2019-07-09 17:57:45 +0200 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2019-07-09 17:57:45 +0200 |
commit | 6e2bbb688aa6d05073dd1dd0b836d9becec195c1 (patch) | |
tree | b267f5f593c397aa4c5eababc8d78ebc69ea3e7b /drivers/pwm/pwm-jz4740.c | |
parent | Merge branch 'siginfo-linus' of git://git.kernel.org/pub/scm/linux/kernel/git... (diff) | |
parent | pwm: fsl-ftm: Make sure to unlock mutex on failure (diff) | |
download | linux-6e2bbb688aa6d05073dd1dd0b836d9becec195c1.tar.xz linux-6e2bbb688aa6d05073dd1dd0b836d9becec195c1.zip |
Merge tag 'pwm/for-5.3-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 contains a new driver for SiFive SoCs as well as
enhancements to the core (device links are used to track dependencies
between PWM providers and consumers, support for PWM controllers via
ACPI, sysfs will now suspend/resume PWMs that it has claimed) and
various existing drivers"
* tag 'pwm/for-5.3-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/thierry.reding/linux-pwm: (37 commits)
pwm: fsl-ftm: Make sure to unlock mutex on failure
pwm: fsl-ftm: Use write protection for prescaler & polarity
pwm: fsl-ftm: More relaxed permissions for updating period
pwm: atmel-hlcdc: Add compatible for SAM9X60 HLCDC's PWM
pwm: bcm2835: Improve precision of PWM
leds: pwm: Support ACPI via firmware-node framework
pwm: Add support referencing PWMs from ACPI
pwm: rcar: Remove suspend/resume support
pwm: sysfs: Add suspend/resume support
pwm: Add power management descriptions
pwm: meson: Add documentation to the driver
pwm: meson: Add support PWM_POLARITY_INVERSED when disabling
pwm: meson: Don't cache struct pwm_state internally
pwm: meson: Read the full hardware state in meson_pwm_get_state()
pwm: meson: Simplify the calculation of the pre-divider and count
pwm: meson: Move pwm_set_chip_data() to meson_pwm_request()
pwm: meson: Add the per-channel register offsets and bits in a struct
pwm: meson: Add the meson_pwm_channel data to struct meson_pwm
pwm: meson: Pass struct pwm_device to meson_pwm_calc()
pwm: meson: Don't duplicate the polarity internally
...
Diffstat (limited to 'drivers/pwm/pwm-jz4740.c')
-rw-r--r-- | drivers/pwm/pwm-jz4740.c | 49 |
1 files changed, 21 insertions, 28 deletions
diff --git a/drivers/pwm/pwm-jz4740.c b/drivers/pwm/pwm-jz4740.c index 88a51a40e695..f901e8a0d33d 100644 --- a/drivers/pwm/pwm-jz4740.c +++ b/drivers/pwm/pwm-jz4740.c @@ -63,7 +63,15 @@ static void jz4740_pwm_disable(struct pwm_chip *chip, struct pwm_device *pwm) { uint32_t ctrl = jz4740_timer_get_ctrl(pwm->hwpwm); - /* Disable PWM output. + /* + * Set duty > period. This trick allows the TCU channels in TCU2 mode to + * properly return to their init level. + */ + jz4740_timer_set_duty(pwm->hwpwm, 0xffff); + jz4740_timer_set_period(pwm->hwpwm, 0x0); + + /* + * Disable PWM output. * In TCU2 mode (channel 1/2 on JZ4750+), this must be done before the * counter is stopped, while in TCU1 mode the order does not matter. */ @@ -74,17 +82,16 @@ static void jz4740_pwm_disable(struct pwm_chip *chip, struct pwm_device *pwm) jz4740_timer_disable(pwm->hwpwm); } -static int jz4740_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm, - int duty_ns, int period_ns) +static int jz4740_pwm_apply(struct pwm_chip *chip, struct pwm_device *pwm, + struct pwm_state *state) { struct jz4740_pwm_chip *jz4740 = to_jz4740(pwm->chip); unsigned long long tmp; unsigned long period, duty; unsigned int prescaler = 0; uint16_t ctrl; - bool is_enabled; - tmp = (unsigned long long)clk_get_rate(jz4740->clk) * period_ns; + tmp = (unsigned long long)clk_get_rate(jz4740->clk) * state->period; do_div(tmp, 1000000000); period = tmp; @@ -96,16 +103,14 @@ static int jz4740_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm, if (prescaler == 6) return -EINVAL; - tmp = (unsigned long long)period * duty_ns; - do_div(tmp, period_ns); + tmp = (unsigned long long)period * state->duty_cycle; + do_div(tmp, state->period); duty = period - tmp; if (duty >= period) duty = period - 1; - is_enabled = jz4740_timer_is_enabled(pwm->hwpwm); - if (is_enabled) - jz4740_pwm_disable(chip, pwm); + jz4740_pwm_disable(chip, pwm); jz4740_timer_set_count(pwm->hwpwm, 0); jz4740_timer_set_duty(pwm->hwpwm, duty); @@ -116,18 +121,7 @@ static int jz4740_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm, jz4740_timer_set_ctrl(pwm->hwpwm, ctrl); - if (is_enabled) - jz4740_pwm_enable(chip, pwm); - - return 0; -} - -static int jz4740_pwm_set_polarity(struct pwm_chip *chip, - struct pwm_device *pwm, enum pwm_polarity polarity) -{ - uint32_t ctrl = jz4740_timer_get_ctrl(pwm->pwm); - - switch (polarity) { + switch (state->polarity) { case PWM_POLARITY_NORMAL: ctrl &= ~JZ_TIMER_CTRL_PWM_ACTIVE_LOW; break; @@ -137,16 +131,17 @@ static int jz4740_pwm_set_polarity(struct pwm_chip *chip, } jz4740_timer_set_ctrl(pwm->hwpwm, ctrl); + + if (state->enabled) + jz4740_pwm_enable(chip, pwm); + return 0; } static const struct pwm_ops jz4740_pwm_ops = { .request = jz4740_pwm_request, .free = jz4740_pwm_free, - .config = jz4740_pwm_config, - .set_polarity = jz4740_pwm_set_polarity, - .enable = jz4740_pwm_enable, - .disable = jz4740_pwm_disable, + .apply = jz4740_pwm_apply, .owner = THIS_MODULE, }; @@ -184,8 +179,6 @@ static int jz4740_pwm_remove(struct platform_device *pdev) #ifdef CONFIG_OF static const struct of_device_id jz4740_pwm_dt_ids[] = { { .compatible = "ingenic,jz4740-pwm", }, - { .compatible = "ingenic,jz4770-pwm", }, - { .compatible = "ingenic,jz4780-pwm", }, {}, }; MODULE_DEVICE_TABLE(of, jz4740_pwm_dt_ids); |