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