From fcbe35b5ec0cf796ba541ffee84595650b8ca917 Mon Sep 17 00:00:00 2001 From: Damon Ding Date: Fri, 11 Aug 2023 14:48:10 +0800 Subject: [PATCH] pwm: rockchip: add a little delay to make sure conlock works The conlock can help to update period and duty when pwm is working. It takes 10 dclk cycles to make sure lock works before unlocking. Signed-off-by: Damon Ding Change-Id: Id750580b409a24e660d208e80417d4169def02ed --- drivers/pwm/pwm-rockchip.c | 26 +++++++++++++++++--------- 1 file changed, 17 insertions(+), 9 deletions(-) diff --git a/drivers/pwm/pwm-rockchip.c b/drivers/pwm/pwm-rockchip.c index 50e91951d496..fa455fb878e3 100644 --- a/drivers/pwm/pwm-rockchip.c +++ b/drivers/pwm/pwm-rockchip.c @@ -169,7 +169,7 @@ static void rockchip_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm, const struct pwm_state *state) { struct rockchip_pwm_chip *pc = to_rockchip_pwm_chip(chip); - unsigned long period, duty; + unsigned long period, duty, delay_ns; unsigned long flags; u64 div; u32 ctrl; @@ -191,11 +191,13 @@ static void rockchip_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm, div = (u64)pc->clk_rate * state->duty_cycle; duty = DIV_ROUND_CLOSEST_ULL(div, dclk_div * pc->data->prescaler * NSEC_PER_SEC); + if (pc->data->supports_lock) { + div = (u64)10 * NSEC_PER_SEC * dclk_div * pc->data->prescaler; + delay_ns = DIV_ROUND_UP_ULL(div, pc->clk_rate); + } + local_irq_save(flags); - /* - * Lock the period and duty of previous configuration, then - * change the duty and period, that would not be effective. - */ + ctrl = readl_relaxed(pc->base + pc->data->regs.ctrl); if (pc->data->vop_pwm) { if (pc->vop_pwm_en) @@ -253,6 +255,10 @@ static void rockchip_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm, } #endif + /* + * Lock the period and duty of previous configuration, then + * change the duty and period, that would not be effective. + */ if (pc->data->supports_lock) { ctrl |= PWM_LOCK_EN; writel_relaxed(ctrl, pc->base + pc->data->regs.ctrl); @@ -270,12 +276,14 @@ static void rockchip_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm, } /* - * Unlock and set polarity at the same time, - * the configuration of duty, period and polarity - * would be effective together at next period. + * Unlock and set polarity at the same time, the configuration of duty, + * period and polarity would be effective together at next period. It + * takes 10 dclk cycles to make sure lock works before unlocking. */ - if (pc->data->supports_lock) + if (pc->data->supports_lock) { ctrl &= ~PWM_LOCK_EN; + ndelay(delay_ns); + } writel(ctrl, pc->base + pc->data->regs.ctrl); local_irq_restore(flags);