blob: 3a36332823d8c707c818fd9eabf10fe56d706389 [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 Bai4fafccb2022-12-13 09:34:07 +080028extern void imx8ulp_init_scmi_server(void);
Jacky Bai478af8d2021-06-25 09:47:46 +080029
Jacky Baifcd41e82020-07-02 14:39:58 +080030static uintptr_t secure_entrypoint;
31
32#define CORE_PWR_STATE(state) ((state)->pwr_domain_state[MPIDR_AFFLVL0])
33#define CLUSTER_PWR_STATE(state) ((state)->pwr_domain_state[MPIDR_AFFLVL1])
34#define SYSTEM_PWR_STATE(state) ((state)->pwr_domain_state[PLAT_MAX_PWR_LVL])
35
36#define RVBARADDRx(c) (IMX_SIM1_BASE + 0x5c + 0x4 * (c))
37#define WKPUx(c) (IMX_SIM1_BASE + 0x3c + 0x4 * (c))
38#define AD_COREx_LPMODE(c) (IMX_CMC1_BASE + 0x50 + 0x4 * (c))
39
Jacky Baidaa44782023-09-18 22:08:52 +080040#define PMIC_CFG(v, m, msk) \
41 { \
42 .volt = (v), \
43 .mode = (m), \
44 .mode_msk = (msk), \
45 }
46
47#define PAD_CFG(c, r, t) \
48 { \
49 .pad_close = (c), \
50 .pad_reset = (r), \
51 .pad_tqsleep = (t) \
52 }
53
54#define BIAS_CFG(m, n, p, mbias) \
55 { \
56 .dombias_cfg = { \
57 .mode = (m), \
58 .rbbn = (n), \
59 .rbbp = (p), \
60 }, \
61 .membias_cfg = {mbias}, \
62 }
63
64#define SWT_BOARD(swt_on, msk) \
65 { \
66 .on = (swt_on), \
67 .mask = (msk), \
68 }
69
70#define SWT_MEM(a, p, m) \
71 { \
72 .array = (a), \
73 .perif = (p), \
74 .mask = (m), \
75 }
76
Jacky Baifcd41e82020-07-02 14:39:58 +080077static int imx_pwr_set_cpu_entry(unsigned int cpu, unsigned int entry)
78{
79 mmio_write_32(RVBARADDRx(cpu), entry);
80
81 /* set update bit */
82 mmio_write_32(IMX_SIM1_BASE + 0x8, mmio_read_32(IMX_SIM1_BASE + 0x8) | BIT_32(24 + cpu));
83 /* wait for ack */
84 while (!(mmio_read_32(IMX_SIM1_BASE + 0x8) & BIT_32(26 + cpu))) {
85 }
86
87 /* clear update bit */
88 mmio_write_32(IMX_SIM1_BASE + 0x8, mmio_read_32(IMX_SIM1_BASE + 0x8) & ~BIT_32(24 + cpu));
89 /* clear ack bit */
90 mmio_write_32(IMX_SIM1_BASE + 0x8, mmio_read_32(IMX_SIM1_BASE + 0x8) | BIT_32(26 + cpu));
91
92 return 0;
93}
94
Jacky Baie1d5c3c2022-08-30 15:51:06 +080095static volatile uint32_t cgc1_nicclk;
Jacky Baifcd41e82020-07-02 14:39:58 +080096int imx_pwr_domain_on(u_register_t mpidr)
97{
98 unsigned int cpu = MPIDR_AFFLVL0_VAL(mpidr);
99
100 imx_pwr_set_cpu_entry(cpu, secure_entrypoint);
101
Jacky Baie1d5c3c2022-08-30 15:51:06 +0800102 /* slow down the APD NIC bus clock */
103 cgc1_nicclk = mmio_read_32(IMX_CGC1_BASE + 0x34);
104 mmio_clrbits_32(IMX_CGC1_BASE + 0x34, GENMASK_32(29, 28));
105
Jacky Baifcd41e82020-07-02 14:39:58 +0800106 mmio_write_32(IMX_CMC1_BASE + 0x18, 0x3f);
107 mmio_write_32(IMX_CMC1_BASE + 0x50 + 0x4 * cpu, 0);
108
109 /* enable wku wakeup for idle */
110 mmio_write_32(IMX_SIM1_BASE + 0x3c + 0x4 * cpu, 0xffffffff);
111
112 return PSCI_E_SUCCESS;
113}
114
115void imx_pwr_domain_on_finish(const psci_power_state_t *target_state)
116{
117 imx_pwr_set_cpu_entry(0, IMX_ROM_ENTRY);
118 plat_gic_pcpu_init();
119 plat_gic_cpuif_enable();
Jacky Baie1d5c3c2022-08-30 15:51:06 +0800120
121 /* set APD NIC back to orignally setting */
122 mmio_write_32(IMX_CGC1_BASE + 0x34, cgc1_nicclk);
Jacky Baifcd41e82020-07-02 14:39:58 +0800123}
124
125int imx_validate_ns_entrypoint(uintptr_t ns_entrypoint)
126{
127 return PSCI_E_SUCCESS;
128}
129
130void imx_pwr_domain_off(const psci_power_state_t *target_state)
131{
132 unsigned int cpu = MPIDR_AFFLVL0_VAL(read_mpidr_el1());
133
134 plat_gic_cpuif_disable();
135
136 /* disable wakeup */
137 mmio_write_32(WKPUx(cpu), 0);
138
Jacky Baidaa44782023-09-18 22:08:52 +0800139 /* set core power mode to PD */
Jacky Baifcd41e82020-07-02 14:39:58 +0800140 mmio_write_32(AD_COREx_LPMODE(cpu), 0x3);
141}
Jacky Bai478af8d2021-06-25 09:47:46 +0800142
Jacky Baidaa44782023-09-18 22:08:52 +0800143/* APD power mode config */
144ps_apd_pwr_mode_cfgs_t apd_pwr_mode_cfgs = {
Jacky Bai891c5472023-09-18 21:53:15 +0800145 [DPD_PWR_MODE] = {
146 .swt_board_offs = 0x180,
147 .swt_mem_offs = 0x188,
Jacky Bai36af80c2021-10-20 11:25:30 +0800148 .pmic_cfg = PMIC_CFG(0x23, 0x0, 0x2),
149 .pad_cfg = PAD_CFG(0x0, 0xc, 0x01e80a02),
Jacky Bai891c5472023-09-18 21:53:15 +0800150 .bias_cfg = BIAS_CFG(0x0, 0x2, 0x2, 0x0),
151 },
152
Jacky Bai478af8d2021-06-25 09:47:46 +0800153 /* PD */
154 [PD_PWR_MODE] = {
155 .swt_board_offs = 0x170,
156 .swt_mem_offs = 0x178,
Jacky Bai36af80c2021-10-20 11:25:30 +0800157 .pmic_cfg = PMIC_CFG(0x23, 0x0, 0x2),
158 .pad_cfg = PAD_CFG(0x0, 0xc, 0x01e80a00),
Jacky Bai478af8d2021-06-25 09:47:46 +0800159 .bias_cfg = BIAS_CFG(0x0, 0x2, 0x2, 0x0),
160 },
161
Jacky Baidaa44782023-09-18 22:08:52 +0800162 [ADMA_PWR_MODE] = {
163 .swt_board_offs = 0x120,
164 .swt_mem_offs = 0x128,
165 .pmic_cfg = PMIC_CFG(0x23, 0x0, 0x2),
166 .pad_cfg = PAD_CFG(0x0, 0x0, 0x0deb7a00),
Jacky Bai36af80c2021-10-20 11:25:30 +0800167 .bias_cfg = BIAS_CFG(0x2, 0x2, 0x2, 0x0),
Jacky Baidaa44782023-09-18 22:08:52 +0800168 },
169
170 [ACT_PWR_MODE] = {
171 .swt_board_offs = 0x110,
172 .swt_mem_offs = 0x118,
Jacky Bai36af80c2021-10-20 11:25:30 +0800173 .pmic_cfg = PMIC_CFG(0x23, 0x0, 0x2),
Jacky Baidaa44782023-09-18 22:08:52 +0800174 .pad_cfg = PAD_CFG(0x0, 0x0, 0x0deb7a00),
Jacky Bai36af80c2021-10-20 11:25:30 +0800175 .bias_cfg = BIAS_CFG(0x2, 0x2, 0x2, 0x0),
Jacky Baidaa44782023-09-18 22:08:52 +0800176 },
177};
178
179/* APD power switch config */
180ps_apd_swt_cfgs_t apd_swt_cfgs = {
Jacky Bai891c5472023-09-18 21:53:15 +0800181 [DPD_PWR_MODE] = {
Jacky Bai36af80c2021-10-20 11:25:30 +0800182 .swt_board[0] = SWT_BOARD(0x0, 0x1fffc),
Jacky Bai891c5472023-09-18 21:53:15 +0800183 .swt_mem[0] = SWT_MEM(0x0, 0x0, 0x1ffff),
184 .swt_mem[1] = SWT_MEM(0x003fffff, 0x003fffff, 0x0),
185 },
186
Jacky Bai478af8d2021-06-25 09:47:46 +0800187 [PD_PWR_MODE] = {
Jacky Bai36af80c2021-10-20 11:25:30 +0800188 .swt_board[0] = SWT_BOARD(0x0, 0x00001fffc),
Jacky Bai478af8d2021-06-25 09:47:46 +0800189 .swt_mem[0] = SWT_MEM(0x00010c00, 0x0, 0x1ffff),
190 .swt_mem[1] = SWT_MEM(0x003fffff, 0x003f0000, 0x0),
191 },
192
Jacky Baidaa44782023-09-18 22:08:52 +0800193 [ADMA_PWR_MODE] = {
Jacky Bai36af80c2021-10-20 11:25:30 +0800194 .swt_board[0] = SWT_BOARD(0x15f74, 0x15f74),
Jacky Bai478af8d2021-06-25 09:47:46 +0800195 .swt_mem[0] = SWT_MEM(0x0001fffd, 0x0001fffd, 0x1ffff),
196 .swt_mem[1] = SWT_MEM(0x003fffff, 0x003fffff, 0x0),
Jacky Baidaa44782023-09-18 22:08:52 +0800197 },
198
199 [ACT_PWR_MODE] = {
Jacky Bai36af80c2021-10-20 11:25:30 +0800200 .swt_board[0] = SWT_BOARD(0x15f74, 0x15f74),
Jacky Bai478af8d2021-06-25 09:47:46 +0800201 .swt_mem[0] = SWT_MEM(0x0001fffd, 0x0001fffd, 0x1ffff),
202 .swt_mem[1] = SWT_MEM(0x003fffff, 0x003fffff, 0x0),
Jacky Baidaa44782023-09-18 22:08:52 +0800203 },
204};
205
Jacky Bai36af80c2021-10-20 11:25:30 +0800206/* PMIC config for power down, LDO1 should be OFF */
207ps_apd_pmic_reg_data_cfgs_t pd_pmic_reg_cfgs = {
208 [0] = {
209 .tag = PMIC_REG_VALID_TAG,
210 .power_mode = PD_PWR_MODE,
211 .i2c_addr = 0x30,
212 .i2c_data = 0x9c,
213 },
214 [1] = {
215 .tag = PMIC_REG_VALID_TAG,
216 .power_mode = PD_PWR_MODE,
217 .i2c_addr = 0x22,
218 .i2c_data = 0xb,
219 },
220 [2] = {
221 .tag = PMIC_REG_VALID_TAG,
222 .power_mode = ACT_PWR_MODE,
223 .i2c_addr = 0x30,
224 .i2c_data = 0x9d,
225 },
226 [3] = {
227 .tag = PMIC_REG_VALID_TAG,
228 .power_mode = ACT_PWR_MODE,
229 .i2c_addr = 0x22,
230 .i2c_data = 0x28,
231 },
232};
233
234/* PMIC config for deep power down, BUCK3 should be OFF */
235ps_apd_pmic_reg_data_cfgs_t dpd_pmic_reg_cfgs = {
236 [0] = {
237 .tag = PMIC_REG_VALID_TAG,
238 .power_mode = DPD_PWR_MODE,
239 .i2c_addr = 0x21,
240 .i2c_data = 0x78,
241 },
242 [1] = {
243 .tag = PMIC_REG_VALID_TAG,
244 .power_mode = DPD_PWR_MODE,
245 .i2c_addr = 0x30,
246 .i2c_data = 0x9c,
247 },
248 [2] = {
249 .tag = PMIC_REG_VALID_TAG,
250 .power_mode = ACT_PWR_MODE,
251 .i2c_addr = 0x21,
252 .i2c_data = 0x79,
253 },
254 [3] = {
255 .tag = PMIC_REG_VALID_TAG,
256 .power_mode = ACT_PWR_MODE,
257 .i2c_addr = 0x30,
258 .i2c_data = 0x9d,
259 },
260};
261
Jacky Baidaa44782023-09-18 22:08:52 +0800262struct ps_pwr_mode_cfg_t *pwr_sys_cfg = (struct ps_pwr_mode_cfg_t *)UPWR_DRAM_SHARED_BASE_ADDR;
263
264void imx_set_pwr_mode_cfg(abs_pwr_mode_t mode)
265{
Jacky Bai36af80c2021-10-20 11:25:30 +0800266 uint32_t volt;
267
Jacky Baidaa44782023-09-18 22:08:52 +0800268 if (mode >= NUM_PWR_MODES) {
269 return;
270 }
271
272 /* apd power mode config */
273 memcpy(&pwr_sys_cfg->ps_apd_pwr_mode_cfg[mode], &apd_pwr_mode_cfgs[mode],
274 sizeof(struct ps_apd_pwr_mode_cfg_t));
275
276 /* apd power switch config */
277 memcpy(&pwr_sys_cfg->ps_apd_swt_cfg[mode], &apd_swt_cfgs[mode], sizeof(swt_config_t));
Jacky Bai36af80c2021-10-20 11:25:30 +0800278
279 /*
280 * BUCK3 & LDO1 can only be shutdown when LPAV is owned by APD side
281 * otherwise RTD side is responsible to control them in low power mode.
282 */
283 if (is_lpav_owned_by_apd()) {
284 /* power off the BUCK3 in DPD mode */
285 if (mode == DPD_PWR_MODE) {
286 memcpy(&pwr_sys_cfg->ps_apd_pmic_reg_data_cfg, &dpd_pmic_reg_cfgs,
287 sizeof(ps_apd_pmic_reg_data_cfgs_t));
288 /* LDO1 should be power off in PD mode */
289 } else if (mode == PD_PWR_MODE) {
290 /* overwrite the buck3 voltage setting in active mode */
291 upower_pmic_i2c_read(0x22, &volt);
292 pd_pmic_reg_cfgs[3].i2c_data = volt;
293 memcpy(&pwr_sys_cfg->ps_apd_pmic_reg_data_cfg, &pd_pmic_reg_cfgs,
294 sizeof(ps_apd_pmic_reg_data_cfgs_t));
295 }
296 }
Jacky Baidaa44782023-09-18 22:08:52 +0800297}
298
299void imx_domain_suspend(const psci_power_state_t *target_state)
300{
301 unsigned int cpu = MPIDR_AFFLVL0_VAL(read_mpidr_el1());
302
303 if (is_local_state_off(CORE_PWR_STATE(target_state))) {
304 plat_gic_cpuif_disable();
305 imx_pwr_set_cpu_entry(cpu, secure_entrypoint);
306 /* core put into power down */
307 mmio_write_32(IMX_CMC1_BASE + 0x50 + 0x4 * cpu, 0x3);
308 /* FIXME config wakeup interrupt in WKPU */
309 mmio_write_32(IMX_SIM1_BASE + 0x3c + 0x4 * cpu, 0x7fffffe3);
310 } else {
311 /* for core standby/retention mode */
312 mmio_write_32(IMX_CMC1_BASE + 0x50 + 0x4 * cpu, 0x1);
313 mmio_write_32(IMX_SIM1_BASE + 0x3c + 0x4 * cpu, 0x7fffffe3);
314 dsb();
315 write_scr_el3(read_scr_el3() | SCR_FIQ_BIT);
316 isb();
317 }
318
Jacky Bai478af8d2021-06-25 09:47:46 +0800319 if (is_local_state_retn(CLUSTER_PWR_STATE(target_state))) {
Jacky Baidaa44782023-09-18 22:08:52 +0800320 /*
321 * just for sleep mode for now, need to update to
Jacky Bai478af8d2021-06-25 09:47:46 +0800322 * support more modes, same for suspend finish call back.
Jacky Baidaa44782023-09-18 22:08:52 +0800323 */
324 mmio_write_32(IMX_CMC1_BASE + 0x10, 0x1);
325 mmio_write_32(IMX_CMC1_BASE + 0x20, 0x1);
Jacky Bai478af8d2021-06-25 09:47:46 +0800326
327 } else if (is_local_state_off(CLUSTER_PWR_STATE(target_state))) {
328 /*
329 * for cluster off state, put cluster into power down mode,
330 * config the cluster clock to be off.
331 */
332 mmio_write_32(IMX_CMC1_BASE + 0x10, 0x7);
333 mmio_write_32(IMX_CMC1_BASE + 0x20, 0xf);
Jacky Baidaa44782023-09-18 22:08:52 +0800334 }
335
Jacky Baidaa44782023-09-18 22:08:52 +0800336 if (is_local_state_off(SYSTEM_PWR_STATE(target_state))) {
337 /*
338 * low power mode config info used by upower
339 * to do low power mode transition.
340 */
341 imx_set_pwr_mode_cfg(ADMA_PWR_MODE);
342 imx_set_pwr_mode_cfg(ACT_PWR_MODE);
Jacky Bai478af8d2021-06-25 09:47:46 +0800343 imx_set_pwr_mode_cfg(PD_PWR_MODE);
344
345 /* clear the upower wakeup */
346 upwr_xcp_set_rtd_apd_llwu(APD_DOMAIN, 0, NULL);
347 upower_wait_resp();
348
349 /* enable the USB wakeup */
350 usb_wakeup_enable(true);
351
352 /* config the WUU to enabled the wakeup source */
353 mmio_write_32(IMX_PCC3_BASE + 0x98, 0xc0800000);
354
355 /* !!! clear all the pad wakeup pending event */
356 mmio_write_32(IMX_WUU1_BASE + 0x20, 0xffffffff);
357
358 /* enable upower usb phy wakeup by default */
359 mmio_setbits_32(IMX_WUU1_BASE + 0x18, BIT(4) | BIT(1) | BIT(0));
360
361 /* enabled all pad wakeup by default */
362 mmio_write_32(IMX_WUU1_BASE + 0x8, 0xffffffff);
363
364 /* save the AD domain context before entering PD mode */
365 imx_apd_ctx_save(cpu);
Jacky Baidaa44782023-09-18 22:08:52 +0800366 }
367}
368
Jacky Bai4fafccb2022-12-13 09:34:07 +0800369#define DRAM_LPM_STATUS U(0x2802b004)
Jacky Baidaa44782023-09-18 22:08:52 +0800370void imx_domain_suspend_finish(const psci_power_state_t *target_state)
371{
372 unsigned int cpu = MPIDR_AFFLVL0_VAL(read_mpidr_el1());
373
374 if (is_local_state_off(SYSTEM_PWR_STATE(target_state))) {
Jacky Bai478af8d2021-06-25 09:47:46 +0800375 /* restore the ap domain context */
376 imx_apd_ctx_restore(cpu);
377
378 /* clear the upower wakeup */
379 upwr_xcp_set_rtd_apd_llwu(APD_DOMAIN, 0, NULL);
380 upower_wait_resp();
381
382 /* disable all pad wakeup */
383 mmio_write_32(IMX_WUU1_BASE + 0x8, 0x0);
384
385 /* clear all the pad wakeup pending event */
386 mmio_write_32(IMX_WUU1_BASE + 0x20, 0xffffffff);
387
388 /*
389 * disable the usb wakeup after resume to make sure the pending
390 * usb wakeup in WUU can be cleared successfully, otherwise,
391 * APD will resume failed in next PD mode.
392 */
393 usb_wakeup_enable(false);
394
395 /* re-init the SCMI channel */
396 imx8ulp_init_scmi_server();
Jacky Baidaa44782023-09-18 22:08:52 +0800397 }
398
Jacky Bai4fafccb2022-12-13 09:34:07 +0800399 /*
400 * wait for DDR is ready when DDR is under the RTD
401 * side control for power saving
402 */
403 while (mmio_read_32(DRAM_LPM_STATUS) != 0) {
404 ;
405 }
406
Jacky Bai478af8d2021-06-25 09:47:46 +0800407 /* clear cluster's LPM setting. */
408 mmio_write_32(IMX_CMC1_BASE + 0x20, 0x0);
409 mmio_write_32(IMX_CMC1_BASE + 0x10, 0x0);
Jacky Baidaa44782023-09-18 22:08:52 +0800410
411 /* clear core's LPM setting */
412 mmio_write_32(IMX_CMC1_BASE + 0x50 + 0x4 * cpu, 0x0);
413 mmio_write_32(IMX_SIM1_BASE + 0x3c + 0x4 * cpu, 0x0);
414
415 if (is_local_state_off(CORE_PWR_STATE(target_state))) {
416 imx_pwr_set_cpu_entry(0, IMX_ROM_ENTRY);
417 plat_gic_cpuif_enable();
418 } else {
419 dsb();
420 write_scr_el3(read_scr_el3() & (~SCR_FIQ_BIT));
421 isb();
422 }
423}
Jacky Baifcd41e82020-07-02 14:39:58 +0800424
425void __dead2 imx8ulp_pwr_domain_pwr_down_wfi(const psci_power_state_t *target_state)
426{
427 while (1) {
428 wfi();
429 }
430}
431
432void __dead2 imx8ulp_system_reset(void)
433{
434 imx_pwr_set_cpu_entry(0, IMX_ROM_ENTRY);
435
436 /* Write invalid command to WDOG CNT to trigger reset */
437 mmio_write_32(IMX_WDOG3_BASE + 0x4, 0x12345678);
438
439 while (true) {
440 wfi();
441 }
442}
443
Jacky Baidaa44782023-09-18 22:08:52 +0800444int imx_validate_power_state(unsigned int power_state,
445 psci_power_state_t *req_state)
446{
447 int pwr_lvl = psci_get_pstate_pwrlvl(power_state);
448 int pwr_type = psci_get_pstate_type(power_state);
449
450 if (pwr_lvl > PLAT_MAX_PWR_LVL) {
451 return PSCI_E_INVALID_PARAMS;
452 }
453
454 if (pwr_type == PSTATE_TYPE_STANDBY) {
455 CORE_PWR_STATE(req_state) = PLAT_MAX_RET_STATE;
456 CLUSTER_PWR_STATE(req_state) = PLAT_MAX_RET_STATE;
457 }
458
459 /* No power down state support */
460 if (pwr_type == PSTATE_TYPE_POWERDOWN) {
461 return PSCI_E_INVALID_PARAMS;
462 }
463
464 return PSCI_E_SUCCESS;
465}
466
467void imx_get_sys_suspend_power_state(psci_power_state_t *req_state)
468{
469 unsigned int i;
470
471 for (i = IMX_PWR_LVL0; i <= PLAT_MAX_PWR_LVL; i++) {
472 req_state->pwr_domain_state[i] = PLAT_POWER_DOWN_OFF_STATE;
473 }
474}
475
Jacky Bai891c5472023-09-18 21:53:15 +0800476void __dead2 imx_system_off(void)
477{
478 unsigned int i;
479
480 /* config the all the core into OFF mode and IRQ masked. */
481 for (i = 0U; i < PLATFORM_CORE_COUNT; i++) {
482 /* disable wakeup from wkpu */
483 mmio_write_32(WKPUx(i), 0x0);
484
485 /* reset the core reset entry to 0x1000 */
486 imx_pwr_set_cpu_entry(i, 0x1000);
487
488 /* config the core power mode to off */
489 mmio_write_32(AD_COREx_LPMODE(i), 0x3);
490 }
491
492 plat_gic_cpuif_disable();
493
Jacky Bai36af80c2021-10-20 11:25:30 +0800494 /* power off all the pad */
495 apd_io_pad_off();
496
Jacky Bai891c5472023-09-18 21:53:15 +0800497 /* Config the power mode info for entering DPD mode and ACT mode */
498 imx_set_pwr_mode_cfg(ADMA_PWR_MODE);
499 imx_set_pwr_mode_cfg(ACT_PWR_MODE);
500 imx_set_pwr_mode_cfg(DPD_PWR_MODE);
501
502 /* Set the APD domain into DPD mode */
503 mmio_write_32(IMX_CMC1_BASE + 0x10, 0x7);
504 mmio_write_32(IMX_CMC1_BASE + 0x20, 0x1f);
505
506 /* make sure no pending upower wakeup */
507 upwr_xcp_set_rtd_apd_llwu(APD_DOMAIN, 0, NULL);
508 upower_wait_resp();
509
510 /* enable the upower wakeup from wuu, act as APD boot up method */
511 mmio_write_32(IMX_PCC3_BASE + 0x98, 0xc0800000);
512 mmio_setbits_32(IMX_WUU1_BASE + 0x18, BIT(4));
513
514 /* make sure no pad wakeup event is pending */
515 mmio_write_32(IMX_WUU1_BASE + 0x20, 0xffffffff);
516
517 wfi();
518
519 ERROR("power off failed.\n");
520 panic();
521}
522
Jacky Baifcd41e82020-07-02 14:39:58 +0800523static const plat_psci_ops_t imx_plat_psci_ops = {
524 .pwr_domain_on = imx_pwr_domain_on,
525 .pwr_domain_on_finish = imx_pwr_domain_on_finish,
526 .validate_ns_entrypoint = imx_validate_ns_entrypoint,
Jacky Bai891c5472023-09-18 21:53:15 +0800527 .system_off = imx_system_off,
Jacky Baifcd41e82020-07-02 14:39:58 +0800528 .system_reset = imx8ulp_system_reset,
529 .pwr_domain_off = imx_pwr_domain_off,
Jacky Baidaa44782023-09-18 22:08:52 +0800530 .pwr_domain_suspend = imx_domain_suspend,
531 .pwr_domain_suspend_finish = imx_domain_suspend_finish,
532 .get_sys_suspend_power_state = imx_get_sys_suspend_power_state,
533 .validate_power_state = imx_validate_power_state,
Jacky Baifcd41e82020-07-02 14:39:58 +0800534 .pwr_domain_pwr_down_wfi = imx8ulp_pwr_domain_pwr_down_wfi,
535};
536
537int plat_setup_psci_ops(uintptr_t sec_entrypoint,
538 const plat_psci_ops_t **psci_ops)
539{
540 secure_entrypoint = sec_entrypoint;
541 imx_pwr_set_cpu_entry(0, sec_entrypoint);
542 *psci_ops = &imx_plat_psci_ops;
543
544 mmio_write_32(IMX_CMC1_BASE + 0x18, 0x3f);
545 mmio_write_32(IMX_SIM1_BASE + 0x3c, 0xffffffff);
546
547 return 0;
548}