xref: /rk3399_ARM-atf/plat/hisilicon/hikey960/hikey960_pm.c (revision 6f7dba4b24ee8e6c134a5237b5af461c9898501e)
1 /*
2  * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved.
3  *
4  * SPDX-License-Identifier: BSD-3-Clause
5  */
6 
7 #include <arch_helpers.h>
8 #include <assert.h>
9 #include <cci.h>
10 #include <debug.h>
11 #include <delay_timer.h>
12 #include <gicv2.h>
13 #include <hi3660.h>
14 #include <hi3660_crg.h>
15 #include <mmio.h>
16 #include <pl011.h>
17 #include <psci.h>
18 #include "drivers/pwrc/hisi_pwrc.h"
19 
20 #include "hikey960_def.h"
21 #include "hikey960_private.h"
22 
23 #define CORE_PWR_STATE(state) \
24 	((state)->pwr_domain_state[MPIDR_AFFLVL0])
25 #define CLUSTER_PWR_STATE(state) \
26 	((state)->pwr_domain_state[MPIDR_AFFLVL1])
27 #define SYSTEM_PWR_STATE(state) \
28 	((state)->pwr_domain_state[PLAT_MAX_PWR_LVL])
29 
30 #define DMAC_GLB_REG_SEC	0x694
31 #define AXI_CONF_BASE		0x820
32 
33 static unsigned int uart_base;
34 static console_pl011_t console;
35 static uintptr_t hikey960_sec_entrypoint;
36 
37 static void hikey960_pwr_domain_standby(plat_local_state_t cpu_state)
38 {
39 	unsigned long scr;
40 
41 	scr = read_scr_el3();
42 
43 	/* Enable Physical IRQ and FIQ to wake the CPU */
44 	write_scr_el3(scr | SCR_IRQ_BIT | SCR_FIQ_BIT);
45 
46 	/* Add barrier before CPU enter WFI state */
47 	isb();
48 	dsb();
49 	wfi();
50 
51 	/*
52 	 * Restore SCR to the original value, synchronisazion of
53 	 * scr_el3 is done by eret while el3_exit to save some
54 	 * execution cycles.
55 	 */
56 	write_scr_el3(scr);
57 }
58 
59 static int hikey960_pwr_domain_on(u_register_t mpidr)
60 {
61 	unsigned int core = mpidr & MPIDR_CPU_MASK;
62 	unsigned int cluster =
63 		(mpidr & MPIDR_CLUSTER_MASK) >> MPIDR_AFFINITY_BITS;
64 	int cluster_stat = cluster_is_powered_on(cluster);
65 
66 	hisi_set_cpu_boot_flag(cluster, core);
67 
68 	mmio_write_32(CRG_REG_BASE + CRG_RVBAR(cluster, core),
69 		      hikey960_sec_entrypoint >> 2);
70 
71 	if (cluster_stat)
72 		hisi_powerup_core(cluster, core);
73 	else
74 		hisi_powerup_cluster(cluster, core);
75 
76 	return PSCI_E_SUCCESS;
77 }
78 
79 static void
80 hikey960_pwr_domain_on_finish(const psci_power_state_t *target_state)
81 {
82 	if (CLUSTER_PWR_STATE(target_state) == PLAT_MAX_OFF_STATE)
83 		cci_enable_snoop_dvm_reqs(MPIDR_AFFLVL1_VAL(read_mpidr_el1()));
84 
85 	gicv2_pcpu_distif_init();
86 	gicv2_cpuif_enable();
87 }
88 
89 void hikey960_pwr_domain_off(const psci_power_state_t *target_state)
90 {
91 	unsigned long mpidr = read_mpidr_el1();
92 	unsigned int core = mpidr & MPIDR_CPU_MASK;
93 	unsigned int cluster =
94 		(mpidr & MPIDR_CLUSTER_MASK) >> MPIDR_AFFINITY_BITS;
95 
96 	clr_ex();
97 	isb();
98 	dsbsy();
99 
100 	gicv2_cpuif_disable();
101 
102 	hisi_clear_cpu_boot_flag(cluster, core);
103 	hisi_powerdn_core(cluster, core);
104 
105 	/* check if any core is powered up */
106 	if (hisi_test_cpu_down(cluster, core)) {
107 
108 		cci_disable_snoop_dvm_reqs(MPIDR_AFFLVL1_VAL(read_mpidr_el1()));
109 
110 		isb();
111 		dsbsy();
112 
113 		hisi_powerdn_cluster(cluster, core);
114 	}
115 }
116 
117 static void __dead2 hikey960_system_reset(void)
118 {
119 	dsb();
120 	isb();
121 	mdelay(2000);
122 	mmio_write_32(SCTRL_SCPEREN1_REG,
123 		      SCPEREN1_WAIT_DDR_SELFREFRESH_DONE_BYPASS);
124 	mmio_write_32(SCTRL_SCSYSSTAT_REG, 0xdeadbeef);
125 	panic();
126 }
127 
128 int hikey960_validate_power_state(unsigned int power_state,
129 			       psci_power_state_t *req_state)
130 {
131 	unsigned int pstate = psci_get_pstate_type(power_state);
132 	unsigned int pwr_lvl = psci_get_pstate_pwrlvl(power_state);
133 	int i;
134 
135 	assert(req_state);
136 
137 	if (pwr_lvl > PLAT_MAX_PWR_LVL)
138 		return PSCI_E_INVALID_PARAMS;
139 
140 	/* Sanity check the requested state */
141 	if (pstate == PSTATE_TYPE_STANDBY) {
142 		/*
143 		 * It's possible to enter standby only on power level 0
144 		 * Ignore any other power level.
145 		 */
146 		if (pwr_lvl != MPIDR_AFFLVL0)
147 			return PSCI_E_INVALID_PARAMS;
148 
149 		req_state->pwr_domain_state[MPIDR_AFFLVL0] =
150 					PLAT_MAX_RET_STATE;
151 	} else {
152 		for (i = MPIDR_AFFLVL0; i <= pwr_lvl; i++)
153 			req_state->pwr_domain_state[i] =
154 					PLAT_MAX_OFF_STATE;
155 	}
156 
157 	/*
158 	 * We expect the 'state id' to be zero.
159 	 */
160 	if (psci_get_pstate_id(power_state))
161 		return PSCI_E_INVALID_PARAMS;
162 
163 	return PSCI_E_SUCCESS;
164 }
165 
166 static int hikey960_validate_ns_entrypoint(uintptr_t entrypoint)
167 {
168 	/*
169 	 * Check if the non secure entrypoint lies within the non
170 	 * secure DRAM.
171 	 */
172 	if ((entrypoint > DDR_BASE) && (entrypoint < (DDR_BASE + DDR_SIZE)))
173 		return PSCI_E_SUCCESS;
174 
175 	return PSCI_E_INVALID_ADDRESS;
176 }
177 
178 static void hikey960_pwr_domain_suspend(const psci_power_state_t *target_state)
179 {
180 	u_register_t mpidr = read_mpidr_el1();
181 	unsigned int core = mpidr & MPIDR_CPU_MASK;
182 	unsigned int cluster =
183 		(mpidr & MPIDR_CLUSTER_MASK) >> MPIDR_AFFINITY_BITS;
184 
185 	if (CORE_PWR_STATE(target_state) != PLAT_MAX_OFF_STATE)
186 		return;
187 
188 	if (CORE_PWR_STATE(target_state) == PLAT_MAX_OFF_STATE) {
189 		clr_ex();
190 		isb();
191 		dsbsy();
192 
193 		gicv2_cpuif_disable();
194 
195 		hisi_cpuidle_lock(cluster, core);
196 		hisi_set_cpuidle_flag(cluster, core);
197 		hisi_cpuidle_unlock(cluster, core);
198 
199 		mmio_write_32(CRG_REG_BASE + CRG_RVBAR(cluster, core),
200 		      hikey960_sec_entrypoint >> 2);
201 
202 		hisi_enter_core_idle(cluster, core);
203 	}
204 
205 	/* Perform the common cluster specific operations */
206 	if (CLUSTER_PWR_STATE(target_state) == PLAT_MAX_OFF_STATE) {
207 		hisi_cpuidle_lock(cluster, core);
208 		hisi_disable_pdc(cluster);
209 
210 		/* check if any core is powered up */
211 		if (hisi_test_pwrdn_allcores(cluster, core)) {
212 
213 			cci_disable_snoop_dvm_reqs(MPIDR_AFFLVL1_VAL(mpidr));
214 
215 			isb();
216 			dsbsy();
217 
218 			/* mask the pdc wakeup irq, then
219 			 * enable pdc to power down the core
220 			 */
221 			hisi_pdc_mask_cluster_wakeirq(cluster);
222 			hisi_enable_pdc(cluster);
223 
224 			hisi_cpuidle_unlock(cluster, core);
225 
226 			/* check the SR flag bit to determine
227 			 * CLUSTER_IDLE_IPC or AP_SR_IPC to send
228 			 */
229 			if (hisi_test_ap_suspend_flag(cluster))
230 				hisi_enter_ap_suspend(cluster, core);
231 			else
232 				hisi_enter_cluster_idle(cluster, core);
233 		} else {
234 			/* enable pdc */
235 			hisi_enable_pdc(cluster);
236 			hisi_cpuidle_unlock(cluster, core);
237 		}
238 	}
239 }
240 
241 static void hikey960_sr_dma_reinit(void)
242 {
243 	unsigned int ctr = 0;
244 
245 	mmio_write_32(DMAC_BASE + DMAC_GLB_REG_SEC, 0x3);
246 
247 	/* 1~15 channel is set non_secure */
248 	for (ctr = 1; ctr <= 15; ctr++)
249 		mmio_write_32(DMAC_BASE + AXI_CONF_BASE + ctr * (0x40),
250 			      (1 << 6) | (1 << 18));
251 }
252 
253 static void
254 hikey960_pwr_domain_suspend_finish(const psci_power_state_t *target_state)
255 {
256 	unsigned long mpidr = read_mpidr_el1();
257 	unsigned int core = mpidr & MPIDR_CPU_MASK;
258 	unsigned int cluster =
259 		(mpidr & MPIDR_CLUSTER_MASK) >> MPIDR_AFFINITY_BITS;
260 
261 	/* Nothing to be done on waking up from retention from CPU level */
262 	if (CORE_PWR_STATE(target_state) != PLAT_MAX_OFF_STATE)
263 		return;
264 
265 	hisi_cpuidle_lock(cluster, core);
266 	hisi_clear_cpuidle_flag(cluster, core);
267 	hisi_cpuidle_unlock(cluster, core);
268 
269 	if (hisi_test_ap_suspend_flag(cluster)) {
270 		hikey960_sr_dma_reinit();
271 		gicv2_cpuif_enable();
272 		console_pl011_register(uart_base, PL011_UART_CLK_IN_HZ,
273 				       PL011_BAUDRATE, &console);
274 	}
275 
276 	hikey960_pwr_domain_on_finish(target_state);
277 }
278 
279 static void hikey960_get_sys_suspend_power_state(psci_power_state_t *req_state)
280 {
281 	int i;
282 
283 	for (i = MPIDR_AFFLVL0; i <= PLAT_MAX_PWR_LVL; i++)
284 		req_state->pwr_domain_state[i] = PLAT_MAX_OFF_STATE;
285 }
286 
287 static const plat_psci_ops_t hikey960_psci_ops = {
288 	.cpu_standby			= hikey960_pwr_domain_standby,
289 	.pwr_domain_on			= hikey960_pwr_domain_on,
290 	.pwr_domain_on_finish		= hikey960_pwr_domain_on_finish,
291 	.pwr_domain_off			= hikey960_pwr_domain_off,
292 	.pwr_domain_suspend		= hikey960_pwr_domain_suspend,
293 	.pwr_domain_suspend_finish	= hikey960_pwr_domain_suspend_finish,
294 	.system_off			= NULL,
295 	.system_reset			= hikey960_system_reset,
296 	.validate_power_state		= hikey960_validate_power_state,
297 	.validate_ns_entrypoint		= hikey960_validate_ns_entrypoint,
298 	.get_sys_suspend_power_state	= hikey960_get_sys_suspend_power_state,
299 };
300 
301 int plat_setup_psci_ops(uintptr_t sec_entrypoint,
302 			const plat_psci_ops_t **psci_ops)
303 {
304 	unsigned int id = 0;
305 	int ret;
306 
307 	ret = hikey960_read_boardid(&id);
308 	if (ret == 0) {
309 		if (id == 5300U)
310 			uart_base = PL011_UART5_BASE;
311 		else
312 			uart_base = PL011_UART6_BASE;
313 	} else {
314 		uart_base = PL011_UART6_BASE;
315 	}
316 
317 	hikey960_sec_entrypoint = sec_entrypoint;
318 
319 	INFO("%s: sec_entrypoint=0x%lx\n", __func__,
320 	     (unsigned long)hikey960_sec_entrypoint);
321 
322 	/*
323 	 * Initialize PSCI ops struct
324 	 */
325 	*psci_ops = &hikey960_psci_ops;
326 	return 0;
327 }
328