The RK3576 NPU domains need a short settle time after the idle
request is released before the QoS registers behind the domain are
written: restoring QoS immediately after de-idle can raise an SError
on the register access while the NoC is still settling (observed on
ROCK 4D as a panic inside rockchip_pd_power() during NPU runtime-PM
cycling).

The vendor kernel handles this with a per-domain delay_us field
applied between the de-idle request and the QoS restore, carrying
15us for the RK3576 NPUTOP domain.  Mirror that: add delay_us to
rockchip_domain_info, honor it in rockchip_pd_power() right before
rockchip_pmu_restore_qos(), and set 15us for NPUTOP, NPU0 and NPU1
(the two core domains power-cycle constantly under runtime PM and
showed the same symptom during bring-up).  All other domains keep 0,
so nothing changes for them.

Signed-off-by: Jiaxing Hu <[email protected]>
---
 drivers/pmdomain/rockchip/pm-domains.c | 51 ++++++++++++++------------
 1 file changed, 28 insertions(+), 23 deletions(-)

diff --git a/drivers/pmdomain/rockchip/pm-domains.c 
b/drivers/pmdomain/rockchip/pm-domains.c
index 490bbb1d1..1787f62ba 100644
--- a/drivers/pmdomain/rockchip/pm-domains.c
+++ b/drivers/pmdomain/rockchip/pm-domains.c
@@ -59,6 +59,7 @@ struct rockchip_domain_info {
        u32 pwr_offset;
        u32 mem_offset;
        u32 req_offset;
+       u32 delay_us;
 };
 
 struct rockchip_pmu_info {
@@ -185,7 +186,7 @@ struct rockchip_pmu {
        .need_regulator = regulator,                    \
 }
 
-#define DOMAIN_M_O_R_G(_name, p_offset, pwr, status, m_offset, m_status, 
r_status, r_offset, req, idle, ack, g_mask, wakeup)   \
+#define DOMAIN_M_O_R_G(_name, p_offset, pwr, status, m_offset, m_status, 
r_status, r_offset, req, idle, ack, g_mask, delay, wakeup)    \
 {                                                      \
        .name = _name,                                  \
        .pwr_offset = p_offset,                         \
@@ -200,6 +201,7 @@ struct rockchip_pmu {
        .req_mask = (req),                              \
        .idle_mask = (idle),                            \
        .clk_ungate_mask = (g_mask),                    \
+       .delay_us = (delay),                            \
        .ack_mask = (ack),                              \
        .active_wakeup = wakeup,                        \
 }
@@ -244,8 +246,8 @@ struct rockchip_pmu {
 #define DOMAIN_RK3568(name, pwr, req, wakeup)          \
        DOMAIN_M(name, pwr, pwr, req, req, req, wakeup)
 
-#define DOMAIN_RK3576(name, p_offset, pwr, status, r_status, r_offset, req, 
idle, g_mask, wakeup)      \
-       DOMAIN_M_O_R_G(name, p_offset, pwr, status, 0, r_status, r_status, 
r_offset, req, idle, idle, g_mask, wakeup)
+#define DOMAIN_RK3576(name, p_offset, pwr, status, r_status, r_offset, req, 
idle, g_mask, delay, wakeup)       \
+       DOMAIN_M_O_R_G(name, p_offset, pwr, status, 0, r_status, r_status, 
r_offset, req, idle, idle, g_mask, delay, wakeup)
 
 /*
  * Dynamic Memory Controller may need to coordinate with us -- see
@@ -612,7 +614,6 @@ static int rockchip_do_pmu_set_power_domain(struct 
rockchip_pm_domain *pd,
                        return ret;
        }
 
-
        ret = readx_poll_timeout_atomic(rockchip_pmu_domain_is_on, pd, is_on,
                                        is_on == on, 0, 10000);
        if (ret) {
@@ -667,6 +668,9 @@ static int rockchip_pd_power(struct rockchip_pm_domain *pd, 
bool power_on)
                if (ret < 0)
                        goto out;
 
+               if (pd->info->delay_us)
+                       udelay(pd->info->delay_us);
+
                rockchip_pmu_restore_qos(pd);
        }
 
@@ -1286,25 +1290,26 @@ static const struct rockchip_domain_info 
rk3568_pm_domains[] = {
 };
 
 static const struct rockchip_domain_info rk3576_pm_domains[] = {
-       [RK3576_PD_NPU]         = DOMAIN_RK3576("npu",    0x0, BIT(0),  BIT(0), 
0,       0x0, 0,       0,       0,       false),
-       [RK3576_PD_NVM]         = DOMAIN_RK3576("nvm",    0x0, BIT(6),  0,      
BIT(6),  0x4, BIT(2),  BIT(18), BIT(2),  false),
-       [RK3576_PD_SDGMAC]      = DOMAIN_RK3576("sdgmac", 0x0, BIT(7),  0,      
BIT(7),  0x4, BIT(1),  BIT(17), 0x6,     false),
-       [RK3576_PD_AUDIO]       = DOMAIN_RK3576("audio",  0x0, BIT(8),  0,      
BIT(8),  0x4, BIT(0),  BIT(16), BIT(0),  false),
-       [RK3576_PD_PHP]         = DOMAIN_RK3576("php",    0x0, BIT(9),  0,      
BIT(9),  0x0, BIT(15), BIT(15), BIT(15), false),
-       [RK3576_PD_SUBPHP]      = DOMAIN_RK3576("subphp", 0x0, BIT(10), 0,      
BIT(10), 0x0, 0,       0,       0,       false),
-       [RK3576_PD_VOP]         = DOMAIN_RK3576("vop",    0x0, BIT(11), 0,      
BIT(11), 0x0, 0x6000,  0x6000,  0x6000,  false),
-       [RK3576_PD_VO1]         = DOMAIN_RK3576("vo1",    0x0, BIT(14), 0,      
BIT(14), 0x0, BIT(12), BIT(12), 0x7000,  false),
-       [RK3576_PD_VO0]         = DOMAIN_RK3576("vo0",    0x0, BIT(15), 0,      
BIT(15), 0x0, BIT(11), BIT(11), 0x6800,  false),
-       [RK3576_PD_USB]         = DOMAIN_RK3576("usb",    0x4, BIT(0),  0,      
BIT(16), 0x0, BIT(10), BIT(10), 0x6400,  true),
-       [RK3576_PD_VI]          = DOMAIN_RK3576("vi",     0x4, BIT(1),  0,      
BIT(17), 0x0, BIT(9),  BIT(9),  BIT(9),  false),
-       [RK3576_PD_VEPU0]       = DOMAIN_RK3576("vepu0",  0x4, BIT(2),  0,      
BIT(18), 0x0, BIT(7),  BIT(7),  0x280,   false),
-       [RK3576_PD_VEPU1]       = DOMAIN_RK3576("vepu1",  0x4, BIT(3),  0,      
BIT(19), 0x0, BIT(8),  BIT(8),  BIT(8),  false),
-       [RK3576_PD_VDEC]        = DOMAIN_RK3576("vdec",   0x4, BIT(4),  0,      
BIT(20), 0x0, BIT(6),  BIT(6),  BIT(6),  false),
-       [RK3576_PD_VPU]         = DOMAIN_RK3576("vpu",    0x4, BIT(5),  0,      
BIT(21), 0x0, BIT(5),  BIT(5),  BIT(5),  false),
-       [RK3576_PD_NPUTOP]      = DOMAIN_RK3576("nputop", 0x4, BIT(6),  0,      
BIT(22), 0x0, 0x18,    0x18,    0x18,    false),
-       [RK3576_PD_NPU0]        = DOMAIN_RK3576("npu0",   0x4, BIT(7),  0,      
BIT(23), 0x0, BIT(1),  BIT(1),  0x1a,    false),
-       [RK3576_PD_NPU1]        = DOMAIN_RK3576("npu1",   0x4, BIT(8),  0,      
BIT(24), 0x0, BIT(2),  BIT(2),  0x1c,    false),
-       [RK3576_PD_GPU]         = DOMAIN_RK3576("gpu",    0x4, BIT(9),  0,      
BIT(25), 0x0, BIT(0),  BIT(0),  BIT(0),  false),
+       /*                                               name    p_offset pwr   
   status  r_status r_offset req      idle     g_mask   delay wakeup */
+       [RK3576_PD_NPU]         = DOMAIN_RK3576("npu",    0x0, BIT(0),  BIT(0), 
0,       0x0, 0,       0,       0,       0,    false),
+       [RK3576_PD_NVM]         = DOMAIN_RK3576("nvm",    0x0, BIT(6),  0,      
BIT(6),  0x4, BIT(2),  BIT(18), BIT(2),  0,    false),
+       [RK3576_PD_SDGMAC]      = DOMAIN_RK3576("sdgmac", 0x0, BIT(7),  0,      
BIT(7),  0x4, BIT(1),  BIT(17), 0x6,     0,    false),
+       [RK3576_PD_AUDIO]       = DOMAIN_RK3576("audio",  0x0, BIT(8),  0,      
BIT(8),  0x4, BIT(0),  BIT(16), BIT(0),  0,    false),
+       [RK3576_PD_PHP]         = DOMAIN_RK3576("php",    0x0, BIT(9),  0,      
BIT(9),  0x0, BIT(15), BIT(15), BIT(15), 0,    false),
+       [RK3576_PD_SUBPHP]      = DOMAIN_RK3576("subphp", 0x0, BIT(10), 0,      
BIT(10), 0x0, 0,       0,       0,       0,    false),
+       [RK3576_PD_VOP]         = DOMAIN_RK3576("vop",    0x0, BIT(11), 0,      
BIT(11), 0x0, 0x6000,  0x6000,  0x6000,  0,    false),
+       [RK3576_PD_VO1]         = DOMAIN_RK3576("vo1",    0x0, BIT(14), 0,      
BIT(14), 0x0, BIT(12), BIT(12), 0x7000,  0,    false),
+       [RK3576_PD_VO0]         = DOMAIN_RK3576("vo0",    0x0, BIT(15), 0,      
BIT(15), 0x0, BIT(11), BIT(11), 0x6800,  0,    false),
+       [RK3576_PD_USB]         = DOMAIN_RK3576("usb",    0x4, BIT(0),  0,      
BIT(16), 0x0, BIT(10), BIT(10), 0x6400,  0,    true),
+       [RK3576_PD_VI]          = DOMAIN_RK3576("vi",     0x4, BIT(1),  0,      
BIT(17), 0x0, BIT(9),  BIT(9),  BIT(9),  0,    false),
+       [RK3576_PD_VEPU0]       = DOMAIN_RK3576("vepu0",  0x4, BIT(2),  0,      
BIT(18), 0x0, BIT(7),  BIT(7),  0x280,   0,    false),
+       [RK3576_PD_VEPU1]       = DOMAIN_RK3576("vepu1",  0x4, BIT(3),  0,      
BIT(19), 0x0, BIT(8),  BIT(8),  BIT(8),  0,    false),
+       [RK3576_PD_VDEC]        = DOMAIN_RK3576("vdec",   0x4, BIT(4),  0,      
BIT(20), 0x0, BIT(6),  BIT(6),  BIT(6),  0,    false),
+       [RK3576_PD_VPU]         = DOMAIN_RK3576("vpu",    0x4, BIT(5),  0,      
BIT(21), 0x0, BIT(5),  BIT(5),  BIT(5),  0,    false),
+       [RK3576_PD_NPUTOP]      = DOMAIN_RK3576("nputop", 0x4, BIT(6),  0,      
BIT(22), 0x0, 0x18,    0x18,    0x18,    15,   false),
+       [RK3576_PD_NPU0]        = DOMAIN_RK3576("npu0",   0x4, BIT(7),  0,      
BIT(23), 0x0, BIT(1),  BIT(1),  0x1a,    15,   false),
+       [RK3576_PD_NPU1]        = DOMAIN_RK3576("npu1",   0x4, BIT(8),  0,      
BIT(24), 0x0, BIT(2),  BIT(2),  0x1c,    15,   false),
+       [RK3576_PD_GPU]         = DOMAIN_RK3576("gpu",    0x4, BIT(9),  0,      
BIT(25), 0x0, BIT(0),  BIT(0),  BIT(0),  0,    false),
 };
 
 static const struct rockchip_domain_info rk3588_pm_domains[] = {
-- 
2.43.0

Reply via email to