xref: /rk3399_ARM-atf/plat/imx/imx8ulp/imx8ulp_psci.c (revision 891c547e9658c1827559d8da5e3b87de5a2e9f6a)
1 /*
2  * Copyright 2021-2024 NXP
3  *
4  * SPDX-License-Identifier: BSD-3-Clause
5  */
6 
7 #include <stdbool.h>
8 
9 #include <arch.h>
10 #include <arch_helpers.h>
11 #include <common/debug.h>
12 #include <drivers/arm/gicv3.h>
13 #include <lib/mmio.h>
14 #include <lib/psci/psci.h>
15 
16 #include <plat_imx8.h>
17 #include <upower_api.h>
18 
19 extern void cgc1_save(void);
20 extern void cgc1_restore(void);
21 extern void imx_apd_ctx_save(unsigned int cpu);
22 extern void imx_apd_ctx_restore(unsigned int cpu);
23 extern void usb_wakeup_enable(bool enable);
24 
25 static uintptr_t secure_entrypoint;
26 
27 #define CORE_PWR_STATE(state) ((state)->pwr_domain_state[MPIDR_AFFLVL0])
28 #define CLUSTER_PWR_STATE(state) ((state)->pwr_domain_state[MPIDR_AFFLVL1])
29 #define SYSTEM_PWR_STATE(state) ((state)->pwr_domain_state[PLAT_MAX_PWR_LVL])
30 
31 #define RVBARADDRx(c)		(IMX_SIM1_BASE + 0x5c + 0x4 * (c))
32 #define WKPUx(c)		(IMX_SIM1_BASE + 0x3c + 0x4 * (c))
33 #define AD_COREx_LPMODE(c)	(IMX_CMC1_BASE + 0x50 + 0x4 * (c))
34 
35 #define PMIC_CFG(v, m, msk)		\
36 	{				\
37 		.volt = (v),		\
38 		.mode = (m),		\
39 		.mode_msk = (msk),	\
40 	}
41 
42 #define PAD_CFG(c, r, t)		\
43 	{				\
44 		.pad_close = (c),	\
45 		.pad_reset = (r),	\
46 		.pad_tqsleep = (t)	\
47 	}
48 
49 #define BIAS_CFG(m, n, p, mbias)	\
50 	{				\
51 		.dombias_cfg = {	\
52 			.mode = (m),	\
53 			.rbbn = (n),	\
54 			.rbbp = (p),	\
55 		},			\
56 		.membias_cfg = {mbias},	\
57 	}
58 
59 #define SWT_BOARD(swt_on, msk)	\
60 	{			\
61 		.on = (swt_on),	\
62 		.mask = (msk),	\
63 	}
64 
65 #define SWT_MEM(a, p, m)	\
66 	{			\
67 		.array = (a),	\
68 		.perif = (p),	\
69 		.mask = (m),	\
70 	}
71 
72 extern void upower_wait_resp(void);
73 
74 static int imx_pwr_set_cpu_entry(unsigned int cpu, unsigned int entry)
75 {
76 	mmio_write_32(RVBARADDRx(cpu), entry);
77 
78 	/* set update bit */
79 	mmio_write_32(IMX_SIM1_BASE + 0x8, mmio_read_32(IMX_SIM1_BASE + 0x8) | BIT_32(24 + cpu));
80 	/* wait for ack */
81 	while (!(mmio_read_32(IMX_SIM1_BASE + 0x8) & BIT_32(26 + cpu))) {
82 	}
83 
84 	/* clear update bit */
85 	mmio_write_32(IMX_SIM1_BASE + 0x8, mmio_read_32(IMX_SIM1_BASE + 0x8) & ~BIT_32(24 + cpu));
86 	/* clear ack bit */
87 	mmio_write_32(IMX_SIM1_BASE + 0x8, mmio_read_32(IMX_SIM1_BASE + 0x8) | BIT_32(26 + cpu));
88 
89 	return 0;
90 }
91 
92 int imx_pwr_domain_on(u_register_t mpidr)
93 {
94 	unsigned int cpu = MPIDR_AFFLVL0_VAL(mpidr);
95 
96 	imx_pwr_set_cpu_entry(cpu, secure_entrypoint);
97 
98 	mmio_write_32(IMX_CMC1_BASE + 0x18, 0x3f);
99 	mmio_write_32(IMX_CMC1_BASE + 0x50 + 0x4 * cpu, 0);
100 
101 	/* enable wku wakeup for idle */
102 	mmio_write_32(IMX_SIM1_BASE + 0x3c + 0x4 * cpu, 0xffffffff);
103 
104 	return PSCI_E_SUCCESS;
105 }
106 
107 void imx_pwr_domain_on_finish(const psci_power_state_t *target_state)
108 {
109 	imx_pwr_set_cpu_entry(0, IMX_ROM_ENTRY);
110 	plat_gic_pcpu_init();
111 	plat_gic_cpuif_enable();
112 }
113 
114 int imx_validate_ns_entrypoint(uintptr_t ns_entrypoint)
115 {
116 	return PSCI_E_SUCCESS;
117 }
118 
119 void imx_pwr_domain_off(const psci_power_state_t *target_state)
120 {
121 	unsigned int cpu = MPIDR_AFFLVL0_VAL(read_mpidr_el1());
122 
123 	plat_gic_cpuif_disable();
124 
125 	/* disable wakeup */
126 	mmio_write_32(WKPUx(cpu), 0);
127 
128 	/* set core power mode to PD */
129 	mmio_write_32(AD_COREx_LPMODE(cpu), 0x3);
130 }
131 
132 /* APD power mode config */
133 ps_apd_pwr_mode_cfgs_t apd_pwr_mode_cfgs = {
134 	[DPD_PWR_MODE] = {
135 		.swt_board_offs = 0x180,
136 		.swt_mem_offs = 0x188,
137 		.pmic_cfg = PMIC_CFG(0x23, 0xa, 0x2),
138 		.pad_cfg = PAD_CFG(0xc, 0x0, 0x01e80a02),
139 		.bias_cfg = BIAS_CFG(0x0, 0x2, 0x2, 0x0),
140 	},
141 
142 	/* PD */
143 	[PD_PWR_MODE] = {
144 		.swt_board_offs = 0x170,
145 		.swt_mem_offs = 0x178,
146 		.pmic_cfg = PMIC_CFG(0x23, 0x2, 0x2),
147 		.pad_cfg = PAD_CFG(0x0, 0x0, 0x01e80a00),
148 		.bias_cfg = BIAS_CFG(0x0, 0x2, 0x2, 0x0),
149 	},
150 
151 	[ADMA_PWR_MODE] = {
152 		.swt_board_offs = 0x120,
153 		.swt_mem_offs = 0x128,
154 		.pmic_cfg = PMIC_CFG(0x23, 0x0, 0x2),
155 		.pad_cfg = PAD_CFG(0x0, 0x0, 0x0deb7a00),
156 		.bias_cfg = BIAS_CFG(0x0, 0x2, 0x2, 0x0),
157 	},
158 
159 	[ACT_PWR_MODE] = {
160 		.swt_board_offs = 0x110,
161 		.swt_mem_offs = 0x118,
162 		.pmic_cfg = PMIC_CFG(0x23, 0x2, 0x2),
163 		.pad_cfg = PAD_CFG(0x0, 0x0, 0x0deb7a00),
164 		.bias_cfg = BIAS_CFG(0x0, 0x2, 0x2, 0x0),
165 	},
166 };
167 
168 /* APD power switch config */
169 ps_apd_swt_cfgs_t apd_swt_cfgs = {
170 	[DPD_PWR_MODE] = {
171 		.swt_board[0] = SWT_BOARD(0x00060003, 0x7c),
172 		.swt_mem[0] = SWT_MEM(0x0, 0x0, 0x1ffff),
173 		.swt_mem[1] = SWT_MEM(0x003fffff, 0x003fffff, 0x0),
174 	},
175 
176 	[PD_PWR_MODE] = {
177 		.swt_board[0] = SWT_BOARD(0x00060003, 0x00001e74),
178 		.swt_mem[0] = SWT_MEM(0x00010c00, 0x0, 0x1ffff),
179 		.swt_mem[1] = SWT_MEM(0x003fffff, 0x003f0000, 0x0),
180 	},
181 
182 	[ADMA_PWR_MODE] = {
183 		.swt_board[0] = SWT_BOARD(0x0006ff77, 0x0006ff7c),
184 		.swt_mem[0] = SWT_MEM(0x0001fffd, 0x0001fffd, 0x1ffff),
185 		.swt_mem[1] = SWT_MEM(0x003fffff, 0x003fffff, 0x0),
186 	},
187 
188 	[ACT_PWR_MODE] = {
189 		.swt_board[0] = SWT_BOARD(0x0006ff77, 0x0000ff7c),
190 		.swt_mem[0] = SWT_MEM(0x0001fffd, 0x0001fffd, 0x1ffff),
191 		.swt_mem[1] = SWT_MEM(0x003fffff, 0x003fffff, 0x0),
192 	},
193 };
194 
195 struct ps_pwr_mode_cfg_t *pwr_sys_cfg = (struct ps_pwr_mode_cfg_t *)UPWR_DRAM_SHARED_BASE_ADDR;
196 
197 void imx_set_pwr_mode_cfg(abs_pwr_mode_t mode)
198 {
199 	if (mode >= NUM_PWR_MODES) {
200 		return;
201 	}
202 
203 	/* apd power mode config */
204 	memcpy(&pwr_sys_cfg->ps_apd_pwr_mode_cfg[mode], &apd_pwr_mode_cfgs[mode],
205 		 sizeof(struct ps_apd_pwr_mode_cfg_t));
206 
207 	/* apd power switch config */
208 	memcpy(&pwr_sys_cfg->ps_apd_swt_cfg[mode], &apd_swt_cfgs[mode], sizeof(swt_config_t));
209 }
210 
211 void imx_domain_suspend(const psci_power_state_t *target_state)
212 {
213 	unsigned int cpu = MPIDR_AFFLVL0_VAL(read_mpidr_el1());
214 
215 	if (is_local_state_off(CORE_PWR_STATE(target_state))) {
216 		plat_gic_cpuif_disable();
217 		imx_pwr_set_cpu_entry(cpu, secure_entrypoint);
218 		/* core put into power down */
219 		mmio_write_32(IMX_CMC1_BASE + 0x50 + 0x4 * cpu, 0x3);
220 		/* FIXME config wakeup interrupt in WKPU */
221 		mmio_write_32(IMX_SIM1_BASE + 0x3c + 0x4 * cpu, 0x7fffffe3);
222 	} else {
223 		/* for core standby/retention mode */
224 		mmio_write_32(IMX_CMC1_BASE + 0x50 + 0x4 * cpu, 0x1);
225 		mmio_write_32(IMX_SIM1_BASE + 0x3c + 0x4 * cpu, 0x7fffffe3);
226 		dsb();
227 		write_scr_el3(read_scr_el3() | SCR_FIQ_BIT);
228 		isb();
229 	}
230 
231 	if (is_local_state_retn(CLUSTER_PWR_STATE(target_state))) {
232 		/*
233 		 * just for sleep mode for now, need to update to
234 		 * support more modes, same for suspend finish call back.
235 		 */
236 		mmio_write_32(IMX_CMC1_BASE + 0x10, 0x1);
237 		mmio_write_32(IMX_CMC1_BASE + 0x20, 0x1);
238 
239 	} else if (is_local_state_off(CLUSTER_PWR_STATE(target_state))) {
240 		/*
241 		 * for cluster off state, put cluster into power down mode,
242 		 * config the cluster clock to be off.
243 		 */
244 		mmio_write_32(IMX_CMC1_BASE + 0x10, 0x7);
245 		mmio_write_32(IMX_CMC1_BASE + 0x20, 0xf);
246 	}
247 
248 	if (is_local_state_off(SYSTEM_PWR_STATE(target_state))) {
249 		/*
250 		 * low power mode config info used by upower
251 		 * to do low power mode transition.
252 		 */
253 		imx_set_pwr_mode_cfg(ADMA_PWR_MODE);
254 		imx_set_pwr_mode_cfg(ACT_PWR_MODE);
255 		imx_set_pwr_mode_cfg(PD_PWR_MODE);
256 
257 		/* clear the upower wakeup */
258 		upwr_xcp_set_rtd_apd_llwu(APD_DOMAIN, 0, NULL);
259 		upower_wait_resp();
260 
261 		/* enable the USB wakeup */
262 		usb_wakeup_enable(true);
263 
264 		/* config the WUU to enabled the wakeup source */
265 		mmio_write_32(IMX_PCC3_BASE + 0x98, 0xc0800000);
266 
267 		/* !!! clear all the pad wakeup pending event */
268 		mmio_write_32(IMX_WUU1_BASE + 0x20, 0xffffffff);
269 
270 		/* enable upower usb phy wakeup by default */
271 		mmio_setbits_32(IMX_WUU1_BASE + 0x18, BIT(4) | BIT(1) | BIT(0));
272 
273 		/* enabled all pad wakeup by default */
274 		mmio_write_32(IMX_WUU1_BASE + 0x8, 0xffffffff);
275 
276 		/* save the AD domain context before entering PD mode */
277 		imx_apd_ctx_save(cpu);
278 	}
279 }
280 
281 extern void imx8ulp_init_scmi_server(void);
282 void imx_domain_suspend_finish(const psci_power_state_t *target_state)
283 {
284 	unsigned int cpu = MPIDR_AFFLVL0_VAL(read_mpidr_el1());
285 
286 	if (is_local_state_off(SYSTEM_PWR_STATE(target_state))) {
287 		/* restore the ap domain context */
288 		imx_apd_ctx_restore(cpu);
289 
290 		/* clear the upower wakeup */
291 		upwr_xcp_set_rtd_apd_llwu(APD_DOMAIN, 0, NULL);
292 		upower_wait_resp();
293 
294 		/* disable all pad wakeup */
295 		mmio_write_32(IMX_WUU1_BASE + 0x8, 0x0);
296 
297 		/* clear all the pad wakeup pending event */
298 		mmio_write_32(IMX_WUU1_BASE + 0x20, 0xffffffff);
299 
300 		/*
301 		 * disable the usb wakeup after resume to make sure the pending
302 		 * usb wakeup in WUU can be cleared successfully, otherwise,
303 		 * APD will resume failed in next PD mode.
304 		 */
305 		usb_wakeup_enable(false);
306 
307 		/* re-init the SCMI channel */
308 		imx8ulp_init_scmi_server();
309 	}
310 
311 	/* clear cluster's LPM setting. */
312 	mmio_write_32(IMX_CMC1_BASE + 0x20, 0x0);
313 	mmio_write_32(IMX_CMC1_BASE + 0x10, 0x0);
314 
315 	/* clear core's LPM setting */
316 	mmio_write_32(IMX_CMC1_BASE + 0x50 + 0x4 * cpu, 0x0);
317 	mmio_write_32(IMX_SIM1_BASE + 0x3c + 0x4 * cpu, 0x0);
318 
319 	if (is_local_state_off(CORE_PWR_STATE(target_state))) {
320 		imx_pwr_set_cpu_entry(0, IMX_ROM_ENTRY);
321 		plat_gic_cpuif_enable();
322 	} else {
323 		dsb();
324 		write_scr_el3(read_scr_el3() & (~SCR_FIQ_BIT));
325 		isb();
326 	}
327 }
328 
329 void __dead2 imx8ulp_pwr_domain_pwr_down_wfi(const psci_power_state_t *target_state)
330 {
331 	while (1) {
332 		wfi();
333 	}
334 }
335 
336 void __dead2 imx8ulp_system_reset(void)
337 {
338 	imx_pwr_set_cpu_entry(0, IMX_ROM_ENTRY);
339 
340 	/* Write invalid command to WDOG CNT to trigger reset */
341 	mmio_write_32(IMX_WDOG3_BASE + 0x4, 0x12345678);
342 
343 	while (true) {
344 		wfi();
345 	}
346 }
347 
348 int imx_validate_power_state(unsigned int power_state,
349 			 psci_power_state_t *req_state)
350 {
351 	int pwr_lvl = psci_get_pstate_pwrlvl(power_state);
352 	int pwr_type = psci_get_pstate_type(power_state);
353 
354 	if (pwr_lvl > PLAT_MAX_PWR_LVL) {
355 		return PSCI_E_INVALID_PARAMS;
356 	}
357 
358 	if (pwr_type == PSTATE_TYPE_STANDBY) {
359 		CORE_PWR_STATE(req_state) = PLAT_MAX_RET_STATE;
360 		CLUSTER_PWR_STATE(req_state) = PLAT_MAX_RET_STATE;
361 	}
362 
363 	/* No power down state support */
364 	if (pwr_type == PSTATE_TYPE_POWERDOWN) {
365 		return PSCI_E_INVALID_PARAMS;
366 	}
367 
368 	return PSCI_E_SUCCESS;
369 }
370 
371 void imx_get_sys_suspend_power_state(psci_power_state_t *req_state)
372 {
373 	unsigned int i;
374 
375 	for (i = IMX_PWR_LVL0; i <= PLAT_MAX_PWR_LVL; i++) {
376 		req_state->pwr_domain_state[i] = PLAT_POWER_DOWN_OFF_STATE;
377 	}
378 }
379 
380 void __dead2 imx_system_off(void)
381 {
382 	unsigned int i;
383 
384 	/* config the all the core into OFF mode and IRQ masked. */
385 	for (i = 0U; i < PLATFORM_CORE_COUNT; i++) {
386 		/* disable wakeup from wkpu */
387 		mmio_write_32(WKPUx(i), 0x0);
388 
389 		/* reset the core reset entry to 0x1000 */
390 		imx_pwr_set_cpu_entry(i, 0x1000);
391 
392 		/* config the core power mode to off */
393 		mmio_write_32(AD_COREx_LPMODE(i), 0x3);
394 	}
395 
396 	plat_gic_cpuif_disable();
397 
398 	/* Config the power mode info for entering DPD mode and ACT mode */
399 	imx_set_pwr_mode_cfg(ADMA_PWR_MODE);
400 	imx_set_pwr_mode_cfg(ACT_PWR_MODE);
401 	imx_set_pwr_mode_cfg(DPD_PWR_MODE);
402 
403 	/* Set the APD domain into DPD mode */
404 	mmio_write_32(IMX_CMC1_BASE + 0x10, 0x7);
405 	mmio_write_32(IMX_CMC1_BASE + 0x20, 0x1f);
406 
407 	/* make sure no pending upower wakeup */
408 	upwr_xcp_set_rtd_apd_llwu(APD_DOMAIN, 0, NULL);
409 	upower_wait_resp();
410 
411 	/* enable the upower wakeup from wuu, act as APD boot up method  */
412 	mmio_write_32(IMX_PCC3_BASE + 0x98, 0xc0800000);
413 	mmio_setbits_32(IMX_WUU1_BASE + 0x18, BIT(4));
414 
415 	/* make sure no pad wakeup event is pending */
416 	mmio_write_32(IMX_WUU1_BASE + 0x20, 0xffffffff);
417 
418 	wfi();
419 
420 	ERROR("power off failed.\n");
421 	panic();
422 }
423 
424 static const plat_psci_ops_t imx_plat_psci_ops = {
425 	.pwr_domain_on = imx_pwr_domain_on,
426 	.pwr_domain_on_finish = imx_pwr_domain_on_finish,
427 	.validate_ns_entrypoint = imx_validate_ns_entrypoint,
428 	.system_off = imx_system_off,
429 	.system_reset = imx8ulp_system_reset,
430 	.pwr_domain_off = imx_pwr_domain_off,
431 	.pwr_domain_suspend = imx_domain_suspend,
432 	.pwr_domain_suspend_finish = imx_domain_suspend_finish,
433 	.get_sys_suspend_power_state = imx_get_sys_suspend_power_state,
434 	.validate_power_state = imx_validate_power_state,
435 	.pwr_domain_pwr_down_wfi = imx8ulp_pwr_domain_pwr_down_wfi,
436 };
437 
438 int plat_setup_psci_ops(uintptr_t sec_entrypoint,
439 			const plat_psci_ops_t **psci_ops)
440 {
441 	secure_entrypoint = sec_entrypoint;
442 	imx_pwr_set_cpu_entry(0, sec_entrypoint);
443 	*psci_ops = &imx_plat_psci_ops;
444 
445 	mmio_write_32(IMX_CMC1_BASE + 0x18, 0x3f);
446 	mmio_write_32(IMX_SIM1_BASE + 0x3c, 0xffffffff);
447 
448 	return 0;
449 }
450