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