1*0d5ec955Stony.xie /* 2*0d5ec955Stony.xie * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved. 3*0d5ec955Stony.xie * 4*0d5ec955Stony.xie * Redistribution and use in source and binary forms, with or without 5*0d5ec955Stony.xie * modification, are permitted provided that the following conditions are met: 6*0d5ec955Stony.xie * 7*0d5ec955Stony.xie * Redistributions of source code must retain the above copyright notice, this 8*0d5ec955Stony.xie * list of conditions and the following disclaimer. 9*0d5ec955Stony.xie * 10*0d5ec955Stony.xie * Redistributions in binary form must reproduce the above copyright notice, 11*0d5ec955Stony.xie * this list of conditions and the following disclaimer in the documentation 12*0d5ec955Stony.xie * and/or other materials provided with the distribution. 13*0d5ec955Stony.xie * 14*0d5ec955Stony.xie * Neither the name of ARM nor the names of its contributors may be used 15*0d5ec955Stony.xie * to endorse or promote products derived from this software without specific 16*0d5ec955Stony.xie * prior written permission. 17*0d5ec955Stony.xie * 18*0d5ec955Stony.xie * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 19*0d5ec955Stony.xie * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 20*0d5ec955Stony.xie * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 21*0d5ec955Stony.xie * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 22*0d5ec955Stony.xie * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 23*0d5ec955Stony.xie * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 24*0d5ec955Stony.xie * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 25*0d5ec955Stony.xie * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 26*0d5ec955Stony.xie * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 27*0d5ec955Stony.xie * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 28*0d5ec955Stony.xie * POSSIBILITY OF SUCH DAMAGE. 29*0d5ec955Stony.xie */ 30*0d5ec955Stony.xie 31*0d5ec955Stony.xie #include <arch_helpers.h> 32*0d5ec955Stony.xie #include <debug.h> 33*0d5ec955Stony.xie #include <assert.h> 34*0d5ec955Stony.xie #include <bakery_lock.h> 35*0d5ec955Stony.xie #include <bl31.h> 36*0d5ec955Stony.xie #include <console.h> 37*0d5ec955Stony.xie #include <delay_timer.h> 38*0d5ec955Stony.xie #include <errno.h> 39*0d5ec955Stony.xie #include <mmio.h> 40*0d5ec955Stony.xie #include <platform.h> 41*0d5ec955Stony.xie #include <platform_def.h> 42*0d5ec955Stony.xie #include <plat_private.h> 43*0d5ec955Stony.xie #include <pmu_sram.h> 44*0d5ec955Stony.xie #include <pmu.h> 45*0d5ec955Stony.xie #include <rk3328_def.h> 46*0d5ec955Stony.xie #include <pmu_com.h> 47*0d5ec955Stony.xie 48*0d5ec955Stony.xie DEFINE_BAKERY_LOCK(rockchip_pd_lock); 49*0d5ec955Stony.xie 50*0d5ec955Stony.xie static struct psram_data_t *psram_sleep_cfg = 51*0d5ec955Stony.xie (struct psram_data_t *)PSRAM_DT_BASE; 52*0d5ec955Stony.xie 53*0d5ec955Stony.xie static struct rk3328_sleep_ddr_data ddr_data; 54*0d5ec955Stony.xie static __sramdata struct rk3328_sleep_sram_data sram_data; 55*0d5ec955Stony.xie 56*0d5ec955Stony.xie static uint32_t cpu_warm_boot_addr; 57*0d5ec955Stony.xie 58*0d5ec955Stony.xie #pragma weak rk3328_pmic_suspend 59*0d5ec955Stony.xie #pragma weak rk3328_pmic_resume 60*0d5ec955Stony.xie 61*0d5ec955Stony.xie void plat_rockchip_pmusram_prepare(void) 62*0d5ec955Stony.xie { 63*0d5ec955Stony.xie uint32_t *sram_dst, *sram_src; 64*0d5ec955Stony.xie size_t sram_size = 2; 65*0d5ec955Stony.xie /* 66*0d5ec955Stony.xie * pmu sram code and data prepare 67*0d5ec955Stony.xie */ 68*0d5ec955Stony.xie sram_dst = (uint32_t *)PMUSRAM_BASE; 69*0d5ec955Stony.xie sram_src = (uint32_t *)&pmu_cpuson_entrypoint_start; 70*0d5ec955Stony.xie sram_size = (uint32_t *)&pmu_cpuson_entrypoint_end - 71*0d5ec955Stony.xie (uint32_t *)sram_src; 72*0d5ec955Stony.xie u32_align_cpy(sram_dst, sram_src, sram_size); 73*0d5ec955Stony.xie 74*0d5ec955Stony.xie psram_sleep_cfg->sp = PSRAM_DT_BASE; 75*0d5ec955Stony.xie } 76*0d5ec955Stony.xie 77*0d5ec955Stony.xie static inline uint32_t get_cpus_pwr_domain_cfg_info(uint32_t cpu_id) 78*0d5ec955Stony.xie { 79*0d5ec955Stony.xie uint32_t pd_reg, apm_reg; 80*0d5ec955Stony.xie 81*0d5ec955Stony.xie pd_reg = mmio_read_32(PMU_BASE + PMU_PWRDN_CON) & BIT(cpu_id); 82*0d5ec955Stony.xie apm_reg = mmio_read_32(PMU_BASE + PMU_CPUAPM_CON(cpu_id)) & 83*0d5ec955Stony.xie BIT(core_pm_en); 84*0d5ec955Stony.xie 85*0d5ec955Stony.xie if (pd_reg && !apm_reg) 86*0d5ec955Stony.xie return core_pwr_pd; 87*0d5ec955Stony.xie else if (!pd_reg && apm_reg) 88*0d5ec955Stony.xie return core_pwr_wfi; 89*0d5ec955Stony.xie 90*0d5ec955Stony.xie ERROR("%s: 0x%x, 0x%x\n", __func__, pd_reg, apm_reg); 91*0d5ec955Stony.xie while (1) 92*0d5ec955Stony.xie ; 93*0d5ec955Stony.xie } 94*0d5ec955Stony.xie 95*0d5ec955Stony.xie static int cpus_power_domain_on(uint32_t cpu_id) 96*0d5ec955Stony.xie { 97*0d5ec955Stony.xie uint32_t cpu_pd, cfg_info; 98*0d5ec955Stony.xie 99*0d5ec955Stony.xie cpu_pd = PD_CPU0 + cpu_id; 100*0d5ec955Stony.xie cfg_info = get_cpus_pwr_domain_cfg_info(cpu_id); 101*0d5ec955Stony.xie 102*0d5ec955Stony.xie if (cfg_info == core_pwr_pd) { 103*0d5ec955Stony.xie /* disable apm cfg */ 104*0d5ec955Stony.xie mmio_write_32(PMU_BASE + PMU_CPUAPM_CON(cpu_id), 105*0d5ec955Stony.xie CORES_PM_DISABLE); 106*0d5ec955Stony.xie 107*0d5ec955Stony.xie /* if the cores have be on, power off it firstly */ 108*0d5ec955Stony.xie if (pmu_power_domain_st(cpu_pd) == pmu_pd_on) { 109*0d5ec955Stony.xie mmio_write_32(PMU_BASE + PMU_CPUAPM_CON(cpu_id), 110*0d5ec955Stony.xie CORES_PM_DISABLE); 111*0d5ec955Stony.xie pmu_power_domain_ctr(cpu_pd, pmu_pd_off); 112*0d5ec955Stony.xie } 113*0d5ec955Stony.xie pmu_power_domain_ctr(cpu_pd, pmu_pd_on); 114*0d5ec955Stony.xie } else { 115*0d5ec955Stony.xie if (pmu_power_domain_st(cpu_pd) == pmu_pd_on) { 116*0d5ec955Stony.xie WARN("%s: cpu%d is not in off,!\n", __func__, cpu_id); 117*0d5ec955Stony.xie return -EINVAL; 118*0d5ec955Stony.xie } 119*0d5ec955Stony.xie 120*0d5ec955Stony.xie mmio_write_32(PMU_BASE + PMU_CPUAPM_CON(cpu_id), 121*0d5ec955Stony.xie BIT(core_pm_sft_wakeup_en)); 122*0d5ec955Stony.xie } 123*0d5ec955Stony.xie 124*0d5ec955Stony.xie return 0; 125*0d5ec955Stony.xie } 126*0d5ec955Stony.xie 127*0d5ec955Stony.xie static int cpus_power_domain_off(uint32_t cpu_id, uint32_t pd_cfg) 128*0d5ec955Stony.xie { 129*0d5ec955Stony.xie uint32_t cpu_pd, core_pm_value; 130*0d5ec955Stony.xie 131*0d5ec955Stony.xie cpu_pd = PD_CPU0 + cpu_id; 132*0d5ec955Stony.xie if (pmu_power_domain_st(cpu_pd) == pmu_pd_off) 133*0d5ec955Stony.xie return 0; 134*0d5ec955Stony.xie 135*0d5ec955Stony.xie if (pd_cfg == core_pwr_pd) { 136*0d5ec955Stony.xie if (check_cpu_wfie(cpu_id, CKECK_WFEI_MSK)) 137*0d5ec955Stony.xie return -EINVAL; 138*0d5ec955Stony.xie /* disable apm cfg */ 139*0d5ec955Stony.xie mmio_write_32(PMU_BASE + PMU_CPUAPM_CON(cpu_id), 140*0d5ec955Stony.xie CORES_PM_DISABLE); 141*0d5ec955Stony.xie pmu_power_domain_ctr(cpu_pd, pmu_pd_off); 142*0d5ec955Stony.xie } else { 143*0d5ec955Stony.xie core_pm_value = BIT(core_pm_en) | BIT(core_pm_dis_int); 144*0d5ec955Stony.xie if (pd_cfg == core_pwr_wfi_int) 145*0d5ec955Stony.xie core_pm_value |= BIT(core_pm_int_wakeup_en); 146*0d5ec955Stony.xie 147*0d5ec955Stony.xie mmio_write_32(PMU_BASE + PMU_CPUAPM_CON(cpu_id), 148*0d5ec955Stony.xie core_pm_value); 149*0d5ec955Stony.xie } 150*0d5ec955Stony.xie 151*0d5ec955Stony.xie return 0; 152*0d5ec955Stony.xie } 153*0d5ec955Stony.xie 154*0d5ec955Stony.xie static void nonboot_cpus_off(void) 155*0d5ec955Stony.xie { 156*0d5ec955Stony.xie uint32_t boot_cpu, cpu; 157*0d5ec955Stony.xie 158*0d5ec955Stony.xie /* turn off noboot cpus */ 159*0d5ec955Stony.xie boot_cpu = plat_my_core_pos(); 160*0d5ec955Stony.xie for (cpu = 0; cpu < PLATFORM_CORE_COUNT; cpu++) { 161*0d5ec955Stony.xie if (cpu == boot_cpu) 162*0d5ec955Stony.xie continue; 163*0d5ec955Stony.xie cpus_power_domain_off(cpu, core_pwr_pd); 164*0d5ec955Stony.xie } 165*0d5ec955Stony.xie } 166*0d5ec955Stony.xie 167*0d5ec955Stony.xie int rockchip_soc_cores_pwr_dm_on(unsigned long mpidr, uint64_t entrypoint) 168*0d5ec955Stony.xie { 169*0d5ec955Stony.xie uint32_t cpu_id = plat_core_pos_by_mpidr(mpidr); 170*0d5ec955Stony.xie 171*0d5ec955Stony.xie assert(cpuson_flags[cpu_id] == 0); 172*0d5ec955Stony.xie cpuson_flags[cpu_id] = PMU_CPU_HOTPLUG; 173*0d5ec955Stony.xie cpuson_entry_point[cpu_id] = entrypoint; 174*0d5ec955Stony.xie dsb(); 175*0d5ec955Stony.xie 176*0d5ec955Stony.xie cpus_power_domain_on(cpu_id); 177*0d5ec955Stony.xie 178*0d5ec955Stony.xie return 0; 179*0d5ec955Stony.xie } 180*0d5ec955Stony.xie 181*0d5ec955Stony.xie int rockchip_soc_cores_pwr_dm_off(void) 182*0d5ec955Stony.xie { 183*0d5ec955Stony.xie uint32_t cpu_id = plat_my_core_pos(); 184*0d5ec955Stony.xie 185*0d5ec955Stony.xie cpus_power_domain_off(cpu_id, core_pwr_wfi); 186*0d5ec955Stony.xie 187*0d5ec955Stony.xie return 0; 188*0d5ec955Stony.xie } 189*0d5ec955Stony.xie 190*0d5ec955Stony.xie int rockchip_soc_cores_pwr_dm_suspend(void) 191*0d5ec955Stony.xie { 192*0d5ec955Stony.xie uint32_t cpu_id = plat_my_core_pos(); 193*0d5ec955Stony.xie 194*0d5ec955Stony.xie assert(cpuson_flags[cpu_id] == 0); 195*0d5ec955Stony.xie cpuson_flags[cpu_id] = PMU_CPU_AUTO_PWRDN; 196*0d5ec955Stony.xie cpuson_entry_point[cpu_id] = (uintptr_t)plat_get_sec_entrypoint(); 197*0d5ec955Stony.xie dsb(); 198*0d5ec955Stony.xie 199*0d5ec955Stony.xie cpus_power_domain_off(cpu_id, core_pwr_wfi_int); 200*0d5ec955Stony.xie 201*0d5ec955Stony.xie return 0; 202*0d5ec955Stony.xie } 203*0d5ec955Stony.xie 204*0d5ec955Stony.xie int rockchip_soc_cores_pwr_dm_on_finish(void) 205*0d5ec955Stony.xie { 206*0d5ec955Stony.xie uint32_t cpu_id = plat_my_core_pos(); 207*0d5ec955Stony.xie 208*0d5ec955Stony.xie mmio_write_32(PMU_BASE + PMU_CPUAPM_CON(cpu_id), CORES_PM_DISABLE); 209*0d5ec955Stony.xie 210*0d5ec955Stony.xie return 0; 211*0d5ec955Stony.xie } 212*0d5ec955Stony.xie 213*0d5ec955Stony.xie int rockchip_soc_cores_pwr_dm_resume(void) 214*0d5ec955Stony.xie { 215*0d5ec955Stony.xie uint32_t cpu_id = plat_my_core_pos(); 216*0d5ec955Stony.xie 217*0d5ec955Stony.xie mmio_write_32(PMU_BASE + PMU_CPUAPM_CON(cpu_id), CORES_PM_DISABLE); 218*0d5ec955Stony.xie 219*0d5ec955Stony.xie return 0; 220*0d5ec955Stony.xie } 221*0d5ec955Stony.xie 222*0d5ec955Stony.xie void __dead2 rockchip_soc_soft_reset(void) 223*0d5ec955Stony.xie { 224*0d5ec955Stony.xie mmio_write_32(CRU_BASE + CRU_CRU_MODE, PLL_SLOW_MODE(CPLL_ID)); 225*0d5ec955Stony.xie mmio_write_32(CRU_BASE + CRU_CRU_MODE, PLL_SLOW_MODE(GPLL_ID)); 226*0d5ec955Stony.xie mmio_write_32(CRU_BASE + CRU_CRU_MODE, PLL_SLOW_MODE(NPLL_ID)); 227*0d5ec955Stony.xie mmio_write_32(CRU_BASE + CRU_CRU_MODE, PLL_SLOW_MODE(APLL_ID)); 228*0d5ec955Stony.xie dsb(); 229*0d5ec955Stony.xie 230*0d5ec955Stony.xie mmio_write_32(CRU_BASE + CRU_GLB_SRST_FST, CRU_GLB_SRST_FST_VALUE); 231*0d5ec955Stony.xie dsb(); 232*0d5ec955Stony.xie /* 233*0d5ec955Stony.xie * Maybe the HW needs some times to reset the system, 234*0d5ec955Stony.xie * so we do not hope the core to excute valid codes. 235*0d5ec955Stony.xie */ 236*0d5ec955Stony.xie while (1) 237*0d5ec955Stony.xie ; 238*0d5ec955Stony.xie } 239*0d5ec955Stony.xie 240*0d5ec955Stony.xie /* 241*0d5ec955Stony.xie * For PMIC RK805, its sleep pin is connect with gpio2_d2 from rk3328. 242*0d5ec955Stony.xie * If the PMIC is configed for responding the sleep pin to power off it, 243*0d5ec955Stony.xie * once the pin is output high, it will get the pmic power off. 244*0d5ec955Stony.xie */ 245*0d5ec955Stony.xie void __dead2 rockchip_soc_system_off(void) 246*0d5ec955Stony.xie { 247*0d5ec955Stony.xie uint32_t val; 248*0d5ec955Stony.xie 249*0d5ec955Stony.xie /* gpio config */ 250*0d5ec955Stony.xie val = mmio_read_32(GRF_BASE + GRF_GPIO2D_IOMUX); 251*0d5ec955Stony.xie val &= ~GPIO2_D2_GPIO_MODE; 252*0d5ec955Stony.xie mmio_write_32(GRF_BASE + GRF_GPIO2D_IOMUX, val); 253*0d5ec955Stony.xie 254*0d5ec955Stony.xie /* config output */ 255*0d5ec955Stony.xie val = mmio_read_32(GPIO2_BASE + SWPORTA_DDR); 256*0d5ec955Stony.xie val |= GPIO2_D2; 257*0d5ec955Stony.xie mmio_write_32(GPIO2_BASE + SWPORTA_DDR, val); 258*0d5ec955Stony.xie 259*0d5ec955Stony.xie /* config output high level */ 260*0d5ec955Stony.xie val = mmio_read_32(GPIO2_BASE); 261*0d5ec955Stony.xie val |= GPIO2_D2; 262*0d5ec955Stony.xie mmio_write_32(GPIO2_BASE, val); 263*0d5ec955Stony.xie dsb(); 264*0d5ec955Stony.xie 265*0d5ec955Stony.xie while (1) 266*0d5ec955Stony.xie ; 267*0d5ec955Stony.xie } 268*0d5ec955Stony.xie 269*0d5ec955Stony.xie static uint32_t clk_ungt_msk[CRU_CLKGATE_NUMS] = { 270*0d5ec955Stony.xie 0x187f, 0x0000, 0x010c, 0x0000, 0x0200, 271*0d5ec955Stony.xie 0x0010, 0x0000, 0x0017, 0x001f, 0x0000, 272*0d5ec955Stony.xie 0x0000, 0x0000, 0x0000, 0x0003, 0x0000, 273*0d5ec955Stony.xie 0xf001, 0x27c0, 0x04D9, 0x03ff, 0x0000, 274*0d5ec955Stony.xie 0x0000, 0x0000, 0x0010, 0x0000, 0x0000, 275*0d5ec955Stony.xie 0x0000, 0x0000, 0x0003, 0x0008 276*0d5ec955Stony.xie }; 277*0d5ec955Stony.xie 278*0d5ec955Stony.xie static void clks_gating_suspend(uint32_t *ungt_msk) 279*0d5ec955Stony.xie { 280*0d5ec955Stony.xie int i; 281*0d5ec955Stony.xie 282*0d5ec955Stony.xie for (i = 0; i < CRU_CLKGATE_NUMS; i++) { 283*0d5ec955Stony.xie ddr_data.clk_ungt_save[i] = 284*0d5ec955Stony.xie mmio_read_32(CRU_BASE + CRU_CLKGATE_CON(i)); 285*0d5ec955Stony.xie mmio_write_32(CRU_BASE + CRU_CLKGATE_CON(i), 286*0d5ec955Stony.xie ((~ungt_msk[i]) << 16) | 0xffff); 287*0d5ec955Stony.xie } 288*0d5ec955Stony.xie } 289*0d5ec955Stony.xie 290*0d5ec955Stony.xie static void clks_gating_resume(void) 291*0d5ec955Stony.xie { 292*0d5ec955Stony.xie int i; 293*0d5ec955Stony.xie 294*0d5ec955Stony.xie for (i = 0; i < CRU_CLKGATE_NUMS; i++) 295*0d5ec955Stony.xie mmio_write_32(CRU_BASE + CRU_CLKGATE_CON(i), 296*0d5ec955Stony.xie ddr_data.clk_ungt_save[i] | 0xffff0000); 297*0d5ec955Stony.xie } 298*0d5ec955Stony.xie 299*0d5ec955Stony.xie static inline void pm_pll_wait_lock(uint32_t pll_id) 300*0d5ec955Stony.xie { 301*0d5ec955Stony.xie uint32_t delay = PLL_LOCKED_TIMEOUT; 302*0d5ec955Stony.xie 303*0d5ec955Stony.xie while (delay > 0) { 304*0d5ec955Stony.xie if (mmio_read_32(CRU_BASE + PLL_CONS(pll_id, 1)) & 305*0d5ec955Stony.xie PLL_IS_LOCKED) 306*0d5ec955Stony.xie break; 307*0d5ec955Stony.xie delay--; 308*0d5ec955Stony.xie } 309*0d5ec955Stony.xie if (delay == 0) 310*0d5ec955Stony.xie ERROR("lock-pll: %d\n", pll_id); 311*0d5ec955Stony.xie } 312*0d5ec955Stony.xie 313*0d5ec955Stony.xie static inline void pll_pwr_dwn(uint32_t pll_id, uint32_t pd) 314*0d5ec955Stony.xie { 315*0d5ec955Stony.xie mmio_write_32(CRU_BASE + PLL_CONS(pll_id, 1), 316*0d5ec955Stony.xie BITS_WITH_WMASK(1, 1, 15)); 317*0d5ec955Stony.xie if (pd) 318*0d5ec955Stony.xie mmio_write_32(CRU_BASE + PLL_CONS(pll_id, 1), 319*0d5ec955Stony.xie BITS_WITH_WMASK(1, 1, 14)); 320*0d5ec955Stony.xie else 321*0d5ec955Stony.xie mmio_write_32(CRU_BASE + PLL_CONS(pll_id, 1), 322*0d5ec955Stony.xie BITS_WITH_WMASK(0, 1, 14)); 323*0d5ec955Stony.xie } 324*0d5ec955Stony.xie 325*0d5ec955Stony.xie static __sramfunc void dpll_suspend(void) 326*0d5ec955Stony.xie { 327*0d5ec955Stony.xie int i; 328*0d5ec955Stony.xie 329*0d5ec955Stony.xie /* slow mode */ 330*0d5ec955Stony.xie mmio_write_32(CRU_BASE + CRU_CRU_MODE, PLL_SLOW_MODE(DPLL_ID)); 331*0d5ec955Stony.xie 332*0d5ec955Stony.xie /* save pll con */ 333*0d5ec955Stony.xie for (i = 0; i < CRU_PLL_CON_NUMS; i++) 334*0d5ec955Stony.xie sram_data.dpll_con_save[i] = 335*0d5ec955Stony.xie mmio_read_32(CRU_BASE + PLL_CONS(DPLL_ID, i)); 336*0d5ec955Stony.xie mmio_write_32(CRU_BASE + PLL_CONS(DPLL_ID, 1), 337*0d5ec955Stony.xie BITS_WITH_WMASK(1, 1, 15)); 338*0d5ec955Stony.xie mmio_write_32(CRU_BASE + PLL_CONS(DPLL_ID, 1), 339*0d5ec955Stony.xie BITS_WITH_WMASK(1, 1, 14)); 340*0d5ec955Stony.xie } 341*0d5ec955Stony.xie 342*0d5ec955Stony.xie static __sramfunc void dpll_resume(void) 343*0d5ec955Stony.xie { 344*0d5ec955Stony.xie uint32_t delay = PLL_LOCKED_TIMEOUT; 345*0d5ec955Stony.xie 346*0d5ec955Stony.xie mmio_write_32(CRU_BASE + PLL_CONS(DPLL_ID, 1), 347*0d5ec955Stony.xie BITS_WITH_WMASK(1, 1, 15)); 348*0d5ec955Stony.xie mmio_write_32(CRU_BASE + PLL_CONS(DPLL_ID, 1), 349*0d5ec955Stony.xie BITS_WITH_WMASK(0, 1, 14)); 350*0d5ec955Stony.xie mmio_write_32(CRU_BASE + PLL_CONS(DPLL_ID, 1), 351*0d5ec955Stony.xie sram_data.dpll_con_save[1] | 0xc0000000); 352*0d5ec955Stony.xie 353*0d5ec955Stony.xie dsb(); 354*0d5ec955Stony.xie 355*0d5ec955Stony.xie while (delay > 0) { 356*0d5ec955Stony.xie if (mmio_read_32(CRU_BASE + PLL_CONS(DPLL_ID, 1)) & 357*0d5ec955Stony.xie PLL_IS_LOCKED) 358*0d5ec955Stony.xie break; 359*0d5ec955Stony.xie delay--; 360*0d5ec955Stony.xie } 361*0d5ec955Stony.xie if (delay == 0) 362*0d5ec955Stony.xie while (1) 363*0d5ec955Stony.xie ; 364*0d5ec955Stony.xie 365*0d5ec955Stony.xie mmio_write_32(CRU_BASE + CRU_CRU_MODE, 366*0d5ec955Stony.xie PLL_NORM_MODE(DPLL_ID)); 367*0d5ec955Stony.xie } 368*0d5ec955Stony.xie 369*0d5ec955Stony.xie static inline void pll_suspend(uint32_t pll_id) 370*0d5ec955Stony.xie { 371*0d5ec955Stony.xie int i; 372*0d5ec955Stony.xie 373*0d5ec955Stony.xie /* slow mode */ 374*0d5ec955Stony.xie mmio_write_32(CRU_BASE + CRU_CRU_MODE, PLL_SLOW_MODE(pll_id)); 375*0d5ec955Stony.xie 376*0d5ec955Stony.xie /* save pll con */ 377*0d5ec955Stony.xie for (i = 0; i < CRU_PLL_CON_NUMS; i++) 378*0d5ec955Stony.xie ddr_data.cru_plls_con_save[pll_id][i] = 379*0d5ec955Stony.xie mmio_read_32(CRU_BASE + PLL_CONS(pll_id, i)); 380*0d5ec955Stony.xie 381*0d5ec955Stony.xie /* powerdown pll */ 382*0d5ec955Stony.xie pll_pwr_dwn(pll_id, pmu_pd_off); 383*0d5ec955Stony.xie } 384*0d5ec955Stony.xie 385*0d5ec955Stony.xie static inline void pll_resume(uint32_t pll_id) 386*0d5ec955Stony.xie { 387*0d5ec955Stony.xie mmio_write_32(CRU_BASE + PLL_CONS(pll_id, 1), 388*0d5ec955Stony.xie ddr_data.cru_plls_con_save[pll_id][1] | 0xc0000000); 389*0d5ec955Stony.xie 390*0d5ec955Stony.xie pm_pll_wait_lock(pll_id); 391*0d5ec955Stony.xie 392*0d5ec955Stony.xie if (PLL_IS_NORM_MODE(ddr_data.cru_mode_save, pll_id)) 393*0d5ec955Stony.xie mmio_write_32(CRU_BASE + CRU_CRU_MODE, 394*0d5ec955Stony.xie PLL_NORM_MODE(pll_id)); 395*0d5ec955Stony.xie } 396*0d5ec955Stony.xie 397*0d5ec955Stony.xie static void pm_plls_suspend(void) 398*0d5ec955Stony.xie { 399*0d5ec955Stony.xie ddr_data.cru_mode_save = mmio_read_32(CRU_BASE + CRU_CRU_MODE); 400*0d5ec955Stony.xie ddr_data.clk_sel0 = mmio_read_32(CRU_BASE + CRU_CLKSEL_CON(0)); 401*0d5ec955Stony.xie ddr_data.clk_sel1 = mmio_read_32(CRU_BASE + CRU_CLKSEL_CON(1)); 402*0d5ec955Stony.xie ddr_data.clk_sel18 = mmio_read_32(CRU_BASE + CRU_CLKSEL_CON(18)); 403*0d5ec955Stony.xie ddr_data.clk_sel20 = mmio_read_32(CRU_BASE + CRU_CLKSEL_CON(20)); 404*0d5ec955Stony.xie ddr_data.clk_sel24 = mmio_read_32(CRU_BASE + CRU_CLKSEL_CON(24)); 405*0d5ec955Stony.xie ddr_data.clk_sel38 = mmio_read_32(CRU_BASE + CRU_CLKSEL_CON(38)); 406*0d5ec955Stony.xie pll_suspend(NPLL_ID); 407*0d5ec955Stony.xie pll_suspend(CPLL_ID); 408*0d5ec955Stony.xie pll_suspend(GPLL_ID); 409*0d5ec955Stony.xie pll_suspend(APLL_ID); 410*0d5ec955Stony.xie 411*0d5ec955Stony.xie /* core */ 412*0d5ec955Stony.xie mmio_write_32(CRU_BASE + CRU_CLKSEL_CON(0), 413*0d5ec955Stony.xie BITS_WITH_WMASK(0, 0x1f, 0)); 414*0d5ec955Stony.xie 415*0d5ec955Stony.xie /* pclk_dbg */ 416*0d5ec955Stony.xie mmio_write_32(CRU_BASE + CRU_CLKSEL_CON(1), 417*0d5ec955Stony.xie BITS_WITH_WMASK(0, 0xf, 0)); 418*0d5ec955Stony.xie 419*0d5ec955Stony.xie /* crypto */ 420*0d5ec955Stony.xie mmio_write_32(CRU_BASE + CRU_CLKSEL_CON(20), 421*0d5ec955Stony.xie BITS_WITH_WMASK(0, 0x1f, 0)); 422*0d5ec955Stony.xie 423*0d5ec955Stony.xie /* pwm0 */ 424*0d5ec955Stony.xie mmio_write_32(CRU_BASE + CRU_CLKSEL_CON(24), 425*0d5ec955Stony.xie BITS_WITH_WMASK(0, 0x7f, 8)); 426*0d5ec955Stony.xie 427*0d5ec955Stony.xie /* uart2 from 24M */ 428*0d5ec955Stony.xie mmio_write_32(CRU_BASE + CRU_CLKSEL_CON(18), 429*0d5ec955Stony.xie BITS_WITH_WMASK(2, 0x3, 8)); 430*0d5ec955Stony.xie 431*0d5ec955Stony.xie /* clk_rtc32k */ 432*0d5ec955Stony.xie mmio_write_32(CRU_BASE + CRU_CLKSEL_CON(38), 433*0d5ec955Stony.xie BITS_WITH_WMASK(767, 0x3fff, 0) | 434*0d5ec955Stony.xie BITS_WITH_WMASK(2, 0x3, 14)); 435*0d5ec955Stony.xie } 436*0d5ec955Stony.xie 437*0d5ec955Stony.xie static void pm_plls_resume(void) 438*0d5ec955Stony.xie { 439*0d5ec955Stony.xie /* clk_rtc32k */ 440*0d5ec955Stony.xie mmio_write_32(CRU_BASE + CRU_CLKSEL_CON(38), 441*0d5ec955Stony.xie ddr_data.clk_sel38 | 442*0d5ec955Stony.xie BITS_WMSK(0x3fff, 0) | 443*0d5ec955Stony.xie BITS_WMSK(0x3, 14)); 444*0d5ec955Stony.xie 445*0d5ec955Stony.xie /* uart2 */ 446*0d5ec955Stony.xie mmio_write_32(CRU_BASE + CRU_CLKSEL_CON(18), 447*0d5ec955Stony.xie ddr_data.clk_sel18 | BITS_WMSK(0x3, 8)); 448*0d5ec955Stony.xie 449*0d5ec955Stony.xie /* pwm0 */ 450*0d5ec955Stony.xie mmio_write_32(CRU_BASE + CRU_CLKSEL_CON(24), 451*0d5ec955Stony.xie ddr_data.clk_sel24 | BITS_WMSK(0x7f, 8)); 452*0d5ec955Stony.xie 453*0d5ec955Stony.xie /* crypto */ 454*0d5ec955Stony.xie mmio_write_32(CRU_BASE + CRU_CLKSEL_CON(20), 455*0d5ec955Stony.xie ddr_data.clk_sel20 | BITS_WMSK(0x1f, 0)); 456*0d5ec955Stony.xie 457*0d5ec955Stony.xie /* pclk_dbg */ 458*0d5ec955Stony.xie mmio_write_32(CRU_BASE + CRU_CLKSEL_CON(1), 459*0d5ec955Stony.xie ddr_data.clk_sel1 | BITS_WMSK(0xf, 0)); 460*0d5ec955Stony.xie 461*0d5ec955Stony.xie /* core */ 462*0d5ec955Stony.xie mmio_write_32(CRU_BASE + CRU_CLKSEL_CON(0), 463*0d5ec955Stony.xie ddr_data.clk_sel0 | BITS_WMSK(0x1f, 0)); 464*0d5ec955Stony.xie 465*0d5ec955Stony.xie pll_pwr_dwn(APLL_ID, pmu_pd_on); 466*0d5ec955Stony.xie pll_pwr_dwn(GPLL_ID, pmu_pd_on); 467*0d5ec955Stony.xie pll_pwr_dwn(CPLL_ID, pmu_pd_on); 468*0d5ec955Stony.xie pll_pwr_dwn(NPLL_ID, pmu_pd_on); 469*0d5ec955Stony.xie 470*0d5ec955Stony.xie pll_resume(APLL_ID); 471*0d5ec955Stony.xie pll_resume(GPLL_ID); 472*0d5ec955Stony.xie pll_resume(CPLL_ID); 473*0d5ec955Stony.xie pll_resume(NPLL_ID); 474*0d5ec955Stony.xie } 475*0d5ec955Stony.xie 476*0d5ec955Stony.xie #define ARCH_TIMER_TICKS_PER_US (SYS_COUNTER_FREQ_IN_TICKS / 1000000) 477*0d5ec955Stony.xie 478*0d5ec955Stony.xie static __sramfunc void sram_udelay(uint32_t us) 479*0d5ec955Stony.xie { 480*0d5ec955Stony.xie uint64_t pct_orig, pct_now; 481*0d5ec955Stony.xie uint64_t to_wait = ARCH_TIMER_TICKS_PER_US * us; 482*0d5ec955Stony.xie 483*0d5ec955Stony.xie isb(); 484*0d5ec955Stony.xie pct_orig = read_cntpct_el0(); 485*0d5ec955Stony.xie 486*0d5ec955Stony.xie do { 487*0d5ec955Stony.xie isb(); 488*0d5ec955Stony.xie pct_now = read_cntpct_el0(); 489*0d5ec955Stony.xie } while ((pct_now - pct_orig) <= to_wait); 490*0d5ec955Stony.xie } 491*0d5ec955Stony.xie 492*0d5ec955Stony.xie /* 493*0d5ec955Stony.xie * For PMIC RK805, its sleep pin is connect with gpio2_d2 from rk3328. 494*0d5ec955Stony.xie * If the PMIC is configed for responding the sleep pin 495*0d5ec955Stony.xie * to get it into sleep mode, 496*0d5ec955Stony.xie * once the pin is output high, it will get the pmic into sleep mode. 497*0d5ec955Stony.xie */ 498*0d5ec955Stony.xie __sramfunc void rk3328_pmic_suspend(void) 499*0d5ec955Stony.xie { 500*0d5ec955Stony.xie sram_data.pmic_sleep_save = mmio_read_32(GRF_BASE + PMIC_SLEEP_REG); 501*0d5ec955Stony.xie sram_data.pmic_sleep_gpio_save[1] = mmio_read_32(GPIO2_BASE + 4); 502*0d5ec955Stony.xie sram_data.pmic_sleep_gpio_save[0] = mmio_read_32(GPIO2_BASE); 503*0d5ec955Stony.xie mmio_write_32(GRF_BASE + PMIC_SLEEP_REG, BITS_WITH_WMASK(0, 0x3, 4)); 504*0d5ec955Stony.xie mmio_write_32(GPIO2_BASE + 4, 505*0d5ec955Stony.xie sram_data.pmic_sleep_gpio_save[1] | BIT(26)); 506*0d5ec955Stony.xie mmio_write_32(GPIO2_BASE, 507*0d5ec955Stony.xie sram_data.pmic_sleep_gpio_save[0] | BIT(26)); 508*0d5ec955Stony.xie } 509*0d5ec955Stony.xie 510*0d5ec955Stony.xie __sramfunc void rk3328_pmic_resume(void) 511*0d5ec955Stony.xie { 512*0d5ec955Stony.xie mmio_write_32(GPIO2_BASE, sram_data.pmic_sleep_gpio_save[0]); 513*0d5ec955Stony.xie mmio_write_32(GPIO2_BASE + 4, sram_data.pmic_sleep_gpio_save[1]); 514*0d5ec955Stony.xie mmio_write_32(GRF_BASE + PMIC_SLEEP_REG, 515*0d5ec955Stony.xie sram_data.pmic_sleep_save | BITS_WMSK(0xffff, 0)); 516*0d5ec955Stony.xie /* Resuming volt need a lot of time */ 517*0d5ec955Stony.xie sram_udelay(100); 518*0d5ec955Stony.xie } 519*0d5ec955Stony.xie 520*0d5ec955Stony.xie static inline void rockchip_set_sram_sp(uint64_t set_sp) 521*0d5ec955Stony.xie { 522*0d5ec955Stony.xie __asm volatile("mov sp, %0\n"::"r" (set_sp) : "sp"); 523*0d5ec955Stony.xie } 524*0d5ec955Stony.xie 525*0d5ec955Stony.xie static __sramfunc void ddr_suspend(void) 526*0d5ec955Stony.xie { 527*0d5ec955Stony.xie sram_data.pd_sr_idle_save = mmio_read_32(DDR_UPCTL_BASE + 528*0d5ec955Stony.xie DDR_PCTL2_PWRCTL); 529*0d5ec955Stony.xie sram_data.pd_sr_idle_save &= SELFREF_EN; 530*0d5ec955Stony.xie 531*0d5ec955Stony.xie mmio_clrbits_32(DDR_UPCTL_BASE + DDR_PCTL2_PWRCTL, SELFREF_EN); 532*0d5ec955Stony.xie sram_data.ddr_grf_con0 = mmio_read_32(DDR_GRF_BASE + 533*0d5ec955Stony.xie DDRGRF_SOC_CON(0)); 534*0d5ec955Stony.xie mmio_write_32(DDR_GRF_BASE, BIT_WITH_WMSK(14) | WMSK_BIT(15)); 535*0d5ec955Stony.xie 536*0d5ec955Stony.xie /* 537*0d5ec955Stony.xie * Override csysreq from ddrc and 538*0d5ec955Stony.xie * send valid csysreq signal to PMU, 539*0d5ec955Stony.xie * csysreq is controlled by ddrc only 540*0d5ec955Stony.xie */ 541*0d5ec955Stony.xie 542*0d5ec955Stony.xie /* in self-refresh */ 543*0d5ec955Stony.xie mmio_setbits_32(PMU_BASE + PMU_SFT_CON, BIT(0)); 544*0d5ec955Stony.xie while ((mmio_read_32(DDR_GRF_BASE + DDRGRF_SOC_STATUS(1)) & 545*0d5ec955Stony.xie (0x03 << 12)) != (0x02 << 12)) 546*0d5ec955Stony.xie ; 547*0d5ec955Stony.xie /* ddr retention */ 548*0d5ec955Stony.xie mmio_setbits_32(PMU_BASE + PMU_SFT_CON, BIT(2)); 549*0d5ec955Stony.xie 550*0d5ec955Stony.xie /* ddr gating */ 551*0d5ec955Stony.xie mmio_write_32(CRU_BASE + CRU_CLKGATE_CON(0), 552*0d5ec955Stony.xie BITS_WITH_WMASK(0x7, 0x7, 4)); 553*0d5ec955Stony.xie mmio_write_32(CRU_BASE + CRU_CLKGATE_CON(7), 554*0d5ec955Stony.xie BITS_WITH_WMASK(1, 1, 4)); 555*0d5ec955Stony.xie mmio_write_32(CRU_BASE + CRU_CLKGATE_CON(18), 556*0d5ec955Stony.xie BITS_WITH_WMASK(0x1ff, 0x1ff, 1)); 557*0d5ec955Stony.xie mmio_write_32(CRU_BASE + CRU_CLKGATE_CON(27), 558*0d5ec955Stony.xie BITS_WITH_WMASK(0x3, 0x3, 0)); 559*0d5ec955Stony.xie 560*0d5ec955Stony.xie dpll_suspend(); 561*0d5ec955Stony.xie } 562*0d5ec955Stony.xie 563*0d5ec955Stony.xie static __sramfunc void ddr_resume(void) 564*0d5ec955Stony.xie { 565*0d5ec955Stony.xie dpll_resume(); 566*0d5ec955Stony.xie 567*0d5ec955Stony.xie /* ddr gating */ 568*0d5ec955Stony.xie mmio_write_32(CRU_BASE + CRU_CLKGATE_CON(0), 569*0d5ec955Stony.xie BITS_WITH_WMASK(0, 0x7, 4)); 570*0d5ec955Stony.xie mmio_write_32(CRU_BASE + CRU_CLKGATE_CON(7), 571*0d5ec955Stony.xie BITS_WITH_WMASK(0, 1, 4)); 572*0d5ec955Stony.xie mmio_write_32(CRU_BASE + CRU_CLKGATE_CON(18), 573*0d5ec955Stony.xie BITS_WITH_WMASK(0, 0x1ff, 1)); 574*0d5ec955Stony.xie mmio_write_32(CRU_BASE + CRU_CLKGATE_CON(27), 575*0d5ec955Stony.xie BITS_WITH_WMASK(0, 0x3, 0)); 576*0d5ec955Stony.xie 577*0d5ec955Stony.xie /* ddr de_retention */ 578*0d5ec955Stony.xie mmio_clrbits_32(PMU_BASE + PMU_SFT_CON, BIT(2)); 579*0d5ec955Stony.xie /* exit self-refresh */ 580*0d5ec955Stony.xie mmio_clrbits_32(PMU_BASE + PMU_SFT_CON, BIT(0)); 581*0d5ec955Stony.xie while ((mmio_read_32(DDR_GRF_BASE + DDRGRF_SOC_STATUS(1)) & 582*0d5ec955Stony.xie (0x03 << 12)) != (0x00 << 12)) 583*0d5ec955Stony.xie ; 584*0d5ec955Stony.xie 585*0d5ec955Stony.xie mmio_write_32(DDR_GRF_BASE, sram_data.ddr_grf_con0 | 0xc0000000); 586*0d5ec955Stony.xie if (sram_data.pd_sr_idle_save) 587*0d5ec955Stony.xie mmio_setbits_32(DDR_UPCTL_BASE + DDR_PCTL2_PWRCTL, 588*0d5ec955Stony.xie SELFREF_EN); 589*0d5ec955Stony.xie } 590*0d5ec955Stony.xie 591*0d5ec955Stony.xie static __sramfunc void sram_dbg_uart_suspend(void) 592*0d5ec955Stony.xie { 593*0d5ec955Stony.xie sram_data.uart2_ier = mmio_read_32(UART2_BASE + UART_IER); 594*0d5ec955Stony.xie mmio_write_32(UART2_BASE + UART_IER, UART_INT_DISABLE); 595*0d5ec955Stony.xie mmio_write_32(CRU_BASE + CRU_CLKGATE_CON(16), 0x20002000); 596*0d5ec955Stony.xie mmio_write_32(CRU_BASE + CRU_CLKGATE_CON(2), 0x00040004); 597*0d5ec955Stony.xie } 598*0d5ec955Stony.xie 599*0d5ec955Stony.xie static __sramfunc void sram_dbg_uart_resume(void) 600*0d5ec955Stony.xie { 601*0d5ec955Stony.xie /* restore uart clk and reset fifo */ 602*0d5ec955Stony.xie mmio_write_32(CRU_BASE + CRU_CLKGATE_CON(16), 0x20000000); 603*0d5ec955Stony.xie mmio_write_32(CRU_BASE + CRU_CLKGATE_CON(2), 0x00040000); 604*0d5ec955Stony.xie mmio_write_32(UART2_BASE + UART_FCR, UART_FIFO_RESET); 605*0d5ec955Stony.xie mmio_write_32(UART2_BASE + UART_IER, sram_data.uart2_ier); 606*0d5ec955Stony.xie } 607*0d5ec955Stony.xie 608*0d5ec955Stony.xie static __sramfunc void sram_soc_enter_lp(void) 609*0d5ec955Stony.xie { 610*0d5ec955Stony.xie uint32_t apm_value; 611*0d5ec955Stony.xie 612*0d5ec955Stony.xie apm_value = BIT(core_pm_en) | 613*0d5ec955Stony.xie BIT(core_pm_dis_int) | 614*0d5ec955Stony.xie BIT(core_pm_int_wakeup_en); 615*0d5ec955Stony.xie mmio_write_32(PMU_BASE + PMU_CPUAPM_CON(PD_CPU0), apm_value); 616*0d5ec955Stony.xie 617*0d5ec955Stony.xie dsb(); 618*0d5ec955Stony.xie isb(); 619*0d5ec955Stony.xie err_loop: 620*0d5ec955Stony.xie wfi(); 621*0d5ec955Stony.xie /* 622*0d5ec955Stony.xie *Soc will enter low power mode and 623*0d5ec955Stony.xie *do not return to here. 624*0d5ec955Stony.xie */ 625*0d5ec955Stony.xie goto err_loop; 626*0d5ec955Stony.xie } 627*0d5ec955Stony.xie 628*0d5ec955Stony.xie __sramfunc void sram_suspend(void) 629*0d5ec955Stony.xie { 630*0d5ec955Stony.xie /* disable mmu and icache */ 631*0d5ec955Stony.xie tlbialle3(); 632*0d5ec955Stony.xie disable_mmu_icache_el3(); 633*0d5ec955Stony.xie 634*0d5ec955Stony.xie mmio_write_32(SGRF_BASE + SGRF_SOC_CON(1), 635*0d5ec955Stony.xie (PMUSRAM_BASE >> CPU_BOOT_ADDR_ALIGN) | 636*0d5ec955Stony.xie CPU_BOOT_ADDR_WMASK); 637*0d5ec955Stony.xie 638*0d5ec955Stony.xie /* ddr self-refresh and gating phy */ 639*0d5ec955Stony.xie ddr_suspend(); 640*0d5ec955Stony.xie 641*0d5ec955Stony.xie rk3328_pmic_suspend(); 642*0d5ec955Stony.xie 643*0d5ec955Stony.xie sram_dbg_uart_suspend(); 644*0d5ec955Stony.xie 645*0d5ec955Stony.xie sram_soc_enter_lp(); 646*0d5ec955Stony.xie } 647*0d5ec955Stony.xie 648*0d5ec955Stony.xie static __sramfunc void sys_resume_first(void) 649*0d5ec955Stony.xie { 650*0d5ec955Stony.xie sram_dbg_uart_resume(); 651*0d5ec955Stony.xie 652*0d5ec955Stony.xie rk3328_pmic_resume(); 653*0d5ec955Stony.xie 654*0d5ec955Stony.xie /* ddr self-refresh exit */ 655*0d5ec955Stony.xie ddr_resume(); 656*0d5ec955Stony.xie 657*0d5ec955Stony.xie /* disable apm cfg */ 658*0d5ec955Stony.xie mmio_write_32(PMU_BASE + PMU_CPUAPM_CON(0), CORES_PM_DISABLE); 659*0d5ec955Stony.xie 660*0d5ec955Stony.xie /* the warm booting address of cpus */ 661*0d5ec955Stony.xie mmio_write_32(SGRF_BASE + SGRF_SOC_CON(1), 662*0d5ec955Stony.xie (cpu_warm_boot_addr >> CPU_BOOT_ADDR_ALIGN) | 663*0d5ec955Stony.xie CPU_BOOT_ADDR_WMASK); 664*0d5ec955Stony.xie } 665*0d5ec955Stony.xie 666*0d5ec955Stony.xie void __dead2 rockchip_soc_sys_pd_pwr_dn_wfi(void) 667*0d5ec955Stony.xie { 668*0d5ec955Stony.xie rockchip_set_sram_sp(PSRAM_DT_BASE); 669*0d5ec955Stony.xie 670*0d5ec955Stony.xie sram_suspend(); 671*0d5ec955Stony.xie 672*0d5ec955Stony.xie /* should never reach here */ 673*0d5ec955Stony.xie psci_power_down_wfi(); 674*0d5ec955Stony.xie } 675*0d5ec955Stony.xie 676*0d5ec955Stony.xie int rockchip_soc_sys_pwr_dm_suspend(void) 677*0d5ec955Stony.xie { 678*0d5ec955Stony.xie clks_gating_suspend(clk_ungt_msk); 679*0d5ec955Stony.xie 680*0d5ec955Stony.xie pm_plls_suspend(); 681*0d5ec955Stony.xie 682*0d5ec955Stony.xie return 0; 683*0d5ec955Stony.xie } 684*0d5ec955Stony.xie 685*0d5ec955Stony.xie int rockchip_soc_sys_pwr_dm_resume(void) 686*0d5ec955Stony.xie { 687*0d5ec955Stony.xie pm_plls_resume(); 688*0d5ec955Stony.xie 689*0d5ec955Stony.xie clks_gating_resume(); 690*0d5ec955Stony.xie 691*0d5ec955Stony.xie plat_rockchip_gic_cpuif_enable(); 692*0d5ec955Stony.xie 693*0d5ec955Stony.xie return 0; 694*0d5ec955Stony.xie } 695*0d5ec955Stony.xie 696*0d5ec955Stony.xie void plat_rockchip_pmu_init(void) 697*0d5ec955Stony.xie { 698*0d5ec955Stony.xie uint32_t cpu; 699*0d5ec955Stony.xie 700*0d5ec955Stony.xie for (cpu = 0; cpu < PLATFORM_CORE_COUNT; cpu++) 701*0d5ec955Stony.xie cpuson_flags[cpu] = 0; 702*0d5ec955Stony.xie 703*0d5ec955Stony.xie cpu_warm_boot_addr = (uint64_t)platform_cpu_warmboot; 704*0d5ec955Stony.xie psram_sleep_cfg->ddr_func = (uint64_t)sys_resume_first; 705*0d5ec955Stony.xie psram_sleep_cfg->ddr_data = 0x00; 706*0d5ec955Stony.xie psram_sleep_cfg->ddr_flag = 0x01; 707*0d5ec955Stony.xie psram_sleep_cfg->boot_mpidr = read_mpidr_el1() & 0xffff; 708*0d5ec955Stony.xie 709*0d5ec955Stony.xie /* the warm booting address of cpus */ 710*0d5ec955Stony.xie mmio_write_32(SGRF_BASE + SGRF_SOC_CON(1), 711*0d5ec955Stony.xie (cpu_warm_boot_addr >> CPU_BOOT_ADDR_ALIGN) | 712*0d5ec955Stony.xie CPU_BOOT_ADDR_WMASK); 713*0d5ec955Stony.xie 714*0d5ec955Stony.xie nonboot_cpus_off(); 715*0d5ec955Stony.xie 716*0d5ec955Stony.xie INFO("%s: pd status 0x%x\n", 717*0d5ec955Stony.xie __func__, mmio_read_32(PMU_BASE + PMU_PWRDN_ST)); 718*0d5ec955Stony.xie } 719