pmu.c 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543
  1. /*
  2. * Copyright (c) 2023, ARM Limited and Contributors. All rights reserved.
  3. *
  4. * The power management unit (PMU) is designed for controlling power resources.
  5. * The PMU is dedicated for managing the power of the whole chip.
  6. *
  7. * SPDX-License-Identifier: BSD-3-Clause
  8. */
  9. #include <assert.h>
  10. #include <errno.h>
  11. #include <bakery_lock.h>
  12. #include <cortex_a55.h>
  13. #include <dsu_def.h>
  14. #include <mmio.h>
  15. #include <platform.h>
  16. #include <platform_def.h>
  17. #include <pmu.h>
  18. #include <cpus_on_fixed_addr.h>
  19. #include <plat_private.h>
  20. #include <soc.h>
  21. /*
  22. * Use this macro to instantiate lock before it is used in below
  23. * rockchip_pd_lock_xxx() macros
  24. */
  25. DECLARE_BAKERY_LOCK(rockchip_pd_lock);
  26. static uint32_t grf_ddr_con3;
  27. static struct psram_data_t *psram_sleep_cfg =
  28. (struct psram_data_t *)&sys_sleep_flag_sram;
  29. /*
  30. * These are wrapper macros to the powe domain Bakery Lock API.
  31. */
  32. #define rockchip_pd_lock_init() bakery_lock_init(&rockchip_pd_lock)
  33. #define rockchip_pd_lock_get() bakery_lock_get(&rockchip_pd_lock)
  34. #define rockchip_pd_lock_rls() bakery_lock_release(&rockchip_pd_lock)
  35. void __dead2 rockchip_soc_sys_pd_pwr_dn_wfi(void)
  36. {
  37. uint64_t ctrl;
  38. __asm__ volatile ("mrs %0, " __XSTRING(CORTEX_A55_CPUPWRCTLR_EL1) : "=r" (ctrl));
  39. ctrl |= 0x01;
  40. __asm__ volatile ("msr " __XSTRING(CORTEX_A55_CPUPWRCTLR_EL1) ", %0" : : "r" (ctrl));
  41. isb();
  42. while (1)
  43. wfi();
  44. }
  45. static void pmu_pmic_sleep_mode_config(void)
  46. {
  47. /* pmic sleep function selection
  48. * 1'b0: From reset pulse generator, can reset external PMIC
  49. * 1'b1: From pmu block, only support sleep function for external PMIC
  50. */
  51. mmio_write_32(PMUGRF_BASE + PMU_GRF_SOC_CON(0), WRITE_MASK_SET(BIT(7)));
  52. mmio_write_32(PMUGRF_BASE + PMU_GRF_GPIO0A_IOMUX_L, PMIC_SLEEP_FUN);
  53. }
  54. static void pmu_wakeup_source_config(void)
  55. {
  56. /* config wakeup source */
  57. mmio_write_32(PMU_BASE + PMU_WAKEUP_INT_CON, WRITE_MASK_SET(BIT(WAKEUP_GPIO0_INT_EN)));
  58. INFO("WAKEUP: PMU_WAKEUP_INT_CON:0x%x, reg: 0x%x\n",
  59. mmio_read_32(PMU_BASE + PMU_WAKEUP_INT_CON), PMU_WAKEUP_INT_CON);
  60. }
  61. static void pmu_pll_powerdown_config(void)
  62. {
  63. uint32_t pll_id;
  64. /* PLL power down by PMU */
  65. pll_id = BIT(APLL_PD_ENA) |
  66. BIT(CPLL_PD_ENA) |
  67. BIT(GPLL_PD_ENA) |
  68. BIT(MPLL_PD_ENA) |
  69. BIT(NPLL_PD_ENA) |
  70. BIT(HPLL_PD_ENA) |
  71. BIT(PPLL_PD_ENA) |
  72. BIT(VPLL_PD_ENA);
  73. mmio_write_32(PMU_BASE + PMU_PLLPD_CON, WRITE_MASK_SET(pll_id));
  74. INFO("PLL: PMU_PLLPD_CON(0x%x):0x%x\n",
  75. PMU_PLLPD_CON, mmio_read_32(PMU_BASE + PMU_PLLPD_CON));
  76. }
  77. static void pmu_stable_count_config(void)
  78. {
  79. mmio_write_32(PMU_BASE + PMU_DSU_STABLE_CNT, 0x180);
  80. mmio_write_32(PMU_BASE + PMU_PMIC_STABLE_CNT, 0x180);
  81. mmio_write_32(PMU_BASE + PMU_OSC_STABLE_CNT, 0x180);
  82. mmio_write_32(PMU_BASE + PMU_WAKEUP_RSTCLR_CNT, 0x180);
  83. mmio_write_32(PMU_BASE + PMU_PLL_LOCK_CNT, 0x180);
  84. mmio_write_32(PMU_BASE + PMU_DSU_PWRUP_CNT, 0x180);
  85. mmio_write_32(PMU_BASE + PMU_DSU_PWRDN_CNT, 0x180);
  86. mmio_write_32(PMU_BASE + PMU_GPU_VOLUP_CNT, 0x180);
  87. mmio_write_32(PMU_BASE + PMU_GPU_VOLDN_CNT, 0x180);
  88. mmio_write_32(PMU_BASE + PMU_WAKEUP_TIMEOUT_CNT, 0x180);
  89. mmio_write_32(PMU_BASE + PMU_PWM_SWITCH_CNT, 0x180);
  90. mmio_write_32(PMU_BASE + PMU_DBG_RST_CNT, 0x180);
  91. }
  92. static void pmu_pd_powerdown_config(void)
  93. {
  94. uint32_t pwr_gate_con, pwr_dwn_st, pmu_bus_idle_con0 = 0;
  95. uint32_t pmu_bus_idle_con1;
  96. /* Pd power down by PMU */
  97. pwr_dwn_st = mmio_read_32(PMU_BASE + PMU_PWR_DWN_ST);
  98. pwr_gate_con = ~pwr_dwn_st & 0x3ff;
  99. if (pwr_gate_con & BIT(PD_GPU_DWN_ENA)) {
  100. pmu_bus_idle_con0 |= BIT(IDLE_REQ_GPU);
  101. }
  102. if (pwr_gate_con & BIT(PD_NPU_DWN_ENA)) {
  103. pmu_bus_idle_con0 |= BIT(IDLE_REQ_NPU);
  104. }
  105. if (pwr_gate_con & BIT(PD_RKVENC_DWN_ENA)) {
  106. pmu_bus_idle_con0 |= BIT(IDLE_REQ_RKVENC);
  107. }
  108. if (pwr_gate_con & BIT(PD_RKVDEC_DWN_ENA)) {
  109. pmu_bus_idle_con0 |= BIT(IDLE_REQ_RKVDEC);
  110. }
  111. if (pwr_gate_con & BIT(PD_RGA_DWN_ENA)) {
  112. pmu_bus_idle_con0 |= BIT(IDLE_REQ_RGA);
  113. }
  114. if (pwr_gate_con & BIT(PD_VI_DWN_ENA)) {
  115. pmu_bus_idle_con0 |= BIT(IDLE_REQ_VI);
  116. }
  117. if (pwr_gate_con & BIT(PD_VO_DWN_ENA)) {
  118. pmu_bus_idle_con0 |= BIT(IDLE_REQ_VO);
  119. }
  120. if (pwr_gate_con & BIT(PD_PIPE_DWN_ENA)) {
  121. pmu_bus_idle_con0 |= BIT(IDLE_REQ_PIPE);
  122. }
  123. pmu_bus_idle_con0 |= BIT(IDLE_REQ_GIC_AUDIO) |
  124. BIT(IDLE_REQ_MSCH) |
  125. BIT(IDLE_REQ_PHP) |
  126. BIT(IDLE_REQ_SECURE_FLASH) |
  127. BIT(IDLE_REQ_PERIMID) |
  128. BIT(IDLE_REQ_USB) |
  129. BIT(IDLE_REQ_BUS);
  130. /* Enable power down PD by PMU automatically */
  131. pwr_gate_con |= (BIT(PD_GPU_DWN_ENA) |
  132. BIT(PD_NPU_DWN_ENA) |
  133. BIT(PD_VPU_DWN_ENA) |
  134. BIT(PD_RKVENC_DWN_ENA) |
  135. BIT(PD_RKVDEC_DWN_ENA) |
  136. BIT(PD_RGA_DWN_ENA) |
  137. BIT(PD_VI_DWN_ENA) |
  138. BIT(PD_VO_DWN_ENA) |
  139. BIT(PD_PIPE_DWN_ENA)) << 16;
  140. pmu_bus_idle_con1 = 0;
  141. mmio_write_32(PMU_BASE + PMU_PWR_GATE_CON, pwr_gate_con);
  142. mmio_write_32(PMU_BASE + PMU_BUS_IDLE_CON0, WRITE_MASK_SET(pmu_bus_idle_con0));
  143. mmio_write_32(PMU_BASE + PMU_BUS_IDLE_CON1, WRITE_MASK_SET(pmu_bus_idle_con1));
  144. /* When perform idle operation,
  145. * corresponding clock can be opened or gated automatically
  146. */
  147. mmio_write_32(PMU_BASE + PMU_NOC_AUTO_CON0, 0xffffffff);
  148. mmio_write_32(PMU_BASE + PMU_NOC_AUTO_CON1, 0x00070007);
  149. mmio_write_32(PMU_BASE + PMU_VOL_GATE_SFTCON, WRITE_MASK_SET(BIT(VD_NPU_ENA)));
  150. mmio_write_32(PMU_BASE + PMU_PWR_CON, WRITE_MASK_CLR(BIT(PWRDN_BYPASS)));
  151. mmio_write_32(PMU_BASE + PMU_PWR_CON, WRITE_MASK_CLR(BIT(BUS_BYPASS)));
  152. INFO("PD & BUS:PMU_PWR_DWN_ST(0x%x):0x%x\n",
  153. PMU_PWR_DWN_ST, mmio_read_32(PMU_BASE + PMU_PWR_DWN_ST));
  154. INFO("PD & BUS:PMU_PWR_GATE_CON(0x%x):0x%x\n",
  155. PMU_PWR_GATE_CON, mmio_read_32(PMU_BASE + PMU_PWR_GATE_CON));
  156. INFO("PD & BUS:PMU_BUS_IDLE_CON0(0x%x):0x%x\n",
  157. PMU_BUS_IDLE_CON0, mmio_read_32(PMU_BASE + PMU_BUS_IDLE_CON0));
  158. INFO("PD & BUS:PMU_BUS_IDLE_CON1(0x%x):0x%x\n",
  159. PMU_BUS_IDLE_CON1, mmio_read_32(PMU_BASE + PMU_BUS_IDLE_CON1));
  160. INFO("PD & BUS:PMU_PWR_CON(0x%x):0x%x\n",
  161. PMU_PWR_CON, mmio_read_32(PMU_BASE + PMU_PWR_CON));
  162. }
  163. static void pmu_ddr_suspend_config(void)
  164. {
  165. uint32_t pmu_ddr_pwr_con;
  166. pmu_ddr_pwr_con = BIT(DDR_SREF_ENA) |
  167. BIT(DDRIO_RET_ENTER_ENA) |
  168. BIT(DDRIO_RET_EXIT_ENA) |
  169. BIT(DDRPHY_AUTO_GATING_ENA);
  170. mmio_write_32(PMU_BASE + PMU_DDR_PWR_CON, WRITE_MASK_SET(pmu_ddr_pwr_con));
  171. /* DPLL power down by PMU */
  172. mmio_write_32(PMU_BASE + PMU_PLLPD_CON, WRITE_MASK_SET(BIT(DPLL_PD_ENA)));
  173. mmio_write_32(PMU_BASE + PMU_PWR_CON, WRITE_MASK_CLR(BIT(DDR_BYPASS)));
  174. grf_ddr_con3 = mmio_read_32(DDRGRF_BASE + GRF_DDR_CON3);
  175. mmio_write_32(DDRGRF_BASE + GRF_DDR_CON3, 0x00600020);
  176. pmu_ddr_pwr_con = mmio_read_32(PMU_BASE + PMU_DDR_PWR_CON);
  177. INFO("DDR: PMU_PLLPD_CON(0x%x):0x%x\n",
  178. PMU_PLLPD_CON, mmio_read_32(PMU_BASE + PMU_PLLPD_CON));
  179. INFO("DDR: PMU_DDR_PWR_CON(0x%x):\t0x%x\n",
  180. PMU_DDR_PWR_CON, pmu_ddr_pwr_con);
  181. if (pmu_ddr_pwr_con & BIT(DDR_SREF_ENA)) {
  182. INFO("\t DDR_SREF_ENA\n");
  183. }
  184. if (pmu_ddr_pwr_con & BIT(DDRIO_RET_ENTER_ENA)) {
  185. INFO("\t DDRIO_RET_ENTER_ENA\n");
  186. }
  187. if (pmu_ddr_pwr_con & BIT(DDRIO_RET_EXIT_ENA)) {
  188. INFO("\t DDRIO_RET_EXIT_ENA\n");
  189. }
  190. if (pmu_ddr_pwr_con & BIT(DDRPHY_AUTO_GATING_ENA)) {
  191. INFO("\t DDRPHY_AUTO_GATING_ENA\n");
  192. }
  193. }
  194. static void pmu_dsu_suspend_config(void)
  195. {
  196. uint32_t pmu_dsu_pwr_con;
  197. pmu_dsu_pwr_con = BIT(DSU_PWRDN_ENA);
  198. mmio_write_32(PMU_BASE + PMU_CLUSTER_IDLE_CON, 0x000f000f);
  199. mmio_write_32(PMU_BASE + PMU_DSU_PWR_CON, WRITE_MASK_SET(pmu_dsu_pwr_con));
  200. mmio_write_32(PMU_BASE + PMU_PWR_CON, WRITE_MASK_CLR(BIT(DSU_BYPASS)));
  201. dsu_pwr_dwn();
  202. INFO("DSU: PMU_DSU_PWR_CON(0x%x): 0x%x\n",
  203. PMU_DSU_PWR_CON, mmio_read_32(PMU_BASE + PMU_DSU_PWR_CON));
  204. INFO("DSU: PMU_CLUSTER_IDLE_CON(0x%x),: 0x%x\n",
  205. PMU_CLUSTER_IDLE_CON, mmio_read_32(PMU_BASE + PMU_CLUSTER_IDLE_CON));
  206. INFO("DSU: PMU_PWR_CON(0x%x),: 0x%x\n",
  207. PMU_PWR_CON, mmio_read_32(PMU_BASE + PMU_PWR_CON));
  208. }
  209. static void pmu_cpu_powerdown_config(void)
  210. {
  211. uint32_t pmu_cluster_pwr_st, cpus_state, cpus_bypass;
  212. pmu_cluster_pwr_st = mmio_read_32(PMU_BASE + PMU_CLUSTER_PWR_ST);
  213. cpus_state = pmu_cluster_pwr_st & 0x0f;
  214. cpus_bypass = cpus_state << CPU0_BYPASS;
  215. INFO("CPU: PMU_CLUSTER_PWR_ST(0x%x):0x%x\n",
  216. PMU_CLUSTER_PWR_ST, mmio_read_32(PMU_BASE + PMU_CLUSTER_PWR_ST));
  217. mmio_write_32(PMU_BASE + PMU_PWR_CON, (0xf << (16 + CPU0_BYPASS)) | cpus_bypass);
  218. INFO("CPU: PMU_PWR_CON(0x%x), 0x%x\n",
  219. PMU_PWR_CON, mmio_read_32(PMU_BASE + PMU_PWR_CON));
  220. }
  221. static void pvtm_32k_config(void)
  222. {
  223. uint32_t pmu_cru_pwr_con;
  224. uint32_t pvtm_freq_khz, pvtm_div;
  225. mmio_write_32(PMUCRU_BASE + PMUCRU_PMUGATE_CON01, 0x38000000);
  226. mmio_write_32(PMUPVTM_BASE + PVTM_CON0, 0x00020002);
  227. dsb();
  228. mmio_write_32(PMUPVTM_BASE + PVTM_CON0, 0x001c0000);
  229. mmio_write_32(PMUPVTM_BASE + PVTM_CON1, PVTM_CALC_CNT);
  230. dsb();
  231. mmio_write_32(PMUPVTM_BASE + PVTM_CON0, 0x00010001);
  232. dsb();
  233. while (mmio_read_32(PMUPVTM_BASE + PVTM_STATUS1) < 30) {
  234. ;
  235. }
  236. dsb();
  237. while (!(mmio_read_32(PMUPVTM_BASE + PVTM_STATUS0) & 0x1)) {
  238. ;
  239. }
  240. pvtm_freq_khz = (mmio_read_32(PMUPVTM_BASE + PVTM_STATUS1) * 24000 +
  241. PVTM_CALC_CNT / 2) / PVTM_CALC_CNT;
  242. pvtm_div = (pvtm_freq_khz + 16) / 32;
  243. mmio_write_32(PMUGRF_BASE + PMU_GRF_DLL_CON0, pvtm_div);
  244. mmio_write_32(PMUCRU_BASE + PMUCRU_PMUCLKSEL_CON00, 0x00c00000);
  245. pmu_cru_pwr_con = BIT(ALIVE_32K_ENA) | BIT(OSC_DIS_ENA);
  246. mmio_write_32(PMU_BASE + PMU_WAKEUP_TIMEOUT_CNT, 32000 * 10);
  247. mmio_write_32(PMU_BASE + PMU_CRU_PWR_CON, WRITE_MASK_SET(pmu_cru_pwr_con));
  248. INFO("PVTM: PMU_CRU_PWR_CON(0x0%x): 0x%x\n",
  249. PMU_CRU_PWR_CON, mmio_read_32(PMU_BASE + PMU_CRU_PWR_CON));
  250. }
  251. static void pmu_cru_suspendmode_config(void)
  252. {
  253. uint32_t pmu_cru_pwr_con;
  254. pmu_cru_pwr_con = BIT(ALIVE_OSC_ENA);
  255. mmio_write_32(PMU_BASE + PMU_CRU_PWR_CON, WRITE_MASK_SET(pmu_cru_pwr_con));
  256. INFO("CRU: PMU_CRU_PWR_CON(0x0%x): 0x%x\n",
  257. PMU_CRU_PWR_CON, mmio_read_32(PMU_BASE + PMU_CRU_PWR_CON));
  258. }
  259. static void pmu_suspend_cru_fsm(void)
  260. {
  261. pmu_pmic_sleep_mode_config();
  262. /* Global interrupt disable */
  263. mmio_write_32(PMU_BASE + PMU_INT_MASK_CON, CLB_INT_DISABLE);
  264. mmio_write_32(PMU_BASE + PMU_PWR_CON, CPUS_BYPASS);
  265. pmu_stable_count_config();
  266. pmu_wakeup_source_config();
  267. mmio_write_32(PMU_BASE + PMU_WAKEUP_TIMEOUT_CNT, 0x5dc0 * 20000);
  268. /* default cru config */
  269. mmio_write_32(PMU_BASE + PMU_CRU_PWR_CON, WRITE_MASK_SET(BIT(ALIVE_OSC_ENA)));
  270. pmu_cru_suspendmode_config();
  271. pmu_cpu_powerdown_config();
  272. pmu_pll_powerdown_config();
  273. pmu_pd_powerdown_config();
  274. pmu_ddr_suspend_config();
  275. pmu_dsu_suspend_config();
  276. pvtm_32k_config();
  277. mmio_write_32(PMU_BASE + PMU_PWR_CON, 0x00010001);
  278. }
  279. static void pmu_reinit(void)
  280. {
  281. mmio_write_32(DDRGRF_BASE + GRF_DDR_CON3, grf_ddr_con3 | 0xffff0000);
  282. mmio_write_32(PMU_BASE + PMU_PWR_CON, 0xffff0000);
  283. mmio_write_32(PMU_BASE + PMU_INT_MASK_CON, 0xffff0000);
  284. mmio_write_32(PMU_BASE + PMU_WAKEUP_INT_CON, 0xffff0000);
  285. mmio_write_32(PMU_BASE + PMU_BUS_IDLE_CON0, 0xffff0000);
  286. mmio_write_32(PMU_BASE + PMU_DDR_PWR_CON, 0xffff0000);
  287. mmio_write_32(PMU_BASE + PMU_BUS_IDLE_CON1, 0xffff0000);
  288. mmio_write_32(PMU_BASE + PMU_PWR_GATE_CON, 0xffff0000);
  289. mmio_write_32(PMU_BASE + PMU_VOL_GATE_SFTCON, 0xffff0000);
  290. mmio_write_32(PMU_BASE + PMU_CRU_PWR_CON, 0xffff0000);
  291. mmio_write_32(PMU_BASE + PMU_PLLPD_CON, 0xffff0000);
  292. mmio_write_32(PMU_BASE + PMU_INFO_TX_CON, 0xffff0000);
  293. mmio_write_32(PMU_BASE + PMU_DSU_PWR_CON, 0xffff0000);
  294. mmio_write_32(PMU_BASE + PMU_CLUSTER_IDLE_CON, 0xffff0000);
  295. }
  296. void rockchip_plat_mmu_el3(void)
  297. {
  298. }
  299. int rockchip_soc_cores_pwr_dm_suspend(void)
  300. {
  301. return 0;
  302. }
  303. int rockchip_soc_cores_pwr_dm_resume(void)
  304. {
  305. return 0;
  306. }
  307. int rockchip_soc_sys_pwr_dm_suspend(void)
  308. {
  309. psram_sleep_cfg->pm_flag = 0;
  310. flush_dcache_range((uintptr_t)&(psram_sleep_cfg->pm_flag),
  311. sizeof(uint32_t));
  312. pmu_suspend_cru_fsm();
  313. return 0;
  314. }
  315. int rockchip_soc_sys_pwr_dm_resume(void)
  316. {
  317. pmu_reinit();
  318. plat_rockchip_gic_cpuif_enable();
  319. psram_sleep_cfg->pm_flag = PM_WARM_BOOT_BIT;
  320. flush_dcache_range((uintptr_t)&(psram_sleep_cfg->pm_flag),
  321. sizeof(uint32_t));
  322. return 0;
  323. }
  324. static int cpus_power_domain_off(uint32_t cpu_id, uint32_t pd_cfg)
  325. {
  326. uint32_t apm_value, offset, idx;
  327. apm_value = BIT(core_pm_en) | BIT(core_pm_int_wakeup_glb_msk);
  328. if (pd_cfg == core_pwr_wfi_int) {
  329. apm_value |= BIT(core_pm_int_wakeup_en);
  330. }
  331. idx = cpu_id / 2;
  332. offset = (cpu_id % 2) << 3;
  333. mmio_write_32(PMU_BASE + PMU_CPUAPM_CON(idx),
  334. BITS_WITH_WMASK(apm_value, 0xf, offset));
  335. dsb();
  336. return 0;
  337. }
  338. static int cpus_power_domain_on(uint32_t cpu_id)
  339. {
  340. uint32_t offset, idx;
  341. idx = cpu_id / 2;
  342. offset = (cpu_id % 2) << 3;
  343. mmio_write_32(PMU_BASE + PMU_CPUAPM_CON(idx),
  344. WMSK_BIT(core_pm_en + offset));
  345. mmio_write_32(PMU_BASE + PMU_CPUAPM_CON(idx),
  346. BIT_WITH_WMSK(core_pm_sft_wakeup_en + offset));
  347. dsb();
  348. return 0;
  349. }
  350. int rockchip_soc_cores_pwr_dm_on(unsigned long mpidr, uint64_t entrypoint)
  351. {
  352. uint32_t cpu_id = plat_core_pos_by_mpidr(mpidr);
  353. assert(cpu_id < PLATFORM_CORE_COUNT);
  354. cpuson_flags[cpu_id] = PMU_CPU_HOTPLUG;
  355. cpuson_entry_point[cpu_id] = entrypoint;
  356. flush_dcache_range((uintptr_t)cpuson_flags, sizeof(cpuson_flags));
  357. flush_dcache_range((uintptr_t)cpuson_entry_point,
  358. sizeof(cpuson_entry_point));
  359. cpus_power_domain_on(cpu_id);
  360. return 0;
  361. }
  362. int rockchip_soc_cores_pwr_dm_off(void)
  363. {
  364. uint32_t cpu_id = plat_my_core_pos();
  365. cpus_power_domain_off(cpu_id,
  366. core_pwr_wfi);
  367. return 0;
  368. }
  369. int rockchip_soc_cores_pwr_dm_on_finish(void)
  370. {
  371. uint32_t cpu_id = plat_my_core_pos();
  372. uint32_t offset, idx;
  373. /* Disable core_pm */
  374. idx = cpu_id / 2;
  375. offset = (cpu_id % 2) << 3;
  376. mmio_write_32(PMU_BASE + PMU_CPUAPM_CON(idx),
  377. BITS_WITH_WMASK(0, 0xf, offset));
  378. return 0;
  379. }
  380. static void nonboot_cpus_off(void)
  381. {
  382. uint32_t tmp;
  383. cpus_power_domain_off(1, 0);
  384. cpus_power_domain_off(2, 0);
  385. cpus_power_domain_off(3, 0);
  386. mmio_write_32(SYSSRAM_BASE + 0x04, 0xdeadbeaf);
  387. mmio_write_32(SYSSRAM_BASE + 0x08, (uintptr_t)&rockchip_soc_sys_pd_pwr_dn_wfi);
  388. sev();
  389. do {
  390. tmp = mmio_read_32(PMU_BASE + PMU_CLUSTER_PWR_ST);
  391. } while ((tmp & 0xe) != 0xe);
  392. }
  393. void plat_rockchip_pmu_init(void)
  394. {
  395. uint32_t cpu;
  396. rockchip_pd_lock_init();
  397. nonboot_cpus_off();
  398. for (cpu = 0; cpu < PLATFORM_CORE_COUNT; cpu++)
  399. cpuson_flags[cpu] = PMU_CPU_HOTPLUG;
  400. psram_sleep_cfg->ddr_data = (uint64_t)0;
  401. psram_sleep_cfg->sp = PSRAM_SP_TOP;
  402. psram_sleep_cfg->ddr_flag = 0x00;
  403. psram_sleep_cfg->boot_mpidr = read_mpidr_el1() & 0xffff;
  404. psram_sleep_cfg->pm_flag = PM_WARM_BOOT_BIT;
  405. /*
  406. * When perform idle operation, corresponding clock can be
  407. * opened or gated automatically.
  408. */
  409. mmio_write_32(PMU_BASE + PMU_NOC_AUTO_CON0, 0xffffffff);
  410. mmio_write_32(PMU_BASE + PMU_NOC_AUTO_CON1, 0x00070007);
  411. /* grf_con_pmic_sleep_sel
  412. * pmic sleep function selection
  413. * 1'b0: From reset pulse generator, can reset external PMIC
  414. * 1'b1: From pmu block, only support sleep function for external PMIC
  415. */
  416. mmio_write_32(PMUGRF_BASE + PMU_GRF_SOC_CON(0), 0x00800080);
  417. /*
  418. * force jtag control
  419. * 1'b0: CPU debug port IO mux is controlled by sdmmc_detect_en status
  420. * 1'b0: CPU debug port IO mux IS controlled by GRF
  421. */
  422. mmio_write_32(SGRF_BASE + 0x008, 0x00100000);
  423. /*
  424. * remap
  425. * 2'b00: Boot from boot-rom.
  426. * 2'b01: Boot from pmu mem.
  427. * 2'b10: Boot from sys mem.
  428. */
  429. mmio_write_32(PMUSGRF_BASE + PMU_SGRF_SOC_CON1, 0x18000800);
  430. }