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