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