blob: 78078d5f882c2cbabff8a1bcd9d54279d26a0080 [file] [log] [blame]
Jacky Baifcd41e82020-07-02 14:39:58 +08001/*
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>
Jacky Baidaa44782023-09-18 22:08:52 +080017#include <upower_api.h>
Jacky Baifcd41e82020-07-02 14:39:58 +080018
Jacky Bai478af8d2021-06-25 09:47:46 +080019extern void cgc1_save(void);
20extern void cgc1_restore(void);
21extern void imx_apd_ctx_save(unsigned int cpu);
22extern void imx_apd_ctx_restore(unsigned int cpu);
23extern void usb_wakeup_enable(bool enable);
Jacky Bai36af80c2021-10-20 11:25:30 +080024extern void upower_wait_resp(void);
25extern bool is_lpav_owned_by_apd(void);
26extern void apd_io_pad_off(void);
27extern int upower_pmic_i2c_read(uint32_t reg_addr, uint32_t *reg_val);
Jacky Bai478af8d2021-06-25 09:47:46 +080028
Jacky Baifcd41e82020-07-02 14:39:58 +080029static 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
Jacky Baidaa44782023-09-18 22:08:52 +080039#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
Jacky Baifcd41e82020-07-02 14:39:58 +080076static 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
94int 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
109void 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
116int imx_validate_ns_entrypoint(uintptr_t ns_entrypoint)
117{
118 return PSCI_E_SUCCESS;
119}
120
121void 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
Jacky Baidaa44782023-09-18 22:08:52 +0800130 /* set core power mode to PD */
Jacky Baifcd41e82020-07-02 14:39:58 +0800131 mmio_write_32(AD_COREx_LPMODE(cpu), 0x3);
132}
Jacky Bai478af8d2021-06-25 09:47:46 +0800133
Jacky Baidaa44782023-09-18 22:08:52 +0800134/* APD power mode config */
135ps_apd_pwr_mode_cfgs_t apd_pwr_mode_cfgs = {
Jacky Bai891c5472023-09-18 21:53:15 +0800136 [DPD_PWR_MODE] = {
137 .swt_board_offs = 0x180,
138 .swt_mem_offs = 0x188,
Jacky Bai36af80c2021-10-20 11:25:30 +0800139 .pmic_cfg = PMIC_CFG(0x23, 0x0, 0x2),
140 .pad_cfg = PAD_CFG(0x0, 0xc, 0x01e80a02),
Jacky Bai891c5472023-09-18 21:53:15 +0800141 .bias_cfg = BIAS_CFG(0x0, 0x2, 0x2, 0x0),
142 },
143
Jacky Bai478af8d2021-06-25 09:47:46 +0800144 /* PD */
145 [PD_PWR_MODE] = {
146 .swt_board_offs = 0x170,
147 .swt_mem_offs = 0x178,
Jacky Bai36af80c2021-10-20 11:25:30 +0800148 .pmic_cfg = PMIC_CFG(0x23, 0x0, 0x2),
149 .pad_cfg = PAD_CFG(0x0, 0xc, 0x01e80a00),
Jacky Bai478af8d2021-06-25 09:47:46 +0800150 .bias_cfg = BIAS_CFG(0x0, 0x2, 0x2, 0x0),
151 },
152
Jacky Baidaa44782023-09-18 22:08:52 +0800153 [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),
Jacky Bai36af80c2021-10-20 11:25:30 +0800158 .bias_cfg = BIAS_CFG(0x2, 0x2, 0x2, 0x0),
Jacky Baidaa44782023-09-18 22:08:52 +0800159 },
160
161 [ACT_PWR_MODE] = {
162 .swt_board_offs = 0x110,
163 .swt_mem_offs = 0x118,
Jacky Bai36af80c2021-10-20 11:25:30 +0800164 .pmic_cfg = PMIC_CFG(0x23, 0x0, 0x2),
Jacky Baidaa44782023-09-18 22:08:52 +0800165 .pad_cfg = PAD_CFG(0x0, 0x0, 0x0deb7a00),
Jacky Bai36af80c2021-10-20 11:25:30 +0800166 .bias_cfg = BIAS_CFG(0x2, 0x2, 0x2, 0x0),
Jacky Baidaa44782023-09-18 22:08:52 +0800167 },
168};
169
170/* APD power switch config */
171ps_apd_swt_cfgs_t apd_swt_cfgs = {
Jacky Bai891c5472023-09-18 21:53:15 +0800172 [DPD_PWR_MODE] = {
Jacky Bai36af80c2021-10-20 11:25:30 +0800173 .swt_board[0] = SWT_BOARD(0x0, 0x1fffc),
Jacky Bai891c5472023-09-18 21:53:15 +0800174 .swt_mem[0] = SWT_MEM(0x0, 0x0, 0x1ffff),
175 .swt_mem[1] = SWT_MEM(0x003fffff, 0x003fffff, 0x0),
176 },
177
Jacky Bai478af8d2021-06-25 09:47:46 +0800178 [PD_PWR_MODE] = {
Jacky Bai36af80c2021-10-20 11:25:30 +0800179 .swt_board[0] = SWT_BOARD(0x0, 0x00001fffc),
Jacky Bai478af8d2021-06-25 09:47:46 +0800180 .swt_mem[0] = SWT_MEM(0x00010c00, 0x0, 0x1ffff),
181 .swt_mem[1] = SWT_MEM(0x003fffff, 0x003f0000, 0x0),
182 },
183
Jacky Baidaa44782023-09-18 22:08:52 +0800184 [ADMA_PWR_MODE] = {
Jacky Bai36af80c2021-10-20 11:25:30 +0800185 .swt_board[0] = SWT_BOARD(0x15f74, 0x15f74),
Jacky Bai478af8d2021-06-25 09:47:46 +0800186 .swt_mem[0] = SWT_MEM(0x0001fffd, 0x0001fffd, 0x1ffff),
187 .swt_mem[1] = SWT_MEM(0x003fffff, 0x003fffff, 0x0),
Jacky Baidaa44782023-09-18 22:08:52 +0800188 },
189
190 [ACT_PWR_MODE] = {
Jacky Bai36af80c2021-10-20 11:25:30 +0800191 .swt_board[0] = SWT_BOARD(0x15f74, 0x15f74),
Jacky Bai478af8d2021-06-25 09:47:46 +0800192 .swt_mem[0] = SWT_MEM(0x0001fffd, 0x0001fffd, 0x1ffff),
193 .swt_mem[1] = SWT_MEM(0x003fffff, 0x003fffff, 0x0),
Jacky Baidaa44782023-09-18 22:08:52 +0800194 },
195};
196
Jacky Bai36af80c2021-10-20 11:25:30 +0800197/* PMIC config for power down, LDO1 should be OFF */
198ps_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 */
226ps_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
Jacky Baidaa44782023-09-18 22:08:52 +0800253struct ps_pwr_mode_cfg_t *pwr_sys_cfg = (struct ps_pwr_mode_cfg_t *)UPWR_DRAM_SHARED_BASE_ADDR;
254
255void imx_set_pwr_mode_cfg(abs_pwr_mode_t mode)
256{
Jacky Bai36af80c2021-10-20 11:25:30 +0800257 uint32_t volt;
258
Jacky Baidaa44782023-09-18 22:08:52 +0800259 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));
Jacky Bai36af80c2021-10-20 11:25:30 +0800269
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 }
Jacky Baidaa44782023-09-18 22:08:52 +0800288}
289
290void 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
Jacky Bai478af8d2021-06-25 09:47:46 +0800310 if (is_local_state_retn(CLUSTER_PWR_STATE(target_state))) {
Jacky Baidaa44782023-09-18 22:08:52 +0800311 /*
312 * just for sleep mode for now, need to update to
Jacky Bai478af8d2021-06-25 09:47:46 +0800313 * support more modes, same for suspend finish call back.
Jacky Baidaa44782023-09-18 22:08:52 +0800314 */
315 mmio_write_32(IMX_CMC1_BASE + 0x10, 0x1);
316 mmio_write_32(IMX_CMC1_BASE + 0x20, 0x1);
Jacky Bai478af8d2021-06-25 09:47:46 +0800317
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);
Jacky Baidaa44782023-09-18 22:08:52 +0800325 }
326
Jacky Baidaa44782023-09-18 22:08:52 +0800327 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);
Jacky Bai478af8d2021-06-25 09:47:46 +0800334 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);
Jacky Baidaa44782023-09-18 22:08:52 +0800357 }
358}
359
Jacky Bai478af8d2021-06-25 09:47:46 +0800360extern void imx8ulp_init_scmi_server(void);
Jacky Baidaa44782023-09-18 22:08:52 +0800361void 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))) {
Jacky Bai478af8d2021-06-25 09:47:46 +0800366 /* 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();
Jacky Baidaa44782023-09-18 22:08:52 +0800388 }
389
Jacky Bai478af8d2021-06-25 09:47:46 +0800390 /* clear cluster's LPM setting. */
391 mmio_write_32(IMX_CMC1_BASE + 0x20, 0x0);
392 mmio_write_32(IMX_CMC1_BASE + 0x10, 0x0);
Jacky Baidaa44782023-09-18 22:08:52 +0800393
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}
Jacky Baifcd41e82020-07-02 14:39:58 +0800407
408void __dead2 imx8ulp_pwr_domain_pwr_down_wfi(const psci_power_state_t *target_state)
409{
410 while (1) {
411 wfi();
412 }
413}
414
415void __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
Jacky Baidaa44782023-09-18 22:08:52 +0800427int 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
450void 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
Jacky Bai891c5472023-09-18 21:53:15 +0800459void __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
Jacky Bai36af80c2021-10-20 11:25:30 +0800477 /* power off all the pad */
478 apd_io_pad_off();
479
Jacky Bai891c5472023-09-18 21:53:15 +0800480 /* 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
Jacky Baifcd41e82020-07-02 14:39:58 +0800506static 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,
Jacky Bai891c5472023-09-18 21:53:15 +0800510 .system_off = imx_system_off,
Jacky Baifcd41e82020-07-02 14:39:58 +0800511 .system_reset = imx8ulp_system_reset,
512 .pwr_domain_off = imx_pwr_domain_off,
Jacky Baidaa44782023-09-18 22:08:52 +0800513 .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,
Jacky Baifcd41e82020-07-02 14:39:58 +0800517 .pwr_domain_pwr_down_wfi = imx8ulp_pwr_domain_pwr_down_wfi,
518};
519
520int 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}