xref: /rk3399_ARM-atf/plat/hisilicon/hikey960/hikey960_pm.c (revision 7593252cee8745bbf1b05deb2f4a5f742d36c412)
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 PSTATE_WIDTH		4
30 #define PSTATE_MASK		((1 << PSTATE_WIDTH) - 1)
31 
32 #define MAKE_PWRSTATE(lvl2_state, lvl1_state, lvl0_state, pwr_lvl, type) \
33 		(((lvl2_state) << (PSTATE_ID_SHIFT + PSTATE_WIDTH * 2)) | \
34 		 ((lvl1_state) << (PSTATE_ID_SHIFT + PSTATE_WIDTH)) | \
35 		 ((lvl0_state) << (PSTATE_ID_SHIFT)) | \
36 		 ((pwr_lvl) << PSTATE_PWR_LVL_SHIFT) | \
37 		 ((type) << PSTATE_TYPE_SHIFT))
38 
39 /*
40  * The table storing the valid idle power states. Ensure that the
41  * array entries are populated in ascending order of state-id to
42  * enable us to use binary search during power state validation.
43  * The table must be terminated by a NULL entry.
44  */
45 const unsigned int hikey960_pwr_idle_states[] = {
46 	/* State-id - 0x001 */
47 	MAKE_PWRSTATE(PLAT_MAX_RUN_STATE, PLAT_MAX_RUN_STATE,
48 		      PLAT_MAX_STB_STATE, MPIDR_AFFLVL0, PSTATE_TYPE_STANDBY),
49 	/* State-id - 0x002 */
50 	MAKE_PWRSTATE(PLAT_MAX_RUN_STATE, PLAT_MAX_RUN_STATE,
51 		      PLAT_MAX_RET_STATE, MPIDR_AFFLVL0, PSTATE_TYPE_STANDBY),
52 	/* State-id - 0x003 */
53 	MAKE_PWRSTATE(PLAT_MAX_RUN_STATE, PLAT_MAX_RUN_STATE,
54 		      PLAT_MAX_OFF_STATE, MPIDR_AFFLVL0, PSTATE_TYPE_POWERDOWN),
55 	/* State-id - 0x033 */
56 	MAKE_PWRSTATE(PLAT_MAX_RUN_STATE, PLAT_MAX_OFF_STATE,
57 		      PLAT_MAX_OFF_STATE, MPIDR_AFFLVL1, PSTATE_TYPE_POWERDOWN),
58 	0,
59 };
60 
61 #define DMAC_GLB_REG_SEC	0x694
62 #define AXI_CONF_BASE		0x820
63 
64 static uintptr_t hikey960_sec_entrypoint;
65 
66 static void hikey960_pwr_domain_standby(plat_local_state_t cpu_state)
67 {
68 	unsigned long scr;
69 	unsigned int val = 0;
70 
71 	assert(cpu_state == PLAT_MAX_STB_STATE ||
72 	       cpu_state == PLAT_MAX_RET_STATE);
73 
74 	scr = read_scr_el3();
75 
76 	/* Enable Physical IRQ and FIQ to wake the CPU*/
77 	write_scr_el3(scr | SCR_IRQ_BIT | SCR_FIQ_BIT);
78 
79 	if (cpu_state == PLAT_MAX_RET_STATE)
80 		set_retention_ticks(val);
81 
82 	wfi();
83 
84 	if (cpu_state == PLAT_MAX_RET_STATE)
85 		clr_retention_ticks(val);
86 
87 	/*
88 	 * Restore SCR to the original value, synchronisazion of
89 	 * scr_el3 is done by eret while el3_exit to save some
90 	 * execution cycles.
91 	 */
92 	write_scr_el3(scr);
93 }
94 
95 static int hikey960_pwr_domain_on(u_register_t mpidr)
96 {
97 	unsigned int core = mpidr & MPIDR_CPU_MASK;
98 	unsigned int cluster =
99 		(mpidr & MPIDR_CLUSTER_MASK) >> MPIDR_AFFINITY_BITS;
100 	int cluster_stat = cluster_is_powered_on(cluster);
101 
102 	hisi_set_cpu_boot_flag(cluster, core);
103 
104 	mmio_write_32(CRG_REG_BASE + CRG_RVBAR(cluster, core),
105 		      hikey960_sec_entrypoint >> 2);
106 
107 	if (cluster_stat)
108 		hisi_powerup_core(cluster, core);
109 	else
110 		hisi_powerup_cluster(cluster, core);
111 
112 	return PSCI_E_SUCCESS;
113 }
114 
115 static void
116 hikey960_pwr_domain_on_finish(const psci_power_state_t *target_state)
117 {
118 	if (CLUSTER_PWR_STATE(target_state) == PLAT_MAX_OFF_STATE)
119 		cci_enable_snoop_dvm_reqs(MPIDR_AFFLVL1_VAL(read_mpidr_el1()));
120 
121 	gicv2_pcpu_distif_init();
122 	gicv2_cpuif_enable();
123 }
124 
125 void hikey960_pwr_domain_off(const psci_power_state_t *target_state)
126 {
127 	unsigned long mpidr = read_mpidr_el1();
128 	unsigned int core = mpidr & MPIDR_CPU_MASK;
129 	unsigned int cluster =
130 		(mpidr & MPIDR_CLUSTER_MASK) >> MPIDR_AFFINITY_BITS;
131 
132 	clr_ex();
133 	isb();
134 	dsbsy();
135 
136 	gicv2_cpuif_disable();
137 
138 	hisi_clear_cpu_boot_flag(cluster, core);
139 	hisi_powerdn_core(cluster, core);
140 
141 	/* check if any core is powered up */
142 	if (hisi_test_cpu_down(cluster, core)) {
143 
144 		cci_disable_snoop_dvm_reqs(MPIDR_AFFLVL1_VAL(read_mpidr_el1()));
145 
146 		isb();
147 		dsbsy();
148 
149 		hisi_powerdn_cluster(cluster, core);
150 	}
151 }
152 
153 static void __dead2 hikey960_system_reset(void)
154 {
155 	mmio_write_32(SCTRL_SCPEREN1_REG,
156 		      SCPEREN1_WAIT_DDR_SELFREFRESH_DONE_BYPASS);
157 	mmio_write_32(SCTRL_SCSYSSTAT_REG, 0xdeadbeef);
158 	panic();
159 }
160 
161 int hikey960_validate_power_state(unsigned int power_state,
162 			       psci_power_state_t *req_state)
163 {
164 	unsigned int state_id;
165 	int i;
166 
167 	assert(req_state);
168 
169 	/*
170 	 *  Currently we are using a linear search for finding the matching
171 	 *  entry in the idle power state array. This can be made a binary
172 	 *  search if the number of entries justify the additional complexity.
173 	 */
174 	for (i = 0; !!hikey960_pwr_idle_states[i]; i++) {
175 		if (power_state == hikey960_pwr_idle_states[i])
176 			break;
177 	}
178 
179 	/* Return error if entry not found in the idle state array */
180 	if (!hikey960_pwr_idle_states[i])
181 		return PSCI_E_INVALID_PARAMS;
182 
183 	i = 0;
184 	state_id = psci_get_pstate_id(power_state);
185 
186 	/* Parse the State ID and populate the state info parameter */
187 	while (state_id) {
188 		req_state->pwr_domain_state[i++] = state_id & PSTATE_MASK;
189 		state_id >>= PSTATE_WIDTH;
190 	}
191 
192 	return PSCI_E_SUCCESS;
193 }
194 
195 static int hikey960_validate_ns_entrypoint(uintptr_t entrypoint)
196 {
197 	/*
198 	 * Check if the non secure entrypoint lies within the non
199 	 * secure DRAM.
200 	 */
201 	if ((entrypoint > DDR_BASE) && (entrypoint < (DDR_BASE + DDR_SIZE)))
202 		return PSCI_E_SUCCESS;
203 
204 	return PSCI_E_INVALID_ADDRESS;
205 }
206 
207 static void hikey960_pwr_domain_suspend(const psci_power_state_t *target_state)
208 {
209 	u_register_t mpidr = read_mpidr_el1();
210 	unsigned int core = mpidr & MPIDR_CPU_MASK;
211 	unsigned int cluster =
212 		(mpidr & MPIDR_CLUSTER_MASK) >> MPIDR_AFFINITY_BITS;
213 
214 	if (CORE_PWR_STATE(target_state) != PLAT_MAX_OFF_STATE)
215 		return;
216 
217 	if (CORE_PWR_STATE(target_state) == PLAT_MAX_OFF_STATE) {
218 		clr_ex();
219 		isb();
220 		dsbsy();
221 
222 		gicv2_cpuif_disable();
223 
224 		hisi_cpuidle_lock(cluster, core);
225 		hisi_set_cpuidle_flag(cluster, core);
226 		hisi_cpuidle_unlock(cluster, core);
227 
228 		mmio_write_32(CRG_REG_BASE + CRG_RVBAR(cluster, core),
229 		      hikey960_sec_entrypoint >> 2);
230 
231 		hisi_enter_core_idle(cluster, core);
232 	}
233 
234 	/* Perform the common cluster specific operations */
235 	if (CLUSTER_PWR_STATE(target_state) == PLAT_MAX_OFF_STATE) {
236 		hisi_cpuidle_lock(cluster, core);
237 		hisi_disable_pdc(cluster);
238 
239 		/* check if any core is powered up */
240 		if (hisi_test_pwrdn_allcores(cluster, core)) {
241 
242 			cci_disable_snoop_dvm_reqs(MPIDR_AFFLVL1_VAL(mpidr));
243 
244 			isb();
245 			dsbsy();
246 
247 			/* mask the pdc wakeup irq, then
248 			 * enable pdc to power down the core
249 			 */
250 			hisi_pdc_mask_cluster_wakeirq(cluster);
251 			hisi_enable_pdc(cluster);
252 
253 			hisi_cpuidle_unlock(cluster, core);
254 
255 			/* check the SR flag bit to determine
256 			 * CLUSTER_IDLE_IPC or AP_SR_IPC to send
257 			 */
258 			if (hisi_test_ap_suspend_flag(cluster))
259 				hisi_enter_ap_suspend(cluster, core);
260 			else
261 				hisi_enter_cluster_idle(cluster, core);
262 		} else {
263 			/* enable pdc */
264 			hisi_enable_pdc(cluster);
265 			hisi_cpuidle_unlock(cluster, core);
266 		}
267 	}
268 }
269 
270 static void hikey960_sr_dma_reinit(void)
271 {
272 	unsigned int ctr = 0;
273 
274 	mmio_write_32(DMAC_BASE + DMAC_GLB_REG_SEC, 0x3);
275 
276 	/* 1~15 channel is set non_secure */
277 	for (ctr = 1; ctr <= 15; ctr++)
278 		mmio_write_32(DMAC_BASE + AXI_CONF_BASE + ctr * (0x40),
279 			      (1 << 6) | (1 << 18));
280 }
281 
282 static void
283 hikey960_pwr_domain_suspend_finish(const psci_power_state_t *target_state)
284 {
285 	unsigned long mpidr = read_mpidr_el1();
286 	unsigned int core = mpidr & MPIDR_CPU_MASK;
287 	unsigned int cluster =
288 		(mpidr & MPIDR_CLUSTER_MASK) >> MPIDR_AFFINITY_BITS;
289 
290 	/* Nothing to be done on waking up from retention from CPU level */
291 	if (CORE_PWR_STATE(target_state) != PLAT_MAX_OFF_STATE)
292 		return;
293 
294 	hisi_cpuidle_lock(cluster, core);
295 	hisi_clear_cpuidle_flag(cluster, core);
296 	hisi_cpuidle_unlock(cluster, core);
297 
298 	if (hisi_test_ap_suspend_flag(cluster)) {
299 		hikey960_sr_dma_reinit();
300 		gicv2_cpuif_enable();
301 		console_init(PL011_UART6_BASE, PL011_UART_CLK_IN_HZ,
302 			     PL011_BAUDRATE);
303 	}
304 
305 	hikey960_pwr_domain_on_finish(target_state);
306 }
307 
308 static void hikey960_get_sys_suspend_power_state(psci_power_state_t *req_state)
309 {
310 	int i;
311 
312 	for (i = MPIDR_AFFLVL0; i <= PLAT_MAX_PWR_LVL; i++)
313 		req_state->pwr_domain_state[i] = PLAT_MAX_OFF_STATE;
314 }
315 
316 static const plat_psci_ops_t hikey960_psci_ops = {
317 	.cpu_standby			= hikey960_pwr_domain_standby,
318 	.pwr_domain_on			= hikey960_pwr_domain_on,
319 	.pwr_domain_on_finish		= hikey960_pwr_domain_on_finish,
320 	.pwr_domain_off			= hikey960_pwr_domain_off,
321 	.pwr_domain_suspend		= hikey960_pwr_domain_suspend,
322 	.pwr_domain_suspend_finish	= hikey960_pwr_domain_suspend_finish,
323 	.system_off			= NULL,
324 	.system_reset			= hikey960_system_reset,
325 	.validate_power_state		= hikey960_validate_power_state,
326 	.validate_ns_entrypoint		= hikey960_validate_ns_entrypoint,
327 	.get_sys_suspend_power_state	= hikey960_get_sys_suspend_power_state,
328 };
329 
330 int plat_setup_psci_ops(uintptr_t sec_entrypoint,
331 			const plat_psci_ops_t **psci_ops)
332 {
333 	hikey960_sec_entrypoint = sec_entrypoint;
334 
335 	INFO("%s: sec_entrypoint=0x%lx\n", __func__,
336 	     (unsigned long)hikey960_sec_entrypoint);
337 
338 	/*
339 	 * Initialize PSCI ops struct
340 	 */
341 	*psci_ops = &hikey960_psci_ops;
342 	return 0;
343 }
344