@@ -43,8 +43,10 @@ struct rockchip_domain_info {
4343 bool active_wakeup ;
4444 int pwr_w_mask ;
4545 int req_w_mask ;
46+ int mem_status_mask ;
4647 int repair_status_mask ;
4748 u32 pwr_offset ;
49+ u32 mem_offset ;
4850 u32 req_offset ;
4951};
5052
@@ -54,6 +56,9 @@ struct rockchip_pmu_info {
5456 u32 req_offset ;
5557 u32 idle_offset ;
5658 u32 ack_offset ;
59+ u32 mem_pwr_offset ;
60+ u32 chain_status_offset ;
61+ u32 mem_status_offset ;
5762 u32 repair_status_offset ;
5863
5964 u32 core_pwrcnt_offset ;
@@ -119,13 +124,15 @@ struct rockchip_pmu {
119124 .active_wakeup = wakeup, \
120125}
121126
122- #define DOMAIN_M_O_R (_name , p_offset , pwr , status , r_status , r_offset , req , idle , ack , wakeup ) \
127+ #define DOMAIN_M_O_R (_name , p_offset , pwr , status , m_offset , m_status , r_status , r_offset , req , idle , ack , wakeup ) \
123128{ \
124129 .name = _name, \
125130 .pwr_offset = p_offset, \
126131 .pwr_w_mask = (pwr) << 16, \
127132 .pwr_mask = (pwr), \
128133 .status_mask = (status), \
134+ .mem_offset = m_offset, \
135+ .mem_status_mask = (m_status), \
129136 .repair_status_mask = (r_status), \
130137 .req_offset = r_offset, \
131138 .req_w_mask = (req) << 16, \
@@ -269,8 +276,8 @@ void rockchip_pmu_unblock(void)
269276}
270277EXPORT_SYMBOL_GPL (rockchip_pmu_unblock );
271278
272- #define DOMAIN_RK3588 (name , p_offset , pwr , status , r_status , r_offset , req , idle , wakeup ) \
273- DOMAIN_M_O_R(name, p_offset, pwr, status, r_status, r_offset, req, idle, idle, wakeup)
279+ #define DOMAIN_RK3588 (name , p_offset , pwr , status , m_offset , m_status , r_status , r_offset , req , idle , wakeup ) \
280+ DOMAIN_M_O_R(name, p_offset, pwr, status, m_offset, m_status, r_status, r_offset, req, idle, idle, wakeup)
274281
275282static bool rockchip_pmu_domain_is_idle (struct rockchip_pm_domain * pd )
276283{
@@ -408,17 +415,92 @@ static bool rockchip_pmu_domain_is_on(struct rockchip_pm_domain *pd)
408415 return !(val & pd -> info -> status_mask );
409416}
410417
418+ static bool rockchip_pmu_domain_is_mem_on (struct rockchip_pm_domain * pd )
419+ {
420+ struct rockchip_pmu * pmu = pd -> pmu ;
421+ unsigned int val ;
422+
423+ regmap_read (pmu -> regmap ,
424+ pmu -> info -> mem_status_offset + pd -> info -> mem_offset , & val );
425+
426+ /* 1'b0: power on, 1'b1: power off */
427+ return !(val & pd -> info -> mem_status_mask );
428+ }
429+
430+ static bool rockchip_pmu_domain_is_chain_on (struct rockchip_pm_domain * pd )
431+ {
432+ struct rockchip_pmu * pmu = pd -> pmu ;
433+ unsigned int val ;
434+
435+ regmap_read (pmu -> regmap ,
436+ pmu -> info -> chain_status_offset + pd -> info -> mem_offset , & val );
437+
438+ /* 1'b1: power on, 1'b0: power off */
439+ return val & pd -> info -> mem_status_mask ;
440+ }
441+
442+ static int rockchip_pmu_domain_mem_reset (struct rockchip_pm_domain * pd )
443+ {
444+ struct rockchip_pmu * pmu = pd -> pmu ;
445+ struct generic_pm_domain * genpd = & pd -> genpd ;
446+ bool is_on ;
447+ int ret = 0 ;
448+
449+ ret = readx_poll_timeout_atomic (rockchip_pmu_domain_is_chain_on , pd , is_on ,
450+ is_on == true, 0 , 10000 );
451+ if (ret ) {
452+ dev_err (pmu -> dev ,
453+ "failed to get chain status '%s', target_on=1, val=%d\n" ,
454+ genpd -> name , is_on );
455+ goto error ;
456+ }
457+
458+ udelay (20 );
459+
460+ regmap_write (pmu -> regmap , pmu -> info -> mem_pwr_offset + pd -> info -> pwr_offset ,
461+ (pd -> info -> pwr_mask | pd -> info -> pwr_w_mask ));
462+ wmb ();
463+
464+ ret = readx_poll_timeout_atomic (rockchip_pmu_domain_is_mem_on , pd , is_on ,
465+ is_on == false, 0 , 10000 );
466+ if (ret ) {
467+ dev_err (pmu -> dev ,
468+ "failed to get mem status '%s', target_on=0, val=%d\n" ,
469+ genpd -> name , is_on );
470+ goto error ;
471+ }
472+
473+ regmap_write (pmu -> regmap , pmu -> info -> mem_pwr_offset + pd -> info -> pwr_offset ,
474+ pd -> info -> pwr_w_mask );
475+ wmb ();
476+
477+ ret = readx_poll_timeout_atomic (rockchip_pmu_domain_is_mem_on , pd , is_on ,
478+ is_on == true, 0 , 10000 );
479+ if (ret ) {
480+ dev_err (pmu -> dev ,
481+ "failed to get mem status '%s', target_on=1, val=%d\n" ,
482+ genpd -> name , is_on );
483+ }
484+
485+ error :
486+ return ret ;
487+ }
488+
411489static void rockchip_do_pmu_set_power_domain (struct rockchip_pm_domain * pd ,
412490 bool on )
413491{
414492 struct rockchip_pmu * pmu = pd -> pmu ;
415493 struct generic_pm_domain * genpd = & pd -> genpd ;
416494 u32 pd_pwr_offset = pd -> info -> pwr_offset ;
417- bool is_on ;
495+ bool is_on , is_mem_on = false ;
418496
419497 if (pd -> info -> pwr_mask == 0 )
420498 return ;
421- else if (pd -> info -> pwr_w_mask )
499+
500+ if (on && pd -> info -> mem_status_mask )
501+ is_mem_on = rockchip_pmu_domain_is_mem_on (pd );
502+
503+ if (pd -> info -> pwr_w_mask )
422504 regmap_write (pmu -> regmap , pmu -> info -> pwr_offset + pd_pwr_offset ,
423505 on ? pd -> info -> pwr_w_mask :
424506 (pd -> info -> pwr_mask | pd -> info -> pwr_w_mask ));
@@ -428,6 +510,9 @@ static void rockchip_do_pmu_set_power_domain(struct rockchip_pm_domain *pd,
428510
429511 wmb ();
430512
513+ if (is_mem_on && rockchip_pmu_domain_mem_reset (pd ))
514+ return ;
515+
431516 if (readx_poll_timeout_atomic (rockchip_pmu_domain_is_on , pd , is_on ,
432517 is_on == on , 0 , 10000 )) {
433518 dev_err (pmu -> dev ,
@@ -645,7 +730,9 @@ static int rockchip_pm_add_one_domain(struct rockchip_pmu *pmu,
645730 pd -> genpd .flags = GENPD_FLAG_PM_CLK ;
646731 if (pd_info -> active_wakeup )
647732 pd -> genpd .flags |= GENPD_FLAG_ACTIVE_WAKEUP ;
648- pm_genpd_init (& pd -> genpd , NULL , !rockchip_pmu_domain_is_on (pd ));
733+ pm_genpd_init (& pd -> genpd , NULL ,
734+ !rockchip_pmu_domain_is_on (pd ) ||
735+ (pd -> info -> mem_status_mask && !rockchip_pmu_domain_is_mem_on (pd )));
649736
650737 pmu -> genpd_data .domains [id ] = & pd -> genpd ;
651738 return 0 ;
@@ -1024,35 +1111,35 @@ static const struct rockchip_domain_info rk3568_pm_domains[] = {
10241111};
10251112
10261113static const struct rockchip_domain_info rk3588_pm_domains [] = {
1027- [RK3588_PD_GPU ] = DOMAIN_RK3588 ("gpu" , 0x0 , BIT (0 ), 0 , BIT (1 ), 0x0 , BIT (0 ), BIT (0 ), false),
1028- [RK3588_PD_NPU ] = DOMAIN_RK3588 ("npu" , 0x0 , BIT (1 ), BIT (1 ), 0 , 0x0 , 0 , 0 , false),
1029- [RK3588_PD_VCODEC ] = DOMAIN_RK3588 ("vcodec" , 0x0 , BIT (2 ), BIT (2 ), 0 , 0x0 , 0 , 0 , false),
1030- [RK3588_PD_NPUTOP ] = DOMAIN_RK3588 ("nputop" , 0x0 , BIT (3 ), 0 , BIT (2 ), 0x0 , BIT (1 ), BIT (1 ), false),
1031- [RK3588_PD_NPU1 ] = DOMAIN_RK3588 ("npu1" , 0x0 , BIT (4 ), 0 , BIT (3 ), 0x0 , BIT (2 ), BIT (2 ), false),
1032- [RK3588_PD_NPU2 ] = DOMAIN_RK3588 ("npu2" , 0x0 , BIT (5 ), 0 , BIT (4 ), 0x0 , BIT (3 ), BIT (3 ), false),
1033- [RK3588_PD_VENC0 ] = DOMAIN_RK3588 ("venc0" , 0x0 , BIT (6 ), 0 , BIT (5 ), 0x0 , BIT (4 ), BIT (4 ), false),
1034- [RK3588_PD_VENC1 ] = DOMAIN_RK3588 ("venc1" , 0x0 , BIT (7 ), 0 , BIT (6 ), 0x0 , BIT (5 ), BIT (5 ), false),
1035- [RK3588_PD_RKVDEC0 ] = DOMAIN_RK3588 ("rkvdec0" , 0x0 , BIT (8 ), 0 , BIT (7 ), 0x0 , BIT (6 ), BIT (6 ), false),
1036- [RK3588_PD_RKVDEC1 ] = DOMAIN_RK3588 ("rkvdec1" , 0x0 , BIT (9 ), 0 , BIT (8 ), 0x0 , BIT (7 ), BIT (7 ), false),
1037- [RK3588_PD_VDPU ] = DOMAIN_RK3588 ("vdpu" , 0x0 , BIT (10 ), 0 , BIT (9 ), 0x0 , BIT (8 ), BIT (8 ), false),
1038- [RK3588_PD_RGA30 ] = DOMAIN_RK3588 ("rga30" , 0x0 , BIT (11 ), 0 , BIT (10 ), 0x0 , 0 , 0 , false),
1039- [RK3588_PD_AV1 ] = DOMAIN_RK3588 ("av1" , 0x0 , BIT (12 ), 0 , BIT (11 ), 0x0 , BIT (9 ), BIT (9 ), false),
1040- [RK3588_PD_VI ] = DOMAIN_RK3588 ("vi" , 0x0 , BIT (13 ), 0 , BIT (12 ), 0x0 , BIT (10 ), BIT (10 ), false),
1041- [RK3588_PD_FEC ] = DOMAIN_RK3588 ("fec" , 0x0 , BIT (14 ), 0 , BIT (13 ), 0x0 , 0 , 0 , false),
1042- [RK3588_PD_ISP1 ] = DOMAIN_RK3588 ("isp1" , 0x0 , BIT (15 ), 0 , BIT (14 ), 0x0 , BIT (11 ), BIT (11 ), false),
1043- [RK3588_PD_RGA31 ] = DOMAIN_RK3588 ("rga31" , 0x4 , BIT (0 ), 0 , BIT (15 ), 0x0 , BIT (12 ), BIT (12 ), false),
1044- [RK3588_PD_VOP ] = DOMAIN_RK3588 ("vop" , 0x4 , BIT (1 ), 0 , BIT (16 ), 0x0 , BIT (13 ) | BIT (14 ), BIT (13 ) | BIT (14 ), false),
1045- [RK3588_PD_VO0 ] = DOMAIN_RK3588 ("vo0" , 0x4 , BIT (2 ), 0 , BIT (17 ), 0x0 , BIT (15 ), BIT (15 ), false),
1046- [RK3588_PD_VO1 ] = DOMAIN_RK3588 ("vo1" , 0x4 , BIT (3 ), 0 , BIT (18 ), 0x4 , BIT (0 ), BIT (16 ), false),
1047- [RK3588_PD_AUDIO ] = DOMAIN_RK3588 ("audio" , 0x4 , BIT (4 ), 0 , BIT (19 ), 0x4 , BIT (1 ), BIT (17 ), false),
1048- [RK3588_PD_PHP ] = DOMAIN_RK3588 ("php" , 0x4 , BIT (5 ), 0 , BIT (20 ), 0x4 , BIT (5 ), BIT (21 ), false),
1049- [RK3588_PD_GMAC ] = DOMAIN_RK3588 ("gmac" , 0x4 , BIT (6 ), 0 , BIT (21 ), 0x0 , 0 , 0 , false),
1050- [RK3588_PD_PCIE ] = DOMAIN_RK3588 ("pcie" , 0x4 , BIT (7 ), 0 , BIT (22 ), 0x0 , 0 , 0 , true),
1051- [RK3588_PD_NVM ] = DOMAIN_RK3588 ("nvm" , 0x4 , BIT (8 ), BIT (24 ), 0 , 0x4 , BIT (2 ), BIT (18 ), false),
1052- [RK3588_PD_NVM0 ] = DOMAIN_RK3588 ("nvm0" , 0x4 , BIT (9 ), 0 , BIT (23 ), 0x0 , 0 , 0 , false),
1053- [RK3588_PD_SDIO ] = DOMAIN_RK3588 ("sdio" , 0x4 , BIT (10 ), 0 , BIT (24 ), 0x4 , BIT (3 ), BIT (19 ), false),
1054- [RK3588_PD_USB ] = DOMAIN_RK3588 ("usb" , 0x4 , BIT (11 ), 0 , BIT (25 ), 0x4 , BIT (4 ), BIT (20 ), true),
1055- [RK3588_PD_SDMMC ] = DOMAIN_RK3588 ("sdmmc" , 0x4 , BIT (13 ), 0 , BIT (26 ), 0x0 , 0 , 0 , false),
1114+ [RK3588_PD_GPU ] = DOMAIN_RK3588 ("gpu" , 0x0 , BIT (0 ), 0 , 0x0 , 0 , BIT (1 ), 0x0 , BIT (0 ), BIT (0 ), false),
1115+ [RK3588_PD_NPU ] = DOMAIN_RK3588 ("npu" , 0x0 , BIT (1 ), BIT (1 ), 0x0 , 0 , 0 , 0x0 , 0 , 0 , false),
1116+ [RK3588_PD_VCODEC ] = DOMAIN_RK3588 ("vcodec" , 0x0 , BIT (2 ), BIT (2 ), 0x0 , 0 , 0 , 0x0 , 0 , 0 , false),
1117+ [RK3588_PD_NPUTOP ] = DOMAIN_RK3588 ("nputop" , 0x0 , BIT (3 ), 0 , 0x0 , BIT ( 11 ), BIT (2 ), 0x0 , BIT (1 ), BIT (1 ), false),
1118+ [RK3588_PD_NPU1 ] = DOMAIN_RK3588 ("npu1" , 0x0 , BIT (4 ), 0 , 0x0 , BIT ( 12 ), BIT (3 ), 0x0 , BIT (2 ), BIT (2 ), false),
1119+ [RK3588_PD_NPU2 ] = DOMAIN_RK3588 ("npu2" , 0x0 , BIT (5 ), 0 , 0x0 , BIT ( 13 ), BIT (4 ), 0x0 , BIT (3 ), BIT (3 ), false),
1120+ [RK3588_PD_VENC0 ] = DOMAIN_RK3588 ("venc0" , 0x0 , BIT (6 ), 0 , 0x0 , BIT ( 14 ), BIT (5 ), 0x0 , BIT (4 ), BIT (4 ), false),
1121+ [RK3588_PD_VENC1 ] = DOMAIN_RK3588 ("venc1" , 0x0 , BIT (7 ), 0 , 0x0 , BIT ( 15 ), BIT (6 ), 0x0 , BIT (5 ), BIT (5 ), false),
1122+ [RK3588_PD_RKVDEC0 ] = DOMAIN_RK3588 ("rkvdec0" , 0x0 , BIT (8 ), 0 , 0x0 , BIT ( 16 ), BIT (7 ), 0x0 , BIT (6 ), BIT (6 ), false),
1123+ [RK3588_PD_RKVDEC1 ] = DOMAIN_RK3588 ("rkvdec1" , 0x0 , BIT (9 ), 0 , 0x0 , BIT ( 17 ), BIT (8 ), 0x0 , BIT (7 ), BIT (7 ), false),
1124+ [RK3588_PD_VDPU ] = DOMAIN_RK3588 ("vdpu" , 0x0 , BIT (10 ), 0 , 0x0 , BIT ( 18 ), BIT (9 ), 0x0 , BIT (8 ), BIT (8 ), false),
1125+ [RK3588_PD_RGA30 ] = DOMAIN_RK3588 ("rga30" , 0x0 , BIT (11 ), 0 , 0x0 , BIT ( 19 ), BIT (10 ), 0x0 , 0 , 0 , false),
1126+ [RK3588_PD_AV1 ] = DOMAIN_RK3588 ("av1" , 0x0 , BIT (12 ), 0 , 0x0 , BIT ( 20 ), BIT (11 ), 0x0 , BIT (9 ), BIT (9 ), false),
1127+ [RK3588_PD_VI ] = DOMAIN_RK3588 ("vi" , 0x0 , BIT (13 ), 0 , 0x0 , BIT ( 21 ), BIT (12 ), 0x0 , BIT (10 ), BIT (10 ), false),
1128+ [RK3588_PD_FEC ] = DOMAIN_RK3588 ("fec" , 0x0 , BIT (14 ), 0 , 0x0 , BIT ( 22 ), BIT (13 ), 0x0 , 0 , 0 , false),
1129+ [RK3588_PD_ISP1 ] = DOMAIN_RK3588 ("isp1" , 0x0 , BIT (15 ), 0 , 0x0 , BIT ( 23 ), BIT (14 ), 0x0 , BIT (11 ), BIT (11 ), false),
1130+ [RK3588_PD_RGA31 ] = DOMAIN_RK3588 ("rga31" , 0x4 , BIT (0 ), 0 , 0x0 , BIT ( 24 ), BIT (15 ), 0x0 , BIT (12 ), BIT (12 ), false),
1131+ [RK3588_PD_VOP ] = DOMAIN_RK3588 ("vop" , 0x4 , BIT (1 ), 0 , 0x0 , BIT ( 25 ), BIT (16 ), 0x0 , BIT (13 ) | BIT (14 ), BIT (13 ) | BIT (14 ), false),
1132+ [RK3588_PD_VO0 ] = DOMAIN_RK3588 ("vo0" , 0x4 , BIT (2 ), 0 , 0x0 , BIT ( 26 ), BIT (17 ), 0x0 , BIT (15 ), BIT (15 ), false),
1133+ [RK3588_PD_VO1 ] = DOMAIN_RK3588 ("vo1" , 0x4 , BIT (3 ), 0 , 0x0 , BIT ( 27 ), BIT (18 ), 0x4 , BIT (0 ), BIT (16 ), false),
1134+ [RK3588_PD_AUDIO ] = DOMAIN_RK3588 ("audio" , 0x4 , BIT (4 ), 0 , 0x0 , BIT ( 28 ), BIT (19 ), 0x4 , BIT (1 ), BIT (17 ), false),
1135+ [RK3588_PD_PHP ] = DOMAIN_RK3588 ("php" , 0x4 , BIT (5 ), 0 , 0x0 , BIT ( 29 ), BIT (20 ), 0x4 , BIT (5 ), BIT (21 ), false),
1136+ [RK3588_PD_GMAC ] = DOMAIN_RK3588 ("gmac" , 0x4 , BIT (6 ), 0 , 0x0 , BIT ( 30 ), BIT (21 ), 0x0 , 0 , 0 , false),
1137+ [RK3588_PD_PCIE ] = DOMAIN_RK3588 ("pcie" , 0x4 , BIT (7 ), 0 , 0x0 , BIT ( 31 ), BIT (22 ), 0x0 , 0 , 0 , true),
1138+ [RK3588_PD_NVM ] = DOMAIN_RK3588 ("nvm" , 0x4 , BIT (8 ), BIT (24 ), 0x4 , 0 , 0 , 0x4 , BIT (2 ), BIT (18 ), false),
1139+ [RK3588_PD_NVM0 ] = DOMAIN_RK3588 ("nvm0" , 0x4 , BIT (9 ), 0 , 0x4 , BIT ( 1 ), BIT (23 ), 0x0 , 0 , 0 , false),
1140+ [RK3588_PD_SDIO ] = DOMAIN_RK3588 ("sdio" , 0x4 , BIT (10 ), 0 , 0x4 , BIT ( 2 ), BIT (24 ), 0x4 , BIT (3 ), BIT (19 ), false),
1141+ [RK3588_PD_USB ] = DOMAIN_RK3588 ("usb" , 0x4 , BIT (11 ), 0 , 0x4 , BIT ( 3 ), BIT (25 ), 0x4 , BIT (4 ), BIT (20 ), true),
1142+ [RK3588_PD_SDMMC ] = DOMAIN_RK3588 ("sdmmc" , 0x4 , BIT (13 ), 0 , 0x4 , BIT ( 5 ), BIT (26 ), 0x0 , 0 , 0 , false),
10561143};
10571144
10581145static const struct rockchip_pmu_info px30_pmu = {
@@ -1207,6 +1294,9 @@ static const struct rockchip_pmu_info rk3588_pmu = {
12071294 .req_offset = 0x10c ,
12081295 .idle_offset = 0x120 ,
12091296 .ack_offset = 0x118 ,
1297+ .mem_pwr_offset = 0x1a0 ,
1298+ .chain_status_offset = 0x1f0 ,
1299+ .mem_status_offset = 0x1f8 ,
12101300 .repair_status_offset = 0x290 ,
12111301
12121302 .num_domains = ARRAY_SIZE (rk3588_pm_domains ),
0 commit comments