blob: 62cba2c9d56b73a4276b70fcb82803e44bfa74ab [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
Jacky Baie1d5c3c2022-08-30 15:51:06 +080094static volatile uint32_t cgc1_nicclk;
Jacky Baifcd41e82020-07-02 14:39:58 +080095int imx_pwr_domain_on(u_register_t mpidr)
96{
97 unsigned int cpu = MPIDR_AFFLVL0_VAL(mpidr);
98
99 imx_pwr_set_cpu_entry(cpu, secure_entrypoint);
100
Jacky Baie1d5c3c2022-08-30 15:51:06 +0800101 /* slow down the APD NIC bus clock */
102 cgc1_nicclk = mmio_read_32(IMX_CGC1_BASE + 0x34);
103 mmio_clrbits_32(IMX_CGC1_BASE + 0x34, GENMASK_32(29, 28));
104
Jacky Baifcd41e82020-07-02 14:39:58 +0800105 mmio_write_32(IMX_CMC1_BASE + 0x18, 0x3f);
106 mmio_write_32(IMX_CMC1_BASE + 0x50 + 0x4 * cpu, 0);
107
108 /* enable wku wakeup for idle */
109 mmio_write_32(IMX_SIM1_BASE + 0x3c + 0x4 * cpu, 0xffffffff);
110
111 return PSCI_E_SUCCESS;
112}
113
114void imx_pwr_domain_on_finish(const psci_power_state_t *target_state)
115{
116 imx_pwr_set_cpu_entry(0, IMX_ROM_ENTRY);
117 plat_gic_pcpu_init();
118 plat_gic_cpuif_enable();
Jacky Baie1d5c3c2022-08-30 15:51:06 +0800119
120 /* set APD NIC back to orignally setting */
121 mmio_write_32(IMX_CGC1_BASE + 0x34, cgc1_nicclk);
Jacky Baifcd41e82020-07-02 14:39:58 +0800122}
123
124int imx_validate_ns_entrypoint(uintptr_t ns_entrypoint)
125{
126 return PSCI_E_SUCCESS;
127}
128
129void imx_pwr_domain_off(const psci_power_state_t *target_state)
130{
131 unsigned int cpu = MPIDR_AFFLVL0_VAL(read_mpidr_el1());
132
133 plat_gic_cpuif_disable();
134
135 /* disable wakeup */
136 mmio_write_32(WKPUx(cpu), 0);
137
Jacky Baidaa44782023-09-18 22:08:52 +0800138 /* set core power mode to PD */
Jacky Baifcd41e82020-07-02 14:39:58 +0800139 mmio_write_32(AD_COREx_LPMODE(cpu), 0x3);
140}
Jacky Bai478af8d2021-06-25 09:47:46 +0800141
Jacky Baidaa44782023-09-18 22:08:52 +0800142/* APD power mode config */
143ps_apd_pwr_mode_cfgs_t apd_pwr_mode_cfgs = {
Jacky Bai891c5472023-09-18 21:53:15 +0800144 [DPD_PWR_MODE] = {
145 .swt_board_offs = 0x180,
146 .swt_mem_offs = 0x188,
Jacky Bai36af80c2021-10-20 11:25:30 +0800147 .pmic_cfg = PMIC_CFG(0x23, 0x0, 0x2),
148 .pad_cfg = PAD_CFG(0x0, 0xc, 0x01e80a02),
Jacky Bai891c5472023-09-18 21:53:15 +0800149 .bias_cfg = BIAS_CFG(0x0, 0x2, 0x2, 0x0),
150 },
151
Jacky Bai478af8d2021-06-25 09:47:46 +0800152 /* PD */
153 [PD_PWR_MODE] = {
154 .swt_board_offs = 0x170,
155 .swt_mem_offs = 0x178,
Jacky Bai36af80c2021-10-20 11:25:30 +0800156 .pmic_cfg = PMIC_CFG(0x23, 0x0, 0x2),
157 .pad_cfg = PAD_CFG(0x0, 0xc, 0x01e80a00),
Jacky Bai478af8d2021-06-25 09:47:46 +0800158 .bias_cfg = BIAS_CFG(0x0, 0x2, 0x2, 0x0),
159 },
160
Jacky Baidaa44782023-09-18 22:08:52 +0800161 [ADMA_PWR_MODE] = {
162 .swt_board_offs = 0x120,
163 .swt_mem_offs = 0x128,
164 .pmic_cfg = PMIC_CFG(0x23, 0x0, 0x2),
165 .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 [ACT_PWR_MODE] = {
170 .swt_board_offs = 0x110,
171 .swt_mem_offs = 0x118,
Jacky Bai36af80c2021-10-20 11:25:30 +0800172 .pmic_cfg = PMIC_CFG(0x23, 0x0, 0x2),
Jacky Baidaa44782023-09-18 22:08:52 +0800173 .pad_cfg = PAD_CFG(0x0, 0x0, 0x0deb7a00),
Jacky Bai36af80c2021-10-20 11:25:30 +0800174 .bias_cfg = BIAS_CFG(0x2, 0x2, 0x2, 0x0),
Jacky Baidaa44782023-09-18 22:08:52 +0800175 },
176};
177
178/* APD power switch config */
179ps_apd_swt_cfgs_t apd_swt_cfgs = {
Jacky Bai891c5472023-09-18 21:53:15 +0800180 [DPD_PWR_MODE] = {
Jacky Bai36af80c2021-10-20 11:25:30 +0800181 .swt_board[0] = SWT_BOARD(0x0, 0x1fffc),
Jacky Bai891c5472023-09-18 21:53:15 +0800182 .swt_mem[0] = SWT_MEM(0x0, 0x0, 0x1ffff),
183 .swt_mem[1] = SWT_MEM(0x003fffff, 0x003fffff, 0x0),
184 },
185
Jacky Bai478af8d2021-06-25 09:47:46 +0800186 [PD_PWR_MODE] = {
Jacky Bai36af80c2021-10-20 11:25:30 +0800187 .swt_board[0] = SWT_BOARD(0x0, 0x00001fffc),
Jacky Bai478af8d2021-06-25 09:47:46 +0800188 .swt_mem[0] = SWT_MEM(0x00010c00, 0x0, 0x1ffff),
189 .swt_mem[1] = SWT_MEM(0x003fffff, 0x003f0000, 0x0),
190 },
191
Jacky Baidaa44782023-09-18 22:08:52 +0800192 [ADMA_PWR_MODE] = {
Jacky Bai36af80c2021-10-20 11:25:30 +0800193 .swt_board[0] = SWT_BOARD(0x15f74, 0x15f74),
Jacky Bai478af8d2021-06-25 09:47:46 +0800194 .swt_mem[0] = SWT_MEM(0x0001fffd, 0x0001fffd, 0x1ffff),
195 .swt_mem[1] = SWT_MEM(0x003fffff, 0x003fffff, 0x0),
Jacky Baidaa44782023-09-18 22:08:52 +0800196 },
197
198 [ACT_PWR_MODE] = {
Jacky Bai36af80c2021-10-20 11:25:30 +0800199 .swt_board[0] = SWT_BOARD(0x15f74, 0x15f74),
Jacky Bai478af8d2021-06-25 09:47:46 +0800200 .swt_mem[0] = SWT_MEM(0x0001fffd, 0x0001fffd, 0x1ffff),
201 .swt_mem[1] = SWT_MEM(0x003fffff, 0x003fffff, 0x0),
Jacky Baidaa44782023-09-18 22:08:52 +0800202 },
203};
204
Jacky Bai36af80c2021-10-20 11:25:30 +0800205/* PMIC config for power down, LDO1 should be OFF */
206ps_apd_pmic_reg_data_cfgs_t pd_pmic_reg_cfgs = {
207 [0] = {
208 .tag = PMIC_REG_VALID_TAG,
209 .power_mode = PD_PWR_MODE,
210 .i2c_addr = 0x30,
211 .i2c_data = 0x9c,
212 },
213 [1] = {
214 .tag = PMIC_REG_VALID_TAG,
215 .power_mode = PD_PWR_MODE,
216 .i2c_addr = 0x22,
217 .i2c_data = 0xb,
218 },
219 [2] = {
220 .tag = PMIC_REG_VALID_TAG,
221 .power_mode = ACT_PWR_MODE,
222 .i2c_addr = 0x30,
223 .i2c_data = 0x9d,
224 },
225 [3] = {
226 .tag = PMIC_REG_VALID_TAG,
227 .power_mode = ACT_PWR_MODE,
228 .i2c_addr = 0x22,
229 .i2c_data = 0x28,
230 },
231};
232
233/* PMIC config for deep power down, BUCK3 should be OFF */
234ps_apd_pmic_reg_data_cfgs_t dpd_pmic_reg_cfgs = {
235 [0] = {
236 .tag = PMIC_REG_VALID_TAG,
237 .power_mode = DPD_PWR_MODE,
238 .i2c_addr = 0x21,
239 .i2c_data = 0x78,
240 },
241 [1] = {
242 .tag = PMIC_REG_VALID_TAG,
243 .power_mode = DPD_PWR_MODE,
244 .i2c_addr = 0x30,
245 .i2c_data = 0x9c,
246 },
247 [2] = {
248 .tag = PMIC_REG_VALID_TAG,
249 .power_mode = ACT_PWR_MODE,
250 .i2c_addr = 0x21,
251 .i2c_data = 0x79,
252 },
253 [3] = {
254 .tag = PMIC_REG_VALID_TAG,
255 .power_mode = ACT_PWR_MODE,
256 .i2c_addr = 0x30,
257 .i2c_data = 0x9d,
258 },
259};
260
Jacky Baidaa44782023-09-18 22:08:52 +0800261struct ps_pwr_mode_cfg_t *pwr_sys_cfg = (struct ps_pwr_mode_cfg_t *)UPWR_DRAM_SHARED_BASE_ADDR;
262
263void imx_set_pwr_mode_cfg(abs_pwr_mode_t mode)
264{
Jacky Bai36af80c2021-10-20 11:25:30 +0800265 uint32_t volt;
266
Jacky Baidaa44782023-09-18 22:08:52 +0800267 if (mode >= NUM_PWR_MODES) {
268 return;
269 }
270
271 /* apd power mode config */
272 memcpy(&pwr_sys_cfg->ps_apd_pwr_mode_cfg[mode], &apd_pwr_mode_cfgs[mode],
273 sizeof(struct ps_apd_pwr_mode_cfg_t));
274
275 /* apd power switch config */
276 memcpy(&pwr_sys_cfg->ps_apd_swt_cfg[mode], &apd_swt_cfgs[mode], sizeof(swt_config_t));
Jacky Bai36af80c2021-10-20 11:25:30 +0800277
278 /*
279 * BUCK3 & LDO1 can only be shutdown when LPAV is owned by APD side
280 * otherwise RTD side is responsible to control them in low power mode.
281 */
282 if (is_lpav_owned_by_apd()) {
283 /* power off the BUCK3 in DPD mode */
284 if (mode == DPD_PWR_MODE) {
285 memcpy(&pwr_sys_cfg->ps_apd_pmic_reg_data_cfg, &dpd_pmic_reg_cfgs,
286 sizeof(ps_apd_pmic_reg_data_cfgs_t));
287 /* LDO1 should be power off in PD mode */
288 } else if (mode == PD_PWR_MODE) {
289 /* overwrite the buck3 voltage setting in active mode */
290 upower_pmic_i2c_read(0x22, &volt);
291 pd_pmic_reg_cfgs[3].i2c_data = volt;
292 memcpy(&pwr_sys_cfg->ps_apd_pmic_reg_data_cfg, &pd_pmic_reg_cfgs,
293 sizeof(ps_apd_pmic_reg_data_cfgs_t));
294 }
295 }
Jacky Baidaa44782023-09-18 22:08:52 +0800296}
297
298void imx_domain_suspend(const psci_power_state_t *target_state)
299{
300 unsigned int cpu = MPIDR_AFFLVL0_VAL(read_mpidr_el1());
301
302 if (is_local_state_off(CORE_PWR_STATE(target_state))) {
303 plat_gic_cpuif_disable();
304 imx_pwr_set_cpu_entry(cpu, secure_entrypoint);
305 /* core put into power down */
306 mmio_write_32(IMX_CMC1_BASE + 0x50 + 0x4 * cpu, 0x3);
307 /* FIXME config wakeup interrupt in WKPU */
308 mmio_write_32(IMX_SIM1_BASE + 0x3c + 0x4 * cpu, 0x7fffffe3);
309 } else {
310 /* for core standby/retention mode */
311 mmio_write_32(IMX_CMC1_BASE + 0x50 + 0x4 * cpu, 0x1);
312 mmio_write_32(IMX_SIM1_BASE + 0x3c + 0x4 * cpu, 0x7fffffe3);
313 dsb();
314 write_scr_el3(read_scr_el3() | SCR_FIQ_BIT);
315 isb();
316 }
317
Jacky Bai478af8d2021-06-25 09:47:46 +0800318 if (is_local_state_retn(CLUSTER_PWR_STATE(target_state))) {
Jacky Baidaa44782023-09-18 22:08:52 +0800319 /*
320 * just for sleep mode for now, need to update to
Jacky Bai478af8d2021-06-25 09:47:46 +0800321 * support more modes, same for suspend finish call back.
Jacky Baidaa44782023-09-18 22:08:52 +0800322 */
323 mmio_write_32(IMX_CMC1_BASE + 0x10, 0x1);
324 mmio_write_32(IMX_CMC1_BASE + 0x20, 0x1);
Jacky Bai478af8d2021-06-25 09:47:46 +0800325
326 } else if (is_local_state_off(CLUSTER_PWR_STATE(target_state))) {
327 /*
328 * for cluster off state, put cluster into power down mode,
329 * config the cluster clock to be off.
330 */
331 mmio_write_32(IMX_CMC1_BASE + 0x10, 0x7);
332 mmio_write_32(IMX_CMC1_BASE + 0x20, 0xf);
Jacky Baidaa44782023-09-18 22:08:52 +0800333 }
334
Jacky Baidaa44782023-09-18 22:08:52 +0800335 if (is_local_state_off(SYSTEM_PWR_STATE(target_state))) {
336 /*
337 * low power mode config info used by upower
338 * to do low power mode transition.
339 */
340 imx_set_pwr_mode_cfg(ADMA_PWR_MODE);
341 imx_set_pwr_mode_cfg(ACT_PWR_MODE);
Jacky Bai478af8d2021-06-25 09:47:46 +0800342 imx_set_pwr_mode_cfg(PD_PWR_MODE);
343
344 /* clear the upower wakeup */
345 upwr_xcp_set_rtd_apd_llwu(APD_DOMAIN, 0, NULL);
346 upower_wait_resp();
347
348 /* enable the USB wakeup */
349 usb_wakeup_enable(true);
350
351 /* config the WUU to enabled the wakeup source */
352 mmio_write_32(IMX_PCC3_BASE + 0x98, 0xc0800000);
353
354 /* !!! clear all the pad wakeup pending event */
355 mmio_write_32(IMX_WUU1_BASE + 0x20, 0xffffffff);
356
357 /* enable upower usb phy wakeup by default */
358 mmio_setbits_32(IMX_WUU1_BASE + 0x18, BIT(4) | BIT(1) | BIT(0));
359
360 /* enabled all pad wakeup by default */
361 mmio_write_32(IMX_WUU1_BASE + 0x8, 0xffffffff);
362
363 /* save the AD domain context before entering PD mode */
364 imx_apd_ctx_save(cpu);
Jacky Baidaa44782023-09-18 22:08:52 +0800365 }
366}
367
Jacky Bai478af8d2021-06-25 09:47:46 +0800368extern void imx8ulp_init_scmi_server(void);
Jacky Baidaa44782023-09-18 22:08:52 +0800369void imx_domain_suspend_finish(const psci_power_state_t *target_state)
370{
371 unsigned int cpu = MPIDR_AFFLVL0_VAL(read_mpidr_el1());
372
373 if (is_local_state_off(SYSTEM_PWR_STATE(target_state))) {
Jacky Bai478af8d2021-06-25 09:47:46 +0800374 /* restore the ap domain context */
375 imx_apd_ctx_restore(cpu);
376
377 /* clear the upower wakeup */
378 upwr_xcp_set_rtd_apd_llwu(APD_DOMAIN, 0, NULL);
379 upower_wait_resp();
380
381 /* disable all pad wakeup */
382 mmio_write_32(IMX_WUU1_BASE + 0x8, 0x0);
383
384 /* clear all the pad wakeup pending event */
385 mmio_write_32(IMX_WUU1_BASE + 0x20, 0xffffffff);
386
387 /*
388 * disable the usb wakeup after resume to make sure the pending
389 * usb wakeup in WUU can be cleared successfully, otherwise,
390 * APD will resume failed in next PD mode.
391 */
392 usb_wakeup_enable(false);
393
394 /* re-init the SCMI channel */
395 imx8ulp_init_scmi_server();
Jacky Baidaa44782023-09-18 22:08:52 +0800396 }
397
Jacky Bai478af8d2021-06-25 09:47:46 +0800398 /* clear cluster's LPM setting. */
399 mmio_write_32(IMX_CMC1_BASE + 0x20, 0x0);
400 mmio_write_32(IMX_CMC1_BASE + 0x10, 0x0);
Jacky Baidaa44782023-09-18 22:08:52 +0800401
402 /* clear core's LPM setting */
403 mmio_write_32(IMX_CMC1_BASE + 0x50 + 0x4 * cpu, 0x0);
404 mmio_write_32(IMX_SIM1_BASE + 0x3c + 0x4 * cpu, 0x0);
405
406 if (is_local_state_off(CORE_PWR_STATE(target_state))) {
407 imx_pwr_set_cpu_entry(0, IMX_ROM_ENTRY);
408 plat_gic_cpuif_enable();
409 } else {
410 dsb();
411 write_scr_el3(read_scr_el3() & (~SCR_FIQ_BIT));
412 isb();
413 }
414}
Jacky Baifcd41e82020-07-02 14:39:58 +0800415
416void __dead2 imx8ulp_pwr_domain_pwr_down_wfi(const psci_power_state_t *target_state)
417{
418 while (1) {
419 wfi();
420 }
421}
422
423void __dead2 imx8ulp_system_reset(void)
424{
425 imx_pwr_set_cpu_entry(0, IMX_ROM_ENTRY);
426
427 /* Write invalid command to WDOG CNT to trigger reset */
428 mmio_write_32(IMX_WDOG3_BASE + 0x4, 0x12345678);
429
430 while (true) {
431 wfi();
432 }
433}
434
Jacky Baidaa44782023-09-18 22:08:52 +0800435int imx_validate_power_state(unsigned int power_state,
436 psci_power_state_t *req_state)
437{
438 int pwr_lvl = psci_get_pstate_pwrlvl(power_state);
439 int pwr_type = psci_get_pstate_type(power_state);
440
441 if (pwr_lvl > PLAT_MAX_PWR_LVL) {
442 return PSCI_E_INVALID_PARAMS;
443 }
444
445 if (pwr_type == PSTATE_TYPE_STANDBY) {
446 CORE_PWR_STATE(req_state) = PLAT_MAX_RET_STATE;
447 CLUSTER_PWR_STATE(req_state) = PLAT_MAX_RET_STATE;
448 }
449
450 /* No power down state support */
451 if (pwr_type == PSTATE_TYPE_POWERDOWN) {
452 return PSCI_E_INVALID_PARAMS;
453 }
454
455 return PSCI_E_SUCCESS;
456}
457
458void imx_get_sys_suspend_power_state(psci_power_state_t *req_state)
459{
460 unsigned int i;
461
462 for (i = IMX_PWR_LVL0; i <= PLAT_MAX_PWR_LVL; i++) {
463 req_state->pwr_domain_state[i] = PLAT_POWER_DOWN_OFF_STATE;
464 }
465}
466
Jacky Bai891c5472023-09-18 21:53:15 +0800467void __dead2 imx_system_off(void)
468{
469 unsigned int i;
470
471 /* config the all the core into OFF mode and IRQ masked. */
472 for (i = 0U; i < PLATFORM_CORE_COUNT; i++) {
473 /* disable wakeup from wkpu */
474 mmio_write_32(WKPUx(i), 0x0);
475
476 /* reset the core reset entry to 0x1000 */
477 imx_pwr_set_cpu_entry(i, 0x1000);
478
479 /* config the core power mode to off */
480 mmio_write_32(AD_COREx_LPMODE(i), 0x3);
481 }
482
483 plat_gic_cpuif_disable();
484
Jacky Bai36af80c2021-10-20 11:25:30 +0800485 /* power off all the pad */
486 apd_io_pad_off();
487
Jacky Bai891c5472023-09-18 21:53:15 +0800488 /* Config the power mode info for entering DPD mode and ACT mode */
489 imx_set_pwr_mode_cfg(ADMA_PWR_MODE);
490 imx_set_pwr_mode_cfg(ACT_PWR_MODE);
491 imx_set_pwr_mode_cfg(DPD_PWR_MODE);
492
493 /* Set the APD domain into DPD mode */
494 mmio_write_32(IMX_CMC1_BASE + 0x10, 0x7);
495 mmio_write_32(IMX_CMC1_BASE + 0x20, 0x1f);
496
497 /* make sure no pending upower wakeup */
498 upwr_xcp_set_rtd_apd_llwu(APD_DOMAIN, 0, NULL);
499 upower_wait_resp();
500
501 /* enable the upower wakeup from wuu, act as APD boot up method */
502 mmio_write_32(IMX_PCC3_BASE + 0x98, 0xc0800000);
503 mmio_setbits_32(IMX_WUU1_BASE + 0x18, BIT(4));
504
505 /* make sure no pad wakeup event is pending */
506 mmio_write_32(IMX_WUU1_BASE + 0x20, 0xffffffff);
507
508 wfi();
509
510 ERROR("power off failed.\n");
511 panic();
512}
513
Jacky Baifcd41e82020-07-02 14:39:58 +0800514static const plat_psci_ops_t imx_plat_psci_ops = {
515 .pwr_domain_on = imx_pwr_domain_on,
516 .pwr_domain_on_finish = imx_pwr_domain_on_finish,
517 .validate_ns_entrypoint = imx_validate_ns_entrypoint,
Jacky Bai891c5472023-09-18 21:53:15 +0800518 .system_off = imx_system_off,
Jacky Baifcd41e82020-07-02 14:39:58 +0800519 .system_reset = imx8ulp_system_reset,
520 .pwr_domain_off = imx_pwr_domain_off,
Jacky Baidaa44782023-09-18 22:08:52 +0800521 .pwr_domain_suspend = imx_domain_suspend,
522 .pwr_domain_suspend_finish = imx_domain_suspend_finish,
523 .get_sys_suspend_power_state = imx_get_sys_suspend_power_state,
524 .validate_power_state = imx_validate_power_state,
Jacky Baifcd41e82020-07-02 14:39:58 +0800525 .pwr_domain_pwr_down_wfi = imx8ulp_pwr_domain_pwr_down_wfi,
526};
527
528int plat_setup_psci_ops(uintptr_t sec_entrypoint,
529 const plat_psci_ops_t **psci_ops)
530{
531 secure_entrypoint = sec_entrypoint;
532 imx_pwr_set_cpu_entry(0, sec_entrypoint);
533 *psci_ops = &imx_plat_psci_ops;
534
535 mmio_write_32(IMX_CMC1_BASE + 0x18, 0x3f);
536 mmio_write_32(IMX_SIM1_BASE + 0x3c, 0xffffffff);
537
538 return 0;
539}