The PWM will always start with the inactive part. To counter that, when PWM is enabled we switch the configured polarity, and use 'period - duty + 1' as the real duty.
Signed-off-by: Paul Cercueil <p...@crapouillou.net> --- drivers/pwm/pwm-jz4740.c | 22 +++++++++++++--------- 1 file changed, 13 insertions(+), 9 deletions(-) diff --git a/drivers/pwm/pwm-jz4740.c b/drivers/pwm/pwm-jz4740.c index 85e2110aae4f..8df898429d47 100644 --- a/drivers/pwm/pwm-jz4740.c +++ b/drivers/pwm/pwm-jz4740.c @@ -121,6 +121,7 @@ static int jz4740_pwm_apply(struct pwm_chip *chip, struct pwm_device *pwm, *parent_clk = clk_get_parent(clk); unsigned long rate, parent_rate, period, duty; unsigned long long tmp; + bool polarity_inversed; int ret; parent_rate = clk_get_rate(parent_clk); @@ -183,24 +184,27 @@ static int jz4740_pwm_apply(struct pwm_chip *chip, struct pwm_device *pwm, /* Reset counter to 0 */ regmap_write(jz4740->map, TCU_REG_TCNTc(pwm->hwpwm), 0); - /* Set duty */ - regmap_write(jz4740->map, TCU_REG_TDHRc(pwm->hwpwm), duty); - /* Set period */ regmap_write(jz4740->map, TCU_REG_TDFRc(pwm->hwpwm), period); + /* + * The PWM will always start with the inactive part. To counter that, + * when PWM is enabled we switch the configured polarity, and use + * 'period - duty + 1' as the real duty. + */ + + /* Set duty */ + regmap_write(jz4740->map, TCU_REG_TDHRc(pwm->hwpwm), period - duty + 1); + /* Set polarity */ - switch (state->polarity) { - case PWM_POLARITY_NORMAL: + polarity_inversed = state->polarity == PWM_POLARITY_INVERSED; + if (!polarity_inversed ^ state->enabled) regmap_update_bits(jz4740->map, TCU_REG_TCSRc(pwm->hwpwm), TCU_TCSR_PWM_INITL_HIGH, 0); - break; - case PWM_POLARITY_INVERSED: + else regmap_update_bits(jz4740->map, TCU_REG_TCSRc(pwm->hwpwm), TCU_TCSR_PWM_INITL_HIGH, TCU_TCSR_PWM_INITL_HIGH); - break; - } if (state->enabled) jz4740_pwm_enable(chip, pwm); -- 2.21.0.593.g511ec345e18