xref: /arm-trusted-firmware/plat/rockchip/px30/drivers/pmu/pmu.c (revision 91f16700b400a8c0651d24a598fc48ee2997a0d7)
1*91f16700Schasinglulu /*
2*91f16700Schasinglulu  * Copyright (c) 2019, ARM Limited and Contributors. All rights reserved.
3*91f16700Schasinglulu  *
4*91f16700Schasinglulu  * SPDX-License-Identifier: BSD-3-Clause
5*91f16700Schasinglulu  */
6*91f16700Schasinglulu 
7*91f16700Schasinglulu #include <assert.h>
8*91f16700Schasinglulu #include <errno.h>
9*91f16700Schasinglulu 
10*91f16700Schasinglulu #include <platform_def.h>
11*91f16700Schasinglulu 
12*91f16700Schasinglulu #include <arch_helpers.h>
13*91f16700Schasinglulu #include <bl31/bl31.h>
14*91f16700Schasinglulu #include <common/debug.h>
15*91f16700Schasinglulu #include <drivers/console.h>
16*91f16700Schasinglulu #include <drivers/delay_timer.h>
17*91f16700Schasinglulu #include <lib/bakery_lock.h>
18*91f16700Schasinglulu #include <lib/mmio.h>
19*91f16700Schasinglulu #include <plat/common/platform.h>
20*91f16700Schasinglulu 
21*91f16700Schasinglulu #include <cpus_on_fixed_addr.h>
22*91f16700Schasinglulu #include <plat_private.h>
23*91f16700Schasinglulu #include <pmu.h>
24*91f16700Schasinglulu #include <px30_def.h>
25*91f16700Schasinglulu #include <secure.h>
26*91f16700Schasinglulu #include <soc.h>
27*91f16700Schasinglulu 
28*91f16700Schasinglulu DEFINE_BAKERY_LOCK(rockchip_pd_lock);
29*91f16700Schasinglulu #define rockchip_pd_lock_init()	bakery_lock_init(&rockchip_pd_lock)
30*91f16700Schasinglulu #define rockchip_pd_lock_get()	bakery_lock_get(&rockchip_pd_lock)
31*91f16700Schasinglulu #define rockchip_pd_lock_rls()	bakery_lock_release(&rockchip_pd_lock)
32*91f16700Schasinglulu 
33*91f16700Schasinglulu static struct psram_data_t *psram_boot_cfg =
34*91f16700Schasinglulu 	(struct psram_data_t *)&sys_sleep_flag_sram;
35*91f16700Schasinglulu 
36*91f16700Schasinglulu /*
37*91f16700Schasinglulu  * There are two ways to powering on or off on core.
38*91f16700Schasinglulu  * 1) Control it power domain into on or off in PMU_PWRDN_CON reg,
39*91f16700Schasinglulu  *    it is core_pwr_pd mode
40*91f16700Schasinglulu  * 2) Enable the core power manage in PMU_CORE_PM_CON reg,
41*91f16700Schasinglulu  *     then, if the core enter into wfi, it power domain will be
42*91f16700Schasinglulu  *     powered off automatically. it is core_pwr_wfi or core_pwr_wfi_int mode
43*91f16700Schasinglulu  * so we need core_pm_cfg_info to distinguish which method be used now.
44*91f16700Schasinglulu  */
45*91f16700Schasinglulu 
46*91f16700Schasinglulu static uint32_t cores_pd_cfg_info[PLATFORM_CORE_COUNT]
47*91f16700Schasinglulu #if USE_COHERENT_MEM
48*91f16700Schasinglulu __attribute__ ((section(".tzfw_coherent_mem")))
49*91f16700Schasinglulu #endif
50*91f16700Schasinglulu ;
51*91f16700Schasinglulu 
52*91f16700Schasinglulu struct px30_sleep_ddr_data {
53*91f16700Schasinglulu 	uint32_t clk_sel0;
54*91f16700Schasinglulu 	uint32_t cru_mode_save;
55*91f16700Schasinglulu 	uint32_t cru_pmu_mode_save;
56*91f16700Schasinglulu 	uint32_t ddrc_hwlpctl;
57*91f16700Schasinglulu 	uint32_t ddrc_pwrctrl;
58*91f16700Schasinglulu 	uint32_t ddrgrf_con0;
59*91f16700Schasinglulu 	uint32_t ddrgrf_con1;
60*91f16700Schasinglulu 	uint32_t ddrstdby_con0;
61*91f16700Schasinglulu 	uint32_t gpio0b_iomux;
62*91f16700Schasinglulu 	uint32_t gpio0c_iomux;
63*91f16700Schasinglulu 	uint32_t pmu_pwrmd_core_l;
64*91f16700Schasinglulu 	uint32_t pmu_pwrmd_core_h;
65*91f16700Schasinglulu 	uint32_t pmu_pwrmd_cmm_l;
66*91f16700Schasinglulu 	uint32_t pmu_pwrmd_cmm_h;
67*91f16700Schasinglulu 	uint32_t pmu_wkup_cfg2_l;
68*91f16700Schasinglulu 	uint32_t pmu_cru_clksel_con0;
69*91f16700Schasinglulu 	uint32_t pmugrf_soc_con0;
70*91f16700Schasinglulu 	uint32_t pmusgrf_soc_con0;
71*91f16700Schasinglulu 	uint32_t pmic_slp_iomux;
72*91f16700Schasinglulu 	uint32_t pgrf_pvtm_con[2];
73*91f16700Schasinglulu 	uint32_t cru_clk_gate[CRU_CLKGATES_CON_CNT];
74*91f16700Schasinglulu 	uint32_t cru_pmu_clk_gate[CRU_PMU_CLKGATE_CON_CNT];
75*91f16700Schasinglulu 	uint32_t cru_plls_con_save[END_PLL_ID][PLL_CON_CNT];
76*91f16700Schasinglulu 	uint32_t cpu_qos[CPU_AXI_QOS_NUM_REGS];
77*91f16700Schasinglulu 	uint32_t gpu_qos[CPU_AXI_QOS_NUM_REGS];
78*91f16700Schasinglulu 	uint32_t isp_128m_qos[CPU_AXI_QOS_NUM_REGS];
79*91f16700Schasinglulu 	uint32_t isp_rd_qos[CPU_AXI_QOS_NUM_REGS];
80*91f16700Schasinglulu 	uint32_t isp_wr_qos[CPU_AXI_QOS_NUM_REGS];
81*91f16700Schasinglulu 	uint32_t isp_m1_qos[CPU_AXI_QOS_NUM_REGS];
82*91f16700Schasinglulu 	uint32_t vip_qos[CPU_AXI_QOS_NUM_REGS];
83*91f16700Schasinglulu 	uint32_t rga_rd_qos[CPU_AXI_QOS_NUM_REGS];
84*91f16700Schasinglulu 	uint32_t rga_wr_qos[CPU_AXI_QOS_NUM_REGS];
85*91f16700Schasinglulu 	uint32_t vop_m0_qos[CPU_AXI_QOS_NUM_REGS];
86*91f16700Schasinglulu 	uint32_t vop_m1_qos[CPU_AXI_QOS_NUM_REGS];
87*91f16700Schasinglulu 	uint32_t vpu_qos[CPU_AXI_QOS_NUM_REGS];
88*91f16700Schasinglulu 	uint32_t vpu_r128_qos[CPU_AXI_QOS_NUM_REGS];
89*91f16700Schasinglulu 	uint32_t dcf_qos[CPU_AXI_QOS_NUM_REGS];
90*91f16700Schasinglulu 	uint32_t dmac_qos[CPU_AXI_QOS_NUM_REGS];
91*91f16700Schasinglulu 	uint32_t crypto_qos[CPU_AXI_QOS_NUM_REGS];
92*91f16700Schasinglulu 	uint32_t gmac_qos[CPU_AXI_QOS_NUM_REGS];
93*91f16700Schasinglulu 	uint32_t emmc_qos[CPU_AXI_QOS_NUM_REGS];
94*91f16700Schasinglulu 	uint32_t nand_qos[CPU_AXI_QOS_NUM_REGS];
95*91f16700Schasinglulu 	uint32_t sdio_qos[CPU_AXI_QOS_NUM_REGS];
96*91f16700Schasinglulu 	uint32_t sfc_qos[CPU_AXI_QOS_NUM_REGS];
97*91f16700Schasinglulu 	uint32_t sdmmc_qos[CPU_AXI_QOS_NUM_REGS];
98*91f16700Schasinglulu 	uint32_t usb_host_qos[CPU_AXI_QOS_NUM_REGS];
99*91f16700Schasinglulu 	uint32_t usb_otg_qos[CPU_AXI_QOS_NUM_REGS];
100*91f16700Schasinglulu };
101*91f16700Schasinglulu 
102*91f16700Schasinglulu static struct px30_sleep_ddr_data ddr_data
103*91f16700Schasinglulu #if USE_COHERENT_MEM
104*91f16700Schasinglulu __attribute__ ((section(".tzfw_coherent_mem")))
105*91f16700Schasinglulu #endif
106*91f16700Schasinglulu ;
107*91f16700Schasinglulu 
108*91f16700Schasinglulu static inline uint32_t get_cpus_pwr_domain_cfg_info(uint32_t cpu_id)
109*91f16700Schasinglulu {
110*91f16700Schasinglulu 	assert(cpu_id < PLATFORM_CORE_COUNT);
111*91f16700Schasinglulu 	return cores_pd_cfg_info[cpu_id];
112*91f16700Schasinglulu }
113*91f16700Schasinglulu 
114*91f16700Schasinglulu static inline void set_cpus_pwr_domain_cfg_info(uint32_t cpu_id, uint32_t value)
115*91f16700Schasinglulu {
116*91f16700Schasinglulu 	assert(cpu_id < PLATFORM_CORE_COUNT);
117*91f16700Schasinglulu 	cores_pd_cfg_info[cpu_id] = value;
118*91f16700Schasinglulu #if !USE_COHERENT_MEM
119*91f16700Schasinglulu 	flush_dcache_range((uintptr_t)&cores_pd_cfg_info[cpu_id],
120*91f16700Schasinglulu 			   sizeof(uint32_t));
121*91f16700Schasinglulu #endif
122*91f16700Schasinglulu }
123*91f16700Schasinglulu 
124*91f16700Schasinglulu static inline uint32_t pmu_power_domain_st(uint32_t pd)
125*91f16700Schasinglulu {
126*91f16700Schasinglulu 	return mmio_read_32(PMU_BASE + PMU_PWRDN_ST) & BIT(pd) ?
127*91f16700Schasinglulu 	       pmu_pd_off :
128*91f16700Schasinglulu 	       pmu_pd_on;
129*91f16700Schasinglulu }
130*91f16700Schasinglulu 
131*91f16700Schasinglulu static int pmu_power_domain_ctr(uint32_t pd, uint32_t pd_state)
132*91f16700Schasinglulu {
133*91f16700Schasinglulu 	uint32_t loop = 0;
134*91f16700Schasinglulu 	int ret = 0;
135*91f16700Schasinglulu 
136*91f16700Schasinglulu 	rockchip_pd_lock_get();
137*91f16700Schasinglulu 
138*91f16700Schasinglulu 	mmio_write_32(PMU_BASE + PMU_PWRDN_CON,
139*91f16700Schasinglulu 		      BITS_WITH_WMASK(pd_state, 0x1, pd));
140*91f16700Schasinglulu 	dsb();
141*91f16700Schasinglulu 
142*91f16700Schasinglulu 	while ((pmu_power_domain_st(pd) != pd_state) && (loop < PD_CTR_LOOP)) {
143*91f16700Schasinglulu 		udelay(1);
144*91f16700Schasinglulu 		loop++;
145*91f16700Schasinglulu 	}
146*91f16700Schasinglulu 
147*91f16700Schasinglulu 	if (pmu_power_domain_st(pd) != pd_state) {
148*91f16700Schasinglulu 		WARN("%s: %d, %d, error!\n", __func__, pd, pd_state);
149*91f16700Schasinglulu 		ret = -EINVAL;
150*91f16700Schasinglulu 	}
151*91f16700Schasinglulu 
152*91f16700Schasinglulu 	rockchip_pd_lock_rls();
153*91f16700Schasinglulu 
154*91f16700Schasinglulu 	return ret;
155*91f16700Schasinglulu }
156*91f16700Schasinglulu 
157*91f16700Schasinglulu static inline uint32_t pmu_bus_idle_st(uint32_t bus)
158*91f16700Schasinglulu {
159*91f16700Schasinglulu 	return !!((mmio_read_32(PMU_BASE + PMU_BUS_IDLE_ST) & BIT(bus)) &&
160*91f16700Schasinglulu 		  (mmio_read_32(PMU_BASE + PMU_BUS_IDLE_ST) & BIT(bus + 16)));
161*91f16700Schasinglulu }
162*91f16700Schasinglulu 
163*91f16700Schasinglulu static void pmu_bus_idle_req(uint32_t bus, uint32_t state)
164*91f16700Schasinglulu {
165*91f16700Schasinglulu 	uint32_t wait_cnt = 0;
166*91f16700Schasinglulu 
167*91f16700Schasinglulu 	mmio_write_32(PMU_BASE + PMU_BUS_IDLE_REQ,
168*91f16700Schasinglulu 		      BITS_WITH_WMASK(state, 0x1, bus));
169*91f16700Schasinglulu 
170*91f16700Schasinglulu 	while (pmu_bus_idle_st(bus) != state &&
171*91f16700Schasinglulu 	       wait_cnt < BUS_IDLE_LOOP) {
172*91f16700Schasinglulu 		udelay(1);
173*91f16700Schasinglulu 		wait_cnt++;
174*91f16700Schasinglulu 	}
175*91f16700Schasinglulu 
176*91f16700Schasinglulu 	if (pmu_bus_idle_st(bus) != state)
177*91f16700Schasinglulu 		WARN("%s:idle_st=0x%x, bus_id=%d\n",
178*91f16700Schasinglulu 		     __func__, mmio_read_32(PMU_BASE + PMU_BUS_IDLE_ST), bus);
179*91f16700Schasinglulu }
180*91f16700Schasinglulu 
181*91f16700Schasinglulu static void qos_save(void)
182*91f16700Schasinglulu {
183*91f16700Schasinglulu 	/* scu powerdomain will power off, so cpu qos should be saved */
184*91f16700Schasinglulu 	SAVE_QOS(ddr_data.cpu_qos, CPU);
185*91f16700Schasinglulu 
186*91f16700Schasinglulu 	if (pmu_power_domain_st(PD_GPU) == pmu_pd_on)
187*91f16700Schasinglulu 		SAVE_QOS(ddr_data.gpu_qos, GPU);
188*91f16700Schasinglulu 	if (pmu_power_domain_st(PD_VI) == pmu_pd_on) {
189*91f16700Schasinglulu 		SAVE_QOS(ddr_data.isp_128m_qos, ISP_128M);
190*91f16700Schasinglulu 		SAVE_QOS(ddr_data.isp_rd_qos, ISP_RD);
191*91f16700Schasinglulu 		SAVE_QOS(ddr_data.isp_wr_qos, ISP_WR);
192*91f16700Schasinglulu 		SAVE_QOS(ddr_data.isp_m1_qos, ISP_M1);
193*91f16700Schasinglulu 		SAVE_QOS(ddr_data.vip_qos, VIP);
194*91f16700Schasinglulu 	}
195*91f16700Schasinglulu 	if (pmu_power_domain_st(PD_VO) == pmu_pd_on) {
196*91f16700Schasinglulu 		SAVE_QOS(ddr_data.rga_rd_qos, RGA_RD);
197*91f16700Schasinglulu 		SAVE_QOS(ddr_data.rga_wr_qos, RGA_WR);
198*91f16700Schasinglulu 		SAVE_QOS(ddr_data.vop_m0_qos, VOP_M0);
199*91f16700Schasinglulu 		SAVE_QOS(ddr_data.vop_m1_qos, VOP_M1);
200*91f16700Schasinglulu 	}
201*91f16700Schasinglulu 	if (pmu_power_domain_st(PD_VPU) == pmu_pd_on) {
202*91f16700Schasinglulu 		SAVE_QOS(ddr_data.vpu_qos, VPU);
203*91f16700Schasinglulu 		SAVE_QOS(ddr_data.vpu_r128_qos, VPU_R128);
204*91f16700Schasinglulu 	}
205*91f16700Schasinglulu 	if (pmu_power_domain_st(PD_MMC_NAND) == pmu_pd_on) {
206*91f16700Schasinglulu 		SAVE_QOS(ddr_data.emmc_qos, EMMC);
207*91f16700Schasinglulu 		SAVE_QOS(ddr_data.nand_qos, NAND);
208*91f16700Schasinglulu 		SAVE_QOS(ddr_data.sdio_qos, SDIO);
209*91f16700Schasinglulu 		SAVE_QOS(ddr_data.sfc_qos, SFC);
210*91f16700Schasinglulu 	}
211*91f16700Schasinglulu 	if (pmu_power_domain_st(PD_GMAC) == pmu_pd_on)
212*91f16700Schasinglulu 		SAVE_QOS(ddr_data.gmac_qos, GMAC);
213*91f16700Schasinglulu 	if (pmu_power_domain_st(PD_CRYPTO) == pmu_pd_on)
214*91f16700Schasinglulu 		SAVE_QOS(ddr_data.crypto_qos, CRYPTO);
215*91f16700Schasinglulu 	if (pmu_power_domain_st(PD_SDCARD) == pmu_pd_on)
216*91f16700Schasinglulu 		SAVE_QOS(ddr_data.sdmmc_qos, SDMMC);
217*91f16700Schasinglulu 	if (pmu_power_domain_st(PD_USB) == pmu_pd_on) {
218*91f16700Schasinglulu 		SAVE_QOS(ddr_data.usb_host_qos, USB_HOST);
219*91f16700Schasinglulu 		SAVE_QOS(ddr_data.usb_otg_qos, USB_OTG);
220*91f16700Schasinglulu 	}
221*91f16700Schasinglulu }
222*91f16700Schasinglulu 
223*91f16700Schasinglulu static void qos_restore(void)
224*91f16700Schasinglulu {
225*91f16700Schasinglulu 	RESTORE_QOS(ddr_data.cpu_qos, CPU);
226*91f16700Schasinglulu 
227*91f16700Schasinglulu 	if (pmu_power_domain_st(PD_GPU) == pmu_pd_on)
228*91f16700Schasinglulu 		RESTORE_QOS(ddr_data.gpu_qos, GPU);
229*91f16700Schasinglulu 	if (pmu_power_domain_st(PD_VI) == pmu_pd_on) {
230*91f16700Schasinglulu 		RESTORE_QOS(ddr_data.isp_128m_qos, ISP_128M);
231*91f16700Schasinglulu 		RESTORE_QOS(ddr_data.isp_rd_qos, ISP_RD);
232*91f16700Schasinglulu 		RESTORE_QOS(ddr_data.isp_wr_qos, ISP_WR);
233*91f16700Schasinglulu 		RESTORE_QOS(ddr_data.isp_m1_qos, ISP_M1);
234*91f16700Schasinglulu 		RESTORE_QOS(ddr_data.vip_qos, VIP);
235*91f16700Schasinglulu 	}
236*91f16700Schasinglulu 	if (pmu_power_domain_st(PD_VO) == pmu_pd_on) {
237*91f16700Schasinglulu 		RESTORE_QOS(ddr_data.rga_rd_qos, RGA_RD);
238*91f16700Schasinglulu 		RESTORE_QOS(ddr_data.rga_wr_qos, RGA_WR);
239*91f16700Schasinglulu 		RESTORE_QOS(ddr_data.vop_m0_qos, VOP_M0);
240*91f16700Schasinglulu 		RESTORE_QOS(ddr_data.vop_m1_qos, VOP_M1);
241*91f16700Schasinglulu 	}
242*91f16700Schasinglulu 	if (pmu_power_domain_st(PD_VPU) == pmu_pd_on) {
243*91f16700Schasinglulu 		RESTORE_QOS(ddr_data.vpu_qos, VPU);
244*91f16700Schasinglulu 		RESTORE_QOS(ddr_data.vpu_r128_qos, VPU_R128);
245*91f16700Schasinglulu 	}
246*91f16700Schasinglulu 	if (pmu_power_domain_st(PD_MMC_NAND) == pmu_pd_on) {
247*91f16700Schasinglulu 		RESTORE_QOS(ddr_data.emmc_qos, EMMC);
248*91f16700Schasinglulu 		RESTORE_QOS(ddr_data.nand_qos, NAND);
249*91f16700Schasinglulu 		RESTORE_QOS(ddr_data.sdio_qos, SDIO);
250*91f16700Schasinglulu 		RESTORE_QOS(ddr_data.sfc_qos, SFC);
251*91f16700Schasinglulu 	}
252*91f16700Schasinglulu 	if (pmu_power_domain_st(PD_GMAC) == pmu_pd_on)
253*91f16700Schasinglulu 		RESTORE_QOS(ddr_data.gmac_qos, GMAC);
254*91f16700Schasinglulu 	if (pmu_power_domain_st(PD_CRYPTO) == pmu_pd_on)
255*91f16700Schasinglulu 		RESTORE_QOS(ddr_data.crypto_qos, CRYPTO);
256*91f16700Schasinglulu 	if (pmu_power_domain_st(PD_SDCARD) == pmu_pd_on)
257*91f16700Schasinglulu 		RESTORE_QOS(ddr_data.sdmmc_qos, SDMMC);
258*91f16700Schasinglulu 	if (pmu_power_domain_st(PD_USB) == pmu_pd_on) {
259*91f16700Schasinglulu 		RESTORE_QOS(ddr_data.usb_host_qos, USB_HOST);
260*91f16700Schasinglulu 		RESTORE_QOS(ddr_data.usb_otg_qos, USB_OTG);
261*91f16700Schasinglulu 	}
262*91f16700Schasinglulu }
263*91f16700Schasinglulu 
264*91f16700Schasinglulu static int pmu_set_power_domain(uint32_t pd_id, uint32_t pd_state)
265*91f16700Schasinglulu {
266*91f16700Schasinglulu 	uint32_t state;
267*91f16700Schasinglulu 
268*91f16700Schasinglulu 	if (pmu_power_domain_st(pd_id) == pd_state)
269*91f16700Schasinglulu 		goto out;
270*91f16700Schasinglulu 
271*91f16700Schasinglulu 	if (pd_state == pmu_pd_on)
272*91f16700Schasinglulu 		pmu_power_domain_ctr(pd_id, pd_state);
273*91f16700Schasinglulu 
274*91f16700Schasinglulu 	state = (pd_state == pmu_pd_off) ? bus_idle : bus_active;
275*91f16700Schasinglulu 
276*91f16700Schasinglulu 	switch (pd_id) {
277*91f16700Schasinglulu 	case PD_GPU:
278*91f16700Schasinglulu 		pmu_bus_idle_req(BUS_ID_GPU, state);
279*91f16700Schasinglulu 		break;
280*91f16700Schasinglulu 	case PD_VI:
281*91f16700Schasinglulu 		pmu_bus_idle_req(BUS_ID_VI, state);
282*91f16700Schasinglulu 		break;
283*91f16700Schasinglulu 	case PD_VO:
284*91f16700Schasinglulu 		pmu_bus_idle_req(BUS_ID_VO, state);
285*91f16700Schasinglulu 		break;
286*91f16700Schasinglulu 	case PD_VPU:
287*91f16700Schasinglulu 		pmu_bus_idle_req(BUS_ID_VPU, state);
288*91f16700Schasinglulu 		break;
289*91f16700Schasinglulu 	case PD_MMC_NAND:
290*91f16700Schasinglulu 		pmu_bus_idle_req(BUS_ID_MMC, state);
291*91f16700Schasinglulu 		break;
292*91f16700Schasinglulu 	case PD_GMAC:
293*91f16700Schasinglulu 		pmu_bus_idle_req(BUS_ID_GMAC, state);
294*91f16700Schasinglulu 		break;
295*91f16700Schasinglulu 	case PD_CRYPTO:
296*91f16700Schasinglulu 		pmu_bus_idle_req(BUS_ID_CRYPTO, state);
297*91f16700Schasinglulu 		break;
298*91f16700Schasinglulu 	case PD_SDCARD:
299*91f16700Schasinglulu 		pmu_bus_idle_req(BUS_ID_SDCARD, state);
300*91f16700Schasinglulu 		break;
301*91f16700Schasinglulu 	case PD_USB:
302*91f16700Schasinglulu 		pmu_bus_idle_req(BUS_ID_USB, state);
303*91f16700Schasinglulu 		break;
304*91f16700Schasinglulu 	default:
305*91f16700Schasinglulu 		break;
306*91f16700Schasinglulu 	}
307*91f16700Schasinglulu 
308*91f16700Schasinglulu 	if (pd_state == pmu_pd_off)
309*91f16700Schasinglulu 		pmu_power_domain_ctr(pd_id, pd_state);
310*91f16700Schasinglulu 
311*91f16700Schasinglulu out:
312*91f16700Schasinglulu 	return 0;
313*91f16700Schasinglulu }
314*91f16700Schasinglulu 
315*91f16700Schasinglulu static uint32_t pmu_powerdomain_state;
316*91f16700Schasinglulu 
317*91f16700Schasinglulu static void pmu_power_domains_suspend(void)
318*91f16700Schasinglulu {
319*91f16700Schasinglulu 	uint32_t clkgt_save[CRU_CLKGATES_CON_CNT + CRU_PMU_CLKGATE_CON_CNT];
320*91f16700Schasinglulu 
321*91f16700Schasinglulu 	clk_gate_con_save(clkgt_save);
322*91f16700Schasinglulu 	clk_gate_con_disable();
323*91f16700Schasinglulu 	qos_save();
324*91f16700Schasinglulu 
325*91f16700Schasinglulu 	pmu_powerdomain_state = mmio_read_32(PMU_BASE + PMU_PWRDN_ST);
326*91f16700Schasinglulu 	pmu_set_power_domain(PD_GPU, pmu_pd_off);
327*91f16700Schasinglulu 	pmu_set_power_domain(PD_VI, pmu_pd_off);
328*91f16700Schasinglulu 	pmu_set_power_domain(PD_VO, pmu_pd_off);
329*91f16700Schasinglulu 	pmu_set_power_domain(PD_VPU, pmu_pd_off);
330*91f16700Schasinglulu 	pmu_set_power_domain(PD_MMC_NAND, pmu_pd_off);
331*91f16700Schasinglulu 	pmu_set_power_domain(PD_GMAC, pmu_pd_off);
332*91f16700Schasinglulu 	pmu_set_power_domain(PD_CRYPTO, pmu_pd_off);
333*91f16700Schasinglulu 	pmu_set_power_domain(PD_SDCARD, pmu_pd_off);
334*91f16700Schasinglulu 	pmu_set_power_domain(PD_USB, pmu_pd_off);
335*91f16700Schasinglulu 
336*91f16700Schasinglulu 	clk_gate_con_restore(clkgt_save);
337*91f16700Schasinglulu }
338*91f16700Schasinglulu 
339*91f16700Schasinglulu static void pmu_power_domains_resume(void)
340*91f16700Schasinglulu {
341*91f16700Schasinglulu 	uint32_t clkgt_save[CRU_CLKGATES_CON_CNT + CRU_PMU_CLKGATE_CON_CNT];
342*91f16700Schasinglulu 
343*91f16700Schasinglulu 	clk_gate_con_save(clkgt_save);
344*91f16700Schasinglulu 	clk_gate_con_disable();
345*91f16700Schasinglulu 
346*91f16700Schasinglulu 	if (!(pmu_powerdomain_state & BIT(PD_USB)))
347*91f16700Schasinglulu 		pmu_set_power_domain(PD_USB, pmu_pd_on);
348*91f16700Schasinglulu 	if (!(pmu_powerdomain_state & BIT(PD_SDCARD)))
349*91f16700Schasinglulu 		pmu_set_power_domain(PD_SDCARD, pmu_pd_on);
350*91f16700Schasinglulu 	if (!(pmu_powerdomain_state & BIT(PD_CRYPTO)))
351*91f16700Schasinglulu 		pmu_set_power_domain(PD_CRYPTO, pmu_pd_on);
352*91f16700Schasinglulu 	if (!(pmu_powerdomain_state & BIT(PD_GMAC)))
353*91f16700Schasinglulu 		pmu_set_power_domain(PD_GMAC, pmu_pd_on);
354*91f16700Schasinglulu 	if (!(pmu_powerdomain_state & BIT(PD_MMC_NAND)))
355*91f16700Schasinglulu 		pmu_set_power_domain(PD_MMC_NAND, pmu_pd_on);
356*91f16700Schasinglulu 	if (!(pmu_powerdomain_state & BIT(PD_VPU)))
357*91f16700Schasinglulu 		pmu_set_power_domain(PD_VPU, pmu_pd_on);
358*91f16700Schasinglulu 	if (!(pmu_powerdomain_state & BIT(PD_VO)))
359*91f16700Schasinglulu 		pmu_set_power_domain(PD_VO, pmu_pd_on);
360*91f16700Schasinglulu 	if (!(pmu_powerdomain_state & BIT(PD_VI)))
361*91f16700Schasinglulu 		pmu_set_power_domain(PD_VI, pmu_pd_on);
362*91f16700Schasinglulu 	if (!(pmu_powerdomain_state & BIT(PD_GPU)))
363*91f16700Schasinglulu 		pmu_set_power_domain(PD_GPU, pmu_pd_on);
364*91f16700Schasinglulu 
365*91f16700Schasinglulu 	qos_restore();
366*91f16700Schasinglulu 	clk_gate_con_restore(clkgt_save);
367*91f16700Schasinglulu }
368*91f16700Schasinglulu 
369*91f16700Schasinglulu static int check_cpu_wfie(uint32_t cpu)
370*91f16700Schasinglulu {
371*91f16700Schasinglulu 	uint32_t loop = 0, wfie_msk = CKECK_WFEI_MSK << cpu;
372*91f16700Schasinglulu 
373*91f16700Schasinglulu 	while (!(mmio_read_32(GRF_BASE + GRF_CPU_STATUS1) & wfie_msk) &&
374*91f16700Schasinglulu 	       (loop < WFEI_CHECK_LOOP)) {
375*91f16700Schasinglulu 		udelay(1);
376*91f16700Schasinglulu 		loop++;
377*91f16700Schasinglulu 	}
378*91f16700Schasinglulu 
379*91f16700Schasinglulu 	if ((mmio_read_32(GRF_BASE + GRF_CPU_STATUS1) & wfie_msk) == 0) {
380*91f16700Schasinglulu 		WARN("%s: %d, %d, error!\n", __func__, cpu, wfie_msk);
381*91f16700Schasinglulu 		return -EINVAL;
382*91f16700Schasinglulu 	}
383*91f16700Schasinglulu 
384*91f16700Schasinglulu 	return 0;
385*91f16700Schasinglulu }
386*91f16700Schasinglulu 
387*91f16700Schasinglulu static int cpus_power_domain_on(uint32_t cpu_id)
388*91f16700Schasinglulu {
389*91f16700Schasinglulu 	uint32_t cpu_pd, apm_value, cfg_info, loop = 0;
390*91f16700Schasinglulu 
391*91f16700Schasinglulu 	cpu_pd = PD_CPU0 + cpu_id;
392*91f16700Schasinglulu 	cfg_info = get_cpus_pwr_domain_cfg_info(cpu_id);
393*91f16700Schasinglulu 
394*91f16700Schasinglulu 	if (cfg_info == core_pwr_pd) {
395*91f16700Schasinglulu 		/* disable apm cfg */
396*91f16700Schasinglulu 		mmio_write_32(PMU_BASE + PMU_CPUAPM_CON(cpu_id),
397*91f16700Schasinglulu 			      WITH_16BITS_WMSK(CORES_PM_DISABLE));
398*91f16700Schasinglulu 		if (pmu_power_domain_st(cpu_pd) == pmu_pd_on) {
399*91f16700Schasinglulu 			mmio_write_32(PMU_BASE + PMU_CPUAPM_CON(cpu_id),
400*91f16700Schasinglulu 				      WITH_16BITS_WMSK(CORES_PM_DISABLE));
401*91f16700Schasinglulu 			pmu_power_domain_ctr(cpu_pd, pmu_pd_off);
402*91f16700Schasinglulu 		}
403*91f16700Schasinglulu 		pmu_power_domain_ctr(cpu_pd, pmu_pd_on);
404*91f16700Schasinglulu 	} else {
405*91f16700Schasinglulu 		/* wait cpu down */
406*91f16700Schasinglulu 		while (pmu_power_domain_st(cpu_pd) == pmu_pd_on && loop < 100) {
407*91f16700Schasinglulu 			udelay(2);
408*91f16700Schasinglulu 			loop++;
409*91f16700Schasinglulu 		}
410*91f16700Schasinglulu 
411*91f16700Schasinglulu 		/* return error if can't wait cpu down */
412*91f16700Schasinglulu 		if (pmu_power_domain_st(cpu_pd) == pmu_pd_on) {
413*91f16700Schasinglulu 			WARN("%s:can't wait cpu down\n", __func__);
414*91f16700Schasinglulu 			return -EINVAL;
415*91f16700Schasinglulu 		}
416*91f16700Schasinglulu 
417*91f16700Schasinglulu 		/* power up cpu in power down state */
418*91f16700Schasinglulu 		apm_value = BIT(core_pm_sft_wakeup_en);
419*91f16700Schasinglulu 		mmio_write_32(PMU_BASE + PMU_CPUAPM_CON(cpu_id),
420*91f16700Schasinglulu 			      WITH_16BITS_WMSK(apm_value));
421*91f16700Schasinglulu 	}
422*91f16700Schasinglulu 
423*91f16700Schasinglulu 	return 0;
424*91f16700Schasinglulu }
425*91f16700Schasinglulu 
426*91f16700Schasinglulu static int cpus_power_domain_off(uint32_t cpu_id, uint32_t pd_cfg)
427*91f16700Schasinglulu {
428*91f16700Schasinglulu 	uint32_t cpu_pd, apm_value;
429*91f16700Schasinglulu 
430*91f16700Schasinglulu 	cpu_pd = PD_CPU0 + cpu_id;
431*91f16700Schasinglulu 	if (pmu_power_domain_st(cpu_pd) == pmu_pd_off)
432*91f16700Schasinglulu 		return 0;
433*91f16700Schasinglulu 
434*91f16700Schasinglulu 	if (pd_cfg == core_pwr_pd) {
435*91f16700Schasinglulu 		if (check_cpu_wfie(cpu_id))
436*91f16700Schasinglulu 			return -EINVAL;
437*91f16700Schasinglulu 		/* disable apm cfg */
438*91f16700Schasinglulu 		mmio_write_32(PMU_BASE + PMU_CPUAPM_CON(cpu_id),
439*91f16700Schasinglulu 			      WITH_16BITS_WMSK(CORES_PM_DISABLE));
440*91f16700Schasinglulu 		set_cpus_pwr_domain_cfg_info(cpu_id, pd_cfg);
441*91f16700Schasinglulu 		pmu_power_domain_ctr(cpu_pd, pmu_pd_off);
442*91f16700Schasinglulu 	} else {
443*91f16700Schasinglulu 		set_cpus_pwr_domain_cfg_info(cpu_id, pd_cfg);
444*91f16700Schasinglulu 		apm_value = BIT(core_pm_en) | BIT(core_pm_dis_int);
445*91f16700Schasinglulu 		if (pd_cfg == core_pwr_wfi_int)
446*91f16700Schasinglulu 			apm_value |= BIT(core_pm_int_wakeup_en);
447*91f16700Schasinglulu 		mmio_write_32(PMU_BASE + PMU_CPUAPM_CON(cpu_id),
448*91f16700Schasinglulu 			      WITH_16BITS_WMSK(apm_value));
449*91f16700Schasinglulu 	}
450*91f16700Schasinglulu 
451*91f16700Schasinglulu 	return 0;
452*91f16700Schasinglulu }
453*91f16700Schasinglulu 
454*91f16700Schasinglulu static void nonboot_cpus_off(void)
455*91f16700Schasinglulu {
456*91f16700Schasinglulu 	uint32_t boot_cpu, cpu;
457*91f16700Schasinglulu 
458*91f16700Schasinglulu 	boot_cpu = plat_my_core_pos();
459*91f16700Schasinglulu 
460*91f16700Schasinglulu 	for (cpu = 0; cpu < PLATFORM_CORE_COUNT; cpu++) {
461*91f16700Schasinglulu 		if (cpu == boot_cpu)
462*91f16700Schasinglulu 			continue;
463*91f16700Schasinglulu 		cpus_power_domain_off(cpu, core_pwr_pd);
464*91f16700Schasinglulu 	}
465*91f16700Schasinglulu }
466*91f16700Schasinglulu 
467*91f16700Schasinglulu int rockchip_soc_cores_pwr_dm_on(unsigned long mpidr,
468*91f16700Schasinglulu 				 uint64_t entrypoint)
469*91f16700Schasinglulu {
470*91f16700Schasinglulu 	uint32_t cpu_id = plat_core_pos_by_mpidr(mpidr);
471*91f16700Schasinglulu 
472*91f16700Schasinglulu 	assert(cpu_id < PLATFORM_CORE_COUNT);
473*91f16700Schasinglulu 	assert(cpuson_flags[cpu_id] == 0);
474*91f16700Schasinglulu 	cpuson_flags[cpu_id] = PMU_CPU_HOTPLUG;
475*91f16700Schasinglulu 	cpuson_entry_point[cpu_id] = entrypoint;
476*91f16700Schasinglulu 	dsb();
477*91f16700Schasinglulu 
478*91f16700Schasinglulu 	cpus_power_domain_on(cpu_id);
479*91f16700Schasinglulu 
480*91f16700Schasinglulu 	return PSCI_E_SUCCESS;
481*91f16700Schasinglulu }
482*91f16700Schasinglulu 
483*91f16700Schasinglulu int rockchip_soc_cores_pwr_dm_on_finish(void)
484*91f16700Schasinglulu {
485*91f16700Schasinglulu 	uint32_t cpu_id = plat_my_core_pos();
486*91f16700Schasinglulu 
487*91f16700Schasinglulu 	mmio_write_32(PMU_BASE + PMU_CPUAPM_CON(cpu_id),
488*91f16700Schasinglulu 		      WITH_16BITS_WMSK(CORES_PM_DISABLE));
489*91f16700Schasinglulu 	return PSCI_E_SUCCESS;
490*91f16700Schasinglulu }
491*91f16700Schasinglulu 
492*91f16700Schasinglulu int rockchip_soc_cores_pwr_dm_off(void)
493*91f16700Schasinglulu {
494*91f16700Schasinglulu 	uint32_t cpu_id = plat_my_core_pos();
495*91f16700Schasinglulu 
496*91f16700Schasinglulu 	cpus_power_domain_off(cpu_id, core_pwr_wfi);
497*91f16700Schasinglulu 
498*91f16700Schasinglulu 	return PSCI_E_SUCCESS;
499*91f16700Schasinglulu }
500*91f16700Schasinglulu 
501*91f16700Schasinglulu int rockchip_soc_cores_pwr_dm_suspend(void)
502*91f16700Schasinglulu {
503*91f16700Schasinglulu 	uint32_t cpu_id = plat_my_core_pos();
504*91f16700Schasinglulu 
505*91f16700Schasinglulu 	assert(cpu_id < PLATFORM_CORE_COUNT);
506*91f16700Schasinglulu 	assert(cpuson_flags[cpu_id] == 0);
507*91f16700Schasinglulu 	cpuson_flags[cpu_id] = PMU_CPU_AUTO_PWRDN;
508*91f16700Schasinglulu 	cpuson_entry_point[cpu_id] = plat_get_sec_entrypoint();
509*91f16700Schasinglulu 	dsb();
510*91f16700Schasinglulu 
511*91f16700Schasinglulu 	cpus_power_domain_off(cpu_id, core_pwr_wfi_int);
512*91f16700Schasinglulu 
513*91f16700Schasinglulu 	return PSCI_E_SUCCESS;
514*91f16700Schasinglulu }
515*91f16700Schasinglulu 
516*91f16700Schasinglulu int rockchip_soc_cores_pwr_dm_resume(void)
517*91f16700Schasinglulu {
518*91f16700Schasinglulu 	uint32_t cpu_id = plat_my_core_pos();
519*91f16700Schasinglulu 
520*91f16700Schasinglulu 	/* Disable core_pm */
521*91f16700Schasinglulu 	mmio_write_32(PMU_BASE + PMU_CPUAPM_CON(cpu_id),
522*91f16700Schasinglulu 		      WITH_16BITS_WMSK(CORES_PM_DISABLE));
523*91f16700Schasinglulu 
524*91f16700Schasinglulu 	return PSCI_E_SUCCESS;
525*91f16700Schasinglulu }
526*91f16700Schasinglulu 
527*91f16700Schasinglulu #define CLK_MSK_GATING(msk, con) \
528*91f16700Schasinglulu 	mmio_write_32(CRU_BASE + (con), ((msk) << 16) | 0xffff)
529*91f16700Schasinglulu #define CLK_MSK_UNGATING(msk, con) \
530*91f16700Schasinglulu 	mmio_write_32(CRU_BASE + (con), ((~(msk)) << 16) | 0xffff)
531*91f16700Schasinglulu 
532*91f16700Schasinglulu static uint32_t clk_ungt_msk[CRU_CLKGATES_CON_CNT] = {
533*91f16700Schasinglulu 	0xe0ff, 0xffff, 0x0000, 0x0000,
534*91f16700Schasinglulu 	0x0000, 0x0380, 0x0000, 0x0000,
535*91f16700Schasinglulu 	0x07c0, 0x0000, 0x0000, 0x000f,
536*91f16700Schasinglulu 	0x0061, 0x1f02, 0x0440, 0x1801,
537*91f16700Schasinglulu 	0x004b, 0x0000
538*91f16700Schasinglulu };
539*91f16700Schasinglulu 
540*91f16700Schasinglulu static uint32_t clk_pmu_ungt_msk[CRU_PMU_CLKGATE_CON_CNT] = {
541*91f16700Schasinglulu 	0xf1ff, 0x0310
542*91f16700Schasinglulu };
543*91f16700Schasinglulu 
544*91f16700Schasinglulu void clk_gate_suspend(void)
545*91f16700Schasinglulu {
546*91f16700Schasinglulu 	int i;
547*91f16700Schasinglulu 
548*91f16700Schasinglulu 	for (i = 0; i < CRU_CLKGATES_CON_CNT; i++) {
549*91f16700Schasinglulu 		ddr_data.cru_clk_gate[i] =
550*91f16700Schasinglulu 			mmio_read_32(CRU_BASE + CRU_CLKGATES_CON(i));
551*91f16700Schasinglulu 			mmio_write_32(CRU_BASE + CRU_CLKGATES_CON(i),
552*91f16700Schasinglulu 				      WITH_16BITS_WMSK(~clk_ungt_msk[i]));
553*91f16700Schasinglulu 	}
554*91f16700Schasinglulu 
555*91f16700Schasinglulu 	for (i = 0; i < CRU_PMU_CLKGATE_CON_CNT; i++) {
556*91f16700Schasinglulu 		ddr_data.cru_pmu_clk_gate[i] =
557*91f16700Schasinglulu 			mmio_read_32(PMUCRU_BASE + CRU_PMU_CLKGATES_CON(i));
558*91f16700Schasinglulu 			mmio_write_32(PMUCRU_BASE + CRU_PMU_CLKGATES_CON(i),
559*91f16700Schasinglulu 				      WITH_16BITS_WMSK(~clk_pmu_ungt_msk[i]));
560*91f16700Schasinglulu 	}
561*91f16700Schasinglulu }
562*91f16700Schasinglulu 
563*91f16700Schasinglulu void clk_gate_resume(void)
564*91f16700Schasinglulu {
565*91f16700Schasinglulu 	int i;
566*91f16700Schasinglulu 
567*91f16700Schasinglulu 	for (i = 0; i < CRU_PMU_CLKGATE_CON_CNT; i++)
568*91f16700Schasinglulu 		mmio_write_32(PMUCRU_BASE + CRU_PMU_CLKGATES_CON(i),
569*91f16700Schasinglulu 			      WITH_16BITS_WMSK(ddr_data.cru_pmu_clk_gate[i]));
570*91f16700Schasinglulu 
571*91f16700Schasinglulu 	for (i = 0; i < CRU_CLKGATES_CON_CNT; i++)
572*91f16700Schasinglulu 		mmio_write_32(CRU_BASE + CRU_CLKGATES_CON(i),
573*91f16700Schasinglulu 			      WITH_16BITS_WMSK(ddr_data.cru_clk_gate[i]));
574*91f16700Schasinglulu }
575*91f16700Schasinglulu 
576*91f16700Schasinglulu static void pvtm_32k_config(void)
577*91f16700Schasinglulu {
578*91f16700Schasinglulu 	uint32_t  pvtm_freq_khz, pvtm_div;
579*91f16700Schasinglulu 
580*91f16700Schasinglulu 	ddr_data.pmu_cru_clksel_con0 =
581*91f16700Schasinglulu 		mmio_read_32(PMUCRU_BASE + CRU_PMU_CLKSELS_CON(0));
582*91f16700Schasinglulu 
583*91f16700Schasinglulu 	ddr_data.pgrf_pvtm_con[0] =
584*91f16700Schasinglulu 		mmio_read_32(PMUGRF_BASE + PMUGRF_PVTM_CON0);
585*91f16700Schasinglulu 	ddr_data.pgrf_pvtm_con[1] =
586*91f16700Schasinglulu 		mmio_read_32(PMUGRF_BASE + PMUGRF_PVTM_CON1);
587*91f16700Schasinglulu 
588*91f16700Schasinglulu 	mmio_write_32(PMUGRF_BASE + PMUGRF_PVTM_CON0,
589*91f16700Schasinglulu 		      BITS_WITH_WMASK(0, 0x3, pgrf_pvtm_st));
590*91f16700Schasinglulu 	dsb();
591*91f16700Schasinglulu 	mmio_write_32(PMUGRF_BASE + PMUGRF_PVTM_CON0,
592*91f16700Schasinglulu 		      BITS_WITH_WMASK(1, 0x1, pgrf_pvtm_en));
593*91f16700Schasinglulu 	dsb();
594*91f16700Schasinglulu 	mmio_write_32(PMUGRF_BASE + PMUGRF_PVTM_CON1, PVTM_CALC_CNT);
595*91f16700Schasinglulu 	dsb();
596*91f16700Schasinglulu 
597*91f16700Schasinglulu 	mmio_write_32(PMUGRF_BASE + PMUGRF_PVTM_CON0,
598*91f16700Schasinglulu 		      BITS_WITH_WMASK(1, 0x1, pgrf_pvtm_st));
599*91f16700Schasinglulu 
600*91f16700Schasinglulu 	/* pmugrf_pvtm_st0 will be clear after PVTM start,
601*91f16700Schasinglulu 	 * which will cost about 6 cycles of pvtm at least.
602*91f16700Schasinglulu 	 * So we wait 30 cycles of pvtm for security.
603*91f16700Schasinglulu 	 */
604*91f16700Schasinglulu 	while (mmio_read_32(PMUGRF_BASE + PMUGRF_PVTM_ST1) < 30)
605*91f16700Schasinglulu 		;
606*91f16700Schasinglulu 
607*91f16700Schasinglulu 	dsb();
608*91f16700Schasinglulu 	while (!(mmio_read_32(PMUGRF_BASE + PMUGRF_PVTM_ST0) & 0x1))
609*91f16700Schasinglulu 		;
610*91f16700Schasinglulu 
611*91f16700Schasinglulu 	pvtm_freq_khz =
612*91f16700Schasinglulu 		(mmio_read_32(PMUGRF_BASE + PMUGRF_PVTM_ST1) * 24000 +
613*91f16700Schasinglulu 		PVTM_CALC_CNT / 2) / PVTM_CALC_CNT;
614*91f16700Schasinglulu 	pvtm_div = (pvtm_freq_khz + 16) / 32;
615*91f16700Schasinglulu 
616*91f16700Schasinglulu 	/* pvtm_div = div_factor << 2 + 1,
617*91f16700Schasinglulu 	 * so div_factor = (pvtm_div - 1) >> 2.
618*91f16700Schasinglulu 	 * But the operation ">> 2" will clear the low bit of pvtm_div,
619*91f16700Schasinglulu 	 * so we don't have to do "- 1" for compasation
620*91f16700Schasinglulu 	 */
621*91f16700Schasinglulu 	pvtm_div = pvtm_div >> 2;
622*91f16700Schasinglulu 	if (pvtm_div > 0x3f)
623*91f16700Schasinglulu 		pvtm_div = 0x3f;
624*91f16700Schasinglulu 
625*91f16700Schasinglulu 	mmio_write_32(PMUGRF_BASE + PMUGRF_PVTM_CON0,
626*91f16700Schasinglulu 		      BITS_WITH_WMASK(pvtm_div, 0x3f, pgrf_pvtm_div));
627*91f16700Schasinglulu 
628*91f16700Schasinglulu 	/* select pvtm as 32k source */
629*91f16700Schasinglulu 	mmio_write_32(PMUCRU_BASE + CRU_PMU_CLKSELS_CON(0),
630*91f16700Schasinglulu 		      BITS_WITH_WMASK(1, 0x3U, 14));
631*91f16700Schasinglulu }
632*91f16700Schasinglulu 
633*91f16700Schasinglulu static void pvtm_32k_config_restore(void)
634*91f16700Schasinglulu {
635*91f16700Schasinglulu 	mmio_write_32(PMUCRU_BASE + CRU_PMU_CLKSELS_CON(0),
636*91f16700Schasinglulu 		      ddr_data.pmu_cru_clksel_con0 | BITS_WMSK(0x3U, 14));
637*91f16700Schasinglulu 
638*91f16700Schasinglulu 	mmio_write_32(PMUGRF_BASE + PMUGRF_PVTM_CON0,
639*91f16700Schasinglulu 		      WITH_16BITS_WMSK(ddr_data.pgrf_pvtm_con[0]));
640*91f16700Schasinglulu 	mmio_write_32(PMUGRF_BASE + PMUGRF_PVTM_CON1,
641*91f16700Schasinglulu 		      ddr_data.pgrf_pvtm_con[1]);
642*91f16700Schasinglulu }
643*91f16700Schasinglulu 
644*91f16700Schasinglulu static void ddr_sleep_config(void)
645*91f16700Schasinglulu {
646*91f16700Schasinglulu 	/* disable ddr pd, sr */
647*91f16700Schasinglulu 	ddr_data.ddrc_pwrctrl = mmio_read_32(DDR_UPCTL_BASE + 0x30);
648*91f16700Schasinglulu 	mmio_write_32(DDR_UPCTL_BASE + 0x30, BITS_WITH_WMASK(0x0, 0x3, 0));
649*91f16700Schasinglulu 
650*91f16700Schasinglulu 	/* disable ddr auto gt */
651*91f16700Schasinglulu 	ddr_data.ddrgrf_con1 = mmio_read_32(DDRGRF_BASE + 0x4);
652*91f16700Schasinglulu 	mmio_write_32(DDRGRF_BASE + 0x4, BITS_WITH_WMASK(0x0, 0x1f, 0));
653*91f16700Schasinglulu 
654*91f16700Schasinglulu 	/* disable ddr standby */
655*91f16700Schasinglulu 	ddr_data.ddrstdby_con0 = mmio_read_32(DDR_STDBY_BASE + 0x0);
656*91f16700Schasinglulu 	mmio_write_32(DDR_STDBY_BASE + 0x0, BITS_WITH_WMASK(0x0, 0x1, 0));
657*91f16700Schasinglulu 	while ((mmio_read_32(DDR_UPCTL_BASE + 0x4) & 0x7) != 1)
658*91f16700Schasinglulu 		;
659*91f16700Schasinglulu 
660*91f16700Schasinglulu 	/* ddr pmu ctrl */
661*91f16700Schasinglulu 	ddr_data.ddrgrf_con0 = mmio_read_32(DDRGRF_BASE + 0x0);
662*91f16700Schasinglulu 	mmio_write_32(DDRGRF_BASE + 0x0, BITS_WITH_WMASK(0x0, 0x1, 5));
663*91f16700Schasinglulu 	dsb();
664*91f16700Schasinglulu 	mmio_write_32(DDRGRF_BASE + 0x0, BITS_WITH_WMASK(0x1, 0x1, 4));
665*91f16700Schasinglulu 
666*91f16700Schasinglulu 	/* ddr ret sel */
667*91f16700Schasinglulu 	ddr_data.pmugrf_soc_con0 =
668*91f16700Schasinglulu 		mmio_read_32(PMUGRF_BASE + PMUGRF_SOC_CON(0));
669*91f16700Schasinglulu 	mmio_write_32(PMUGRF_BASE + PMUGRF_SOC_CON(0),
670*91f16700Schasinglulu 		      BITS_WITH_WMASK(0x0, 0x1, 12));
671*91f16700Schasinglulu }
672*91f16700Schasinglulu 
673*91f16700Schasinglulu static void ddr_sleep_config_restore(void)
674*91f16700Schasinglulu {
675*91f16700Schasinglulu 	/* restore ddr ret sel */
676*91f16700Schasinglulu 	mmio_write_32(PMUGRF_BASE + PMUGRF_SOC_CON(0),
677*91f16700Schasinglulu 		      ddr_data.pmugrf_soc_con0 | BITS_WMSK(0x1, 12));
678*91f16700Schasinglulu 
679*91f16700Schasinglulu 	/* restore ddr pmu ctrl */
680*91f16700Schasinglulu 	mmio_write_32(DDRGRF_BASE + 0x0,
681*91f16700Schasinglulu 		      ddr_data.ddrgrf_con0 | BITS_WMSK(0x1, 4));
682*91f16700Schasinglulu 	dsb();
683*91f16700Schasinglulu 	mmio_write_32(DDRGRF_BASE + 0x0,
684*91f16700Schasinglulu 		      ddr_data.ddrgrf_con0 | BITS_WMSK(0x1, 5));
685*91f16700Schasinglulu 
686*91f16700Schasinglulu 	/* restore ddr standby */
687*91f16700Schasinglulu 	mmio_write_32(DDR_STDBY_BASE + 0x0,
688*91f16700Schasinglulu 		      ddr_data.ddrstdby_con0 | BITS_WMSK(0x1, 0));
689*91f16700Schasinglulu 
690*91f16700Schasinglulu 	/* restore ddr auto gt */
691*91f16700Schasinglulu 	mmio_write_32(DDRGRF_BASE + 0x4,
692*91f16700Schasinglulu 		      ddr_data.ddrgrf_con1 | BITS_WMSK(0x1f, 0));
693*91f16700Schasinglulu 
694*91f16700Schasinglulu 	/* restore ddr pd, sr */
695*91f16700Schasinglulu 	mmio_write_32(DDR_UPCTL_BASE + 0x30,
696*91f16700Schasinglulu 		      ddr_data.ddrc_pwrctrl | BITS_WMSK(0x3, 0));
697*91f16700Schasinglulu }
698*91f16700Schasinglulu 
699*91f16700Schasinglulu static void pmu_sleep_config(void)
700*91f16700Schasinglulu {
701*91f16700Schasinglulu 	uint32_t pwrmd_core_lo, pwrmd_core_hi, pwrmd_com_lo, pwrmd_com_hi;
702*91f16700Schasinglulu 	uint32_t pmu_wkup_cfg2_lo;
703*91f16700Schasinglulu 	uint32_t clk_freq_khz;
704*91f16700Schasinglulu 
705*91f16700Schasinglulu 	/* save pmic_sleep iomux gpio0_a4 */
706*91f16700Schasinglulu 	ddr_data.pmic_slp_iomux = mmio_read_32(PMUGRF_BASE + GPIO0A_IOMUX);
707*91f16700Schasinglulu 
708*91f16700Schasinglulu 	ddr_data.pmu_pwrmd_core_l =
709*91f16700Schasinglulu 			mmio_read_32(PMU_BASE + PMU_PWRMODE_CORE_LO);
710*91f16700Schasinglulu 	ddr_data.pmu_pwrmd_core_h =
711*91f16700Schasinglulu 			mmio_read_32(PMU_BASE + PMU_PWRMODE_CORE_HI);
712*91f16700Schasinglulu 	ddr_data.pmu_pwrmd_cmm_l =
713*91f16700Schasinglulu 			mmio_read_32(PMU_BASE + PMU_PWRMODE_COMMON_CON_LO);
714*91f16700Schasinglulu 	ddr_data.pmu_pwrmd_cmm_h =
715*91f16700Schasinglulu 			mmio_read_32(PMU_BASE + PMU_PWRMODE_COMMON_CON_HI);
716*91f16700Schasinglulu 	ddr_data.pmu_wkup_cfg2_l = mmio_read_32(PMU_BASE + PMU_WKUP_CFG2_LO);
717*91f16700Schasinglulu 
718*91f16700Schasinglulu 	pwrmd_core_lo = BIT(pmu_global_int_dis) |
719*91f16700Schasinglulu 			BIT(pmu_core_src_gt) |
720*91f16700Schasinglulu 			BIT(pmu_cpu0_pd) |
721*91f16700Schasinglulu 			BIT(pmu_clr_core) |
722*91f16700Schasinglulu 			BIT(pmu_scu_pd) |
723*91f16700Schasinglulu 			BIT(pmu_l2_idle) |
724*91f16700Schasinglulu 			BIT(pmu_l2_flush) |
725*91f16700Schasinglulu 			BIT(pmu_clr_bus2main) |
726*91f16700Schasinglulu 			BIT(pmu_clr_peri2msch);
727*91f16700Schasinglulu 
728*91f16700Schasinglulu 	pwrmd_core_hi = BIT(pmu_dpll_pd_en) |
729*91f16700Schasinglulu 			BIT(pmu_apll_pd_en) |
730*91f16700Schasinglulu 			BIT(pmu_cpll_pd_en) |
731*91f16700Schasinglulu 			BIT(pmu_gpll_pd_en) |
732*91f16700Schasinglulu 			BIT(pmu_npll_pd_en);
733*91f16700Schasinglulu 
734*91f16700Schasinglulu 	pwrmd_com_lo = BIT(pmu_mode_en) |
735*91f16700Schasinglulu 		       BIT(pmu_pll_pd) |
736*91f16700Schasinglulu 		       BIT(pmu_pmu_use_if) |
737*91f16700Schasinglulu 		       BIT(pmu_alive_use_if) |
738*91f16700Schasinglulu 		       BIT(pmu_osc_dis) |
739*91f16700Schasinglulu 		       BIT(pmu_sref_enter) |
740*91f16700Schasinglulu 		       BIT(pmu_ddrc_gt) |
741*91f16700Schasinglulu 		       BIT(pmu_clr_pmu) |
742*91f16700Schasinglulu 		       BIT(pmu_clr_peri_pmu);
743*91f16700Schasinglulu 
744*91f16700Schasinglulu 	pwrmd_com_hi = BIT(pmu_clr_bus) |
745*91f16700Schasinglulu 		       BIT(pmu_clr_msch) |
746*91f16700Schasinglulu 		       BIT(pmu_wakeup_begin_cfg);
747*91f16700Schasinglulu 
748*91f16700Schasinglulu 	pmu_wkup_cfg2_lo = BIT(pmu_cluster_wkup_en) |
749*91f16700Schasinglulu 			   BIT(pmu_gpio_wkup_en) |
750*91f16700Schasinglulu 			   BIT(pmu_timer_wkup_en);
751*91f16700Schasinglulu 
752*91f16700Schasinglulu 	/* set pmic_sleep iomux gpio0_a4 */
753*91f16700Schasinglulu 	mmio_write_32(PMUGRF_BASE + GPIO0A_IOMUX,
754*91f16700Schasinglulu 		      BITS_WITH_WMASK(1, 0x3, 8));
755*91f16700Schasinglulu 
756*91f16700Schasinglulu 	clk_freq_khz = 32;
757*91f16700Schasinglulu 
758*91f16700Schasinglulu 	mmio_write_32(PMU_BASE + PMU_OSC_CNT_LO,
759*91f16700Schasinglulu 		      WITH_16BITS_WMSK(clk_freq_khz * 32 & 0xffff));
760*91f16700Schasinglulu 	mmio_write_32(PMU_BASE + PMU_OSC_CNT_HI,
761*91f16700Schasinglulu 		      WITH_16BITS_WMSK(clk_freq_khz * 32 >> 16));
762*91f16700Schasinglulu 
763*91f16700Schasinglulu 	mmio_write_32(PMU_BASE + PMU_STABLE_CNT_LO,
764*91f16700Schasinglulu 		      WITH_16BITS_WMSK(clk_freq_khz * 32 & 0xffff));
765*91f16700Schasinglulu 	mmio_write_32(PMU_BASE + PMU_STABLE_CNT_HI,
766*91f16700Schasinglulu 		      WITH_16BITS_WMSK(clk_freq_khz * 32 >> 16));
767*91f16700Schasinglulu 
768*91f16700Schasinglulu 	mmio_write_32(PMU_BASE + PMU_WAKEUP_RST_CLR_LO,
769*91f16700Schasinglulu 		      WITH_16BITS_WMSK(clk_freq_khz * 2 & 0xffff));
770*91f16700Schasinglulu 	mmio_write_32(PMU_BASE + PMU_WAKEUP_RST_CLR_HI,
771*91f16700Schasinglulu 		      WITH_16BITS_WMSK(clk_freq_khz * 2 >> 16));
772*91f16700Schasinglulu 
773*91f16700Schasinglulu 	/* Pmu's clk has switched to 24M back When pmu FSM counts
774*91f16700Schasinglulu 	 * the follow counters, so we should use 24M to calculate
775*91f16700Schasinglulu 	 * these counters.
776*91f16700Schasinglulu 	 */
777*91f16700Schasinglulu 	mmio_write_32(PMU_BASE + PMU_SCU_PWRDN_CNT_LO,
778*91f16700Schasinglulu 		      WITH_16BITS_WMSK(24000 * 2 & 0xffff));
779*91f16700Schasinglulu 	mmio_write_32(PMU_BASE + PMU_SCU_PWRDN_CNT_HI,
780*91f16700Schasinglulu 		      WITH_16BITS_WMSK(24000 * 2 >> 16));
781*91f16700Schasinglulu 
782*91f16700Schasinglulu 	mmio_write_32(PMU_BASE + PMU_SCU_PWRUP_CNT_LO,
783*91f16700Schasinglulu 		      WITH_16BITS_WMSK(24000 * 2 & 0xffff));
784*91f16700Schasinglulu 	mmio_write_32(PMU_BASE + PMU_SCU_PWRUP_CNT_HI,
785*91f16700Schasinglulu 		      WITH_16BITS_WMSK(24000 * 2 >> 16));
786*91f16700Schasinglulu 
787*91f16700Schasinglulu 	mmio_write_32(PMU_BASE + PMU_PLLLOCK_CNT_LO,
788*91f16700Schasinglulu 		      WITH_16BITS_WMSK(24000 * 5 & 0xffff));
789*91f16700Schasinglulu 	mmio_write_32(PMU_BASE + PMU_PLLLOCK_CNT_HI,
790*91f16700Schasinglulu 		      WITH_16BITS_WMSK(24000 * 5 >> 16));
791*91f16700Schasinglulu 
792*91f16700Schasinglulu 	mmio_write_32(PMU_BASE + PMU_PLLRST_CNT_LO,
793*91f16700Schasinglulu 		      WITH_16BITS_WMSK(24000 * 2 & 0xffff));
794*91f16700Schasinglulu 	mmio_write_32(PMU_BASE + PMU_PLLRST_CNT_HI,
795*91f16700Schasinglulu 		      WITH_16BITS_WMSK(24000 * 2 >> 16));
796*91f16700Schasinglulu 
797*91f16700Schasinglulu 	/* Config pmu power mode and pmu wakeup source */
798*91f16700Schasinglulu 	mmio_write_32(PMU_BASE + PMU_PWRMODE_CORE_LO,
799*91f16700Schasinglulu 		      WITH_16BITS_WMSK(pwrmd_core_lo));
800*91f16700Schasinglulu 	mmio_write_32(PMU_BASE + PMU_PWRMODE_CORE_HI,
801*91f16700Schasinglulu 		      WITH_16BITS_WMSK(pwrmd_core_hi));
802*91f16700Schasinglulu 
803*91f16700Schasinglulu 	mmio_write_32(PMU_BASE + PMU_PWRMODE_COMMON_CON_LO,
804*91f16700Schasinglulu 		      WITH_16BITS_WMSK(pwrmd_com_lo));
805*91f16700Schasinglulu 	mmio_write_32(PMU_BASE + PMU_PWRMODE_COMMON_CON_HI,
806*91f16700Schasinglulu 		      WITH_16BITS_WMSK(pwrmd_com_hi));
807*91f16700Schasinglulu 
808*91f16700Schasinglulu 	mmio_write_32(PMU_BASE + PMU_WKUP_CFG2_LO,
809*91f16700Schasinglulu 		      WITH_16BITS_WMSK(pmu_wkup_cfg2_lo));
810*91f16700Schasinglulu }
811*91f16700Schasinglulu 
812*91f16700Schasinglulu static void pmu_sleep_restore(void)
813*91f16700Schasinglulu {
814*91f16700Schasinglulu 	mmio_write_32(PMU_BASE + PMU_PWRMODE_CORE_LO,
815*91f16700Schasinglulu 		      WITH_16BITS_WMSK(ddr_data.pmu_pwrmd_core_l));
816*91f16700Schasinglulu 	mmio_write_32(PMU_BASE + PMU_PWRMODE_CORE_HI,
817*91f16700Schasinglulu 		      WITH_16BITS_WMSK(ddr_data.pmu_pwrmd_core_h));
818*91f16700Schasinglulu 	mmio_write_32(PMU_BASE + PMU_PWRMODE_COMMON_CON_LO,
819*91f16700Schasinglulu 		      WITH_16BITS_WMSK(ddr_data.pmu_pwrmd_cmm_l));
820*91f16700Schasinglulu 	mmio_write_32(PMU_BASE + PMU_PWRMODE_COMMON_CON_HI,
821*91f16700Schasinglulu 		      WITH_16BITS_WMSK(ddr_data.pmu_pwrmd_cmm_h));
822*91f16700Schasinglulu 	mmio_write_32(PMU_BASE + PMU_WKUP_CFG2_LO,
823*91f16700Schasinglulu 		      WITH_16BITS_WMSK(ddr_data.pmu_wkup_cfg2_l));
824*91f16700Schasinglulu 
825*91f16700Schasinglulu 	/* restore pmic_sleep iomux */
826*91f16700Schasinglulu 	mmio_write_32(PMUGRF_BASE + GPIO0A_IOMUX,
827*91f16700Schasinglulu 		      WITH_16BITS_WMSK(ddr_data.pmic_slp_iomux));
828*91f16700Schasinglulu }
829*91f16700Schasinglulu 
830*91f16700Schasinglulu static void soc_sleep_config(void)
831*91f16700Schasinglulu {
832*91f16700Schasinglulu 	ddr_data.gpio0c_iomux = mmio_read_32(PMUGRF_BASE + GPIO0C_IOMUX);
833*91f16700Schasinglulu 
834*91f16700Schasinglulu 	pmu_sleep_config();
835*91f16700Schasinglulu 
836*91f16700Schasinglulu 	ddr_sleep_config();
837*91f16700Schasinglulu 
838*91f16700Schasinglulu 	pvtm_32k_config();
839*91f16700Schasinglulu }
840*91f16700Schasinglulu 
841*91f16700Schasinglulu static void soc_sleep_restore(void)
842*91f16700Schasinglulu {
843*91f16700Schasinglulu 	secure_timer_init();
844*91f16700Schasinglulu 
845*91f16700Schasinglulu 	pvtm_32k_config_restore();
846*91f16700Schasinglulu 
847*91f16700Schasinglulu 	ddr_sleep_config_restore();
848*91f16700Schasinglulu 
849*91f16700Schasinglulu 	pmu_sleep_restore();
850*91f16700Schasinglulu 
851*91f16700Schasinglulu 	mmio_write_32(PMUGRF_BASE + GPIO0C_IOMUX,
852*91f16700Schasinglulu 		      WITH_16BITS_WMSK(ddr_data.gpio0c_iomux));
853*91f16700Schasinglulu }
854*91f16700Schasinglulu 
855*91f16700Schasinglulu static inline void pm_pll_wait_lock(uint32_t pll_base, uint32_t pll_id)
856*91f16700Schasinglulu {
857*91f16700Schasinglulu 	uint32_t delay = PLL_LOCKED_TIMEOUT;
858*91f16700Schasinglulu 
859*91f16700Schasinglulu 	while (delay > 0) {
860*91f16700Schasinglulu 		if (mmio_read_32(pll_base + PLL_CON(1)) &
861*91f16700Schasinglulu 		    PLL_LOCK_MSK)
862*91f16700Schasinglulu 			break;
863*91f16700Schasinglulu 		delay--;
864*91f16700Schasinglulu 	}
865*91f16700Schasinglulu 
866*91f16700Schasinglulu 	if (delay == 0)
867*91f16700Schasinglulu 		ERROR("Can't wait pll:%d lock\n", pll_id);
868*91f16700Schasinglulu }
869*91f16700Schasinglulu 
870*91f16700Schasinglulu static inline void pll_pwr_ctr(uint32_t pll_base, uint32_t pll_id, uint32_t pd)
871*91f16700Schasinglulu {
872*91f16700Schasinglulu 	mmio_write_32(pll_base + PLL_CON(1),
873*91f16700Schasinglulu 		      BITS_WITH_WMASK(1, 1U, 15));
874*91f16700Schasinglulu 	if (pd)
875*91f16700Schasinglulu 		mmio_write_32(pll_base + PLL_CON(1),
876*91f16700Schasinglulu 			      BITS_WITH_WMASK(1, 1, 14));
877*91f16700Schasinglulu 	else
878*91f16700Schasinglulu 		mmio_write_32(pll_base + PLL_CON(1),
879*91f16700Schasinglulu 			      BITS_WITH_WMASK(0, 1, 14));
880*91f16700Schasinglulu }
881*91f16700Schasinglulu 
882*91f16700Schasinglulu static inline void pll_set_mode(uint32_t pll_id, uint32_t mode)
883*91f16700Schasinglulu {
884*91f16700Schasinglulu 	uint32_t val = BITS_WITH_WMASK(mode, 0x3, PLL_MODE_SHIFT(pll_id));
885*91f16700Schasinglulu 
886*91f16700Schasinglulu 	if (pll_id != GPLL_ID)
887*91f16700Schasinglulu 		mmio_write_32(CRU_BASE + CRU_MODE, val);
888*91f16700Schasinglulu 	else
889*91f16700Schasinglulu 		mmio_write_32(PMUCRU_BASE + CRU_PMU_MODE,
890*91f16700Schasinglulu 			      BITS_WITH_WMASK(mode, 0x3, 0));
891*91f16700Schasinglulu }
892*91f16700Schasinglulu 
893*91f16700Schasinglulu static inline void pll_suspend(uint32_t pll_id)
894*91f16700Schasinglulu {
895*91f16700Schasinglulu 	int i;
896*91f16700Schasinglulu 	uint32_t pll_base;
897*91f16700Schasinglulu 
898*91f16700Schasinglulu 	if (pll_id != GPLL_ID)
899*91f16700Schasinglulu 		pll_base = CRU_BASE + CRU_PLL_CONS(pll_id, 0);
900*91f16700Schasinglulu 	else
901*91f16700Schasinglulu 		pll_base = PMUCRU_BASE + CRU_PLL_CONS(0, 0);
902*91f16700Schasinglulu 
903*91f16700Schasinglulu 	/* save pll con */
904*91f16700Schasinglulu 	for (i = 0; i < PLL_CON_CNT; i++)
905*91f16700Schasinglulu 		ddr_data.cru_plls_con_save[pll_id][i] =
906*91f16700Schasinglulu 				mmio_read_32(pll_base + PLL_CON(i));
907*91f16700Schasinglulu 
908*91f16700Schasinglulu 	/* slow mode */
909*91f16700Schasinglulu 	pll_set_mode(pll_id, SLOW_MODE);
910*91f16700Schasinglulu }
911*91f16700Schasinglulu 
912*91f16700Schasinglulu static inline void pll_resume(uint32_t pll_id)
913*91f16700Schasinglulu {
914*91f16700Schasinglulu 	uint32_t mode, pll_base;
915*91f16700Schasinglulu 
916*91f16700Schasinglulu 	if (pll_id != GPLL_ID) {
917*91f16700Schasinglulu 		pll_base = CRU_BASE + CRU_PLL_CONS(pll_id, 0);
918*91f16700Schasinglulu 		mode = (ddr_data.cru_mode_save >> PLL_MODE_SHIFT(pll_id)) & 0x3;
919*91f16700Schasinglulu 	} else {
920*91f16700Schasinglulu 		pll_base = PMUCRU_BASE + CRU_PLL_CONS(0, 0);
921*91f16700Schasinglulu 		mode = ddr_data.cru_pmu_mode_save & 0x3;
922*91f16700Schasinglulu 	}
923*91f16700Schasinglulu 
924*91f16700Schasinglulu 	/* if pll locked before suspend, we should wait atfer resume */
925*91f16700Schasinglulu 	if (ddr_data.cru_plls_con_save[pll_id][1] & PLL_LOCK_MSK)
926*91f16700Schasinglulu 		pm_pll_wait_lock(pll_base, pll_id);
927*91f16700Schasinglulu 
928*91f16700Schasinglulu 	pll_set_mode(pll_id, mode);
929*91f16700Schasinglulu }
930*91f16700Schasinglulu 
931*91f16700Schasinglulu static void pm_plls_suspend(void)
932*91f16700Schasinglulu {
933*91f16700Schasinglulu 	ddr_data.cru_mode_save = mmio_read_32(CRU_BASE + CRU_MODE);
934*91f16700Schasinglulu 	ddr_data.cru_pmu_mode_save = mmio_read_32(PMUCRU_BASE + CRU_PMU_MODE);
935*91f16700Schasinglulu 	ddr_data.clk_sel0 = mmio_read_32(CRU_BASE + CRU_CLKSELS_CON(0));
936*91f16700Schasinglulu 
937*91f16700Schasinglulu 	pll_suspend(GPLL_ID);
938*91f16700Schasinglulu 	pll_suspend(NPLL_ID);
939*91f16700Schasinglulu 	pll_suspend(CPLL_ID);
940*91f16700Schasinglulu 	pll_suspend(APLL_ID);
941*91f16700Schasinglulu 
942*91f16700Schasinglulu 	/* core */
943*91f16700Schasinglulu 	mmio_write_32(CRU_BASE + CRU_CLKSELS_CON(0),
944*91f16700Schasinglulu 		      BITS_WITH_WMASK(0, 0xf, 0));
945*91f16700Schasinglulu 
946*91f16700Schasinglulu 	/* pclk_dbg */
947*91f16700Schasinglulu 	mmio_write_32(CRU_BASE + CRU_CLKSELS_CON(0),
948*91f16700Schasinglulu 		      BITS_WITH_WMASK(0, 0xf, 8));
949*91f16700Schasinglulu }
950*91f16700Schasinglulu 
951*91f16700Schasinglulu static void pm_plls_resume(void)
952*91f16700Schasinglulu {
953*91f16700Schasinglulu 	/* pclk_dbg */
954*91f16700Schasinglulu 	mmio_write_32(CRU_BASE + CRU_CLKSELS_CON(0),
955*91f16700Schasinglulu 		      ddr_data.clk_sel0 | BITS_WMSK(0xf, 8));
956*91f16700Schasinglulu 
957*91f16700Schasinglulu 	/* core */
958*91f16700Schasinglulu 	mmio_write_32(CRU_BASE + CRU_CLKSELS_CON(0),
959*91f16700Schasinglulu 		      ddr_data.clk_sel0 | BITS_WMSK(0xf, 0));
960*91f16700Schasinglulu 
961*91f16700Schasinglulu 	pll_resume(APLL_ID);
962*91f16700Schasinglulu 	pll_resume(CPLL_ID);
963*91f16700Schasinglulu 	pll_resume(NPLL_ID);
964*91f16700Schasinglulu 	pll_resume(GPLL_ID);
965*91f16700Schasinglulu }
966*91f16700Schasinglulu 
967*91f16700Schasinglulu int rockchip_soc_sys_pwr_dm_suspend(void)
968*91f16700Schasinglulu {
969*91f16700Schasinglulu 	pmu_power_domains_suspend();
970*91f16700Schasinglulu 
971*91f16700Schasinglulu 	clk_gate_suspend();
972*91f16700Schasinglulu 
973*91f16700Schasinglulu 	soc_sleep_config();
974*91f16700Schasinglulu 
975*91f16700Schasinglulu 	pm_plls_suspend();
976*91f16700Schasinglulu 
977*91f16700Schasinglulu 	psram_boot_cfg->pm_flag &= ~PM_WARM_BOOT_BIT;
978*91f16700Schasinglulu 
979*91f16700Schasinglulu 	return 0;
980*91f16700Schasinglulu }
981*91f16700Schasinglulu 
982*91f16700Schasinglulu int rockchip_soc_sys_pwr_dm_resume(void)
983*91f16700Schasinglulu {
984*91f16700Schasinglulu 	psram_boot_cfg->pm_flag |= PM_WARM_BOOT_BIT;
985*91f16700Schasinglulu 
986*91f16700Schasinglulu 	pm_plls_resume();
987*91f16700Schasinglulu 
988*91f16700Schasinglulu 	soc_sleep_restore();
989*91f16700Schasinglulu 
990*91f16700Schasinglulu 	clk_gate_resume();
991*91f16700Schasinglulu 
992*91f16700Schasinglulu 	pmu_power_domains_resume();
993*91f16700Schasinglulu 
994*91f16700Schasinglulu 	plat_rockchip_gic_cpuif_enable();
995*91f16700Schasinglulu 
996*91f16700Schasinglulu 	return 0;
997*91f16700Schasinglulu }
998*91f16700Schasinglulu 
999*91f16700Schasinglulu void __dead2 rockchip_soc_soft_reset(void)
1000*91f16700Schasinglulu {
1001*91f16700Schasinglulu 	pll_set_mode(GPLL_ID, SLOW_MODE);
1002*91f16700Schasinglulu 	pll_set_mode(CPLL_ID, SLOW_MODE);
1003*91f16700Schasinglulu 	pll_set_mode(NPLL_ID, SLOW_MODE);
1004*91f16700Schasinglulu 	pll_set_mode(APLL_ID, SLOW_MODE);
1005*91f16700Schasinglulu 	dsb();
1006*91f16700Schasinglulu 
1007*91f16700Schasinglulu 	mmio_write_32(CRU_BASE + CRU_GLB_SRST_FST, CRU_GLB_SRST_FST_VALUE);
1008*91f16700Schasinglulu 	dsb();
1009*91f16700Schasinglulu 
1010*91f16700Schasinglulu 	/*
1011*91f16700Schasinglulu 	 * Maybe the HW needs some times to reset the system,
1012*91f16700Schasinglulu 	 * so we do not hope the core to execute valid codes.
1013*91f16700Schasinglulu 	 */
1014*91f16700Schasinglulu 	psci_power_down_wfi();
1015*91f16700Schasinglulu }
1016*91f16700Schasinglulu 
1017*91f16700Schasinglulu void __dead2 rockchip_soc_system_off(void)
1018*91f16700Schasinglulu {
1019*91f16700Schasinglulu 	uint32_t val;
1020*91f16700Schasinglulu 
1021*91f16700Schasinglulu 	/* set pmic_sleep pin(gpio0_a4) to gpio mode */
1022*91f16700Schasinglulu 	mmio_write_32(PMUGRF_BASE + GPIO0A_IOMUX, BITS_WITH_WMASK(0, 0x3, 8));
1023*91f16700Schasinglulu 
1024*91f16700Schasinglulu 	/* config output */
1025*91f16700Schasinglulu 	val = mmio_read_32(GPIO0_BASE + SWPORTA_DDR);
1026*91f16700Schasinglulu 	val |= BIT(4);
1027*91f16700Schasinglulu 	mmio_write_32(GPIO0_BASE + SWPORTA_DDR, val);
1028*91f16700Schasinglulu 
1029*91f16700Schasinglulu 	/* config output high level */
1030*91f16700Schasinglulu 	val = mmio_read_32(GPIO0_BASE);
1031*91f16700Schasinglulu 	val |= BIT(4);
1032*91f16700Schasinglulu 	mmio_write_32(GPIO0_BASE, val);
1033*91f16700Schasinglulu 	dsb();
1034*91f16700Schasinglulu 
1035*91f16700Schasinglulu 	/*
1036*91f16700Schasinglulu 	 * Maybe the HW needs some times to reset the system,
1037*91f16700Schasinglulu 	 * so we do not hope the core to execute valid codes.
1038*91f16700Schasinglulu 	 */
1039*91f16700Schasinglulu 	psci_power_down_wfi();
1040*91f16700Schasinglulu }
1041*91f16700Schasinglulu 
1042*91f16700Schasinglulu void rockchip_plat_mmu_el3(void)
1043*91f16700Schasinglulu {
1044*91f16700Schasinglulu 	/* TODO: support the el3 for px30 SoCs */
1045*91f16700Schasinglulu }
1046*91f16700Schasinglulu 
1047*91f16700Schasinglulu void plat_rockchip_pmu_init(void)
1048*91f16700Schasinglulu {
1049*91f16700Schasinglulu 	uint32_t cpu;
1050*91f16700Schasinglulu 
1051*91f16700Schasinglulu 	rockchip_pd_lock_init();
1052*91f16700Schasinglulu 
1053*91f16700Schasinglulu 	for (cpu = 0; cpu < PLATFORM_CORE_COUNT; cpu++)
1054*91f16700Schasinglulu 		cpuson_flags[cpu] = 0;
1055*91f16700Schasinglulu 
1056*91f16700Schasinglulu 	psram_boot_cfg->ddr_func = (uint64_t)0;
1057*91f16700Schasinglulu 	psram_boot_cfg->ddr_data = (uint64_t)0;
1058*91f16700Schasinglulu 	psram_boot_cfg->sp = PSRAM_SP_TOP;
1059*91f16700Schasinglulu 	psram_boot_cfg->ddr_flag = 0x0;
1060*91f16700Schasinglulu 	psram_boot_cfg->boot_mpidr = read_mpidr_el1() & 0xffff;
1061*91f16700Schasinglulu 	psram_boot_cfg->pm_flag = PM_WARM_BOOT_BIT;
1062*91f16700Schasinglulu 
1063*91f16700Schasinglulu 	nonboot_cpus_off();
1064*91f16700Schasinglulu 
1065*91f16700Schasinglulu 	/* Remap pmu_sram's base address to boot address */
1066*91f16700Schasinglulu 	mmio_write_32(PMUSGRF_BASE + PMUSGRF_SOC_CON(0),
1067*91f16700Schasinglulu 		      BITS_WITH_WMASK(1, 0x1, 13));
1068*91f16700Schasinglulu 
1069*91f16700Schasinglulu 	INFO("%s: pd status %x\n",
1070*91f16700Schasinglulu 	     __func__, mmio_read_32(PMU_BASE + PMU_PWRDN_ST));
1071*91f16700Schasinglulu }
1072