The RK3576 NPU domains need a short settle time after the idle request
is released before the QoS registers behind the domain answer. Without
it rockchip_pmu_restore_qos() reads back zeroes, and the NPU throws an
async SError on the first cold power-on.

Give rockchip_domain_info an optional delay_us and wait for it between
releasing idle and restoring QoS. Rename DOMAIN_M_O_R_G to
DOMAIN_M_O_R_G_W, since the suffixes name the fields the macro sets and
this one now also carries a wakeup delay; RK3576 is its only user, so
the old spelling is not kept around.

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

diff --git a/drivers/pmdomain/rockchip/pm-domains.c 
b/drivers/pmdomain/rockchip/pm-domains.c
index ba66ae719..e1857f878 100644
--- a/drivers/pmdomain/rockchip/pm-domains.c
+++ b/drivers/pmdomain/rockchip/pm-domains.c
@@ -18,6 +18,7 @@
 #include <linux/of_address.h>
 #include <linux/of_clk.h>
 #include <linux/clk.h>
+#include <linux/delay.h>
 #include <linux/regmap.h>
 #include <linux/regulator/consumer.h>
 #include <linux/mfd/syscon.h>
@@ -59,6 +60,7 @@ struct rockchip_domain_info {
        u32 pwr_offset;
        u32 mem_offset;
        u32 req_offset;
+       u32 delay_us;
 };
 
 struct rockchip_pmu_info {
@@ -185,7 +187,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_W(_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 +202,7 @@ struct rockchip_pmu {
        .req_mask = (req),                              \
        .idle_mask = (idle),                            \
        .clk_ungate_mask = (g_mask),                    \
+       .delay_us = (delay),                            \
        .ack_mask = (ack),                              \
        .active_wakeup = wakeup,                        \
 }
@@ -258,8 +261,8 @@ struct rockchip_pmu {
 #define DOMAIN_RK3568(name, pwr, req, wakeup, regulator)               \
        DOMAIN_M_R(name, pwr, pwr, req, req, req, wakeup, regulator)
 
-#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_W(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
@@ -681,6 +684,10 @@ static int rockchip_pd_power(struct rockchip_pm_domain 
*pd, bool power_on)
                if (ret < 0)
                        goto out;
 
+               /* Some domains need to settle before the QoS registers answer. 
*/
+               if (pd->info->delay_us)
+                       udelay(pd->info->delay_us);
+
                rockchip_pmu_restore_qos(pd);
        }
 
@@ -1300,25 +1307,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