19fd9f1d0Sshengfei Xu /*
2*4e1ccc60SShengfei Xu * Copyright (c) 2023-2025, ARM Limited and Contributors. All rights reserved.
39fd9f1d0Sshengfei Xu *
49fd9f1d0Sshengfei Xu * The power management unit (PMU) is designed for controlling power resources.
59fd9f1d0Sshengfei Xu * The PMU is dedicated for managing the power of the whole chip.
69fd9f1d0Sshengfei Xu *
79fd9f1d0Sshengfei Xu * SPDX-License-Identifier: BSD-3-Clause
89fd9f1d0Sshengfei Xu */
99fd9f1d0Sshengfei Xu
109fd9f1d0Sshengfei Xu #include <assert.h>
119fd9f1d0Sshengfei Xu #include <errno.h>
129fd9f1d0Sshengfei Xu
139fd9f1d0Sshengfei Xu #include <bakery_lock.h>
149fd9f1d0Sshengfei Xu #include <cortex_a55.h>
159fd9f1d0Sshengfei Xu #include <dsu_def.h>
169fd9f1d0Sshengfei Xu #include <mmio.h>
179fd9f1d0Sshengfei Xu #include <platform.h>
189fd9f1d0Sshengfei Xu #include <platform_def.h>
199fd9f1d0Sshengfei Xu #include <pmu.h>
209fd9f1d0Sshengfei Xu
219fd9f1d0Sshengfei Xu #include <cpus_on_fixed_addr.h>
229fd9f1d0Sshengfei Xu #include <plat_private.h>
23*4e1ccc60SShengfei Xu #include <rk3568_clk.h>
249fd9f1d0Sshengfei Xu #include <soc.h>
259fd9f1d0Sshengfei Xu
269fd9f1d0Sshengfei Xu /*
279fd9f1d0Sshengfei Xu * Use this macro to instantiate lock before it is used in below
289fd9f1d0Sshengfei Xu * rockchip_pd_lock_xxx() macros
299fd9f1d0Sshengfei Xu */
309fd9f1d0Sshengfei Xu DECLARE_BAKERY_LOCK(rockchip_pd_lock);
319fd9f1d0Sshengfei Xu
329fd9f1d0Sshengfei Xu static uint32_t grf_ddr_con3;
339fd9f1d0Sshengfei Xu static struct psram_data_t *psram_sleep_cfg =
349fd9f1d0Sshengfei Xu (struct psram_data_t *)&sys_sleep_flag_sram;
359fd9f1d0Sshengfei Xu
369fd9f1d0Sshengfei Xu /*
379fd9f1d0Sshengfei Xu * These are wrapper macros to the powe domain Bakery Lock API.
389fd9f1d0Sshengfei Xu */
399fd9f1d0Sshengfei Xu #define rockchip_pd_lock_init() bakery_lock_init(&rockchip_pd_lock)
409fd9f1d0Sshengfei Xu #define rockchip_pd_lock_get() bakery_lock_get(&rockchip_pd_lock)
419fd9f1d0Sshengfei Xu #define rockchip_pd_lock_rls() bakery_lock_release(&rockchip_pd_lock)
429fd9f1d0Sshengfei Xu
rockchip_soc_sys_pd_pwr_dn_wfi(void)439fd9f1d0Sshengfei Xu void __dead2 rockchip_soc_sys_pd_pwr_dn_wfi(void)
449fd9f1d0Sshengfei Xu {
459fd9f1d0Sshengfei Xu uint64_t ctrl;
469fd9f1d0Sshengfei Xu
479fd9f1d0Sshengfei Xu __asm__ volatile ("mrs %0, " __XSTRING(CORTEX_A55_CPUPWRCTLR_EL1) : "=r" (ctrl));
489fd9f1d0Sshengfei Xu ctrl |= 0x01;
499fd9f1d0Sshengfei Xu __asm__ volatile ("msr " __XSTRING(CORTEX_A55_CPUPWRCTLR_EL1) ", %0" : : "r" (ctrl));
509fd9f1d0Sshengfei Xu isb();
519fd9f1d0Sshengfei Xu
529fd9f1d0Sshengfei Xu while (1)
539fd9f1d0Sshengfei Xu wfi();
549fd9f1d0Sshengfei Xu }
559fd9f1d0Sshengfei Xu
pmu_pmic_sleep_mode_config(void)569fd9f1d0Sshengfei Xu static void pmu_pmic_sleep_mode_config(void)
579fd9f1d0Sshengfei Xu {
589fd9f1d0Sshengfei Xu /* pmic sleep function selection
599fd9f1d0Sshengfei Xu * 1'b0: From reset pulse generator, can reset external PMIC
609fd9f1d0Sshengfei Xu * 1'b1: From pmu block, only support sleep function for external PMIC
619fd9f1d0Sshengfei Xu */
629fd9f1d0Sshengfei Xu mmio_write_32(PMUGRF_BASE + PMU_GRF_SOC_CON(0), WRITE_MASK_SET(BIT(7)));
639fd9f1d0Sshengfei Xu mmio_write_32(PMUGRF_BASE + PMU_GRF_GPIO0A_IOMUX_L, PMIC_SLEEP_FUN);
649fd9f1d0Sshengfei Xu }
659fd9f1d0Sshengfei Xu
pmu_wakeup_source_config(void)669fd9f1d0Sshengfei Xu static void pmu_wakeup_source_config(void)
679fd9f1d0Sshengfei Xu {
689fd9f1d0Sshengfei Xu /* config wakeup source */
699fd9f1d0Sshengfei Xu mmio_write_32(PMU_BASE + PMU_WAKEUP_INT_CON, WRITE_MASK_SET(BIT(WAKEUP_GPIO0_INT_EN)));
709fd9f1d0Sshengfei Xu
719fd9f1d0Sshengfei Xu INFO("WAKEUP: PMU_WAKEUP_INT_CON:0x%x, reg: 0x%x\n",
729fd9f1d0Sshengfei Xu mmio_read_32(PMU_BASE + PMU_WAKEUP_INT_CON), PMU_WAKEUP_INT_CON);
739fd9f1d0Sshengfei Xu }
749fd9f1d0Sshengfei Xu
pmu_pll_powerdown_config(void)759fd9f1d0Sshengfei Xu static void pmu_pll_powerdown_config(void)
769fd9f1d0Sshengfei Xu {
779fd9f1d0Sshengfei Xu uint32_t pll_id;
789fd9f1d0Sshengfei Xu
799fd9f1d0Sshengfei Xu /* PLL power down by PMU */
809fd9f1d0Sshengfei Xu pll_id = BIT(APLL_PD_ENA) |
819fd9f1d0Sshengfei Xu BIT(CPLL_PD_ENA) |
829fd9f1d0Sshengfei Xu BIT(GPLL_PD_ENA) |
839fd9f1d0Sshengfei Xu BIT(MPLL_PD_ENA) |
849fd9f1d0Sshengfei Xu BIT(NPLL_PD_ENA) |
859fd9f1d0Sshengfei Xu BIT(HPLL_PD_ENA) |
869fd9f1d0Sshengfei Xu BIT(PPLL_PD_ENA) |
879fd9f1d0Sshengfei Xu BIT(VPLL_PD_ENA);
889fd9f1d0Sshengfei Xu mmio_write_32(PMU_BASE + PMU_PLLPD_CON, WRITE_MASK_SET(pll_id));
899fd9f1d0Sshengfei Xu INFO("PLL: PMU_PLLPD_CON(0x%x):0x%x\n",
909fd9f1d0Sshengfei Xu PMU_PLLPD_CON, mmio_read_32(PMU_BASE + PMU_PLLPD_CON));
919fd9f1d0Sshengfei Xu }
929fd9f1d0Sshengfei Xu
pmu_stable_count_config(void)939fd9f1d0Sshengfei Xu static void pmu_stable_count_config(void)
949fd9f1d0Sshengfei Xu {
959fd9f1d0Sshengfei Xu mmio_write_32(PMU_BASE + PMU_DSU_STABLE_CNT, 0x180);
969fd9f1d0Sshengfei Xu mmio_write_32(PMU_BASE + PMU_PMIC_STABLE_CNT, 0x180);
979fd9f1d0Sshengfei Xu mmio_write_32(PMU_BASE + PMU_OSC_STABLE_CNT, 0x180);
989fd9f1d0Sshengfei Xu mmio_write_32(PMU_BASE + PMU_WAKEUP_RSTCLR_CNT, 0x180);
999fd9f1d0Sshengfei Xu mmio_write_32(PMU_BASE + PMU_PLL_LOCK_CNT, 0x180);
1009fd9f1d0Sshengfei Xu mmio_write_32(PMU_BASE + PMU_DSU_PWRUP_CNT, 0x180);
1019fd9f1d0Sshengfei Xu mmio_write_32(PMU_BASE + PMU_DSU_PWRDN_CNT, 0x180);
1029fd9f1d0Sshengfei Xu mmio_write_32(PMU_BASE + PMU_GPU_VOLUP_CNT, 0x180);
1039fd9f1d0Sshengfei Xu mmio_write_32(PMU_BASE + PMU_GPU_VOLDN_CNT, 0x180);
1049fd9f1d0Sshengfei Xu mmio_write_32(PMU_BASE + PMU_WAKEUP_TIMEOUT_CNT, 0x180);
1059fd9f1d0Sshengfei Xu mmio_write_32(PMU_BASE + PMU_PWM_SWITCH_CNT, 0x180);
1069fd9f1d0Sshengfei Xu mmio_write_32(PMU_BASE + PMU_DBG_RST_CNT, 0x180);
1079fd9f1d0Sshengfei Xu }
1089fd9f1d0Sshengfei Xu
pmu_pd_powerdown_config(void)1099fd9f1d0Sshengfei Xu static void pmu_pd_powerdown_config(void)
1109fd9f1d0Sshengfei Xu {
1119fd9f1d0Sshengfei Xu uint32_t pwr_gate_con, pwr_dwn_st, pmu_bus_idle_con0 = 0;
1129fd9f1d0Sshengfei Xu uint32_t pmu_bus_idle_con1;
1139fd9f1d0Sshengfei Xu
1149fd9f1d0Sshengfei Xu /* Pd power down by PMU */
1159fd9f1d0Sshengfei Xu pwr_dwn_st = mmio_read_32(PMU_BASE + PMU_PWR_DWN_ST);
1169fd9f1d0Sshengfei Xu pwr_gate_con = ~pwr_dwn_st & 0x3ff;
1179fd9f1d0Sshengfei Xu
1189fd9f1d0Sshengfei Xu if (pwr_gate_con & BIT(PD_GPU_DWN_ENA)) {
1199fd9f1d0Sshengfei Xu pmu_bus_idle_con0 |= BIT(IDLE_REQ_GPU);
1209fd9f1d0Sshengfei Xu }
1219fd9f1d0Sshengfei Xu
1229fd9f1d0Sshengfei Xu if (pwr_gate_con & BIT(PD_NPU_DWN_ENA)) {
1239fd9f1d0Sshengfei Xu pmu_bus_idle_con0 |= BIT(IDLE_REQ_NPU);
1249fd9f1d0Sshengfei Xu }
1259fd9f1d0Sshengfei Xu
1269fd9f1d0Sshengfei Xu if (pwr_gate_con & BIT(PD_RKVENC_DWN_ENA)) {
1279fd9f1d0Sshengfei Xu pmu_bus_idle_con0 |= BIT(IDLE_REQ_RKVENC);
1289fd9f1d0Sshengfei Xu }
1299fd9f1d0Sshengfei Xu
1309fd9f1d0Sshengfei Xu if (pwr_gate_con & BIT(PD_RKVDEC_DWN_ENA)) {
1319fd9f1d0Sshengfei Xu pmu_bus_idle_con0 |= BIT(IDLE_REQ_RKVDEC);
1329fd9f1d0Sshengfei Xu }
1339fd9f1d0Sshengfei Xu
1349fd9f1d0Sshengfei Xu if (pwr_gate_con & BIT(PD_RGA_DWN_ENA)) {
1359fd9f1d0Sshengfei Xu pmu_bus_idle_con0 |= BIT(IDLE_REQ_RGA);
1369fd9f1d0Sshengfei Xu }
1379fd9f1d0Sshengfei Xu
1389fd9f1d0Sshengfei Xu if (pwr_gate_con & BIT(PD_VI_DWN_ENA)) {
1399fd9f1d0Sshengfei Xu pmu_bus_idle_con0 |= BIT(IDLE_REQ_VI);
1409fd9f1d0Sshengfei Xu }
1419fd9f1d0Sshengfei Xu
1429fd9f1d0Sshengfei Xu if (pwr_gate_con & BIT(PD_VO_DWN_ENA)) {
1439fd9f1d0Sshengfei Xu pmu_bus_idle_con0 |= BIT(IDLE_REQ_VO);
1449fd9f1d0Sshengfei Xu }
1459fd9f1d0Sshengfei Xu
1469fd9f1d0Sshengfei Xu if (pwr_gate_con & BIT(PD_PIPE_DWN_ENA)) {
1479fd9f1d0Sshengfei Xu pmu_bus_idle_con0 |= BIT(IDLE_REQ_PIPE);
1489fd9f1d0Sshengfei Xu }
1499fd9f1d0Sshengfei Xu
1509fd9f1d0Sshengfei Xu pmu_bus_idle_con0 |= BIT(IDLE_REQ_GIC_AUDIO) |
1519fd9f1d0Sshengfei Xu BIT(IDLE_REQ_MSCH) |
1529fd9f1d0Sshengfei Xu BIT(IDLE_REQ_PHP) |
1539fd9f1d0Sshengfei Xu BIT(IDLE_REQ_SECURE_FLASH) |
1549fd9f1d0Sshengfei Xu BIT(IDLE_REQ_PERIMID) |
1559fd9f1d0Sshengfei Xu BIT(IDLE_REQ_USB) |
1569fd9f1d0Sshengfei Xu BIT(IDLE_REQ_BUS);
1579fd9f1d0Sshengfei Xu
1589fd9f1d0Sshengfei Xu /* Enable power down PD by PMU automatically */
1599fd9f1d0Sshengfei Xu pwr_gate_con |= (BIT(PD_GPU_DWN_ENA) |
1609fd9f1d0Sshengfei Xu BIT(PD_NPU_DWN_ENA) |
1619fd9f1d0Sshengfei Xu BIT(PD_VPU_DWN_ENA) |
1629fd9f1d0Sshengfei Xu BIT(PD_RKVENC_DWN_ENA) |
1639fd9f1d0Sshengfei Xu BIT(PD_RKVDEC_DWN_ENA) |
1649fd9f1d0Sshengfei Xu BIT(PD_RGA_DWN_ENA) |
1659fd9f1d0Sshengfei Xu BIT(PD_VI_DWN_ENA) |
1669fd9f1d0Sshengfei Xu BIT(PD_VO_DWN_ENA) |
1679fd9f1d0Sshengfei Xu BIT(PD_PIPE_DWN_ENA)) << 16;
1689fd9f1d0Sshengfei Xu
1699fd9f1d0Sshengfei Xu pmu_bus_idle_con1 = 0;
1709fd9f1d0Sshengfei Xu
1719fd9f1d0Sshengfei Xu mmio_write_32(PMU_BASE + PMU_PWR_GATE_CON, pwr_gate_con);
1729fd9f1d0Sshengfei Xu mmio_write_32(PMU_BASE + PMU_BUS_IDLE_CON0, WRITE_MASK_SET(pmu_bus_idle_con0));
1739fd9f1d0Sshengfei Xu mmio_write_32(PMU_BASE + PMU_BUS_IDLE_CON1, WRITE_MASK_SET(pmu_bus_idle_con1));
1749fd9f1d0Sshengfei Xu
1759fd9f1d0Sshengfei Xu /* When perform idle operation,
1769fd9f1d0Sshengfei Xu * corresponding clock can be opened or gated automatically
1779fd9f1d0Sshengfei Xu */
1789fd9f1d0Sshengfei Xu mmio_write_32(PMU_BASE + PMU_NOC_AUTO_CON0, 0xffffffff);
1799fd9f1d0Sshengfei Xu mmio_write_32(PMU_BASE + PMU_NOC_AUTO_CON1, 0x00070007);
1809fd9f1d0Sshengfei Xu
1819fd9f1d0Sshengfei Xu mmio_write_32(PMU_BASE + PMU_VOL_GATE_SFTCON, WRITE_MASK_SET(BIT(VD_NPU_ENA)));
1829fd9f1d0Sshengfei Xu
1839fd9f1d0Sshengfei Xu mmio_write_32(PMU_BASE + PMU_PWR_CON, WRITE_MASK_CLR(BIT(PWRDN_BYPASS)));
1849fd9f1d0Sshengfei Xu mmio_write_32(PMU_BASE + PMU_PWR_CON, WRITE_MASK_CLR(BIT(BUS_BYPASS)));
1859fd9f1d0Sshengfei Xu
1869fd9f1d0Sshengfei Xu INFO("PD & BUS:PMU_PWR_DWN_ST(0x%x):0x%x\n",
1879fd9f1d0Sshengfei Xu PMU_PWR_DWN_ST, mmio_read_32(PMU_BASE + PMU_PWR_DWN_ST));
1889fd9f1d0Sshengfei Xu INFO("PD & BUS:PMU_PWR_GATE_CON(0x%x):0x%x\n",
1899fd9f1d0Sshengfei Xu PMU_PWR_GATE_CON, mmio_read_32(PMU_BASE + PMU_PWR_GATE_CON));
1909fd9f1d0Sshengfei Xu INFO("PD & BUS:PMU_BUS_IDLE_CON0(0x%x):0x%x\n",
1919fd9f1d0Sshengfei Xu PMU_BUS_IDLE_CON0, mmio_read_32(PMU_BASE + PMU_BUS_IDLE_CON0));
1929fd9f1d0Sshengfei Xu INFO("PD & BUS:PMU_BUS_IDLE_CON1(0x%x):0x%x\n",
1939fd9f1d0Sshengfei Xu PMU_BUS_IDLE_CON1, mmio_read_32(PMU_BASE + PMU_BUS_IDLE_CON1));
1949fd9f1d0Sshengfei Xu INFO("PD & BUS:PMU_PWR_CON(0x%x):0x%x\n",
1959fd9f1d0Sshengfei Xu PMU_PWR_CON, mmio_read_32(PMU_BASE + PMU_PWR_CON));
1969fd9f1d0Sshengfei Xu }
1979fd9f1d0Sshengfei Xu
pmu_ddr_suspend_config(void)1989fd9f1d0Sshengfei Xu static void pmu_ddr_suspend_config(void)
1999fd9f1d0Sshengfei Xu {
2009fd9f1d0Sshengfei Xu uint32_t pmu_ddr_pwr_con;
2019fd9f1d0Sshengfei Xu
2029fd9f1d0Sshengfei Xu pmu_ddr_pwr_con = BIT(DDR_SREF_ENA) |
2039fd9f1d0Sshengfei Xu BIT(DDRIO_RET_ENTER_ENA) |
2049fd9f1d0Sshengfei Xu BIT(DDRIO_RET_EXIT_ENA) |
2059fd9f1d0Sshengfei Xu BIT(DDRPHY_AUTO_GATING_ENA);
2069fd9f1d0Sshengfei Xu
2079fd9f1d0Sshengfei Xu mmio_write_32(PMU_BASE + PMU_DDR_PWR_CON, WRITE_MASK_SET(pmu_ddr_pwr_con));
2089fd9f1d0Sshengfei Xu /* DPLL power down by PMU */
2099fd9f1d0Sshengfei Xu mmio_write_32(PMU_BASE + PMU_PLLPD_CON, WRITE_MASK_SET(BIT(DPLL_PD_ENA)));
2109fd9f1d0Sshengfei Xu mmio_write_32(PMU_BASE + PMU_PWR_CON, WRITE_MASK_CLR(BIT(DDR_BYPASS)));
2119fd9f1d0Sshengfei Xu
2129fd9f1d0Sshengfei Xu grf_ddr_con3 = mmio_read_32(DDRGRF_BASE + GRF_DDR_CON3);
2139fd9f1d0Sshengfei Xu
2149fd9f1d0Sshengfei Xu mmio_write_32(DDRGRF_BASE + GRF_DDR_CON3, 0x00600020);
2159fd9f1d0Sshengfei Xu
2169fd9f1d0Sshengfei Xu pmu_ddr_pwr_con = mmio_read_32(PMU_BASE + PMU_DDR_PWR_CON);
2179fd9f1d0Sshengfei Xu
2189fd9f1d0Sshengfei Xu INFO("DDR: PMU_PLLPD_CON(0x%x):0x%x\n",
2199fd9f1d0Sshengfei Xu PMU_PLLPD_CON, mmio_read_32(PMU_BASE + PMU_PLLPD_CON));
2209fd9f1d0Sshengfei Xu INFO("DDR: PMU_DDR_PWR_CON(0x%x):\t0x%x\n",
2219fd9f1d0Sshengfei Xu PMU_DDR_PWR_CON, pmu_ddr_pwr_con);
2229fd9f1d0Sshengfei Xu
2239fd9f1d0Sshengfei Xu if (pmu_ddr_pwr_con & BIT(DDR_SREF_ENA)) {
2249fd9f1d0Sshengfei Xu INFO("\t DDR_SREF_ENA\n");
2259fd9f1d0Sshengfei Xu }
2269fd9f1d0Sshengfei Xu
2279fd9f1d0Sshengfei Xu if (pmu_ddr_pwr_con & BIT(DDRIO_RET_ENTER_ENA)) {
2289fd9f1d0Sshengfei Xu INFO("\t DDRIO_RET_ENTER_ENA\n");
2299fd9f1d0Sshengfei Xu }
2309fd9f1d0Sshengfei Xu
2319fd9f1d0Sshengfei Xu if (pmu_ddr_pwr_con & BIT(DDRIO_RET_EXIT_ENA)) {
2329fd9f1d0Sshengfei Xu INFO("\t DDRIO_RET_EXIT_ENA\n");
2339fd9f1d0Sshengfei Xu }
2349fd9f1d0Sshengfei Xu
2359fd9f1d0Sshengfei Xu if (pmu_ddr_pwr_con & BIT(DDRPHY_AUTO_GATING_ENA)) {
2369fd9f1d0Sshengfei Xu INFO("\t DDRPHY_AUTO_GATING_ENA\n");
2379fd9f1d0Sshengfei Xu }
2389fd9f1d0Sshengfei Xu }
2399fd9f1d0Sshengfei Xu
pmu_dsu_suspend_config(void)2409fd9f1d0Sshengfei Xu static void pmu_dsu_suspend_config(void)
2419fd9f1d0Sshengfei Xu {
2429fd9f1d0Sshengfei Xu uint32_t pmu_dsu_pwr_con;
2439fd9f1d0Sshengfei Xu
2449fd9f1d0Sshengfei Xu pmu_dsu_pwr_con = BIT(DSU_PWRDN_ENA);
2459fd9f1d0Sshengfei Xu
2469fd9f1d0Sshengfei Xu mmio_write_32(PMU_BASE + PMU_CLUSTER_IDLE_CON, 0x000f000f);
2479fd9f1d0Sshengfei Xu mmio_write_32(PMU_BASE + PMU_DSU_PWR_CON, WRITE_MASK_SET(pmu_dsu_pwr_con));
2489fd9f1d0Sshengfei Xu mmio_write_32(PMU_BASE + PMU_PWR_CON, WRITE_MASK_CLR(BIT(DSU_BYPASS)));
2499fd9f1d0Sshengfei Xu dsu_pwr_dwn();
2509fd9f1d0Sshengfei Xu
2519fd9f1d0Sshengfei Xu INFO("DSU: PMU_DSU_PWR_CON(0x%x): 0x%x\n",
2529fd9f1d0Sshengfei Xu PMU_DSU_PWR_CON, mmio_read_32(PMU_BASE + PMU_DSU_PWR_CON));
2539fd9f1d0Sshengfei Xu INFO("DSU: PMU_CLUSTER_IDLE_CON(0x%x),: 0x%x\n",
2549fd9f1d0Sshengfei Xu PMU_CLUSTER_IDLE_CON, mmio_read_32(PMU_BASE + PMU_CLUSTER_IDLE_CON));
2559fd9f1d0Sshengfei Xu INFO("DSU: PMU_PWR_CON(0x%x),: 0x%x\n",
2569fd9f1d0Sshengfei Xu PMU_PWR_CON, mmio_read_32(PMU_BASE + PMU_PWR_CON));
2579fd9f1d0Sshengfei Xu }
2589fd9f1d0Sshengfei Xu
pmu_cpu_powerdown_config(void)2599fd9f1d0Sshengfei Xu static void pmu_cpu_powerdown_config(void)
2609fd9f1d0Sshengfei Xu {
2619fd9f1d0Sshengfei Xu uint32_t pmu_cluster_pwr_st, cpus_state, cpus_bypass;
2629fd9f1d0Sshengfei Xu
2639fd9f1d0Sshengfei Xu pmu_cluster_pwr_st = mmio_read_32(PMU_BASE + PMU_CLUSTER_PWR_ST);
2649fd9f1d0Sshengfei Xu cpus_state = pmu_cluster_pwr_st & 0x0f;
2659fd9f1d0Sshengfei Xu
2669fd9f1d0Sshengfei Xu cpus_bypass = cpus_state << CPU0_BYPASS;
2679fd9f1d0Sshengfei Xu
2689fd9f1d0Sshengfei Xu INFO("CPU: PMU_CLUSTER_PWR_ST(0x%x):0x%x\n",
2699fd9f1d0Sshengfei Xu PMU_CLUSTER_PWR_ST, mmio_read_32(PMU_BASE + PMU_CLUSTER_PWR_ST));
2709fd9f1d0Sshengfei Xu mmio_write_32(PMU_BASE + PMU_PWR_CON, (0xf << (16 + CPU0_BYPASS)) | cpus_bypass);
2719fd9f1d0Sshengfei Xu
2729fd9f1d0Sshengfei Xu INFO("CPU: PMU_PWR_CON(0x%x), 0x%x\n",
2739fd9f1d0Sshengfei Xu PMU_PWR_CON, mmio_read_32(PMU_BASE + PMU_PWR_CON));
2749fd9f1d0Sshengfei Xu }
2759fd9f1d0Sshengfei Xu
pvtm_32k_config(void)2769fd9f1d0Sshengfei Xu static void pvtm_32k_config(void)
2779fd9f1d0Sshengfei Xu {
2789fd9f1d0Sshengfei Xu uint32_t pmu_cru_pwr_con;
2799fd9f1d0Sshengfei Xu uint32_t pvtm_freq_khz, pvtm_div;
2809fd9f1d0Sshengfei Xu
2819fd9f1d0Sshengfei Xu mmio_write_32(PMUCRU_BASE + PMUCRU_PMUGATE_CON01, 0x38000000);
2829fd9f1d0Sshengfei Xu mmio_write_32(PMUPVTM_BASE + PVTM_CON0, 0x00020002);
2839fd9f1d0Sshengfei Xu dsb();
2849fd9f1d0Sshengfei Xu
2859fd9f1d0Sshengfei Xu mmio_write_32(PMUPVTM_BASE + PVTM_CON0, 0x001c0000);
2869fd9f1d0Sshengfei Xu
2879fd9f1d0Sshengfei Xu mmio_write_32(PMUPVTM_BASE + PVTM_CON1, PVTM_CALC_CNT);
2889fd9f1d0Sshengfei Xu dsb();
2899fd9f1d0Sshengfei Xu
2909fd9f1d0Sshengfei Xu mmio_write_32(PMUPVTM_BASE + PVTM_CON0, 0x00010001);
2919fd9f1d0Sshengfei Xu dsb();
2929fd9f1d0Sshengfei Xu
2939fd9f1d0Sshengfei Xu while (mmio_read_32(PMUPVTM_BASE + PVTM_STATUS1) < 30) {
2949fd9f1d0Sshengfei Xu ;
2959fd9f1d0Sshengfei Xu }
2969fd9f1d0Sshengfei Xu
2979fd9f1d0Sshengfei Xu dsb();
2989fd9f1d0Sshengfei Xu while (!(mmio_read_32(PMUPVTM_BASE + PVTM_STATUS0) & 0x1)) {
2999fd9f1d0Sshengfei Xu ;
3009fd9f1d0Sshengfei Xu }
3019fd9f1d0Sshengfei Xu
3029fd9f1d0Sshengfei Xu pvtm_freq_khz = (mmio_read_32(PMUPVTM_BASE + PVTM_STATUS1) * 24000 +
3039fd9f1d0Sshengfei Xu PVTM_CALC_CNT / 2) / PVTM_CALC_CNT;
3049fd9f1d0Sshengfei Xu pvtm_div = (pvtm_freq_khz + 16) / 32;
3059fd9f1d0Sshengfei Xu
3069fd9f1d0Sshengfei Xu mmio_write_32(PMUGRF_BASE + PMU_GRF_DLL_CON0, pvtm_div);
3079fd9f1d0Sshengfei Xu
3089fd9f1d0Sshengfei Xu mmio_write_32(PMUCRU_BASE + PMUCRU_PMUCLKSEL_CON00, 0x00c00000);
3099fd9f1d0Sshengfei Xu
3109fd9f1d0Sshengfei Xu pmu_cru_pwr_con = BIT(ALIVE_32K_ENA) | BIT(OSC_DIS_ENA);
3119fd9f1d0Sshengfei Xu
3129fd9f1d0Sshengfei Xu mmio_write_32(PMU_BASE + PMU_WAKEUP_TIMEOUT_CNT, 32000 * 10);
3139fd9f1d0Sshengfei Xu
3149fd9f1d0Sshengfei Xu mmio_write_32(PMU_BASE + PMU_CRU_PWR_CON, WRITE_MASK_SET(pmu_cru_pwr_con));
3159fd9f1d0Sshengfei Xu INFO("PVTM: PMU_CRU_PWR_CON(0x0%x): 0x%x\n",
3169fd9f1d0Sshengfei Xu PMU_CRU_PWR_CON, mmio_read_32(PMU_BASE + PMU_CRU_PWR_CON));
3179fd9f1d0Sshengfei Xu }
3189fd9f1d0Sshengfei Xu
pmu_cru_suspendmode_config(void)3199fd9f1d0Sshengfei Xu static void pmu_cru_suspendmode_config(void)
3209fd9f1d0Sshengfei Xu {
3219fd9f1d0Sshengfei Xu uint32_t pmu_cru_pwr_con;
3229fd9f1d0Sshengfei Xu
3239fd9f1d0Sshengfei Xu pmu_cru_pwr_con = BIT(ALIVE_OSC_ENA);
3249fd9f1d0Sshengfei Xu
3259fd9f1d0Sshengfei Xu mmio_write_32(PMU_BASE + PMU_CRU_PWR_CON, WRITE_MASK_SET(pmu_cru_pwr_con));
3269fd9f1d0Sshengfei Xu INFO("CRU: PMU_CRU_PWR_CON(0x0%x): 0x%x\n",
3279fd9f1d0Sshengfei Xu PMU_CRU_PWR_CON, mmio_read_32(PMU_BASE + PMU_CRU_PWR_CON));
3289fd9f1d0Sshengfei Xu }
3299fd9f1d0Sshengfei Xu
pmu_suspend_cru_fsm(void)3309fd9f1d0Sshengfei Xu static void pmu_suspend_cru_fsm(void)
3319fd9f1d0Sshengfei Xu {
3329fd9f1d0Sshengfei Xu pmu_pmic_sleep_mode_config();
3339fd9f1d0Sshengfei Xu
3349fd9f1d0Sshengfei Xu /* Global interrupt disable */
3359fd9f1d0Sshengfei Xu mmio_write_32(PMU_BASE + PMU_INT_MASK_CON, CLB_INT_DISABLE);
3369fd9f1d0Sshengfei Xu mmio_write_32(PMU_BASE + PMU_PWR_CON, CPUS_BYPASS);
3379fd9f1d0Sshengfei Xu
3389fd9f1d0Sshengfei Xu pmu_stable_count_config();
3399fd9f1d0Sshengfei Xu pmu_wakeup_source_config();
3409fd9f1d0Sshengfei Xu mmio_write_32(PMU_BASE + PMU_WAKEUP_TIMEOUT_CNT, 0x5dc0 * 20000);
3419fd9f1d0Sshengfei Xu /* default cru config */
3429fd9f1d0Sshengfei Xu mmio_write_32(PMU_BASE + PMU_CRU_PWR_CON, WRITE_MASK_SET(BIT(ALIVE_OSC_ENA)));
3439fd9f1d0Sshengfei Xu
3449fd9f1d0Sshengfei Xu pmu_cru_suspendmode_config();
3459fd9f1d0Sshengfei Xu pmu_cpu_powerdown_config();
3469fd9f1d0Sshengfei Xu pmu_pll_powerdown_config();
3479fd9f1d0Sshengfei Xu pmu_pd_powerdown_config();
3489fd9f1d0Sshengfei Xu pmu_ddr_suspend_config();
3499fd9f1d0Sshengfei Xu pmu_dsu_suspend_config();
3509fd9f1d0Sshengfei Xu pvtm_32k_config();
3519fd9f1d0Sshengfei Xu mmio_write_32(PMU_BASE + PMU_PWR_CON, 0x00010001);
3529fd9f1d0Sshengfei Xu }
3539fd9f1d0Sshengfei Xu
pmu_reinit(void)3549fd9f1d0Sshengfei Xu static void pmu_reinit(void)
3559fd9f1d0Sshengfei Xu {
3569fd9f1d0Sshengfei Xu mmio_write_32(DDRGRF_BASE + GRF_DDR_CON3, grf_ddr_con3 | 0xffff0000);
3579fd9f1d0Sshengfei Xu mmio_write_32(PMU_BASE + PMU_PWR_CON, 0xffff0000);
3589fd9f1d0Sshengfei Xu mmio_write_32(PMU_BASE + PMU_INT_MASK_CON, 0xffff0000);
3599fd9f1d0Sshengfei Xu mmio_write_32(PMU_BASE + PMU_WAKEUP_INT_CON, 0xffff0000);
3609fd9f1d0Sshengfei Xu mmio_write_32(PMU_BASE + PMU_BUS_IDLE_CON0, 0xffff0000);
3619fd9f1d0Sshengfei Xu mmio_write_32(PMU_BASE + PMU_DDR_PWR_CON, 0xffff0000);
3629fd9f1d0Sshengfei Xu mmio_write_32(PMU_BASE + PMU_BUS_IDLE_CON1, 0xffff0000);
3639fd9f1d0Sshengfei Xu
3649fd9f1d0Sshengfei Xu mmio_write_32(PMU_BASE + PMU_PWR_GATE_CON, 0xffff0000);
3659fd9f1d0Sshengfei Xu mmio_write_32(PMU_BASE + PMU_VOL_GATE_SFTCON, 0xffff0000);
3669fd9f1d0Sshengfei Xu mmio_write_32(PMU_BASE + PMU_CRU_PWR_CON, 0xffff0000);
3679fd9f1d0Sshengfei Xu
3689fd9f1d0Sshengfei Xu mmio_write_32(PMU_BASE + PMU_PLLPD_CON, 0xffff0000);
3699fd9f1d0Sshengfei Xu mmio_write_32(PMU_BASE + PMU_INFO_TX_CON, 0xffff0000);
3709fd9f1d0Sshengfei Xu mmio_write_32(PMU_BASE + PMU_DSU_PWR_CON, 0xffff0000);
3719fd9f1d0Sshengfei Xu mmio_write_32(PMU_BASE + PMU_CLUSTER_IDLE_CON, 0xffff0000);
3729fd9f1d0Sshengfei Xu }
3739fd9f1d0Sshengfei Xu
rockchip_plat_mmu_el3(void)3749fd9f1d0Sshengfei Xu void rockchip_plat_mmu_el3(void)
3759fd9f1d0Sshengfei Xu {
3769fd9f1d0Sshengfei Xu }
3779fd9f1d0Sshengfei Xu
rockchip_soc_cores_pwr_dm_suspend(void)3789fd9f1d0Sshengfei Xu int rockchip_soc_cores_pwr_dm_suspend(void)
3799fd9f1d0Sshengfei Xu {
3809fd9f1d0Sshengfei Xu return 0;
3819fd9f1d0Sshengfei Xu }
3829fd9f1d0Sshengfei Xu
rockchip_soc_cores_pwr_dm_resume(void)3839fd9f1d0Sshengfei Xu int rockchip_soc_cores_pwr_dm_resume(void)
3849fd9f1d0Sshengfei Xu {
3859fd9f1d0Sshengfei Xu return 0;
3869fd9f1d0Sshengfei Xu }
3879fd9f1d0Sshengfei Xu
rockchip_soc_sys_pwr_dm_suspend(void)3889fd9f1d0Sshengfei Xu int rockchip_soc_sys_pwr_dm_suspend(void)
3899fd9f1d0Sshengfei Xu {
390*4e1ccc60SShengfei Xu pvtplls_suspend();
3919fd9f1d0Sshengfei Xu psram_sleep_cfg->pm_flag = 0;
3929fd9f1d0Sshengfei Xu flush_dcache_range((uintptr_t)&(psram_sleep_cfg->pm_flag),
3939fd9f1d0Sshengfei Xu sizeof(uint32_t));
3949fd9f1d0Sshengfei Xu pmu_suspend_cru_fsm();
3959fd9f1d0Sshengfei Xu
3969fd9f1d0Sshengfei Xu return 0;
3979fd9f1d0Sshengfei Xu }
3989fd9f1d0Sshengfei Xu
rockchip_soc_sys_pwr_dm_resume(void)3999fd9f1d0Sshengfei Xu int rockchip_soc_sys_pwr_dm_resume(void)
4009fd9f1d0Sshengfei Xu {
401*4e1ccc60SShengfei Xu pvtplls_resume();
4029fd9f1d0Sshengfei Xu pmu_reinit();
4039fd9f1d0Sshengfei Xu plat_rockchip_gic_cpuif_enable();
4049fd9f1d0Sshengfei Xu psram_sleep_cfg->pm_flag = PM_WARM_BOOT_BIT;
4059fd9f1d0Sshengfei Xu flush_dcache_range((uintptr_t)&(psram_sleep_cfg->pm_flag),
4069fd9f1d0Sshengfei Xu sizeof(uint32_t));
4079fd9f1d0Sshengfei Xu
4089fd9f1d0Sshengfei Xu return 0;
4099fd9f1d0Sshengfei Xu }
4109fd9f1d0Sshengfei Xu
cpus_power_domain_off(uint32_t cpu_id,uint32_t pd_cfg)4119fd9f1d0Sshengfei Xu static int cpus_power_domain_off(uint32_t cpu_id, uint32_t pd_cfg)
4129fd9f1d0Sshengfei Xu {
4139fd9f1d0Sshengfei Xu uint32_t apm_value, offset, idx;
4149fd9f1d0Sshengfei Xu
4159fd9f1d0Sshengfei Xu apm_value = BIT(core_pm_en) | BIT(core_pm_int_wakeup_glb_msk);
4169fd9f1d0Sshengfei Xu
4179fd9f1d0Sshengfei Xu if (pd_cfg == core_pwr_wfi_int) {
4189fd9f1d0Sshengfei Xu apm_value |= BIT(core_pm_int_wakeup_en);
4199fd9f1d0Sshengfei Xu }
4209fd9f1d0Sshengfei Xu
4219fd9f1d0Sshengfei Xu idx = cpu_id / 2;
4229fd9f1d0Sshengfei Xu offset = (cpu_id % 2) << 3;
4239fd9f1d0Sshengfei Xu
4249fd9f1d0Sshengfei Xu mmio_write_32(PMU_BASE + PMU_CPUAPM_CON(idx),
4259fd9f1d0Sshengfei Xu BITS_WITH_WMASK(apm_value, 0xf, offset));
4269fd9f1d0Sshengfei Xu dsb();
4279fd9f1d0Sshengfei Xu
4289fd9f1d0Sshengfei Xu return 0;
4299fd9f1d0Sshengfei Xu }
4309fd9f1d0Sshengfei Xu
cpus_power_domain_on(uint32_t cpu_id)4319fd9f1d0Sshengfei Xu static int cpus_power_domain_on(uint32_t cpu_id)
4329fd9f1d0Sshengfei Xu {
4339fd9f1d0Sshengfei Xu uint32_t offset, idx;
4349fd9f1d0Sshengfei Xu
4359fd9f1d0Sshengfei Xu idx = cpu_id / 2;
4369fd9f1d0Sshengfei Xu offset = (cpu_id % 2) << 3;
4379fd9f1d0Sshengfei Xu
4389fd9f1d0Sshengfei Xu mmio_write_32(PMU_BASE + PMU_CPUAPM_CON(idx),
4399fd9f1d0Sshengfei Xu WMSK_BIT(core_pm_en + offset));
4409fd9f1d0Sshengfei Xu mmio_write_32(PMU_BASE + PMU_CPUAPM_CON(idx),
4419fd9f1d0Sshengfei Xu BIT_WITH_WMSK(core_pm_sft_wakeup_en + offset));
4429fd9f1d0Sshengfei Xu dsb();
4439fd9f1d0Sshengfei Xu
4449fd9f1d0Sshengfei Xu return 0;
4459fd9f1d0Sshengfei Xu }
4469fd9f1d0Sshengfei Xu
rockchip_soc_cores_pwr_dm_on(unsigned long mpidr,uint64_t entrypoint)4479fd9f1d0Sshengfei Xu int rockchip_soc_cores_pwr_dm_on(unsigned long mpidr, uint64_t entrypoint)
4489fd9f1d0Sshengfei Xu {
4499fd9f1d0Sshengfei Xu uint32_t cpu_id = plat_core_pos_by_mpidr(mpidr);
4509fd9f1d0Sshengfei Xu
4519fd9f1d0Sshengfei Xu assert(cpu_id < PLATFORM_CORE_COUNT);
4529fd9f1d0Sshengfei Xu
4539fd9f1d0Sshengfei Xu cpuson_flags[cpu_id] = PMU_CPU_HOTPLUG;
4549fd9f1d0Sshengfei Xu cpuson_entry_point[cpu_id] = entrypoint;
4559fd9f1d0Sshengfei Xu flush_dcache_range((uintptr_t)cpuson_flags, sizeof(cpuson_flags));
4569fd9f1d0Sshengfei Xu flush_dcache_range((uintptr_t)cpuson_entry_point,
4579fd9f1d0Sshengfei Xu sizeof(cpuson_entry_point));
4589fd9f1d0Sshengfei Xu
4599fd9f1d0Sshengfei Xu cpus_power_domain_on(cpu_id);
4609fd9f1d0Sshengfei Xu return 0;
4619fd9f1d0Sshengfei Xu }
4629fd9f1d0Sshengfei Xu
rockchip_soc_cores_pwr_dm_off(void)4639fd9f1d0Sshengfei Xu int rockchip_soc_cores_pwr_dm_off(void)
4649fd9f1d0Sshengfei Xu {
4659fd9f1d0Sshengfei Xu uint32_t cpu_id = plat_my_core_pos();
4669fd9f1d0Sshengfei Xu
4679fd9f1d0Sshengfei Xu cpus_power_domain_off(cpu_id,
4689fd9f1d0Sshengfei Xu core_pwr_wfi);
4699fd9f1d0Sshengfei Xu return 0;
4709fd9f1d0Sshengfei Xu }
4719fd9f1d0Sshengfei Xu
rockchip_soc_cores_pwr_dm_on_finish(void)4729fd9f1d0Sshengfei Xu int rockchip_soc_cores_pwr_dm_on_finish(void)
4739fd9f1d0Sshengfei Xu {
4749fd9f1d0Sshengfei Xu uint32_t cpu_id = plat_my_core_pos();
4759fd9f1d0Sshengfei Xu uint32_t offset, idx;
4769fd9f1d0Sshengfei Xu
4779fd9f1d0Sshengfei Xu /* Disable core_pm */
4789fd9f1d0Sshengfei Xu idx = cpu_id / 2;
4799fd9f1d0Sshengfei Xu offset = (cpu_id % 2) << 3;
4809fd9f1d0Sshengfei Xu mmio_write_32(PMU_BASE + PMU_CPUAPM_CON(idx),
4819fd9f1d0Sshengfei Xu BITS_WITH_WMASK(0, 0xf, offset));
4829fd9f1d0Sshengfei Xu
4839fd9f1d0Sshengfei Xu return 0;
4849fd9f1d0Sshengfei Xu }
4859fd9f1d0Sshengfei Xu
nonboot_cpus_off(void)4869fd9f1d0Sshengfei Xu static void nonboot_cpus_off(void)
4879fd9f1d0Sshengfei Xu {
4889fd9f1d0Sshengfei Xu uint32_t tmp;
4899fd9f1d0Sshengfei Xu
4909fd9f1d0Sshengfei Xu cpus_power_domain_off(1, 0);
4919fd9f1d0Sshengfei Xu cpus_power_domain_off(2, 0);
4929fd9f1d0Sshengfei Xu cpus_power_domain_off(3, 0);
4939fd9f1d0Sshengfei Xu
4949fd9f1d0Sshengfei Xu mmio_write_32(SYSSRAM_BASE + 0x04, 0xdeadbeaf);
4959fd9f1d0Sshengfei Xu mmio_write_32(SYSSRAM_BASE + 0x08, (uintptr_t)&rockchip_soc_sys_pd_pwr_dn_wfi);
4969fd9f1d0Sshengfei Xu sev();
4979fd9f1d0Sshengfei Xu
4989fd9f1d0Sshengfei Xu do {
4999fd9f1d0Sshengfei Xu tmp = mmio_read_32(PMU_BASE + PMU_CLUSTER_PWR_ST);
5009fd9f1d0Sshengfei Xu } while ((tmp & 0xe) != 0xe);
5019fd9f1d0Sshengfei Xu }
5029fd9f1d0Sshengfei Xu
plat_rockchip_pmu_init(void)5039fd9f1d0Sshengfei Xu void plat_rockchip_pmu_init(void)
5049fd9f1d0Sshengfei Xu {
5059fd9f1d0Sshengfei Xu uint32_t cpu;
5069fd9f1d0Sshengfei Xu
5079fd9f1d0Sshengfei Xu rockchip_pd_lock_init();
5089fd9f1d0Sshengfei Xu nonboot_cpus_off();
5099fd9f1d0Sshengfei Xu for (cpu = 0; cpu < PLATFORM_CORE_COUNT; cpu++)
5109fd9f1d0Sshengfei Xu cpuson_flags[cpu] = PMU_CPU_HOTPLUG;
5119fd9f1d0Sshengfei Xu
5129fd9f1d0Sshengfei Xu psram_sleep_cfg->ddr_data = (uint64_t)0;
5139fd9f1d0Sshengfei Xu psram_sleep_cfg->sp = PSRAM_SP_TOP;
5149fd9f1d0Sshengfei Xu psram_sleep_cfg->ddr_flag = 0x00;
5159fd9f1d0Sshengfei Xu psram_sleep_cfg->boot_mpidr = read_mpidr_el1() & 0xffff;
5169fd9f1d0Sshengfei Xu psram_sleep_cfg->pm_flag = PM_WARM_BOOT_BIT;
5179fd9f1d0Sshengfei Xu
5189fd9f1d0Sshengfei Xu /*
5199fd9f1d0Sshengfei Xu * When perform idle operation, corresponding clock can be
5209fd9f1d0Sshengfei Xu * opened or gated automatically.
5219fd9f1d0Sshengfei Xu */
5229fd9f1d0Sshengfei Xu mmio_write_32(PMU_BASE + PMU_NOC_AUTO_CON0, 0xffffffff);
5239fd9f1d0Sshengfei Xu mmio_write_32(PMU_BASE + PMU_NOC_AUTO_CON1, 0x00070007);
5249fd9f1d0Sshengfei Xu
5259fd9f1d0Sshengfei Xu /* grf_con_pmic_sleep_sel
5269fd9f1d0Sshengfei Xu * pmic sleep function selection
5279fd9f1d0Sshengfei Xu * 1'b0: From reset pulse generator, can reset external PMIC
5289fd9f1d0Sshengfei Xu * 1'b1: From pmu block, only support sleep function for external PMIC
5299fd9f1d0Sshengfei Xu */
5309fd9f1d0Sshengfei Xu mmio_write_32(PMUGRF_BASE + PMU_GRF_SOC_CON(0), 0x00800080);
5319fd9f1d0Sshengfei Xu
5329fd9f1d0Sshengfei Xu /*
5339fd9f1d0Sshengfei Xu * force jtag control
5349fd9f1d0Sshengfei Xu * 1'b0: CPU debug port IO mux is controlled by sdmmc_detect_en status
5359fd9f1d0Sshengfei Xu * 1'b0: CPU debug port IO mux IS controlled by GRF
5369fd9f1d0Sshengfei Xu */
5379fd9f1d0Sshengfei Xu mmio_write_32(SGRF_BASE + 0x008, 0x00100000);
5389fd9f1d0Sshengfei Xu
5399fd9f1d0Sshengfei Xu /*
5409fd9f1d0Sshengfei Xu * remap
5419fd9f1d0Sshengfei Xu * 2'b00: Boot from boot-rom.
5429fd9f1d0Sshengfei Xu * 2'b01: Boot from pmu mem.
5439fd9f1d0Sshengfei Xu * 2'b10: Boot from sys mem.
5449fd9f1d0Sshengfei Xu */
5459fd9f1d0Sshengfei Xu mmio_write_32(PMUSGRF_BASE + PMU_SGRF_SOC_CON1, 0x18000800);
5469fd9f1d0Sshengfei Xu }
547