xref: /rk3399_ARM-atf/plat/rockchip/rk3588/drivers/pmu/pmu.c (revision e3ec6ff4b24c7daa4dfa82709c23a22829947160)
1*e3ec6ff4SXiaoDong Huang /*
2*e3ec6ff4SXiaoDong Huang  * Copyright (c) 2024, Rockchip, Inc. All rights reserved.
3*e3ec6ff4SXiaoDong Huang  *
4*e3ec6ff4SXiaoDong Huang  * SPDX-License-Identifier: BSD-3-Clause
5*e3ec6ff4SXiaoDong Huang  */
6*e3ec6ff4SXiaoDong Huang 
7*e3ec6ff4SXiaoDong Huang #include <assert.h>
8*e3ec6ff4SXiaoDong Huang #include <errno.h>
9*e3ec6ff4SXiaoDong Huang 
10*e3ec6ff4SXiaoDong Huang #include <arch_helpers.h>
11*e3ec6ff4SXiaoDong Huang #include <bl31/bl31.h>
12*e3ec6ff4SXiaoDong Huang #include <common/debug.h>
13*e3ec6ff4SXiaoDong Huang #include <drivers/arm/gicv3.h>
14*e3ec6ff4SXiaoDong Huang #include <drivers/console.h>
15*e3ec6ff4SXiaoDong Huang #include <drivers/delay_timer.h>
16*e3ec6ff4SXiaoDong Huang #include <drivers/ti/uart/uart_16550.h>
17*e3ec6ff4SXiaoDong Huang #include <lib/mmio.h>
18*e3ec6ff4SXiaoDong Huang #include <plat/common/platform.h>
19*e3ec6ff4SXiaoDong Huang #include <platform_def.h>
20*e3ec6ff4SXiaoDong Huang #include <pmu.h>
21*e3ec6ff4SXiaoDong Huang 
22*e3ec6ff4SXiaoDong Huang #include <cpus_on_fixed_addr.h>
23*e3ec6ff4SXiaoDong Huang #include <plat_pm_helpers.h>
24*e3ec6ff4SXiaoDong Huang #include <plat_private.h>
25*e3ec6ff4SXiaoDong Huang #include <pm_pd_regs.h>
26*e3ec6ff4SXiaoDong Huang #include <rockchip_sip_svc.h>
27*e3ec6ff4SXiaoDong Huang #include <secure.h>
28*e3ec6ff4SXiaoDong Huang #include <soc.h>
29*e3ec6ff4SXiaoDong Huang 
30*e3ec6ff4SXiaoDong Huang #define PSRAM_SP_TOP	((PMUSRAM_BASE + PMUSRAM_RSIZE) & ~0xf)
31*e3ec6ff4SXiaoDong Huang #define NONBOOT_CPUS_OFF_LOOP (500000)
32*e3ec6ff4SXiaoDong Huang 
33*e3ec6ff4SXiaoDong Huang #define DSUGRF_REG_CNT			(0x78 / 4 + 1)
34*e3ec6ff4SXiaoDong Huang #define BCORE_GRF_REG_CNT		(0x30 / 4 + 1)
35*e3ec6ff4SXiaoDong Huang #define LCORE_GRF_REG_CNT		(0x30 / 4 + 1)
36*e3ec6ff4SXiaoDong Huang 
37*e3ec6ff4SXiaoDong Huang #define CENTER_GRF_REG_CNT		(0x20 / 4 + 1)
38*e3ec6ff4SXiaoDong Huang 
39*e3ec6ff4SXiaoDong Huang static struct psram_data_t *psram_sleep_cfg =
40*e3ec6ff4SXiaoDong Huang 	(struct psram_data_t *)&sys_sleep_flag_sram;
41*e3ec6ff4SXiaoDong Huang 
42*e3ec6ff4SXiaoDong Huang static int8_t pd_repair_map[] = {
43*e3ec6ff4SXiaoDong Huang 	[PD_GPU] = PD_RPR_GPU,
44*e3ec6ff4SXiaoDong Huang 	[PD_NPU] = -1,
45*e3ec6ff4SXiaoDong Huang 	[PD_VCODEC] = -1,
46*e3ec6ff4SXiaoDong Huang 	[PD_NPUTOP] = PD_RPR_NPUTOP,
47*e3ec6ff4SXiaoDong Huang 	[PD_NPU1] = PD_RPR_NPU1,
48*e3ec6ff4SXiaoDong Huang 	[PD_NPU2] = PD_RPR_NPU2,
49*e3ec6ff4SXiaoDong Huang 	[PD_VENC0] = PD_RPR_VENC0,
50*e3ec6ff4SXiaoDong Huang 	[PD_VENC1] = PD_RPR_VENC1,
51*e3ec6ff4SXiaoDong Huang 	[PD_RKVDEC0] = PD_RPR_RKVDEC0,
52*e3ec6ff4SXiaoDong Huang 	[PD_RKVDEC1] = PD_RPR_RKVDEC1,
53*e3ec6ff4SXiaoDong Huang 	[PD_VDPU] = PD_RPR_VDPU,
54*e3ec6ff4SXiaoDong Huang 	[PD_RGA30] = PD_RPR_RGA30,
55*e3ec6ff4SXiaoDong Huang 	[PD_AV1] = PD_RPR_AV1,
56*e3ec6ff4SXiaoDong Huang 	[PD_VI] = PD_RPR_VI,
57*e3ec6ff4SXiaoDong Huang 	[PD_FEC] = PD_RPR_FEC,
58*e3ec6ff4SXiaoDong Huang 	[PD_ISP1] = PD_RPR_ISP1,
59*e3ec6ff4SXiaoDong Huang 	[PD_RGA31] = PD_RPR_RGA31,
60*e3ec6ff4SXiaoDong Huang 	[PD_VOP] = PD_RPR_VOP,
61*e3ec6ff4SXiaoDong Huang 	[PD_VO0] = PD_RPR_VO0,
62*e3ec6ff4SXiaoDong Huang 	[PD_VO1] = PD_RPR_VO1,
63*e3ec6ff4SXiaoDong Huang 	[PD_AUDIO] = PD_RPR_AUDIO,
64*e3ec6ff4SXiaoDong Huang 	[PD_PHP] = PD_RPR_PHP,
65*e3ec6ff4SXiaoDong Huang 	[PD_GMAC] = PD_RPR_GMAC,
66*e3ec6ff4SXiaoDong Huang 	[PD_PCIE] = PD_RPR_PCIE,
67*e3ec6ff4SXiaoDong Huang 	[PD_NVM] = -1,
68*e3ec6ff4SXiaoDong Huang 	[PD_NVM0] = PD_RPR_NVM0,
69*e3ec6ff4SXiaoDong Huang 	[PD_SDIO] = PD_RPR_SDIO,
70*e3ec6ff4SXiaoDong Huang 	[PD_USB] = PD_RPR_USB,
71*e3ec6ff4SXiaoDong Huang 	[PD_SECURE] = -1,
72*e3ec6ff4SXiaoDong Huang 	[PD_SDMMC] = PD_RPR_SDMMC,
73*e3ec6ff4SXiaoDong Huang 	[PD_CRYPTO] = PD_RPR_CRYPTO,
74*e3ec6ff4SXiaoDong Huang 	[PD_CENTER] = PD_RPR_CENTER,
75*e3ec6ff4SXiaoDong Huang 	[PD_DDR01] = PD_RPR_DDR01,
76*e3ec6ff4SXiaoDong Huang 	[PD_DDR23] = PD_RPR_DDR23,
77*e3ec6ff4SXiaoDong Huang };
78*e3ec6ff4SXiaoDong Huang 
79*e3ec6ff4SXiaoDong Huang struct rk3588_sleep_ddr_data {
80*e3ec6ff4SXiaoDong Huang 	uint32_t gpio0a_iomux_l, gpio0a_iomux_h, gpio0b_iomux_l;
81*e3ec6ff4SXiaoDong Huang 	uint32_t pmu_pd_st0, bus_idle_st0, qch_pwr_st;
82*e3ec6ff4SXiaoDong Huang 	uint32_t pmu2_vol_gate_con[3], pmu2_submem_gate_sft_con0;
83*e3ec6ff4SXiaoDong Huang 	uint32_t pmu2_bisr_con0;
84*e3ec6ff4SXiaoDong Huang 	uint32_t cpll_con0;
85*e3ec6ff4SXiaoDong Huang 	uint32_t cru_mode_con, busscru_mode_con;
86*e3ec6ff4SXiaoDong Huang 	uint32_t bussgrf_soc_con7;
87*e3ec6ff4SXiaoDong Huang 	uint32_t pmu0grf_soc_con0, pmu0grf_soc_con1, pmu0grf_soc_con3;
88*e3ec6ff4SXiaoDong Huang 	uint32_t pmu1grf_soc_con2, pmu1grf_soc_con7, pmu1grf_soc_con8, pmu1grf_soc_con9;
89*e3ec6ff4SXiaoDong Huang 	uint32_t pmu0sgrf_soc_con1;
90*e3ec6ff4SXiaoDong Huang 	uint32_t pmu1sgrf_soc_con14;
91*e3ec6ff4SXiaoDong Huang 	uint32_t ddrgrf_chn_con0[4], ddrgrf_chn_con1[4],
92*e3ec6ff4SXiaoDong Huang 		ddrgrf_chn_con2[4], pmu1_ddr_pwr_sft_con[4];
93*e3ec6ff4SXiaoDong Huang 	uint32_t pmu1cru_clksel_con1;
94*e3ec6ff4SXiaoDong Huang };
95*e3ec6ff4SXiaoDong Huang 
96*e3ec6ff4SXiaoDong Huang static struct rk3588_sleep_ddr_data ddr_data;
97*e3ec6ff4SXiaoDong Huang 
98*e3ec6ff4SXiaoDong Huang struct rk3588_sleep_pmusram_data {
99*e3ec6ff4SXiaoDong Huang 	uint32_t dsusgrf_soc_con[DSUSGRF_SOC_CON_CNT],
100*e3ec6ff4SXiaoDong Huang 		dsusgrf_ddr_hash_con[DSUSGRF_DDR_HASH_CON_CNT];
101*e3ec6ff4SXiaoDong Huang 	uint32_t dsu_ddr_fw_rgn_reg[FIREWALL_DSU_RGN_CNT],
102*e3ec6ff4SXiaoDong Huang 		dsu_ddr_fw_mst_reg[FIREWALL_DSU_MST_CNT],
103*e3ec6ff4SXiaoDong Huang 		dsu_ddr_fw_con_reg[FIREWALL_DSU_CON_CNT];
104*e3ec6ff4SXiaoDong Huang 	uint32_t busioc_gpio0b_iomux_h;
105*e3ec6ff4SXiaoDong Huang };
106*e3ec6ff4SXiaoDong Huang 
107*e3ec6ff4SXiaoDong Huang static __pmusramdata struct rk3588_sleep_pmusram_data pmusram_data;
108*e3ec6ff4SXiaoDong Huang 
109*e3ec6ff4SXiaoDong Huang static __pmusramfunc void dsu_restore_early(void)
110*e3ec6ff4SXiaoDong Huang {
111*e3ec6ff4SXiaoDong Huang 	int i;
112*e3ec6ff4SXiaoDong Huang 
113*e3ec6ff4SXiaoDong Huang 	/* dsusgrf */
114*e3ec6ff4SXiaoDong Huang 	for (i = 0; i < DSUSGRF_SOC_CON_CNT; i++)
115*e3ec6ff4SXiaoDong Huang 		mmio_write_32(DSUSGRF_BASE + DSUSGRF_SOC_CON(i),
116*e3ec6ff4SXiaoDong Huang 			      WITH_16BITS_WMSK(pmusram_data.dsusgrf_soc_con[i]));
117*e3ec6ff4SXiaoDong Huang 
118*e3ec6ff4SXiaoDong Huang 	for (i = 0; i < DSUSGRF_DDR_HASH_CON_CNT; i++)
119*e3ec6ff4SXiaoDong Huang 		mmio_write_32(DSUSGRF_BASE + DSUSGRF_DDR_HASH_CON(i),
120*e3ec6ff4SXiaoDong Huang 			      pmusram_data.dsusgrf_ddr_hash_con[i]);
121*e3ec6ff4SXiaoDong Huang 
122*e3ec6ff4SXiaoDong Huang 	/* dsu ddr firewall */
123*e3ec6ff4SXiaoDong Huang 	for (i = 0; i < FIREWALL_DSU_RGN_CNT; i++)
124*e3ec6ff4SXiaoDong Huang 		mmio_write_32(FIREWALL_DSU_BASE + FIREWALL_DSU_RGN(i),
125*e3ec6ff4SXiaoDong Huang 			      pmusram_data.dsu_ddr_fw_rgn_reg[i]);
126*e3ec6ff4SXiaoDong Huang 
127*e3ec6ff4SXiaoDong Huang 	for (i = 0; i < FIREWALL_DSU_MST_CNT; i++)
128*e3ec6ff4SXiaoDong Huang 		mmio_write_32(FIREWALL_DSU_BASE + FIREWALL_DSU_MST(i),
129*e3ec6ff4SXiaoDong Huang 			      pmusram_data.dsu_ddr_fw_mst_reg[i]);
130*e3ec6ff4SXiaoDong Huang 
131*e3ec6ff4SXiaoDong Huang 	for (i = 0; i < FIREWALL_DSU_CON_CNT; i++)
132*e3ec6ff4SXiaoDong Huang 		mmio_write_32(FIREWALL_DSU_BASE + FIREWALL_DSU_CON(i),
133*e3ec6ff4SXiaoDong Huang 			      pmusram_data.dsu_ddr_fw_con_reg[i]);
134*e3ec6ff4SXiaoDong Huang }
135*e3ec6ff4SXiaoDong Huang 
136*e3ec6ff4SXiaoDong Huang static __pmusramfunc void ddr_resume(void)
137*e3ec6ff4SXiaoDong Huang {
138*e3ec6ff4SXiaoDong Huang 	dsu_restore_early();
139*e3ec6ff4SXiaoDong Huang }
140*e3ec6ff4SXiaoDong Huang 
141*e3ec6ff4SXiaoDong Huang static void dsu_core_save(void)
142*e3ec6ff4SXiaoDong Huang {
143*e3ec6ff4SXiaoDong Huang 	int i;
144*e3ec6ff4SXiaoDong Huang 
145*e3ec6ff4SXiaoDong Huang 	/* dsusgrf */
146*e3ec6ff4SXiaoDong Huang 	for (i = 0; i < DSUSGRF_SOC_CON_CNT; i++)
147*e3ec6ff4SXiaoDong Huang 		pmusram_data.dsusgrf_soc_con[i] =
148*e3ec6ff4SXiaoDong Huang 			mmio_read_32(DSUSGRF_BASE + DSUSGRF_SOC_CON(i));
149*e3ec6ff4SXiaoDong Huang 
150*e3ec6ff4SXiaoDong Huang 	for (i = 0; i < DSUSGRF_DDR_HASH_CON_CNT; i++)
151*e3ec6ff4SXiaoDong Huang 		pmusram_data.dsusgrf_ddr_hash_con[i] =
152*e3ec6ff4SXiaoDong Huang 			mmio_read_32(DSUSGRF_BASE + DSUSGRF_DDR_HASH_CON(i));
153*e3ec6ff4SXiaoDong Huang 
154*e3ec6ff4SXiaoDong Huang 	/* dsu ddr firewall */
155*e3ec6ff4SXiaoDong Huang 	for (i = 0; i < FIREWALL_DSU_RGN_CNT; i++)
156*e3ec6ff4SXiaoDong Huang 		pmusram_data.dsu_ddr_fw_rgn_reg[i] =
157*e3ec6ff4SXiaoDong Huang 			mmio_read_32(FIREWALL_DSU_BASE + FIREWALL_DSU_RGN(i));
158*e3ec6ff4SXiaoDong Huang 
159*e3ec6ff4SXiaoDong Huang 	for (i = 0; i < FIREWALL_DSU_MST_CNT; i++)
160*e3ec6ff4SXiaoDong Huang 		pmusram_data.dsu_ddr_fw_mst_reg[i] =
161*e3ec6ff4SXiaoDong Huang 			mmio_read_32(FIREWALL_DSU_BASE + FIREWALL_DSU_MST(i));
162*e3ec6ff4SXiaoDong Huang 
163*e3ec6ff4SXiaoDong Huang 	for (i = 0; i < FIREWALL_DSU_CON_CNT; i++)
164*e3ec6ff4SXiaoDong Huang 		pmusram_data.dsu_ddr_fw_con_reg[i] =
165*e3ec6ff4SXiaoDong Huang 			mmio_read_32(FIREWALL_DSU_BASE + FIREWALL_DSU_CON(i));
166*e3ec6ff4SXiaoDong Huang 
167*e3ec6ff4SXiaoDong Huang 	pd_dsu_core_save();
168*e3ec6ff4SXiaoDong Huang }
169*e3ec6ff4SXiaoDong Huang 
170*e3ec6ff4SXiaoDong Huang static void dsu_core_restore(void)
171*e3ec6ff4SXiaoDong Huang {
172*e3ec6ff4SXiaoDong Huang 	pd_dsu_core_restore();
173*e3ec6ff4SXiaoDong Huang }
174*e3ec6ff4SXiaoDong Huang 
175*e3ec6ff4SXiaoDong Huang static uint32_t clk_save[CRU_CLKGATE_CON_CNT + PHPCRU_CLKGATE_CON_CNT +
176*e3ec6ff4SXiaoDong Huang 			 SECURECRU_CLKGATE_CON_CNT + PMU1CRU_CLKGATE_CON_CNT];
177*e3ec6ff4SXiaoDong Huang 
178*e3ec6ff4SXiaoDong Huang void clk_gate_con_save(void)
179*e3ec6ff4SXiaoDong Huang {
180*e3ec6ff4SXiaoDong Huang 	int i, j = 0;
181*e3ec6ff4SXiaoDong Huang 
182*e3ec6ff4SXiaoDong Huang 	for (i = 0; i < CRU_CLKGATE_CON_CNT; i++, j++)
183*e3ec6ff4SXiaoDong Huang 		clk_save[j] = mmio_read_32(CRU_BASE + CRU_CLKGATE_CON(i));
184*e3ec6ff4SXiaoDong Huang 
185*e3ec6ff4SXiaoDong Huang 	clk_save[j] = mmio_read_32(PHP_CRU_BASE + PHPCRU_CLKGATE_CON);
186*e3ec6ff4SXiaoDong Huang 
187*e3ec6ff4SXiaoDong Huang 	for (i = 0; i < SECURECRU_CLKGATE_CON_CNT; i++, j++)
188*e3ec6ff4SXiaoDong Huang 		clk_save[j] = mmio_read_32(SCRU_BASE + SECURECRU_CLKGATE_CON(i));
189*e3ec6ff4SXiaoDong Huang 
190*e3ec6ff4SXiaoDong Huang 	for (i = 0; i < PMU1CRU_CLKGATE_CON_CNT; i++, j++)
191*e3ec6ff4SXiaoDong Huang 		clk_save[j] = mmio_read_32(PMU1CRU_BASE + CRU_CLKGATE_CON(i));
192*e3ec6ff4SXiaoDong Huang }
193*e3ec6ff4SXiaoDong Huang 
194*e3ec6ff4SXiaoDong Huang void clk_gate_con_disable(void)
195*e3ec6ff4SXiaoDong Huang {
196*e3ec6ff4SXiaoDong Huang 	int i;
197*e3ec6ff4SXiaoDong Huang 
198*e3ec6ff4SXiaoDong Huang 	for (i = 0; i < CRU_CLKGATE_CON_CNT; i++)
199*e3ec6ff4SXiaoDong Huang 		mmio_write_32(CRU_BASE + CRU_CLKGATE_CON(i), 0xffff0000);
200*e3ec6ff4SXiaoDong Huang 
201*e3ec6ff4SXiaoDong Huang 	 mmio_write_32(PHP_CRU_BASE + PHPCRU_CLKGATE_CON, 0xffff0000);
202*e3ec6ff4SXiaoDong Huang 
203*e3ec6ff4SXiaoDong Huang 	for (i = 0; i < SECURECRU_CLKGATE_CON_CNT; i++)
204*e3ec6ff4SXiaoDong Huang 		mmio_write_32(SCRU_BASE + SECURECRU_CLKGATE_CON(i), 0xffff0000);
205*e3ec6ff4SXiaoDong Huang 
206*e3ec6ff4SXiaoDong Huang 	for (i = 0; i < PMU1CRU_CLKGATE_CON_CNT; i++)
207*e3ec6ff4SXiaoDong Huang 		mmio_write_32(PMU1CRU_BASE + CRU_CLKGATE_CON(i), 0xffff0000);
208*e3ec6ff4SXiaoDong Huang }
209*e3ec6ff4SXiaoDong Huang 
210*e3ec6ff4SXiaoDong Huang void clk_gate_con_restore(void)
211*e3ec6ff4SXiaoDong Huang {
212*e3ec6ff4SXiaoDong Huang 	int i, j = 0;
213*e3ec6ff4SXiaoDong Huang 
214*e3ec6ff4SXiaoDong Huang 	for (i = 0; i < CRU_CLKGATE_CON_CNT; i++, j++)
215*e3ec6ff4SXiaoDong Huang 		mmio_write_32(CRU_BASE + CRU_CLKGATE_CON(i),
216*e3ec6ff4SXiaoDong Huang 			      WITH_16BITS_WMSK(clk_save[j]));
217*e3ec6ff4SXiaoDong Huang 
218*e3ec6ff4SXiaoDong Huang 	mmio_write_32(PHP_CRU_BASE + PHPCRU_CLKGATE_CON,
219*e3ec6ff4SXiaoDong Huang 		      WITH_16BITS_WMSK(clk_save[j]));
220*e3ec6ff4SXiaoDong Huang 
221*e3ec6ff4SXiaoDong Huang 	for (i = 0; i < SECURECRU_CLKGATE_CON_CNT; i++, j++)
222*e3ec6ff4SXiaoDong Huang 		mmio_write_32(SCRU_BASE + SECURECRU_CLKGATE_CON(i),
223*e3ec6ff4SXiaoDong Huang 			      WITH_16BITS_WMSK(clk_save[j]));
224*e3ec6ff4SXiaoDong Huang 
225*e3ec6ff4SXiaoDong Huang 	for (i = 0; i < PMU1CRU_CLKGATE_CON_CNT; i++, j++)
226*e3ec6ff4SXiaoDong Huang 		mmio_write_32(PMU1CRU_BASE + CRU_CLKGATE_CON(i),
227*e3ec6ff4SXiaoDong Huang 			      WITH_16BITS_WMSK(clk_save[j]));
228*e3ec6ff4SXiaoDong Huang }
229*e3ec6ff4SXiaoDong Huang 
230*e3ec6ff4SXiaoDong Huang static void pmu_bus_idle_req(uint32_t bus, uint32_t state)
231*e3ec6ff4SXiaoDong Huang {
232*e3ec6ff4SXiaoDong Huang 	uint32_t wait_cnt = 0;
233*e3ec6ff4SXiaoDong Huang 
234*e3ec6ff4SXiaoDong Huang 	mmio_write_32(PMU_BASE + PMU2_BUS_IDLE_SFTCON(bus / 16),
235*e3ec6ff4SXiaoDong Huang 		      BITS_WITH_WMASK(state, 0x1, bus % 16));
236*e3ec6ff4SXiaoDong Huang 
237*e3ec6ff4SXiaoDong Huang 	while (pmu_bus_idle_st(bus) != state ||
238*e3ec6ff4SXiaoDong Huang 	       pmu_bus_idle_ack(bus) != state) {
239*e3ec6ff4SXiaoDong Huang 		if (++wait_cnt > BUS_IDLE_LOOP)
240*e3ec6ff4SXiaoDong Huang 			break;
241*e3ec6ff4SXiaoDong Huang 		udelay(1);
242*e3ec6ff4SXiaoDong Huang 	}
243*e3ec6ff4SXiaoDong Huang 
244*e3ec6ff4SXiaoDong Huang 	if (wait_cnt > BUS_IDLE_LOOP)
245*e3ec6ff4SXiaoDong Huang 		WARN("%s: can't  wait state %d for bus %d (0x%x)\n",
246*e3ec6ff4SXiaoDong Huang 		     __func__, state, bus,
247*e3ec6ff4SXiaoDong Huang 		     mmio_read_32(PMU_BASE + PMU2_BUS_IDLE_ST(bus / 32)));
248*e3ec6ff4SXiaoDong Huang }
249*e3ec6ff4SXiaoDong Huang 
250*e3ec6ff4SXiaoDong Huang static void pmu_qch_pwr_ctlr(uint32_t msk, uint32_t state)
251*e3ec6ff4SXiaoDong Huang {
252*e3ec6ff4SXiaoDong Huang 	uint32_t wait_cnt = 0;
253*e3ec6ff4SXiaoDong Huang 
254*e3ec6ff4SXiaoDong Huang 	if (state != 0)
255*e3ec6ff4SXiaoDong Huang 		state = msk;
256*e3ec6ff4SXiaoDong Huang 
257*e3ec6ff4SXiaoDong Huang 	mmio_write_32(PMU_BASE + PMU2_QCHANNEL_PWR_SFTCON,
258*e3ec6ff4SXiaoDong Huang 		      BITS_WITH_WMASK(state, msk, 0));
259*e3ec6ff4SXiaoDong Huang 
260*e3ec6ff4SXiaoDong Huang 	while ((mmio_read_32(PMU_BASE + PMU2_QCHANNEL_STATUS) & msk) != state) {
261*e3ec6ff4SXiaoDong Huang 		if (++wait_cnt > QCH_PWR_LOOP)
262*e3ec6ff4SXiaoDong Huang 			break;
263*e3ec6ff4SXiaoDong Huang 		udelay(1);
264*e3ec6ff4SXiaoDong Huang 	}
265*e3ec6ff4SXiaoDong Huang 
266*e3ec6ff4SXiaoDong Huang 	if (wait_cnt > BUS_IDLE_LOOP)
267*e3ec6ff4SXiaoDong Huang 		WARN("%s: can't wait qch:0x%x to state:0x%x (0x%x)\n",
268*e3ec6ff4SXiaoDong Huang 		     __func__, msk, state,
269*e3ec6ff4SXiaoDong Huang 		     mmio_read_32(PMU_BASE + PMU2_QCHANNEL_STATUS));
270*e3ec6ff4SXiaoDong Huang }
271*e3ec6ff4SXiaoDong Huang 
272*e3ec6ff4SXiaoDong Huang static inline uint32_t pmu_power_domain_chain_st(uint32_t pd)
273*e3ec6ff4SXiaoDong Huang {
274*e3ec6ff4SXiaoDong Huang 	return mmio_read_32(PMU_BASE + PMU2_PWR_CHAIN1_ST(pd / 32)) & BIT(pd % 32) ?
275*e3ec6ff4SXiaoDong Huang 	       pmu_pd_on :
276*e3ec6ff4SXiaoDong Huang 	       pmu_pd_off;
277*e3ec6ff4SXiaoDong Huang }
278*e3ec6ff4SXiaoDong Huang 
279*e3ec6ff4SXiaoDong Huang static inline uint32_t pmu_power_domain_mem_st(uint32_t pd)
280*e3ec6ff4SXiaoDong Huang {
281*e3ec6ff4SXiaoDong Huang 	return mmio_read_32(PMU_BASE + PMU2_PWR_MEM_ST(pd / 32)) & BIT(pd % 32) ?
282*e3ec6ff4SXiaoDong Huang 	       pmu_pd_off :
283*e3ec6ff4SXiaoDong Huang 	       pmu_pd_on;
284*e3ec6ff4SXiaoDong Huang }
285*e3ec6ff4SXiaoDong Huang 
286*e3ec6ff4SXiaoDong Huang static inline uint32_t pmu_power_domain_st(uint32_t pd)
287*e3ec6ff4SXiaoDong Huang {
288*e3ec6ff4SXiaoDong Huang 	int8_t pd_repair = pd_repair_map[pd];
289*e3ec6ff4SXiaoDong Huang 
290*e3ec6ff4SXiaoDong Huang 	if (pd_repair >= 0)
291*e3ec6ff4SXiaoDong Huang 		return mmio_read_32(PMU_BASE + PMU2_BISR_STATUS(4)) & BIT(pd_repair) ?
292*e3ec6ff4SXiaoDong Huang 		       pmu_pd_on :
293*e3ec6ff4SXiaoDong Huang 		       pmu_pd_off;
294*e3ec6ff4SXiaoDong Huang 	else
295*e3ec6ff4SXiaoDong Huang 		return mmio_read_32(PMU_BASE + PMU2_PWR_GATE_ST(pd / 32)) & BIT(pd % 32) ?
296*e3ec6ff4SXiaoDong Huang 		       pmu_pd_off :
297*e3ec6ff4SXiaoDong Huang 		       pmu_pd_on;
298*e3ec6ff4SXiaoDong Huang }
299*e3ec6ff4SXiaoDong Huang 
300*e3ec6ff4SXiaoDong Huang static int pmu_power_domain_pd_to_mem_st(uint32_t pd, uint32_t *pd_mem_st)
301*e3ec6ff4SXiaoDong Huang {
302*e3ec6ff4SXiaoDong Huang 	uint32_t mem_st;
303*e3ec6ff4SXiaoDong Huang 
304*e3ec6ff4SXiaoDong Huang 	switch (pd) {
305*e3ec6ff4SXiaoDong Huang 	case PD_NPUTOP:
306*e3ec6ff4SXiaoDong Huang 		mem_st = PD_NPU_TOP_MEM_ST;
307*e3ec6ff4SXiaoDong Huang 		break;
308*e3ec6ff4SXiaoDong Huang 	case PD_NPU1:
309*e3ec6ff4SXiaoDong Huang 		mem_st = PD_NPU1_MEM_ST;
310*e3ec6ff4SXiaoDong Huang 		break;
311*e3ec6ff4SXiaoDong Huang 	case PD_NPU2:
312*e3ec6ff4SXiaoDong Huang 		mem_st = PD_NPU2_MEM_ST;
313*e3ec6ff4SXiaoDong Huang 		break;
314*e3ec6ff4SXiaoDong Huang 	case PD_VENC0:
315*e3ec6ff4SXiaoDong Huang 		mem_st = PD_VENC0_MEM_ST;
316*e3ec6ff4SXiaoDong Huang 		break;
317*e3ec6ff4SXiaoDong Huang 	case PD_VENC1:
318*e3ec6ff4SXiaoDong Huang 		mem_st = PD_VENC1_MEM_ST;
319*e3ec6ff4SXiaoDong Huang 		break;
320*e3ec6ff4SXiaoDong Huang 	case PD_RKVDEC0:
321*e3ec6ff4SXiaoDong Huang 		mem_st = PD_RKVDEC0_MEM_ST;
322*e3ec6ff4SXiaoDong Huang 		break;
323*e3ec6ff4SXiaoDong Huang 	case PD_RKVDEC1:
324*e3ec6ff4SXiaoDong Huang 		mem_st = PD_RKVDEC1_MEM_ST;
325*e3ec6ff4SXiaoDong Huang 		break;
326*e3ec6ff4SXiaoDong Huang 	case PD_RGA30:
327*e3ec6ff4SXiaoDong Huang 		mem_st = PD_RGA30_MEM_ST;
328*e3ec6ff4SXiaoDong Huang 		break;
329*e3ec6ff4SXiaoDong Huang 	case PD_AV1:
330*e3ec6ff4SXiaoDong Huang 		mem_st = PD_AV1_MEM_ST;
331*e3ec6ff4SXiaoDong Huang 		break;
332*e3ec6ff4SXiaoDong Huang 	case PD_VI:
333*e3ec6ff4SXiaoDong Huang 		mem_st = PD_VI_MEM_ST;
334*e3ec6ff4SXiaoDong Huang 		break;
335*e3ec6ff4SXiaoDong Huang 	case PD_FEC:
336*e3ec6ff4SXiaoDong Huang 		mem_st = PD_FEC_MEM_ST;
337*e3ec6ff4SXiaoDong Huang 		break;
338*e3ec6ff4SXiaoDong Huang 	case PD_ISP1:
339*e3ec6ff4SXiaoDong Huang 		mem_st = PD_ISP1_MEM_ST;
340*e3ec6ff4SXiaoDong Huang 		break;
341*e3ec6ff4SXiaoDong Huang 	case PD_RGA31:
342*e3ec6ff4SXiaoDong Huang 		mem_st = PD_RGA31_MEM_ST;
343*e3ec6ff4SXiaoDong Huang 		break;
344*e3ec6ff4SXiaoDong Huang 	case PD_VOP:
345*e3ec6ff4SXiaoDong Huang 		mem_st = PD_VOP_MEM_ST;
346*e3ec6ff4SXiaoDong Huang 		break;
347*e3ec6ff4SXiaoDong Huang 	case PD_VO0:
348*e3ec6ff4SXiaoDong Huang 		mem_st = PD_VO0_MEM_ST;
349*e3ec6ff4SXiaoDong Huang 		break;
350*e3ec6ff4SXiaoDong Huang 	case PD_VO1:
351*e3ec6ff4SXiaoDong Huang 		mem_st = PD_VO1_MEM_ST;
352*e3ec6ff4SXiaoDong Huang 		break;
353*e3ec6ff4SXiaoDong Huang 	case PD_AUDIO:
354*e3ec6ff4SXiaoDong Huang 		mem_st = PD_AUDIO_MEM_ST;
355*e3ec6ff4SXiaoDong Huang 		break;
356*e3ec6ff4SXiaoDong Huang 	case PD_PHP:
357*e3ec6ff4SXiaoDong Huang 		mem_st = PD_PHP_MEM_ST;
358*e3ec6ff4SXiaoDong Huang 		break;
359*e3ec6ff4SXiaoDong Huang 	case PD_GMAC:
360*e3ec6ff4SXiaoDong Huang 		mem_st = PD_GMAC_MEM_ST;
361*e3ec6ff4SXiaoDong Huang 		break;
362*e3ec6ff4SXiaoDong Huang 	case PD_PCIE:
363*e3ec6ff4SXiaoDong Huang 		mem_st = PD_PCIE_MEM_ST;
364*e3ec6ff4SXiaoDong Huang 		break;
365*e3ec6ff4SXiaoDong Huang 	case PD_NVM0:
366*e3ec6ff4SXiaoDong Huang 		mem_st = PD_NVM0_MEM_ST;
367*e3ec6ff4SXiaoDong Huang 		break;
368*e3ec6ff4SXiaoDong Huang 	case PD_SDIO:
369*e3ec6ff4SXiaoDong Huang 		mem_st = PD_SDIO_MEM_ST;
370*e3ec6ff4SXiaoDong Huang 		break;
371*e3ec6ff4SXiaoDong Huang 	case PD_USB:
372*e3ec6ff4SXiaoDong Huang 		mem_st = PD_USB_MEM_ST;
373*e3ec6ff4SXiaoDong Huang 		break;
374*e3ec6ff4SXiaoDong Huang 	case PD_SDMMC:
375*e3ec6ff4SXiaoDong Huang 		mem_st = PD_SDMMC_MEM_ST;
376*e3ec6ff4SXiaoDong Huang 		break;
377*e3ec6ff4SXiaoDong Huang 	default:
378*e3ec6ff4SXiaoDong Huang 		return -EINVAL;
379*e3ec6ff4SXiaoDong Huang 	}
380*e3ec6ff4SXiaoDong Huang 
381*e3ec6ff4SXiaoDong Huang 	*pd_mem_st = mem_st;
382*e3ec6ff4SXiaoDong Huang 
383*e3ec6ff4SXiaoDong Huang 	return 0;
384*e3ec6ff4SXiaoDong Huang }
385*e3ec6ff4SXiaoDong Huang 
386*e3ec6ff4SXiaoDong Huang static int pmu_power_domain_reset_mem(uint32_t pd, uint32_t pd_mem_st)
387*e3ec6ff4SXiaoDong Huang {
388*e3ec6ff4SXiaoDong Huang 	uint32_t loop = 0;
389*e3ec6ff4SXiaoDong Huang 	int ret = 0;
390*e3ec6ff4SXiaoDong Huang 
391*e3ec6ff4SXiaoDong Huang 	while (pmu_power_domain_chain_st(pd_mem_st) != pmu_pd_on) {
392*e3ec6ff4SXiaoDong Huang 		udelay(1);
393*e3ec6ff4SXiaoDong Huang 		loop++;
394*e3ec6ff4SXiaoDong Huang 		if (loop >= PD_CTR_LOOP) {
395*e3ec6ff4SXiaoDong Huang 			WARN("%s: %d chain up time out\n", __func__, pd);
396*e3ec6ff4SXiaoDong Huang 			ret = -EINVAL;
397*e3ec6ff4SXiaoDong Huang 			goto error;
398*e3ec6ff4SXiaoDong Huang 		}
399*e3ec6ff4SXiaoDong Huang 	}
400*e3ec6ff4SXiaoDong Huang 
401*e3ec6ff4SXiaoDong Huang 	udelay(60);
402*e3ec6ff4SXiaoDong Huang 
403*e3ec6ff4SXiaoDong Huang 	mmio_write_32(PMU_BASE + PMU2_MEMPWR_GATE_SFTCON(pd / 16),
404*e3ec6ff4SXiaoDong Huang 		      BITS_WITH_WMASK(pmu_pd_off, 0x1, pd % 16));
405*e3ec6ff4SXiaoDong Huang 	dsb();
406*e3ec6ff4SXiaoDong Huang 
407*e3ec6ff4SXiaoDong Huang 	loop = 0;
408*e3ec6ff4SXiaoDong Huang 	while (pmu_power_domain_mem_st(pd_mem_st) != pmu_pd_off) {
409*e3ec6ff4SXiaoDong Huang 		udelay(1);
410*e3ec6ff4SXiaoDong Huang 		loop++;
411*e3ec6ff4SXiaoDong Huang 		if (loop >= PD_CTR_LOOP) {
412*e3ec6ff4SXiaoDong Huang 			WARN("%s: %d mem down time out\n", __func__, pd);
413*e3ec6ff4SXiaoDong Huang 			ret = -EINVAL;
414*e3ec6ff4SXiaoDong Huang 			goto error;
415*e3ec6ff4SXiaoDong Huang 		}
416*e3ec6ff4SXiaoDong Huang 	}
417*e3ec6ff4SXiaoDong Huang 
418*e3ec6ff4SXiaoDong Huang 	mmio_write_32(PMU_BASE + PMU2_MEMPWR_GATE_SFTCON(pd / 16),
419*e3ec6ff4SXiaoDong Huang 		      BITS_WITH_WMASK(pmu_pd_on, 0x1, pd % 16));
420*e3ec6ff4SXiaoDong Huang 	dsb();
421*e3ec6ff4SXiaoDong Huang 
422*e3ec6ff4SXiaoDong Huang 	loop = 0;
423*e3ec6ff4SXiaoDong Huang 	while (pmu_power_domain_mem_st(pd_mem_st) != pmu_pd_on) {
424*e3ec6ff4SXiaoDong Huang 		udelay(1);
425*e3ec6ff4SXiaoDong Huang 		loop++;
426*e3ec6ff4SXiaoDong Huang 		if (loop >= PD_CTR_LOOP) {
427*e3ec6ff4SXiaoDong Huang 			WARN("%s: %d mem up time out\n", __func__, pd);
428*e3ec6ff4SXiaoDong Huang 			ret = -EINVAL;
429*e3ec6ff4SXiaoDong Huang 			goto error;
430*e3ec6ff4SXiaoDong Huang 		}
431*e3ec6ff4SXiaoDong Huang 	}
432*e3ec6ff4SXiaoDong Huang 
433*e3ec6ff4SXiaoDong Huang 	return 0;
434*e3ec6ff4SXiaoDong Huang 
435*e3ec6ff4SXiaoDong Huang error:
436*e3ec6ff4SXiaoDong Huang 	return ret;
437*e3ec6ff4SXiaoDong Huang }
438*e3ec6ff4SXiaoDong Huang 
439*e3ec6ff4SXiaoDong Huang static int pmu_power_domain_ctr(uint32_t pd, uint32_t pd_state)
440*e3ec6ff4SXiaoDong Huang {
441*e3ec6ff4SXiaoDong Huang 	uint32_t loop = 0;
442*e3ec6ff4SXiaoDong Huang 	uint32_t is_mem_on = pmu_pd_off;
443*e3ec6ff4SXiaoDong Huang 	uint32_t pd_mem_st;
444*e3ec6ff4SXiaoDong Huang 	int ret = 0;
445*e3ec6ff4SXiaoDong Huang 
446*e3ec6ff4SXiaoDong Huang 	if (pd_state == pmu_pd_on) {
447*e3ec6ff4SXiaoDong Huang 		ret = pmu_power_domain_pd_to_mem_st(pd, &pd_mem_st);
448*e3ec6ff4SXiaoDong Huang 		if (ret == 0) {
449*e3ec6ff4SXiaoDong Huang 			is_mem_on = pmu_power_domain_mem_st(pd_mem_st);
450*e3ec6ff4SXiaoDong Huang 			if (is_mem_on == pmu_pd_on)
451*e3ec6ff4SXiaoDong Huang 				WARN("%s: %d mem is up\n", __func__, pd);
452*e3ec6ff4SXiaoDong Huang 		}
453*e3ec6ff4SXiaoDong Huang 	}
454*e3ec6ff4SXiaoDong Huang 
455*e3ec6ff4SXiaoDong Huang 	mmio_write_32(PMU_BASE + PMU2_PWR_GATE_SFTCON(pd / 16),
456*e3ec6ff4SXiaoDong Huang 		      BITS_WITH_WMASK(pd_state, 0x1, pd % 16));
457*e3ec6ff4SXiaoDong Huang 	dsb();
458*e3ec6ff4SXiaoDong Huang 
459*e3ec6ff4SXiaoDong Huang 	if (is_mem_on == pmu_pd_on) {
460*e3ec6ff4SXiaoDong Huang 		ret = pmu_power_domain_reset_mem(pd, pd_mem_st);
461*e3ec6ff4SXiaoDong Huang 		if (ret != 0)
462*e3ec6ff4SXiaoDong Huang 			goto out;
463*e3ec6ff4SXiaoDong Huang 		WARN("%s: %d mem reset ok\n", __func__, pd);
464*e3ec6ff4SXiaoDong Huang 	}
465*e3ec6ff4SXiaoDong Huang 
466*e3ec6ff4SXiaoDong Huang 	while ((pmu_power_domain_st(pd) != pd_state) && (loop < PD_CTR_LOOP)) {
467*e3ec6ff4SXiaoDong Huang 		udelay(1);
468*e3ec6ff4SXiaoDong Huang 		loop++;
469*e3ec6ff4SXiaoDong Huang 	}
470*e3ec6ff4SXiaoDong Huang 
471*e3ec6ff4SXiaoDong Huang 	if (pmu_power_domain_st(pd) != pd_state) {
472*e3ec6ff4SXiaoDong Huang 		WARN("%s: %d, %d, (0x%x, 0x%x) error!\n", __func__, pd, pd_state,
473*e3ec6ff4SXiaoDong Huang 		     mmio_read_32(PMU_BASE + PMU2_PWR_GATE_ST(0)),
474*e3ec6ff4SXiaoDong Huang 		     mmio_read_32(PMU_BASE + PMU2_BISR_STATUS(4)));
475*e3ec6ff4SXiaoDong Huang 		ret = -EINVAL;
476*e3ec6ff4SXiaoDong Huang 	}
477*e3ec6ff4SXiaoDong Huang 
478*e3ec6ff4SXiaoDong Huang out:
479*e3ec6ff4SXiaoDong Huang 	return ret;
480*e3ec6ff4SXiaoDong Huang }
481*e3ec6ff4SXiaoDong Huang 
482*e3ec6ff4SXiaoDong Huang static int pmu_set_power_domain(uint32_t pd_id, uint32_t pd_state)
483*e3ec6ff4SXiaoDong Huang {
484*e3ec6ff4SXiaoDong Huang 	uint32_t state;
485*e3ec6ff4SXiaoDong Huang 
486*e3ec6ff4SXiaoDong Huang 	if (pmu_power_domain_st(pd_id) == pd_state)
487*e3ec6ff4SXiaoDong Huang 		goto out;
488*e3ec6ff4SXiaoDong Huang 
489*e3ec6ff4SXiaoDong Huang 	if (pd_state == pmu_pd_on)
490*e3ec6ff4SXiaoDong Huang 		pmu_power_domain_ctr(pd_id, pd_state);
491*e3ec6ff4SXiaoDong Huang 
492*e3ec6ff4SXiaoDong Huang 	state = (pd_state == pmu_pd_off) ? bus_idle : bus_active;
493*e3ec6ff4SXiaoDong Huang 
494*e3ec6ff4SXiaoDong Huang 	switch (pd_id) {
495*e3ec6ff4SXiaoDong Huang 	case PD_GPU:
496*e3ec6ff4SXiaoDong Huang 		pmu_bus_idle_req(BUS_ID_GPU, state);
497*e3ec6ff4SXiaoDong Huang 		break;
498*e3ec6ff4SXiaoDong Huang 	case PD_NPUTOP:
499*e3ec6ff4SXiaoDong Huang 		pmu_bus_idle_req(BUS_ID_NPUTOP, state);
500*e3ec6ff4SXiaoDong Huang 		break;
501*e3ec6ff4SXiaoDong Huang 	case PD_NPU1:
502*e3ec6ff4SXiaoDong Huang 		pmu_bus_idle_req(BUS_ID_NPU1, state);
503*e3ec6ff4SXiaoDong Huang 		break;
504*e3ec6ff4SXiaoDong Huang 	case PD_NPU2:
505*e3ec6ff4SXiaoDong Huang 		pmu_bus_idle_req(BUS_ID_NPU2, state);
506*e3ec6ff4SXiaoDong Huang 		break;
507*e3ec6ff4SXiaoDong Huang 	case PD_VENC0:
508*e3ec6ff4SXiaoDong Huang 		pmu_bus_idle_req(BUS_ID_RKVENC0, state);
509*e3ec6ff4SXiaoDong Huang 		break;
510*e3ec6ff4SXiaoDong Huang 	case PD_VENC1:
511*e3ec6ff4SXiaoDong Huang 		pmu_bus_idle_req(BUS_ID_RKVENC1, state);
512*e3ec6ff4SXiaoDong Huang 		break;
513*e3ec6ff4SXiaoDong Huang 	case PD_RKVDEC0:
514*e3ec6ff4SXiaoDong Huang 		pmu_bus_idle_req(BUS_ID_RKVDEC0, state);
515*e3ec6ff4SXiaoDong Huang 		break;
516*e3ec6ff4SXiaoDong Huang 	case PD_RKVDEC1:
517*e3ec6ff4SXiaoDong Huang 		pmu_bus_idle_req(BUS_ID_RKVDEC1, state);
518*e3ec6ff4SXiaoDong Huang 		break;
519*e3ec6ff4SXiaoDong Huang 	case PD_VDPU:
520*e3ec6ff4SXiaoDong Huang 		pmu_bus_idle_req(BUS_ID_VDPU, state);
521*e3ec6ff4SXiaoDong Huang 		break;
522*e3ec6ff4SXiaoDong Huang 	case PD_AV1:
523*e3ec6ff4SXiaoDong Huang 		pmu_bus_idle_req(BUS_ID_AV1, state);
524*e3ec6ff4SXiaoDong Huang 		break;
525*e3ec6ff4SXiaoDong Huang 	case PD_VI:
526*e3ec6ff4SXiaoDong Huang 		pmu_bus_idle_req(BUS_ID_VI, state);
527*e3ec6ff4SXiaoDong Huang 		break;
528*e3ec6ff4SXiaoDong Huang 	case PD_ISP1:
529*e3ec6ff4SXiaoDong Huang 		pmu_bus_idle_req(BUS_ID_ISP, state);
530*e3ec6ff4SXiaoDong Huang 		break;
531*e3ec6ff4SXiaoDong Huang 	case PD_RGA31:
532*e3ec6ff4SXiaoDong Huang 		pmu_bus_idle_req(BUS_ID_RGA31, state);
533*e3ec6ff4SXiaoDong Huang 		break;
534*e3ec6ff4SXiaoDong Huang 	case PD_VOP:
535*e3ec6ff4SXiaoDong Huang 		pmu_bus_idle_req(BUS_ID_VOP_CHANNEL, state);
536*e3ec6ff4SXiaoDong Huang 		pmu_bus_idle_req(BUS_ID_VOP, state);
537*e3ec6ff4SXiaoDong Huang 		break;
538*e3ec6ff4SXiaoDong Huang 	case PD_VO0:
539*e3ec6ff4SXiaoDong Huang 		pmu_bus_idle_req(BUS_ID_VO0, state);
540*e3ec6ff4SXiaoDong Huang 		break;
541*e3ec6ff4SXiaoDong Huang 	case PD_VO1:
542*e3ec6ff4SXiaoDong Huang 		pmu_bus_idle_req(BUS_ID_VO1, state);
543*e3ec6ff4SXiaoDong Huang 		break;
544*e3ec6ff4SXiaoDong Huang 	case PD_AUDIO:
545*e3ec6ff4SXiaoDong Huang 		pmu_bus_idle_req(BUS_ID_AUDIO, state);
546*e3ec6ff4SXiaoDong Huang 		break;
547*e3ec6ff4SXiaoDong Huang 	case PD_PHP:
548*e3ec6ff4SXiaoDong Huang 		pmu_bus_idle_req(BUS_ID_PHP, state);
549*e3ec6ff4SXiaoDong Huang 		break;
550*e3ec6ff4SXiaoDong Huang 	case PD_NVM:
551*e3ec6ff4SXiaoDong Huang 		pmu_bus_idle_req(BUS_ID_NVM, state);
552*e3ec6ff4SXiaoDong Huang 		break;
553*e3ec6ff4SXiaoDong Huang 	case PD_SDIO:
554*e3ec6ff4SXiaoDong Huang 		pmu_bus_idle_req(BUS_ID_SDIO, state);
555*e3ec6ff4SXiaoDong Huang 		break;
556*e3ec6ff4SXiaoDong Huang 	case PD_USB:
557*e3ec6ff4SXiaoDong Huang 		pmu_bus_idle_req(BUS_ID_USB, state);
558*e3ec6ff4SXiaoDong Huang 		break;
559*e3ec6ff4SXiaoDong Huang 	case PD_SECURE:
560*e3ec6ff4SXiaoDong Huang 		pmu_bus_idle_req(BUS_ID_SECURE, state);
561*e3ec6ff4SXiaoDong Huang 		break;
562*e3ec6ff4SXiaoDong Huang 	default:
563*e3ec6ff4SXiaoDong Huang 		break;
564*e3ec6ff4SXiaoDong Huang 	}
565*e3ec6ff4SXiaoDong Huang 
566*e3ec6ff4SXiaoDong Huang 	if (pd_state == pmu_pd_off)
567*e3ec6ff4SXiaoDong Huang 		pmu_power_domain_ctr(pd_id, pd_state);
568*e3ec6ff4SXiaoDong Huang 
569*e3ec6ff4SXiaoDong Huang out:
570*e3ec6ff4SXiaoDong Huang 	return 0;
571*e3ec6ff4SXiaoDong Huang }
572*e3ec6ff4SXiaoDong Huang 
573*e3ec6ff4SXiaoDong Huang static void pmu_power_domains_suspend(void)
574*e3ec6ff4SXiaoDong Huang {
575*e3ec6ff4SXiaoDong Huang 	ddr_data.qch_pwr_st =
576*e3ec6ff4SXiaoDong Huang 		mmio_read_32(PMU_BASE + PMU2_QCHANNEL_STATUS) & PMU2_QCH_PWR_MSK;
577*e3ec6ff4SXiaoDong Huang 	ddr_data.pmu_pd_st0 = mmio_read_32(PMU_BASE + PMU2_PWR_GATE_ST(0));
578*e3ec6ff4SXiaoDong Huang 	ddr_data.bus_idle_st0 = mmio_read_32(PMU_BASE + PMU2_BUS_IDLE_ST(0));
579*e3ec6ff4SXiaoDong Huang 
580*e3ec6ff4SXiaoDong Huang 	qos_save();
581*e3ec6ff4SXiaoDong Huang 
582*e3ec6ff4SXiaoDong Huang 	if ((ddr_data.pmu_pd_st0 & BIT(PD_PHP)) == 0)
583*e3ec6ff4SXiaoDong Huang 		pd_php_save();
584*e3ec6ff4SXiaoDong Huang 
585*e3ec6ff4SXiaoDong Huang 	if ((ddr_data.pmu_pd_st0 & BIT(PD_CRYPTO)) == 0)
586*e3ec6ff4SXiaoDong Huang 		pd_crypto_save();
587*e3ec6ff4SXiaoDong Huang 
588*e3ec6ff4SXiaoDong Huang 	pmu_qch_pwr_ctlr(0x20, 1);
589*e3ec6ff4SXiaoDong Huang 	pmu_qch_pwr_ctlr(0x40, 1);
590*e3ec6ff4SXiaoDong Huang 	pmu_qch_pwr_ctlr(0x1, 1);
591*e3ec6ff4SXiaoDong Huang 	pmu_qch_pwr_ctlr(0x2, 1);
592*e3ec6ff4SXiaoDong Huang 	pmu_qch_pwr_ctlr(0x4, 1);
593*e3ec6ff4SXiaoDong Huang 	pmu_qch_pwr_ctlr(0x8, 1);
594*e3ec6ff4SXiaoDong Huang 	pmu_qch_pwr_ctlr(0x10, 1);
595*e3ec6ff4SXiaoDong Huang 
596*e3ec6ff4SXiaoDong Huang 	pmu_bus_idle_req(BUS_ID_VO1USBTOP, bus_idle);
597*e3ec6ff4SXiaoDong Huang 	pmu_bus_idle_req(BUS_ID_SECURE_VO1USB_CHANNEL, bus_idle);
598*e3ec6ff4SXiaoDong Huang 
599*e3ec6ff4SXiaoDong Huang 	pmu_bus_idle_req(BUS_ID_USB, bus_idle);
600*e3ec6ff4SXiaoDong Huang 
601*e3ec6ff4SXiaoDong Huang 	pmu_set_power_domain(PD_GPU, pmu_pd_off);
602*e3ec6ff4SXiaoDong Huang 
603*e3ec6ff4SXiaoDong Huang 	pmu_set_power_domain(PD_NPU1, pmu_pd_off);
604*e3ec6ff4SXiaoDong Huang 	pmu_set_power_domain(PD_NPU2, pmu_pd_off);
605*e3ec6ff4SXiaoDong Huang 	pmu_set_power_domain(PD_NPUTOP, pmu_pd_off);
606*e3ec6ff4SXiaoDong Huang 	pmu_set_power_domain(PD_NPU, pmu_pd_off);
607*e3ec6ff4SXiaoDong Huang 
608*e3ec6ff4SXiaoDong Huang 	pmu_set_power_domain(PD_RKVDEC1, pmu_pd_off);
609*e3ec6ff4SXiaoDong Huang 	pmu_set_power_domain(PD_RKVDEC0, pmu_pd_off);
610*e3ec6ff4SXiaoDong Huang 	pmu_set_power_domain(PD_VENC1, pmu_pd_off);
611*e3ec6ff4SXiaoDong Huang 	pmu_set_power_domain(PD_VENC0, pmu_pd_off);
612*e3ec6ff4SXiaoDong Huang 	pmu_set_power_domain(PD_VCODEC, pmu_pd_off);
613*e3ec6ff4SXiaoDong Huang 
614*e3ec6ff4SXiaoDong Huang 	pmu_set_power_domain(PD_RGA30, pmu_pd_off);
615*e3ec6ff4SXiaoDong Huang 	pmu_set_power_domain(PD_AV1, pmu_pd_off);
616*e3ec6ff4SXiaoDong Huang 	pmu_set_power_domain(PD_VDPU, pmu_pd_off);
617*e3ec6ff4SXiaoDong Huang 
618*e3ec6ff4SXiaoDong Huang 	pmu_set_power_domain(PD_VO0, pmu_pd_off);
619*e3ec6ff4SXiaoDong Huang 	pmu_set_power_domain(PD_VO1, pmu_pd_off);
620*e3ec6ff4SXiaoDong Huang 	pmu_set_power_domain(PD_VOP, pmu_pd_off);
621*e3ec6ff4SXiaoDong Huang 
622*e3ec6ff4SXiaoDong Huang 	pmu_set_power_domain(PD_FEC, pmu_pd_off);
623*e3ec6ff4SXiaoDong Huang 	pmu_set_power_domain(PD_ISP1, pmu_pd_off);
624*e3ec6ff4SXiaoDong Huang 	pmu_set_power_domain(PD_VI, pmu_pd_off);
625*e3ec6ff4SXiaoDong Huang 
626*e3ec6ff4SXiaoDong Huang 	pmu_set_power_domain(PD_RGA31, pmu_pd_off);
627*e3ec6ff4SXiaoDong Huang 
628*e3ec6ff4SXiaoDong Huang 	pmu_set_power_domain(PD_AUDIO, pmu_pd_off);
629*e3ec6ff4SXiaoDong Huang 
630*e3ec6ff4SXiaoDong Huang 	pmu_set_power_domain(PD_GMAC, pmu_pd_off);
631*e3ec6ff4SXiaoDong Huang 	pmu_set_power_domain(PD_PCIE, pmu_pd_off);
632*e3ec6ff4SXiaoDong Huang 	pmu_set_power_domain(PD_PHP, pmu_pd_off);
633*e3ec6ff4SXiaoDong Huang 
634*e3ec6ff4SXiaoDong Huang 	pmu_set_power_domain(PD_SDIO, pmu_pd_off);
635*e3ec6ff4SXiaoDong Huang 
636*e3ec6ff4SXiaoDong Huang 	pmu_set_power_domain(PD_NVM0, pmu_pd_off);
637*e3ec6ff4SXiaoDong Huang 	pmu_set_power_domain(PD_NVM, pmu_pd_off);
638*e3ec6ff4SXiaoDong Huang 
639*e3ec6ff4SXiaoDong Huang 	pmu_set_power_domain(PD_SDMMC, pmu_pd_off);
640*e3ec6ff4SXiaoDong Huang 	pmu_set_power_domain(PD_CRYPTO, pmu_pd_off);
641*e3ec6ff4SXiaoDong Huang }
642*e3ec6ff4SXiaoDong Huang 
643*e3ec6ff4SXiaoDong Huang static void pmu_power_domains_resume(void)
644*e3ec6ff4SXiaoDong Huang {
645*e3ec6ff4SXiaoDong Huang 	int i;
646*e3ec6ff4SXiaoDong Huang 
647*e3ec6ff4SXiaoDong Huang 	pmu_set_power_domain(PD_CRYPTO, !!(ddr_data.pmu_pd_st0 & BIT(PD_CRYPTO)));
648*e3ec6ff4SXiaoDong Huang 	pmu_set_power_domain(PD_SDMMC, !!(ddr_data.pmu_pd_st0 & BIT(PD_SDMMC)));
649*e3ec6ff4SXiaoDong Huang 
650*e3ec6ff4SXiaoDong Huang 	pmu_set_power_domain(PD_NVM, !!(ddr_data.pmu_pd_st0 & BIT(PD_NVM)));
651*e3ec6ff4SXiaoDong Huang 	pmu_set_power_domain(PD_NVM0, !!(ddr_data.pmu_pd_st0 & BIT(PD_NVM0)));
652*e3ec6ff4SXiaoDong Huang 
653*e3ec6ff4SXiaoDong Huang 	pmu_set_power_domain(PD_SDIO, !!(ddr_data.pmu_pd_st0 & BIT(PD_SDIO)));
654*e3ec6ff4SXiaoDong Huang 
655*e3ec6ff4SXiaoDong Huang 	pmu_set_power_domain(PD_PHP, !!(ddr_data.pmu_pd_st0 & BIT(PD_PHP)));
656*e3ec6ff4SXiaoDong Huang 	pmu_set_power_domain(PD_PCIE, !!(ddr_data.pmu_pd_st0 & BIT(PD_PCIE)));
657*e3ec6ff4SXiaoDong Huang 	pmu_set_power_domain(PD_GMAC, !!(ddr_data.pmu_pd_st0 & BIT(PD_GMAC)));
658*e3ec6ff4SXiaoDong Huang 
659*e3ec6ff4SXiaoDong Huang 	pmu_set_power_domain(PD_AUDIO, !!(ddr_data.pmu_pd_st0 & BIT(PD_AUDIO)));
660*e3ec6ff4SXiaoDong Huang 
661*e3ec6ff4SXiaoDong Huang 	pmu_set_power_domain(PD_USB, !!(ddr_data.pmu_pd_st0 & BIT(PD_USB)));
662*e3ec6ff4SXiaoDong Huang 
663*e3ec6ff4SXiaoDong Huang 	pmu_set_power_domain(PD_RGA31, !!(ddr_data.pmu_pd_st0 & BIT(PD_RGA31)));
664*e3ec6ff4SXiaoDong Huang 
665*e3ec6ff4SXiaoDong Huang 	pmu_set_power_domain(PD_VI, !!(ddr_data.pmu_pd_st0 & BIT(PD_VI)));
666*e3ec6ff4SXiaoDong Huang 	pmu_set_power_domain(PD_ISP1, !!(ddr_data.pmu_pd_st0 & BIT(PD_ISP1)));
667*e3ec6ff4SXiaoDong Huang 	pmu_set_power_domain(PD_FEC, !!(ddr_data.pmu_pd_st0 & BIT(PD_FEC)));
668*e3ec6ff4SXiaoDong Huang 
669*e3ec6ff4SXiaoDong Huang 	pmu_set_power_domain(PD_VOP, !!(ddr_data.pmu_pd_st0 & BIT(PD_VOP)));
670*e3ec6ff4SXiaoDong Huang 
671*e3ec6ff4SXiaoDong Huang 	pmu_set_power_domain(PD_VO1, !!(ddr_data.pmu_pd_st0 & BIT(PD_VO1)));
672*e3ec6ff4SXiaoDong Huang 
673*e3ec6ff4SXiaoDong Huang 	pmu_set_power_domain(PD_VO0, !!(ddr_data.pmu_pd_st0 & BIT(PD_VO0)));
674*e3ec6ff4SXiaoDong Huang 
675*e3ec6ff4SXiaoDong Huang 	pmu_set_power_domain(PD_VDPU, !!(ddr_data.pmu_pd_st0 & BIT(PD_VDPU)));
676*e3ec6ff4SXiaoDong Huang 	pmu_set_power_domain(PD_AV1, !!(ddr_data.pmu_pd_st0 & BIT(PD_AV1)));
677*e3ec6ff4SXiaoDong Huang 	pmu_set_power_domain(PD_RGA30, !!(ddr_data.pmu_pd_st0 & BIT(PD_RGA30)));
678*e3ec6ff4SXiaoDong Huang 
679*e3ec6ff4SXiaoDong Huang 	pmu_set_power_domain(PD_VCODEC, !!(ddr_data.pmu_pd_st0 & BIT(PD_VCODEC)));
680*e3ec6ff4SXiaoDong Huang 	pmu_set_power_domain(PD_VENC0, !!(ddr_data.pmu_pd_st0 & BIT(PD_VENC0)));
681*e3ec6ff4SXiaoDong Huang 	pmu_set_power_domain(PD_VENC1, !!(ddr_data.pmu_pd_st0 & BIT(PD_VENC1)));
682*e3ec6ff4SXiaoDong Huang 	pmu_set_power_domain(PD_RKVDEC0, !!(ddr_data.pmu_pd_st0 & BIT(PD_RKVDEC0)));
683*e3ec6ff4SXiaoDong Huang 	pmu_set_power_domain(PD_RKVDEC1, !!(ddr_data.pmu_pd_st0 & BIT(PD_RKVDEC1)));
684*e3ec6ff4SXiaoDong Huang 
685*e3ec6ff4SXiaoDong Huang 	pmu_set_power_domain(PD_NPU, !!(ddr_data.pmu_pd_st0 & BIT(PD_NPU)));
686*e3ec6ff4SXiaoDong Huang 	pmu_set_power_domain(PD_NPUTOP, !!(ddr_data.pmu_pd_st0 & BIT(PD_NPUTOP)));
687*e3ec6ff4SXiaoDong Huang 	pmu_set_power_domain(PD_NPU2, !!(ddr_data.pmu_pd_st0 & BIT(PD_NPU2)));
688*e3ec6ff4SXiaoDong Huang 	pmu_set_power_domain(PD_NPU1, !!(ddr_data.pmu_pd_st0 & BIT(PD_NPU1)));
689*e3ec6ff4SXiaoDong Huang 
690*e3ec6ff4SXiaoDong Huang 	pmu_set_power_domain(PD_GPU, !!(ddr_data.pmu_pd_st0 & BIT(PD_GPU)));
691*e3ec6ff4SXiaoDong Huang 
692*e3ec6ff4SXiaoDong Huang 	for (i = 0; i < 32; i++)
693*e3ec6ff4SXiaoDong Huang 		pmu_bus_idle_req(i, !!(ddr_data.bus_idle_st0 & BIT(i)));
694*e3ec6ff4SXiaoDong Huang 
695*e3ec6ff4SXiaoDong Huang 	pmu_qch_pwr_ctlr(0x10, !!(ddr_data.qch_pwr_st & 0x10));
696*e3ec6ff4SXiaoDong Huang 	pmu_qch_pwr_ctlr(0x8, !!(ddr_data.qch_pwr_st & 0x8));
697*e3ec6ff4SXiaoDong Huang 	pmu_qch_pwr_ctlr(0x4, !!(ddr_data.qch_pwr_st & 0x4));
698*e3ec6ff4SXiaoDong Huang 	pmu_qch_pwr_ctlr(0x2, !!(ddr_data.qch_pwr_st & 0x2));
699*e3ec6ff4SXiaoDong Huang 	pmu_qch_pwr_ctlr(0x1, !!(ddr_data.qch_pwr_st & 0x1));
700*e3ec6ff4SXiaoDong Huang 	pmu_qch_pwr_ctlr(0x40, !!(ddr_data.qch_pwr_st & 0x40));
701*e3ec6ff4SXiaoDong Huang 	pmu_qch_pwr_ctlr(0x20, !!(ddr_data.qch_pwr_st & 0x20));
702*e3ec6ff4SXiaoDong Huang 
703*e3ec6ff4SXiaoDong Huang 	if ((ddr_data.pmu_pd_st0 & BIT(PD_CRYPTO)) == 0)
704*e3ec6ff4SXiaoDong Huang 		pd_crypto_restore();
705*e3ec6ff4SXiaoDong Huang 
706*e3ec6ff4SXiaoDong Huang 	if ((ddr_data.pmu_pd_st0 & BIT(PD_PHP)) == 0)
707*e3ec6ff4SXiaoDong Huang 		pd_php_restore();
708*e3ec6ff4SXiaoDong Huang 
709*e3ec6ff4SXiaoDong Huang 	qos_restore();
710*e3ec6ff4SXiaoDong Huang }
711*e3ec6ff4SXiaoDong Huang 
712*e3ec6ff4SXiaoDong Huang static int cpus_power_domain_on(uint32_t cpu_id)
713*e3ec6ff4SXiaoDong Huang {
714*e3ec6ff4SXiaoDong Huang 	mmio_write_32(PMU_BASE + PMU2_CPU_AUTO_PWR_CON(cpu_id),
715*e3ec6ff4SXiaoDong Huang 		      BITS_WITH_WMASK(0, 0x1, core_pm_en));
716*e3ec6ff4SXiaoDong Huang 	mmio_write_32(PMU_BASE + PMU2_CPU_AUTO_PWR_CON(cpu_id),
717*e3ec6ff4SXiaoDong Huang 		      BITS_WITH_WMASK(1, 0x1, core_pm_sft_wakeup_en));
718*e3ec6ff4SXiaoDong Huang 	dsb();
719*e3ec6ff4SXiaoDong Huang 
720*e3ec6ff4SXiaoDong Huang 	return 0;
721*e3ec6ff4SXiaoDong Huang }
722*e3ec6ff4SXiaoDong Huang 
723*e3ec6ff4SXiaoDong Huang static int cpus_power_domain_off(uint32_t cpu_id, uint32_t pd_cfg)
724*e3ec6ff4SXiaoDong Huang {
725*e3ec6ff4SXiaoDong Huang 	uint32_t apm_value = BIT(core_pm_en);
726*e3ec6ff4SXiaoDong Huang 
727*e3ec6ff4SXiaoDong Huang 	if (pd_cfg == core_pwr_wfi_int)
728*e3ec6ff4SXiaoDong Huang 		apm_value |= BIT(core_pm_int_wakeup_en);
729*e3ec6ff4SXiaoDong Huang 
730*e3ec6ff4SXiaoDong Huang 	mmio_write_32(PMU_BASE + PMU2_CPU_AUTO_PWR_CON(cpu_id),
731*e3ec6ff4SXiaoDong Huang 		      BITS_WITH_WMASK(apm_value, 0x3, 0));
732*e3ec6ff4SXiaoDong Huang 	dsb();
733*e3ec6ff4SXiaoDong Huang 
734*e3ec6ff4SXiaoDong Huang 	return 0;
735*e3ec6ff4SXiaoDong Huang }
736*e3ec6ff4SXiaoDong Huang 
737*e3ec6ff4SXiaoDong Huang static inline void cpus_pd_req_enter_wfi(void)
738*e3ec6ff4SXiaoDong Huang {
739*e3ec6ff4SXiaoDong Huang 	/* CORTEX_A55_CPUACTLR_EL1 */
740*e3ec6ff4SXiaoDong Huang 	__asm__ volatile ("msr	DBGPRCR_EL1, xzr\n"
741*e3ec6ff4SXiaoDong Huang 			  "mrs	x0, S3_0_C15_C2_7\n"
742*e3ec6ff4SXiaoDong Huang 			  "orr	x0, x0, #0x1\n"
743*e3ec6ff4SXiaoDong Huang 			  "msr	S3_0_C15_C2_7, x0\n"
744*e3ec6ff4SXiaoDong Huang 			  "wfi_loop:\n"
745*e3ec6ff4SXiaoDong Huang 			  "isb\n"
746*e3ec6ff4SXiaoDong Huang 			  "wfi\n"
747*e3ec6ff4SXiaoDong Huang 			  "b wfi_loop\n");
748*e3ec6ff4SXiaoDong Huang }
749*e3ec6ff4SXiaoDong Huang 
750*e3ec6ff4SXiaoDong Huang static void nonboot_cpus_off(void)
751*e3ec6ff4SXiaoDong Huang {
752*e3ec6ff4SXiaoDong Huang 	uint32_t boot_cpu, cpu, tmp;
753*e3ec6ff4SXiaoDong Huang 	uint32_t exp_st;
754*e3ec6ff4SXiaoDong Huang 	uint32_t bcore0_rst_msk = 0, bcore1_rst_msk = 0;
755*e3ec6ff4SXiaoDong Huang 	int wait_cnt;
756*e3ec6ff4SXiaoDong Huang 
757*e3ec6ff4SXiaoDong Huang 	bcore0_rst_msk = CRU_BIGCPU02_RST_MSK | CRU_BIGCPU13_RST_MSK;
758*e3ec6ff4SXiaoDong Huang 	bcore1_rst_msk = CRU_BIGCPU02_RST_MSK | CRU_BIGCPU13_RST_MSK;
759*e3ec6ff4SXiaoDong Huang 
760*e3ec6ff4SXiaoDong Huang 	mmio_write_32(BIGCORE0CRU_BASE + 0xa00, BITS_WITH_WMASK(0, bcore0_rst_msk, 0));
761*e3ec6ff4SXiaoDong Huang 	mmio_write_32(BIGCORE1CRU_BASE + 0xa00, BITS_WITH_WMASK(0, bcore1_rst_msk, 0));
762*e3ec6ff4SXiaoDong Huang 
763*e3ec6ff4SXiaoDong Huang 	wait_cnt = NONBOOT_CPUS_OFF_LOOP;
764*e3ec6ff4SXiaoDong Huang 	exp_st = SYS_GRF_BIG_CPUS_WFE;
765*e3ec6ff4SXiaoDong Huang 	do {
766*e3ec6ff4SXiaoDong Huang 		wait_cnt--;
767*e3ec6ff4SXiaoDong Huang 		tmp = mmio_read_32(SYSGRF_BASE + SYS_GRF_SOC_STATUS(3));
768*e3ec6ff4SXiaoDong Huang 		tmp &= SYS_GRF_BIG_CPUS_WFE;
769*e3ec6ff4SXiaoDong Huang 	} while (tmp != exp_st && wait_cnt);
770*e3ec6ff4SXiaoDong Huang 
771*e3ec6ff4SXiaoDong Huang 	boot_cpu = plat_my_core_pos();
772*e3ec6ff4SXiaoDong Huang 
773*e3ec6ff4SXiaoDong Huang 	/* turn off noboot cpus */
774*e3ec6ff4SXiaoDong Huang 	for (cpu = 0; cpu < PLATFORM_CORE_COUNT; cpu++) {
775*e3ec6ff4SXiaoDong Huang 		if (cpu == boot_cpu)
776*e3ec6ff4SXiaoDong Huang 			continue;
777*e3ec6ff4SXiaoDong Huang 		cpus_power_domain_off(cpu, core_pwr_wfi);
778*e3ec6ff4SXiaoDong Huang 	}
779*e3ec6ff4SXiaoDong Huang 
780*e3ec6ff4SXiaoDong Huang 	mmio_write_32(SRAM_BASE + 0x08, (uintptr_t)&cpus_pd_req_enter_wfi);
781*e3ec6ff4SXiaoDong Huang 	mmio_write_32(SRAM_BASE + 0x04, 0xdeadbeaf);
782*e3ec6ff4SXiaoDong Huang 
783*e3ec6ff4SXiaoDong Huang 	dsb();
784*e3ec6ff4SXiaoDong Huang 	isb();
785*e3ec6ff4SXiaoDong Huang 
786*e3ec6ff4SXiaoDong Huang 	sev();
787*e3ec6ff4SXiaoDong Huang 
788*e3ec6ff4SXiaoDong Huang 	wait_cnt = NONBOOT_CPUS_OFF_LOOP;
789*e3ec6ff4SXiaoDong Huang 	do {
790*e3ec6ff4SXiaoDong Huang 		wait_cnt--;
791*e3ec6ff4SXiaoDong Huang 		tmp = mmio_read_32(PMU_BASE + PMU2_CLUSTER_ST);
792*e3ec6ff4SXiaoDong Huang 		tmp &= CLUSTER_STS_NONBOOT_CPUS_DWN;
793*e3ec6ff4SXiaoDong Huang 	} while (tmp != CLUSTER_STS_NONBOOT_CPUS_DWN && wait_cnt);
794*e3ec6ff4SXiaoDong Huang 
795*e3ec6ff4SXiaoDong Huang 	if (tmp != CLUSTER_STS_NONBOOT_CPUS_DWN)
796*e3ec6ff4SXiaoDong Huang 		ERROR("nonboot cpus status(%x) error!\n", tmp);
797*e3ec6ff4SXiaoDong Huang }
798*e3ec6ff4SXiaoDong Huang 
799*e3ec6ff4SXiaoDong Huang int rockchip_soc_cores_pwr_dm_on(unsigned long mpidr,
800*e3ec6ff4SXiaoDong Huang 				 uint64_t entrypoint)
801*e3ec6ff4SXiaoDong Huang {
802*e3ec6ff4SXiaoDong Huang 	uint32_t cpu_id = plat_core_pos_by_mpidr(mpidr);
803*e3ec6ff4SXiaoDong Huang 
804*e3ec6ff4SXiaoDong Huang 	assert(cpu_id < PLATFORM_CORE_COUNT);
805*e3ec6ff4SXiaoDong Huang 	assert(cpuson_flags[cpu_id] == 0);
806*e3ec6ff4SXiaoDong Huang 	cpuson_flags[cpu_id] = PMU_CPU_HOTPLUG;
807*e3ec6ff4SXiaoDong Huang 	cpuson_entry_point[cpu_id] = entrypoint;
808*e3ec6ff4SXiaoDong Huang 	dsb();
809*e3ec6ff4SXiaoDong Huang 
810*e3ec6ff4SXiaoDong Huang 	flush_dcache_range((uintptr_t)cpuson_flags, sizeof(cpuson_flags));
811*e3ec6ff4SXiaoDong Huang 	flush_dcache_range((uintptr_t)cpuson_entry_point,
812*e3ec6ff4SXiaoDong Huang 			   sizeof(cpuson_entry_point));
813*e3ec6ff4SXiaoDong Huang 	dsb();
814*e3ec6ff4SXiaoDong Huang 	isb();
815*e3ec6ff4SXiaoDong Huang 
816*e3ec6ff4SXiaoDong Huang 	cpus_power_domain_on(cpu_id);
817*e3ec6ff4SXiaoDong Huang 
818*e3ec6ff4SXiaoDong Huang 	return PSCI_E_SUCCESS;
819*e3ec6ff4SXiaoDong Huang }
820*e3ec6ff4SXiaoDong Huang 
821*e3ec6ff4SXiaoDong Huang int rockchip_soc_cores_pwr_dm_on_finish(void)
822*e3ec6ff4SXiaoDong Huang {
823*e3ec6ff4SXiaoDong Huang 	uint32_t cpu_id = plat_my_core_pos();
824*e3ec6ff4SXiaoDong Huang 
825*e3ec6ff4SXiaoDong Huang 	mmio_write_32(PMU_BASE + PMU2_CPU_AUTO_PWR_CON(cpu_id),
826*e3ec6ff4SXiaoDong Huang 		      BITS_WITH_WMASK(0, 0xf, 0));
827*e3ec6ff4SXiaoDong Huang 
828*e3ec6ff4SXiaoDong Huang 	return PSCI_E_SUCCESS;
829*e3ec6ff4SXiaoDong Huang }
830*e3ec6ff4SXiaoDong Huang 
831*e3ec6ff4SXiaoDong Huang int rockchip_soc_cores_pwr_dm_off(void)
832*e3ec6ff4SXiaoDong Huang {
833*e3ec6ff4SXiaoDong Huang 	uint32_t cpu_id = plat_my_core_pos();
834*e3ec6ff4SXiaoDong Huang 
835*e3ec6ff4SXiaoDong Huang 	cpus_power_domain_off(cpu_id, core_pwr_wfi);
836*e3ec6ff4SXiaoDong Huang 
837*e3ec6ff4SXiaoDong Huang 	return PSCI_E_SUCCESS;
838*e3ec6ff4SXiaoDong Huang }
839*e3ec6ff4SXiaoDong Huang 
840*e3ec6ff4SXiaoDong Huang int rockchip_soc_cores_pwr_dm_suspend(void)
841*e3ec6ff4SXiaoDong Huang {
842*e3ec6ff4SXiaoDong Huang 	uint32_t cpu_id = plat_my_core_pos();
843*e3ec6ff4SXiaoDong Huang 
844*e3ec6ff4SXiaoDong Huang 	assert(cpu_id < PLATFORM_CORE_COUNT);
845*e3ec6ff4SXiaoDong Huang 
846*e3ec6ff4SXiaoDong Huang 	cpuson_flags[cpu_id] = PMU_CPU_AUTO_PWRDN;
847*e3ec6ff4SXiaoDong Huang 	cpuson_entry_point[cpu_id] = plat_get_sec_entrypoint();
848*e3ec6ff4SXiaoDong Huang 	dsb();
849*e3ec6ff4SXiaoDong Huang 	flush_dcache_range((uintptr_t)cpuson_flags, sizeof(cpuson_flags));
850*e3ec6ff4SXiaoDong Huang 	flush_dcache_range((uintptr_t)cpuson_entry_point,
851*e3ec6ff4SXiaoDong Huang 			   sizeof(cpuson_entry_point));
852*e3ec6ff4SXiaoDong Huang 	dsb();
853*e3ec6ff4SXiaoDong Huang 	isb();
854*e3ec6ff4SXiaoDong Huang 
855*e3ec6ff4SXiaoDong Huang 	cpus_power_domain_off(cpu_id, core_pwr_wfi_int);
856*e3ec6ff4SXiaoDong Huang 
857*e3ec6ff4SXiaoDong Huang 	__asm__ volatile ("msr	DBGPRCR_EL1, xzr\n"
858*e3ec6ff4SXiaoDong Huang 			  "mrs	x0, S3_0_C15_C2_7\n"
859*e3ec6ff4SXiaoDong Huang 			  "orr	x0, x0, #0x1\n"
860*e3ec6ff4SXiaoDong Huang 			  "msr	S3_0_C15_C2_7, x0\n");
861*e3ec6ff4SXiaoDong Huang 
862*e3ec6ff4SXiaoDong Huang 	return PSCI_E_SUCCESS;
863*e3ec6ff4SXiaoDong Huang }
864*e3ec6ff4SXiaoDong Huang 
865*e3ec6ff4SXiaoDong Huang int rockchip_soc_cores_pwr_dm_resume(void)
866*e3ec6ff4SXiaoDong Huang {
867*e3ec6ff4SXiaoDong Huang 	uint32_t cpu_id = plat_my_core_pos();
868*e3ec6ff4SXiaoDong Huang 
869*e3ec6ff4SXiaoDong Huang 	mmio_write_32(PMU_BASE + PMU2_CPU_AUTO_PWR_CON(cpu_id),
870*e3ec6ff4SXiaoDong Huang 		      BITS_WITH_WMASK(0, 0x3, 0));
871*e3ec6ff4SXiaoDong Huang 
872*e3ec6ff4SXiaoDong Huang 	dsb();
873*e3ec6ff4SXiaoDong Huang 
874*e3ec6ff4SXiaoDong Huang 	return PSCI_E_SUCCESS;
875*e3ec6ff4SXiaoDong Huang }
876*e3ec6ff4SXiaoDong Huang 
877*e3ec6ff4SXiaoDong Huang static void ddr_sleep_config(void)
878*e3ec6ff4SXiaoDong Huang {
879*e3ec6ff4SXiaoDong Huang 	int i;
880*e3ec6ff4SXiaoDong Huang 
881*e3ec6ff4SXiaoDong Huang 	if (pmu_power_domain_st(PD_DDR01) == 0) {
882*e3ec6ff4SXiaoDong Huang 		ddr_data.ddrgrf_chn_con0[0] =
883*e3ec6ff4SXiaoDong Huang 			mmio_read_32(DDR01GRF_BASE + DDRGRF_CHA_CON(0));
884*e3ec6ff4SXiaoDong Huang 		ddr_data.ddrgrf_chn_con0[1] =
885*e3ec6ff4SXiaoDong Huang 			mmio_read_32(DDR01GRF_BASE + DDRGRF_CHB_CON(0));
886*e3ec6ff4SXiaoDong Huang 		ddr_data.ddrgrf_chn_con1[0] =
887*e3ec6ff4SXiaoDong Huang 			mmio_read_32(DDR01GRF_BASE + DDRGRF_CHA_CON(1));
888*e3ec6ff4SXiaoDong Huang 		ddr_data.ddrgrf_chn_con1[1] =
889*e3ec6ff4SXiaoDong Huang 			mmio_read_32(DDR01GRF_BASE + DDRGRF_CHB_CON(1));
890*e3ec6ff4SXiaoDong Huang 		ddr_data.ddrgrf_chn_con2[0] =
891*e3ec6ff4SXiaoDong Huang 			mmio_read_32(DDR01GRF_BASE + DDRGRF_CHA_CON(2));
892*e3ec6ff4SXiaoDong Huang 		ddr_data.ddrgrf_chn_con2[1] =
893*e3ec6ff4SXiaoDong Huang 			mmio_read_32(DDR01GRF_BASE + DDRGRF_CHB_CON(2));
894*e3ec6ff4SXiaoDong Huang 
895*e3ec6ff4SXiaoDong Huang 		mmio_write_32(DDR01GRF_BASE + DDRGRF_CHA_CON(2), 0x20002000);
896*e3ec6ff4SXiaoDong Huang 		mmio_write_32(DDR01GRF_BASE + DDRGRF_CHB_CON(2), 0x20002000);
897*e3ec6ff4SXiaoDong Huang 		mmio_write_32(DDR01GRF_BASE + DDRGRF_CHA_CON(2), 0x08000000);
898*e3ec6ff4SXiaoDong Huang 		mmio_write_32(DDR01GRF_BASE + DDRGRF_CHB_CON(2), 0x08000000);
899*e3ec6ff4SXiaoDong Huang 		mmio_write_32(DDR01GRF_BASE + DDRGRF_CHA_CON(0), 0x00200020);
900*e3ec6ff4SXiaoDong Huang 		mmio_write_32(DDR01GRF_BASE + DDRGRF_CHB_CON(0), 0x00200020);
901*e3ec6ff4SXiaoDong Huang 		mmio_write_32(DDR01GRF_BASE + DDRGRF_CHA_CON(1), 0x00400040);
902*e3ec6ff4SXiaoDong Huang 		mmio_write_32(DDR01GRF_BASE + DDRGRF_CHB_CON(1), 0x00400040);
903*e3ec6ff4SXiaoDong Huang 	}
904*e3ec6ff4SXiaoDong Huang 
905*e3ec6ff4SXiaoDong Huang 	if (pmu_power_domain_st(PD_DDR23) == 0) {
906*e3ec6ff4SXiaoDong Huang 		ddr_data.ddrgrf_chn_con0[2] =
907*e3ec6ff4SXiaoDong Huang 			mmio_read_32(DDR23GRF_BASE + DDRGRF_CHA_CON(0));
908*e3ec6ff4SXiaoDong Huang 		ddr_data.ddrgrf_chn_con0[3] =
909*e3ec6ff4SXiaoDong Huang 			mmio_read_32(DDR23GRF_BASE + DDRGRF_CHB_CON(0));
910*e3ec6ff4SXiaoDong Huang 		ddr_data.ddrgrf_chn_con1[2] =
911*e3ec6ff4SXiaoDong Huang 			mmio_read_32(DDR23GRF_BASE + DDRGRF_CHA_CON(1));
912*e3ec6ff4SXiaoDong Huang 		ddr_data.ddrgrf_chn_con1[3] =
913*e3ec6ff4SXiaoDong Huang 			mmio_read_32(DDR23GRF_BASE + DDRGRF_CHB_CON(1));
914*e3ec6ff4SXiaoDong Huang 		ddr_data.ddrgrf_chn_con2[2] =
915*e3ec6ff4SXiaoDong Huang 			mmio_read_32(DDR23GRF_BASE + DDRGRF_CHA_CON(2));
916*e3ec6ff4SXiaoDong Huang 		ddr_data.ddrgrf_chn_con2[3] =
917*e3ec6ff4SXiaoDong Huang 			mmio_read_32(DDR23GRF_BASE + DDRGRF_CHB_CON(2));
918*e3ec6ff4SXiaoDong Huang 
919*e3ec6ff4SXiaoDong Huang 		mmio_write_32(DDR23GRF_BASE + DDRGRF_CHA_CON(2), 0x20002000);
920*e3ec6ff4SXiaoDong Huang 		mmio_write_32(DDR23GRF_BASE + DDRGRF_CHB_CON(2), 0x20002000);
921*e3ec6ff4SXiaoDong Huang 		mmio_write_32(DDR23GRF_BASE + DDRGRF_CHA_CON(2), 0x08000000);
922*e3ec6ff4SXiaoDong Huang 		mmio_write_32(DDR23GRF_BASE + DDRGRF_CHB_CON(2), 0x08000000);
923*e3ec6ff4SXiaoDong Huang 		mmio_write_32(DDR23GRF_BASE + DDRGRF_CHA_CON(0), 0x00200020);
924*e3ec6ff4SXiaoDong Huang 		mmio_write_32(DDR23GRF_BASE + DDRGRF_CHB_CON(0), 0x00200020);
925*e3ec6ff4SXiaoDong Huang 		mmio_write_32(DDR23GRF_BASE + DDRGRF_CHA_CON(1), 0x00400040);
926*e3ec6ff4SXiaoDong Huang 		mmio_write_32(DDR23GRF_BASE + DDRGRF_CHB_CON(1), 0x00400040);
927*e3ec6ff4SXiaoDong Huang 	}
928*e3ec6ff4SXiaoDong Huang 
929*e3ec6ff4SXiaoDong Huang 	for (i = 0; i < DDR_CHN_CNT; i++) {
930*e3ec6ff4SXiaoDong Huang 		ddr_data.pmu1_ddr_pwr_sft_con[i] =
931*e3ec6ff4SXiaoDong Huang 			mmio_read_32(PMU_BASE + PMU1_DDR_PWR_SFTCON(i));
932*e3ec6ff4SXiaoDong Huang 		mmio_write_32(PMU_BASE + PMU1_DDR_PWR_SFTCON(i), 0x0fff0900);
933*e3ec6ff4SXiaoDong Huang 	}
934*e3ec6ff4SXiaoDong Huang }
935*e3ec6ff4SXiaoDong Huang 
936*e3ec6ff4SXiaoDong Huang static void ddr_sleep_config_restore(void)
937*e3ec6ff4SXiaoDong Huang {
938*e3ec6ff4SXiaoDong Huang 	int i;
939*e3ec6ff4SXiaoDong Huang 
940*e3ec6ff4SXiaoDong Huang 	for (i = 0; i < DDR_CHN_CNT; i++) {
941*e3ec6ff4SXiaoDong Huang 		mmio_write_32(PMU_BASE + PMU1_DDR_PWR_SFTCON(i),
942*e3ec6ff4SXiaoDong Huang 			      0x0fff0000 | ddr_data.pmu1_ddr_pwr_sft_con[i]);
943*e3ec6ff4SXiaoDong Huang 	}
944*e3ec6ff4SXiaoDong Huang 
945*e3ec6ff4SXiaoDong Huang 	if (pmu_power_domain_st(PD_DDR01) == 0) {
946*e3ec6ff4SXiaoDong Huang 		mmio_write_32(DDR01GRF_BASE + DDRGRF_CHA_CON(1),
947*e3ec6ff4SXiaoDong Huang 			      0x00400000 | ddr_data.ddrgrf_chn_con1[0]);
948*e3ec6ff4SXiaoDong Huang 		mmio_write_32(DDR01GRF_BASE + DDRGRF_CHB_CON(1),
949*e3ec6ff4SXiaoDong Huang 			      0x00400000 | ddr_data.ddrgrf_chn_con1[1]);
950*e3ec6ff4SXiaoDong Huang 		mmio_write_32(DDR01GRF_BASE + DDRGRF_CHA_CON(0),
951*e3ec6ff4SXiaoDong Huang 			      0x00200000 | ddr_data.ddrgrf_chn_con0[0]);
952*e3ec6ff4SXiaoDong Huang 		mmio_write_32(DDR01GRF_BASE + DDRGRF_CHB_CON(0),
953*e3ec6ff4SXiaoDong Huang 			      0x00200000 | ddr_data.ddrgrf_chn_con0[1]);
954*e3ec6ff4SXiaoDong Huang 		mmio_write_32(DDR01GRF_BASE + DDRGRF_CHA_CON(2),
955*e3ec6ff4SXiaoDong Huang 			      0x28000000 | ddr_data.ddrgrf_chn_con2[0]);
956*e3ec6ff4SXiaoDong Huang 		mmio_write_32(DDR01GRF_BASE + DDRGRF_CHB_CON(2),
957*e3ec6ff4SXiaoDong Huang 			      0x28000000 | ddr_data.ddrgrf_chn_con2[1]);
958*e3ec6ff4SXiaoDong Huang 	}
959*e3ec6ff4SXiaoDong Huang 
960*e3ec6ff4SXiaoDong Huang 	if (pmu_power_domain_st(PD_DDR23) == 0) {
961*e3ec6ff4SXiaoDong Huang 		mmio_write_32(DDR23GRF_BASE + DDRGRF_CHA_CON(1),
962*e3ec6ff4SXiaoDong Huang 			      0x00400000 | ddr_data.ddrgrf_chn_con1[2]);
963*e3ec6ff4SXiaoDong Huang 		mmio_write_32(DDR23GRF_BASE + DDRGRF_CHB_CON(1),
964*e3ec6ff4SXiaoDong Huang 			      0x00400000 | ddr_data.ddrgrf_chn_con1[3]);
965*e3ec6ff4SXiaoDong Huang 		mmio_write_32(DDR23GRF_BASE + DDRGRF_CHA_CON(0),
966*e3ec6ff4SXiaoDong Huang 			      0x00200000 | ddr_data.ddrgrf_chn_con0[2]);
967*e3ec6ff4SXiaoDong Huang 		mmio_write_32(DDR23GRF_BASE + DDRGRF_CHB_CON(0),
968*e3ec6ff4SXiaoDong Huang 			      0x00200000 | ddr_data.ddrgrf_chn_con0[3]);
969*e3ec6ff4SXiaoDong Huang 		mmio_write_32(DDR23GRF_BASE + DDRGRF_CHA_CON(2),
970*e3ec6ff4SXiaoDong Huang 			      0x28000000 | ddr_data.ddrgrf_chn_con2[2]);
971*e3ec6ff4SXiaoDong Huang 		mmio_write_32(DDR23GRF_BASE + DDRGRF_CHB_CON(2),
972*e3ec6ff4SXiaoDong Huang 			      0x28000000 | ddr_data.ddrgrf_chn_con2[3]);
973*e3ec6ff4SXiaoDong Huang 	}
974*e3ec6ff4SXiaoDong Huang }
975*e3ec6ff4SXiaoDong Huang 
976*e3ec6ff4SXiaoDong Huang static void pmu_sleep_config(void)
977*e3ec6ff4SXiaoDong Huang {
978*e3ec6ff4SXiaoDong Huang 	uint32_t pmu1_pwr_con, pmu1_wkup_int_con, pmu1_cru_pwr_con;
979*e3ec6ff4SXiaoDong Huang 	uint32_t pmu1_ddr_pwr_con, pmu1_pll_pd_con[2] = {0};
980*e3ec6ff4SXiaoDong Huang 	uint32_t pmu2_dsu_pwr_con, pmu2_core_pwr_con, pmu2_clst_idle_con;
981*e3ec6ff4SXiaoDong Huang 	uint32_t pmu2_bus_idle_con[3] = {0}, pmu2_pwr_gate_con[3] = {0};
982*e3ec6ff4SXiaoDong Huang 	uint32_t pmu2_vol_gate_con[3] = {0}, pmu2_qch_pwr_con = 0;
983*e3ec6ff4SXiaoDong Huang 	int i;
984*e3ec6ff4SXiaoDong Huang 
985*e3ec6ff4SXiaoDong Huang 	ddr_data.pmu1grf_soc_con7 = mmio_read_32(PMU1GRF_BASE + PMU1_GRF_SOC_CON(7));
986*e3ec6ff4SXiaoDong Huang 	ddr_data.pmu1grf_soc_con8 = mmio_read_32(PMU1GRF_BASE + PMU1_GRF_SOC_CON(8));
987*e3ec6ff4SXiaoDong Huang 	ddr_data.pmu1grf_soc_con9 = mmio_read_32(PMU1GRF_BASE + PMU1_GRF_SOC_CON(9));
988*e3ec6ff4SXiaoDong Huang 	ddr_data.pmu1sgrf_soc_con14 = mmio_read_32(PMU1SGRF_BASE + PMU1_SGRF_SOC_CON(14));
989*e3ec6ff4SXiaoDong Huang 	ddr_data.pmu0sgrf_soc_con1 = mmio_read_32(PMU0SGRF_BASE + PMU0_SGRF_SOC_CON(1));
990*e3ec6ff4SXiaoDong Huang 	ddr_data.pmu0grf_soc_con1 = mmio_read_32(PMU0GRF_BASE + PMU0_GRF_SOC_CON(1));
991*e3ec6ff4SXiaoDong Huang 
992*e3ec6ff4SXiaoDong Huang 	ddr_data.pmu2_vol_gate_con[0] = mmio_read_32(PMU_BASE + PMU2_VOL_GATE_CON(0));
993*e3ec6ff4SXiaoDong Huang 	ddr_data.pmu2_vol_gate_con[1] = mmio_read_32(PMU_BASE + PMU2_VOL_GATE_CON(1));
994*e3ec6ff4SXiaoDong Huang 	ddr_data.pmu2_vol_gate_con[2] = mmio_read_32(PMU_BASE + PMU2_VOL_GATE_CON(2));
995*e3ec6ff4SXiaoDong Huang 
996*e3ec6ff4SXiaoDong Huang 	ddr_data.pmu2_submem_gate_sft_con0 =
997*e3ec6ff4SXiaoDong Huang 		mmio_read_32(PMU_BASE + PMU2_MEMPWR_MD_GATE_SFTCON(0));
998*e3ec6ff4SXiaoDong Huang 
999*e3ec6ff4SXiaoDong Huang 	/* save pmic_sleep iomux gpio0_a4 */
1000*e3ec6ff4SXiaoDong Huang 	ddr_data.gpio0a_iomux_l = mmio_read_32(PMU0IOC_BASE + 0);
1001*e3ec6ff4SXiaoDong Huang 	ddr_data.gpio0a_iomux_h = mmio_read_32(PMU0IOC_BASE + 4);
1002*e3ec6ff4SXiaoDong Huang 	ddr_data.pmu0grf_soc_con3 = mmio_read_32(PMU0GRF_BASE + PMU0_GRF_SOC_CON(3));
1003*e3ec6ff4SXiaoDong Huang 
1004*e3ec6ff4SXiaoDong Huang 	/* PMU1 repair disable */
1005*e3ec6ff4SXiaoDong Huang 	mmio_write_32(PMU0GRF_BASE + PMU0_GRF_SOC_CON(0), 0x00010000);
1006*e3ec6ff4SXiaoDong Huang 
1007*e3ec6ff4SXiaoDong Huang 	/* set pmic_sleep iomux */
1008*e3ec6ff4SXiaoDong Huang 	mmio_write_32(PMU0IOC_BASE + 0,
1009*e3ec6ff4SXiaoDong Huang 		      BITS_WITH_WMASK(1, 0xf, 8) |
1010*e3ec6ff4SXiaoDong Huang 		      BITS_WITH_WMASK(1, 0xfu, 12));
1011*e3ec6ff4SXiaoDong Huang 
1012*e3ec6ff4SXiaoDong Huang 	/* set tsadc_shut_m0 pin iomux to gpio */
1013*e3ec6ff4SXiaoDong Huang 	mmio_write_32(PMU0IOC_BASE + 0,
1014*e3ec6ff4SXiaoDong Huang 		      BITS_WITH_WMASK(0, 0xf, 4));
1015*e3ec6ff4SXiaoDong Huang 
1016*e3ec6ff4SXiaoDong Huang 	/* set spi2_cs0/1 pin iomux to gpio */
1017*e3ec6ff4SXiaoDong Huang 	mmio_write_32(PMU0IOC_BASE + 8,
1018*e3ec6ff4SXiaoDong Huang 		      BITS_WITH_WMASK(0, 0xff, 0));
1019*e3ec6ff4SXiaoDong Huang 
1020*e3ec6ff4SXiaoDong Huang 	/* sleep 1~2 src select */
1021*e3ec6ff4SXiaoDong Huang 	mmio_write_32(PMU0GRF_BASE + PMU0_GRF_SOC_CON(3),
1022*e3ec6ff4SXiaoDong Huang 		      BITS_WITH_WMASK(0x8, 0xf, 0) |
1023*e3ec6ff4SXiaoDong Huang 		      BITS_WITH_WMASK(0x8, 0xf, 4) |
1024*e3ec6ff4SXiaoDong Huang 		      BITS_WITH_WMASK(0x0, 0x3, 8));
1025*e3ec6ff4SXiaoDong Huang 
1026*e3ec6ff4SXiaoDong Huang 	pmu1_wkup_int_con = BIT(WAKEUP_GPIO0_INT_EN) |
1027*e3ec6ff4SXiaoDong Huang 			    BIT(WAKEUP_CPU0_INT_EN);
1028*e3ec6ff4SXiaoDong Huang 
1029*e3ec6ff4SXiaoDong Huang 	pmu1_pwr_con = BIT(powermode_en);
1030*e3ec6ff4SXiaoDong Huang 
1031*e3ec6ff4SXiaoDong Huang 	pmu1_cru_pwr_con =
1032*e3ec6ff4SXiaoDong Huang 		BIT(alive_osc_mode_en) |
1033*e3ec6ff4SXiaoDong Huang 		BIT(power_off_en) |
1034*e3ec6ff4SXiaoDong Huang 		BIT(pd_clk_src_gate_en);
1035*e3ec6ff4SXiaoDong Huang 
1036*e3ec6ff4SXiaoDong Huang 	pmu1_ddr_pwr_con = 0;
1037*e3ec6ff4SXiaoDong Huang 
1038*e3ec6ff4SXiaoDong Huang 	pmu2_dsu_pwr_con =
1039*e3ec6ff4SXiaoDong Huang 		BIT(DSU_PWRDN_EN) |
1040*e3ec6ff4SXiaoDong Huang 		BIT(DSU_PWROFF_EN);
1041*e3ec6ff4SXiaoDong Huang 
1042*e3ec6ff4SXiaoDong Huang 	pmu2_core_pwr_con = BIT(CORE_PWRDN_EN);
1043*e3ec6ff4SXiaoDong Huang 
1044*e3ec6ff4SXiaoDong Huang 	pmu2_clst_idle_con =
1045*e3ec6ff4SXiaoDong Huang 		BIT(IDLE_REQ_BIGCORE0_EN) |
1046*e3ec6ff4SXiaoDong Huang 		BIT(IDLE_REQ_BIGCORE1_EN) |
1047*e3ec6ff4SXiaoDong Huang 		BIT(IDLE_REQ_DSU_EN) |
1048*e3ec6ff4SXiaoDong Huang 		BIT(IDLE_REQ_LITDSU_EN) |
1049*e3ec6ff4SXiaoDong Huang 		BIT(IDLE_REQ_ADB400_CORE_QCH_EN);
1050*e3ec6ff4SXiaoDong Huang 
1051*e3ec6ff4SXiaoDong Huang 	pmu1_pll_pd_con[0] =
1052*e3ec6ff4SXiaoDong Huang 		BIT(B0PLL_PD_EN) |
1053*e3ec6ff4SXiaoDong Huang 		BIT(B1PLL_PD_EN) |
1054*e3ec6ff4SXiaoDong Huang 		BIT(LPLL_PD_EN) |
1055*e3ec6ff4SXiaoDong Huang 		BIT(V0PLL_PD_EN) |
1056*e3ec6ff4SXiaoDong Huang 		BIT(AUPLL_PD_EN) |
1057*e3ec6ff4SXiaoDong Huang 		BIT(GPLL_PD_EN) |
1058*e3ec6ff4SXiaoDong Huang 		BIT(CPLL_PD_EN) |
1059*e3ec6ff4SXiaoDong Huang 		BIT(NPLL_PD_EN);
1060*e3ec6ff4SXiaoDong Huang 
1061*e3ec6ff4SXiaoDong Huang 	pmu1_pll_pd_con[1] =
1062*e3ec6ff4SXiaoDong Huang 		BIT(PPLL_PD_EN) |
1063*e3ec6ff4SXiaoDong Huang 		BIT(SPLL_PD_EN);
1064*e3ec6ff4SXiaoDong Huang 
1065*e3ec6ff4SXiaoDong Huang 	pmu2_bus_idle_con[0] = 0;
1066*e3ec6ff4SXiaoDong Huang 
1067*e3ec6ff4SXiaoDong Huang 	pmu2_bus_idle_con[1] =
1068*e3ec6ff4SXiaoDong Huang 		BIT(BUS_ID_SECURE - 16) |
1069*e3ec6ff4SXiaoDong Huang 		BIT(BUS_ID_SECURE_CENTER_CHANNEL - 16) |
1070*e3ec6ff4SXiaoDong Huang 		BIT(BUS_ID_CENTER_CHANNEL - 16);
1071*e3ec6ff4SXiaoDong Huang 
1072*e3ec6ff4SXiaoDong Huang 	pmu2_bus_idle_con[2] =
1073*e3ec6ff4SXiaoDong Huang 		BIT(BUS_ID_MSCH - 32) |
1074*e3ec6ff4SXiaoDong Huang 		BIT(BUS_ID_BUS - 32) |
1075*e3ec6ff4SXiaoDong Huang 		BIT(BUS_ID_TOP - 32);
1076*e3ec6ff4SXiaoDong Huang 
1077*e3ec6ff4SXiaoDong Huang 	pmu2_pwr_gate_con[0] = 0;
1078*e3ec6ff4SXiaoDong Huang 	pmu2_pwr_gate_con[1] = BIT(PD_SECURE - 16);
1079*e3ec6ff4SXiaoDong Huang 	pmu2_pwr_gate_con[2] = 0;
1080*e3ec6ff4SXiaoDong Huang 
1081*e3ec6ff4SXiaoDong Huang 	pmu2_qch_pwr_con = 0;
1082*e3ec6ff4SXiaoDong Huang 
1083*e3ec6ff4SXiaoDong Huang 	pmu2_vol_gate_con[0] = 0x7;
1084*e3ec6ff4SXiaoDong Huang 	pmu2_vol_gate_con[2] = 0;
1085*e3ec6ff4SXiaoDong Huang 
1086*e3ec6ff4SXiaoDong Huang 	mmio_write_32(PMU_BASE + PMU2_CORE_AUTO_PWR_CON(0), 0x00030000);
1087*e3ec6ff4SXiaoDong Huang 	mmio_write_32(PMU_BASE + PMU2_CORE_AUTO_PWR_CON(1), 0x00030000);
1088*e3ec6ff4SXiaoDong Huang 	mmio_write_32(PMU_BASE + PMU2_CORE_PWR_CON(0),
1089*e3ec6ff4SXiaoDong Huang 		      WITH_16BITS_WMSK(pmu2_core_pwr_con));
1090*e3ec6ff4SXiaoDong Huang 	mmio_write_32(PMU_BASE + PMU2_CORE_PWR_CON(1),
1091*e3ec6ff4SXiaoDong Huang 		      WITH_16BITS_WMSK(pmu2_core_pwr_con));
1092*e3ec6ff4SXiaoDong Huang 	mmio_write_32(PMU_BASE + PMU2_CLUSTER_IDLE_CON,
1093*e3ec6ff4SXiaoDong Huang 		      WITH_16BITS_WMSK(pmu2_clst_idle_con));
1094*e3ec6ff4SXiaoDong Huang 	mmio_write_32(PMU_BASE + PMU2_DSU_AUTO_PWR_CON, 0x00030000);
1095*e3ec6ff4SXiaoDong Huang 	mmio_write_32(PMU_BASE + PMU2_DSU_PWR_CON,
1096*e3ec6ff4SXiaoDong Huang 		      WITH_16BITS_WMSK(pmu2_dsu_pwr_con));
1097*e3ec6ff4SXiaoDong Huang 
1098*e3ec6ff4SXiaoDong Huang 	mmio_write_32(PMU_BASE + PMU1_OSC_STABLE_CNT_THRESH, 24000);
1099*e3ec6ff4SXiaoDong Huang 	mmio_write_32(PMU_BASE + PMU1_STABLE_CNT_THRESH, 24000);
1100*e3ec6ff4SXiaoDong Huang 	mmio_write_32(PMU_BASE + PMU1_WAKEUP_RST_CLR_CNT_THRESH, 24000);
1101*e3ec6ff4SXiaoDong Huang 	mmio_write_32(PMU_BASE + PMU1_PLL_LOCK_CNT_THRESH, 24000);
1102*e3ec6ff4SXiaoDong Huang 	mmio_write_32(PMU_BASE + PMU1_PWM_SWITCH_CNT_THRESH, 24000);
1103*e3ec6ff4SXiaoDong Huang 	mmio_write_32(PMU_BASE + PMU2_CORE0_STABLE_CNT_THRESH, 24000);
1104*e3ec6ff4SXiaoDong Huang 	mmio_write_32(PMU_BASE + PMU2_CORE0_PWRUP_CNT_THRESH, 24000);
1105*e3ec6ff4SXiaoDong Huang 	mmio_write_32(PMU_BASE + PMU2_CORE0_PWRDN_CNT_THRESH, 24000);
1106*e3ec6ff4SXiaoDong Huang 	mmio_write_32(PMU_BASE + PMU2_CORE1_STABLE_CNT_THRESH, 24000);
1107*e3ec6ff4SXiaoDong Huang 	mmio_write_32(PMU_BASE + PMU2_CORE1_PWRUP_CNT_THRESH, 24000);
1108*e3ec6ff4SXiaoDong Huang 	mmio_write_32(PMU_BASE + PMU2_CORE1_PWRDN_CNT_THRESH, 24000);
1109*e3ec6ff4SXiaoDong Huang 	mmio_write_32(PMU_BASE + PMU2_DSU_STABLE_CNT_THRESH, 24000);
1110*e3ec6ff4SXiaoDong Huang 	mmio_write_32(PMU_BASE + PMU2_DSU_PWRUP_CNT_THRESH, 24000);
1111*e3ec6ff4SXiaoDong Huang 	mmio_write_32(PMU_BASE + PMU2_DSU_PWRDN_CNT_THRESH, 24000);
1112*e3ec6ff4SXiaoDong Huang 
1113*e3ec6ff4SXiaoDong Huang 	/* Config pmu power mode and pmu wakeup source */
1114*e3ec6ff4SXiaoDong Huang 	mmio_write_32(PMU_BASE + PMU1_INT_MASK_CON,
1115*e3ec6ff4SXiaoDong Huang 		      BITS_WITH_WMASK(1, 0x1, 0));
1116*e3ec6ff4SXiaoDong Huang 
1117*e3ec6ff4SXiaoDong Huang 	/* pmu1_pwr_con */
1118*e3ec6ff4SXiaoDong Huang 	mmio_write_32(PMU_BASE + PMU1_PWR_CON,
1119*e3ec6ff4SXiaoDong Huang 		      WITH_16BITS_WMSK(pmu1_pwr_con));
1120*e3ec6ff4SXiaoDong Huang 
1121*e3ec6ff4SXiaoDong Huang 	/* cru_pwr_con */
1122*e3ec6ff4SXiaoDong Huang 	mmio_write_32(PMU_BASE + PMU1_CRU_PWR_CON,
1123*e3ec6ff4SXiaoDong Huang 		      WITH_16BITS_WMSK(pmu1_cru_pwr_con));
1124*e3ec6ff4SXiaoDong Huang 
1125*e3ec6ff4SXiaoDong Huang 	/* wakeup source */
1126*e3ec6ff4SXiaoDong Huang 	mmio_write_32(PMU_BASE + PMU1_WAKEUP_INT_CON, pmu1_wkup_int_con);
1127*e3ec6ff4SXiaoDong Huang 
1128*e3ec6ff4SXiaoDong Huang 	/* ddr pwr con */
1129*e3ec6ff4SXiaoDong Huang 	for (i = 0; i < DDR_CHN_CNT; i++) {
1130*e3ec6ff4SXiaoDong Huang 		mmio_write_32(PMU_BASE + PMU1_DDR_PWR_CON(i),
1131*e3ec6ff4SXiaoDong Huang 			      WITH_16BITS_WMSK(pmu1_ddr_pwr_con));
1132*e3ec6ff4SXiaoDong Huang 		pmu2_bus_idle_con[1] |=
1133*e3ec6ff4SXiaoDong Huang 			BIT(BUS_ID_MSCH0 - 16 + i);
1134*e3ec6ff4SXiaoDong Huang 	}
1135*e3ec6ff4SXiaoDong Huang 
1136*e3ec6ff4SXiaoDong Huang 	/* pll_pd */
1137*e3ec6ff4SXiaoDong Huang 	mmio_write_32(PMU_BASE + PMU1_PLLPD_CON(0),
1138*e3ec6ff4SXiaoDong Huang 		      WITH_16BITS_WMSK(pmu1_pll_pd_con[0]));
1139*e3ec6ff4SXiaoDong Huang 	mmio_write_32(PMU_BASE + PMU1_PLLPD_CON(1),
1140*e3ec6ff4SXiaoDong Huang 		      WITH_16BITS_WMSK(pmu1_pll_pd_con[1]));
1141*e3ec6ff4SXiaoDong Huang 
1142*e3ec6ff4SXiaoDong Huang 	/* bypass cpu1~7*/
1143*e3ec6ff4SXiaoDong Huang 	mmio_write_32(PMU_BASE + PMU2_PWR_CON1, 0x00ff00fe);
1144*e3ec6ff4SXiaoDong Huang 
1145*e3ec6ff4SXiaoDong Huang 	/* bus idle */
1146*e3ec6ff4SXiaoDong Huang 	mmio_write_32(PMU_BASE + PMU2_BUS_IDLE_CON(0),
1147*e3ec6ff4SXiaoDong Huang 		      WITH_16BITS_WMSK(pmu2_bus_idle_con[0]));
1148*e3ec6ff4SXiaoDong Huang 	mmio_write_32(PMU_BASE + PMU2_BUS_IDLE_CON(1),
1149*e3ec6ff4SXiaoDong Huang 		      WITH_16BITS_WMSK(pmu2_bus_idle_con[1]));
1150*e3ec6ff4SXiaoDong Huang 	mmio_write_32(PMU_BASE + PMU2_BUS_IDLE_CON(2),
1151*e3ec6ff4SXiaoDong Huang 		      WITH_16BITS_WMSK(pmu2_bus_idle_con[2]));
1152*e3ec6ff4SXiaoDong Huang 	mmio_write_32(PMU_BASE + PMU2_BUS_IDLE_CON(2),
1153*e3ec6ff4SXiaoDong Huang 		      0xf000f000);
1154*e3ec6ff4SXiaoDong Huang 	/* power gate */
1155*e3ec6ff4SXiaoDong Huang 	mmio_write_32(PMU_BASE + PMU2_PWR_GATE_CON(0),
1156*e3ec6ff4SXiaoDong Huang 		      WITH_16BITS_WMSK(pmu2_pwr_gate_con[0]));
1157*e3ec6ff4SXiaoDong Huang 	mmio_write_32(PMU_BASE + PMU2_PWR_GATE_CON(1),
1158*e3ec6ff4SXiaoDong Huang 		      WITH_16BITS_WMSK(pmu2_pwr_gate_con[1]));
1159*e3ec6ff4SXiaoDong Huang 	mmio_write_32(PMU_BASE + PMU2_PWR_GATE_CON(2),
1160*e3ec6ff4SXiaoDong Huang 		      WITH_16BITS_WMSK(pmu2_pwr_gate_con[2]));
1161*e3ec6ff4SXiaoDong Huang 	/* vol gate */
1162*e3ec6ff4SXiaoDong Huang 	mmio_write_32(PMU_BASE + PMU2_VOL_GATE_CON(0),
1163*e3ec6ff4SXiaoDong Huang 		      BITS_WITH_WMASK(pmu2_vol_gate_con[0], 0x7, 0));
1164*e3ec6ff4SXiaoDong Huang 	mmio_write_32(PMU_BASE + PMU2_VOL_GATE_CON(1), 0);
1165*e3ec6ff4SXiaoDong Huang 	mmio_write_32(PMU_BASE + PMU2_VOL_GATE_CON(2),
1166*e3ec6ff4SXiaoDong Huang 		      BITS_WITH_WMASK(pmu2_vol_gate_con[2], 0x3, 0));
1167*e3ec6ff4SXiaoDong Huang 	/* qch */
1168*e3ec6ff4SXiaoDong Huang 	mmio_write_32(PMU_BASE + PMU2_QCHANNEL_PWR_CON,
1169*e3ec6ff4SXiaoDong Huang 		      BITS_WITH_WMASK(pmu2_qch_pwr_con, 0x7f, 0));
1170*e3ec6ff4SXiaoDong Huang 
1171*e3ec6ff4SXiaoDong Huang 	mmio_write_32(PMU_BASE + PMU2_MEMPWR_MD_GATE_SFTCON(0),
1172*e3ec6ff4SXiaoDong Huang 		      0x000f000f);
1173*e3ec6ff4SXiaoDong Huang }
1174*e3ec6ff4SXiaoDong Huang 
1175*e3ec6ff4SXiaoDong Huang static void pmu_sleep_restore(void)
1176*e3ec6ff4SXiaoDong Huang {
1177*e3ec6ff4SXiaoDong Huang 	mmio_write_32(PMU1GRF_BASE + PMU1_GRF_SOC_CON(7),
1178*e3ec6ff4SXiaoDong Huang 		      WITH_16BITS_WMSK(ddr_data.pmu1grf_soc_con7));
1179*e3ec6ff4SXiaoDong Huang 	mmio_write_32(PMU1GRF_BASE + PMU1_GRF_SOC_CON(8),
1180*e3ec6ff4SXiaoDong Huang 		      WITH_16BITS_WMSK(ddr_data.pmu1grf_soc_con8));
1181*e3ec6ff4SXiaoDong Huang 	mmio_write_32(PMU1GRF_BASE + PMU1_GRF_SOC_CON(9),
1182*e3ec6ff4SXiaoDong Huang 		      WITH_16BITS_WMSK(ddr_data.pmu1grf_soc_con9));
1183*e3ec6ff4SXiaoDong Huang 	mmio_write_32(PMU1SGRF_BASE + PMU1_SGRF_SOC_CON(14),
1184*e3ec6ff4SXiaoDong Huang 		      WITH_16BITS_WMSK(ddr_data.pmu1sgrf_soc_con14));
1185*e3ec6ff4SXiaoDong Huang 
1186*e3ec6ff4SXiaoDong Huang 	mmio_write_32(PMU0SGRF_BASE + PMU0_SGRF_SOC_CON(1),
1187*e3ec6ff4SXiaoDong Huang 		      WITH_16BITS_WMSK(ddr_data.pmu0sgrf_soc_con1));
1188*e3ec6ff4SXiaoDong Huang 	mmio_write_32(PMU0GRF_BASE + PMU0_GRF_SOC_CON(1),
1189*e3ec6ff4SXiaoDong Huang 		      WITH_16BITS_WMSK(ddr_data.pmu0grf_soc_con1));
1190*e3ec6ff4SXiaoDong Huang 
1191*e3ec6ff4SXiaoDong Huang 	mmio_write_32(PMU_BASE + PMU2_CORE_PWR_CON(0), 0xffff0000);
1192*e3ec6ff4SXiaoDong Huang 	mmio_write_32(PMU_BASE + PMU2_CORE_PWR_CON(1), 0xffff0000);
1193*e3ec6ff4SXiaoDong Huang 	mmio_write_32(PMU_BASE + PMU2_CLUSTER_IDLE_CON, 0xffff0000);
1194*e3ec6ff4SXiaoDong Huang 	mmio_write_32(PMU_BASE + PMU2_DSU_PWR_CON, 0xffff0000);
1195*e3ec6ff4SXiaoDong Huang 	mmio_write_32(PMU_BASE + PMU2_PWR_CON1, 0xffff0000);
1196*e3ec6ff4SXiaoDong Huang 
1197*e3ec6ff4SXiaoDong Huang 	/* Must clear PMU1_WAKEUP_INT_CON because the wakeup source
1198*e3ec6ff4SXiaoDong Huang 	 * in PMU1_WAKEUP_INT_CON will wakeup cpus in cpu_auto_pd state.
1199*e3ec6ff4SXiaoDong Huang 	 */
1200*e3ec6ff4SXiaoDong Huang 	mmio_write_32(PMU_BASE + PMU1_WAKEUP_INT_CON, 0);
1201*e3ec6ff4SXiaoDong Huang 	mmio_write_32(PMU_BASE + PMU1_PWR_CON, 0xffff0000);
1202*e3ec6ff4SXiaoDong Huang 	mmio_write_32(PMU_BASE + PMU1_INT_MASK_CON, 0x00010000);
1203*e3ec6ff4SXiaoDong Huang 	mmio_write_32(PMU_BASE + PMU0_WAKEUP_INT_CON, 0x00010000);
1204*e3ec6ff4SXiaoDong Huang 	mmio_write_32(PMU_BASE + PMU0_PWR_CON, 0xffff0000);
1205*e3ec6ff4SXiaoDong Huang 
1206*e3ec6ff4SXiaoDong Huang 	mmio_write_32(PMU_BASE + PMU2_VOL_GATE_CON(0),
1207*e3ec6ff4SXiaoDong Huang 		      WITH_16BITS_WMSK(ddr_data.pmu2_vol_gate_con[0]));
1208*e3ec6ff4SXiaoDong Huang 	mmio_write_32(PMU_BASE + PMU2_VOL_GATE_CON(1),
1209*e3ec6ff4SXiaoDong Huang 		      WITH_16BITS_WMSK(ddr_data.pmu2_vol_gate_con[1]));
1210*e3ec6ff4SXiaoDong Huang 	mmio_write_32(PMU_BASE + PMU2_VOL_GATE_CON(2),
1211*e3ec6ff4SXiaoDong Huang 		      WITH_16BITS_WMSK(ddr_data.pmu2_vol_gate_con[2]));
1212*e3ec6ff4SXiaoDong Huang 
1213*e3ec6ff4SXiaoDong Huang 	mmio_write_32(PMU_BASE + PMU2_MEMPWR_MD_GATE_SFTCON(0),
1214*e3ec6ff4SXiaoDong Huang 		      WITH_16BITS_WMSK(ddr_data.pmu2_submem_gate_sft_con0));
1215*e3ec6ff4SXiaoDong Huang 
1216*e3ec6ff4SXiaoDong Huang 	mmio_write_32(PMU0GRF_BASE + PMU0_GRF_SOC_CON(3),
1217*e3ec6ff4SXiaoDong Huang 		      WITH_16BITS_WMSK(ddr_data.pmu0grf_soc_con3));
1218*e3ec6ff4SXiaoDong Huang 	mmio_write_32(PMU1GRF_BASE + PMU1_GRF_SOC_CON(2),
1219*e3ec6ff4SXiaoDong Huang 		      WITH_16BITS_WMSK(ddr_data.pmu1grf_soc_con2));
1220*e3ec6ff4SXiaoDong Huang 
1221*e3ec6ff4SXiaoDong Huang 	mmio_write_32(PMU0IOC_BASE + 0x4,
1222*e3ec6ff4SXiaoDong Huang 		      WITH_16BITS_WMSK(ddr_data.gpio0a_iomux_h));
1223*e3ec6ff4SXiaoDong Huang 	mmio_write_32(PMU0IOC_BASE + 0,
1224*e3ec6ff4SXiaoDong Huang 		      WITH_16BITS_WMSK(ddr_data.gpio0a_iomux_l));
1225*e3ec6ff4SXiaoDong Huang }
1226*e3ec6ff4SXiaoDong Huang 
1227*e3ec6ff4SXiaoDong Huang static void soc_sleep_config(void)
1228*e3ec6ff4SXiaoDong Huang {
1229*e3ec6ff4SXiaoDong Huang 	ddr_data.gpio0b_iomux_l = mmio_read_32(PMU0IOC_BASE + 0x8);
1230*e3ec6ff4SXiaoDong Huang 
1231*e3ec6ff4SXiaoDong Huang 	pmu_sleep_config();
1232*e3ec6ff4SXiaoDong Huang 	ddr_sleep_config();
1233*e3ec6ff4SXiaoDong Huang }
1234*e3ec6ff4SXiaoDong Huang 
1235*e3ec6ff4SXiaoDong Huang static void soc_sleep_restore(void)
1236*e3ec6ff4SXiaoDong Huang {
1237*e3ec6ff4SXiaoDong Huang 	ddr_sleep_config_restore();
1238*e3ec6ff4SXiaoDong Huang 	pmu_sleep_restore();
1239*e3ec6ff4SXiaoDong Huang 
1240*e3ec6ff4SXiaoDong Huang 	mmio_write_32(PMU0IOC_BASE + 0x8, WITH_16BITS_WMSK(ddr_data.gpio0b_iomux_l));
1241*e3ec6ff4SXiaoDong Huang }
1242*e3ec6ff4SXiaoDong Huang 
1243*e3ec6ff4SXiaoDong Huang static void pm_pll_suspend(void)
1244*e3ec6ff4SXiaoDong Huang {
1245*e3ec6ff4SXiaoDong Huang 	ddr_data.cru_mode_con = mmio_read_32(CRU_BASE + 0x280);
1246*e3ec6ff4SXiaoDong Huang 	ddr_data.busscru_mode_con = mmio_read_32(BUSSCRU_BASE + 0x280);
1247*e3ec6ff4SXiaoDong Huang 	ddr_data.pmu2_bisr_con0 = mmio_read_32(PMU_BASE + PMU2_BISR_CON(0));
1248*e3ec6ff4SXiaoDong Huang 	ddr_data.cpll_con0 = mmio_read_32(CRU_BASE + CRU_PLLS_CON(2, 0));
1249*e3ec6ff4SXiaoDong Huang 	ddr_data.pmu1cru_clksel_con1 = mmio_read_32(PMU1CRU_BASE + CRU_CLKSEL_CON(1));
1250*e3ec6ff4SXiaoDong Huang 
1251*e3ec6ff4SXiaoDong Huang 	/* disable bisr_init */
1252*e3ec6ff4SXiaoDong Huang 	mmio_write_32(PMU_BASE + PMU2_BISR_CON(0), BITS_WITH_WMASK(0, 0x1, 0));
1253*e3ec6ff4SXiaoDong Huang 	/* cpll bypass */
1254*e3ec6ff4SXiaoDong Huang 	mmio_write_32(CRU_BASE + CRU_PLLS_CON(2, 0), BITS_WITH_WMASK(1u, 1u, 15));
1255*e3ec6ff4SXiaoDong Huang }
1256*e3ec6ff4SXiaoDong Huang 
1257*e3ec6ff4SXiaoDong Huang static void pm_pll_restore(void)
1258*e3ec6ff4SXiaoDong Huang {
1259*e3ec6ff4SXiaoDong Huang 	pm_pll_wait_lock(CRU_BASE + CRU_PLLS_CON(2, 0));
1260*e3ec6ff4SXiaoDong Huang 
1261*e3ec6ff4SXiaoDong Huang 	mmio_write_32(CRU_BASE + 0x280, WITH_16BITS_WMSK(ddr_data.cru_mode_con));
1262*e3ec6ff4SXiaoDong Huang 	mmio_write_32(BUSSCRU_BASE + 0x280, WITH_16BITS_WMSK(ddr_data.busscru_mode_con));
1263*e3ec6ff4SXiaoDong Huang 	mmio_write_32(CRU_BASE + CRU_PLLS_CON(2, 0), WITH_16BITS_WMSK(ddr_data.cpll_con0));
1264*e3ec6ff4SXiaoDong Huang 	dsb();
1265*e3ec6ff4SXiaoDong Huang 	isb();
1266*e3ec6ff4SXiaoDong Huang 	mmio_write_32(PMU_BASE + PMU2_BISR_CON(0), WITH_16BITS_WMSK(ddr_data.pmu2_bisr_con0));
1267*e3ec6ff4SXiaoDong Huang }
1268*e3ec6ff4SXiaoDong Huang 
1269*e3ec6ff4SXiaoDong Huang int rockchip_soc_sys_pwr_dm_suspend(void)
1270*e3ec6ff4SXiaoDong Huang {
1271*e3ec6ff4SXiaoDong Huang 	clk_gate_con_save();
1272*e3ec6ff4SXiaoDong Huang 	clk_gate_con_disable();
1273*e3ec6ff4SXiaoDong Huang 
1274*e3ec6ff4SXiaoDong Huang 	psram_sleep_cfg->pm_flag &= ~PM_WARM_BOOT_BIT;
1275*e3ec6ff4SXiaoDong Huang 
1276*e3ec6ff4SXiaoDong Huang 	pmu_power_domains_suspend();
1277*e3ec6ff4SXiaoDong Huang 	soc_sleep_config();
1278*e3ec6ff4SXiaoDong Huang 	dsu_core_save();
1279*e3ec6ff4SXiaoDong Huang 	pm_pll_suspend();
1280*e3ec6ff4SXiaoDong Huang 
1281*e3ec6ff4SXiaoDong Huang 	return 0;
1282*e3ec6ff4SXiaoDong Huang }
1283*e3ec6ff4SXiaoDong Huang 
1284*e3ec6ff4SXiaoDong Huang int rockchip_soc_sys_pwr_dm_resume(void)
1285*e3ec6ff4SXiaoDong Huang {
1286*e3ec6ff4SXiaoDong Huang 	pm_pll_restore();
1287*e3ec6ff4SXiaoDong Huang 	dsu_core_restore();
1288*e3ec6ff4SXiaoDong Huang 	soc_sleep_restore();
1289*e3ec6ff4SXiaoDong Huang 	pmu_power_domains_resume();
1290*e3ec6ff4SXiaoDong Huang 	plat_rockchip_gic_cpuif_enable();
1291*e3ec6ff4SXiaoDong Huang 
1292*e3ec6ff4SXiaoDong Huang 	psram_sleep_cfg->pm_flag |= PM_WARM_BOOT_BIT;
1293*e3ec6ff4SXiaoDong Huang 
1294*e3ec6ff4SXiaoDong Huang 	clk_gate_con_restore();
1295*e3ec6ff4SXiaoDong Huang 
1296*e3ec6ff4SXiaoDong Huang 	return 0;
1297*e3ec6ff4SXiaoDong Huang }
1298*e3ec6ff4SXiaoDong Huang 
1299*e3ec6ff4SXiaoDong Huang void __dead2 rockchip_soc_cores_pd_pwr_dn_wfi(const
1300*e3ec6ff4SXiaoDong Huang 					psci_power_state_t *target_state)
1301*e3ec6ff4SXiaoDong Huang {
1302*e3ec6ff4SXiaoDong Huang 	psci_power_down_wfi();
1303*e3ec6ff4SXiaoDong Huang }
1304*e3ec6ff4SXiaoDong Huang 
1305*e3ec6ff4SXiaoDong Huang void __dead2 rockchip_soc_sys_pd_pwr_dn_wfi(void)
1306*e3ec6ff4SXiaoDong Huang {
1307*e3ec6ff4SXiaoDong Huang 	cpus_pd_req_enter_wfi();
1308*e3ec6ff4SXiaoDong Huang 	psci_power_down_wfi();
1309*e3ec6ff4SXiaoDong Huang }
1310*e3ec6ff4SXiaoDong Huang 
1311*e3ec6ff4SXiaoDong Huang void __dead2 rockchip_soc_soft_reset(void)
1312*e3ec6ff4SXiaoDong Huang {
1313*e3ec6ff4SXiaoDong Huang 	/* pll slow mode */
1314*e3ec6ff4SXiaoDong Huang 	mmio_write_32(CRU_BASE + 0x280, 0x03ff0000);
1315*e3ec6ff4SXiaoDong Huang 	mmio_write_32(BIGCORE0CRU_BASE + 0x280, 0x00030000);
1316*e3ec6ff4SXiaoDong Huang 	mmio_write_32(BIGCORE0CRU_BASE + 0x300, 0x60000000);
1317*e3ec6ff4SXiaoDong Huang 	mmio_write_32(BIGCORE0CRU_BASE + 0x304, 0x00600000);
1318*e3ec6ff4SXiaoDong Huang 	mmio_write_32(BIGCORE1CRU_BASE + 0x280, 0x00030000);
1319*e3ec6ff4SXiaoDong Huang 	mmio_write_32(BIGCORE1CRU_BASE + 0x300, 0x60000000);
1320*e3ec6ff4SXiaoDong Huang 	mmio_write_32(BIGCORE1CRU_BASE + 0x304, 0x00600000);
1321*e3ec6ff4SXiaoDong Huang 	mmio_write_32(DSUCRU_BASE + 0x280, 0x00030000);
1322*e3ec6ff4SXiaoDong Huang 	mmio_write_32(DSUCRU_BASE + 0x318, 0x30600000);
1323*e3ec6ff4SXiaoDong Huang 	mmio_write_32(DSUCRU_BASE + 0x31c, 0x30600000);
1324*e3ec6ff4SXiaoDong Huang 	mmio_write_32(DSUCRU_BASE + 0x304, 0x00010000);
1325*e3ec6ff4SXiaoDong Huang 	mmio_write_32(BUSSCRU_BASE + 0x280, 0x0003000);
1326*e3ec6ff4SXiaoDong Huang 	dsb();
1327*e3ec6ff4SXiaoDong Huang 	isb();
1328*e3ec6ff4SXiaoDong Huang 
1329*e3ec6ff4SXiaoDong Huang 	mmio_write_32(CRU_BASE + CRU_GLB_SRST_FST, GLB_SRST_FST_CFG_VAL);
1330*e3ec6ff4SXiaoDong Huang 
1331*e3ec6ff4SXiaoDong Huang 	/*
1332*e3ec6ff4SXiaoDong Huang 	 * Maybe the HW needs some times to reset the system,
1333*e3ec6ff4SXiaoDong Huang 	 * so we do not hope the core to execute valid codes.
1334*e3ec6ff4SXiaoDong Huang 	 */
1335*e3ec6ff4SXiaoDong Huang 	psci_power_down_wfi();
1336*e3ec6ff4SXiaoDong Huang }
1337*e3ec6ff4SXiaoDong Huang 
1338*e3ec6ff4SXiaoDong Huang void __dead2 rockchip_soc_system_off(void)
1339*e3ec6ff4SXiaoDong Huang {
1340*e3ec6ff4SXiaoDong Huang 	/* set pmic_sleep pin(gpio0_a2) to gpio mode */
1341*e3ec6ff4SXiaoDong Huang 	mmio_write_32(PMU0IOC_BASE + 0, BITS_WITH_WMASK(0, 0xf, 8));
1342*e3ec6ff4SXiaoDong Huang 
1343*e3ec6ff4SXiaoDong Huang 	/* config output */
1344*e3ec6ff4SXiaoDong Huang 	mmio_write_32(GPIO0_BASE + GPIO_SWPORT_DDR_L,
1345*e3ec6ff4SXiaoDong Huang 		      BITS_WITH_WMASK(1, 0x1, 2));
1346*e3ec6ff4SXiaoDong Huang 
1347*e3ec6ff4SXiaoDong Huang 	/* config output high level */
1348*e3ec6ff4SXiaoDong Huang 	mmio_write_32(GPIO0_BASE + GPIO_SWPORT_DR_L,
1349*e3ec6ff4SXiaoDong Huang 		      BITS_WITH_WMASK(1, 0x1, 2));
1350*e3ec6ff4SXiaoDong Huang 	dsb();
1351*e3ec6ff4SXiaoDong Huang 
1352*e3ec6ff4SXiaoDong Huang 	/*
1353*e3ec6ff4SXiaoDong Huang 	 * Maybe the HW needs some times to reset the system,
1354*e3ec6ff4SXiaoDong Huang 	 * so we do not hope the core to execute valid codes.
1355*e3ec6ff4SXiaoDong Huang 	 */
1356*e3ec6ff4SXiaoDong Huang 	psci_power_down_wfi();
1357*e3ec6ff4SXiaoDong Huang }
1358*e3ec6ff4SXiaoDong Huang 
1359*e3ec6ff4SXiaoDong Huang static void rockchip_pmu_pd_init(void)
1360*e3ec6ff4SXiaoDong Huang {
1361*e3ec6ff4SXiaoDong Huang 	mmio_write_32(PMU_BASE + PMU2_BISR_CON(1), 0xffffffff);
1362*e3ec6ff4SXiaoDong Huang 	mmio_write_32(PMU_BASE + PMU2_BISR_CON(2), 0xffffffff);
1363*e3ec6ff4SXiaoDong Huang 	mmio_write_32(PMU_BASE + PMU2_BISR_CON(3), 0xffffffff);
1364*e3ec6ff4SXiaoDong Huang 
1365*e3ec6ff4SXiaoDong Huang 	pmu_set_power_domain(PD_PHP, pmu_pd_on);
1366*e3ec6ff4SXiaoDong Huang 	pmu_set_power_domain(PD_PCIE, pmu_pd_on);
1367*e3ec6ff4SXiaoDong Huang 	pmu_set_power_domain(PD_GMAC, pmu_pd_on);
1368*e3ec6ff4SXiaoDong Huang 	pmu_set_power_domain(PD_SECURE, pmu_pd_on);
1369*e3ec6ff4SXiaoDong Huang 	pmu_set_power_domain(PD_VOP, pmu_pd_on);
1370*e3ec6ff4SXiaoDong Huang 	pmu_set_power_domain(PD_VO0, pmu_pd_on);
1371*e3ec6ff4SXiaoDong Huang 	pmu_set_power_domain(PD_VO1, pmu_pd_on);
1372*e3ec6ff4SXiaoDong Huang }
1373*e3ec6ff4SXiaoDong Huang 
1374*e3ec6ff4SXiaoDong Huang #define PLL_LOCKED_TIMEOUT 600000U
1375*e3ec6ff4SXiaoDong Huang 
1376*e3ec6ff4SXiaoDong Huang void pm_pll_wait_lock(uint32_t pll_base)
1377*e3ec6ff4SXiaoDong Huang {
1378*e3ec6ff4SXiaoDong Huang 	int delay = PLL_LOCKED_TIMEOUT;
1379*e3ec6ff4SXiaoDong Huang 
1380*e3ec6ff4SXiaoDong Huang 	if ((mmio_read_32(pll_base + CRU_PLL_CON(1)) & CRU_PLLCON1_PWRDOWN) != 0)
1381*e3ec6ff4SXiaoDong Huang 		return;
1382*e3ec6ff4SXiaoDong Huang 
1383*e3ec6ff4SXiaoDong Huang 	while (delay-- >= 0) {
1384*e3ec6ff4SXiaoDong Huang 		if (mmio_read_32(pll_base + CRU_PLL_CON(6)) &
1385*e3ec6ff4SXiaoDong Huang 		    CRU_PLLCON6_LOCK_STATUS)
1386*e3ec6ff4SXiaoDong Huang 			break;
1387*e3ec6ff4SXiaoDong Huang 		udelay(1);
1388*e3ec6ff4SXiaoDong Huang 	}
1389*e3ec6ff4SXiaoDong Huang 
1390*e3ec6ff4SXiaoDong Huang 	if (delay <= 0)
1391*e3ec6ff4SXiaoDong Huang 		ERROR("Can't wait pll(0x%x) lock\n", pll_base);
1392*e3ec6ff4SXiaoDong Huang }
1393*e3ec6ff4SXiaoDong Huang 
1394*e3ec6ff4SXiaoDong Huang void rockchip_plat_mmu_el3(void)
1395*e3ec6ff4SXiaoDong Huang {
1396*e3ec6ff4SXiaoDong Huang 	/* Nothing todo */
1397*e3ec6ff4SXiaoDong Huang }
1398*e3ec6ff4SXiaoDong Huang 
1399*e3ec6ff4SXiaoDong Huang void plat_rockchip_pmu_init(void)
1400*e3ec6ff4SXiaoDong Huang {
1401*e3ec6ff4SXiaoDong Huang 	int cpu;
1402*e3ec6ff4SXiaoDong Huang 
1403*e3ec6ff4SXiaoDong Huang 	for (cpu = 0; cpu < PLATFORM_CORE_COUNT; cpu++)
1404*e3ec6ff4SXiaoDong Huang 		cpuson_flags[cpu] = 0;
1405*e3ec6ff4SXiaoDong Huang 
1406*e3ec6ff4SXiaoDong Huang 	psram_sleep_cfg->sp = PSRAM_SP_TOP;
1407*e3ec6ff4SXiaoDong Huang 	psram_sleep_cfg->ddr_func = (uint64_t)ddr_resume;
1408*e3ec6ff4SXiaoDong Huang 	psram_sleep_cfg->ddr_data = 0;
1409*e3ec6ff4SXiaoDong Huang 	psram_sleep_cfg->ddr_flag = 0;
1410*e3ec6ff4SXiaoDong Huang 	psram_sleep_cfg->boot_mpidr = read_mpidr_el1() & 0xffff;
1411*e3ec6ff4SXiaoDong Huang 	psram_sleep_cfg->pm_flag = PM_WARM_BOOT_BIT;
1412*e3ec6ff4SXiaoDong Huang 
1413*e3ec6ff4SXiaoDong Huang 	nonboot_cpus_off();
1414*e3ec6ff4SXiaoDong Huang 
1415*e3ec6ff4SXiaoDong Huang 	/*
1416*e3ec6ff4SXiaoDong Huang 	 * When perform idle operation, corresponding clock can be
1417*e3ec6ff4SXiaoDong Huang 	 * opened or gated automatically.
1418*e3ec6ff4SXiaoDong Huang 	 */
1419*e3ec6ff4SXiaoDong Huang 	mmio_write_32(PMU_BASE + PMU2_BIU_AUTO_CON(0), 0xffffffff);
1420*e3ec6ff4SXiaoDong Huang 	mmio_write_32(PMU_BASE + PMU2_BIU_AUTO_CON(1), 0xffffffff);
1421*e3ec6ff4SXiaoDong Huang 	mmio_write_32(PMU_BASE + PMU2_BIU_AUTO_CON(2), 0x00070007);
1422*e3ec6ff4SXiaoDong Huang 
1423*e3ec6ff4SXiaoDong Huang 	rockchip_pmu_pd_init();
1424*e3ec6ff4SXiaoDong Huang 
1425*e3ec6ff4SXiaoDong Huang 	/* grf_con_pmic_sleep_sel
1426*e3ec6ff4SXiaoDong Huang 	 * pmic sleep function selection
1427*e3ec6ff4SXiaoDong Huang 	 * 1'b0: From reset pulse generator, can reset external PMIC
1428*e3ec6ff4SXiaoDong Huang 	 * 1'b1: From pmu block, only support sleep function for external PMIC
1429*e3ec6ff4SXiaoDong Huang 	 */
1430*e3ec6ff4SXiaoDong Huang 	mmio_write_32(PMU0GRF_BASE + PMU0_GRF_SOC_CON(3), 0x03ff0000);
1431*e3ec6ff4SXiaoDong Huang 
1432*e3ec6ff4SXiaoDong Huang 	/* pmusram remap to 0xffff0000 */
1433*e3ec6ff4SXiaoDong Huang 	mmio_write_32(PMU0SGRF_BASE + PMU0_SGRF_SOC_CON(2), 0x00030001);
1434*e3ec6ff4SXiaoDong Huang 
1435*e3ec6ff4SXiaoDong Huang 	pm_reg_rgns_init();
1436*e3ec6ff4SXiaoDong Huang }
1437