imx8ulp_psci.c 14 KB

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