xref: /rk3399_ARM-atf/plat/rockchip/rk3288/drivers/pmu/pmu.c (revision 780e3f24553ef4dd177b7278bbfef30053de1656)
1*780e3f24SHeiko Stuebner /*
2*780e3f24SHeiko Stuebner  * Copyright (c) 2016, ARM Limited and Contributors. All rights reserved.
3*780e3f24SHeiko Stuebner  *
4*780e3f24SHeiko Stuebner  * SPDX-License-Identifier: BSD-3-Clause
5*780e3f24SHeiko Stuebner  */
6*780e3f24SHeiko Stuebner 
7*780e3f24SHeiko Stuebner #include <assert.h>
8*780e3f24SHeiko Stuebner #include <errno.h>
9*780e3f24SHeiko Stuebner 
10*780e3f24SHeiko Stuebner #include <platform_def.h>
11*780e3f24SHeiko Stuebner 
12*780e3f24SHeiko Stuebner #include <arch_helpers.h>
13*780e3f24SHeiko Stuebner #include <common/debug.h>
14*780e3f24SHeiko Stuebner #include <drivers/delay_timer.h>
15*780e3f24SHeiko Stuebner #include <lib/mmio.h>
16*780e3f24SHeiko Stuebner #include <plat/common/platform.h>
17*780e3f24SHeiko Stuebner 
18*780e3f24SHeiko Stuebner #include <plat_private.h>
19*780e3f24SHeiko Stuebner #include <pmu.h>
20*780e3f24SHeiko Stuebner #include <pmu_com.h>
21*780e3f24SHeiko Stuebner #include <rk3288_def.h>
22*780e3f24SHeiko Stuebner #include <secure.h>
23*780e3f24SHeiko Stuebner #include <soc.h>
24*780e3f24SHeiko Stuebner 
25*780e3f24SHeiko Stuebner DEFINE_BAKERY_LOCK(rockchip_pd_lock);
26*780e3f24SHeiko Stuebner 
27*780e3f24SHeiko Stuebner static uint32_t cpu_warm_boot_addr;
28*780e3f24SHeiko Stuebner 
29*780e3f24SHeiko Stuebner static uint32_t store_pmu_pwrmode_con;
30*780e3f24SHeiko Stuebner static uint32_t store_sgrf_soc_con0;
31*780e3f24SHeiko Stuebner static uint32_t store_sgrf_cpu_con0;
32*780e3f24SHeiko Stuebner 
33*780e3f24SHeiko Stuebner /* These enum are variants of low power mode */
34*780e3f24SHeiko Stuebner enum {
35*780e3f24SHeiko Stuebner 	ROCKCHIP_ARM_OFF_LOGIC_NORMAL = 0,
36*780e3f24SHeiko Stuebner 	ROCKCHIP_ARM_OFF_LOGIC_DEEP = 1,
37*780e3f24SHeiko Stuebner };
38*780e3f24SHeiko Stuebner 
39*780e3f24SHeiko Stuebner static inline int rk3288_pmu_bus_idle(uint32_t req, uint32_t idle)
40*780e3f24SHeiko Stuebner {
41*780e3f24SHeiko Stuebner 	uint32_t mask = BIT(req);
42*780e3f24SHeiko Stuebner 	uint32_t idle_mask = 0;
43*780e3f24SHeiko Stuebner 	uint32_t idle_target = 0;
44*780e3f24SHeiko Stuebner 	uint32_t val;
45*780e3f24SHeiko Stuebner 	uint32_t wait_cnt = 0;
46*780e3f24SHeiko Stuebner 
47*780e3f24SHeiko Stuebner 	switch (req) {
48*780e3f24SHeiko Stuebner 	case bus_ide_req_gpu:
49*780e3f24SHeiko Stuebner 		idle_mask = BIT(pmu_idle_ack_gpu) | BIT(pmu_idle_gpu);
50*780e3f24SHeiko Stuebner 		idle_target = (idle << pmu_idle_ack_gpu) |
51*780e3f24SHeiko Stuebner 			      (idle << pmu_idle_gpu);
52*780e3f24SHeiko Stuebner 		break;
53*780e3f24SHeiko Stuebner 	case bus_ide_req_core:
54*780e3f24SHeiko Stuebner 		idle_mask = BIT(pmu_idle_ack_core) | BIT(pmu_idle_core);
55*780e3f24SHeiko Stuebner 		idle_target = (idle << pmu_idle_ack_core) |
56*780e3f24SHeiko Stuebner 			      (idle << pmu_idle_core);
57*780e3f24SHeiko Stuebner 		break;
58*780e3f24SHeiko Stuebner 	case bus_ide_req_cpup:
59*780e3f24SHeiko Stuebner 		idle_mask = BIT(pmu_idle_ack_cpup) | BIT(pmu_idle_cpup);
60*780e3f24SHeiko Stuebner 		idle_target = (idle << pmu_idle_ack_cpup) |
61*780e3f24SHeiko Stuebner 			      (idle << pmu_idle_cpup);
62*780e3f24SHeiko Stuebner 		break;
63*780e3f24SHeiko Stuebner 	case bus_ide_req_bus:
64*780e3f24SHeiko Stuebner 		idle_mask = BIT(pmu_idle_ack_bus) | BIT(pmu_idle_bus);
65*780e3f24SHeiko Stuebner 		idle_target = (idle << pmu_idle_ack_bus) |
66*780e3f24SHeiko Stuebner 			      (idle << pmu_idle_bus);
67*780e3f24SHeiko Stuebner 		break;
68*780e3f24SHeiko Stuebner 	case bus_ide_req_dma:
69*780e3f24SHeiko Stuebner 		idle_mask = BIT(pmu_idle_ack_dma) | BIT(pmu_idle_dma);
70*780e3f24SHeiko Stuebner 		idle_target = (idle << pmu_idle_ack_dma) |
71*780e3f24SHeiko Stuebner 			      (idle << pmu_idle_dma);
72*780e3f24SHeiko Stuebner 		break;
73*780e3f24SHeiko Stuebner 	case bus_ide_req_peri:
74*780e3f24SHeiko Stuebner 		idle_mask = BIT(pmu_idle_ack_peri) | BIT(pmu_idle_peri);
75*780e3f24SHeiko Stuebner 		idle_target = (idle << pmu_idle_ack_peri) |
76*780e3f24SHeiko Stuebner 			      (idle << pmu_idle_peri);
77*780e3f24SHeiko Stuebner 		break;
78*780e3f24SHeiko Stuebner 	case bus_ide_req_video:
79*780e3f24SHeiko Stuebner 		idle_mask = BIT(pmu_idle_ack_video) | BIT(pmu_idle_video);
80*780e3f24SHeiko Stuebner 		idle_target = (idle << pmu_idle_ack_video) |
81*780e3f24SHeiko Stuebner 			      (idle << pmu_idle_video);
82*780e3f24SHeiko Stuebner 		break;
83*780e3f24SHeiko Stuebner 	case bus_ide_req_hevc:
84*780e3f24SHeiko Stuebner 		idle_mask = BIT(pmu_idle_ack_hevc) | BIT(pmu_idle_hevc);
85*780e3f24SHeiko Stuebner 		idle_target = (idle << pmu_idle_ack_hevc) |
86*780e3f24SHeiko Stuebner 			      (idle << pmu_idle_hevc);
87*780e3f24SHeiko Stuebner 		break;
88*780e3f24SHeiko Stuebner 	case bus_ide_req_vio:
89*780e3f24SHeiko Stuebner 		idle_mask = BIT(pmu_idle_ack_vio) | BIT(pmu_idle_vio);
90*780e3f24SHeiko Stuebner 		idle_target = (pmu_idle_ack_vio) |
91*780e3f24SHeiko Stuebner 			      (idle << pmu_idle_vio);
92*780e3f24SHeiko Stuebner 		break;
93*780e3f24SHeiko Stuebner 	case bus_ide_req_alive:
94*780e3f24SHeiko Stuebner 		idle_mask = BIT(pmu_idle_ack_alive) | BIT(pmu_idle_alive);
95*780e3f24SHeiko Stuebner 		idle_target = (idle << pmu_idle_ack_alive) |
96*780e3f24SHeiko Stuebner 			      (idle << pmu_idle_alive);
97*780e3f24SHeiko Stuebner 		break;
98*780e3f24SHeiko Stuebner 	default:
99*780e3f24SHeiko Stuebner 		ERROR("%s: Unsupported the idle request\n", __func__);
100*780e3f24SHeiko Stuebner 		break;
101*780e3f24SHeiko Stuebner 	}
102*780e3f24SHeiko Stuebner 
103*780e3f24SHeiko Stuebner 	val = mmio_read_32(PMU_BASE + PMU_BUS_IDE_REQ);
104*780e3f24SHeiko Stuebner 	if (idle)
105*780e3f24SHeiko Stuebner 		val |= mask;
106*780e3f24SHeiko Stuebner 	else
107*780e3f24SHeiko Stuebner 		val &= ~mask;
108*780e3f24SHeiko Stuebner 
109*780e3f24SHeiko Stuebner 	mmio_write_32(PMU_BASE + PMU_BUS_IDE_REQ, val);
110*780e3f24SHeiko Stuebner 
111*780e3f24SHeiko Stuebner 	while ((mmio_read_32(PMU_BASE +
112*780e3f24SHeiko Stuebner 	       PMU_BUS_IDE_ST) & idle_mask) != idle_target) {
113*780e3f24SHeiko Stuebner 		wait_cnt++;
114*780e3f24SHeiko Stuebner 		if (!(wait_cnt % MAX_WAIT_CONUT))
115*780e3f24SHeiko Stuebner 			WARN("%s:st=%x(%x)\n", __func__,
116*780e3f24SHeiko Stuebner 			     mmio_read_32(PMU_BASE + PMU_BUS_IDE_ST),
117*780e3f24SHeiko Stuebner 			     idle_mask);
118*780e3f24SHeiko Stuebner 	}
119*780e3f24SHeiko Stuebner 
120*780e3f24SHeiko Stuebner 	return 0;
121*780e3f24SHeiko Stuebner }
122*780e3f24SHeiko Stuebner 
123*780e3f24SHeiko Stuebner static bool rk3288_sleep_disable_osc(void)
124*780e3f24SHeiko Stuebner {
125*780e3f24SHeiko Stuebner 	static const uint32_t reg_offset[] = { GRF_UOC0_CON0, GRF_UOC1_CON0,
126*780e3f24SHeiko Stuebner 					       GRF_UOC2_CON0 };
127*780e3f24SHeiko Stuebner 	uint32_t reg, i;
128*780e3f24SHeiko Stuebner 
129*780e3f24SHeiko Stuebner 	/*
130*780e3f24SHeiko Stuebner 	 * if any usb phy is still on(GRF_SIDDQ==0), that means we need the
131*780e3f24SHeiko Stuebner 	 * function of usb wakeup, so do not switch to 32khz, since the usb phy
132*780e3f24SHeiko Stuebner 	 * clk does not connect to 32khz osc
133*780e3f24SHeiko Stuebner 	 */
134*780e3f24SHeiko Stuebner 	for (i = 0; i < ARRAY_SIZE(reg_offset); i++) {
135*780e3f24SHeiko Stuebner 		reg = mmio_read_32(GRF_BASE + reg_offset[i]);
136*780e3f24SHeiko Stuebner 		if (!(reg & GRF_SIDDQ))
137*780e3f24SHeiko Stuebner 			return false;
138*780e3f24SHeiko Stuebner 	}
139*780e3f24SHeiko Stuebner 
140*780e3f24SHeiko Stuebner 	return true;
141*780e3f24SHeiko Stuebner }
142*780e3f24SHeiko Stuebner 
143*780e3f24SHeiko Stuebner static void pmu_set_sleep_mode(int level)
144*780e3f24SHeiko Stuebner {
145*780e3f24SHeiko Stuebner 	uint32_t mode_set, mode_set1;
146*780e3f24SHeiko Stuebner 	bool osc_disable = rk3288_sleep_disable_osc();
147*780e3f24SHeiko Stuebner 
148*780e3f24SHeiko Stuebner 	mode_set = BIT(pmu_mode_glb_int_dis) | BIT(pmu_mode_l2_flush_en) |
149*780e3f24SHeiko Stuebner 		   BIT(pmu_mode_sref0_enter) | BIT(pmu_mode_sref1_enter) |
150*780e3f24SHeiko Stuebner 		   BIT(pmu_mode_ddrc0_gt) | BIT(pmu_mode_ddrc1_gt) |
151*780e3f24SHeiko Stuebner 		   BIT(pmu_mode_en) | BIT(pmu_mode_chip_pd) |
152*780e3f24SHeiko Stuebner 		   BIT(pmu_mode_scu_pd);
153*780e3f24SHeiko Stuebner 
154*780e3f24SHeiko Stuebner 	mode_set1 = BIT(pmu_mode_clr_core) | BIT(pmu_mode_clr_cpup);
155*780e3f24SHeiko Stuebner 
156*780e3f24SHeiko Stuebner 	if (level == ROCKCHIP_ARM_OFF_LOGIC_DEEP) {
157*780e3f24SHeiko Stuebner 		/* arm off, logic deep sleep */
158*780e3f24SHeiko Stuebner 		mode_set |= BIT(pmu_mode_bus_pd) | BIT(pmu_mode_pmu_use_lf) |
159*780e3f24SHeiko Stuebner 			    BIT(pmu_mode_ddrio1_ret) |
160*780e3f24SHeiko Stuebner 			    BIT(pmu_mode_ddrio0_ret) |
161*780e3f24SHeiko Stuebner 			    BIT(pmu_mode_pmu_alive_use_lf) |
162*780e3f24SHeiko Stuebner 			    BIT(pmu_mode_pll_pd);
163*780e3f24SHeiko Stuebner 
164*780e3f24SHeiko Stuebner 		if (osc_disable)
165*780e3f24SHeiko Stuebner 			mode_set |= BIT(pmu_mode_osc_dis);
166*780e3f24SHeiko Stuebner 
167*780e3f24SHeiko Stuebner 		mode_set1 |= BIT(pmu_mode_clr_alive) | BIT(pmu_mode_clr_bus) |
168*780e3f24SHeiko Stuebner 			     BIT(pmu_mode_clr_peri) | BIT(pmu_mode_clr_dma);
169*780e3f24SHeiko Stuebner 
170*780e3f24SHeiko Stuebner 		mmio_write_32(PMU_BASE + PMU_WAKEUP_CFG1,
171*780e3f24SHeiko Stuebner 			      pmu_armint_wakeup_en);
172*780e3f24SHeiko Stuebner 
173*780e3f24SHeiko Stuebner 		/*
174*780e3f24SHeiko Stuebner 		 * In deep suspend we use PMU_PMU_USE_LF to let the rk3288
175*780e3f24SHeiko Stuebner 		 * switch its main clock supply to the alternative 32kHz
176*780e3f24SHeiko Stuebner 		 * source. Therefore set 30ms on a 32kHz clock for pmic
177*780e3f24SHeiko Stuebner 		 * stabilization. Similar 30ms on 24MHz for the other
178*780e3f24SHeiko Stuebner 		 * mode below.
179*780e3f24SHeiko Stuebner 		 */
180*780e3f24SHeiko Stuebner 		mmio_write_32(PMU_BASE + PMU_STABL_CNT, 32 * 30);
181*780e3f24SHeiko Stuebner 
182*780e3f24SHeiko Stuebner 		/* only wait for stabilization, if we turned the osc off */
183*780e3f24SHeiko Stuebner 		mmio_write_32(PMU_BASE + PMU_OSC_CNT,
184*780e3f24SHeiko Stuebner 					 osc_disable ? 32 * 30 : 0);
185*780e3f24SHeiko Stuebner 	} else {
186*780e3f24SHeiko Stuebner 		/*
187*780e3f24SHeiko Stuebner 		 * arm off, logic normal
188*780e3f24SHeiko Stuebner 		 * if pmu_clk_core_src_gate_en is not set,
189*780e3f24SHeiko Stuebner 		 * wakeup will be error
190*780e3f24SHeiko Stuebner 		 */
191*780e3f24SHeiko Stuebner 		mode_set |= BIT(pmu_mode_core_src_gt);
192*780e3f24SHeiko Stuebner 
193*780e3f24SHeiko Stuebner 		mmio_write_32(PMU_BASE + PMU_WAKEUP_CFG1,
194*780e3f24SHeiko Stuebner 			      BIT(pmu_armint_wakeup_en) |
195*780e3f24SHeiko Stuebner 			      BIT(pmu_gpioint_wakeup_en));
196*780e3f24SHeiko Stuebner 
197*780e3f24SHeiko Stuebner 		/* 30ms on a 24MHz clock for pmic stabilization */
198*780e3f24SHeiko Stuebner 		mmio_write_32(PMU_BASE + PMU_STABL_CNT, 24000 * 30);
199*780e3f24SHeiko Stuebner 
200*780e3f24SHeiko Stuebner 		/* oscillator is still running, so no need to wait */
201*780e3f24SHeiko Stuebner 		mmio_write_32(PMU_BASE + PMU_OSC_CNT, 0);
202*780e3f24SHeiko Stuebner 	}
203*780e3f24SHeiko Stuebner 
204*780e3f24SHeiko Stuebner 	mmio_write_32(PMU_BASE + PMU_PWRMODE_CON, mode_set);
205*780e3f24SHeiko Stuebner 	mmio_write_32(PMU_BASE + PMU_PWRMODE_CON1, mode_set1);
206*780e3f24SHeiko Stuebner }
207*780e3f24SHeiko Stuebner 
208*780e3f24SHeiko Stuebner static int cpus_power_domain_on(uint32_t cpu_id)
209*780e3f24SHeiko Stuebner {
210*780e3f24SHeiko Stuebner 	uint32_t cpu_pd;
211*780e3f24SHeiko Stuebner 
212*780e3f24SHeiko Stuebner 	cpu_pd = PD_CPU0 + cpu_id;
213*780e3f24SHeiko Stuebner 
214*780e3f24SHeiko Stuebner 	/* if the core has been on, power it off first */
215*780e3f24SHeiko Stuebner 	if (pmu_power_domain_st(cpu_pd) == pmu_pd_on) {
216*780e3f24SHeiko Stuebner 		/* put core in reset - some sort of A12/A17 bug */
217*780e3f24SHeiko Stuebner 		mmio_write_32(CRU_BASE + CRU_SOFTRSTS_CON(0),
218*780e3f24SHeiko Stuebner 			      BIT(cpu_id) | (BIT(cpu_id) << 16));
219*780e3f24SHeiko Stuebner 
220*780e3f24SHeiko Stuebner 		pmu_power_domain_ctr(cpu_pd, pmu_pd_off);
221*780e3f24SHeiko Stuebner 	}
222*780e3f24SHeiko Stuebner 
223*780e3f24SHeiko Stuebner 	pmu_power_domain_ctr(cpu_pd, pmu_pd_on);
224*780e3f24SHeiko Stuebner 
225*780e3f24SHeiko Stuebner 	/* pull core out of reset */
226*780e3f24SHeiko Stuebner 	mmio_write_32(CRU_BASE + CRU_SOFTRSTS_CON(0), BIT(cpu_id) << 16);
227*780e3f24SHeiko Stuebner 
228*780e3f24SHeiko Stuebner 	return 0;
229*780e3f24SHeiko Stuebner }
230*780e3f24SHeiko Stuebner 
231*780e3f24SHeiko Stuebner static int cpus_power_domain_off(uint32_t cpu_id)
232*780e3f24SHeiko Stuebner {
233*780e3f24SHeiko Stuebner 	uint32_t cpu_pd = PD_CPU0 + cpu_id;
234*780e3f24SHeiko Stuebner 
235*780e3f24SHeiko Stuebner 	if (pmu_power_domain_st(cpu_pd) == pmu_pd_off)
236*780e3f24SHeiko Stuebner 		return 0;
237*780e3f24SHeiko Stuebner 
238*780e3f24SHeiko Stuebner 	if (check_cpu_wfie(cpu_id, CKECK_WFEI_MSK))
239*780e3f24SHeiko Stuebner 		return -EINVAL;
240*780e3f24SHeiko Stuebner 
241*780e3f24SHeiko Stuebner 	/* put core in reset - some sort of A12/A17 bug */
242*780e3f24SHeiko Stuebner 	mmio_write_32(CRU_BASE + CRU_SOFTRSTS_CON(0),
243*780e3f24SHeiko Stuebner 		      BIT(cpu_id) | (BIT(cpu_id) << 16));
244*780e3f24SHeiko Stuebner 
245*780e3f24SHeiko Stuebner 	pmu_power_domain_ctr(cpu_pd, pmu_pd_off);
246*780e3f24SHeiko Stuebner 
247*780e3f24SHeiko Stuebner 	return 0;
248*780e3f24SHeiko Stuebner }
249*780e3f24SHeiko Stuebner 
250*780e3f24SHeiko Stuebner static void nonboot_cpus_off(void)
251*780e3f24SHeiko Stuebner {
252*780e3f24SHeiko Stuebner 	uint32_t boot_cpu, cpu;
253*780e3f24SHeiko Stuebner 
254*780e3f24SHeiko Stuebner 	boot_cpu = plat_my_core_pos();
255*780e3f24SHeiko Stuebner 	boot_cpu = MPIDR_AFFLVL0_VAL(read_mpidr());
256*780e3f24SHeiko Stuebner 
257*780e3f24SHeiko Stuebner 	/* turn off noboot cpus */
258*780e3f24SHeiko Stuebner 	for (cpu = 0; cpu < PLATFORM_CORE_COUNT; cpu++) {
259*780e3f24SHeiko Stuebner 		if (cpu == boot_cpu)
260*780e3f24SHeiko Stuebner 			continue;
261*780e3f24SHeiko Stuebner 
262*780e3f24SHeiko Stuebner 		cpus_power_domain_off(cpu);
263*780e3f24SHeiko Stuebner 	}
264*780e3f24SHeiko Stuebner }
265*780e3f24SHeiko Stuebner 
266*780e3f24SHeiko Stuebner void sram_save(void)
267*780e3f24SHeiko Stuebner {
268*780e3f24SHeiko Stuebner 	/* TODO: support the sdram save for rk3288 SoCs*/
269*780e3f24SHeiko Stuebner }
270*780e3f24SHeiko Stuebner 
271*780e3f24SHeiko Stuebner void sram_restore(void)
272*780e3f24SHeiko Stuebner {
273*780e3f24SHeiko Stuebner 	/* TODO: support the sdram restore for rk3288 SoCs */
274*780e3f24SHeiko Stuebner }
275*780e3f24SHeiko Stuebner 
276*780e3f24SHeiko Stuebner int rockchip_soc_cores_pwr_dm_on(unsigned long mpidr, uint64_t entrypoint)
277*780e3f24SHeiko Stuebner {
278*780e3f24SHeiko Stuebner 	uint32_t cpu_id = plat_core_pos_by_mpidr(mpidr);
279*780e3f24SHeiko Stuebner 
280*780e3f24SHeiko Stuebner 	assert(cpu_id < PLATFORM_CORE_COUNT);
281*780e3f24SHeiko Stuebner 	assert(cpuson_flags[cpu_id] == 0);
282*780e3f24SHeiko Stuebner 	cpuson_flags[cpu_id] = PMU_CPU_HOTPLUG;
283*780e3f24SHeiko Stuebner 	cpuson_entry_point[cpu_id] = entrypoint;
284*780e3f24SHeiko Stuebner 	dsb();
285*780e3f24SHeiko Stuebner 
286*780e3f24SHeiko Stuebner 	cpus_power_domain_on(cpu_id);
287*780e3f24SHeiko Stuebner 
288*780e3f24SHeiko Stuebner 	/*
289*780e3f24SHeiko Stuebner 	 * We communicate with the bootrom to active the cpus other
290*780e3f24SHeiko Stuebner 	 * than cpu0, after a blob of initialize code, they will
291*780e3f24SHeiko Stuebner 	 * stay at wfe state, once they are actived, they will check
292*780e3f24SHeiko Stuebner 	 * the mailbox:
293*780e3f24SHeiko Stuebner 	 * sram_base_addr + 4: 0xdeadbeaf
294*780e3f24SHeiko Stuebner 	 * sram_base_addr + 8: start address for pc
295*780e3f24SHeiko Stuebner 	 * The cpu0 need to wait the other cpus other than cpu0 entering
296*780e3f24SHeiko Stuebner 	 * the wfe state.The wait time is affected by many aspects.
297*780e3f24SHeiko Stuebner 	 * (e.g: cpu frequency, bootrom frequency, sram frequency, ...)
298*780e3f24SHeiko Stuebner 	 */
299*780e3f24SHeiko Stuebner 	mdelay(1); /* ensure the cpus other than cpu0 to startup */
300*780e3f24SHeiko Stuebner 
301*780e3f24SHeiko Stuebner 	/* tell the bootrom mailbox where to start from */
302*780e3f24SHeiko Stuebner 	mmio_write_32(SRAM_BASE + 8, cpu_warm_boot_addr);
303*780e3f24SHeiko Stuebner 	mmio_write_32(SRAM_BASE + 4, 0xDEADBEAF);
304*780e3f24SHeiko Stuebner 	dsb();
305*780e3f24SHeiko Stuebner 	sev();
306*780e3f24SHeiko Stuebner 
307*780e3f24SHeiko Stuebner 	return 0;
308*780e3f24SHeiko Stuebner }
309*780e3f24SHeiko Stuebner 
310*780e3f24SHeiko Stuebner int rockchip_soc_cores_pwr_dm_on_finish(void)
311*780e3f24SHeiko Stuebner {
312*780e3f24SHeiko Stuebner 	return 0;
313*780e3f24SHeiko Stuebner }
314*780e3f24SHeiko Stuebner 
315*780e3f24SHeiko Stuebner int rockchip_soc_sys_pwr_dm_resume(void)
316*780e3f24SHeiko Stuebner {
317*780e3f24SHeiko Stuebner 	mmio_write_32(PMU_BASE + PMU_PWRMODE_CON, store_pmu_pwrmode_con);
318*780e3f24SHeiko Stuebner 	mmio_write_32(SGRF_BASE + SGRF_CPU_CON(0),
319*780e3f24SHeiko Stuebner 		      store_sgrf_cpu_con0 | SGRF_DAPDEVICE_MSK);
320*780e3f24SHeiko Stuebner 
321*780e3f24SHeiko Stuebner 	/* disable fastboot mode */
322*780e3f24SHeiko Stuebner 	mmio_write_32(SGRF_BASE + SGRF_SOC_CON(0),
323*780e3f24SHeiko Stuebner 		      store_sgrf_soc_con0 | SGRF_FAST_BOOT_DIS);
324*780e3f24SHeiko Stuebner 
325*780e3f24SHeiko Stuebner 	secure_watchdog_ungate();
326*780e3f24SHeiko Stuebner 	clk_gate_con_restore();
327*780e3f24SHeiko Stuebner 	clk_sel_con_restore();
328*780e3f24SHeiko Stuebner 	clk_plls_resume();
329*780e3f24SHeiko Stuebner 
330*780e3f24SHeiko Stuebner 	secure_gic_init();
331*780e3f24SHeiko Stuebner 	plat_rockchip_gic_init();
332*780e3f24SHeiko Stuebner 
333*780e3f24SHeiko Stuebner 	return 0;
334*780e3f24SHeiko Stuebner }
335*780e3f24SHeiko Stuebner 
336*780e3f24SHeiko Stuebner int rockchip_soc_sys_pwr_dm_suspend(void)
337*780e3f24SHeiko Stuebner {
338*780e3f24SHeiko Stuebner 	nonboot_cpus_off();
339*780e3f24SHeiko Stuebner 
340*780e3f24SHeiko Stuebner 	store_sgrf_cpu_con0 = mmio_read_32(SGRF_BASE + SGRF_CPU_CON(0));
341*780e3f24SHeiko Stuebner 	store_sgrf_soc_con0 = mmio_read_32(SGRF_BASE + SGRF_SOC_CON(0));
342*780e3f24SHeiko Stuebner 	store_pmu_pwrmode_con = mmio_read_32(PMU_BASE + PMU_PWRMODE_CON);
343*780e3f24SHeiko Stuebner 
344*780e3f24SHeiko Stuebner 	/* save clk-gates and ungate all for suspend */
345*780e3f24SHeiko Stuebner 	clk_gate_con_save();
346*780e3f24SHeiko Stuebner 	clk_gate_con_disable();
347*780e3f24SHeiko Stuebner 	clk_sel_con_save();
348*780e3f24SHeiko Stuebner 
349*780e3f24SHeiko Stuebner 	pmu_set_sleep_mode(ROCKCHIP_ARM_OFF_LOGIC_NORMAL);
350*780e3f24SHeiko Stuebner 
351*780e3f24SHeiko Stuebner 	clk_plls_suspend();
352*780e3f24SHeiko Stuebner 	secure_watchdog_gate();
353*780e3f24SHeiko Stuebner 
354*780e3f24SHeiko Stuebner 	/*
355*780e3f24SHeiko Stuebner 	 * The dapswjdp can not auto reset before resume, that cause it may
356*780e3f24SHeiko Stuebner 	 * access some illegal address during resume. Let's disable it before
357*780e3f24SHeiko Stuebner 	 * suspend, and the MASKROM will enable it back.
358*780e3f24SHeiko Stuebner 	 */
359*780e3f24SHeiko Stuebner 	mmio_write_32(SGRF_BASE + SGRF_CPU_CON(0), SGRF_DAPDEVICE_MSK);
360*780e3f24SHeiko Stuebner 
361*780e3f24SHeiko Stuebner 	/*
362*780e3f24SHeiko Stuebner 	 * SGRF_FAST_BOOT_EN - system to boot from FAST_BOOT_ADDR
363*780e3f24SHeiko Stuebner 	 */
364*780e3f24SHeiko Stuebner 	mmio_write_32(SGRF_BASE + SGRF_SOC_CON(0), SGRF_FAST_BOOT_ENA);
365*780e3f24SHeiko Stuebner 
366*780e3f24SHeiko Stuebner 	/* boot-address of resuming system is from this register value */
367*780e3f24SHeiko Stuebner 	mmio_write_32(SGRF_BASE + SGRF_FAST_BOOT_ADDR,
368*780e3f24SHeiko Stuebner 		      (uint32_t)&pmu_cpuson_entrypoint);
369*780e3f24SHeiko Stuebner 
370*780e3f24SHeiko Stuebner 	/* flush all caches - otherwise we might loose the resume address */
371*780e3f24SHeiko Stuebner 	dcsw_op_all(DC_OP_CISW);
372*780e3f24SHeiko Stuebner 
373*780e3f24SHeiko Stuebner 	return 0;
374*780e3f24SHeiko Stuebner }
375*780e3f24SHeiko Stuebner 
376*780e3f24SHeiko Stuebner void rockchip_plat_mmu_svc_mon(void)
377*780e3f24SHeiko Stuebner {
378*780e3f24SHeiko Stuebner }
379*780e3f24SHeiko Stuebner 
380*780e3f24SHeiko Stuebner void plat_rockchip_pmu_init(void)
381*780e3f24SHeiko Stuebner {
382*780e3f24SHeiko Stuebner 	uint32_t cpu;
383*780e3f24SHeiko Stuebner 
384*780e3f24SHeiko Stuebner 	cpu_warm_boot_addr = (uint32_t)platform_cpu_warmboot;
385*780e3f24SHeiko Stuebner 
386*780e3f24SHeiko Stuebner 	/* on boot all power-domains are on */
387*780e3f24SHeiko Stuebner 	for (cpu = 0; cpu < PLATFORM_CORE_COUNT; cpu++)
388*780e3f24SHeiko Stuebner 		cpuson_flags[cpu] = pmu_pd_on;
389*780e3f24SHeiko Stuebner 
390*780e3f24SHeiko Stuebner 	nonboot_cpus_off();
391*780e3f24SHeiko Stuebner }
392