1*036935a8SXiaoDong Huang // SPDX-License-Identifier: BSD-3-Clause
2*036935a8SXiaoDong Huang /*
3*036935a8SXiaoDong Huang * Copyright (c) 2025, Rockchip Electronics Co., Ltd.
4*036935a8SXiaoDong Huang */
5*036935a8SXiaoDong Huang
6*036935a8SXiaoDong Huang #include <assert.h>
7*036935a8SXiaoDong Huang #include <errno.h>
8*036935a8SXiaoDong Huang
9*036935a8SXiaoDong Huang #include <arch_helpers.h>
10*036935a8SXiaoDong Huang #include <bl31/bl31.h>
11*036935a8SXiaoDong Huang #include <common/debug.h>
12*036935a8SXiaoDong Huang #include <drivers/console.h>
13*036935a8SXiaoDong Huang #include <drivers/delay_timer.h>
14*036935a8SXiaoDong Huang #include <lib/mmio.h>
15*036935a8SXiaoDong Huang #include <platform.h>
16*036935a8SXiaoDong Huang #include <platform_def.h>
17*036935a8SXiaoDong Huang #include <pmu.h>
18*036935a8SXiaoDong Huang
19*036935a8SXiaoDong Huang #include <plat_pm_helpers.h>
20*036935a8SXiaoDong Huang #include <plat_private.h>
21*036935a8SXiaoDong Huang #include <pm_pd_regs.h>
22*036935a8SXiaoDong Huang #include <rk3576_clk.h>
23*036935a8SXiaoDong Huang #include <soc.h>
24*036935a8SXiaoDong Huang
25*036935a8SXiaoDong Huang #define WMSK_VAL 0xffff0000
26*036935a8SXiaoDong Huang
27*036935a8SXiaoDong Huang static struct reg_region qos_reg_rgns[] = {
28*036935a8SXiaoDong Huang [qos_decom] = REG_REGION(0x08, 0x18, 4, 0x27f00000, 0),
29*036935a8SXiaoDong Huang [qos_dmac0] = REG_REGION(0x08, 0x18, 4, 0x27f00080, 0),
30*036935a8SXiaoDong Huang [qos_dmac1] = REG_REGION(0x08, 0x18, 4, 0x27f00100, 0),
31*036935a8SXiaoDong Huang [qos_dmac2] = REG_REGION(0x08, 0x18, 4, 0x27f00180, 0),
32*036935a8SXiaoDong Huang [qos_bus_mcu] = REG_REGION(0x08, 0x18, 4, 0x27f00200, 0),
33*036935a8SXiaoDong Huang [qos_can0] = REG_REGION(0x08, 0x18, 4, 0x27f00280, 0),
34*036935a8SXiaoDong Huang [qos_can1] = REG_REGION(0x08, 0x18, 4, 0x27f00300, 0),
35*036935a8SXiaoDong Huang [qos_cci_m0] = REG_REGION(0x08, 0x18, 4, 0x27f01000, 0),
36*036935a8SXiaoDong Huang [qos_cci_m1] = REG_REGION(0x08, 0x18, 4, 0x27f18880, 0),
37*036935a8SXiaoDong Huang [qos_cci_m2] = REG_REGION(0x08, 0x18, 4, 0x27f18900, 0),
38*036935a8SXiaoDong Huang [qos_dap_lite] = REG_REGION(0x08, 0x18, 4, 0x27f01080, 0),
39*036935a8SXiaoDong Huang [qos_hdcp1] = REG_REGION(0x08, 0x18, 4, 0x27f02000, 0),
40*036935a8SXiaoDong Huang [qos_ddr_mcu] = REG_REGION(0x08, 0x18, 4, 0x27f03000, 0),
41*036935a8SXiaoDong Huang [qos_fspi1] = REG_REGION(0x08, 0x18, 4, 0x27f04000, 0),
42*036935a8SXiaoDong Huang [qos_gmac0] = REG_REGION(0x08, 0x18, 4, 0x27f04080, 0),
43*036935a8SXiaoDong Huang [qos_gmac1] = REG_REGION(0x08, 0x18, 4, 0x27f04100, 0),
44*036935a8SXiaoDong Huang [qos_sdio] = REG_REGION(0x08, 0x18, 4, 0x27f04180, 0),
45*036935a8SXiaoDong Huang [qos_sdmmc] = REG_REGION(0x08, 0x18, 4, 0x27f04200, 0),
46*036935a8SXiaoDong Huang [qos_flexbus] = REG_REGION(0x08, 0x18, 4, 0x27f04280, 0),
47*036935a8SXiaoDong Huang [qos_gpu] = REG_REGION(0x08, 0x18, 4, 0x27f05000, 0),
48*036935a8SXiaoDong Huang [qos_vepu1] = REG_REGION(0x08, 0x18, 4, 0x27f06000, 0),
49*036935a8SXiaoDong Huang [qos_npu_mcu] = REG_REGION(0x08, 0x18, 4, 0x27f08000, 0),
50*036935a8SXiaoDong Huang [qos_npu_nsp0] = REG_REGION(0x08, 0x18, 4, 0x27f08080, 0),
51*036935a8SXiaoDong Huang [qos_npu_nsp1] = REG_REGION(0x08, 0x18, 4, 0x27f08100, 0),
52*036935a8SXiaoDong Huang [qos_npu_m0] = REG_REGION(0x08, 0x18, 4, 0x27f20000, 0),
53*036935a8SXiaoDong Huang [qos_npu_m1] = REG_REGION(0x08, 0x18, 4, 0x27f21000, 0),
54*036935a8SXiaoDong Huang [qos_npu_m0ro] = REG_REGION(0x08, 0x18, 4, 0x27f22080, 0),
55*036935a8SXiaoDong Huang [qos_npu_m1ro] = REG_REGION(0x08, 0x18, 4, 0x27f22100, 0),
56*036935a8SXiaoDong Huang [qos_emmc] = REG_REGION(0x08, 0x18, 4, 0x27f09000, 0),
57*036935a8SXiaoDong Huang [qos_fspi0] = REG_REGION(0x08, 0x18, 4, 0x27f09080, 0),
58*036935a8SXiaoDong Huang [qos_mmu0] = REG_REGION(0x08, 0x18, 4, 0x27f0a000, 0),
59*036935a8SXiaoDong Huang [qos_mmu1] = REG_REGION(0x08, 0x18, 4, 0x27f0a080, 0),
60*036935a8SXiaoDong Huang [qos_pmu_mcu] = REG_REGION(0x08, 0x18, 4, 0x27f0b000, 0),
61*036935a8SXiaoDong Huang [qos_rkvdec] = REG_REGION(0x08, 0x18, 4, 0x27f0c000, 0),
62*036935a8SXiaoDong Huang [qos_crypto] = REG_REGION(0x08, 0x18, 4, 0x27f0d000, 0),
63*036935a8SXiaoDong Huang [qos_mmu2] = REG_REGION(0x08, 0x18, 4, 0x27f0e000, 0),
64*036935a8SXiaoDong Huang [qos_ufshc] = REG_REGION(0x08, 0x18, 4, 0x27f0e080, 0),
65*036935a8SXiaoDong Huang [qos_vepu0] = REG_REGION(0x08, 0x18, 4, 0x27f0f000, 0),
66*036935a8SXiaoDong Huang [qos_isp_mro] = REG_REGION(0x08, 0x18, 4, 0x27f10000, 0),
67*036935a8SXiaoDong Huang [qos_isp_mwo] = REG_REGION(0x08, 0x18, 4, 0x27f10080, 0),
68*036935a8SXiaoDong Huang [qos_vicap_m0] = REG_REGION(0x08, 0x18, 4, 0x27f10100, 0),
69*036935a8SXiaoDong Huang [qos_vpss_mro] = REG_REGION(0x08, 0x18, 4, 0x27f10180, 0),
70*036935a8SXiaoDong Huang [qos_vpss_mwo] = REG_REGION(0x08, 0x18, 4, 0x27f10200, 0),
71*036935a8SXiaoDong Huang [qos_hdcp0] = REG_REGION(0x08, 0x18, 4, 0x27f11000, 0),
72*036935a8SXiaoDong Huang [qos_vop_m0] = REG_REGION(0x08, 0x18, 4, 0x27f12800, 0),
73*036935a8SXiaoDong Huang [qos_vop_m1ro] = REG_REGION(0x08, 0x18, 4, 0x27f12880, 0),
74*036935a8SXiaoDong Huang [qos_ebc] = REG_REGION(0x08, 0x18, 4, 0x27f13000, 0),
75*036935a8SXiaoDong Huang [qos_rga0] = REG_REGION(0x08, 0x18, 4, 0x27f13080, 0),
76*036935a8SXiaoDong Huang [qos_rga1] = REG_REGION(0x08, 0x18, 4, 0x27f13100, 0),
77*036935a8SXiaoDong Huang [qos_jpeg] = REG_REGION(0x08, 0x18, 4, 0x27f13180, 0),
78*036935a8SXiaoDong Huang [qos_vdpp] = REG_REGION(0x08, 0x18, 4, 0x27f13200, 0),
79*036935a8SXiaoDong Huang [qos_dma2ddr] = REG_REGION(0x08, 0x18, 4, 0x27f15880, 0),
80*036935a8SXiaoDong Huang };
81*036935a8SXiaoDong Huang
82*036935a8SXiaoDong Huang static struct reg_region pd_bcore_reg_rgns[] = {
83*036935a8SXiaoDong Huang /* bcore cru */
84*036935a8SXiaoDong Huang /* REG_REGION(0x280, 0x280, 4, BIGCORE0CRU_BASE, WMSK_VAL), */
85*036935a8SXiaoDong Huang REG_REGION(0x300, 0x30c, 4, BIGCORE_CRU_BASE, WMSK_VAL),
86*036935a8SXiaoDong Huang REG_REGION(0x800, 0x804, 4, BIGCORE_CRU_BASE, WMSK_VAL),
87*036935a8SXiaoDong Huang REG_REGION(0xa00, 0xa0c, 4, BIGCORE_CRU_BASE, WMSK_VAL),
88*036935a8SXiaoDong Huang REG_REGION(0xcc0, 0xcc0, 4, BIGCORE_CRU_BASE, 0),
89*036935a8SXiaoDong Huang REG_REGION(0xf28, 0xf28, 8, BIGCORE_CRU_BASE, 0),
90*036935a8SXiaoDong Huang REG_REGION(0xf2c, 0xf2c, 8, BIGCORE_CRU_BASE, WMSK_VAL),
91*036935a8SXiaoDong Huang
92*036935a8SXiaoDong Huang /* bcore_grf */
93*036935a8SXiaoDong Huang REG_REGION(0x34, 0x3c, 4, BIGCORE_GRF_BASE, WMSK_VAL),
94*036935a8SXiaoDong Huang REG_REGION(0x44, 0x44, 4, BIGCORE_GRF_BASE, WMSK_VAL),
95*036935a8SXiaoDong Huang };
96*036935a8SXiaoDong Huang
97*036935a8SXiaoDong Huang static struct reg_region pd_core_reg_rgns[] = {
98*036935a8SXiaoDong Huang /* cci cru */
99*036935a8SXiaoDong Huang REG_REGION(0x310, 0x310, 4, CCI_CRU_BASE, WMSK_VAL),
100*036935a8SXiaoDong Huang REG_REGION(0x804, 0x808, 4, CCI_CRU_BASE, WMSK_VAL),
101*036935a8SXiaoDong Huang REG_REGION(0xa04, 0xa08, 4, CCI_CRU_BASE, WMSK_VAL),
102*036935a8SXiaoDong Huang REG_REGION(0xc50, 0xc58, 4, CCI_CRU_BASE, WMSK_VAL),
103*036935a8SXiaoDong Huang REG_REGION(0xd00, 0xd00, 8, CCI_CRU_BASE, 0),
104*036935a8SXiaoDong Huang REG_REGION(0xd04, 0xd04, 8, CCI_CRU_BASE, WMSK_VAL),
105*036935a8SXiaoDong Huang /* Restore lpll registers after clksel_* registers. Because lpll
106*036935a8SXiaoDong Huang * may be turned off during restoring, which cause cci_cru to lost clock.
107*036935a8SXiaoDong Huang */
108*036935a8SXiaoDong Huang REG_REGION(0x040, 0x044, 4, CCI_CRU_BASE, WMSK_VAL),
109*036935a8SXiaoDong Huang REG_REGION(0x048, 0x048, 4, CCI_CRU_BASE, 0),
110*036935a8SXiaoDong Huang REG_REGION(0x04c, 0x058, 4, CCI_CRU_BASE, WMSK_VAL),
111*036935a8SXiaoDong Huang
112*036935a8SXiaoDong Huang /* lcore cru */
113*036935a8SXiaoDong Huang /* REG_REGION(0x280, 0x280, 4, BIGCORE1CRU_BASE, WMSK_VAL), */
114*036935a8SXiaoDong Huang REG_REGION(0x300, 0x30c, 4, LITTLE_CRU_BASE, WMSK_VAL),
115*036935a8SXiaoDong Huang REG_REGION(0x800, 0x804, 4, LITTLE_CRU_BASE, WMSK_VAL),
116*036935a8SXiaoDong Huang REG_REGION(0xa00, 0xa0c, 4, LITTLE_CRU_BASE, WMSK_VAL),
117*036935a8SXiaoDong Huang REG_REGION(0xcc0, 0xcc0, 4, LITTLE_CRU_BASE, 0),
118*036935a8SXiaoDong Huang REG_REGION(0xf38, 0xf38, 8, LITTLE_CRU_BASE, 0),
119*036935a8SXiaoDong Huang REG_REGION(0xf3c, 0xf3c, 8, LITTLE_CRU_BASE, WMSK_VAL),
120*036935a8SXiaoDong Huang
121*036935a8SXiaoDong Huang /* bcore cru */
122*036935a8SXiaoDong Huang /* REG_REGION(0x280, 0x280, 4, BIGCORE0CRU_BASE, WMSK_VAL), */
123*036935a8SXiaoDong Huang REG_REGION(0x300, 0x30c, 4, BIGCORE_CRU_BASE, WMSK_VAL),
124*036935a8SXiaoDong Huang REG_REGION(0x800, 0x804, 4, BIGCORE_CRU_BASE, WMSK_VAL),
125*036935a8SXiaoDong Huang REG_REGION(0xa00, 0xa0c, 4, BIGCORE_CRU_BASE, WMSK_VAL),
126*036935a8SXiaoDong Huang REG_REGION(0xcc0, 0xcc0, 4, BIGCORE_CRU_BASE, 0),
127*036935a8SXiaoDong Huang REG_REGION(0xf28, 0xf28, 8, BIGCORE_CRU_BASE, 0),
128*036935a8SXiaoDong Huang REG_REGION(0xf2c, 0xf2c, 8, BIGCORE_CRU_BASE, WMSK_VAL),
129*036935a8SXiaoDong Huang
130*036935a8SXiaoDong Huang /* cci grf */
131*036935a8SXiaoDong Huang REG_REGION(0x00, 0x10, 4, CCI_GRF_BASE, WMSK_VAL),
132*036935a8SXiaoDong Huang REG_REGION(0x54, 0x54, 4, CCI_GRF_BASE, WMSK_VAL),
133*036935a8SXiaoDong Huang
134*036935a8SXiaoDong Huang /* lcore_grf */
135*036935a8SXiaoDong Huang REG_REGION(0x34, 0x3c, 4, LITCORE_GRF_BASE, WMSK_VAL),
136*036935a8SXiaoDong Huang REG_REGION(0x44, 0x44, 4, LITCORE_GRF_BASE, WMSK_VAL),
137*036935a8SXiaoDong Huang
138*036935a8SXiaoDong Huang /* bcore_grf */
139*036935a8SXiaoDong Huang REG_REGION(0x34, 0x3c, 4, BIGCORE_GRF_BASE, WMSK_VAL),
140*036935a8SXiaoDong Huang REG_REGION(0x44, 0x44, 4, BIGCORE_GRF_BASE, WMSK_VAL),
141*036935a8SXiaoDong Huang };
142*036935a8SXiaoDong Huang
143*036935a8SXiaoDong Huang static struct reg_region pd_php_reg_rgns[] = {
144*036935a8SXiaoDong Huang /* php_grf */
145*036935a8SXiaoDong Huang REG_REGION(0x004, 0x00c, 4, PHP_GRF_BASE, WMSK_VAL),
146*036935a8SXiaoDong Huang REG_REGION(0x010, 0x018, 4, PHP_GRF_BASE, 0),
147*036935a8SXiaoDong Huang REG_REGION(0x01c, 0x020, 4, PHP_GRF_BASE, WMSK_VAL),
148*036935a8SXiaoDong Huang REG_REGION(0x048, 0x048, 4, PHP_GRF_BASE, 0),
149*036935a8SXiaoDong Huang };
150*036935a8SXiaoDong Huang
151*036935a8SXiaoDong Huang static struct reg_region pd_usb2phy_reg_rgns[] = {
152*036935a8SXiaoDong Huang /* usb */
153*036935a8SXiaoDong Huang REG_REGION(0x00, 0x14, 4, USB2PHY0_GRF_BASE, WMSK_VAL),
154*036935a8SXiaoDong Huang REG_REGION(0x40, 0x40, 4, USB2PHY0_GRF_BASE, WMSK_VAL),
155*036935a8SXiaoDong Huang REG_REGION(0x44, 0x50, 4, USB2PHY0_GRF_BASE, 0),
156*036935a8SXiaoDong Huang REG_REGION(0x00, 0x14, 4, USB2PHY1_GRF_BASE, WMSK_VAL),
157*036935a8SXiaoDong Huang REG_REGION(0x08, 0x08, 4, USBDPPHY_GRF_BASE, WMSK_VAL),
158*036935a8SXiaoDong Huang };
159*036935a8SXiaoDong Huang
160*036935a8SXiaoDong Huang #define PLL_LOCKED_TIMEOUT 600000U
161*036935a8SXiaoDong Huang
pm_pll_wait_lock(uint32_t pll_base)162*036935a8SXiaoDong Huang static void pm_pll_wait_lock(uint32_t pll_base)
163*036935a8SXiaoDong Huang {
164*036935a8SXiaoDong Huang int delay = PLL_LOCKED_TIMEOUT;
165*036935a8SXiaoDong Huang
166*036935a8SXiaoDong Huang if ((mmio_read_32(pll_base + CRU_PLL_CON(1)) & CRU_PLLCON1_PWRDOWN) != 0)
167*036935a8SXiaoDong Huang return;
168*036935a8SXiaoDong Huang
169*036935a8SXiaoDong Huang while (delay-- >= 0) {
170*036935a8SXiaoDong Huang if ((mmio_read_32(pll_base + CRU_PLL_CON(6)) & CRU_PLLCON6_LOCK_STATUS) != 0)
171*036935a8SXiaoDong Huang break;
172*036935a8SXiaoDong Huang udelay(1);
173*036935a8SXiaoDong Huang }
174*036935a8SXiaoDong Huang
175*036935a8SXiaoDong Huang if (delay <= 0)
176*036935a8SXiaoDong Huang ERROR("Can't wait pll(0x%x) lock\n", pll_base);
177*036935a8SXiaoDong Huang }
178*036935a8SXiaoDong Huang
qos_save(void)179*036935a8SXiaoDong Huang void qos_save(void)
180*036935a8SXiaoDong Huang {
181*036935a8SXiaoDong Huang uint32_t pmu_pd_st = mmio_read_32(PMU_BASE + PMU2_PWR_GATE_ST);
182*036935a8SXiaoDong Huang
183*036935a8SXiaoDong Huang if ((pmu_pd_st & BIT(pmu_pd_nvm)) == 0) {
184*036935a8SXiaoDong Huang rockchip_reg_rgn_save(&qos_reg_rgns[qos_emmc], 1);
185*036935a8SXiaoDong Huang rockchip_reg_rgn_save(&qos_reg_rgns[qos_fspi0], 1);
186*036935a8SXiaoDong Huang }
187*036935a8SXiaoDong Huang
188*036935a8SXiaoDong Huang if ((pmu_pd_st & BIT(pmu_pd_sd_gmac)) == 0) {
189*036935a8SXiaoDong Huang rockchip_reg_rgn_save(&qos_reg_rgns[qos_fspi1], 1);
190*036935a8SXiaoDong Huang rockchip_reg_rgn_save(&qos_reg_rgns[qos_gmac0], 1);
191*036935a8SXiaoDong Huang rockchip_reg_rgn_save(&qos_reg_rgns[qos_gmac1], 1);
192*036935a8SXiaoDong Huang rockchip_reg_rgn_save(&qos_reg_rgns[qos_sdio], 1);
193*036935a8SXiaoDong Huang rockchip_reg_rgn_save(&qos_reg_rgns[qos_sdmmc], 1);
194*036935a8SXiaoDong Huang rockchip_reg_rgn_save(&qos_reg_rgns[qos_flexbus], 1);
195*036935a8SXiaoDong Huang }
196*036935a8SXiaoDong Huang
197*036935a8SXiaoDong Huang if ((pmu_pd_st & BIT(pmu_pd_php)) == 0) {
198*036935a8SXiaoDong Huang rockchip_reg_rgn_save(&qos_reg_rgns[qos_mmu0], 1);
199*036935a8SXiaoDong Huang rockchip_reg_rgn_save(&qos_reg_rgns[qos_mmu1], 1);
200*036935a8SXiaoDong Huang }
201*036935a8SXiaoDong Huang
202*036935a8SXiaoDong Huang if ((pmu_pd_st & BIT(pmu_pd_vop)) == 0) {
203*036935a8SXiaoDong Huang rockchip_reg_rgn_save(&qos_reg_rgns[qos_vop_m0], 1);
204*036935a8SXiaoDong Huang rockchip_reg_rgn_save(&qos_reg_rgns[qos_vop_m1ro], 1);
205*036935a8SXiaoDong Huang }
206*036935a8SXiaoDong Huang
207*036935a8SXiaoDong Huang if ((pmu_pd_st & BIT(pmu_pd_vo1)) == 0)
208*036935a8SXiaoDong Huang rockchip_reg_rgn_save(&qos_reg_rgns[qos_hdcp1], 1);
209*036935a8SXiaoDong Huang
210*036935a8SXiaoDong Huang if ((pmu_pd_st & BIT(pmu_pd_vo0)) == 0)
211*036935a8SXiaoDong Huang rockchip_reg_rgn_save(&qos_reg_rgns[qos_hdcp0], 1);
212*036935a8SXiaoDong Huang
213*036935a8SXiaoDong Huang if ((pmu_pd_st & BIT(pmu_pd_usb)) == 0) {
214*036935a8SXiaoDong Huang rockchip_reg_rgn_save(&qos_reg_rgns[qos_mmu2], 1);
215*036935a8SXiaoDong Huang rockchip_reg_rgn_save(&qos_reg_rgns[qos_ufshc], 1);
216*036935a8SXiaoDong Huang }
217*036935a8SXiaoDong Huang
218*036935a8SXiaoDong Huang if ((pmu_pd_st & BIT(pmu_pd_vi)) == 0) {
219*036935a8SXiaoDong Huang rockchip_reg_rgn_save(&qos_reg_rgns[qos_isp_mro], 1);
220*036935a8SXiaoDong Huang rockchip_reg_rgn_save(&qos_reg_rgns[qos_isp_mwo], 1);
221*036935a8SXiaoDong Huang rockchip_reg_rgn_save(&qos_reg_rgns[qos_vicap_m0], 1);
222*036935a8SXiaoDong Huang rockchip_reg_rgn_save(&qos_reg_rgns[qos_vpss_mro], 1);
223*036935a8SXiaoDong Huang rockchip_reg_rgn_save(&qos_reg_rgns[qos_vpss_mwo], 1);
224*036935a8SXiaoDong Huang }
225*036935a8SXiaoDong Huang
226*036935a8SXiaoDong Huang if ((pmu_pd_st & BIT(pmu_pd_vepu0)) == 0)
227*036935a8SXiaoDong Huang rockchip_reg_rgn_save(&qos_reg_rgns[qos_vepu0], 1);
228*036935a8SXiaoDong Huang
229*036935a8SXiaoDong Huang if ((pmu_pd_st & BIT(pmu_pd_vepu1)) == 0)
230*036935a8SXiaoDong Huang rockchip_reg_rgn_save(&qos_reg_rgns[qos_vepu1], 1);
231*036935a8SXiaoDong Huang
232*036935a8SXiaoDong Huang if ((pmu_pd_st & BIT(pmu_pd_vdec)) == 0)
233*036935a8SXiaoDong Huang rockchip_reg_rgn_save(&qos_reg_rgns[qos_rkvdec], 1);
234*036935a8SXiaoDong Huang
235*036935a8SXiaoDong Huang if ((pmu_pd_st & BIT(pmu_pd_vpu)) == 0) {
236*036935a8SXiaoDong Huang rockchip_reg_rgn_save(&qos_reg_rgns[qos_ebc], 1);
237*036935a8SXiaoDong Huang rockchip_reg_rgn_save(&qos_reg_rgns[qos_rga0], 1);
238*036935a8SXiaoDong Huang rockchip_reg_rgn_save(&qos_reg_rgns[qos_rga1], 1);
239*036935a8SXiaoDong Huang rockchip_reg_rgn_save(&qos_reg_rgns[qos_jpeg], 1);
240*036935a8SXiaoDong Huang rockchip_reg_rgn_save(&qos_reg_rgns[qos_vdpp], 1);
241*036935a8SXiaoDong Huang }
242*036935a8SXiaoDong Huang
243*036935a8SXiaoDong Huang if ((pmu_pd_st & BIT(pmu_pd_nputop)) == 0) {
244*036935a8SXiaoDong Huang rockchip_reg_rgn_save(&qos_reg_rgns[qos_npu_mcu], 1);
245*036935a8SXiaoDong Huang rockchip_reg_rgn_save(&qos_reg_rgns[qos_npu_nsp0], 1);
246*036935a8SXiaoDong Huang rockchip_reg_rgn_save(&qos_reg_rgns[qos_npu_nsp1], 1);
247*036935a8SXiaoDong Huang rockchip_reg_rgn_save(&qos_reg_rgns[qos_npu_m0ro], 1);
248*036935a8SXiaoDong Huang rockchip_reg_rgn_save(&qos_reg_rgns[qos_npu_m1ro], 1);
249*036935a8SXiaoDong Huang }
250*036935a8SXiaoDong Huang
251*036935a8SXiaoDong Huang if ((pmu_pd_st & BIT(pmu_pd_npu0)) == 0)
252*036935a8SXiaoDong Huang rockchip_reg_rgn_save(&qos_reg_rgns[qos_npu_m0], 1);
253*036935a8SXiaoDong Huang
254*036935a8SXiaoDong Huang if ((pmu_pd_st & BIT(pmu_pd_npu1)) == 0)
255*036935a8SXiaoDong Huang rockchip_reg_rgn_save(&qos_reg_rgns[qos_npu_m1], 1);
256*036935a8SXiaoDong Huang
257*036935a8SXiaoDong Huang if ((pmu_pd_st & BIT(pmu_pd_gpu)) == 0)
258*036935a8SXiaoDong Huang rockchip_reg_rgn_save(&qos_reg_rgns[qos_gpu], 1);
259*036935a8SXiaoDong Huang }
260*036935a8SXiaoDong Huang
qos_restore(void)261*036935a8SXiaoDong Huang void qos_restore(void)
262*036935a8SXiaoDong Huang {
263*036935a8SXiaoDong Huang uint32_t pmu_pd_st = mmio_read_32(PMU_BASE + PMU2_PWR_GATE_ST);
264*036935a8SXiaoDong Huang
265*036935a8SXiaoDong Huang if ((pmu_pd_st & BIT(pmu_pd_nvm)) == 0) {
266*036935a8SXiaoDong Huang rockchip_reg_rgn_restore(&qos_reg_rgns[qos_emmc], 1);
267*036935a8SXiaoDong Huang rockchip_reg_rgn_restore(&qos_reg_rgns[qos_fspi0], 1);
268*036935a8SXiaoDong Huang }
269*036935a8SXiaoDong Huang
270*036935a8SXiaoDong Huang if ((pmu_pd_st & BIT(pmu_pd_sd_gmac)) == 0) {
271*036935a8SXiaoDong Huang rockchip_reg_rgn_restore(&qos_reg_rgns[qos_fspi1], 1);
272*036935a8SXiaoDong Huang rockchip_reg_rgn_restore(&qos_reg_rgns[qos_gmac0], 1);
273*036935a8SXiaoDong Huang rockchip_reg_rgn_restore(&qos_reg_rgns[qos_gmac1], 1);
274*036935a8SXiaoDong Huang rockchip_reg_rgn_restore(&qos_reg_rgns[qos_sdio], 1);
275*036935a8SXiaoDong Huang rockchip_reg_rgn_restore(&qos_reg_rgns[qos_sdmmc], 1);
276*036935a8SXiaoDong Huang rockchip_reg_rgn_restore(&qos_reg_rgns[qos_flexbus], 1);
277*036935a8SXiaoDong Huang }
278*036935a8SXiaoDong Huang
279*036935a8SXiaoDong Huang if ((pmu_pd_st & BIT(pmu_pd_php)) == 0) {
280*036935a8SXiaoDong Huang rockchip_reg_rgn_restore(&qos_reg_rgns[qos_mmu0], 1);
281*036935a8SXiaoDong Huang rockchip_reg_rgn_restore(&qos_reg_rgns[qos_mmu1], 1);
282*036935a8SXiaoDong Huang }
283*036935a8SXiaoDong Huang
284*036935a8SXiaoDong Huang if ((pmu_pd_st & BIT(pmu_pd_vop)) == 0) {
285*036935a8SXiaoDong Huang rockchip_reg_rgn_restore(&qos_reg_rgns[qos_vop_m0], 1);
286*036935a8SXiaoDong Huang rockchip_reg_rgn_restore(&qos_reg_rgns[qos_vop_m1ro], 1);
287*036935a8SXiaoDong Huang }
288*036935a8SXiaoDong Huang
289*036935a8SXiaoDong Huang if ((pmu_pd_st & BIT(pmu_pd_vo1)) == 0)
290*036935a8SXiaoDong Huang rockchip_reg_rgn_restore(&qos_reg_rgns[qos_hdcp1], 1);
291*036935a8SXiaoDong Huang
292*036935a8SXiaoDong Huang if ((pmu_pd_st & BIT(pmu_pd_vo0)) == 0)
293*036935a8SXiaoDong Huang rockchip_reg_rgn_restore(&qos_reg_rgns[qos_hdcp0], 1);
294*036935a8SXiaoDong Huang
295*036935a8SXiaoDong Huang if ((pmu_pd_st & BIT(pmu_pd_usb)) == 0) {
296*036935a8SXiaoDong Huang rockchip_reg_rgn_restore(&qos_reg_rgns[qos_mmu2], 1);
297*036935a8SXiaoDong Huang rockchip_reg_rgn_restore(&qos_reg_rgns[qos_ufshc], 1);
298*036935a8SXiaoDong Huang }
299*036935a8SXiaoDong Huang
300*036935a8SXiaoDong Huang if ((pmu_pd_st & BIT(pmu_pd_vi)) == 0) {
301*036935a8SXiaoDong Huang rockchip_reg_rgn_restore(&qos_reg_rgns[qos_isp_mro], 1);
302*036935a8SXiaoDong Huang rockchip_reg_rgn_restore(&qos_reg_rgns[qos_isp_mwo], 1);
303*036935a8SXiaoDong Huang rockchip_reg_rgn_restore(&qos_reg_rgns[qos_vicap_m0], 1);
304*036935a8SXiaoDong Huang rockchip_reg_rgn_restore(&qos_reg_rgns[qos_vpss_mro], 1);
305*036935a8SXiaoDong Huang rockchip_reg_rgn_restore(&qos_reg_rgns[qos_vpss_mwo], 1);
306*036935a8SXiaoDong Huang }
307*036935a8SXiaoDong Huang
308*036935a8SXiaoDong Huang if ((pmu_pd_st & BIT(pmu_pd_vepu0)) == 0)
309*036935a8SXiaoDong Huang rockchip_reg_rgn_restore(&qos_reg_rgns[qos_vepu0], 1);
310*036935a8SXiaoDong Huang
311*036935a8SXiaoDong Huang if ((pmu_pd_st & BIT(pmu_pd_vepu1)) == 0)
312*036935a8SXiaoDong Huang rockchip_reg_rgn_restore(&qos_reg_rgns[qos_vepu1], 1);
313*036935a8SXiaoDong Huang
314*036935a8SXiaoDong Huang if ((pmu_pd_st & BIT(pmu_pd_vdec)) == 0)
315*036935a8SXiaoDong Huang rockchip_reg_rgn_restore(&qos_reg_rgns[qos_rkvdec], 1);
316*036935a8SXiaoDong Huang
317*036935a8SXiaoDong Huang if ((pmu_pd_st & BIT(pmu_pd_vpu)) == 0) {
318*036935a8SXiaoDong Huang rockchip_reg_rgn_restore(&qos_reg_rgns[qos_ebc], 1);
319*036935a8SXiaoDong Huang rockchip_reg_rgn_restore(&qos_reg_rgns[qos_rga0], 1);
320*036935a8SXiaoDong Huang rockchip_reg_rgn_restore(&qos_reg_rgns[qos_rga1], 1);
321*036935a8SXiaoDong Huang rockchip_reg_rgn_restore(&qos_reg_rgns[qos_jpeg], 1);
322*036935a8SXiaoDong Huang rockchip_reg_rgn_restore(&qos_reg_rgns[qos_vdpp], 1);
323*036935a8SXiaoDong Huang }
324*036935a8SXiaoDong Huang
325*036935a8SXiaoDong Huang if ((pmu_pd_st & BIT(pmu_pd_nputop)) == 0) {
326*036935a8SXiaoDong Huang rockchip_reg_rgn_restore(&qos_reg_rgns[qos_npu_mcu], 1);
327*036935a8SXiaoDong Huang rockchip_reg_rgn_restore(&qos_reg_rgns[qos_npu_nsp0], 1);
328*036935a8SXiaoDong Huang rockchip_reg_rgn_restore(&qos_reg_rgns[qos_npu_nsp1], 1);
329*036935a8SXiaoDong Huang rockchip_reg_rgn_restore(&qos_reg_rgns[qos_npu_m0ro], 1);
330*036935a8SXiaoDong Huang rockchip_reg_rgn_restore(&qos_reg_rgns[qos_npu_m1ro], 1);
331*036935a8SXiaoDong Huang }
332*036935a8SXiaoDong Huang
333*036935a8SXiaoDong Huang if ((pmu_pd_st & BIT(pmu_pd_npu0)) == 0)
334*036935a8SXiaoDong Huang rockchip_reg_rgn_restore(&qos_reg_rgns[qos_npu_m0], 1);
335*036935a8SXiaoDong Huang
336*036935a8SXiaoDong Huang if ((pmu_pd_st & BIT(pmu_pd_npu1)) == 0)
337*036935a8SXiaoDong Huang rockchip_reg_rgn_restore(&qos_reg_rgns[qos_npu_m1], 1);
338*036935a8SXiaoDong Huang
339*036935a8SXiaoDong Huang if ((pmu_pd_st & BIT(pmu_pd_gpu)) == 0)
340*036935a8SXiaoDong Huang rockchip_reg_rgn_restore(&qos_reg_rgns[qos_gpu], 1);
341*036935a8SXiaoDong Huang }
342*036935a8SXiaoDong Huang
pd_usb2phy_save(void)343*036935a8SXiaoDong Huang void pd_usb2phy_save(void)
344*036935a8SXiaoDong Huang {
345*036935a8SXiaoDong Huang rockchip_reg_rgn_save(pd_usb2phy_reg_rgns, ARRAY_SIZE(pd_usb2phy_reg_rgns));
346*036935a8SXiaoDong Huang }
347*036935a8SXiaoDong Huang
pd_usb2phy_restore(void)348*036935a8SXiaoDong Huang void pd_usb2phy_restore(void)
349*036935a8SXiaoDong Huang {
350*036935a8SXiaoDong Huang rockchip_reg_rgn_restore(pd_usb2phy_reg_rgns, ARRAY_SIZE(pd_usb2phy_reg_rgns));
351*036935a8SXiaoDong Huang }
352*036935a8SXiaoDong Huang
353*036935a8SXiaoDong Huang static uint32_t b_cru_mode, l_cru_mode;
354*036935a8SXiaoDong Huang static uint32_t bcore_need_restore;
355*036935a8SXiaoDong Huang
pd_bcore_save(void)356*036935a8SXiaoDong Huang void pd_bcore_save(void)
357*036935a8SXiaoDong Huang {
358*036935a8SXiaoDong Huang pvtplls_cpub_suspend();
359*036935a8SXiaoDong Huang
360*036935a8SXiaoDong Huang b_cru_mode = mmio_read_32(BIGCORE_CRU_BASE + 0x280);
361*036935a8SXiaoDong Huang rockchip_reg_rgn_save(pd_bcore_reg_rgns, ARRAY_SIZE(pd_bcore_reg_rgns));
362*036935a8SXiaoDong Huang
363*036935a8SXiaoDong Huang bcore_need_restore = 1;
364*036935a8SXiaoDong Huang }
365*036935a8SXiaoDong Huang
pd_bcore_restore(void)366*036935a8SXiaoDong Huang void pd_bcore_restore(void)
367*036935a8SXiaoDong Huang {
368*036935a8SXiaoDong Huang if (bcore_need_restore == 0)
369*036935a8SXiaoDong Huang return;
370*036935a8SXiaoDong Huang
371*036935a8SXiaoDong Huang /* slow mode */
372*036935a8SXiaoDong Huang mmio_write_32(BIGCORE_CRU_BASE + 0x280, 0x00030000);
373*036935a8SXiaoDong Huang
374*036935a8SXiaoDong Huang rockchip_reg_rgn_restore(pd_bcore_reg_rgns, ARRAY_SIZE(pd_bcore_reg_rgns));
375*036935a8SXiaoDong Huang
376*036935a8SXiaoDong Huang /* trigger lcore/bcore mem_cfg */
377*036935a8SXiaoDong Huang mmio_write_32(BIGCORE_GRF_BASE + 0x38, BITS_WITH_WMASK(1, 0x1, 1));
378*036935a8SXiaoDong Huang udelay(1);
379*036935a8SXiaoDong Huang mmio_write_32(BIGCORE_GRF_BASE + 0x38, BITS_WITH_WMASK(0, 0x1, 1));
380*036935a8SXiaoDong Huang
381*036935a8SXiaoDong Huang /* restore mode */
382*036935a8SXiaoDong Huang mmio_write_32(BIGCORE_CRU_BASE + 0x280, WITH_16BITS_WMSK(b_cru_mode));
383*036935a8SXiaoDong Huang
384*036935a8SXiaoDong Huang pvtplls_cpub_resume();
385*036935a8SXiaoDong Huang
386*036935a8SXiaoDong Huang bcore_need_restore = 0;
387*036935a8SXiaoDong Huang }
388*036935a8SXiaoDong Huang
pd_core_save(void)389*036935a8SXiaoDong Huang void pd_core_save(void)
390*036935a8SXiaoDong Huang {
391*036935a8SXiaoDong Huang pvtplls_suspend();
392*036935a8SXiaoDong Huang
393*036935a8SXiaoDong Huang b_cru_mode = mmio_read_32(BIGCORE_CRU_BASE + 0x280);
394*036935a8SXiaoDong Huang l_cru_mode = mmio_read_32(LITTLE_CRU_BASE + 0x280);
395*036935a8SXiaoDong Huang
396*036935a8SXiaoDong Huang rockchip_reg_rgn_save(&qos_reg_rgns[qos_cci_m0], 1);
397*036935a8SXiaoDong Huang rockchip_reg_rgn_save(&qos_reg_rgns[qos_cci_m1], 1);
398*036935a8SXiaoDong Huang rockchip_reg_rgn_save(&qos_reg_rgns[qos_cci_m2], 1);
399*036935a8SXiaoDong Huang rockchip_reg_rgn_save(&qos_reg_rgns[qos_dap_lite], 1);
400*036935a8SXiaoDong Huang
401*036935a8SXiaoDong Huang rockchip_reg_rgn_save(pd_core_reg_rgns, ARRAY_SIZE(pd_core_reg_rgns));
402*036935a8SXiaoDong Huang }
403*036935a8SXiaoDong Huang
pd_core_restore(void)404*036935a8SXiaoDong Huang void pd_core_restore(void)
405*036935a8SXiaoDong Huang {
406*036935a8SXiaoDong Huang /* slow mode */
407*036935a8SXiaoDong Huang mmio_write_32(BIGCORE_CRU_BASE + 0x280, 0x00030000);
408*036935a8SXiaoDong Huang mmio_write_32(LITTLE_CRU_BASE + 0x280, 0x00030000);
409*036935a8SXiaoDong Huang
410*036935a8SXiaoDong Huang rockchip_reg_rgn_restore(pd_core_reg_rgns, ARRAY_SIZE(pd_core_reg_rgns));
411*036935a8SXiaoDong Huang
412*036935a8SXiaoDong Huang /* trigger lcore/bcore mem_cfg */
413*036935a8SXiaoDong Huang mmio_write_32(LITCORE_GRF_BASE + 0x38, BITS_WITH_WMASK(1, 0x1, 1));
414*036935a8SXiaoDong Huang mmio_write_32(BIGCORE_GRF_BASE + 0x38, BITS_WITH_WMASK(1, 0x1, 1));
415*036935a8SXiaoDong Huang udelay(1);
416*036935a8SXiaoDong Huang mmio_write_32(LITCORE_GRF_BASE + 0x38, BITS_WITH_WMASK(0, 0x1, 1));
417*036935a8SXiaoDong Huang mmio_write_32(BIGCORE_GRF_BASE + 0x38, BITS_WITH_WMASK(0, 0x1, 1));
418*036935a8SXiaoDong Huang
419*036935a8SXiaoDong Huang /* wait lock */
420*036935a8SXiaoDong Huang pm_pll_wait_lock(CCI_CRU_BASE + 0x40);
421*036935a8SXiaoDong Huang
422*036935a8SXiaoDong Huang /* restore mode */
423*036935a8SXiaoDong Huang mmio_write_32(BIGCORE_CRU_BASE + 0x280, WITH_16BITS_WMSK(b_cru_mode));
424*036935a8SXiaoDong Huang mmio_write_32(LITTLE_CRU_BASE + 0x280, WITH_16BITS_WMSK(l_cru_mode));
425*036935a8SXiaoDong Huang
426*036935a8SXiaoDong Huang rockchip_reg_rgn_restore(&qos_reg_rgns[qos_cci_m0], 1);
427*036935a8SXiaoDong Huang rockchip_reg_rgn_restore(&qos_reg_rgns[qos_cci_m1], 1);
428*036935a8SXiaoDong Huang rockchip_reg_rgn_restore(&qos_reg_rgns[qos_cci_m2], 1);
429*036935a8SXiaoDong Huang rockchip_reg_rgn_restore(&qos_reg_rgns[qos_dap_lite], 1);
430*036935a8SXiaoDong Huang
431*036935a8SXiaoDong Huang pvtplls_resume();
432*036935a8SXiaoDong Huang }
433*036935a8SXiaoDong Huang
pd_php_save(void)434*036935a8SXiaoDong Huang void pd_php_save(void)
435*036935a8SXiaoDong Huang {
436*036935a8SXiaoDong Huang rockchip_reg_rgn_save(pd_php_reg_rgns, ARRAY_SIZE(pd_php_reg_rgns));
437*036935a8SXiaoDong Huang }
438*036935a8SXiaoDong Huang
pd_php_restore(void)439*036935a8SXiaoDong Huang void pd_php_restore(void)
440*036935a8SXiaoDong Huang {
441*036935a8SXiaoDong Huang rockchip_reg_rgn_restore(pd_php_reg_rgns, ARRAY_SIZE(pd_php_reg_rgns));
442*036935a8SXiaoDong Huang }
443*036935a8SXiaoDong Huang
pm_reg_rgns_init(void)444*036935a8SXiaoDong Huang void pm_reg_rgns_init(void)
445*036935a8SXiaoDong Huang {
446*036935a8SXiaoDong Huang rockchip_alloc_region_mem(qos_reg_rgns, ARRAY_SIZE(qos_reg_rgns));
447*036935a8SXiaoDong Huang rockchip_alloc_region_mem(pd_bcore_reg_rgns, ARRAY_SIZE(pd_bcore_reg_rgns));
448*036935a8SXiaoDong Huang rockchip_alloc_region_mem(pd_core_reg_rgns, ARRAY_SIZE(pd_core_reg_rgns));
449*036935a8SXiaoDong Huang rockchip_alloc_region_mem(pd_php_reg_rgns, ARRAY_SIZE(pd_php_reg_rgns));
450*036935a8SXiaoDong Huang rockchip_alloc_region_mem(pd_usb2phy_reg_rgns, ARRAY_SIZE(pd_usb2phy_reg_rgns));
451*036935a8SXiaoDong Huang }
452