1*91f16700Schasinglulu /* 2*91f16700Schasinglulu * Copyright (c) 2016-2021, 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 #include <string.h> 10*91f16700Schasinglulu 11*91f16700Schasinglulu #include <platform_def.h> 12*91f16700Schasinglulu 13*91f16700Schasinglulu #include <arch_helpers.h> 14*91f16700Schasinglulu #include <bl31/bl31.h> 15*91f16700Schasinglulu #include <common/debug.h> 16*91f16700Schasinglulu #include <drivers/arm/gicv3.h> 17*91f16700Schasinglulu #include <drivers/delay_timer.h> 18*91f16700Schasinglulu #include <drivers/gpio.h> 19*91f16700Schasinglulu #include <lib/bakery_lock.h> 20*91f16700Schasinglulu #include <lib/mmio.h> 21*91f16700Schasinglulu #include <plat/common/platform.h> 22*91f16700Schasinglulu 23*91f16700Schasinglulu #include <dfs.h> 24*91f16700Schasinglulu #include <m0_ctl.h> 25*91f16700Schasinglulu #include <plat_params.h> 26*91f16700Schasinglulu #include <plat_private.h> 27*91f16700Schasinglulu #include <pmu.h> 28*91f16700Schasinglulu #include <pmu_com.h> 29*91f16700Schasinglulu #include <pwm.h> 30*91f16700Schasinglulu #include <rk3399_def.h> 31*91f16700Schasinglulu #include <secure.h> 32*91f16700Schasinglulu #include <soc.h> 33*91f16700Schasinglulu #include <suspend.h> 34*91f16700Schasinglulu 35*91f16700Schasinglulu DEFINE_BAKERY_LOCK(rockchip_pd_lock); 36*91f16700Schasinglulu 37*91f16700Schasinglulu static uint32_t cpu_warm_boot_addr; 38*91f16700Schasinglulu static char store_sram[SRAM_BIN_LIMIT + SRAM_TEXT_LIMIT + SRAM_DATA_LIMIT]; 39*91f16700Schasinglulu static uint32_t store_cru[CRU_SDIO0_CON1 / 4 + 1]; 40*91f16700Schasinglulu static uint32_t store_usbphy0[7]; 41*91f16700Schasinglulu static uint32_t store_usbphy1[7]; 42*91f16700Schasinglulu static uint32_t store_grf_io_vsel; 43*91f16700Schasinglulu static uint32_t store_grf_soc_con0; 44*91f16700Schasinglulu static uint32_t store_grf_soc_con1; 45*91f16700Schasinglulu static uint32_t store_grf_soc_con2; 46*91f16700Schasinglulu static uint32_t store_grf_soc_con3; 47*91f16700Schasinglulu static uint32_t store_grf_soc_con4; 48*91f16700Schasinglulu static uint32_t store_grf_soc_con7; 49*91f16700Schasinglulu static uint32_t store_grf_ddrc_con[4]; 50*91f16700Schasinglulu static uint32_t store_wdt0[2]; 51*91f16700Schasinglulu static uint32_t store_wdt1[2]; 52*91f16700Schasinglulu static gicv3_dist_ctx_t dist_ctx; 53*91f16700Schasinglulu static gicv3_redist_ctx_t rdist_ctx; 54*91f16700Schasinglulu 55*91f16700Schasinglulu /* 56*91f16700Schasinglulu * There are two ways to powering on or off on core. 57*91f16700Schasinglulu * 1) Control it power domain into on or off in PMU_PWRDN_CON reg, 58*91f16700Schasinglulu * it is core_pwr_pd mode 59*91f16700Schasinglulu * 2) Enable the core power manage in PMU_CORE_PM_CON reg, 60*91f16700Schasinglulu * then, if the core enter into wfi, it power domain will be 61*91f16700Schasinglulu * powered off automatically. it is core_pwr_wfi or core_pwr_wfi_int mode 62*91f16700Schasinglulu * so we need core_pm_cfg_info to distinguish which method be used now. 63*91f16700Schasinglulu */ 64*91f16700Schasinglulu 65*91f16700Schasinglulu static uint32_t core_pm_cfg_info[PLATFORM_CORE_COUNT] 66*91f16700Schasinglulu #if USE_COHERENT_MEM 67*91f16700Schasinglulu __attribute__ ((section(".tzfw_coherent_mem"))) 68*91f16700Schasinglulu #endif 69*91f16700Schasinglulu ;/* coheront */ 70*91f16700Schasinglulu 71*91f16700Schasinglulu static void pmu_bus_idle_req(uint32_t bus, uint32_t state) 72*91f16700Schasinglulu { 73*91f16700Schasinglulu uint32_t bus_id = BIT(bus); 74*91f16700Schasinglulu uint32_t bus_req; 75*91f16700Schasinglulu uint32_t wait_cnt = 0; 76*91f16700Schasinglulu uint32_t bus_state, bus_ack; 77*91f16700Schasinglulu 78*91f16700Schasinglulu if (state) 79*91f16700Schasinglulu bus_req = BIT(bus); 80*91f16700Schasinglulu else 81*91f16700Schasinglulu bus_req = 0; 82*91f16700Schasinglulu 83*91f16700Schasinglulu mmio_clrsetbits_32(PMU_BASE + PMU_BUS_IDLE_REQ, bus_id, bus_req); 84*91f16700Schasinglulu 85*91f16700Schasinglulu do { 86*91f16700Schasinglulu bus_state = mmio_read_32(PMU_BASE + PMU_BUS_IDLE_ST) & bus_id; 87*91f16700Schasinglulu bus_ack = mmio_read_32(PMU_BASE + PMU_BUS_IDLE_ACK) & bus_id; 88*91f16700Schasinglulu if (bus_state == bus_req && bus_ack == bus_req) 89*91f16700Schasinglulu break; 90*91f16700Schasinglulu 91*91f16700Schasinglulu wait_cnt++; 92*91f16700Schasinglulu udelay(1); 93*91f16700Schasinglulu } while (wait_cnt < MAX_WAIT_COUNT); 94*91f16700Schasinglulu 95*91f16700Schasinglulu if (bus_state != bus_req || bus_ack != bus_req) { 96*91f16700Schasinglulu INFO("%s:st=%x(%x)\n", __func__, 97*91f16700Schasinglulu mmio_read_32(PMU_BASE + PMU_BUS_IDLE_ST), 98*91f16700Schasinglulu bus_state); 99*91f16700Schasinglulu INFO("%s:st=%x(%x)\n", __func__, 100*91f16700Schasinglulu mmio_read_32(PMU_BASE + PMU_BUS_IDLE_ACK), 101*91f16700Schasinglulu bus_ack); 102*91f16700Schasinglulu } 103*91f16700Schasinglulu } 104*91f16700Schasinglulu 105*91f16700Schasinglulu struct pmu_slpdata_s pmu_slpdata; 106*91f16700Schasinglulu 107*91f16700Schasinglulu static void qos_restore(void) 108*91f16700Schasinglulu { 109*91f16700Schasinglulu if (pmu_power_domain_st(PD_GPU) == pmu_pd_on) 110*91f16700Schasinglulu RESTORE_QOS(pmu_slpdata.gpu_qos, GPU); 111*91f16700Schasinglulu if (pmu_power_domain_st(PD_ISP0) == pmu_pd_on) { 112*91f16700Schasinglulu RESTORE_QOS(pmu_slpdata.isp0_m0_qos, ISP0_M0); 113*91f16700Schasinglulu RESTORE_QOS(pmu_slpdata.isp0_m1_qos, ISP0_M1); 114*91f16700Schasinglulu } 115*91f16700Schasinglulu if (pmu_power_domain_st(PD_ISP1) == pmu_pd_on) { 116*91f16700Schasinglulu RESTORE_QOS(pmu_slpdata.isp1_m0_qos, ISP1_M0); 117*91f16700Schasinglulu RESTORE_QOS(pmu_slpdata.isp1_m1_qos, ISP1_M1); 118*91f16700Schasinglulu } 119*91f16700Schasinglulu if (pmu_power_domain_st(PD_VO) == pmu_pd_on) { 120*91f16700Schasinglulu RESTORE_QOS(pmu_slpdata.vop_big_r, VOP_BIG_R); 121*91f16700Schasinglulu RESTORE_QOS(pmu_slpdata.vop_big_w, VOP_BIG_W); 122*91f16700Schasinglulu RESTORE_QOS(pmu_slpdata.vop_little, VOP_LITTLE); 123*91f16700Schasinglulu } 124*91f16700Schasinglulu if (pmu_power_domain_st(PD_HDCP) == pmu_pd_on) 125*91f16700Schasinglulu RESTORE_QOS(pmu_slpdata.hdcp_qos, HDCP); 126*91f16700Schasinglulu if (pmu_power_domain_st(PD_GMAC) == pmu_pd_on) 127*91f16700Schasinglulu RESTORE_QOS(pmu_slpdata.gmac_qos, GMAC); 128*91f16700Schasinglulu if (pmu_power_domain_st(PD_CCI) == pmu_pd_on) { 129*91f16700Schasinglulu RESTORE_QOS(pmu_slpdata.cci_m0_qos, CCI_M0); 130*91f16700Schasinglulu RESTORE_QOS(pmu_slpdata.cci_m1_qos, CCI_M1); 131*91f16700Schasinglulu } 132*91f16700Schasinglulu if (pmu_power_domain_st(PD_SD) == pmu_pd_on) 133*91f16700Schasinglulu RESTORE_QOS(pmu_slpdata.sdmmc_qos, SDMMC); 134*91f16700Schasinglulu if (pmu_power_domain_st(PD_EMMC) == pmu_pd_on) 135*91f16700Schasinglulu RESTORE_QOS(pmu_slpdata.emmc_qos, EMMC); 136*91f16700Schasinglulu if (pmu_power_domain_st(PD_SDIOAUDIO) == pmu_pd_on) 137*91f16700Schasinglulu RESTORE_QOS(pmu_slpdata.sdio_qos, SDIO); 138*91f16700Schasinglulu if (pmu_power_domain_st(PD_GIC) == pmu_pd_on) 139*91f16700Schasinglulu RESTORE_QOS(pmu_slpdata.gic_qos, GIC); 140*91f16700Schasinglulu if (pmu_power_domain_st(PD_RGA) == pmu_pd_on) { 141*91f16700Schasinglulu RESTORE_QOS(pmu_slpdata.rga_r_qos, RGA_R); 142*91f16700Schasinglulu RESTORE_QOS(pmu_slpdata.rga_w_qos, RGA_W); 143*91f16700Schasinglulu } 144*91f16700Schasinglulu if (pmu_power_domain_st(PD_IEP) == pmu_pd_on) 145*91f16700Schasinglulu RESTORE_QOS(pmu_slpdata.iep_qos, IEP); 146*91f16700Schasinglulu if (pmu_power_domain_st(PD_USB3) == pmu_pd_on) { 147*91f16700Schasinglulu RESTORE_QOS(pmu_slpdata.usb_otg0_qos, USB_OTG0); 148*91f16700Schasinglulu RESTORE_QOS(pmu_slpdata.usb_otg1_qos, USB_OTG1); 149*91f16700Schasinglulu } 150*91f16700Schasinglulu if (pmu_power_domain_st(PD_PERIHP) == pmu_pd_on) { 151*91f16700Schasinglulu RESTORE_QOS(pmu_slpdata.usb_host0_qos, USB_HOST0); 152*91f16700Schasinglulu RESTORE_QOS(pmu_slpdata.usb_host1_qos, USB_HOST1); 153*91f16700Schasinglulu RESTORE_QOS(pmu_slpdata.perihp_nsp_qos, PERIHP_NSP); 154*91f16700Schasinglulu } 155*91f16700Schasinglulu if (pmu_power_domain_st(PD_PERILP) == pmu_pd_on) { 156*91f16700Schasinglulu RESTORE_QOS(pmu_slpdata.dmac0_qos, DMAC0); 157*91f16700Schasinglulu RESTORE_QOS(pmu_slpdata.dmac1_qos, DMAC1); 158*91f16700Schasinglulu RESTORE_QOS(pmu_slpdata.dcf_qos, DCF); 159*91f16700Schasinglulu RESTORE_QOS(pmu_slpdata.crypto0_qos, CRYPTO0); 160*91f16700Schasinglulu RESTORE_QOS(pmu_slpdata.crypto1_qos, CRYPTO1); 161*91f16700Schasinglulu RESTORE_QOS(pmu_slpdata.perilp_nsp_qos, PERILP_NSP); 162*91f16700Schasinglulu RESTORE_QOS(pmu_slpdata.perilpslv_nsp_qos, PERILPSLV_NSP); 163*91f16700Schasinglulu RESTORE_QOS(pmu_slpdata.peri_cm1_qos, PERI_CM1); 164*91f16700Schasinglulu } 165*91f16700Schasinglulu if (pmu_power_domain_st(PD_VDU) == pmu_pd_on) 166*91f16700Schasinglulu RESTORE_QOS(pmu_slpdata.video_m0_qos, VIDEO_M0); 167*91f16700Schasinglulu if (pmu_power_domain_st(PD_VCODEC) == pmu_pd_on) { 168*91f16700Schasinglulu RESTORE_QOS(pmu_slpdata.video_m1_r_qos, VIDEO_M1_R); 169*91f16700Schasinglulu RESTORE_QOS(pmu_slpdata.video_m1_w_qos, VIDEO_M1_W); 170*91f16700Schasinglulu } 171*91f16700Schasinglulu } 172*91f16700Schasinglulu 173*91f16700Schasinglulu static void qos_save(void) 174*91f16700Schasinglulu { 175*91f16700Schasinglulu if (pmu_power_domain_st(PD_GPU) == pmu_pd_on) 176*91f16700Schasinglulu SAVE_QOS(pmu_slpdata.gpu_qos, GPU); 177*91f16700Schasinglulu if (pmu_power_domain_st(PD_ISP0) == pmu_pd_on) { 178*91f16700Schasinglulu SAVE_QOS(pmu_slpdata.isp0_m0_qos, ISP0_M0); 179*91f16700Schasinglulu SAVE_QOS(pmu_slpdata.isp0_m1_qos, ISP0_M1); 180*91f16700Schasinglulu } 181*91f16700Schasinglulu if (pmu_power_domain_st(PD_ISP1) == pmu_pd_on) { 182*91f16700Schasinglulu SAVE_QOS(pmu_slpdata.isp1_m0_qos, ISP1_M0); 183*91f16700Schasinglulu SAVE_QOS(pmu_slpdata.isp1_m1_qos, ISP1_M1); 184*91f16700Schasinglulu } 185*91f16700Schasinglulu if (pmu_power_domain_st(PD_VO) == pmu_pd_on) { 186*91f16700Schasinglulu SAVE_QOS(pmu_slpdata.vop_big_r, VOP_BIG_R); 187*91f16700Schasinglulu SAVE_QOS(pmu_slpdata.vop_big_w, VOP_BIG_W); 188*91f16700Schasinglulu SAVE_QOS(pmu_slpdata.vop_little, VOP_LITTLE); 189*91f16700Schasinglulu } 190*91f16700Schasinglulu if (pmu_power_domain_st(PD_HDCP) == pmu_pd_on) 191*91f16700Schasinglulu SAVE_QOS(pmu_slpdata.hdcp_qos, HDCP); 192*91f16700Schasinglulu if (pmu_power_domain_st(PD_GMAC) == pmu_pd_on) 193*91f16700Schasinglulu SAVE_QOS(pmu_slpdata.gmac_qos, GMAC); 194*91f16700Schasinglulu if (pmu_power_domain_st(PD_CCI) == pmu_pd_on) { 195*91f16700Schasinglulu SAVE_QOS(pmu_slpdata.cci_m0_qos, CCI_M0); 196*91f16700Schasinglulu SAVE_QOS(pmu_slpdata.cci_m1_qos, CCI_M1); 197*91f16700Schasinglulu } 198*91f16700Schasinglulu if (pmu_power_domain_st(PD_SD) == pmu_pd_on) 199*91f16700Schasinglulu SAVE_QOS(pmu_slpdata.sdmmc_qos, SDMMC); 200*91f16700Schasinglulu if (pmu_power_domain_st(PD_EMMC) == pmu_pd_on) 201*91f16700Schasinglulu SAVE_QOS(pmu_slpdata.emmc_qos, EMMC); 202*91f16700Schasinglulu if (pmu_power_domain_st(PD_SDIOAUDIO) == pmu_pd_on) 203*91f16700Schasinglulu SAVE_QOS(pmu_slpdata.sdio_qos, SDIO); 204*91f16700Schasinglulu if (pmu_power_domain_st(PD_GIC) == pmu_pd_on) 205*91f16700Schasinglulu SAVE_QOS(pmu_slpdata.gic_qos, GIC); 206*91f16700Schasinglulu if (pmu_power_domain_st(PD_RGA) == pmu_pd_on) { 207*91f16700Schasinglulu SAVE_QOS(pmu_slpdata.rga_r_qos, RGA_R); 208*91f16700Schasinglulu SAVE_QOS(pmu_slpdata.rga_w_qos, RGA_W); 209*91f16700Schasinglulu } 210*91f16700Schasinglulu if (pmu_power_domain_st(PD_IEP) == pmu_pd_on) 211*91f16700Schasinglulu SAVE_QOS(pmu_slpdata.iep_qos, IEP); 212*91f16700Schasinglulu if (pmu_power_domain_st(PD_USB3) == pmu_pd_on) { 213*91f16700Schasinglulu SAVE_QOS(pmu_slpdata.usb_otg0_qos, USB_OTG0); 214*91f16700Schasinglulu SAVE_QOS(pmu_slpdata.usb_otg1_qos, USB_OTG1); 215*91f16700Schasinglulu } 216*91f16700Schasinglulu if (pmu_power_domain_st(PD_PERIHP) == pmu_pd_on) { 217*91f16700Schasinglulu SAVE_QOS(pmu_slpdata.usb_host0_qos, USB_HOST0); 218*91f16700Schasinglulu SAVE_QOS(pmu_slpdata.usb_host1_qos, USB_HOST1); 219*91f16700Schasinglulu SAVE_QOS(pmu_slpdata.perihp_nsp_qos, PERIHP_NSP); 220*91f16700Schasinglulu } 221*91f16700Schasinglulu if (pmu_power_domain_st(PD_PERILP) == pmu_pd_on) { 222*91f16700Schasinglulu SAVE_QOS(pmu_slpdata.dmac0_qos, DMAC0); 223*91f16700Schasinglulu SAVE_QOS(pmu_slpdata.dmac1_qos, DMAC1); 224*91f16700Schasinglulu SAVE_QOS(pmu_slpdata.dcf_qos, DCF); 225*91f16700Schasinglulu SAVE_QOS(pmu_slpdata.crypto0_qos, CRYPTO0); 226*91f16700Schasinglulu SAVE_QOS(pmu_slpdata.crypto1_qos, CRYPTO1); 227*91f16700Schasinglulu SAVE_QOS(pmu_slpdata.perilp_nsp_qos, PERILP_NSP); 228*91f16700Schasinglulu SAVE_QOS(pmu_slpdata.perilpslv_nsp_qos, PERILPSLV_NSP); 229*91f16700Schasinglulu SAVE_QOS(pmu_slpdata.peri_cm1_qos, PERI_CM1); 230*91f16700Schasinglulu } 231*91f16700Schasinglulu if (pmu_power_domain_st(PD_VDU) == pmu_pd_on) 232*91f16700Schasinglulu SAVE_QOS(pmu_slpdata.video_m0_qos, VIDEO_M0); 233*91f16700Schasinglulu if (pmu_power_domain_st(PD_VCODEC) == pmu_pd_on) { 234*91f16700Schasinglulu SAVE_QOS(pmu_slpdata.video_m1_r_qos, VIDEO_M1_R); 235*91f16700Schasinglulu SAVE_QOS(pmu_slpdata.video_m1_w_qos, VIDEO_M1_W); 236*91f16700Schasinglulu } 237*91f16700Schasinglulu } 238*91f16700Schasinglulu 239*91f16700Schasinglulu static int pmu_set_power_domain(uint32_t pd_id, uint32_t pd_state) 240*91f16700Schasinglulu { 241*91f16700Schasinglulu uint32_t state; 242*91f16700Schasinglulu 243*91f16700Schasinglulu if (pmu_power_domain_st(pd_id) == pd_state) 244*91f16700Schasinglulu goto out; 245*91f16700Schasinglulu 246*91f16700Schasinglulu if (pd_state == pmu_pd_on) 247*91f16700Schasinglulu pmu_power_domain_ctr(pd_id, pd_state); 248*91f16700Schasinglulu 249*91f16700Schasinglulu state = (pd_state == pmu_pd_off) ? BUS_IDLE : BUS_ACTIVE; 250*91f16700Schasinglulu 251*91f16700Schasinglulu switch (pd_id) { 252*91f16700Schasinglulu case PD_GPU: 253*91f16700Schasinglulu pmu_bus_idle_req(BUS_ID_GPU, state); 254*91f16700Schasinglulu break; 255*91f16700Schasinglulu case PD_VIO: 256*91f16700Schasinglulu pmu_bus_idle_req(BUS_ID_VIO, state); 257*91f16700Schasinglulu break; 258*91f16700Schasinglulu case PD_ISP0: 259*91f16700Schasinglulu pmu_bus_idle_req(BUS_ID_ISP0, state); 260*91f16700Schasinglulu break; 261*91f16700Schasinglulu case PD_ISP1: 262*91f16700Schasinglulu pmu_bus_idle_req(BUS_ID_ISP1, state); 263*91f16700Schasinglulu break; 264*91f16700Schasinglulu case PD_VO: 265*91f16700Schasinglulu pmu_bus_idle_req(BUS_ID_VOPB, state); 266*91f16700Schasinglulu pmu_bus_idle_req(BUS_ID_VOPL, state); 267*91f16700Schasinglulu break; 268*91f16700Schasinglulu case PD_HDCP: 269*91f16700Schasinglulu pmu_bus_idle_req(BUS_ID_HDCP, state); 270*91f16700Schasinglulu break; 271*91f16700Schasinglulu case PD_TCPD0: 272*91f16700Schasinglulu break; 273*91f16700Schasinglulu case PD_TCPD1: 274*91f16700Schasinglulu break; 275*91f16700Schasinglulu case PD_GMAC: 276*91f16700Schasinglulu pmu_bus_idle_req(BUS_ID_GMAC, state); 277*91f16700Schasinglulu break; 278*91f16700Schasinglulu case PD_CCI: 279*91f16700Schasinglulu pmu_bus_idle_req(BUS_ID_CCIM0, state); 280*91f16700Schasinglulu pmu_bus_idle_req(BUS_ID_CCIM1, state); 281*91f16700Schasinglulu break; 282*91f16700Schasinglulu case PD_SD: 283*91f16700Schasinglulu pmu_bus_idle_req(BUS_ID_SD, state); 284*91f16700Schasinglulu break; 285*91f16700Schasinglulu case PD_EMMC: 286*91f16700Schasinglulu pmu_bus_idle_req(BUS_ID_EMMC, state); 287*91f16700Schasinglulu break; 288*91f16700Schasinglulu case PD_EDP: 289*91f16700Schasinglulu pmu_bus_idle_req(BUS_ID_EDP, state); 290*91f16700Schasinglulu break; 291*91f16700Schasinglulu case PD_SDIOAUDIO: 292*91f16700Schasinglulu pmu_bus_idle_req(BUS_ID_SDIOAUDIO, state); 293*91f16700Schasinglulu break; 294*91f16700Schasinglulu case PD_GIC: 295*91f16700Schasinglulu pmu_bus_idle_req(BUS_ID_GIC, state); 296*91f16700Schasinglulu break; 297*91f16700Schasinglulu case PD_RGA: 298*91f16700Schasinglulu pmu_bus_idle_req(BUS_ID_RGA, state); 299*91f16700Schasinglulu break; 300*91f16700Schasinglulu case PD_VCODEC: 301*91f16700Schasinglulu pmu_bus_idle_req(BUS_ID_VCODEC, state); 302*91f16700Schasinglulu break; 303*91f16700Schasinglulu case PD_VDU: 304*91f16700Schasinglulu pmu_bus_idle_req(BUS_ID_VDU, state); 305*91f16700Schasinglulu break; 306*91f16700Schasinglulu case PD_IEP: 307*91f16700Schasinglulu pmu_bus_idle_req(BUS_ID_IEP, state); 308*91f16700Schasinglulu break; 309*91f16700Schasinglulu case PD_USB3: 310*91f16700Schasinglulu pmu_bus_idle_req(BUS_ID_USB3, state); 311*91f16700Schasinglulu break; 312*91f16700Schasinglulu case PD_PERIHP: 313*91f16700Schasinglulu pmu_bus_idle_req(BUS_ID_PERIHP, state); 314*91f16700Schasinglulu break; 315*91f16700Schasinglulu default: 316*91f16700Schasinglulu /* Do nothing in default case */ 317*91f16700Schasinglulu break; 318*91f16700Schasinglulu } 319*91f16700Schasinglulu 320*91f16700Schasinglulu if (pd_state == pmu_pd_off) 321*91f16700Schasinglulu pmu_power_domain_ctr(pd_id, pd_state); 322*91f16700Schasinglulu 323*91f16700Schasinglulu out: 324*91f16700Schasinglulu return 0; 325*91f16700Schasinglulu } 326*91f16700Schasinglulu 327*91f16700Schasinglulu static uint32_t pmu_powerdomain_state; 328*91f16700Schasinglulu 329*91f16700Schasinglulu static void pmu_power_domains_suspend(void) 330*91f16700Schasinglulu { 331*91f16700Schasinglulu clk_gate_con_save(); 332*91f16700Schasinglulu clk_gate_con_disable(); 333*91f16700Schasinglulu qos_save(); 334*91f16700Schasinglulu pmu_powerdomain_state = mmio_read_32(PMU_BASE + PMU_PWRDN_ST); 335*91f16700Schasinglulu pmu_set_power_domain(PD_GPU, pmu_pd_off); 336*91f16700Schasinglulu pmu_set_power_domain(PD_TCPD0, pmu_pd_off); 337*91f16700Schasinglulu pmu_set_power_domain(PD_TCPD1, pmu_pd_off); 338*91f16700Schasinglulu pmu_set_power_domain(PD_VO, pmu_pd_off); 339*91f16700Schasinglulu pmu_set_power_domain(PD_ISP0, pmu_pd_off); 340*91f16700Schasinglulu pmu_set_power_domain(PD_ISP1, pmu_pd_off); 341*91f16700Schasinglulu pmu_set_power_domain(PD_HDCP, pmu_pd_off); 342*91f16700Schasinglulu pmu_set_power_domain(PD_SDIOAUDIO, pmu_pd_off); 343*91f16700Schasinglulu pmu_set_power_domain(PD_GMAC, pmu_pd_off); 344*91f16700Schasinglulu pmu_set_power_domain(PD_EDP, pmu_pd_off); 345*91f16700Schasinglulu pmu_set_power_domain(PD_IEP, pmu_pd_off); 346*91f16700Schasinglulu pmu_set_power_domain(PD_RGA, pmu_pd_off); 347*91f16700Schasinglulu pmu_set_power_domain(PD_VCODEC, pmu_pd_off); 348*91f16700Schasinglulu pmu_set_power_domain(PD_VDU, pmu_pd_off); 349*91f16700Schasinglulu pmu_set_power_domain(PD_USB3, pmu_pd_off); 350*91f16700Schasinglulu pmu_set_power_domain(PD_EMMC, pmu_pd_off); 351*91f16700Schasinglulu pmu_set_power_domain(PD_VIO, pmu_pd_off); 352*91f16700Schasinglulu pmu_set_power_domain(PD_SD, pmu_pd_off); 353*91f16700Schasinglulu pmu_set_power_domain(PD_PERIHP, pmu_pd_off); 354*91f16700Schasinglulu clk_gate_con_restore(); 355*91f16700Schasinglulu } 356*91f16700Schasinglulu 357*91f16700Schasinglulu static void pmu_power_domains_resume(void) 358*91f16700Schasinglulu { 359*91f16700Schasinglulu clk_gate_con_save(); 360*91f16700Schasinglulu clk_gate_con_disable(); 361*91f16700Schasinglulu if (!(pmu_powerdomain_state & BIT(PD_VDU))) 362*91f16700Schasinglulu pmu_set_power_domain(PD_VDU, pmu_pd_on); 363*91f16700Schasinglulu if (!(pmu_powerdomain_state & BIT(PD_VCODEC))) 364*91f16700Schasinglulu pmu_set_power_domain(PD_VCODEC, pmu_pd_on); 365*91f16700Schasinglulu if (!(pmu_powerdomain_state & BIT(PD_RGA))) 366*91f16700Schasinglulu pmu_set_power_domain(PD_RGA, pmu_pd_on); 367*91f16700Schasinglulu if (!(pmu_powerdomain_state & BIT(PD_IEP))) 368*91f16700Schasinglulu pmu_set_power_domain(PD_IEP, pmu_pd_on); 369*91f16700Schasinglulu if (!(pmu_powerdomain_state & BIT(PD_EDP))) 370*91f16700Schasinglulu pmu_set_power_domain(PD_EDP, pmu_pd_on); 371*91f16700Schasinglulu if (!(pmu_powerdomain_state & BIT(PD_GMAC))) 372*91f16700Schasinglulu pmu_set_power_domain(PD_GMAC, pmu_pd_on); 373*91f16700Schasinglulu if (!(pmu_powerdomain_state & BIT(PD_SDIOAUDIO))) 374*91f16700Schasinglulu pmu_set_power_domain(PD_SDIOAUDIO, pmu_pd_on); 375*91f16700Schasinglulu if (!(pmu_powerdomain_state & BIT(PD_HDCP))) 376*91f16700Schasinglulu pmu_set_power_domain(PD_HDCP, pmu_pd_on); 377*91f16700Schasinglulu if (!(pmu_powerdomain_state & BIT(PD_ISP1))) 378*91f16700Schasinglulu pmu_set_power_domain(PD_ISP1, pmu_pd_on); 379*91f16700Schasinglulu if (!(pmu_powerdomain_state & BIT(PD_ISP0))) 380*91f16700Schasinglulu pmu_set_power_domain(PD_ISP0, pmu_pd_on); 381*91f16700Schasinglulu if (!(pmu_powerdomain_state & BIT(PD_VO))) 382*91f16700Schasinglulu pmu_set_power_domain(PD_VO, pmu_pd_on); 383*91f16700Schasinglulu if (!(pmu_powerdomain_state & BIT(PD_TCPD1))) 384*91f16700Schasinglulu pmu_set_power_domain(PD_TCPD1, pmu_pd_on); 385*91f16700Schasinglulu if (!(pmu_powerdomain_state & BIT(PD_TCPD0))) 386*91f16700Schasinglulu pmu_set_power_domain(PD_TCPD0, pmu_pd_on); 387*91f16700Schasinglulu if (!(pmu_powerdomain_state & BIT(PD_GPU))) 388*91f16700Schasinglulu pmu_set_power_domain(PD_GPU, pmu_pd_on); 389*91f16700Schasinglulu if (!(pmu_powerdomain_state & BIT(PD_USB3))) 390*91f16700Schasinglulu pmu_set_power_domain(PD_USB3, pmu_pd_on); 391*91f16700Schasinglulu if (!(pmu_powerdomain_state & BIT(PD_EMMC))) 392*91f16700Schasinglulu pmu_set_power_domain(PD_EMMC, pmu_pd_on); 393*91f16700Schasinglulu if (!(pmu_powerdomain_state & BIT(PD_VIO))) 394*91f16700Schasinglulu pmu_set_power_domain(PD_VIO, pmu_pd_on); 395*91f16700Schasinglulu if (!(pmu_powerdomain_state & BIT(PD_SD))) 396*91f16700Schasinglulu pmu_set_power_domain(PD_SD, pmu_pd_on); 397*91f16700Schasinglulu if (!(pmu_powerdomain_state & BIT(PD_PERIHP))) 398*91f16700Schasinglulu pmu_set_power_domain(PD_PERIHP, pmu_pd_on); 399*91f16700Schasinglulu qos_restore(); 400*91f16700Schasinglulu clk_gate_con_restore(); 401*91f16700Schasinglulu } 402*91f16700Schasinglulu 403*91f16700Schasinglulu void pmu_power_domains_on(void) 404*91f16700Schasinglulu { 405*91f16700Schasinglulu clk_gate_con_disable(); 406*91f16700Schasinglulu pmu_set_power_domain(PD_VDU, pmu_pd_on); 407*91f16700Schasinglulu pmu_set_power_domain(PD_VCODEC, pmu_pd_on); 408*91f16700Schasinglulu pmu_set_power_domain(PD_RGA, pmu_pd_on); 409*91f16700Schasinglulu pmu_set_power_domain(PD_IEP, pmu_pd_on); 410*91f16700Schasinglulu pmu_set_power_domain(PD_EDP, pmu_pd_on); 411*91f16700Schasinglulu pmu_set_power_domain(PD_GMAC, pmu_pd_on); 412*91f16700Schasinglulu pmu_set_power_domain(PD_SDIOAUDIO, pmu_pd_on); 413*91f16700Schasinglulu pmu_set_power_domain(PD_HDCP, pmu_pd_on); 414*91f16700Schasinglulu pmu_set_power_domain(PD_ISP1, pmu_pd_on); 415*91f16700Schasinglulu pmu_set_power_domain(PD_ISP0, pmu_pd_on); 416*91f16700Schasinglulu pmu_set_power_domain(PD_VO, pmu_pd_on); 417*91f16700Schasinglulu pmu_set_power_domain(PD_TCPD1, pmu_pd_on); 418*91f16700Schasinglulu pmu_set_power_domain(PD_TCPD0, pmu_pd_on); 419*91f16700Schasinglulu pmu_set_power_domain(PD_GPU, pmu_pd_on); 420*91f16700Schasinglulu } 421*91f16700Schasinglulu 422*91f16700Schasinglulu void rk3399_flush_l2_b(void) 423*91f16700Schasinglulu { 424*91f16700Schasinglulu uint32_t wait_cnt = 0; 425*91f16700Schasinglulu 426*91f16700Schasinglulu mmio_setbits_32(PMU_BASE + PMU_SFT_CON, BIT(L2_FLUSH_REQ_CLUSTER_B)); 427*91f16700Schasinglulu dsb(); 428*91f16700Schasinglulu 429*91f16700Schasinglulu /* 430*91f16700Schasinglulu * The Big cluster flush L2 cache took ~4ms by default, give 10ms for 431*91f16700Schasinglulu * the enough margin. 432*91f16700Schasinglulu */ 433*91f16700Schasinglulu while (!(mmio_read_32(PMU_BASE + PMU_CORE_PWR_ST) & 434*91f16700Schasinglulu BIT(L2_FLUSHDONE_CLUSTER_B))) { 435*91f16700Schasinglulu wait_cnt++; 436*91f16700Schasinglulu udelay(10); 437*91f16700Schasinglulu if (wait_cnt == 10000 / 10) 438*91f16700Schasinglulu WARN("L2 cache flush on suspend took longer than 10ms\n"); 439*91f16700Schasinglulu } 440*91f16700Schasinglulu 441*91f16700Schasinglulu mmio_clrbits_32(PMU_BASE + PMU_SFT_CON, BIT(L2_FLUSH_REQ_CLUSTER_B)); 442*91f16700Schasinglulu } 443*91f16700Schasinglulu 444*91f16700Schasinglulu static void pmu_scu_b_pwrdn(void) 445*91f16700Schasinglulu { 446*91f16700Schasinglulu uint32_t wait_cnt = 0; 447*91f16700Schasinglulu 448*91f16700Schasinglulu if ((mmio_read_32(PMU_BASE + PMU_PWRDN_ST) & 449*91f16700Schasinglulu (BIT(PMU_A72_B0_PWRDWN_ST) | BIT(PMU_A72_B1_PWRDWN_ST))) != 450*91f16700Schasinglulu (BIT(PMU_A72_B0_PWRDWN_ST) | BIT(PMU_A72_B1_PWRDWN_ST))) { 451*91f16700Schasinglulu ERROR("%s: not all cpus is off\n", __func__); 452*91f16700Schasinglulu return; 453*91f16700Schasinglulu } 454*91f16700Schasinglulu 455*91f16700Schasinglulu rk3399_flush_l2_b(); 456*91f16700Schasinglulu 457*91f16700Schasinglulu mmio_setbits_32(PMU_BASE + PMU_SFT_CON, BIT(ACINACTM_CLUSTER_B_CFG)); 458*91f16700Schasinglulu 459*91f16700Schasinglulu while (!(mmio_read_32(PMU_BASE + PMU_CORE_PWR_ST) & 460*91f16700Schasinglulu BIT(STANDBY_BY_WFIL2_CLUSTER_B))) { 461*91f16700Schasinglulu wait_cnt++; 462*91f16700Schasinglulu udelay(1); 463*91f16700Schasinglulu if (wait_cnt >= MAX_WAIT_COUNT) 464*91f16700Schasinglulu ERROR("%s:wait cluster-b l2(%x)\n", __func__, 465*91f16700Schasinglulu mmio_read_32(PMU_BASE + PMU_CORE_PWR_ST)); 466*91f16700Schasinglulu } 467*91f16700Schasinglulu } 468*91f16700Schasinglulu 469*91f16700Schasinglulu static void pmu_scu_b_pwrup(void) 470*91f16700Schasinglulu { 471*91f16700Schasinglulu mmio_clrbits_32(PMU_BASE + PMU_SFT_CON, BIT(ACINACTM_CLUSTER_B_CFG)); 472*91f16700Schasinglulu } 473*91f16700Schasinglulu 474*91f16700Schasinglulu static inline uint32_t get_cpus_pwr_domain_cfg_info(uint32_t cpu_id) 475*91f16700Schasinglulu { 476*91f16700Schasinglulu assert(cpu_id < PLATFORM_CORE_COUNT); 477*91f16700Schasinglulu return core_pm_cfg_info[cpu_id]; 478*91f16700Schasinglulu } 479*91f16700Schasinglulu 480*91f16700Schasinglulu static inline void set_cpus_pwr_domain_cfg_info(uint32_t cpu_id, uint32_t value) 481*91f16700Schasinglulu { 482*91f16700Schasinglulu assert(cpu_id < PLATFORM_CORE_COUNT); 483*91f16700Schasinglulu core_pm_cfg_info[cpu_id] = value; 484*91f16700Schasinglulu #if !USE_COHERENT_MEM 485*91f16700Schasinglulu flush_dcache_range((uintptr_t)&core_pm_cfg_info[cpu_id], 486*91f16700Schasinglulu sizeof(uint32_t)); 487*91f16700Schasinglulu #endif 488*91f16700Schasinglulu } 489*91f16700Schasinglulu 490*91f16700Schasinglulu static int cpus_power_domain_on(uint32_t cpu_id) 491*91f16700Schasinglulu { 492*91f16700Schasinglulu uint32_t cfg_info; 493*91f16700Schasinglulu uint32_t cpu_pd = PD_CPUL0 + cpu_id; 494*91f16700Schasinglulu /* 495*91f16700Schasinglulu * There are two ways to powering on or off on core. 496*91f16700Schasinglulu * 1) Control it power domain into on or off in PMU_PWRDN_CON reg 497*91f16700Schasinglulu * 2) Enable the core power manage in PMU_CORE_PM_CON reg, 498*91f16700Schasinglulu * then, if the core enter into wfi, it power domain will be 499*91f16700Schasinglulu * powered off automatically. 500*91f16700Schasinglulu */ 501*91f16700Schasinglulu 502*91f16700Schasinglulu cfg_info = get_cpus_pwr_domain_cfg_info(cpu_id); 503*91f16700Schasinglulu 504*91f16700Schasinglulu if (cfg_info == core_pwr_pd) { 505*91f16700Schasinglulu /* disable core_pm cfg */ 506*91f16700Schasinglulu mmio_write_32(PMU_BASE + PMU_CORE_PM_CON(cpu_id), 507*91f16700Schasinglulu CORES_PM_DISABLE); 508*91f16700Schasinglulu /* if the cores have be on, power off it firstly */ 509*91f16700Schasinglulu if (pmu_power_domain_st(cpu_pd) == pmu_pd_on) { 510*91f16700Schasinglulu mmio_write_32(PMU_BASE + PMU_CORE_PM_CON(cpu_id), 0); 511*91f16700Schasinglulu pmu_power_domain_ctr(cpu_pd, pmu_pd_off); 512*91f16700Schasinglulu } 513*91f16700Schasinglulu 514*91f16700Schasinglulu pmu_power_domain_ctr(cpu_pd, pmu_pd_on); 515*91f16700Schasinglulu } else { 516*91f16700Schasinglulu if (pmu_power_domain_st(cpu_pd) == pmu_pd_on) { 517*91f16700Schasinglulu WARN("%s: cpu%d is not in off,!\n", __func__, cpu_id); 518*91f16700Schasinglulu return -EINVAL; 519*91f16700Schasinglulu } 520*91f16700Schasinglulu 521*91f16700Schasinglulu mmio_write_32(PMU_BASE + PMU_CORE_PM_CON(cpu_id), 522*91f16700Schasinglulu BIT(core_pm_sft_wakeup_en)); 523*91f16700Schasinglulu dsb(); 524*91f16700Schasinglulu } 525*91f16700Schasinglulu 526*91f16700Schasinglulu return 0; 527*91f16700Schasinglulu } 528*91f16700Schasinglulu 529*91f16700Schasinglulu static int cpus_power_domain_off(uint32_t cpu_id, uint32_t pd_cfg) 530*91f16700Schasinglulu { 531*91f16700Schasinglulu uint32_t cpu_pd; 532*91f16700Schasinglulu uint32_t core_pm_value; 533*91f16700Schasinglulu 534*91f16700Schasinglulu cpu_pd = PD_CPUL0 + cpu_id; 535*91f16700Schasinglulu if (pmu_power_domain_st(cpu_pd) == pmu_pd_off) 536*91f16700Schasinglulu return 0; 537*91f16700Schasinglulu 538*91f16700Schasinglulu if (pd_cfg == core_pwr_pd) { 539*91f16700Schasinglulu if (check_cpu_wfie(cpu_id, CKECK_WFEI_MSK)) 540*91f16700Schasinglulu return -EINVAL; 541*91f16700Schasinglulu 542*91f16700Schasinglulu /* disable core_pm cfg */ 543*91f16700Schasinglulu mmio_write_32(PMU_BASE + PMU_CORE_PM_CON(cpu_id), 544*91f16700Schasinglulu CORES_PM_DISABLE); 545*91f16700Schasinglulu 546*91f16700Schasinglulu set_cpus_pwr_domain_cfg_info(cpu_id, pd_cfg); 547*91f16700Schasinglulu pmu_power_domain_ctr(cpu_pd, pmu_pd_off); 548*91f16700Schasinglulu } else { 549*91f16700Schasinglulu set_cpus_pwr_domain_cfg_info(cpu_id, pd_cfg); 550*91f16700Schasinglulu 551*91f16700Schasinglulu core_pm_value = BIT(core_pm_en); 552*91f16700Schasinglulu if (pd_cfg == core_pwr_wfi_int) 553*91f16700Schasinglulu core_pm_value |= BIT(core_pm_int_wakeup_en); 554*91f16700Schasinglulu mmio_write_32(PMU_BASE + PMU_CORE_PM_CON(cpu_id), 555*91f16700Schasinglulu core_pm_value); 556*91f16700Schasinglulu dsb(); 557*91f16700Schasinglulu } 558*91f16700Schasinglulu 559*91f16700Schasinglulu return 0; 560*91f16700Schasinglulu } 561*91f16700Schasinglulu 562*91f16700Schasinglulu static inline void clst_pwr_domain_suspend(plat_local_state_t lvl_state) 563*91f16700Schasinglulu { 564*91f16700Schasinglulu uint32_t cpu_id = plat_my_core_pos(); 565*91f16700Schasinglulu uint32_t pll_id, clst_st_msk, clst_st_chk_msk, pmu_st; 566*91f16700Schasinglulu 567*91f16700Schasinglulu assert(cpu_id < PLATFORM_CORE_COUNT); 568*91f16700Schasinglulu 569*91f16700Schasinglulu if (lvl_state == PLAT_MAX_OFF_STATE) { 570*91f16700Schasinglulu if (cpu_id < PLATFORM_CLUSTER0_CORE_COUNT) { 571*91f16700Schasinglulu pll_id = ALPLL_ID; 572*91f16700Schasinglulu clst_st_msk = CLST_L_CPUS_MSK; 573*91f16700Schasinglulu } else { 574*91f16700Schasinglulu pll_id = ABPLL_ID; 575*91f16700Schasinglulu clst_st_msk = CLST_B_CPUS_MSK << 576*91f16700Schasinglulu PLATFORM_CLUSTER0_CORE_COUNT; 577*91f16700Schasinglulu } 578*91f16700Schasinglulu 579*91f16700Schasinglulu clst_st_chk_msk = clst_st_msk & ~(BIT(cpu_id)); 580*91f16700Schasinglulu 581*91f16700Schasinglulu pmu_st = mmio_read_32(PMU_BASE + PMU_PWRDN_ST); 582*91f16700Schasinglulu 583*91f16700Schasinglulu pmu_st &= clst_st_msk; 584*91f16700Schasinglulu 585*91f16700Schasinglulu if (pmu_st == clst_st_chk_msk) { 586*91f16700Schasinglulu mmio_write_32(CRU_BASE + CRU_PLL_CON(pll_id, 3), 587*91f16700Schasinglulu PLL_SLOW_MODE); 588*91f16700Schasinglulu 589*91f16700Schasinglulu clst_warmboot_data[pll_id] = PMU_CLST_RET; 590*91f16700Schasinglulu 591*91f16700Schasinglulu pmu_st = mmio_read_32(PMU_BASE + PMU_PWRDN_ST); 592*91f16700Schasinglulu pmu_st &= clst_st_msk; 593*91f16700Schasinglulu if (pmu_st == clst_st_chk_msk) 594*91f16700Schasinglulu return; 595*91f16700Schasinglulu /* 596*91f16700Schasinglulu * it is mean that others cpu is up again, 597*91f16700Schasinglulu * we must resume the cfg at once. 598*91f16700Schasinglulu */ 599*91f16700Schasinglulu mmio_write_32(CRU_BASE + CRU_PLL_CON(pll_id, 3), 600*91f16700Schasinglulu PLL_NOMAL_MODE); 601*91f16700Schasinglulu clst_warmboot_data[pll_id] = 0; 602*91f16700Schasinglulu } 603*91f16700Schasinglulu } 604*91f16700Schasinglulu } 605*91f16700Schasinglulu 606*91f16700Schasinglulu static int clst_pwr_domain_resume(plat_local_state_t lvl_state) 607*91f16700Schasinglulu { 608*91f16700Schasinglulu uint32_t cpu_id = plat_my_core_pos(); 609*91f16700Schasinglulu uint32_t pll_id, pll_st; 610*91f16700Schasinglulu 611*91f16700Schasinglulu assert(cpu_id < PLATFORM_CORE_COUNT); 612*91f16700Schasinglulu 613*91f16700Schasinglulu if (lvl_state == PLAT_MAX_OFF_STATE) { 614*91f16700Schasinglulu if (cpu_id < PLATFORM_CLUSTER0_CORE_COUNT) 615*91f16700Schasinglulu pll_id = ALPLL_ID; 616*91f16700Schasinglulu else 617*91f16700Schasinglulu pll_id = ABPLL_ID; 618*91f16700Schasinglulu 619*91f16700Schasinglulu pll_st = mmio_read_32(CRU_BASE + CRU_PLL_CON(pll_id, 3)) >> 620*91f16700Schasinglulu PLL_MODE_SHIFT; 621*91f16700Schasinglulu 622*91f16700Schasinglulu if (pll_st != NORMAL_MODE) { 623*91f16700Schasinglulu WARN("%s: clst (%d) is in error mode (%d)\n", 624*91f16700Schasinglulu __func__, pll_id, pll_st); 625*91f16700Schasinglulu return -1; 626*91f16700Schasinglulu } 627*91f16700Schasinglulu } 628*91f16700Schasinglulu 629*91f16700Schasinglulu return 0; 630*91f16700Schasinglulu } 631*91f16700Schasinglulu 632*91f16700Schasinglulu static void nonboot_cpus_off(void) 633*91f16700Schasinglulu { 634*91f16700Schasinglulu uint32_t boot_cpu, cpu; 635*91f16700Schasinglulu 636*91f16700Schasinglulu boot_cpu = plat_my_core_pos(); 637*91f16700Schasinglulu 638*91f16700Schasinglulu /* turn off noboot cpus */ 639*91f16700Schasinglulu for (cpu = 0; cpu < PLATFORM_CORE_COUNT; cpu++) { 640*91f16700Schasinglulu if (cpu == boot_cpu) 641*91f16700Schasinglulu continue; 642*91f16700Schasinglulu cpus_power_domain_off(cpu, core_pwr_pd); 643*91f16700Schasinglulu } 644*91f16700Schasinglulu } 645*91f16700Schasinglulu 646*91f16700Schasinglulu int rockchip_soc_cores_pwr_dm_on(unsigned long mpidr, uint64_t entrypoint) 647*91f16700Schasinglulu { 648*91f16700Schasinglulu uint32_t cpu_id = plat_core_pos_by_mpidr(mpidr); 649*91f16700Schasinglulu 650*91f16700Schasinglulu assert(cpu_id < PLATFORM_CORE_COUNT); 651*91f16700Schasinglulu assert(cpuson_flags[cpu_id] == 0); 652*91f16700Schasinglulu cpuson_flags[cpu_id] = PMU_CPU_HOTPLUG; 653*91f16700Schasinglulu cpuson_entry_point[cpu_id] = entrypoint; 654*91f16700Schasinglulu dsb(); 655*91f16700Schasinglulu 656*91f16700Schasinglulu cpus_power_domain_on(cpu_id); 657*91f16700Schasinglulu 658*91f16700Schasinglulu return PSCI_E_SUCCESS; 659*91f16700Schasinglulu } 660*91f16700Schasinglulu 661*91f16700Schasinglulu int rockchip_soc_cores_pwr_dm_off(void) 662*91f16700Schasinglulu { 663*91f16700Schasinglulu uint32_t cpu_id = plat_my_core_pos(); 664*91f16700Schasinglulu 665*91f16700Schasinglulu cpus_power_domain_off(cpu_id, core_pwr_wfi); 666*91f16700Schasinglulu 667*91f16700Schasinglulu return PSCI_E_SUCCESS; 668*91f16700Schasinglulu } 669*91f16700Schasinglulu 670*91f16700Schasinglulu int rockchip_soc_hlvl_pwr_dm_off(uint32_t lvl, 671*91f16700Schasinglulu plat_local_state_t lvl_state) 672*91f16700Schasinglulu { 673*91f16700Schasinglulu if (lvl == MPIDR_AFFLVL1) { 674*91f16700Schasinglulu clst_pwr_domain_suspend(lvl_state); 675*91f16700Schasinglulu } 676*91f16700Schasinglulu 677*91f16700Schasinglulu return PSCI_E_SUCCESS; 678*91f16700Schasinglulu } 679*91f16700Schasinglulu 680*91f16700Schasinglulu int rockchip_soc_cores_pwr_dm_suspend(void) 681*91f16700Schasinglulu { 682*91f16700Schasinglulu uint32_t cpu_id = plat_my_core_pos(); 683*91f16700Schasinglulu 684*91f16700Schasinglulu assert(cpu_id < PLATFORM_CORE_COUNT); 685*91f16700Schasinglulu assert(cpuson_flags[cpu_id] == 0); 686*91f16700Schasinglulu cpuson_flags[cpu_id] = PMU_CPU_AUTO_PWRDN; 687*91f16700Schasinglulu cpuson_entry_point[cpu_id] = plat_get_sec_entrypoint(); 688*91f16700Schasinglulu dsb(); 689*91f16700Schasinglulu 690*91f16700Schasinglulu cpus_power_domain_off(cpu_id, core_pwr_wfi_int); 691*91f16700Schasinglulu 692*91f16700Schasinglulu return PSCI_E_SUCCESS; 693*91f16700Schasinglulu } 694*91f16700Schasinglulu 695*91f16700Schasinglulu int rockchip_soc_hlvl_pwr_dm_suspend(uint32_t lvl, plat_local_state_t lvl_state) 696*91f16700Schasinglulu { 697*91f16700Schasinglulu if (lvl == MPIDR_AFFLVL1) { 698*91f16700Schasinglulu clst_pwr_domain_suspend(lvl_state); 699*91f16700Schasinglulu } 700*91f16700Schasinglulu 701*91f16700Schasinglulu return PSCI_E_SUCCESS; 702*91f16700Schasinglulu } 703*91f16700Schasinglulu 704*91f16700Schasinglulu int rockchip_soc_cores_pwr_dm_on_finish(void) 705*91f16700Schasinglulu { 706*91f16700Schasinglulu uint32_t cpu_id = plat_my_core_pos(); 707*91f16700Schasinglulu 708*91f16700Schasinglulu mmio_write_32(PMU_BASE + PMU_CORE_PM_CON(cpu_id), 709*91f16700Schasinglulu CORES_PM_DISABLE); 710*91f16700Schasinglulu return PSCI_E_SUCCESS; 711*91f16700Schasinglulu } 712*91f16700Schasinglulu 713*91f16700Schasinglulu int rockchip_soc_hlvl_pwr_dm_on_finish(uint32_t lvl, 714*91f16700Schasinglulu plat_local_state_t lvl_state) 715*91f16700Schasinglulu { 716*91f16700Schasinglulu if (lvl == MPIDR_AFFLVL1) { 717*91f16700Schasinglulu clst_pwr_domain_resume(lvl_state); 718*91f16700Schasinglulu } 719*91f16700Schasinglulu 720*91f16700Schasinglulu return PSCI_E_SUCCESS; 721*91f16700Schasinglulu } 722*91f16700Schasinglulu 723*91f16700Schasinglulu int rockchip_soc_cores_pwr_dm_resume(void) 724*91f16700Schasinglulu { 725*91f16700Schasinglulu uint32_t cpu_id = plat_my_core_pos(); 726*91f16700Schasinglulu 727*91f16700Schasinglulu /* Disable core_pm */ 728*91f16700Schasinglulu mmio_write_32(PMU_BASE + PMU_CORE_PM_CON(cpu_id), CORES_PM_DISABLE); 729*91f16700Schasinglulu 730*91f16700Schasinglulu return PSCI_E_SUCCESS; 731*91f16700Schasinglulu } 732*91f16700Schasinglulu 733*91f16700Schasinglulu int rockchip_soc_hlvl_pwr_dm_resume(uint32_t lvl, plat_local_state_t lvl_state) 734*91f16700Schasinglulu { 735*91f16700Schasinglulu if (lvl == MPIDR_AFFLVL1) { 736*91f16700Schasinglulu clst_pwr_domain_resume(lvl_state); 737*91f16700Schasinglulu } 738*91f16700Schasinglulu 739*91f16700Schasinglulu return PSCI_E_SUCCESS; 740*91f16700Schasinglulu } 741*91f16700Schasinglulu 742*91f16700Schasinglulu /** 743*91f16700Schasinglulu * init_pmu_counts - Init timing counts in the PMU register area 744*91f16700Schasinglulu * 745*91f16700Schasinglulu * At various points when we power up or down parts of the system we need 746*91f16700Schasinglulu * a delay to wait for power / clocks to become stable. The PMU has counters 747*91f16700Schasinglulu * to help software do the delay properly. Basically, it works like this: 748*91f16700Schasinglulu * - Software sets up counter values 749*91f16700Schasinglulu * - When software turns on something in the PMU, the counter kicks off 750*91f16700Schasinglulu * - The hardware sets a bit automatically when the counter has finished and 751*91f16700Schasinglulu * software knows that the initialization is done. 752*91f16700Schasinglulu * 753*91f16700Schasinglulu * It's software's job to setup these counters. The hardware power on default 754*91f16700Schasinglulu * for these settings is conservative, setting everything to 0x5dc0 755*91f16700Schasinglulu * (750 ms in 32 kHz counts or 1 ms in 24 MHz counts). 756*91f16700Schasinglulu * 757*91f16700Schasinglulu * Note that some of these counters are only really used at suspend/resume 758*91f16700Schasinglulu * time (for instance, that's the only time we turn off/on the oscillator) and 759*91f16700Schasinglulu * others are used during normal runtime (like turning on/off a CPU or GPU) but 760*91f16700Schasinglulu * it doesn't hurt to init everything at boot. 761*91f16700Schasinglulu * 762*91f16700Schasinglulu * Also note that these counters can run off the 32 kHz clock or the 24 MHz 763*91f16700Schasinglulu * clock. While the 24 MHz clock can give us more precision, it's not always 764*91f16700Schasinglulu * available (like when we turn the oscillator off at sleep time). The 765*91f16700Schasinglulu * pmu_use_lf (lf: low freq) is available in power mode. Current understanding 766*91f16700Schasinglulu * is that counts work like this: 767*91f16700Schasinglulu * IF (pmu_use_lf == 0) || (power_mode_en == 0) 768*91f16700Schasinglulu * use the 24M OSC for counts 769*91f16700Schasinglulu * ELSE 770*91f16700Schasinglulu * use the 32K OSC for counts 771*91f16700Schasinglulu * 772*91f16700Schasinglulu * Notes: 773*91f16700Schasinglulu * - There is a separate bit for the PMU called PMU_24M_EN_CFG. At the moment 774*91f16700Schasinglulu * we always keep that 0. This apparently choose between using the PLL as 775*91f16700Schasinglulu * the source for the PMU vs. the 24M clock. If we ever set it to 1 we 776*91f16700Schasinglulu * should consider how it affects these counts (if at all). 777*91f16700Schasinglulu * - The power_mode_en is documented to auto-clear automatically when we leave 778*91f16700Schasinglulu * "power mode". That's why most clocks are on 24M. Only timings used when 779*91f16700Schasinglulu * in "power mode" are 32k. 780*91f16700Schasinglulu * - In some cases the kernel may override these counts. 781*91f16700Schasinglulu * 782*91f16700Schasinglulu * The PMU_STABLE_CNT / PMU_OSC_CNT / PMU_PLLLOCK_CNT are important CNTs 783*91f16700Schasinglulu * in power mode, we need to ensure that they are available. 784*91f16700Schasinglulu */ 785*91f16700Schasinglulu static void init_pmu_counts(void) 786*91f16700Schasinglulu { 787*91f16700Schasinglulu /* COUNTS FOR INSIDE POWER MODE */ 788*91f16700Schasinglulu 789*91f16700Schasinglulu /* 790*91f16700Schasinglulu * From limited testing, need PMU stable >= 2ms, but go overkill 791*91f16700Schasinglulu * and choose 30 ms to match testing on past SoCs. Also let 792*91f16700Schasinglulu * OSC have 30 ms for stabilization. 793*91f16700Schasinglulu */ 794*91f16700Schasinglulu mmio_write_32(PMU_BASE + PMU_STABLE_CNT, CYCL_32K_CNT_MS(30)); 795*91f16700Schasinglulu mmio_write_32(PMU_BASE + PMU_OSC_CNT, CYCL_32K_CNT_MS(30)); 796*91f16700Schasinglulu 797*91f16700Schasinglulu /* Unclear what these should be; try 3 ms */ 798*91f16700Schasinglulu mmio_write_32(PMU_BASE + PMU_WAKEUP_RST_CLR_CNT, CYCL_32K_CNT_MS(3)); 799*91f16700Schasinglulu 800*91f16700Schasinglulu /* Unclear what this should be, but set the default explicitly */ 801*91f16700Schasinglulu mmio_write_32(PMU_BASE + PMU_TIMEOUT_CNT, 0x5dc0); 802*91f16700Schasinglulu 803*91f16700Schasinglulu /* COUNTS FOR OUTSIDE POWER MODE */ 804*91f16700Schasinglulu 805*91f16700Schasinglulu /* Put something sorta conservative here until we know better */ 806*91f16700Schasinglulu mmio_write_32(PMU_BASE + PMU_PLLLOCK_CNT, CYCL_24M_CNT_MS(3)); 807*91f16700Schasinglulu mmio_write_32(PMU_BASE + PMU_DDRIO_PWRON_CNT, CYCL_24M_CNT_MS(1)); 808*91f16700Schasinglulu mmio_write_32(PMU_BASE + PMU_CENTER_PWRDN_CNT, CYCL_24M_CNT_MS(1)); 809*91f16700Schasinglulu mmio_write_32(PMU_BASE + PMU_CENTER_PWRUP_CNT, CYCL_24M_CNT_MS(1)); 810*91f16700Schasinglulu 811*91f16700Schasinglulu /* 812*91f16700Schasinglulu * when we enable PMU_CLR_PERILP, it will shut down the SRAM, but 813*91f16700Schasinglulu * M0 code run in SRAM, and we need it to check whether cpu enter 814*91f16700Schasinglulu * FSM status, so we must wait M0 finish their code and enter WFI, 815*91f16700Schasinglulu * then we can shutdown SRAM, according FSM order: 816*91f16700Schasinglulu * ST_NORMAL->..->ST_SCU_L_PWRDN->..->ST_CENTER_PWRDN->ST_PERILP_PWRDN 817*91f16700Schasinglulu * we can add delay when shutdown ST_SCU_L_PWRDN to guarantee M0 get 818*91f16700Schasinglulu * the FSM status and enter WFI, then enable PMU_CLR_PERILP. 819*91f16700Schasinglulu */ 820*91f16700Schasinglulu mmio_write_32(PMU_BASE + PMU_SCU_L_PWRDN_CNT, CYCL_24M_CNT_MS(5)); 821*91f16700Schasinglulu mmio_write_32(PMU_BASE + PMU_SCU_L_PWRUP_CNT, CYCL_24M_CNT_US(1)); 822*91f16700Schasinglulu 823*91f16700Schasinglulu /* 824*91f16700Schasinglulu * Set CPU/GPU to 1 us. 825*91f16700Schasinglulu * 826*91f16700Schasinglulu * NOTE: Even though ATF doesn't configure the GPU we'll still setup 827*91f16700Schasinglulu * counts here. After all ATF controls all these other bits and also 828*91f16700Schasinglulu * chooses which clock these counters use. 829*91f16700Schasinglulu */ 830*91f16700Schasinglulu mmio_write_32(PMU_BASE + PMU_SCU_B_PWRDN_CNT, CYCL_24M_CNT_US(1)); 831*91f16700Schasinglulu mmio_write_32(PMU_BASE + PMU_SCU_B_PWRUP_CNT, CYCL_24M_CNT_US(1)); 832*91f16700Schasinglulu mmio_write_32(PMU_BASE + PMU_GPU_PWRDN_CNT, CYCL_24M_CNT_US(1)); 833*91f16700Schasinglulu mmio_write_32(PMU_BASE + PMU_GPU_PWRUP_CNT, CYCL_24M_CNT_US(1)); 834*91f16700Schasinglulu } 835*91f16700Schasinglulu 836*91f16700Schasinglulu static uint32_t clk_ddrc_save; 837*91f16700Schasinglulu 838*91f16700Schasinglulu static void sys_slp_config(void) 839*91f16700Schasinglulu { 840*91f16700Schasinglulu uint32_t slp_mode_cfg = 0; 841*91f16700Schasinglulu 842*91f16700Schasinglulu /* keep enabling clk_ddrc_bpll_src_en gate for DDRC */ 843*91f16700Schasinglulu clk_ddrc_save = mmio_read_32(CRU_BASE + CRU_CLKGATE_CON(3)); 844*91f16700Schasinglulu mmio_write_32(CRU_BASE + CRU_CLKGATE_CON(3), WMSK_BIT(1)); 845*91f16700Schasinglulu 846*91f16700Schasinglulu prepare_abpll_for_ddrctrl(); 847*91f16700Schasinglulu sram_func_set_ddrctl_pll(ABPLL_ID); 848*91f16700Schasinglulu 849*91f16700Schasinglulu mmio_write_32(GRF_BASE + GRF_SOC_CON4, CCI_FORCE_WAKEUP); 850*91f16700Schasinglulu mmio_write_32(PMU_BASE + PMU_CCI500_CON, 851*91f16700Schasinglulu BIT_WITH_WMSK(PMU_CLR_PREQ_CCI500_HW) | 852*91f16700Schasinglulu BIT_WITH_WMSK(PMU_CLR_QREQ_CCI500_HW) | 853*91f16700Schasinglulu BIT_WITH_WMSK(PMU_QGATING_CCI500_CFG)); 854*91f16700Schasinglulu 855*91f16700Schasinglulu mmio_write_32(PMU_BASE + PMU_ADB400_CON, 856*91f16700Schasinglulu BIT_WITH_WMSK(PMU_CLR_CORE_L_HW) | 857*91f16700Schasinglulu BIT_WITH_WMSK(PMU_CLR_CORE_L_2GIC_HW) | 858*91f16700Schasinglulu BIT_WITH_WMSK(PMU_CLR_GIC2_CORE_L_HW)); 859*91f16700Schasinglulu 860*91f16700Schasinglulu slp_mode_cfg = BIT(PMU_PWR_MODE_EN) | 861*91f16700Schasinglulu BIT(PMU_WKUP_RST_EN) | 862*91f16700Schasinglulu BIT(PMU_INPUT_CLAMP_EN) | 863*91f16700Schasinglulu BIT(PMU_POWER_OFF_REQ_CFG) | 864*91f16700Schasinglulu BIT(PMU_CPU0_PD_EN) | 865*91f16700Schasinglulu BIT(PMU_L2_FLUSH_EN) | 866*91f16700Schasinglulu BIT(PMU_L2_IDLE_EN) | 867*91f16700Schasinglulu BIT(PMU_SCU_PD_EN) | 868*91f16700Schasinglulu BIT(PMU_CCI_PD_EN) | 869*91f16700Schasinglulu BIT(PMU_CLK_CORE_SRC_GATE_EN) | 870*91f16700Schasinglulu BIT(PMU_ALIVE_USE_LF) | 871*91f16700Schasinglulu BIT(PMU_SREF0_ENTER_EN) | 872*91f16700Schasinglulu BIT(PMU_SREF1_ENTER_EN) | 873*91f16700Schasinglulu BIT(PMU_DDRC0_GATING_EN) | 874*91f16700Schasinglulu BIT(PMU_DDRC1_GATING_EN) | 875*91f16700Schasinglulu BIT(PMU_DDRIO0_RET_EN) | 876*91f16700Schasinglulu BIT(PMU_DDRIO0_RET_DE_REQ) | 877*91f16700Schasinglulu BIT(PMU_DDRIO1_RET_EN) | 878*91f16700Schasinglulu BIT(PMU_DDRIO1_RET_DE_REQ) | 879*91f16700Schasinglulu BIT(PMU_CENTER_PD_EN) | 880*91f16700Schasinglulu BIT(PMU_PERILP_PD_EN) | 881*91f16700Schasinglulu BIT(PMU_CLK_PERILP_SRC_GATE_EN) | 882*91f16700Schasinglulu BIT(PMU_PLL_PD_EN) | 883*91f16700Schasinglulu BIT(PMU_CLK_CENTER_SRC_GATE_EN) | 884*91f16700Schasinglulu BIT(PMU_OSC_DIS) | 885*91f16700Schasinglulu BIT(PMU_PMU_USE_LF); 886*91f16700Schasinglulu 887*91f16700Schasinglulu mmio_setbits_32(PMU_BASE + PMU_WKUP_CFG4, BIT(PMU_GPIO_WKUP_EN)); 888*91f16700Schasinglulu mmio_write_32(PMU_BASE + PMU_PWRMODE_CON, slp_mode_cfg); 889*91f16700Schasinglulu 890*91f16700Schasinglulu mmio_write_32(PMU_BASE + PMU_PLL_CON, PLL_PD_HW); 891*91f16700Schasinglulu mmio_write_32(PMUGRF_BASE + PMUGRF_SOC_CON0, EXTERNAL_32K); 892*91f16700Schasinglulu mmio_write_32(PMUGRF_BASE, IOMUX_CLK_32K); /* 32k iomux */ 893*91f16700Schasinglulu } 894*91f16700Schasinglulu 895*91f16700Schasinglulu static void set_hw_idle(uint32_t hw_idle) 896*91f16700Schasinglulu { 897*91f16700Schasinglulu mmio_setbits_32(PMU_BASE + PMU_BUS_CLR, hw_idle); 898*91f16700Schasinglulu } 899*91f16700Schasinglulu 900*91f16700Schasinglulu static void clr_hw_idle(uint32_t hw_idle) 901*91f16700Schasinglulu { 902*91f16700Schasinglulu mmio_clrbits_32(PMU_BASE + PMU_BUS_CLR, hw_idle); 903*91f16700Schasinglulu } 904*91f16700Schasinglulu 905*91f16700Schasinglulu static uint32_t iomux_status[12]; 906*91f16700Schasinglulu static uint32_t pull_mode_status[12]; 907*91f16700Schasinglulu static uint32_t gpio_direction[3]; 908*91f16700Schasinglulu static uint32_t gpio_2_4_clk_gate; 909*91f16700Schasinglulu 910*91f16700Schasinglulu static void suspend_apio(void) 911*91f16700Schasinglulu { 912*91f16700Schasinglulu struct bl_aux_rk_apio_info *suspend_apio; 913*91f16700Schasinglulu int i; 914*91f16700Schasinglulu 915*91f16700Schasinglulu suspend_apio = plat_get_rockchip_suspend_apio(); 916*91f16700Schasinglulu 917*91f16700Schasinglulu if (!suspend_apio) 918*91f16700Schasinglulu return; 919*91f16700Schasinglulu 920*91f16700Schasinglulu /* save gpio2 ~ gpio4 iomux and pull mode */ 921*91f16700Schasinglulu for (i = 0; i < 12; i++) { 922*91f16700Schasinglulu iomux_status[i] = mmio_read_32(GRF_BASE + 923*91f16700Schasinglulu GRF_GPIO2A_IOMUX + i * 4); 924*91f16700Schasinglulu pull_mode_status[i] = mmio_read_32(GRF_BASE + 925*91f16700Schasinglulu GRF_GPIO2A_P + i * 4); 926*91f16700Schasinglulu } 927*91f16700Schasinglulu 928*91f16700Schasinglulu /* store gpio2 ~ gpio4 clock gate state */ 929*91f16700Schasinglulu gpio_2_4_clk_gate = (mmio_read_32(CRU_BASE + CRU_CLKGATE_CON(31)) >> 930*91f16700Schasinglulu PCLK_GPIO2_GATE_SHIFT) & 0x07; 931*91f16700Schasinglulu 932*91f16700Schasinglulu /* enable gpio2 ~ gpio4 clock gate */ 933*91f16700Schasinglulu mmio_write_32(CRU_BASE + CRU_CLKGATE_CON(31), 934*91f16700Schasinglulu BITS_WITH_WMASK(0, 0x07, PCLK_GPIO2_GATE_SHIFT)); 935*91f16700Schasinglulu 936*91f16700Schasinglulu /* save gpio2 ~ gpio4 direction */ 937*91f16700Schasinglulu gpio_direction[0] = mmio_read_32(GPIO2_BASE + 0x04); 938*91f16700Schasinglulu gpio_direction[1] = mmio_read_32(GPIO3_BASE + 0x04); 939*91f16700Schasinglulu gpio_direction[2] = mmio_read_32(GPIO4_BASE + 0x04); 940*91f16700Schasinglulu 941*91f16700Schasinglulu /* apio1 charge gpio3a0 ~ gpio3c7 */ 942*91f16700Schasinglulu if (suspend_apio->apio1) { 943*91f16700Schasinglulu 944*91f16700Schasinglulu /* set gpio3a0 ~ gpio3c7 iomux to gpio */ 945*91f16700Schasinglulu mmio_write_32(GRF_BASE + GRF_GPIO3A_IOMUX, 946*91f16700Schasinglulu REG_SOC_WMSK | GRF_IOMUX_GPIO); 947*91f16700Schasinglulu mmio_write_32(GRF_BASE + GRF_GPIO3B_IOMUX, 948*91f16700Schasinglulu REG_SOC_WMSK | GRF_IOMUX_GPIO); 949*91f16700Schasinglulu mmio_write_32(GRF_BASE + GRF_GPIO3C_IOMUX, 950*91f16700Schasinglulu REG_SOC_WMSK | GRF_IOMUX_GPIO); 951*91f16700Schasinglulu 952*91f16700Schasinglulu /* set gpio3a0 ~ gpio3c7 pull mode to pull none */ 953*91f16700Schasinglulu mmio_write_32(GRF_BASE + GRF_GPIO3A_P, REG_SOC_WMSK | 0); 954*91f16700Schasinglulu mmio_write_32(GRF_BASE + GRF_GPIO3B_P, REG_SOC_WMSK | 0); 955*91f16700Schasinglulu mmio_write_32(GRF_BASE + GRF_GPIO3C_P, REG_SOC_WMSK | 0); 956*91f16700Schasinglulu 957*91f16700Schasinglulu /* set gpio3a0 ~ gpio3c7 to input */ 958*91f16700Schasinglulu mmio_clrbits_32(GPIO3_BASE + 0x04, 0x00ffffff); 959*91f16700Schasinglulu } 960*91f16700Schasinglulu 961*91f16700Schasinglulu /* apio2 charge gpio2a0 ~ gpio2b4 */ 962*91f16700Schasinglulu if (suspend_apio->apio2) { 963*91f16700Schasinglulu 964*91f16700Schasinglulu /* set gpio2a0 ~ gpio2b4 iomux to gpio */ 965*91f16700Schasinglulu mmio_write_32(GRF_BASE + GRF_GPIO2A_IOMUX, 966*91f16700Schasinglulu REG_SOC_WMSK | GRF_IOMUX_GPIO); 967*91f16700Schasinglulu mmio_write_32(GRF_BASE + GRF_GPIO2B_IOMUX, 968*91f16700Schasinglulu REG_SOC_WMSK | GRF_IOMUX_GPIO); 969*91f16700Schasinglulu 970*91f16700Schasinglulu /* set gpio2a0 ~ gpio2b4 pull mode to pull none */ 971*91f16700Schasinglulu mmio_write_32(GRF_BASE + GRF_GPIO2A_P, REG_SOC_WMSK | 0); 972*91f16700Schasinglulu mmio_write_32(GRF_BASE + GRF_GPIO2B_P, REG_SOC_WMSK | 0); 973*91f16700Schasinglulu 974*91f16700Schasinglulu /* set gpio2a0 ~ gpio2b4 to input */ 975*91f16700Schasinglulu mmio_clrbits_32(GPIO2_BASE + 0x04, 0x00001fff); 976*91f16700Schasinglulu } 977*91f16700Schasinglulu 978*91f16700Schasinglulu /* apio3 charge gpio2c0 ~ gpio2d4*/ 979*91f16700Schasinglulu if (suspend_apio->apio3) { 980*91f16700Schasinglulu 981*91f16700Schasinglulu /* set gpio2a0 ~ gpio2b4 iomux to gpio */ 982*91f16700Schasinglulu mmio_write_32(GRF_BASE + GRF_GPIO2C_IOMUX, 983*91f16700Schasinglulu REG_SOC_WMSK | GRF_IOMUX_GPIO); 984*91f16700Schasinglulu mmio_write_32(GRF_BASE + GRF_GPIO2D_IOMUX, 985*91f16700Schasinglulu REG_SOC_WMSK | GRF_IOMUX_GPIO); 986*91f16700Schasinglulu 987*91f16700Schasinglulu /* set gpio2c0 ~ gpio2d4 pull mode to pull none */ 988*91f16700Schasinglulu mmio_write_32(GRF_BASE + GRF_GPIO2C_P, REG_SOC_WMSK | 0); 989*91f16700Schasinglulu mmio_write_32(GRF_BASE + GRF_GPIO2D_P, REG_SOC_WMSK | 0); 990*91f16700Schasinglulu 991*91f16700Schasinglulu /* set gpio2c0 ~ gpio2d4 to input */ 992*91f16700Schasinglulu mmio_clrbits_32(GPIO2_BASE + 0x04, 0x1fff0000); 993*91f16700Schasinglulu } 994*91f16700Schasinglulu 995*91f16700Schasinglulu /* apio4 charge gpio4c0 ~ gpio4c7, gpio4d0 ~ gpio4d6 */ 996*91f16700Schasinglulu if (suspend_apio->apio4) { 997*91f16700Schasinglulu 998*91f16700Schasinglulu /* set gpio4c0 ~ gpio4d6 iomux to gpio */ 999*91f16700Schasinglulu mmio_write_32(GRF_BASE + GRF_GPIO4C_IOMUX, 1000*91f16700Schasinglulu REG_SOC_WMSK | GRF_IOMUX_GPIO); 1001*91f16700Schasinglulu mmio_write_32(GRF_BASE + GRF_GPIO4D_IOMUX, 1002*91f16700Schasinglulu REG_SOC_WMSK | GRF_IOMUX_GPIO); 1003*91f16700Schasinglulu 1004*91f16700Schasinglulu /* set gpio4c0 ~ gpio4d6 pull mode to pull none */ 1005*91f16700Schasinglulu mmio_write_32(GRF_BASE + GRF_GPIO4C_P, REG_SOC_WMSK | 0); 1006*91f16700Schasinglulu mmio_write_32(GRF_BASE + GRF_GPIO4D_P, REG_SOC_WMSK | 0); 1007*91f16700Schasinglulu 1008*91f16700Schasinglulu /* set gpio4c0 ~ gpio4d6 to input */ 1009*91f16700Schasinglulu mmio_clrbits_32(GPIO4_BASE + 0x04, 0x7fff0000); 1010*91f16700Schasinglulu } 1011*91f16700Schasinglulu 1012*91f16700Schasinglulu /* apio5 charge gpio3d0 ~ gpio3d7, gpio4a0 ~ gpio4a7*/ 1013*91f16700Schasinglulu if (suspend_apio->apio5) { 1014*91f16700Schasinglulu /* set gpio3d0 ~ gpio4a7 iomux to gpio */ 1015*91f16700Schasinglulu mmio_write_32(GRF_BASE + GRF_GPIO3D_IOMUX, 1016*91f16700Schasinglulu REG_SOC_WMSK | GRF_IOMUX_GPIO); 1017*91f16700Schasinglulu mmio_write_32(GRF_BASE + GRF_GPIO4A_IOMUX, 1018*91f16700Schasinglulu REG_SOC_WMSK | GRF_IOMUX_GPIO); 1019*91f16700Schasinglulu 1020*91f16700Schasinglulu /* set gpio3d0 ~ gpio4a7 pull mode to pull none */ 1021*91f16700Schasinglulu mmio_write_32(GRF_BASE + GRF_GPIO3D_P, REG_SOC_WMSK | 0); 1022*91f16700Schasinglulu mmio_write_32(GRF_BASE + GRF_GPIO4A_P, REG_SOC_WMSK | 0); 1023*91f16700Schasinglulu 1024*91f16700Schasinglulu /* set gpio4c0 ~ gpio4d6 to input */ 1025*91f16700Schasinglulu mmio_clrbits_32(GPIO3_BASE + 0x04, 0xff000000); 1026*91f16700Schasinglulu mmio_clrbits_32(GPIO4_BASE + 0x04, 0x000000ff); 1027*91f16700Schasinglulu } 1028*91f16700Schasinglulu } 1029*91f16700Schasinglulu 1030*91f16700Schasinglulu static void resume_apio(void) 1031*91f16700Schasinglulu { 1032*91f16700Schasinglulu struct bl_aux_rk_apio_info *suspend_apio; 1033*91f16700Schasinglulu int i; 1034*91f16700Schasinglulu 1035*91f16700Schasinglulu suspend_apio = plat_get_rockchip_suspend_apio(); 1036*91f16700Schasinglulu 1037*91f16700Schasinglulu if (!suspend_apio) 1038*91f16700Schasinglulu return; 1039*91f16700Schasinglulu 1040*91f16700Schasinglulu for (i = 0; i < 12; i++) { 1041*91f16700Schasinglulu mmio_write_32(GRF_BASE + GRF_GPIO2A_P + i * 4, 1042*91f16700Schasinglulu REG_SOC_WMSK | pull_mode_status[i]); 1043*91f16700Schasinglulu mmio_write_32(GRF_BASE + GRF_GPIO2A_IOMUX + i * 4, 1044*91f16700Schasinglulu REG_SOC_WMSK | iomux_status[i]); 1045*91f16700Schasinglulu } 1046*91f16700Schasinglulu 1047*91f16700Schasinglulu /* set gpio2 ~ gpio4 direction back to store value */ 1048*91f16700Schasinglulu mmio_write_32(GPIO2_BASE + 0x04, gpio_direction[0]); 1049*91f16700Schasinglulu mmio_write_32(GPIO3_BASE + 0x04, gpio_direction[1]); 1050*91f16700Schasinglulu mmio_write_32(GPIO4_BASE + 0x04, gpio_direction[2]); 1051*91f16700Schasinglulu 1052*91f16700Schasinglulu /* set gpio2 ~ gpio4 clock gate back to store value */ 1053*91f16700Schasinglulu mmio_write_32(CRU_BASE + CRU_CLKGATE_CON(31), 1054*91f16700Schasinglulu BITS_WITH_WMASK(gpio_2_4_clk_gate, 0x07, 1055*91f16700Schasinglulu PCLK_GPIO2_GATE_SHIFT)); 1056*91f16700Schasinglulu } 1057*91f16700Schasinglulu 1058*91f16700Schasinglulu static void suspend_gpio(void) 1059*91f16700Schasinglulu { 1060*91f16700Schasinglulu struct bl_aux_gpio_info *suspend_gpio; 1061*91f16700Schasinglulu uint32_t count; 1062*91f16700Schasinglulu int i; 1063*91f16700Schasinglulu 1064*91f16700Schasinglulu suspend_gpio = plat_get_rockchip_suspend_gpio(&count); 1065*91f16700Schasinglulu 1066*91f16700Schasinglulu for (i = 0; i < count; i++) { 1067*91f16700Schasinglulu gpio_set_value(suspend_gpio[i].index, suspend_gpio[i].polarity); 1068*91f16700Schasinglulu gpio_set_direction(suspend_gpio[i].index, GPIO_DIR_OUT); 1069*91f16700Schasinglulu udelay(1); 1070*91f16700Schasinglulu } 1071*91f16700Schasinglulu } 1072*91f16700Schasinglulu 1073*91f16700Schasinglulu static void resume_gpio(void) 1074*91f16700Schasinglulu { 1075*91f16700Schasinglulu struct bl_aux_gpio_info *suspend_gpio; 1076*91f16700Schasinglulu uint32_t count; 1077*91f16700Schasinglulu int i; 1078*91f16700Schasinglulu 1079*91f16700Schasinglulu suspend_gpio = plat_get_rockchip_suspend_gpio(&count); 1080*91f16700Schasinglulu 1081*91f16700Schasinglulu for (i = count - 1; i >= 0; i--) { 1082*91f16700Schasinglulu gpio_set_value(suspend_gpio[i].index, 1083*91f16700Schasinglulu !suspend_gpio[i].polarity); 1084*91f16700Schasinglulu gpio_set_direction(suspend_gpio[i].index, GPIO_DIR_OUT); 1085*91f16700Schasinglulu udelay(1); 1086*91f16700Schasinglulu } 1087*91f16700Schasinglulu } 1088*91f16700Schasinglulu 1089*91f16700Schasinglulu void sram_save(void) 1090*91f16700Schasinglulu { 1091*91f16700Schasinglulu size_t text_size = (char *)&__bl31_sram_text_real_end - 1092*91f16700Schasinglulu (char *)&__bl31_sram_text_start; 1093*91f16700Schasinglulu size_t data_size = (char *)&__bl31_sram_data_real_end - 1094*91f16700Schasinglulu (char *)&__bl31_sram_data_start; 1095*91f16700Schasinglulu size_t incbin_size = (char *)&__sram_incbin_real_end - 1096*91f16700Schasinglulu (char *)&__sram_incbin_start; 1097*91f16700Schasinglulu 1098*91f16700Schasinglulu memcpy(&store_sram[0], &__bl31_sram_text_start, text_size); 1099*91f16700Schasinglulu memcpy(&store_sram[text_size], &__bl31_sram_data_start, data_size); 1100*91f16700Schasinglulu memcpy(&store_sram[text_size + data_size], &__sram_incbin_start, 1101*91f16700Schasinglulu incbin_size); 1102*91f16700Schasinglulu } 1103*91f16700Schasinglulu 1104*91f16700Schasinglulu void sram_restore(void) 1105*91f16700Schasinglulu { 1106*91f16700Schasinglulu size_t text_size = (char *)&__bl31_sram_text_real_end - 1107*91f16700Schasinglulu (char *)&__bl31_sram_text_start; 1108*91f16700Schasinglulu size_t data_size = (char *)&__bl31_sram_data_real_end - 1109*91f16700Schasinglulu (char *)&__bl31_sram_data_start; 1110*91f16700Schasinglulu size_t incbin_size = (char *)&__sram_incbin_real_end - 1111*91f16700Schasinglulu (char *)&__sram_incbin_start; 1112*91f16700Schasinglulu 1113*91f16700Schasinglulu memcpy(&__bl31_sram_text_start, &store_sram[0], text_size); 1114*91f16700Schasinglulu memcpy(&__bl31_sram_data_start, &store_sram[text_size], data_size); 1115*91f16700Schasinglulu memcpy(&__sram_incbin_start, &store_sram[text_size + data_size], 1116*91f16700Schasinglulu incbin_size); 1117*91f16700Schasinglulu } 1118*91f16700Schasinglulu 1119*91f16700Schasinglulu struct uart_debug { 1120*91f16700Schasinglulu uint32_t uart_dll; 1121*91f16700Schasinglulu uint32_t uart_dlh; 1122*91f16700Schasinglulu uint32_t uart_ier; 1123*91f16700Schasinglulu uint32_t uart_fcr; 1124*91f16700Schasinglulu uint32_t uart_mcr; 1125*91f16700Schasinglulu uint32_t uart_lcr; 1126*91f16700Schasinglulu }; 1127*91f16700Schasinglulu 1128*91f16700Schasinglulu #define UART_DLL 0x00 1129*91f16700Schasinglulu #define UART_DLH 0x04 1130*91f16700Schasinglulu #define UART_IER 0x04 1131*91f16700Schasinglulu #define UART_FCR 0x08 1132*91f16700Schasinglulu #define UART_LCR 0x0c 1133*91f16700Schasinglulu #define UART_MCR 0x10 1134*91f16700Schasinglulu #define UARTSRR 0x88 1135*91f16700Schasinglulu 1136*91f16700Schasinglulu #define UART_RESET BIT(0) 1137*91f16700Schasinglulu #define UARTFCR_FIFOEN BIT(0) 1138*91f16700Schasinglulu #define RCVR_FIFO_RESET BIT(1) 1139*91f16700Schasinglulu #define XMIT_FIFO_RESET BIT(2) 1140*91f16700Schasinglulu #define DIAGNOSTIC_MODE BIT(4) 1141*91f16700Schasinglulu #define UARTLCR_DLAB BIT(7) 1142*91f16700Schasinglulu 1143*91f16700Schasinglulu static struct uart_debug uart_save; 1144*91f16700Schasinglulu 1145*91f16700Schasinglulu void suspend_uart(void) 1146*91f16700Schasinglulu { 1147*91f16700Schasinglulu uint32_t uart_base = rockchip_get_uart_base(); 1148*91f16700Schasinglulu 1149*91f16700Schasinglulu if (uart_base == 0) 1150*91f16700Schasinglulu return; 1151*91f16700Schasinglulu 1152*91f16700Schasinglulu uart_save.uart_lcr = mmio_read_32(uart_base + UART_LCR); 1153*91f16700Schasinglulu uart_save.uart_ier = mmio_read_32(uart_base + UART_IER); 1154*91f16700Schasinglulu uart_save.uart_mcr = mmio_read_32(uart_base + UART_MCR); 1155*91f16700Schasinglulu mmio_write_32(uart_base + UART_LCR, 1156*91f16700Schasinglulu uart_save.uart_lcr | UARTLCR_DLAB); 1157*91f16700Schasinglulu uart_save.uart_dll = mmio_read_32(uart_base + UART_DLL); 1158*91f16700Schasinglulu uart_save.uart_dlh = mmio_read_32(uart_base + UART_DLH); 1159*91f16700Schasinglulu mmio_write_32(uart_base + UART_LCR, uart_save.uart_lcr); 1160*91f16700Schasinglulu } 1161*91f16700Schasinglulu 1162*91f16700Schasinglulu void resume_uart(void) 1163*91f16700Schasinglulu { 1164*91f16700Schasinglulu uint32_t uart_base = rockchip_get_uart_base(); 1165*91f16700Schasinglulu uint32_t uart_lcr; 1166*91f16700Schasinglulu 1167*91f16700Schasinglulu if (uart_base == 0) 1168*91f16700Schasinglulu return; 1169*91f16700Schasinglulu 1170*91f16700Schasinglulu mmio_write_32(uart_base + UARTSRR, 1171*91f16700Schasinglulu XMIT_FIFO_RESET | RCVR_FIFO_RESET | UART_RESET); 1172*91f16700Schasinglulu 1173*91f16700Schasinglulu uart_lcr = mmio_read_32(uart_base + UART_LCR); 1174*91f16700Schasinglulu mmio_write_32(uart_base + UART_MCR, DIAGNOSTIC_MODE); 1175*91f16700Schasinglulu mmio_write_32(uart_base + UART_LCR, uart_lcr | UARTLCR_DLAB); 1176*91f16700Schasinglulu mmio_write_32(uart_base + UART_DLL, uart_save.uart_dll); 1177*91f16700Schasinglulu mmio_write_32(uart_base + UART_DLH, uart_save.uart_dlh); 1178*91f16700Schasinglulu mmio_write_32(uart_base + UART_LCR, uart_save.uart_lcr); 1179*91f16700Schasinglulu mmio_write_32(uart_base + UART_IER, uart_save.uart_ier); 1180*91f16700Schasinglulu mmio_write_32(uart_base + UART_FCR, UARTFCR_FIFOEN); 1181*91f16700Schasinglulu mmio_write_32(uart_base + UART_MCR, uart_save.uart_mcr); 1182*91f16700Schasinglulu } 1183*91f16700Schasinglulu 1184*91f16700Schasinglulu void save_usbphy(void) 1185*91f16700Schasinglulu { 1186*91f16700Schasinglulu store_usbphy0[0] = mmio_read_32(GRF_BASE + GRF_USBPHY0_CTRL0); 1187*91f16700Schasinglulu store_usbphy0[1] = mmio_read_32(GRF_BASE + GRF_USBPHY0_CTRL2); 1188*91f16700Schasinglulu store_usbphy0[2] = mmio_read_32(GRF_BASE + GRF_USBPHY0_CTRL3); 1189*91f16700Schasinglulu store_usbphy0[3] = mmio_read_32(GRF_BASE + GRF_USBPHY0_CTRL12); 1190*91f16700Schasinglulu store_usbphy0[4] = mmio_read_32(GRF_BASE + GRF_USBPHY0_CTRL13); 1191*91f16700Schasinglulu store_usbphy0[5] = mmio_read_32(GRF_BASE + GRF_USBPHY0_CTRL15); 1192*91f16700Schasinglulu store_usbphy0[6] = mmio_read_32(GRF_BASE + GRF_USBPHY0_CTRL16); 1193*91f16700Schasinglulu 1194*91f16700Schasinglulu store_usbphy1[0] = mmio_read_32(GRF_BASE + GRF_USBPHY1_CTRL0); 1195*91f16700Schasinglulu store_usbphy1[1] = mmio_read_32(GRF_BASE + GRF_USBPHY1_CTRL2); 1196*91f16700Schasinglulu store_usbphy1[2] = mmio_read_32(GRF_BASE + GRF_USBPHY1_CTRL3); 1197*91f16700Schasinglulu store_usbphy1[3] = mmio_read_32(GRF_BASE + GRF_USBPHY1_CTRL12); 1198*91f16700Schasinglulu store_usbphy1[4] = mmio_read_32(GRF_BASE + GRF_USBPHY1_CTRL13); 1199*91f16700Schasinglulu store_usbphy1[5] = mmio_read_32(GRF_BASE + GRF_USBPHY1_CTRL15); 1200*91f16700Schasinglulu store_usbphy1[6] = mmio_read_32(GRF_BASE + GRF_USBPHY1_CTRL16); 1201*91f16700Schasinglulu } 1202*91f16700Schasinglulu 1203*91f16700Schasinglulu void restore_usbphy(void) 1204*91f16700Schasinglulu { 1205*91f16700Schasinglulu mmio_write_32(GRF_BASE + GRF_USBPHY0_CTRL0, 1206*91f16700Schasinglulu REG_SOC_WMSK | store_usbphy0[0]); 1207*91f16700Schasinglulu mmio_write_32(GRF_BASE + GRF_USBPHY0_CTRL2, 1208*91f16700Schasinglulu REG_SOC_WMSK | store_usbphy0[1]); 1209*91f16700Schasinglulu mmio_write_32(GRF_BASE + GRF_USBPHY0_CTRL3, 1210*91f16700Schasinglulu REG_SOC_WMSK | store_usbphy0[2]); 1211*91f16700Schasinglulu mmio_write_32(GRF_BASE + GRF_USBPHY0_CTRL12, 1212*91f16700Schasinglulu REG_SOC_WMSK | store_usbphy0[3]); 1213*91f16700Schasinglulu mmio_write_32(GRF_BASE + GRF_USBPHY0_CTRL13, 1214*91f16700Schasinglulu REG_SOC_WMSK | store_usbphy0[4]); 1215*91f16700Schasinglulu mmio_write_32(GRF_BASE + GRF_USBPHY0_CTRL15, 1216*91f16700Schasinglulu REG_SOC_WMSK | store_usbphy0[5]); 1217*91f16700Schasinglulu mmio_write_32(GRF_BASE + GRF_USBPHY0_CTRL16, 1218*91f16700Schasinglulu REG_SOC_WMSK | store_usbphy0[6]); 1219*91f16700Schasinglulu 1220*91f16700Schasinglulu mmio_write_32(GRF_BASE + GRF_USBPHY1_CTRL0, 1221*91f16700Schasinglulu REG_SOC_WMSK | store_usbphy1[0]); 1222*91f16700Schasinglulu mmio_write_32(GRF_BASE + GRF_USBPHY1_CTRL2, 1223*91f16700Schasinglulu REG_SOC_WMSK | store_usbphy1[1]); 1224*91f16700Schasinglulu mmio_write_32(GRF_BASE + GRF_USBPHY1_CTRL3, 1225*91f16700Schasinglulu REG_SOC_WMSK | store_usbphy1[2]); 1226*91f16700Schasinglulu mmio_write_32(GRF_BASE + GRF_USBPHY1_CTRL12, 1227*91f16700Schasinglulu REG_SOC_WMSK | store_usbphy1[3]); 1228*91f16700Schasinglulu mmio_write_32(GRF_BASE + GRF_USBPHY1_CTRL13, 1229*91f16700Schasinglulu REG_SOC_WMSK | store_usbphy1[4]); 1230*91f16700Schasinglulu mmio_write_32(GRF_BASE + GRF_USBPHY1_CTRL15, 1231*91f16700Schasinglulu REG_SOC_WMSK | store_usbphy1[5]); 1232*91f16700Schasinglulu mmio_write_32(GRF_BASE + GRF_USBPHY1_CTRL16, 1233*91f16700Schasinglulu REG_SOC_WMSK | store_usbphy1[6]); 1234*91f16700Schasinglulu } 1235*91f16700Schasinglulu 1236*91f16700Schasinglulu void grf_register_save(void) 1237*91f16700Schasinglulu { 1238*91f16700Schasinglulu int i; 1239*91f16700Schasinglulu 1240*91f16700Schasinglulu store_grf_soc_con0 = mmio_read_32(GRF_BASE + GRF_SOC_CON(0)); 1241*91f16700Schasinglulu store_grf_soc_con1 = mmio_read_32(GRF_BASE + GRF_SOC_CON(1)); 1242*91f16700Schasinglulu store_grf_soc_con2 = mmio_read_32(GRF_BASE + GRF_SOC_CON(2)); 1243*91f16700Schasinglulu store_grf_soc_con3 = mmio_read_32(GRF_BASE + GRF_SOC_CON(3)); 1244*91f16700Schasinglulu store_grf_soc_con4 = mmio_read_32(GRF_BASE + GRF_SOC_CON(4)); 1245*91f16700Schasinglulu store_grf_soc_con7 = mmio_read_32(GRF_BASE + GRF_SOC_CON(7)); 1246*91f16700Schasinglulu 1247*91f16700Schasinglulu for (i = 0; i < 4; i++) 1248*91f16700Schasinglulu store_grf_ddrc_con[i] = 1249*91f16700Schasinglulu mmio_read_32(GRF_BASE + GRF_DDRC0_CON0 + i * 4); 1250*91f16700Schasinglulu 1251*91f16700Schasinglulu store_grf_io_vsel = mmio_read_32(GRF_BASE + GRF_IO_VSEL); 1252*91f16700Schasinglulu } 1253*91f16700Schasinglulu 1254*91f16700Schasinglulu void grf_register_restore(void) 1255*91f16700Schasinglulu { 1256*91f16700Schasinglulu int i; 1257*91f16700Schasinglulu 1258*91f16700Schasinglulu mmio_write_32(GRF_BASE + GRF_SOC_CON(0), 1259*91f16700Schasinglulu REG_SOC_WMSK | store_grf_soc_con0); 1260*91f16700Schasinglulu mmio_write_32(GRF_BASE + GRF_SOC_CON(1), 1261*91f16700Schasinglulu REG_SOC_WMSK | store_grf_soc_con1); 1262*91f16700Schasinglulu mmio_write_32(GRF_BASE + GRF_SOC_CON(2), 1263*91f16700Schasinglulu REG_SOC_WMSK | store_grf_soc_con2); 1264*91f16700Schasinglulu mmio_write_32(GRF_BASE + GRF_SOC_CON(3), 1265*91f16700Schasinglulu REG_SOC_WMSK | store_grf_soc_con3); 1266*91f16700Schasinglulu mmio_write_32(GRF_BASE + GRF_SOC_CON(4), 1267*91f16700Schasinglulu REG_SOC_WMSK | store_grf_soc_con4); 1268*91f16700Schasinglulu mmio_write_32(GRF_BASE + GRF_SOC_CON(7), 1269*91f16700Schasinglulu REG_SOC_WMSK | store_grf_soc_con7); 1270*91f16700Schasinglulu 1271*91f16700Schasinglulu for (i = 0; i < 4; i++) 1272*91f16700Schasinglulu mmio_write_32(GRF_BASE + GRF_DDRC0_CON0 + i * 4, 1273*91f16700Schasinglulu REG_SOC_WMSK | store_grf_ddrc_con[i]); 1274*91f16700Schasinglulu 1275*91f16700Schasinglulu mmio_write_32(GRF_BASE + GRF_IO_VSEL, REG_SOC_WMSK | store_grf_io_vsel); 1276*91f16700Schasinglulu } 1277*91f16700Schasinglulu 1278*91f16700Schasinglulu void cru_register_save(void) 1279*91f16700Schasinglulu { 1280*91f16700Schasinglulu int i; 1281*91f16700Schasinglulu 1282*91f16700Schasinglulu for (i = 0; i <= CRU_SDIO0_CON1; i = i + 4) 1283*91f16700Schasinglulu store_cru[i / 4] = mmio_read_32(CRU_BASE + i); 1284*91f16700Schasinglulu } 1285*91f16700Schasinglulu 1286*91f16700Schasinglulu void cru_register_restore(void) 1287*91f16700Schasinglulu { 1288*91f16700Schasinglulu int i; 1289*91f16700Schasinglulu 1290*91f16700Schasinglulu for (i = 0; i <= CRU_SDIO0_CON1; i = i + 4) { 1291*91f16700Schasinglulu 1292*91f16700Schasinglulu /* 1293*91f16700Schasinglulu * since DPLL, CRU_CLKSEL_CON6 have been restore in 1294*91f16700Schasinglulu * dmc_resume, ABPLL will resote later, so skip them 1295*91f16700Schasinglulu */ 1296*91f16700Schasinglulu if ((i == CRU_CLKSEL_CON6) || 1297*91f16700Schasinglulu (i >= CRU_PLL_CON(ABPLL_ID, 0) && 1298*91f16700Schasinglulu i <= CRU_PLL_CON(DPLL_ID, 5))) 1299*91f16700Schasinglulu continue; 1300*91f16700Schasinglulu 1301*91f16700Schasinglulu if ((i == CRU_PLL_CON(ALPLL_ID, 2)) || 1302*91f16700Schasinglulu (i == CRU_PLL_CON(CPLL_ID, 2)) || 1303*91f16700Schasinglulu (i == CRU_PLL_CON(GPLL_ID, 2)) || 1304*91f16700Schasinglulu (i == CRU_PLL_CON(NPLL_ID, 2)) || 1305*91f16700Schasinglulu (i == CRU_PLL_CON(VPLL_ID, 2))) 1306*91f16700Schasinglulu mmio_write_32(CRU_BASE + i, store_cru[i / 4]); 1307*91f16700Schasinglulu /* 1308*91f16700Schasinglulu * CRU_GLB_CNT_TH and CRU_CLKSEL_CON97~CRU_CLKSEL_CON107 1309*91f16700Schasinglulu * not need do high 16bit mask 1310*91f16700Schasinglulu */ 1311*91f16700Schasinglulu else if ((i > 0x27c && i < 0x2b0) || (i == 0x508)) 1312*91f16700Schasinglulu mmio_write_32(CRU_BASE + i, store_cru[i / 4]); 1313*91f16700Schasinglulu else 1314*91f16700Schasinglulu mmio_write_32(CRU_BASE + i, 1315*91f16700Schasinglulu REG_SOC_WMSK | store_cru[i / 4]); 1316*91f16700Schasinglulu } 1317*91f16700Schasinglulu } 1318*91f16700Schasinglulu 1319*91f16700Schasinglulu void wdt_register_save(void) 1320*91f16700Schasinglulu { 1321*91f16700Schasinglulu int i; 1322*91f16700Schasinglulu 1323*91f16700Schasinglulu for (i = 0; i < 2; i++) { 1324*91f16700Schasinglulu store_wdt0[i] = mmio_read_32(WDT0_BASE + i * 4); 1325*91f16700Schasinglulu store_wdt1[i] = mmio_read_32(WDT1_BASE + i * 4); 1326*91f16700Schasinglulu } 1327*91f16700Schasinglulu pmu_enable_watchdog0 = (uint8_t) store_wdt0[0] & 0x1; 1328*91f16700Schasinglulu } 1329*91f16700Schasinglulu 1330*91f16700Schasinglulu void wdt_register_restore(void) 1331*91f16700Schasinglulu { 1332*91f16700Schasinglulu int i; 1333*91f16700Schasinglulu 1334*91f16700Schasinglulu for (i = 1; i >= 0; i--) { 1335*91f16700Schasinglulu mmio_write_32(WDT0_BASE + i * 4, store_wdt0[i]); 1336*91f16700Schasinglulu mmio_write_32(WDT1_BASE + i * 4, store_wdt1[i]); 1337*91f16700Schasinglulu } 1338*91f16700Schasinglulu 1339*91f16700Schasinglulu /* write 0x76 to cnt_restart to keep watchdog alive */ 1340*91f16700Schasinglulu mmio_write_32(WDT0_BASE + 0x0c, 0x76); 1341*91f16700Schasinglulu mmio_write_32(WDT1_BASE + 0x0c, 0x76); 1342*91f16700Schasinglulu } 1343*91f16700Schasinglulu 1344*91f16700Schasinglulu int rockchip_soc_sys_pwr_dm_suspend(void) 1345*91f16700Schasinglulu { 1346*91f16700Schasinglulu uint32_t wait_cnt = 0; 1347*91f16700Schasinglulu uint32_t status = 0; 1348*91f16700Schasinglulu 1349*91f16700Schasinglulu ddr_prepare_for_sys_suspend(); 1350*91f16700Schasinglulu dmc_suspend(); 1351*91f16700Schasinglulu pmu_scu_b_pwrdn(); 1352*91f16700Schasinglulu 1353*91f16700Schasinglulu gicv3_rdistif_save(plat_my_core_pos(), &rdist_ctx); 1354*91f16700Schasinglulu gicv3_distif_save(&dist_ctx); 1355*91f16700Schasinglulu 1356*91f16700Schasinglulu /* need to save usbphy before shutdown PERIHP PD */ 1357*91f16700Schasinglulu save_usbphy(); 1358*91f16700Schasinglulu 1359*91f16700Schasinglulu pmu_power_domains_suspend(); 1360*91f16700Schasinglulu set_hw_idle(BIT(PMU_CLR_CENTER1) | 1361*91f16700Schasinglulu BIT(PMU_CLR_ALIVE) | 1362*91f16700Schasinglulu BIT(PMU_CLR_MSCH0) | 1363*91f16700Schasinglulu BIT(PMU_CLR_MSCH1) | 1364*91f16700Schasinglulu BIT(PMU_CLR_CCIM0) | 1365*91f16700Schasinglulu BIT(PMU_CLR_CCIM1) | 1366*91f16700Schasinglulu BIT(PMU_CLR_CENTER) | 1367*91f16700Schasinglulu BIT(PMU_CLR_PERILP) | 1368*91f16700Schasinglulu BIT(PMU_CLR_PERILPM0) | 1369*91f16700Schasinglulu BIT(PMU_CLR_GIC)); 1370*91f16700Schasinglulu set_pmu_rsthold(); 1371*91f16700Schasinglulu sys_slp_config(); 1372*91f16700Schasinglulu 1373*91f16700Schasinglulu m0_configure_execute_addr(M0PMU_BINCODE_BASE); 1374*91f16700Schasinglulu m0_start(); 1375*91f16700Schasinglulu 1376*91f16700Schasinglulu pmu_sgrf_rst_hld(); 1377*91f16700Schasinglulu 1378*91f16700Schasinglulu mmio_write_32(SGRF_BASE + SGRF_SOC_CON(1), 1379*91f16700Schasinglulu ((uintptr_t)&pmu_cpuson_entrypoint >> 1380*91f16700Schasinglulu CPU_BOOT_ADDR_ALIGN) | CPU_BOOT_ADDR_WMASK); 1381*91f16700Schasinglulu 1382*91f16700Schasinglulu mmio_write_32(PMU_BASE + PMU_ADB400_CON, 1383*91f16700Schasinglulu BIT_WITH_WMSK(PMU_PWRDWN_REQ_CORE_B_2GIC_SW) | 1384*91f16700Schasinglulu BIT_WITH_WMSK(PMU_PWRDWN_REQ_CORE_B_SW) | 1385*91f16700Schasinglulu BIT_WITH_WMSK(PMU_PWRDWN_REQ_GIC2_CORE_B_SW)); 1386*91f16700Schasinglulu dsb(); 1387*91f16700Schasinglulu status = BIT(PMU_PWRDWN_REQ_CORE_B_2GIC_SW_ST) | 1388*91f16700Schasinglulu BIT(PMU_PWRDWN_REQ_CORE_B_SW_ST) | 1389*91f16700Schasinglulu BIT(PMU_PWRDWN_REQ_GIC2_CORE_B_SW_ST); 1390*91f16700Schasinglulu while ((mmio_read_32(PMU_BASE + 1391*91f16700Schasinglulu PMU_ADB400_ST) & status) != status) { 1392*91f16700Schasinglulu wait_cnt++; 1393*91f16700Schasinglulu if (wait_cnt >= MAX_WAIT_COUNT) { 1394*91f16700Schasinglulu ERROR("%s:wait cluster-b l2(%x)\n", __func__, 1395*91f16700Schasinglulu mmio_read_32(PMU_BASE + PMU_ADB400_ST)); 1396*91f16700Schasinglulu panic(); 1397*91f16700Schasinglulu } 1398*91f16700Schasinglulu udelay(1); 1399*91f16700Schasinglulu } 1400*91f16700Schasinglulu mmio_setbits_32(PMU_BASE + PMU_PWRDN_CON, BIT(PMU_SCU_B_PWRDWN_EN)); 1401*91f16700Schasinglulu 1402*91f16700Schasinglulu wdt_register_save(); 1403*91f16700Schasinglulu secure_watchdog_gate(); 1404*91f16700Schasinglulu 1405*91f16700Schasinglulu /* 1406*91f16700Schasinglulu * Disabling PLLs/PWM/DVFS is approaching WFI which is 1407*91f16700Schasinglulu * the last steps in suspend. 1408*91f16700Schasinglulu */ 1409*91f16700Schasinglulu disable_dvfs_plls(); 1410*91f16700Schasinglulu disable_pwms(); 1411*91f16700Schasinglulu disable_nodvfs_plls(); 1412*91f16700Schasinglulu 1413*91f16700Schasinglulu suspend_apio(); 1414*91f16700Schasinglulu suspend_gpio(); 1415*91f16700Schasinglulu suspend_uart(); 1416*91f16700Schasinglulu grf_register_save(); 1417*91f16700Schasinglulu cru_register_save(); 1418*91f16700Schasinglulu sram_save(); 1419*91f16700Schasinglulu plat_rockchip_save_gpio(); 1420*91f16700Schasinglulu 1421*91f16700Schasinglulu return 0; 1422*91f16700Schasinglulu } 1423*91f16700Schasinglulu 1424*91f16700Schasinglulu int rockchip_soc_sys_pwr_dm_resume(void) 1425*91f16700Schasinglulu { 1426*91f16700Schasinglulu uint32_t wait_cnt = 0; 1427*91f16700Schasinglulu uint32_t status = 0; 1428*91f16700Schasinglulu 1429*91f16700Schasinglulu plat_rockchip_restore_gpio(); 1430*91f16700Schasinglulu cru_register_restore(); 1431*91f16700Schasinglulu grf_register_restore(); 1432*91f16700Schasinglulu wdt_register_restore(); 1433*91f16700Schasinglulu resume_uart(); 1434*91f16700Schasinglulu resume_apio(); 1435*91f16700Schasinglulu resume_gpio(); 1436*91f16700Schasinglulu enable_nodvfs_plls(); 1437*91f16700Schasinglulu enable_pwms(); 1438*91f16700Schasinglulu /* PWM regulators take time to come up; give 300us to be safe. */ 1439*91f16700Schasinglulu udelay(300); 1440*91f16700Schasinglulu enable_dvfs_plls(); 1441*91f16700Schasinglulu 1442*91f16700Schasinglulu secure_sgrf_init(); 1443*91f16700Schasinglulu secure_sgrf_ddr_rgn_init(); 1444*91f16700Schasinglulu 1445*91f16700Schasinglulu /* restore clk_ddrc_bpll_src_en gate */ 1446*91f16700Schasinglulu mmio_write_32(CRU_BASE + CRU_CLKGATE_CON(3), 1447*91f16700Schasinglulu BITS_WITH_WMASK(clk_ddrc_save, 0xff, 0)); 1448*91f16700Schasinglulu 1449*91f16700Schasinglulu /* 1450*91f16700Schasinglulu * The wakeup status is not cleared by itself, we need to clear it 1451*91f16700Schasinglulu * manually. Otherwise we will alway query some interrupt next time. 1452*91f16700Schasinglulu * 1453*91f16700Schasinglulu * NOTE: If the kernel needs to query this, we might want to stash it 1454*91f16700Schasinglulu * somewhere. 1455*91f16700Schasinglulu */ 1456*91f16700Schasinglulu mmio_write_32(PMU_BASE + PMU_WAKEUP_STATUS, 0xffffffff); 1457*91f16700Schasinglulu mmio_write_32(PMU_BASE + PMU_WKUP_CFG4, 0x00); 1458*91f16700Schasinglulu 1459*91f16700Schasinglulu mmio_write_32(SGRF_BASE + SGRF_SOC_CON(1), 1460*91f16700Schasinglulu (cpu_warm_boot_addr >> CPU_BOOT_ADDR_ALIGN) | 1461*91f16700Schasinglulu CPU_BOOT_ADDR_WMASK); 1462*91f16700Schasinglulu 1463*91f16700Schasinglulu mmio_write_32(PMU_BASE + PMU_CCI500_CON, 1464*91f16700Schasinglulu WMSK_BIT(PMU_CLR_PREQ_CCI500_HW) | 1465*91f16700Schasinglulu WMSK_BIT(PMU_CLR_QREQ_CCI500_HW) | 1466*91f16700Schasinglulu WMSK_BIT(PMU_QGATING_CCI500_CFG)); 1467*91f16700Schasinglulu dsb(); 1468*91f16700Schasinglulu mmio_clrbits_32(PMU_BASE + PMU_PWRDN_CON, 1469*91f16700Schasinglulu BIT(PMU_SCU_B_PWRDWN_EN)); 1470*91f16700Schasinglulu 1471*91f16700Schasinglulu mmio_write_32(PMU_BASE + PMU_ADB400_CON, 1472*91f16700Schasinglulu WMSK_BIT(PMU_PWRDWN_REQ_CORE_B_2GIC_SW) | 1473*91f16700Schasinglulu WMSK_BIT(PMU_PWRDWN_REQ_CORE_B_SW) | 1474*91f16700Schasinglulu WMSK_BIT(PMU_PWRDWN_REQ_GIC2_CORE_B_SW) | 1475*91f16700Schasinglulu WMSK_BIT(PMU_CLR_CORE_L_HW) | 1476*91f16700Schasinglulu WMSK_BIT(PMU_CLR_CORE_L_2GIC_HW) | 1477*91f16700Schasinglulu WMSK_BIT(PMU_CLR_GIC2_CORE_L_HW)); 1478*91f16700Schasinglulu 1479*91f16700Schasinglulu status = BIT(PMU_PWRDWN_REQ_CORE_B_2GIC_SW_ST) | 1480*91f16700Schasinglulu BIT(PMU_PWRDWN_REQ_CORE_B_SW_ST) | 1481*91f16700Schasinglulu BIT(PMU_PWRDWN_REQ_GIC2_CORE_B_SW_ST); 1482*91f16700Schasinglulu 1483*91f16700Schasinglulu while ((mmio_read_32(PMU_BASE + 1484*91f16700Schasinglulu PMU_ADB400_ST) & status)) { 1485*91f16700Schasinglulu wait_cnt++; 1486*91f16700Schasinglulu if (wait_cnt >= MAX_WAIT_COUNT) { 1487*91f16700Schasinglulu ERROR("%s:wait cluster-b l2(%x)\n", __func__, 1488*91f16700Schasinglulu mmio_read_32(PMU_BASE + PMU_ADB400_ST)); 1489*91f16700Schasinglulu panic(); 1490*91f16700Schasinglulu } 1491*91f16700Schasinglulu udelay(1); 1492*91f16700Schasinglulu } 1493*91f16700Schasinglulu 1494*91f16700Schasinglulu pmu_scu_b_pwrup(); 1495*91f16700Schasinglulu pmu_power_domains_resume(); 1496*91f16700Schasinglulu 1497*91f16700Schasinglulu restore_abpll(); 1498*91f16700Schasinglulu clr_hw_idle(BIT(PMU_CLR_CENTER1) | 1499*91f16700Schasinglulu BIT(PMU_CLR_ALIVE) | 1500*91f16700Schasinglulu BIT(PMU_CLR_MSCH0) | 1501*91f16700Schasinglulu BIT(PMU_CLR_MSCH1) | 1502*91f16700Schasinglulu BIT(PMU_CLR_CCIM0) | 1503*91f16700Schasinglulu BIT(PMU_CLR_CCIM1) | 1504*91f16700Schasinglulu BIT(PMU_CLR_CENTER) | 1505*91f16700Schasinglulu BIT(PMU_CLR_PERILP) | 1506*91f16700Schasinglulu BIT(PMU_CLR_PERILPM0) | 1507*91f16700Schasinglulu BIT(PMU_CLR_GIC)); 1508*91f16700Schasinglulu 1509*91f16700Schasinglulu gicv3_distif_init_restore(&dist_ctx); 1510*91f16700Schasinglulu gicv3_rdistif_init_restore(plat_my_core_pos(), &rdist_ctx); 1511*91f16700Schasinglulu plat_rockchip_gic_cpuif_enable(); 1512*91f16700Schasinglulu m0_stop(); 1513*91f16700Schasinglulu 1514*91f16700Schasinglulu restore_usbphy(); 1515*91f16700Schasinglulu 1516*91f16700Schasinglulu ddr_prepare_for_sys_resume(); 1517*91f16700Schasinglulu 1518*91f16700Schasinglulu return 0; 1519*91f16700Schasinglulu } 1520*91f16700Schasinglulu 1521*91f16700Schasinglulu void __dead2 rockchip_soc_soft_reset(void) 1522*91f16700Schasinglulu { 1523*91f16700Schasinglulu struct bl_aux_gpio_info *rst_gpio; 1524*91f16700Schasinglulu 1525*91f16700Schasinglulu rst_gpio = plat_get_rockchip_gpio_reset(); 1526*91f16700Schasinglulu 1527*91f16700Schasinglulu if (rst_gpio) { 1528*91f16700Schasinglulu gpio_set_direction(rst_gpio->index, GPIO_DIR_OUT); 1529*91f16700Schasinglulu gpio_set_value(rst_gpio->index, rst_gpio->polarity); 1530*91f16700Schasinglulu } else { 1531*91f16700Schasinglulu soc_global_soft_reset(); 1532*91f16700Schasinglulu } 1533*91f16700Schasinglulu 1534*91f16700Schasinglulu while (1) 1535*91f16700Schasinglulu ; 1536*91f16700Schasinglulu } 1537*91f16700Schasinglulu 1538*91f16700Schasinglulu void __dead2 rockchip_soc_system_off(void) 1539*91f16700Schasinglulu { 1540*91f16700Schasinglulu struct bl_aux_gpio_info *poweroff_gpio; 1541*91f16700Schasinglulu 1542*91f16700Schasinglulu poweroff_gpio = plat_get_rockchip_gpio_poweroff(); 1543*91f16700Schasinglulu 1544*91f16700Schasinglulu if (poweroff_gpio) { 1545*91f16700Schasinglulu /* 1546*91f16700Schasinglulu * if use tsadc over temp pin(GPIO1A6) as shutdown gpio, 1547*91f16700Schasinglulu * need to set this pin iomux back to gpio function 1548*91f16700Schasinglulu */ 1549*91f16700Schasinglulu if (poweroff_gpio->index == TSADC_INT_PIN) { 1550*91f16700Schasinglulu mmio_write_32(PMUGRF_BASE + PMUGRF_GPIO1A_IOMUX, 1551*91f16700Schasinglulu GPIO1A6_IOMUX); 1552*91f16700Schasinglulu } 1553*91f16700Schasinglulu gpio_set_direction(poweroff_gpio->index, GPIO_DIR_OUT); 1554*91f16700Schasinglulu gpio_set_value(poweroff_gpio->index, poweroff_gpio->polarity); 1555*91f16700Schasinglulu } else { 1556*91f16700Schasinglulu WARN("Do nothing when system off\n"); 1557*91f16700Schasinglulu } 1558*91f16700Schasinglulu 1559*91f16700Schasinglulu while (1) 1560*91f16700Schasinglulu ; 1561*91f16700Schasinglulu } 1562*91f16700Schasinglulu 1563*91f16700Schasinglulu void rockchip_plat_mmu_el3(void) 1564*91f16700Schasinglulu { 1565*91f16700Schasinglulu size_t sram_size; 1566*91f16700Schasinglulu 1567*91f16700Schasinglulu /* sram.text size */ 1568*91f16700Schasinglulu sram_size = (char *)&__bl31_sram_text_end - 1569*91f16700Schasinglulu (char *)&__bl31_sram_text_start; 1570*91f16700Schasinglulu mmap_add_region((unsigned long)&__bl31_sram_text_start, 1571*91f16700Schasinglulu (unsigned long)&__bl31_sram_text_start, 1572*91f16700Schasinglulu sram_size, MT_MEMORY | MT_RO | MT_SECURE); 1573*91f16700Schasinglulu 1574*91f16700Schasinglulu /* sram.data size */ 1575*91f16700Schasinglulu sram_size = (char *)&__bl31_sram_data_end - 1576*91f16700Schasinglulu (char *)&__bl31_sram_data_start; 1577*91f16700Schasinglulu mmap_add_region((unsigned long)&__bl31_sram_data_start, 1578*91f16700Schasinglulu (unsigned long)&__bl31_sram_data_start, 1579*91f16700Schasinglulu sram_size, MT_MEMORY | MT_RW | MT_SECURE); 1580*91f16700Schasinglulu 1581*91f16700Schasinglulu sram_size = (char *)&__bl31_sram_stack_end - 1582*91f16700Schasinglulu (char *)&__bl31_sram_stack_start; 1583*91f16700Schasinglulu mmap_add_region((unsigned long)&__bl31_sram_stack_start, 1584*91f16700Schasinglulu (unsigned long)&__bl31_sram_stack_start, 1585*91f16700Schasinglulu sram_size, MT_MEMORY | MT_RW | MT_SECURE); 1586*91f16700Schasinglulu 1587*91f16700Schasinglulu sram_size = (char *)&__sram_incbin_end - (char *)&__sram_incbin_start; 1588*91f16700Schasinglulu mmap_add_region((unsigned long)&__sram_incbin_start, 1589*91f16700Schasinglulu (unsigned long)&__sram_incbin_start, 1590*91f16700Schasinglulu sram_size, MT_NON_CACHEABLE | MT_RW | MT_SECURE); 1591*91f16700Schasinglulu } 1592*91f16700Schasinglulu 1593*91f16700Schasinglulu void plat_rockchip_pmu_init(void) 1594*91f16700Schasinglulu { 1595*91f16700Schasinglulu uint32_t cpu; 1596*91f16700Schasinglulu 1597*91f16700Schasinglulu rockchip_pd_lock_init(); 1598*91f16700Schasinglulu 1599*91f16700Schasinglulu /* register requires 32bits mode, switch it to 32 bits */ 1600*91f16700Schasinglulu cpu_warm_boot_addr = (uint64_t)platform_cpu_warmboot; 1601*91f16700Schasinglulu 1602*91f16700Schasinglulu for (cpu = 0; cpu < PLATFORM_CORE_COUNT; cpu++) 1603*91f16700Schasinglulu cpuson_flags[cpu] = 0; 1604*91f16700Schasinglulu 1605*91f16700Schasinglulu for (cpu = 0; cpu < PLATFORM_CLUSTER_COUNT; cpu++) 1606*91f16700Schasinglulu clst_warmboot_data[cpu] = 0; 1607*91f16700Schasinglulu 1608*91f16700Schasinglulu /* config cpu's warm boot address */ 1609*91f16700Schasinglulu mmio_write_32(SGRF_BASE + SGRF_SOC_CON(1), 1610*91f16700Schasinglulu (cpu_warm_boot_addr >> CPU_BOOT_ADDR_ALIGN) | 1611*91f16700Schasinglulu CPU_BOOT_ADDR_WMASK); 1612*91f16700Schasinglulu mmio_write_32(PMU_BASE + PMU_NOC_AUTO_ENA, NOC_AUTO_ENABLE); 1613*91f16700Schasinglulu 1614*91f16700Schasinglulu /* 1615*91f16700Schasinglulu * Enable Schmitt trigger for better 32 kHz input signal, which is 1616*91f16700Schasinglulu * important for suspend/resume reliability among other things. 1617*91f16700Schasinglulu */ 1618*91f16700Schasinglulu mmio_write_32(PMUGRF_BASE + PMUGRF_GPIO0A_SMT, GPIO0A0_SMT_ENABLE); 1619*91f16700Schasinglulu 1620*91f16700Schasinglulu init_pmu_counts(); 1621*91f16700Schasinglulu 1622*91f16700Schasinglulu nonboot_cpus_off(); 1623*91f16700Schasinglulu 1624*91f16700Schasinglulu INFO("%s(%d): pd status %x\n", __func__, __LINE__, 1625*91f16700Schasinglulu mmio_read_32(PMU_BASE + PMU_PWRDN_ST)); 1626*91f16700Schasinglulu } 1627