1*91f16700Schasinglulu /* 2*91f16700Schasinglulu * Copyright (c) 2019, ARM Limited and Contributors. All rights reserved. 3*91f16700Schasinglulu * 4*91f16700Schasinglulu * SPDX-License-Identifier: BSD-3-Clause 5*91f16700Schasinglulu */ 6*91f16700Schasinglulu 7*91f16700Schasinglulu #include <assert.h> 8*91f16700Schasinglulu #include <errno.h> 9*91f16700Schasinglulu 10*91f16700Schasinglulu #include <platform_def.h> 11*91f16700Schasinglulu 12*91f16700Schasinglulu #include <arch_helpers.h> 13*91f16700Schasinglulu #include <bl31/bl31.h> 14*91f16700Schasinglulu #include <common/debug.h> 15*91f16700Schasinglulu #include <drivers/console.h> 16*91f16700Schasinglulu #include <drivers/delay_timer.h> 17*91f16700Schasinglulu #include <lib/bakery_lock.h> 18*91f16700Schasinglulu #include <lib/mmio.h> 19*91f16700Schasinglulu #include <plat/common/platform.h> 20*91f16700Schasinglulu 21*91f16700Schasinglulu #include <cpus_on_fixed_addr.h> 22*91f16700Schasinglulu #include <plat_private.h> 23*91f16700Schasinglulu #include <pmu.h> 24*91f16700Schasinglulu #include <px30_def.h> 25*91f16700Schasinglulu #include <secure.h> 26*91f16700Schasinglulu #include <soc.h> 27*91f16700Schasinglulu 28*91f16700Schasinglulu DEFINE_BAKERY_LOCK(rockchip_pd_lock); 29*91f16700Schasinglulu #define rockchip_pd_lock_init() bakery_lock_init(&rockchip_pd_lock) 30*91f16700Schasinglulu #define rockchip_pd_lock_get() bakery_lock_get(&rockchip_pd_lock) 31*91f16700Schasinglulu #define rockchip_pd_lock_rls() bakery_lock_release(&rockchip_pd_lock) 32*91f16700Schasinglulu 33*91f16700Schasinglulu static struct psram_data_t *psram_boot_cfg = 34*91f16700Schasinglulu (struct psram_data_t *)&sys_sleep_flag_sram; 35*91f16700Schasinglulu 36*91f16700Schasinglulu /* 37*91f16700Schasinglulu * There are two ways to powering on or off on core. 38*91f16700Schasinglulu * 1) Control it power domain into on or off in PMU_PWRDN_CON reg, 39*91f16700Schasinglulu * it is core_pwr_pd mode 40*91f16700Schasinglulu * 2) Enable the core power manage in PMU_CORE_PM_CON reg, 41*91f16700Schasinglulu * then, if the core enter into wfi, it power domain will be 42*91f16700Schasinglulu * powered off automatically. it is core_pwr_wfi or core_pwr_wfi_int mode 43*91f16700Schasinglulu * so we need core_pm_cfg_info to distinguish which method be used now. 44*91f16700Schasinglulu */ 45*91f16700Schasinglulu 46*91f16700Schasinglulu static uint32_t cores_pd_cfg_info[PLATFORM_CORE_COUNT] 47*91f16700Schasinglulu #if USE_COHERENT_MEM 48*91f16700Schasinglulu __attribute__ ((section(".tzfw_coherent_mem"))) 49*91f16700Schasinglulu #endif 50*91f16700Schasinglulu ; 51*91f16700Schasinglulu 52*91f16700Schasinglulu struct px30_sleep_ddr_data { 53*91f16700Schasinglulu uint32_t clk_sel0; 54*91f16700Schasinglulu uint32_t cru_mode_save; 55*91f16700Schasinglulu uint32_t cru_pmu_mode_save; 56*91f16700Schasinglulu uint32_t ddrc_hwlpctl; 57*91f16700Schasinglulu uint32_t ddrc_pwrctrl; 58*91f16700Schasinglulu uint32_t ddrgrf_con0; 59*91f16700Schasinglulu uint32_t ddrgrf_con1; 60*91f16700Schasinglulu uint32_t ddrstdby_con0; 61*91f16700Schasinglulu uint32_t gpio0b_iomux; 62*91f16700Schasinglulu uint32_t gpio0c_iomux; 63*91f16700Schasinglulu uint32_t pmu_pwrmd_core_l; 64*91f16700Schasinglulu uint32_t pmu_pwrmd_core_h; 65*91f16700Schasinglulu uint32_t pmu_pwrmd_cmm_l; 66*91f16700Schasinglulu uint32_t pmu_pwrmd_cmm_h; 67*91f16700Schasinglulu uint32_t pmu_wkup_cfg2_l; 68*91f16700Schasinglulu uint32_t pmu_cru_clksel_con0; 69*91f16700Schasinglulu uint32_t pmugrf_soc_con0; 70*91f16700Schasinglulu uint32_t pmusgrf_soc_con0; 71*91f16700Schasinglulu uint32_t pmic_slp_iomux; 72*91f16700Schasinglulu uint32_t pgrf_pvtm_con[2]; 73*91f16700Schasinglulu uint32_t cru_clk_gate[CRU_CLKGATES_CON_CNT]; 74*91f16700Schasinglulu uint32_t cru_pmu_clk_gate[CRU_PMU_CLKGATE_CON_CNT]; 75*91f16700Schasinglulu uint32_t cru_plls_con_save[END_PLL_ID][PLL_CON_CNT]; 76*91f16700Schasinglulu uint32_t cpu_qos[CPU_AXI_QOS_NUM_REGS]; 77*91f16700Schasinglulu uint32_t gpu_qos[CPU_AXI_QOS_NUM_REGS]; 78*91f16700Schasinglulu uint32_t isp_128m_qos[CPU_AXI_QOS_NUM_REGS]; 79*91f16700Schasinglulu uint32_t isp_rd_qos[CPU_AXI_QOS_NUM_REGS]; 80*91f16700Schasinglulu uint32_t isp_wr_qos[CPU_AXI_QOS_NUM_REGS]; 81*91f16700Schasinglulu uint32_t isp_m1_qos[CPU_AXI_QOS_NUM_REGS]; 82*91f16700Schasinglulu uint32_t vip_qos[CPU_AXI_QOS_NUM_REGS]; 83*91f16700Schasinglulu uint32_t rga_rd_qos[CPU_AXI_QOS_NUM_REGS]; 84*91f16700Schasinglulu uint32_t rga_wr_qos[CPU_AXI_QOS_NUM_REGS]; 85*91f16700Schasinglulu uint32_t vop_m0_qos[CPU_AXI_QOS_NUM_REGS]; 86*91f16700Schasinglulu uint32_t vop_m1_qos[CPU_AXI_QOS_NUM_REGS]; 87*91f16700Schasinglulu uint32_t vpu_qos[CPU_AXI_QOS_NUM_REGS]; 88*91f16700Schasinglulu uint32_t vpu_r128_qos[CPU_AXI_QOS_NUM_REGS]; 89*91f16700Schasinglulu uint32_t dcf_qos[CPU_AXI_QOS_NUM_REGS]; 90*91f16700Schasinglulu uint32_t dmac_qos[CPU_AXI_QOS_NUM_REGS]; 91*91f16700Schasinglulu uint32_t crypto_qos[CPU_AXI_QOS_NUM_REGS]; 92*91f16700Schasinglulu uint32_t gmac_qos[CPU_AXI_QOS_NUM_REGS]; 93*91f16700Schasinglulu uint32_t emmc_qos[CPU_AXI_QOS_NUM_REGS]; 94*91f16700Schasinglulu uint32_t nand_qos[CPU_AXI_QOS_NUM_REGS]; 95*91f16700Schasinglulu uint32_t sdio_qos[CPU_AXI_QOS_NUM_REGS]; 96*91f16700Schasinglulu uint32_t sfc_qos[CPU_AXI_QOS_NUM_REGS]; 97*91f16700Schasinglulu uint32_t sdmmc_qos[CPU_AXI_QOS_NUM_REGS]; 98*91f16700Schasinglulu uint32_t usb_host_qos[CPU_AXI_QOS_NUM_REGS]; 99*91f16700Schasinglulu uint32_t usb_otg_qos[CPU_AXI_QOS_NUM_REGS]; 100*91f16700Schasinglulu }; 101*91f16700Schasinglulu 102*91f16700Schasinglulu static struct px30_sleep_ddr_data ddr_data 103*91f16700Schasinglulu #if USE_COHERENT_MEM 104*91f16700Schasinglulu __attribute__ ((section(".tzfw_coherent_mem"))) 105*91f16700Schasinglulu #endif 106*91f16700Schasinglulu ; 107*91f16700Schasinglulu 108*91f16700Schasinglulu static inline uint32_t get_cpus_pwr_domain_cfg_info(uint32_t cpu_id) 109*91f16700Schasinglulu { 110*91f16700Schasinglulu assert(cpu_id < PLATFORM_CORE_COUNT); 111*91f16700Schasinglulu return cores_pd_cfg_info[cpu_id]; 112*91f16700Schasinglulu } 113*91f16700Schasinglulu 114*91f16700Schasinglulu static inline void set_cpus_pwr_domain_cfg_info(uint32_t cpu_id, uint32_t value) 115*91f16700Schasinglulu { 116*91f16700Schasinglulu assert(cpu_id < PLATFORM_CORE_COUNT); 117*91f16700Schasinglulu cores_pd_cfg_info[cpu_id] = value; 118*91f16700Schasinglulu #if !USE_COHERENT_MEM 119*91f16700Schasinglulu flush_dcache_range((uintptr_t)&cores_pd_cfg_info[cpu_id], 120*91f16700Schasinglulu sizeof(uint32_t)); 121*91f16700Schasinglulu #endif 122*91f16700Schasinglulu } 123*91f16700Schasinglulu 124*91f16700Schasinglulu static inline uint32_t pmu_power_domain_st(uint32_t pd) 125*91f16700Schasinglulu { 126*91f16700Schasinglulu return mmio_read_32(PMU_BASE + PMU_PWRDN_ST) & BIT(pd) ? 127*91f16700Schasinglulu pmu_pd_off : 128*91f16700Schasinglulu pmu_pd_on; 129*91f16700Schasinglulu } 130*91f16700Schasinglulu 131*91f16700Schasinglulu static int pmu_power_domain_ctr(uint32_t pd, uint32_t pd_state) 132*91f16700Schasinglulu { 133*91f16700Schasinglulu uint32_t loop = 0; 134*91f16700Schasinglulu int ret = 0; 135*91f16700Schasinglulu 136*91f16700Schasinglulu rockchip_pd_lock_get(); 137*91f16700Schasinglulu 138*91f16700Schasinglulu mmio_write_32(PMU_BASE + PMU_PWRDN_CON, 139*91f16700Schasinglulu BITS_WITH_WMASK(pd_state, 0x1, pd)); 140*91f16700Schasinglulu dsb(); 141*91f16700Schasinglulu 142*91f16700Schasinglulu while ((pmu_power_domain_st(pd) != pd_state) && (loop < PD_CTR_LOOP)) { 143*91f16700Schasinglulu udelay(1); 144*91f16700Schasinglulu loop++; 145*91f16700Schasinglulu } 146*91f16700Schasinglulu 147*91f16700Schasinglulu if (pmu_power_domain_st(pd) != pd_state) { 148*91f16700Schasinglulu WARN("%s: %d, %d, error!\n", __func__, pd, pd_state); 149*91f16700Schasinglulu ret = -EINVAL; 150*91f16700Schasinglulu } 151*91f16700Schasinglulu 152*91f16700Schasinglulu rockchip_pd_lock_rls(); 153*91f16700Schasinglulu 154*91f16700Schasinglulu return ret; 155*91f16700Schasinglulu } 156*91f16700Schasinglulu 157*91f16700Schasinglulu static inline uint32_t pmu_bus_idle_st(uint32_t bus) 158*91f16700Schasinglulu { 159*91f16700Schasinglulu return !!((mmio_read_32(PMU_BASE + PMU_BUS_IDLE_ST) & BIT(bus)) && 160*91f16700Schasinglulu (mmio_read_32(PMU_BASE + PMU_BUS_IDLE_ST) & BIT(bus + 16))); 161*91f16700Schasinglulu } 162*91f16700Schasinglulu 163*91f16700Schasinglulu static void pmu_bus_idle_req(uint32_t bus, uint32_t state) 164*91f16700Schasinglulu { 165*91f16700Schasinglulu uint32_t wait_cnt = 0; 166*91f16700Schasinglulu 167*91f16700Schasinglulu mmio_write_32(PMU_BASE + PMU_BUS_IDLE_REQ, 168*91f16700Schasinglulu BITS_WITH_WMASK(state, 0x1, bus)); 169*91f16700Schasinglulu 170*91f16700Schasinglulu while (pmu_bus_idle_st(bus) != state && 171*91f16700Schasinglulu wait_cnt < BUS_IDLE_LOOP) { 172*91f16700Schasinglulu udelay(1); 173*91f16700Schasinglulu wait_cnt++; 174*91f16700Schasinglulu } 175*91f16700Schasinglulu 176*91f16700Schasinglulu if (pmu_bus_idle_st(bus) != state) 177*91f16700Schasinglulu WARN("%s:idle_st=0x%x, bus_id=%d\n", 178*91f16700Schasinglulu __func__, mmio_read_32(PMU_BASE + PMU_BUS_IDLE_ST), bus); 179*91f16700Schasinglulu } 180*91f16700Schasinglulu 181*91f16700Schasinglulu static void qos_save(void) 182*91f16700Schasinglulu { 183*91f16700Schasinglulu /* scu powerdomain will power off, so cpu qos should be saved */ 184*91f16700Schasinglulu SAVE_QOS(ddr_data.cpu_qos, CPU); 185*91f16700Schasinglulu 186*91f16700Schasinglulu if (pmu_power_domain_st(PD_GPU) == pmu_pd_on) 187*91f16700Schasinglulu SAVE_QOS(ddr_data.gpu_qos, GPU); 188*91f16700Schasinglulu if (pmu_power_domain_st(PD_VI) == pmu_pd_on) { 189*91f16700Schasinglulu SAVE_QOS(ddr_data.isp_128m_qos, ISP_128M); 190*91f16700Schasinglulu SAVE_QOS(ddr_data.isp_rd_qos, ISP_RD); 191*91f16700Schasinglulu SAVE_QOS(ddr_data.isp_wr_qos, ISP_WR); 192*91f16700Schasinglulu SAVE_QOS(ddr_data.isp_m1_qos, ISP_M1); 193*91f16700Schasinglulu SAVE_QOS(ddr_data.vip_qos, VIP); 194*91f16700Schasinglulu } 195*91f16700Schasinglulu if (pmu_power_domain_st(PD_VO) == pmu_pd_on) { 196*91f16700Schasinglulu SAVE_QOS(ddr_data.rga_rd_qos, RGA_RD); 197*91f16700Schasinglulu SAVE_QOS(ddr_data.rga_wr_qos, RGA_WR); 198*91f16700Schasinglulu SAVE_QOS(ddr_data.vop_m0_qos, VOP_M0); 199*91f16700Schasinglulu SAVE_QOS(ddr_data.vop_m1_qos, VOP_M1); 200*91f16700Schasinglulu } 201*91f16700Schasinglulu if (pmu_power_domain_st(PD_VPU) == pmu_pd_on) { 202*91f16700Schasinglulu SAVE_QOS(ddr_data.vpu_qos, VPU); 203*91f16700Schasinglulu SAVE_QOS(ddr_data.vpu_r128_qos, VPU_R128); 204*91f16700Schasinglulu } 205*91f16700Schasinglulu if (pmu_power_domain_st(PD_MMC_NAND) == pmu_pd_on) { 206*91f16700Schasinglulu SAVE_QOS(ddr_data.emmc_qos, EMMC); 207*91f16700Schasinglulu SAVE_QOS(ddr_data.nand_qos, NAND); 208*91f16700Schasinglulu SAVE_QOS(ddr_data.sdio_qos, SDIO); 209*91f16700Schasinglulu SAVE_QOS(ddr_data.sfc_qos, SFC); 210*91f16700Schasinglulu } 211*91f16700Schasinglulu if (pmu_power_domain_st(PD_GMAC) == pmu_pd_on) 212*91f16700Schasinglulu SAVE_QOS(ddr_data.gmac_qos, GMAC); 213*91f16700Schasinglulu if (pmu_power_domain_st(PD_CRYPTO) == pmu_pd_on) 214*91f16700Schasinglulu SAVE_QOS(ddr_data.crypto_qos, CRYPTO); 215*91f16700Schasinglulu if (pmu_power_domain_st(PD_SDCARD) == pmu_pd_on) 216*91f16700Schasinglulu SAVE_QOS(ddr_data.sdmmc_qos, SDMMC); 217*91f16700Schasinglulu if (pmu_power_domain_st(PD_USB) == pmu_pd_on) { 218*91f16700Schasinglulu SAVE_QOS(ddr_data.usb_host_qos, USB_HOST); 219*91f16700Schasinglulu SAVE_QOS(ddr_data.usb_otg_qos, USB_OTG); 220*91f16700Schasinglulu } 221*91f16700Schasinglulu } 222*91f16700Schasinglulu 223*91f16700Schasinglulu static void qos_restore(void) 224*91f16700Schasinglulu { 225*91f16700Schasinglulu RESTORE_QOS(ddr_data.cpu_qos, CPU); 226*91f16700Schasinglulu 227*91f16700Schasinglulu if (pmu_power_domain_st(PD_GPU) == pmu_pd_on) 228*91f16700Schasinglulu RESTORE_QOS(ddr_data.gpu_qos, GPU); 229*91f16700Schasinglulu if (pmu_power_domain_st(PD_VI) == pmu_pd_on) { 230*91f16700Schasinglulu RESTORE_QOS(ddr_data.isp_128m_qos, ISP_128M); 231*91f16700Schasinglulu RESTORE_QOS(ddr_data.isp_rd_qos, ISP_RD); 232*91f16700Schasinglulu RESTORE_QOS(ddr_data.isp_wr_qos, ISP_WR); 233*91f16700Schasinglulu RESTORE_QOS(ddr_data.isp_m1_qos, ISP_M1); 234*91f16700Schasinglulu RESTORE_QOS(ddr_data.vip_qos, VIP); 235*91f16700Schasinglulu } 236*91f16700Schasinglulu if (pmu_power_domain_st(PD_VO) == pmu_pd_on) { 237*91f16700Schasinglulu RESTORE_QOS(ddr_data.rga_rd_qos, RGA_RD); 238*91f16700Schasinglulu RESTORE_QOS(ddr_data.rga_wr_qos, RGA_WR); 239*91f16700Schasinglulu RESTORE_QOS(ddr_data.vop_m0_qos, VOP_M0); 240*91f16700Schasinglulu RESTORE_QOS(ddr_data.vop_m1_qos, VOP_M1); 241*91f16700Schasinglulu } 242*91f16700Schasinglulu if (pmu_power_domain_st(PD_VPU) == pmu_pd_on) { 243*91f16700Schasinglulu RESTORE_QOS(ddr_data.vpu_qos, VPU); 244*91f16700Schasinglulu RESTORE_QOS(ddr_data.vpu_r128_qos, VPU_R128); 245*91f16700Schasinglulu } 246*91f16700Schasinglulu if (pmu_power_domain_st(PD_MMC_NAND) == pmu_pd_on) { 247*91f16700Schasinglulu RESTORE_QOS(ddr_data.emmc_qos, EMMC); 248*91f16700Schasinglulu RESTORE_QOS(ddr_data.nand_qos, NAND); 249*91f16700Schasinglulu RESTORE_QOS(ddr_data.sdio_qos, SDIO); 250*91f16700Schasinglulu RESTORE_QOS(ddr_data.sfc_qos, SFC); 251*91f16700Schasinglulu } 252*91f16700Schasinglulu if (pmu_power_domain_st(PD_GMAC) == pmu_pd_on) 253*91f16700Schasinglulu RESTORE_QOS(ddr_data.gmac_qos, GMAC); 254*91f16700Schasinglulu if (pmu_power_domain_st(PD_CRYPTO) == pmu_pd_on) 255*91f16700Schasinglulu RESTORE_QOS(ddr_data.crypto_qos, CRYPTO); 256*91f16700Schasinglulu if (pmu_power_domain_st(PD_SDCARD) == pmu_pd_on) 257*91f16700Schasinglulu RESTORE_QOS(ddr_data.sdmmc_qos, SDMMC); 258*91f16700Schasinglulu if (pmu_power_domain_st(PD_USB) == pmu_pd_on) { 259*91f16700Schasinglulu RESTORE_QOS(ddr_data.usb_host_qos, USB_HOST); 260*91f16700Schasinglulu RESTORE_QOS(ddr_data.usb_otg_qos, USB_OTG); 261*91f16700Schasinglulu } 262*91f16700Schasinglulu } 263*91f16700Schasinglulu 264*91f16700Schasinglulu static int pmu_set_power_domain(uint32_t pd_id, uint32_t pd_state) 265*91f16700Schasinglulu { 266*91f16700Schasinglulu uint32_t state; 267*91f16700Schasinglulu 268*91f16700Schasinglulu if (pmu_power_domain_st(pd_id) == pd_state) 269*91f16700Schasinglulu goto out; 270*91f16700Schasinglulu 271*91f16700Schasinglulu if (pd_state == pmu_pd_on) 272*91f16700Schasinglulu pmu_power_domain_ctr(pd_id, pd_state); 273*91f16700Schasinglulu 274*91f16700Schasinglulu state = (pd_state == pmu_pd_off) ? bus_idle : bus_active; 275*91f16700Schasinglulu 276*91f16700Schasinglulu switch (pd_id) { 277*91f16700Schasinglulu case PD_GPU: 278*91f16700Schasinglulu pmu_bus_idle_req(BUS_ID_GPU, state); 279*91f16700Schasinglulu break; 280*91f16700Schasinglulu case PD_VI: 281*91f16700Schasinglulu pmu_bus_idle_req(BUS_ID_VI, state); 282*91f16700Schasinglulu break; 283*91f16700Schasinglulu case PD_VO: 284*91f16700Schasinglulu pmu_bus_idle_req(BUS_ID_VO, state); 285*91f16700Schasinglulu break; 286*91f16700Schasinglulu case PD_VPU: 287*91f16700Schasinglulu pmu_bus_idle_req(BUS_ID_VPU, state); 288*91f16700Schasinglulu break; 289*91f16700Schasinglulu case PD_MMC_NAND: 290*91f16700Schasinglulu pmu_bus_idle_req(BUS_ID_MMC, state); 291*91f16700Schasinglulu break; 292*91f16700Schasinglulu case PD_GMAC: 293*91f16700Schasinglulu pmu_bus_idle_req(BUS_ID_GMAC, state); 294*91f16700Schasinglulu break; 295*91f16700Schasinglulu case PD_CRYPTO: 296*91f16700Schasinglulu pmu_bus_idle_req(BUS_ID_CRYPTO, state); 297*91f16700Schasinglulu break; 298*91f16700Schasinglulu case PD_SDCARD: 299*91f16700Schasinglulu pmu_bus_idle_req(BUS_ID_SDCARD, state); 300*91f16700Schasinglulu break; 301*91f16700Schasinglulu case PD_USB: 302*91f16700Schasinglulu pmu_bus_idle_req(BUS_ID_USB, state); 303*91f16700Schasinglulu break; 304*91f16700Schasinglulu default: 305*91f16700Schasinglulu break; 306*91f16700Schasinglulu } 307*91f16700Schasinglulu 308*91f16700Schasinglulu if (pd_state == pmu_pd_off) 309*91f16700Schasinglulu pmu_power_domain_ctr(pd_id, pd_state); 310*91f16700Schasinglulu 311*91f16700Schasinglulu out: 312*91f16700Schasinglulu return 0; 313*91f16700Schasinglulu } 314*91f16700Schasinglulu 315*91f16700Schasinglulu static uint32_t pmu_powerdomain_state; 316*91f16700Schasinglulu 317*91f16700Schasinglulu static void pmu_power_domains_suspend(void) 318*91f16700Schasinglulu { 319*91f16700Schasinglulu uint32_t clkgt_save[CRU_CLKGATES_CON_CNT + CRU_PMU_CLKGATE_CON_CNT]; 320*91f16700Schasinglulu 321*91f16700Schasinglulu clk_gate_con_save(clkgt_save); 322*91f16700Schasinglulu clk_gate_con_disable(); 323*91f16700Schasinglulu qos_save(); 324*91f16700Schasinglulu 325*91f16700Schasinglulu pmu_powerdomain_state = mmio_read_32(PMU_BASE + PMU_PWRDN_ST); 326*91f16700Schasinglulu pmu_set_power_domain(PD_GPU, pmu_pd_off); 327*91f16700Schasinglulu pmu_set_power_domain(PD_VI, pmu_pd_off); 328*91f16700Schasinglulu pmu_set_power_domain(PD_VO, pmu_pd_off); 329*91f16700Schasinglulu pmu_set_power_domain(PD_VPU, pmu_pd_off); 330*91f16700Schasinglulu pmu_set_power_domain(PD_MMC_NAND, pmu_pd_off); 331*91f16700Schasinglulu pmu_set_power_domain(PD_GMAC, pmu_pd_off); 332*91f16700Schasinglulu pmu_set_power_domain(PD_CRYPTO, pmu_pd_off); 333*91f16700Schasinglulu pmu_set_power_domain(PD_SDCARD, pmu_pd_off); 334*91f16700Schasinglulu pmu_set_power_domain(PD_USB, pmu_pd_off); 335*91f16700Schasinglulu 336*91f16700Schasinglulu clk_gate_con_restore(clkgt_save); 337*91f16700Schasinglulu } 338*91f16700Schasinglulu 339*91f16700Schasinglulu static void pmu_power_domains_resume(void) 340*91f16700Schasinglulu { 341*91f16700Schasinglulu uint32_t clkgt_save[CRU_CLKGATES_CON_CNT + CRU_PMU_CLKGATE_CON_CNT]; 342*91f16700Schasinglulu 343*91f16700Schasinglulu clk_gate_con_save(clkgt_save); 344*91f16700Schasinglulu clk_gate_con_disable(); 345*91f16700Schasinglulu 346*91f16700Schasinglulu if (!(pmu_powerdomain_state & BIT(PD_USB))) 347*91f16700Schasinglulu pmu_set_power_domain(PD_USB, pmu_pd_on); 348*91f16700Schasinglulu if (!(pmu_powerdomain_state & BIT(PD_SDCARD))) 349*91f16700Schasinglulu pmu_set_power_domain(PD_SDCARD, pmu_pd_on); 350*91f16700Schasinglulu if (!(pmu_powerdomain_state & BIT(PD_CRYPTO))) 351*91f16700Schasinglulu pmu_set_power_domain(PD_CRYPTO, pmu_pd_on); 352*91f16700Schasinglulu if (!(pmu_powerdomain_state & BIT(PD_GMAC))) 353*91f16700Schasinglulu pmu_set_power_domain(PD_GMAC, pmu_pd_on); 354*91f16700Schasinglulu if (!(pmu_powerdomain_state & BIT(PD_MMC_NAND))) 355*91f16700Schasinglulu pmu_set_power_domain(PD_MMC_NAND, pmu_pd_on); 356*91f16700Schasinglulu if (!(pmu_powerdomain_state & BIT(PD_VPU))) 357*91f16700Schasinglulu pmu_set_power_domain(PD_VPU, pmu_pd_on); 358*91f16700Schasinglulu if (!(pmu_powerdomain_state & BIT(PD_VO))) 359*91f16700Schasinglulu pmu_set_power_domain(PD_VO, pmu_pd_on); 360*91f16700Schasinglulu if (!(pmu_powerdomain_state & BIT(PD_VI))) 361*91f16700Schasinglulu pmu_set_power_domain(PD_VI, pmu_pd_on); 362*91f16700Schasinglulu if (!(pmu_powerdomain_state & BIT(PD_GPU))) 363*91f16700Schasinglulu pmu_set_power_domain(PD_GPU, pmu_pd_on); 364*91f16700Schasinglulu 365*91f16700Schasinglulu qos_restore(); 366*91f16700Schasinglulu clk_gate_con_restore(clkgt_save); 367*91f16700Schasinglulu } 368*91f16700Schasinglulu 369*91f16700Schasinglulu static int check_cpu_wfie(uint32_t cpu) 370*91f16700Schasinglulu { 371*91f16700Schasinglulu uint32_t loop = 0, wfie_msk = CKECK_WFEI_MSK << cpu; 372*91f16700Schasinglulu 373*91f16700Schasinglulu while (!(mmio_read_32(GRF_BASE + GRF_CPU_STATUS1) & wfie_msk) && 374*91f16700Schasinglulu (loop < WFEI_CHECK_LOOP)) { 375*91f16700Schasinglulu udelay(1); 376*91f16700Schasinglulu loop++; 377*91f16700Schasinglulu } 378*91f16700Schasinglulu 379*91f16700Schasinglulu if ((mmio_read_32(GRF_BASE + GRF_CPU_STATUS1) & wfie_msk) == 0) { 380*91f16700Schasinglulu WARN("%s: %d, %d, error!\n", __func__, cpu, wfie_msk); 381*91f16700Schasinglulu return -EINVAL; 382*91f16700Schasinglulu } 383*91f16700Schasinglulu 384*91f16700Schasinglulu return 0; 385*91f16700Schasinglulu } 386*91f16700Schasinglulu 387*91f16700Schasinglulu static int cpus_power_domain_on(uint32_t cpu_id) 388*91f16700Schasinglulu { 389*91f16700Schasinglulu uint32_t cpu_pd, apm_value, cfg_info, loop = 0; 390*91f16700Schasinglulu 391*91f16700Schasinglulu cpu_pd = PD_CPU0 + cpu_id; 392*91f16700Schasinglulu cfg_info = get_cpus_pwr_domain_cfg_info(cpu_id); 393*91f16700Schasinglulu 394*91f16700Schasinglulu if (cfg_info == core_pwr_pd) { 395*91f16700Schasinglulu /* disable apm cfg */ 396*91f16700Schasinglulu mmio_write_32(PMU_BASE + PMU_CPUAPM_CON(cpu_id), 397*91f16700Schasinglulu WITH_16BITS_WMSK(CORES_PM_DISABLE)); 398*91f16700Schasinglulu if (pmu_power_domain_st(cpu_pd) == pmu_pd_on) { 399*91f16700Schasinglulu mmio_write_32(PMU_BASE + PMU_CPUAPM_CON(cpu_id), 400*91f16700Schasinglulu WITH_16BITS_WMSK(CORES_PM_DISABLE)); 401*91f16700Schasinglulu pmu_power_domain_ctr(cpu_pd, pmu_pd_off); 402*91f16700Schasinglulu } 403*91f16700Schasinglulu pmu_power_domain_ctr(cpu_pd, pmu_pd_on); 404*91f16700Schasinglulu } else { 405*91f16700Schasinglulu /* wait cpu down */ 406*91f16700Schasinglulu while (pmu_power_domain_st(cpu_pd) == pmu_pd_on && loop < 100) { 407*91f16700Schasinglulu udelay(2); 408*91f16700Schasinglulu loop++; 409*91f16700Schasinglulu } 410*91f16700Schasinglulu 411*91f16700Schasinglulu /* return error if can't wait cpu down */ 412*91f16700Schasinglulu if (pmu_power_domain_st(cpu_pd) == pmu_pd_on) { 413*91f16700Schasinglulu WARN("%s:can't wait cpu down\n", __func__); 414*91f16700Schasinglulu return -EINVAL; 415*91f16700Schasinglulu } 416*91f16700Schasinglulu 417*91f16700Schasinglulu /* power up cpu in power down state */ 418*91f16700Schasinglulu apm_value = BIT(core_pm_sft_wakeup_en); 419*91f16700Schasinglulu mmio_write_32(PMU_BASE + PMU_CPUAPM_CON(cpu_id), 420*91f16700Schasinglulu WITH_16BITS_WMSK(apm_value)); 421*91f16700Schasinglulu } 422*91f16700Schasinglulu 423*91f16700Schasinglulu return 0; 424*91f16700Schasinglulu } 425*91f16700Schasinglulu 426*91f16700Schasinglulu static int cpus_power_domain_off(uint32_t cpu_id, uint32_t pd_cfg) 427*91f16700Schasinglulu { 428*91f16700Schasinglulu uint32_t cpu_pd, apm_value; 429*91f16700Schasinglulu 430*91f16700Schasinglulu cpu_pd = PD_CPU0 + cpu_id; 431*91f16700Schasinglulu if (pmu_power_domain_st(cpu_pd) == pmu_pd_off) 432*91f16700Schasinglulu return 0; 433*91f16700Schasinglulu 434*91f16700Schasinglulu if (pd_cfg == core_pwr_pd) { 435*91f16700Schasinglulu if (check_cpu_wfie(cpu_id)) 436*91f16700Schasinglulu return -EINVAL; 437*91f16700Schasinglulu /* disable apm cfg */ 438*91f16700Schasinglulu mmio_write_32(PMU_BASE + PMU_CPUAPM_CON(cpu_id), 439*91f16700Schasinglulu WITH_16BITS_WMSK(CORES_PM_DISABLE)); 440*91f16700Schasinglulu set_cpus_pwr_domain_cfg_info(cpu_id, pd_cfg); 441*91f16700Schasinglulu pmu_power_domain_ctr(cpu_pd, pmu_pd_off); 442*91f16700Schasinglulu } else { 443*91f16700Schasinglulu set_cpus_pwr_domain_cfg_info(cpu_id, pd_cfg); 444*91f16700Schasinglulu apm_value = BIT(core_pm_en) | BIT(core_pm_dis_int); 445*91f16700Schasinglulu if (pd_cfg == core_pwr_wfi_int) 446*91f16700Schasinglulu apm_value |= BIT(core_pm_int_wakeup_en); 447*91f16700Schasinglulu mmio_write_32(PMU_BASE + PMU_CPUAPM_CON(cpu_id), 448*91f16700Schasinglulu WITH_16BITS_WMSK(apm_value)); 449*91f16700Schasinglulu } 450*91f16700Schasinglulu 451*91f16700Schasinglulu return 0; 452*91f16700Schasinglulu } 453*91f16700Schasinglulu 454*91f16700Schasinglulu static void nonboot_cpus_off(void) 455*91f16700Schasinglulu { 456*91f16700Schasinglulu uint32_t boot_cpu, cpu; 457*91f16700Schasinglulu 458*91f16700Schasinglulu boot_cpu = plat_my_core_pos(); 459*91f16700Schasinglulu 460*91f16700Schasinglulu for (cpu = 0; cpu < PLATFORM_CORE_COUNT; cpu++) { 461*91f16700Schasinglulu if (cpu == boot_cpu) 462*91f16700Schasinglulu continue; 463*91f16700Schasinglulu cpus_power_domain_off(cpu, core_pwr_pd); 464*91f16700Schasinglulu } 465*91f16700Schasinglulu } 466*91f16700Schasinglulu 467*91f16700Schasinglulu int rockchip_soc_cores_pwr_dm_on(unsigned long mpidr, 468*91f16700Schasinglulu uint64_t entrypoint) 469*91f16700Schasinglulu { 470*91f16700Schasinglulu uint32_t cpu_id = plat_core_pos_by_mpidr(mpidr); 471*91f16700Schasinglulu 472*91f16700Schasinglulu assert(cpu_id < PLATFORM_CORE_COUNT); 473*91f16700Schasinglulu assert(cpuson_flags[cpu_id] == 0); 474*91f16700Schasinglulu cpuson_flags[cpu_id] = PMU_CPU_HOTPLUG; 475*91f16700Schasinglulu cpuson_entry_point[cpu_id] = entrypoint; 476*91f16700Schasinglulu dsb(); 477*91f16700Schasinglulu 478*91f16700Schasinglulu cpus_power_domain_on(cpu_id); 479*91f16700Schasinglulu 480*91f16700Schasinglulu return PSCI_E_SUCCESS; 481*91f16700Schasinglulu } 482*91f16700Schasinglulu 483*91f16700Schasinglulu int rockchip_soc_cores_pwr_dm_on_finish(void) 484*91f16700Schasinglulu { 485*91f16700Schasinglulu uint32_t cpu_id = plat_my_core_pos(); 486*91f16700Schasinglulu 487*91f16700Schasinglulu mmio_write_32(PMU_BASE + PMU_CPUAPM_CON(cpu_id), 488*91f16700Schasinglulu WITH_16BITS_WMSK(CORES_PM_DISABLE)); 489*91f16700Schasinglulu return PSCI_E_SUCCESS; 490*91f16700Schasinglulu } 491*91f16700Schasinglulu 492*91f16700Schasinglulu int rockchip_soc_cores_pwr_dm_off(void) 493*91f16700Schasinglulu { 494*91f16700Schasinglulu uint32_t cpu_id = plat_my_core_pos(); 495*91f16700Schasinglulu 496*91f16700Schasinglulu cpus_power_domain_off(cpu_id, core_pwr_wfi); 497*91f16700Schasinglulu 498*91f16700Schasinglulu return PSCI_E_SUCCESS; 499*91f16700Schasinglulu } 500*91f16700Schasinglulu 501*91f16700Schasinglulu int rockchip_soc_cores_pwr_dm_suspend(void) 502*91f16700Schasinglulu { 503*91f16700Schasinglulu uint32_t cpu_id = plat_my_core_pos(); 504*91f16700Schasinglulu 505*91f16700Schasinglulu assert(cpu_id < PLATFORM_CORE_COUNT); 506*91f16700Schasinglulu assert(cpuson_flags[cpu_id] == 0); 507*91f16700Schasinglulu cpuson_flags[cpu_id] = PMU_CPU_AUTO_PWRDN; 508*91f16700Schasinglulu cpuson_entry_point[cpu_id] = plat_get_sec_entrypoint(); 509*91f16700Schasinglulu dsb(); 510*91f16700Schasinglulu 511*91f16700Schasinglulu cpus_power_domain_off(cpu_id, core_pwr_wfi_int); 512*91f16700Schasinglulu 513*91f16700Schasinglulu return PSCI_E_SUCCESS; 514*91f16700Schasinglulu } 515*91f16700Schasinglulu 516*91f16700Schasinglulu int rockchip_soc_cores_pwr_dm_resume(void) 517*91f16700Schasinglulu { 518*91f16700Schasinglulu uint32_t cpu_id = plat_my_core_pos(); 519*91f16700Schasinglulu 520*91f16700Schasinglulu /* Disable core_pm */ 521*91f16700Schasinglulu mmio_write_32(PMU_BASE + PMU_CPUAPM_CON(cpu_id), 522*91f16700Schasinglulu WITH_16BITS_WMSK(CORES_PM_DISABLE)); 523*91f16700Schasinglulu 524*91f16700Schasinglulu return PSCI_E_SUCCESS; 525*91f16700Schasinglulu } 526*91f16700Schasinglulu 527*91f16700Schasinglulu #define CLK_MSK_GATING(msk, con) \ 528*91f16700Schasinglulu mmio_write_32(CRU_BASE + (con), ((msk) << 16) | 0xffff) 529*91f16700Schasinglulu #define CLK_MSK_UNGATING(msk, con) \ 530*91f16700Schasinglulu mmio_write_32(CRU_BASE + (con), ((~(msk)) << 16) | 0xffff) 531*91f16700Schasinglulu 532*91f16700Schasinglulu static uint32_t clk_ungt_msk[CRU_CLKGATES_CON_CNT] = { 533*91f16700Schasinglulu 0xe0ff, 0xffff, 0x0000, 0x0000, 534*91f16700Schasinglulu 0x0000, 0x0380, 0x0000, 0x0000, 535*91f16700Schasinglulu 0x07c0, 0x0000, 0x0000, 0x000f, 536*91f16700Schasinglulu 0x0061, 0x1f02, 0x0440, 0x1801, 537*91f16700Schasinglulu 0x004b, 0x0000 538*91f16700Schasinglulu }; 539*91f16700Schasinglulu 540*91f16700Schasinglulu static uint32_t clk_pmu_ungt_msk[CRU_PMU_CLKGATE_CON_CNT] = { 541*91f16700Schasinglulu 0xf1ff, 0x0310 542*91f16700Schasinglulu }; 543*91f16700Schasinglulu 544*91f16700Schasinglulu void clk_gate_suspend(void) 545*91f16700Schasinglulu { 546*91f16700Schasinglulu int i; 547*91f16700Schasinglulu 548*91f16700Schasinglulu for (i = 0; i < CRU_CLKGATES_CON_CNT; i++) { 549*91f16700Schasinglulu ddr_data.cru_clk_gate[i] = 550*91f16700Schasinglulu mmio_read_32(CRU_BASE + CRU_CLKGATES_CON(i)); 551*91f16700Schasinglulu mmio_write_32(CRU_BASE + CRU_CLKGATES_CON(i), 552*91f16700Schasinglulu WITH_16BITS_WMSK(~clk_ungt_msk[i])); 553*91f16700Schasinglulu } 554*91f16700Schasinglulu 555*91f16700Schasinglulu for (i = 0; i < CRU_PMU_CLKGATE_CON_CNT; i++) { 556*91f16700Schasinglulu ddr_data.cru_pmu_clk_gate[i] = 557*91f16700Schasinglulu mmio_read_32(PMUCRU_BASE + CRU_PMU_CLKGATES_CON(i)); 558*91f16700Schasinglulu mmio_write_32(PMUCRU_BASE + CRU_PMU_CLKGATES_CON(i), 559*91f16700Schasinglulu WITH_16BITS_WMSK(~clk_pmu_ungt_msk[i])); 560*91f16700Schasinglulu } 561*91f16700Schasinglulu } 562*91f16700Schasinglulu 563*91f16700Schasinglulu void clk_gate_resume(void) 564*91f16700Schasinglulu { 565*91f16700Schasinglulu int i; 566*91f16700Schasinglulu 567*91f16700Schasinglulu for (i = 0; i < CRU_PMU_CLKGATE_CON_CNT; i++) 568*91f16700Schasinglulu mmio_write_32(PMUCRU_BASE + CRU_PMU_CLKGATES_CON(i), 569*91f16700Schasinglulu WITH_16BITS_WMSK(ddr_data.cru_pmu_clk_gate[i])); 570*91f16700Schasinglulu 571*91f16700Schasinglulu for (i = 0; i < CRU_CLKGATES_CON_CNT; i++) 572*91f16700Schasinglulu mmio_write_32(CRU_BASE + CRU_CLKGATES_CON(i), 573*91f16700Schasinglulu WITH_16BITS_WMSK(ddr_data.cru_clk_gate[i])); 574*91f16700Schasinglulu } 575*91f16700Schasinglulu 576*91f16700Schasinglulu static void pvtm_32k_config(void) 577*91f16700Schasinglulu { 578*91f16700Schasinglulu uint32_t pvtm_freq_khz, pvtm_div; 579*91f16700Schasinglulu 580*91f16700Schasinglulu ddr_data.pmu_cru_clksel_con0 = 581*91f16700Schasinglulu mmio_read_32(PMUCRU_BASE + CRU_PMU_CLKSELS_CON(0)); 582*91f16700Schasinglulu 583*91f16700Schasinglulu ddr_data.pgrf_pvtm_con[0] = 584*91f16700Schasinglulu mmio_read_32(PMUGRF_BASE + PMUGRF_PVTM_CON0); 585*91f16700Schasinglulu ddr_data.pgrf_pvtm_con[1] = 586*91f16700Schasinglulu mmio_read_32(PMUGRF_BASE + PMUGRF_PVTM_CON1); 587*91f16700Schasinglulu 588*91f16700Schasinglulu mmio_write_32(PMUGRF_BASE + PMUGRF_PVTM_CON0, 589*91f16700Schasinglulu BITS_WITH_WMASK(0, 0x3, pgrf_pvtm_st)); 590*91f16700Schasinglulu dsb(); 591*91f16700Schasinglulu mmio_write_32(PMUGRF_BASE + PMUGRF_PVTM_CON0, 592*91f16700Schasinglulu BITS_WITH_WMASK(1, 0x1, pgrf_pvtm_en)); 593*91f16700Schasinglulu dsb(); 594*91f16700Schasinglulu mmio_write_32(PMUGRF_BASE + PMUGRF_PVTM_CON1, PVTM_CALC_CNT); 595*91f16700Schasinglulu dsb(); 596*91f16700Schasinglulu 597*91f16700Schasinglulu mmio_write_32(PMUGRF_BASE + PMUGRF_PVTM_CON0, 598*91f16700Schasinglulu BITS_WITH_WMASK(1, 0x1, pgrf_pvtm_st)); 599*91f16700Schasinglulu 600*91f16700Schasinglulu /* pmugrf_pvtm_st0 will be clear after PVTM start, 601*91f16700Schasinglulu * which will cost about 6 cycles of pvtm at least. 602*91f16700Schasinglulu * So we wait 30 cycles of pvtm for security. 603*91f16700Schasinglulu */ 604*91f16700Schasinglulu while (mmio_read_32(PMUGRF_BASE + PMUGRF_PVTM_ST1) < 30) 605*91f16700Schasinglulu ; 606*91f16700Schasinglulu 607*91f16700Schasinglulu dsb(); 608*91f16700Schasinglulu while (!(mmio_read_32(PMUGRF_BASE + PMUGRF_PVTM_ST0) & 0x1)) 609*91f16700Schasinglulu ; 610*91f16700Schasinglulu 611*91f16700Schasinglulu pvtm_freq_khz = 612*91f16700Schasinglulu (mmio_read_32(PMUGRF_BASE + PMUGRF_PVTM_ST1) * 24000 + 613*91f16700Schasinglulu PVTM_CALC_CNT / 2) / PVTM_CALC_CNT; 614*91f16700Schasinglulu pvtm_div = (pvtm_freq_khz + 16) / 32; 615*91f16700Schasinglulu 616*91f16700Schasinglulu /* pvtm_div = div_factor << 2 + 1, 617*91f16700Schasinglulu * so div_factor = (pvtm_div - 1) >> 2. 618*91f16700Schasinglulu * But the operation ">> 2" will clear the low bit of pvtm_div, 619*91f16700Schasinglulu * so we don't have to do "- 1" for compasation 620*91f16700Schasinglulu */ 621*91f16700Schasinglulu pvtm_div = pvtm_div >> 2; 622*91f16700Schasinglulu if (pvtm_div > 0x3f) 623*91f16700Schasinglulu pvtm_div = 0x3f; 624*91f16700Schasinglulu 625*91f16700Schasinglulu mmio_write_32(PMUGRF_BASE + PMUGRF_PVTM_CON0, 626*91f16700Schasinglulu BITS_WITH_WMASK(pvtm_div, 0x3f, pgrf_pvtm_div)); 627*91f16700Schasinglulu 628*91f16700Schasinglulu /* select pvtm as 32k source */ 629*91f16700Schasinglulu mmio_write_32(PMUCRU_BASE + CRU_PMU_CLKSELS_CON(0), 630*91f16700Schasinglulu BITS_WITH_WMASK(1, 0x3U, 14)); 631*91f16700Schasinglulu } 632*91f16700Schasinglulu 633*91f16700Schasinglulu static void pvtm_32k_config_restore(void) 634*91f16700Schasinglulu { 635*91f16700Schasinglulu mmio_write_32(PMUCRU_BASE + CRU_PMU_CLKSELS_CON(0), 636*91f16700Schasinglulu ddr_data.pmu_cru_clksel_con0 | BITS_WMSK(0x3U, 14)); 637*91f16700Schasinglulu 638*91f16700Schasinglulu mmio_write_32(PMUGRF_BASE + PMUGRF_PVTM_CON0, 639*91f16700Schasinglulu WITH_16BITS_WMSK(ddr_data.pgrf_pvtm_con[0])); 640*91f16700Schasinglulu mmio_write_32(PMUGRF_BASE + PMUGRF_PVTM_CON1, 641*91f16700Schasinglulu ddr_data.pgrf_pvtm_con[1]); 642*91f16700Schasinglulu } 643*91f16700Schasinglulu 644*91f16700Schasinglulu static void ddr_sleep_config(void) 645*91f16700Schasinglulu { 646*91f16700Schasinglulu /* disable ddr pd, sr */ 647*91f16700Schasinglulu ddr_data.ddrc_pwrctrl = mmio_read_32(DDR_UPCTL_BASE + 0x30); 648*91f16700Schasinglulu mmio_write_32(DDR_UPCTL_BASE + 0x30, BITS_WITH_WMASK(0x0, 0x3, 0)); 649*91f16700Schasinglulu 650*91f16700Schasinglulu /* disable ddr auto gt */ 651*91f16700Schasinglulu ddr_data.ddrgrf_con1 = mmio_read_32(DDRGRF_BASE + 0x4); 652*91f16700Schasinglulu mmio_write_32(DDRGRF_BASE + 0x4, BITS_WITH_WMASK(0x0, 0x1f, 0)); 653*91f16700Schasinglulu 654*91f16700Schasinglulu /* disable ddr standby */ 655*91f16700Schasinglulu ddr_data.ddrstdby_con0 = mmio_read_32(DDR_STDBY_BASE + 0x0); 656*91f16700Schasinglulu mmio_write_32(DDR_STDBY_BASE + 0x0, BITS_WITH_WMASK(0x0, 0x1, 0)); 657*91f16700Schasinglulu while ((mmio_read_32(DDR_UPCTL_BASE + 0x4) & 0x7) != 1) 658*91f16700Schasinglulu ; 659*91f16700Schasinglulu 660*91f16700Schasinglulu /* ddr pmu ctrl */ 661*91f16700Schasinglulu ddr_data.ddrgrf_con0 = mmio_read_32(DDRGRF_BASE + 0x0); 662*91f16700Schasinglulu mmio_write_32(DDRGRF_BASE + 0x0, BITS_WITH_WMASK(0x0, 0x1, 5)); 663*91f16700Schasinglulu dsb(); 664*91f16700Schasinglulu mmio_write_32(DDRGRF_BASE + 0x0, BITS_WITH_WMASK(0x1, 0x1, 4)); 665*91f16700Schasinglulu 666*91f16700Schasinglulu /* ddr ret sel */ 667*91f16700Schasinglulu ddr_data.pmugrf_soc_con0 = 668*91f16700Schasinglulu mmio_read_32(PMUGRF_BASE + PMUGRF_SOC_CON(0)); 669*91f16700Schasinglulu mmio_write_32(PMUGRF_BASE + PMUGRF_SOC_CON(0), 670*91f16700Schasinglulu BITS_WITH_WMASK(0x0, 0x1, 12)); 671*91f16700Schasinglulu } 672*91f16700Schasinglulu 673*91f16700Schasinglulu static void ddr_sleep_config_restore(void) 674*91f16700Schasinglulu { 675*91f16700Schasinglulu /* restore ddr ret sel */ 676*91f16700Schasinglulu mmio_write_32(PMUGRF_BASE + PMUGRF_SOC_CON(0), 677*91f16700Schasinglulu ddr_data.pmugrf_soc_con0 | BITS_WMSK(0x1, 12)); 678*91f16700Schasinglulu 679*91f16700Schasinglulu /* restore ddr pmu ctrl */ 680*91f16700Schasinglulu mmio_write_32(DDRGRF_BASE + 0x0, 681*91f16700Schasinglulu ddr_data.ddrgrf_con0 | BITS_WMSK(0x1, 4)); 682*91f16700Schasinglulu dsb(); 683*91f16700Schasinglulu mmio_write_32(DDRGRF_BASE + 0x0, 684*91f16700Schasinglulu ddr_data.ddrgrf_con0 | BITS_WMSK(0x1, 5)); 685*91f16700Schasinglulu 686*91f16700Schasinglulu /* restore ddr standby */ 687*91f16700Schasinglulu mmio_write_32(DDR_STDBY_BASE + 0x0, 688*91f16700Schasinglulu ddr_data.ddrstdby_con0 | BITS_WMSK(0x1, 0)); 689*91f16700Schasinglulu 690*91f16700Schasinglulu /* restore ddr auto gt */ 691*91f16700Schasinglulu mmio_write_32(DDRGRF_BASE + 0x4, 692*91f16700Schasinglulu ddr_data.ddrgrf_con1 | BITS_WMSK(0x1f, 0)); 693*91f16700Schasinglulu 694*91f16700Schasinglulu /* restore ddr pd, sr */ 695*91f16700Schasinglulu mmio_write_32(DDR_UPCTL_BASE + 0x30, 696*91f16700Schasinglulu ddr_data.ddrc_pwrctrl | BITS_WMSK(0x3, 0)); 697*91f16700Schasinglulu } 698*91f16700Schasinglulu 699*91f16700Schasinglulu static void pmu_sleep_config(void) 700*91f16700Schasinglulu { 701*91f16700Schasinglulu uint32_t pwrmd_core_lo, pwrmd_core_hi, pwrmd_com_lo, pwrmd_com_hi; 702*91f16700Schasinglulu uint32_t pmu_wkup_cfg2_lo; 703*91f16700Schasinglulu uint32_t clk_freq_khz; 704*91f16700Schasinglulu 705*91f16700Schasinglulu /* save pmic_sleep iomux gpio0_a4 */ 706*91f16700Schasinglulu ddr_data.pmic_slp_iomux = mmio_read_32(PMUGRF_BASE + GPIO0A_IOMUX); 707*91f16700Schasinglulu 708*91f16700Schasinglulu ddr_data.pmu_pwrmd_core_l = 709*91f16700Schasinglulu mmio_read_32(PMU_BASE + PMU_PWRMODE_CORE_LO); 710*91f16700Schasinglulu ddr_data.pmu_pwrmd_core_h = 711*91f16700Schasinglulu mmio_read_32(PMU_BASE + PMU_PWRMODE_CORE_HI); 712*91f16700Schasinglulu ddr_data.pmu_pwrmd_cmm_l = 713*91f16700Schasinglulu mmio_read_32(PMU_BASE + PMU_PWRMODE_COMMON_CON_LO); 714*91f16700Schasinglulu ddr_data.pmu_pwrmd_cmm_h = 715*91f16700Schasinglulu mmio_read_32(PMU_BASE + PMU_PWRMODE_COMMON_CON_HI); 716*91f16700Schasinglulu ddr_data.pmu_wkup_cfg2_l = mmio_read_32(PMU_BASE + PMU_WKUP_CFG2_LO); 717*91f16700Schasinglulu 718*91f16700Schasinglulu pwrmd_core_lo = BIT(pmu_global_int_dis) | 719*91f16700Schasinglulu BIT(pmu_core_src_gt) | 720*91f16700Schasinglulu BIT(pmu_cpu0_pd) | 721*91f16700Schasinglulu BIT(pmu_clr_core) | 722*91f16700Schasinglulu BIT(pmu_scu_pd) | 723*91f16700Schasinglulu BIT(pmu_l2_idle) | 724*91f16700Schasinglulu BIT(pmu_l2_flush) | 725*91f16700Schasinglulu BIT(pmu_clr_bus2main) | 726*91f16700Schasinglulu BIT(pmu_clr_peri2msch); 727*91f16700Schasinglulu 728*91f16700Schasinglulu pwrmd_core_hi = BIT(pmu_dpll_pd_en) | 729*91f16700Schasinglulu BIT(pmu_apll_pd_en) | 730*91f16700Schasinglulu BIT(pmu_cpll_pd_en) | 731*91f16700Schasinglulu BIT(pmu_gpll_pd_en) | 732*91f16700Schasinglulu BIT(pmu_npll_pd_en); 733*91f16700Schasinglulu 734*91f16700Schasinglulu pwrmd_com_lo = BIT(pmu_mode_en) | 735*91f16700Schasinglulu BIT(pmu_pll_pd) | 736*91f16700Schasinglulu BIT(pmu_pmu_use_if) | 737*91f16700Schasinglulu BIT(pmu_alive_use_if) | 738*91f16700Schasinglulu BIT(pmu_osc_dis) | 739*91f16700Schasinglulu BIT(pmu_sref_enter) | 740*91f16700Schasinglulu BIT(pmu_ddrc_gt) | 741*91f16700Schasinglulu BIT(pmu_clr_pmu) | 742*91f16700Schasinglulu BIT(pmu_clr_peri_pmu); 743*91f16700Schasinglulu 744*91f16700Schasinglulu pwrmd_com_hi = BIT(pmu_clr_bus) | 745*91f16700Schasinglulu BIT(pmu_clr_msch) | 746*91f16700Schasinglulu BIT(pmu_wakeup_begin_cfg); 747*91f16700Schasinglulu 748*91f16700Schasinglulu pmu_wkup_cfg2_lo = BIT(pmu_cluster_wkup_en) | 749*91f16700Schasinglulu BIT(pmu_gpio_wkup_en) | 750*91f16700Schasinglulu BIT(pmu_timer_wkup_en); 751*91f16700Schasinglulu 752*91f16700Schasinglulu /* set pmic_sleep iomux gpio0_a4 */ 753*91f16700Schasinglulu mmio_write_32(PMUGRF_BASE + GPIO0A_IOMUX, 754*91f16700Schasinglulu BITS_WITH_WMASK(1, 0x3, 8)); 755*91f16700Schasinglulu 756*91f16700Schasinglulu clk_freq_khz = 32; 757*91f16700Schasinglulu 758*91f16700Schasinglulu mmio_write_32(PMU_BASE + PMU_OSC_CNT_LO, 759*91f16700Schasinglulu WITH_16BITS_WMSK(clk_freq_khz * 32 & 0xffff)); 760*91f16700Schasinglulu mmio_write_32(PMU_BASE + PMU_OSC_CNT_HI, 761*91f16700Schasinglulu WITH_16BITS_WMSK(clk_freq_khz * 32 >> 16)); 762*91f16700Schasinglulu 763*91f16700Schasinglulu mmio_write_32(PMU_BASE + PMU_STABLE_CNT_LO, 764*91f16700Schasinglulu WITH_16BITS_WMSK(clk_freq_khz * 32 & 0xffff)); 765*91f16700Schasinglulu mmio_write_32(PMU_BASE + PMU_STABLE_CNT_HI, 766*91f16700Schasinglulu WITH_16BITS_WMSK(clk_freq_khz * 32 >> 16)); 767*91f16700Schasinglulu 768*91f16700Schasinglulu mmio_write_32(PMU_BASE + PMU_WAKEUP_RST_CLR_LO, 769*91f16700Schasinglulu WITH_16BITS_WMSK(clk_freq_khz * 2 & 0xffff)); 770*91f16700Schasinglulu mmio_write_32(PMU_BASE + PMU_WAKEUP_RST_CLR_HI, 771*91f16700Schasinglulu WITH_16BITS_WMSK(clk_freq_khz * 2 >> 16)); 772*91f16700Schasinglulu 773*91f16700Schasinglulu /* Pmu's clk has switched to 24M back When pmu FSM counts 774*91f16700Schasinglulu * the follow counters, so we should use 24M to calculate 775*91f16700Schasinglulu * these counters. 776*91f16700Schasinglulu */ 777*91f16700Schasinglulu mmio_write_32(PMU_BASE + PMU_SCU_PWRDN_CNT_LO, 778*91f16700Schasinglulu WITH_16BITS_WMSK(24000 * 2 & 0xffff)); 779*91f16700Schasinglulu mmio_write_32(PMU_BASE + PMU_SCU_PWRDN_CNT_HI, 780*91f16700Schasinglulu WITH_16BITS_WMSK(24000 * 2 >> 16)); 781*91f16700Schasinglulu 782*91f16700Schasinglulu mmio_write_32(PMU_BASE + PMU_SCU_PWRUP_CNT_LO, 783*91f16700Schasinglulu WITH_16BITS_WMSK(24000 * 2 & 0xffff)); 784*91f16700Schasinglulu mmio_write_32(PMU_BASE + PMU_SCU_PWRUP_CNT_HI, 785*91f16700Schasinglulu WITH_16BITS_WMSK(24000 * 2 >> 16)); 786*91f16700Schasinglulu 787*91f16700Schasinglulu mmio_write_32(PMU_BASE + PMU_PLLLOCK_CNT_LO, 788*91f16700Schasinglulu WITH_16BITS_WMSK(24000 * 5 & 0xffff)); 789*91f16700Schasinglulu mmio_write_32(PMU_BASE + PMU_PLLLOCK_CNT_HI, 790*91f16700Schasinglulu WITH_16BITS_WMSK(24000 * 5 >> 16)); 791*91f16700Schasinglulu 792*91f16700Schasinglulu mmio_write_32(PMU_BASE + PMU_PLLRST_CNT_LO, 793*91f16700Schasinglulu WITH_16BITS_WMSK(24000 * 2 & 0xffff)); 794*91f16700Schasinglulu mmio_write_32(PMU_BASE + PMU_PLLRST_CNT_HI, 795*91f16700Schasinglulu WITH_16BITS_WMSK(24000 * 2 >> 16)); 796*91f16700Schasinglulu 797*91f16700Schasinglulu /* Config pmu power mode and pmu wakeup source */ 798*91f16700Schasinglulu mmio_write_32(PMU_BASE + PMU_PWRMODE_CORE_LO, 799*91f16700Schasinglulu WITH_16BITS_WMSK(pwrmd_core_lo)); 800*91f16700Schasinglulu mmio_write_32(PMU_BASE + PMU_PWRMODE_CORE_HI, 801*91f16700Schasinglulu WITH_16BITS_WMSK(pwrmd_core_hi)); 802*91f16700Schasinglulu 803*91f16700Schasinglulu mmio_write_32(PMU_BASE + PMU_PWRMODE_COMMON_CON_LO, 804*91f16700Schasinglulu WITH_16BITS_WMSK(pwrmd_com_lo)); 805*91f16700Schasinglulu mmio_write_32(PMU_BASE + PMU_PWRMODE_COMMON_CON_HI, 806*91f16700Schasinglulu WITH_16BITS_WMSK(pwrmd_com_hi)); 807*91f16700Schasinglulu 808*91f16700Schasinglulu mmio_write_32(PMU_BASE + PMU_WKUP_CFG2_LO, 809*91f16700Schasinglulu WITH_16BITS_WMSK(pmu_wkup_cfg2_lo)); 810*91f16700Schasinglulu } 811*91f16700Schasinglulu 812*91f16700Schasinglulu static void pmu_sleep_restore(void) 813*91f16700Schasinglulu { 814*91f16700Schasinglulu mmio_write_32(PMU_BASE + PMU_PWRMODE_CORE_LO, 815*91f16700Schasinglulu WITH_16BITS_WMSK(ddr_data.pmu_pwrmd_core_l)); 816*91f16700Schasinglulu mmio_write_32(PMU_BASE + PMU_PWRMODE_CORE_HI, 817*91f16700Schasinglulu WITH_16BITS_WMSK(ddr_data.pmu_pwrmd_core_h)); 818*91f16700Schasinglulu mmio_write_32(PMU_BASE + PMU_PWRMODE_COMMON_CON_LO, 819*91f16700Schasinglulu WITH_16BITS_WMSK(ddr_data.pmu_pwrmd_cmm_l)); 820*91f16700Schasinglulu mmio_write_32(PMU_BASE + PMU_PWRMODE_COMMON_CON_HI, 821*91f16700Schasinglulu WITH_16BITS_WMSK(ddr_data.pmu_pwrmd_cmm_h)); 822*91f16700Schasinglulu mmio_write_32(PMU_BASE + PMU_WKUP_CFG2_LO, 823*91f16700Schasinglulu WITH_16BITS_WMSK(ddr_data.pmu_wkup_cfg2_l)); 824*91f16700Schasinglulu 825*91f16700Schasinglulu /* restore pmic_sleep iomux */ 826*91f16700Schasinglulu mmio_write_32(PMUGRF_BASE + GPIO0A_IOMUX, 827*91f16700Schasinglulu WITH_16BITS_WMSK(ddr_data.pmic_slp_iomux)); 828*91f16700Schasinglulu } 829*91f16700Schasinglulu 830*91f16700Schasinglulu static void soc_sleep_config(void) 831*91f16700Schasinglulu { 832*91f16700Schasinglulu ddr_data.gpio0c_iomux = mmio_read_32(PMUGRF_BASE + GPIO0C_IOMUX); 833*91f16700Schasinglulu 834*91f16700Schasinglulu pmu_sleep_config(); 835*91f16700Schasinglulu 836*91f16700Schasinglulu ddr_sleep_config(); 837*91f16700Schasinglulu 838*91f16700Schasinglulu pvtm_32k_config(); 839*91f16700Schasinglulu } 840*91f16700Schasinglulu 841*91f16700Schasinglulu static void soc_sleep_restore(void) 842*91f16700Schasinglulu { 843*91f16700Schasinglulu secure_timer_init(); 844*91f16700Schasinglulu 845*91f16700Schasinglulu pvtm_32k_config_restore(); 846*91f16700Schasinglulu 847*91f16700Schasinglulu ddr_sleep_config_restore(); 848*91f16700Schasinglulu 849*91f16700Schasinglulu pmu_sleep_restore(); 850*91f16700Schasinglulu 851*91f16700Schasinglulu mmio_write_32(PMUGRF_BASE + GPIO0C_IOMUX, 852*91f16700Schasinglulu WITH_16BITS_WMSK(ddr_data.gpio0c_iomux)); 853*91f16700Schasinglulu } 854*91f16700Schasinglulu 855*91f16700Schasinglulu static inline void pm_pll_wait_lock(uint32_t pll_base, uint32_t pll_id) 856*91f16700Schasinglulu { 857*91f16700Schasinglulu uint32_t delay = PLL_LOCKED_TIMEOUT; 858*91f16700Schasinglulu 859*91f16700Schasinglulu while (delay > 0) { 860*91f16700Schasinglulu if (mmio_read_32(pll_base + PLL_CON(1)) & 861*91f16700Schasinglulu PLL_LOCK_MSK) 862*91f16700Schasinglulu break; 863*91f16700Schasinglulu delay--; 864*91f16700Schasinglulu } 865*91f16700Schasinglulu 866*91f16700Schasinglulu if (delay == 0) 867*91f16700Schasinglulu ERROR("Can't wait pll:%d lock\n", pll_id); 868*91f16700Schasinglulu } 869*91f16700Schasinglulu 870*91f16700Schasinglulu static inline void pll_pwr_ctr(uint32_t pll_base, uint32_t pll_id, uint32_t pd) 871*91f16700Schasinglulu { 872*91f16700Schasinglulu mmio_write_32(pll_base + PLL_CON(1), 873*91f16700Schasinglulu BITS_WITH_WMASK(1, 1U, 15)); 874*91f16700Schasinglulu if (pd) 875*91f16700Schasinglulu mmio_write_32(pll_base + PLL_CON(1), 876*91f16700Schasinglulu BITS_WITH_WMASK(1, 1, 14)); 877*91f16700Schasinglulu else 878*91f16700Schasinglulu mmio_write_32(pll_base + PLL_CON(1), 879*91f16700Schasinglulu BITS_WITH_WMASK(0, 1, 14)); 880*91f16700Schasinglulu } 881*91f16700Schasinglulu 882*91f16700Schasinglulu static inline void pll_set_mode(uint32_t pll_id, uint32_t mode) 883*91f16700Schasinglulu { 884*91f16700Schasinglulu uint32_t val = BITS_WITH_WMASK(mode, 0x3, PLL_MODE_SHIFT(pll_id)); 885*91f16700Schasinglulu 886*91f16700Schasinglulu if (pll_id != GPLL_ID) 887*91f16700Schasinglulu mmio_write_32(CRU_BASE + CRU_MODE, val); 888*91f16700Schasinglulu else 889*91f16700Schasinglulu mmio_write_32(PMUCRU_BASE + CRU_PMU_MODE, 890*91f16700Schasinglulu BITS_WITH_WMASK(mode, 0x3, 0)); 891*91f16700Schasinglulu } 892*91f16700Schasinglulu 893*91f16700Schasinglulu static inline void pll_suspend(uint32_t pll_id) 894*91f16700Schasinglulu { 895*91f16700Schasinglulu int i; 896*91f16700Schasinglulu uint32_t pll_base; 897*91f16700Schasinglulu 898*91f16700Schasinglulu if (pll_id != GPLL_ID) 899*91f16700Schasinglulu pll_base = CRU_BASE + CRU_PLL_CONS(pll_id, 0); 900*91f16700Schasinglulu else 901*91f16700Schasinglulu pll_base = PMUCRU_BASE + CRU_PLL_CONS(0, 0); 902*91f16700Schasinglulu 903*91f16700Schasinglulu /* save pll con */ 904*91f16700Schasinglulu for (i = 0; i < PLL_CON_CNT; i++) 905*91f16700Schasinglulu ddr_data.cru_plls_con_save[pll_id][i] = 906*91f16700Schasinglulu mmio_read_32(pll_base + PLL_CON(i)); 907*91f16700Schasinglulu 908*91f16700Schasinglulu /* slow mode */ 909*91f16700Schasinglulu pll_set_mode(pll_id, SLOW_MODE); 910*91f16700Schasinglulu } 911*91f16700Schasinglulu 912*91f16700Schasinglulu static inline void pll_resume(uint32_t pll_id) 913*91f16700Schasinglulu { 914*91f16700Schasinglulu uint32_t mode, pll_base; 915*91f16700Schasinglulu 916*91f16700Schasinglulu if (pll_id != GPLL_ID) { 917*91f16700Schasinglulu pll_base = CRU_BASE + CRU_PLL_CONS(pll_id, 0); 918*91f16700Schasinglulu mode = (ddr_data.cru_mode_save >> PLL_MODE_SHIFT(pll_id)) & 0x3; 919*91f16700Schasinglulu } else { 920*91f16700Schasinglulu pll_base = PMUCRU_BASE + CRU_PLL_CONS(0, 0); 921*91f16700Schasinglulu mode = ddr_data.cru_pmu_mode_save & 0x3; 922*91f16700Schasinglulu } 923*91f16700Schasinglulu 924*91f16700Schasinglulu /* if pll locked before suspend, we should wait atfer resume */ 925*91f16700Schasinglulu if (ddr_data.cru_plls_con_save[pll_id][1] & PLL_LOCK_MSK) 926*91f16700Schasinglulu pm_pll_wait_lock(pll_base, pll_id); 927*91f16700Schasinglulu 928*91f16700Schasinglulu pll_set_mode(pll_id, mode); 929*91f16700Schasinglulu } 930*91f16700Schasinglulu 931*91f16700Schasinglulu static void pm_plls_suspend(void) 932*91f16700Schasinglulu { 933*91f16700Schasinglulu ddr_data.cru_mode_save = mmio_read_32(CRU_BASE + CRU_MODE); 934*91f16700Schasinglulu ddr_data.cru_pmu_mode_save = mmio_read_32(PMUCRU_BASE + CRU_PMU_MODE); 935*91f16700Schasinglulu ddr_data.clk_sel0 = mmio_read_32(CRU_BASE + CRU_CLKSELS_CON(0)); 936*91f16700Schasinglulu 937*91f16700Schasinglulu pll_suspend(GPLL_ID); 938*91f16700Schasinglulu pll_suspend(NPLL_ID); 939*91f16700Schasinglulu pll_suspend(CPLL_ID); 940*91f16700Schasinglulu pll_suspend(APLL_ID); 941*91f16700Schasinglulu 942*91f16700Schasinglulu /* core */ 943*91f16700Schasinglulu mmio_write_32(CRU_BASE + CRU_CLKSELS_CON(0), 944*91f16700Schasinglulu BITS_WITH_WMASK(0, 0xf, 0)); 945*91f16700Schasinglulu 946*91f16700Schasinglulu /* pclk_dbg */ 947*91f16700Schasinglulu mmio_write_32(CRU_BASE + CRU_CLKSELS_CON(0), 948*91f16700Schasinglulu BITS_WITH_WMASK(0, 0xf, 8)); 949*91f16700Schasinglulu } 950*91f16700Schasinglulu 951*91f16700Schasinglulu static void pm_plls_resume(void) 952*91f16700Schasinglulu { 953*91f16700Schasinglulu /* pclk_dbg */ 954*91f16700Schasinglulu mmio_write_32(CRU_BASE + CRU_CLKSELS_CON(0), 955*91f16700Schasinglulu ddr_data.clk_sel0 | BITS_WMSK(0xf, 8)); 956*91f16700Schasinglulu 957*91f16700Schasinglulu /* core */ 958*91f16700Schasinglulu mmio_write_32(CRU_BASE + CRU_CLKSELS_CON(0), 959*91f16700Schasinglulu ddr_data.clk_sel0 | BITS_WMSK(0xf, 0)); 960*91f16700Schasinglulu 961*91f16700Schasinglulu pll_resume(APLL_ID); 962*91f16700Schasinglulu pll_resume(CPLL_ID); 963*91f16700Schasinglulu pll_resume(NPLL_ID); 964*91f16700Schasinglulu pll_resume(GPLL_ID); 965*91f16700Schasinglulu } 966*91f16700Schasinglulu 967*91f16700Schasinglulu int rockchip_soc_sys_pwr_dm_suspend(void) 968*91f16700Schasinglulu { 969*91f16700Schasinglulu pmu_power_domains_suspend(); 970*91f16700Schasinglulu 971*91f16700Schasinglulu clk_gate_suspend(); 972*91f16700Schasinglulu 973*91f16700Schasinglulu soc_sleep_config(); 974*91f16700Schasinglulu 975*91f16700Schasinglulu pm_plls_suspend(); 976*91f16700Schasinglulu 977*91f16700Schasinglulu psram_boot_cfg->pm_flag &= ~PM_WARM_BOOT_BIT; 978*91f16700Schasinglulu 979*91f16700Schasinglulu return 0; 980*91f16700Schasinglulu } 981*91f16700Schasinglulu 982*91f16700Schasinglulu int rockchip_soc_sys_pwr_dm_resume(void) 983*91f16700Schasinglulu { 984*91f16700Schasinglulu psram_boot_cfg->pm_flag |= PM_WARM_BOOT_BIT; 985*91f16700Schasinglulu 986*91f16700Schasinglulu pm_plls_resume(); 987*91f16700Schasinglulu 988*91f16700Schasinglulu soc_sleep_restore(); 989*91f16700Schasinglulu 990*91f16700Schasinglulu clk_gate_resume(); 991*91f16700Schasinglulu 992*91f16700Schasinglulu pmu_power_domains_resume(); 993*91f16700Schasinglulu 994*91f16700Schasinglulu plat_rockchip_gic_cpuif_enable(); 995*91f16700Schasinglulu 996*91f16700Schasinglulu return 0; 997*91f16700Schasinglulu } 998*91f16700Schasinglulu 999*91f16700Schasinglulu void __dead2 rockchip_soc_soft_reset(void) 1000*91f16700Schasinglulu { 1001*91f16700Schasinglulu pll_set_mode(GPLL_ID, SLOW_MODE); 1002*91f16700Schasinglulu pll_set_mode(CPLL_ID, SLOW_MODE); 1003*91f16700Schasinglulu pll_set_mode(NPLL_ID, SLOW_MODE); 1004*91f16700Schasinglulu pll_set_mode(APLL_ID, SLOW_MODE); 1005*91f16700Schasinglulu dsb(); 1006*91f16700Schasinglulu 1007*91f16700Schasinglulu mmio_write_32(CRU_BASE + CRU_GLB_SRST_FST, CRU_GLB_SRST_FST_VALUE); 1008*91f16700Schasinglulu dsb(); 1009*91f16700Schasinglulu 1010*91f16700Schasinglulu /* 1011*91f16700Schasinglulu * Maybe the HW needs some times to reset the system, 1012*91f16700Schasinglulu * so we do not hope the core to execute valid codes. 1013*91f16700Schasinglulu */ 1014*91f16700Schasinglulu psci_power_down_wfi(); 1015*91f16700Schasinglulu } 1016*91f16700Schasinglulu 1017*91f16700Schasinglulu void __dead2 rockchip_soc_system_off(void) 1018*91f16700Schasinglulu { 1019*91f16700Schasinglulu uint32_t val; 1020*91f16700Schasinglulu 1021*91f16700Schasinglulu /* set pmic_sleep pin(gpio0_a4) to gpio mode */ 1022*91f16700Schasinglulu mmio_write_32(PMUGRF_BASE + GPIO0A_IOMUX, BITS_WITH_WMASK(0, 0x3, 8)); 1023*91f16700Schasinglulu 1024*91f16700Schasinglulu /* config output */ 1025*91f16700Schasinglulu val = mmio_read_32(GPIO0_BASE + SWPORTA_DDR); 1026*91f16700Schasinglulu val |= BIT(4); 1027*91f16700Schasinglulu mmio_write_32(GPIO0_BASE + SWPORTA_DDR, val); 1028*91f16700Schasinglulu 1029*91f16700Schasinglulu /* config output high level */ 1030*91f16700Schasinglulu val = mmio_read_32(GPIO0_BASE); 1031*91f16700Schasinglulu val |= BIT(4); 1032*91f16700Schasinglulu mmio_write_32(GPIO0_BASE, val); 1033*91f16700Schasinglulu dsb(); 1034*91f16700Schasinglulu 1035*91f16700Schasinglulu /* 1036*91f16700Schasinglulu * Maybe the HW needs some times to reset the system, 1037*91f16700Schasinglulu * so we do not hope the core to execute valid codes. 1038*91f16700Schasinglulu */ 1039*91f16700Schasinglulu psci_power_down_wfi(); 1040*91f16700Schasinglulu } 1041*91f16700Schasinglulu 1042*91f16700Schasinglulu void rockchip_plat_mmu_el3(void) 1043*91f16700Schasinglulu { 1044*91f16700Schasinglulu /* TODO: support the el3 for px30 SoCs */ 1045*91f16700Schasinglulu } 1046*91f16700Schasinglulu 1047*91f16700Schasinglulu void plat_rockchip_pmu_init(void) 1048*91f16700Schasinglulu { 1049*91f16700Schasinglulu uint32_t cpu; 1050*91f16700Schasinglulu 1051*91f16700Schasinglulu rockchip_pd_lock_init(); 1052*91f16700Schasinglulu 1053*91f16700Schasinglulu for (cpu = 0; cpu < PLATFORM_CORE_COUNT; cpu++) 1054*91f16700Schasinglulu cpuson_flags[cpu] = 0; 1055*91f16700Schasinglulu 1056*91f16700Schasinglulu psram_boot_cfg->ddr_func = (uint64_t)0; 1057*91f16700Schasinglulu psram_boot_cfg->ddr_data = (uint64_t)0; 1058*91f16700Schasinglulu psram_boot_cfg->sp = PSRAM_SP_TOP; 1059*91f16700Schasinglulu psram_boot_cfg->ddr_flag = 0x0; 1060*91f16700Schasinglulu psram_boot_cfg->boot_mpidr = read_mpidr_el1() & 0xffff; 1061*91f16700Schasinglulu psram_boot_cfg->pm_flag = PM_WARM_BOOT_BIT; 1062*91f16700Schasinglulu 1063*91f16700Schasinglulu nonboot_cpus_off(); 1064*91f16700Schasinglulu 1065*91f16700Schasinglulu /* Remap pmu_sram's base address to boot address */ 1066*91f16700Schasinglulu mmio_write_32(PMUSGRF_BASE + PMUSGRF_SOC_CON(0), 1067*91f16700Schasinglulu BITS_WITH_WMASK(1, 0x1, 13)); 1068*91f16700Schasinglulu 1069*91f16700Schasinglulu INFO("%s: pd status %x\n", 1070*91f16700Schasinglulu __func__, mmio_read_32(PMU_BASE + PMU_PWRDN_ST)); 1071*91f16700Schasinglulu } 1072