From 6778948f9de86c3cfaf36725a7c87dcff9ba247f Mon Sep 17 00:00:00 2001
From: hc <hc@nodka.com>
Date: Mon, 11 Dec 2023 08:20:59 +0000
Subject: [PATCH] kernel_5.10 no rt

---
 kernel/drivers/pwm/pwm-rockchip.c |   26 +++++++++++++++++---------
 1 files changed, 17 insertions(+), 9 deletions(-)

diff --git a/kernel/drivers/pwm/pwm-rockchip.c b/kernel/drivers/pwm/pwm-rockchip.c
index 50e9195..fa455fb 100644
--- a/kernel/drivers/pwm/pwm-rockchip.c
+++ b/kernel/drivers/pwm/pwm-rockchip.c
@@ -169,7 +169,7 @@
 			       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 @@
 	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 @@
 	}
 #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 @@
 	}
 
 	/*
-	 * 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);

--
Gitblit v1.6.2