1*780e3f24SHeiko Stuebner /* 2*780e3f24SHeiko Stuebner * Copyright (c) 2016, ARM Limited and Contributors. All rights reserved. 3*780e3f24SHeiko Stuebner * 4*780e3f24SHeiko Stuebner * SPDX-License-Identifier: BSD-3-Clause 5*780e3f24SHeiko Stuebner */ 6*780e3f24SHeiko Stuebner 7*780e3f24SHeiko Stuebner #include <assert.h> 8*780e3f24SHeiko Stuebner #include <errno.h> 9*780e3f24SHeiko Stuebner 10*780e3f24SHeiko Stuebner #include <platform_def.h> 11*780e3f24SHeiko Stuebner 12*780e3f24SHeiko Stuebner #include <arch_helpers.h> 13*780e3f24SHeiko Stuebner #include <common/debug.h> 14*780e3f24SHeiko Stuebner #include <drivers/delay_timer.h> 15*780e3f24SHeiko Stuebner #include <lib/mmio.h> 16*780e3f24SHeiko Stuebner #include <plat/common/platform.h> 17*780e3f24SHeiko Stuebner 18*780e3f24SHeiko Stuebner #include <plat_private.h> 19*780e3f24SHeiko Stuebner #include <pmu.h> 20*780e3f24SHeiko Stuebner #include <pmu_com.h> 21*780e3f24SHeiko Stuebner #include <rk3288_def.h> 22*780e3f24SHeiko Stuebner #include <secure.h> 23*780e3f24SHeiko Stuebner #include <soc.h> 24*780e3f24SHeiko Stuebner 25*780e3f24SHeiko Stuebner DEFINE_BAKERY_LOCK(rockchip_pd_lock); 26*780e3f24SHeiko Stuebner 27*780e3f24SHeiko Stuebner static uint32_t cpu_warm_boot_addr; 28*780e3f24SHeiko Stuebner 29*780e3f24SHeiko Stuebner static uint32_t store_pmu_pwrmode_con; 30*780e3f24SHeiko Stuebner static uint32_t store_sgrf_soc_con0; 31*780e3f24SHeiko Stuebner static uint32_t store_sgrf_cpu_con0; 32*780e3f24SHeiko Stuebner 33*780e3f24SHeiko Stuebner /* These enum are variants of low power mode */ 34*780e3f24SHeiko Stuebner enum { 35*780e3f24SHeiko Stuebner ROCKCHIP_ARM_OFF_LOGIC_NORMAL = 0, 36*780e3f24SHeiko Stuebner ROCKCHIP_ARM_OFF_LOGIC_DEEP = 1, 37*780e3f24SHeiko Stuebner }; 38*780e3f24SHeiko Stuebner 39*780e3f24SHeiko Stuebner static inline int rk3288_pmu_bus_idle(uint32_t req, uint32_t idle) 40*780e3f24SHeiko Stuebner { 41*780e3f24SHeiko Stuebner uint32_t mask = BIT(req); 42*780e3f24SHeiko Stuebner uint32_t idle_mask = 0; 43*780e3f24SHeiko Stuebner uint32_t idle_target = 0; 44*780e3f24SHeiko Stuebner uint32_t val; 45*780e3f24SHeiko Stuebner uint32_t wait_cnt = 0; 46*780e3f24SHeiko Stuebner 47*780e3f24SHeiko Stuebner switch (req) { 48*780e3f24SHeiko Stuebner case bus_ide_req_gpu: 49*780e3f24SHeiko Stuebner idle_mask = BIT(pmu_idle_ack_gpu) | BIT(pmu_idle_gpu); 50*780e3f24SHeiko Stuebner idle_target = (idle << pmu_idle_ack_gpu) | 51*780e3f24SHeiko Stuebner (idle << pmu_idle_gpu); 52*780e3f24SHeiko Stuebner break; 53*780e3f24SHeiko Stuebner case bus_ide_req_core: 54*780e3f24SHeiko Stuebner idle_mask = BIT(pmu_idle_ack_core) | BIT(pmu_idle_core); 55*780e3f24SHeiko Stuebner idle_target = (idle << pmu_idle_ack_core) | 56*780e3f24SHeiko Stuebner (idle << pmu_idle_core); 57*780e3f24SHeiko Stuebner break; 58*780e3f24SHeiko Stuebner case bus_ide_req_cpup: 59*780e3f24SHeiko Stuebner idle_mask = BIT(pmu_idle_ack_cpup) | BIT(pmu_idle_cpup); 60*780e3f24SHeiko Stuebner idle_target = (idle << pmu_idle_ack_cpup) | 61*780e3f24SHeiko Stuebner (idle << pmu_idle_cpup); 62*780e3f24SHeiko Stuebner break; 63*780e3f24SHeiko Stuebner case bus_ide_req_bus: 64*780e3f24SHeiko Stuebner idle_mask = BIT(pmu_idle_ack_bus) | BIT(pmu_idle_bus); 65*780e3f24SHeiko Stuebner idle_target = (idle << pmu_idle_ack_bus) | 66*780e3f24SHeiko Stuebner (idle << pmu_idle_bus); 67*780e3f24SHeiko Stuebner break; 68*780e3f24SHeiko Stuebner case bus_ide_req_dma: 69*780e3f24SHeiko Stuebner idle_mask = BIT(pmu_idle_ack_dma) | BIT(pmu_idle_dma); 70*780e3f24SHeiko Stuebner idle_target = (idle << pmu_idle_ack_dma) | 71*780e3f24SHeiko Stuebner (idle << pmu_idle_dma); 72*780e3f24SHeiko Stuebner break; 73*780e3f24SHeiko Stuebner case bus_ide_req_peri: 74*780e3f24SHeiko Stuebner idle_mask = BIT(pmu_idle_ack_peri) | BIT(pmu_idle_peri); 75*780e3f24SHeiko Stuebner idle_target = (idle << pmu_idle_ack_peri) | 76*780e3f24SHeiko Stuebner (idle << pmu_idle_peri); 77*780e3f24SHeiko Stuebner break; 78*780e3f24SHeiko Stuebner case bus_ide_req_video: 79*780e3f24SHeiko Stuebner idle_mask = BIT(pmu_idle_ack_video) | BIT(pmu_idle_video); 80*780e3f24SHeiko Stuebner idle_target = (idle << pmu_idle_ack_video) | 81*780e3f24SHeiko Stuebner (idle << pmu_idle_video); 82*780e3f24SHeiko Stuebner break; 83*780e3f24SHeiko Stuebner case bus_ide_req_hevc: 84*780e3f24SHeiko Stuebner idle_mask = BIT(pmu_idle_ack_hevc) | BIT(pmu_idle_hevc); 85*780e3f24SHeiko Stuebner idle_target = (idle << pmu_idle_ack_hevc) | 86*780e3f24SHeiko Stuebner (idle << pmu_idle_hevc); 87*780e3f24SHeiko Stuebner break; 88*780e3f24SHeiko Stuebner case bus_ide_req_vio: 89*780e3f24SHeiko Stuebner idle_mask = BIT(pmu_idle_ack_vio) | BIT(pmu_idle_vio); 90*780e3f24SHeiko Stuebner idle_target = (pmu_idle_ack_vio) | 91*780e3f24SHeiko Stuebner (idle << pmu_idle_vio); 92*780e3f24SHeiko Stuebner break; 93*780e3f24SHeiko Stuebner case bus_ide_req_alive: 94*780e3f24SHeiko Stuebner idle_mask = BIT(pmu_idle_ack_alive) | BIT(pmu_idle_alive); 95*780e3f24SHeiko Stuebner idle_target = (idle << pmu_idle_ack_alive) | 96*780e3f24SHeiko Stuebner (idle << pmu_idle_alive); 97*780e3f24SHeiko Stuebner break; 98*780e3f24SHeiko Stuebner default: 99*780e3f24SHeiko Stuebner ERROR("%s: Unsupported the idle request\n", __func__); 100*780e3f24SHeiko Stuebner break; 101*780e3f24SHeiko Stuebner } 102*780e3f24SHeiko Stuebner 103*780e3f24SHeiko Stuebner val = mmio_read_32(PMU_BASE + PMU_BUS_IDE_REQ); 104*780e3f24SHeiko Stuebner if (idle) 105*780e3f24SHeiko Stuebner val |= mask; 106*780e3f24SHeiko Stuebner else 107*780e3f24SHeiko Stuebner val &= ~mask; 108*780e3f24SHeiko Stuebner 109*780e3f24SHeiko Stuebner mmio_write_32(PMU_BASE + PMU_BUS_IDE_REQ, val); 110*780e3f24SHeiko Stuebner 111*780e3f24SHeiko Stuebner while ((mmio_read_32(PMU_BASE + 112*780e3f24SHeiko Stuebner PMU_BUS_IDE_ST) & idle_mask) != idle_target) { 113*780e3f24SHeiko Stuebner wait_cnt++; 114*780e3f24SHeiko Stuebner if (!(wait_cnt % MAX_WAIT_CONUT)) 115*780e3f24SHeiko Stuebner WARN("%s:st=%x(%x)\n", __func__, 116*780e3f24SHeiko Stuebner mmio_read_32(PMU_BASE + PMU_BUS_IDE_ST), 117*780e3f24SHeiko Stuebner idle_mask); 118*780e3f24SHeiko Stuebner } 119*780e3f24SHeiko Stuebner 120*780e3f24SHeiko Stuebner return 0; 121*780e3f24SHeiko Stuebner } 122*780e3f24SHeiko Stuebner 123*780e3f24SHeiko Stuebner static bool rk3288_sleep_disable_osc(void) 124*780e3f24SHeiko Stuebner { 125*780e3f24SHeiko Stuebner static const uint32_t reg_offset[] = { GRF_UOC0_CON0, GRF_UOC1_CON0, 126*780e3f24SHeiko Stuebner GRF_UOC2_CON0 }; 127*780e3f24SHeiko Stuebner uint32_t reg, i; 128*780e3f24SHeiko Stuebner 129*780e3f24SHeiko Stuebner /* 130*780e3f24SHeiko Stuebner * if any usb phy is still on(GRF_SIDDQ==0), that means we need the 131*780e3f24SHeiko Stuebner * function of usb wakeup, so do not switch to 32khz, since the usb phy 132*780e3f24SHeiko Stuebner * clk does not connect to 32khz osc 133*780e3f24SHeiko Stuebner */ 134*780e3f24SHeiko Stuebner for (i = 0; i < ARRAY_SIZE(reg_offset); i++) { 135*780e3f24SHeiko Stuebner reg = mmio_read_32(GRF_BASE + reg_offset[i]); 136*780e3f24SHeiko Stuebner if (!(reg & GRF_SIDDQ)) 137*780e3f24SHeiko Stuebner return false; 138*780e3f24SHeiko Stuebner } 139*780e3f24SHeiko Stuebner 140*780e3f24SHeiko Stuebner return true; 141*780e3f24SHeiko Stuebner } 142*780e3f24SHeiko Stuebner 143*780e3f24SHeiko Stuebner static void pmu_set_sleep_mode(int level) 144*780e3f24SHeiko Stuebner { 145*780e3f24SHeiko Stuebner uint32_t mode_set, mode_set1; 146*780e3f24SHeiko Stuebner bool osc_disable = rk3288_sleep_disable_osc(); 147*780e3f24SHeiko Stuebner 148*780e3f24SHeiko Stuebner mode_set = BIT(pmu_mode_glb_int_dis) | BIT(pmu_mode_l2_flush_en) | 149*780e3f24SHeiko Stuebner BIT(pmu_mode_sref0_enter) | BIT(pmu_mode_sref1_enter) | 150*780e3f24SHeiko Stuebner BIT(pmu_mode_ddrc0_gt) | BIT(pmu_mode_ddrc1_gt) | 151*780e3f24SHeiko Stuebner BIT(pmu_mode_en) | BIT(pmu_mode_chip_pd) | 152*780e3f24SHeiko Stuebner BIT(pmu_mode_scu_pd); 153*780e3f24SHeiko Stuebner 154*780e3f24SHeiko Stuebner mode_set1 = BIT(pmu_mode_clr_core) | BIT(pmu_mode_clr_cpup); 155*780e3f24SHeiko Stuebner 156*780e3f24SHeiko Stuebner if (level == ROCKCHIP_ARM_OFF_LOGIC_DEEP) { 157*780e3f24SHeiko Stuebner /* arm off, logic deep sleep */ 158*780e3f24SHeiko Stuebner mode_set |= BIT(pmu_mode_bus_pd) | BIT(pmu_mode_pmu_use_lf) | 159*780e3f24SHeiko Stuebner BIT(pmu_mode_ddrio1_ret) | 160*780e3f24SHeiko Stuebner BIT(pmu_mode_ddrio0_ret) | 161*780e3f24SHeiko Stuebner BIT(pmu_mode_pmu_alive_use_lf) | 162*780e3f24SHeiko Stuebner BIT(pmu_mode_pll_pd); 163*780e3f24SHeiko Stuebner 164*780e3f24SHeiko Stuebner if (osc_disable) 165*780e3f24SHeiko Stuebner mode_set |= BIT(pmu_mode_osc_dis); 166*780e3f24SHeiko Stuebner 167*780e3f24SHeiko Stuebner mode_set1 |= BIT(pmu_mode_clr_alive) | BIT(pmu_mode_clr_bus) | 168*780e3f24SHeiko Stuebner BIT(pmu_mode_clr_peri) | BIT(pmu_mode_clr_dma); 169*780e3f24SHeiko Stuebner 170*780e3f24SHeiko Stuebner mmio_write_32(PMU_BASE + PMU_WAKEUP_CFG1, 171*780e3f24SHeiko Stuebner pmu_armint_wakeup_en); 172*780e3f24SHeiko Stuebner 173*780e3f24SHeiko Stuebner /* 174*780e3f24SHeiko Stuebner * In deep suspend we use PMU_PMU_USE_LF to let the rk3288 175*780e3f24SHeiko Stuebner * switch its main clock supply to the alternative 32kHz 176*780e3f24SHeiko Stuebner * source. Therefore set 30ms on a 32kHz clock for pmic 177*780e3f24SHeiko Stuebner * stabilization. Similar 30ms on 24MHz for the other 178*780e3f24SHeiko Stuebner * mode below. 179*780e3f24SHeiko Stuebner */ 180*780e3f24SHeiko Stuebner mmio_write_32(PMU_BASE + PMU_STABL_CNT, 32 * 30); 181*780e3f24SHeiko Stuebner 182*780e3f24SHeiko Stuebner /* only wait for stabilization, if we turned the osc off */ 183*780e3f24SHeiko Stuebner mmio_write_32(PMU_BASE + PMU_OSC_CNT, 184*780e3f24SHeiko Stuebner osc_disable ? 32 * 30 : 0); 185*780e3f24SHeiko Stuebner } else { 186*780e3f24SHeiko Stuebner /* 187*780e3f24SHeiko Stuebner * arm off, logic normal 188*780e3f24SHeiko Stuebner * if pmu_clk_core_src_gate_en is not set, 189*780e3f24SHeiko Stuebner * wakeup will be error 190*780e3f24SHeiko Stuebner */ 191*780e3f24SHeiko Stuebner mode_set |= BIT(pmu_mode_core_src_gt); 192*780e3f24SHeiko Stuebner 193*780e3f24SHeiko Stuebner mmio_write_32(PMU_BASE + PMU_WAKEUP_CFG1, 194*780e3f24SHeiko Stuebner BIT(pmu_armint_wakeup_en) | 195*780e3f24SHeiko Stuebner BIT(pmu_gpioint_wakeup_en)); 196*780e3f24SHeiko Stuebner 197*780e3f24SHeiko Stuebner /* 30ms on a 24MHz clock for pmic stabilization */ 198*780e3f24SHeiko Stuebner mmio_write_32(PMU_BASE + PMU_STABL_CNT, 24000 * 30); 199*780e3f24SHeiko Stuebner 200*780e3f24SHeiko Stuebner /* oscillator is still running, so no need to wait */ 201*780e3f24SHeiko Stuebner mmio_write_32(PMU_BASE + PMU_OSC_CNT, 0); 202*780e3f24SHeiko Stuebner } 203*780e3f24SHeiko Stuebner 204*780e3f24SHeiko Stuebner mmio_write_32(PMU_BASE + PMU_PWRMODE_CON, mode_set); 205*780e3f24SHeiko Stuebner mmio_write_32(PMU_BASE + PMU_PWRMODE_CON1, mode_set1); 206*780e3f24SHeiko Stuebner } 207*780e3f24SHeiko Stuebner 208*780e3f24SHeiko Stuebner static int cpus_power_domain_on(uint32_t cpu_id) 209*780e3f24SHeiko Stuebner { 210*780e3f24SHeiko Stuebner uint32_t cpu_pd; 211*780e3f24SHeiko Stuebner 212*780e3f24SHeiko Stuebner cpu_pd = PD_CPU0 + cpu_id; 213*780e3f24SHeiko Stuebner 214*780e3f24SHeiko Stuebner /* if the core has been on, power it off first */ 215*780e3f24SHeiko Stuebner if (pmu_power_domain_st(cpu_pd) == pmu_pd_on) { 216*780e3f24SHeiko Stuebner /* put core in reset - some sort of A12/A17 bug */ 217*780e3f24SHeiko Stuebner mmio_write_32(CRU_BASE + CRU_SOFTRSTS_CON(0), 218*780e3f24SHeiko Stuebner BIT(cpu_id) | (BIT(cpu_id) << 16)); 219*780e3f24SHeiko Stuebner 220*780e3f24SHeiko Stuebner pmu_power_domain_ctr(cpu_pd, pmu_pd_off); 221*780e3f24SHeiko Stuebner } 222*780e3f24SHeiko Stuebner 223*780e3f24SHeiko Stuebner pmu_power_domain_ctr(cpu_pd, pmu_pd_on); 224*780e3f24SHeiko Stuebner 225*780e3f24SHeiko Stuebner /* pull core out of reset */ 226*780e3f24SHeiko Stuebner mmio_write_32(CRU_BASE + CRU_SOFTRSTS_CON(0), BIT(cpu_id) << 16); 227*780e3f24SHeiko Stuebner 228*780e3f24SHeiko Stuebner return 0; 229*780e3f24SHeiko Stuebner } 230*780e3f24SHeiko Stuebner 231*780e3f24SHeiko Stuebner static int cpus_power_domain_off(uint32_t cpu_id) 232*780e3f24SHeiko Stuebner { 233*780e3f24SHeiko Stuebner uint32_t cpu_pd = PD_CPU0 + cpu_id; 234*780e3f24SHeiko Stuebner 235*780e3f24SHeiko Stuebner if (pmu_power_domain_st(cpu_pd) == pmu_pd_off) 236*780e3f24SHeiko Stuebner return 0; 237*780e3f24SHeiko Stuebner 238*780e3f24SHeiko Stuebner if (check_cpu_wfie(cpu_id, CKECK_WFEI_MSK)) 239*780e3f24SHeiko Stuebner return -EINVAL; 240*780e3f24SHeiko Stuebner 241*780e3f24SHeiko Stuebner /* put core in reset - some sort of A12/A17 bug */ 242*780e3f24SHeiko Stuebner mmio_write_32(CRU_BASE + CRU_SOFTRSTS_CON(0), 243*780e3f24SHeiko Stuebner BIT(cpu_id) | (BIT(cpu_id) << 16)); 244*780e3f24SHeiko Stuebner 245*780e3f24SHeiko Stuebner pmu_power_domain_ctr(cpu_pd, pmu_pd_off); 246*780e3f24SHeiko Stuebner 247*780e3f24SHeiko Stuebner return 0; 248*780e3f24SHeiko Stuebner } 249*780e3f24SHeiko Stuebner 250*780e3f24SHeiko Stuebner static void nonboot_cpus_off(void) 251*780e3f24SHeiko Stuebner { 252*780e3f24SHeiko Stuebner uint32_t boot_cpu, cpu; 253*780e3f24SHeiko Stuebner 254*780e3f24SHeiko Stuebner boot_cpu = plat_my_core_pos(); 255*780e3f24SHeiko Stuebner boot_cpu = MPIDR_AFFLVL0_VAL(read_mpidr()); 256*780e3f24SHeiko Stuebner 257*780e3f24SHeiko Stuebner /* turn off noboot cpus */ 258*780e3f24SHeiko Stuebner for (cpu = 0; cpu < PLATFORM_CORE_COUNT; cpu++) { 259*780e3f24SHeiko Stuebner if (cpu == boot_cpu) 260*780e3f24SHeiko Stuebner continue; 261*780e3f24SHeiko Stuebner 262*780e3f24SHeiko Stuebner cpus_power_domain_off(cpu); 263*780e3f24SHeiko Stuebner } 264*780e3f24SHeiko Stuebner } 265*780e3f24SHeiko Stuebner 266*780e3f24SHeiko Stuebner void sram_save(void) 267*780e3f24SHeiko Stuebner { 268*780e3f24SHeiko Stuebner /* TODO: support the sdram save for rk3288 SoCs*/ 269*780e3f24SHeiko Stuebner } 270*780e3f24SHeiko Stuebner 271*780e3f24SHeiko Stuebner void sram_restore(void) 272*780e3f24SHeiko Stuebner { 273*780e3f24SHeiko Stuebner /* TODO: support the sdram restore for rk3288 SoCs */ 274*780e3f24SHeiko Stuebner } 275*780e3f24SHeiko Stuebner 276*780e3f24SHeiko Stuebner int rockchip_soc_cores_pwr_dm_on(unsigned long mpidr, uint64_t entrypoint) 277*780e3f24SHeiko Stuebner { 278*780e3f24SHeiko Stuebner uint32_t cpu_id = plat_core_pos_by_mpidr(mpidr); 279*780e3f24SHeiko Stuebner 280*780e3f24SHeiko Stuebner assert(cpu_id < PLATFORM_CORE_COUNT); 281*780e3f24SHeiko Stuebner assert(cpuson_flags[cpu_id] == 0); 282*780e3f24SHeiko Stuebner cpuson_flags[cpu_id] = PMU_CPU_HOTPLUG; 283*780e3f24SHeiko Stuebner cpuson_entry_point[cpu_id] = entrypoint; 284*780e3f24SHeiko Stuebner dsb(); 285*780e3f24SHeiko Stuebner 286*780e3f24SHeiko Stuebner cpus_power_domain_on(cpu_id); 287*780e3f24SHeiko Stuebner 288*780e3f24SHeiko Stuebner /* 289*780e3f24SHeiko Stuebner * We communicate with the bootrom to active the cpus other 290*780e3f24SHeiko Stuebner * than cpu0, after a blob of initialize code, they will 291*780e3f24SHeiko Stuebner * stay at wfe state, once they are actived, they will check 292*780e3f24SHeiko Stuebner * the mailbox: 293*780e3f24SHeiko Stuebner * sram_base_addr + 4: 0xdeadbeaf 294*780e3f24SHeiko Stuebner * sram_base_addr + 8: start address for pc 295*780e3f24SHeiko Stuebner * The cpu0 need to wait the other cpus other than cpu0 entering 296*780e3f24SHeiko Stuebner * the wfe state.The wait time is affected by many aspects. 297*780e3f24SHeiko Stuebner * (e.g: cpu frequency, bootrom frequency, sram frequency, ...) 298*780e3f24SHeiko Stuebner */ 299*780e3f24SHeiko Stuebner mdelay(1); /* ensure the cpus other than cpu0 to startup */ 300*780e3f24SHeiko Stuebner 301*780e3f24SHeiko Stuebner /* tell the bootrom mailbox where to start from */ 302*780e3f24SHeiko Stuebner mmio_write_32(SRAM_BASE + 8, cpu_warm_boot_addr); 303*780e3f24SHeiko Stuebner mmio_write_32(SRAM_BASE + 4, 0xDEADBEAF); 304*780e3f24SHeiko Stuebner dsb(); 305*780e3f24SHeiko Stuebner sev(); 306*780e3f24SHeiko Stuebner 307*780e3f24SHeiko Stuebner return 0; 308*780e3f24SHeiko Stuebner } 309*780e3f24SHeiko Stuebner 310*780e3f24SHeiko Stuebner int rockchip_soc_cores_pwr_dm_on_finish(void) 311*780e3f24SHeiko Stuebner { 312*780e3f24SHeiko Stuebner return 0; 313*780e3f24SHeiko Stuebner } 314*780e3f24SHeiko Stuebner 315*780e3f24SHeiko Stuebner int rockchip_soc_sys_pwr_dm_resume(void) 316*780e3f24SHeiko Stuebner { 317*780e3f24SHeiko Stuebner mmio_write_32(PMU_BASE + PMU_PWRMODE_CON, store_pmu_pwrmode_con); 318*780e3f24SHeiko Stuebner mmio_write_32(SGRF_BASE + SGRF_CPU_CON(0), 319*780e3f24SHeiko Stuebner store_sgrf_cpu_con0 | SGRF_DAPDEVICE_MSK); 320*780e3f24SHeiko Stuebner 321*780e3f24SHeiko Stuebner /* disable fastboot mode */ 322*780e3f24SHeiko Stuebner mmio_write_32(SGRF_BASE + SGRF_SOC_CON(0), 323*780e3f24SHeiko Stuebner store_sgrf_soc_con0 | SGRF_FAST_BOOT_DIS); 324*780e3f24SHeiko Stuebner 325*780e3f24SHeiko Stuebner secure_watchdog_ungate(); 326*780e3f24SHeiko Stuebner clk_gate_con_restore(); 327*780e3f24SHeiko Stuebner clk_sel_con_restore(); 328*780e3f24SHeiko Stuebner clk_plls_resume(); 329*780e3f24SHeiko Stuebner 330*780e3f24SHeiko Stuebner secure_gic_init(); 331*780e3f24SHeiko Stuebner plat_rockchip_gic_init(); 332*780e3f24SHeiko Stuebner 333*780e3f24SHeiko Stuebner return 0; 334*780e3f24SHeiko Stuebner } 335*780e3f24SHeiko Stuebner 336*780e3f24SHeiko Stuebner int rockchip_soc_sys_pwr_dm_suspend(void) 337*780e3f24SHeiko Stuebner { 338*780e3f24SHeiko Stuebner nonboot_cpus_off(); 339*780e3f24SHeiko Stuebner 340*780e3f24SHeiko Stuebner store_sgrf_cpu_con0 = mmio_read_32(SGRF_BASE + SGRF_CPU_CON(0)); 341*780e3f24SHeiko Stuebner store_sgrf_soc_con0 = mmio_read_32(SGRF_BASE + SGRF_SOC_CON(0)); 342*780e3f24SHeiko Stuebner store_pmu_pwrmode_con = mmio_read_32(PMU_BASE + PMU_PWRMODE_CON); 343*780e3f24SHeiko Stuebner 344*780e3f24SHeiko Stuebner /* save clk-gates and ungate all for suspend */ 345*780e3f24SHeiko Stuebner clk_gate_con_save(); 346*780e3f24SHeiko Stuebner clk_gate_con_disable(); 347*780e3f24SHeiko Stuebner clk_sel_con_save(); 348*780e3f24SHeiko Stuebner 349*780e3f24SHeiko Stuebner pmu_set_sleep_mode(ROCKCHIP_ARM_OFF_LOGIC_NORMAL); 350*780e3f24SHeiko Stuebner 351*780e3f24SHeiko Stuebner clk_plls_suspend(); 352*780e3f24SHeiko Stuebner secure_watchdog_gate(); 353*780e3f24SHeiko Stuebner 354*780e3f24SHeiko Stuebner /* 355*780e3f24SHeiko Stuebner * The dapswjdp can not auto reset before resume, that cause it may 356*780e3f24SHeiko Stuebner * access some illegal address during resume. Let's disable it before 357*780e3f24SHeiko Stuebner * suspend, and the MASKROM will enable it back. 358*780e3f24SHeiko Stuebner */ 359*780e3f24SHeiko Stuebner mmio_write_32(SGRF_BASE + SGRF_CPU_CON(0), SGRF_DAPDEVICE_MSK); 360*780e3f24SHeiko Stuebner 361*780e3f24SHeiko Stuebner /* 362*780e3f24SHeiko Stuebner * SGRF_FAST_BOOT_EN - system to boot from FAST_BOOT_ADDR 363*780e3f24SHeiko Stuebner */ 364*780e3f24SHeiko Stuebner mmio_write_32(SGRF_BASE + SGRF_SOC_CON(0), SGRF_FAST_BOOT_ENA); 365*780e3f24SHeiko Stuebner 366*780e3f24SHeiko Stuebner /* boot-address of resuming system is from this register value */ 367*780e3f24SHeiko Stuebner mmio_write_32(SGRF_BASE + SGRF_FAST_BOOT_ADDR, 368*780e3f24SHeiko Stuebner (uint32_t)&pmu_cpuson_entrypoint); 369*780e3f24SHeiko Stuebner 370*780e3f24SHeiko Stuebner /* flush all caches - otherwise we might loose the resume address */ 371*780e3f24SHeiko Stuebner dcsw_op_all(DC_OP_CISW); 372*780e3f24SHeiko Stuebner 373*780e3f24SHeiko Stuebner return 0; 374*780e3f24SHeiko Stuebner } 375*780e3f24SHeiko Stuebner 376*780e3f24SHeiko Stuebner void rockchip_plat_mmu_svc_mon(void) 377*780e3f24SHeiko Stuebner { 378*780e3f24SHeiko Stuebner } 379*780e3f24SHeiko Stuebner 380*780e3f24SHeiko Stuebner void plat_rockchip_pmu_init(void) 381*780e3f24SHeiko Stuebner { 382*780e3f24SHeiko Stuebner uint32_t cpu; 383*780e3f24SHeiko Stuebner 384*780e3f24SHeiko Stuebner cpu_warm_boot_addr = (uint32_t)platform_cpu_warmboot; 385*780e3f24SHeiko Stuebner 386*780e3f24SHeiko Stuebner /* on boot all power-domains are on */ 387*780e3f24SHeiko Stuebner for (cpu = 0; cpu < PLATFORM_CORE_COUNT; cpu++) 388*780e3f24SHeiko Stuebner cpuson_flags[cpu] = pmu_pd_on; 389*780e3f24SHeiko Stuebner 390*780e3f24SHeiko Stuebner nonboot_cpus_off(); 391*780e3f24SHeiko Stuebner } 392