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