1*e3ec6ff4SXiaoDong Huang /* 2*e3ec6ff4SXiaoDong Huang * Copyright (c) 2024, Rockchip, Inc. All rights reserved. 3*e3ec6ff4SXiaoDong Huang * 4*e3ec6ff4SXiaoDong Huang * SPDX-License-Identifier: BSD-3-Clause 5*e3ec6ff4SXiaoDong Huang */ 6*e3ec6ff4SXiaoDong Huang 7*e3ec6ff4SXiaoDong Huang #include <assert.h> 8*e3ec6ff4SXiaoDong Huang #include <errno.h> 9*e3ec6ff4SXiaoDong Huang 10*e3ec6ff4SXiaoDong Huang #include <arch_helpers.h> 11*e3ec6ff4SXiaoDong Huang #include <bl31/bl31.h> 12*e3ec6ff4SXiaoDong Huang #include <common/debug.h> 13*e3ec6ff4SXiaoDong Huang #include <drivers/arm/gicv3.h> 14*e3ec6ff4SXiaoDong Huang #include <drivers/console.h> 15*e3ec6ff4SXiaoDong Huang #include <drivers/delay_timer.h> 16*e3ec6ff4SXiaoDong Huang #include <drivers/ti/uart/uart_16550.h> 17*e3ec6ff4SXiaoDong Huang #include <lib/mmio.h> 18*e3ec6ff4SXiaoDong Huang #include <plat/common/platform.h> 19*e3ec6ff4SXiaoDong Huang #include <platform_def.h> 20*e3ec6ff4SXiaoDong Huang #include <pmu.h> 21*e3ec6ff4SXiaoDong Huang 22*e3ec6ff4SXiaoDong Huang #include <cpus_on_fixed_addr.h> 23*e3ec6ff4SXiaoDong Huang #include <plat_pm_helpers.h> 24*e3ec6ff4SXiaoDong Huang #include <plat_private.h> 25*e3ec6ff4SXiaoDong Huang #include <pm_pd_regs.h> 26*e3ec6ff4SXiaoDong Huang #include <rockchip_sip_svc.h> 27*e3ec6ff4SXiaoDong Huang #include <secure.h> 28*e3ec6ff4SXiaoDong Huang #include <soc.h> 29*e3ec6ff4SXiaoDong Huang 30*e3ec6ff4SXiaoDong Huang #define PSRAM_SP_TOP ((PMUSRAM_BASE + PMUSRAM_RSIZE) & ~0xf) 31*e3ec6ff4SXiaoDong Huang #define NONBOOT_CPUS_OFF_LOOP (500000) 32*e3ec6ff4SXiaoDong Huang 33*e3ec6ff4SXiaoDong Huang #define DSUGRF_REG_CNT (0x78 / 4 + 1) 34*e3ec6ff4SXiaoDong Huang #define BCORE_GRF_REG_CNT (0x30 / 4 + 1) 35*e3ec6ff4SXiaoDong Huang #define LCORE_GRF_REG_CNT (0x30 / 4 + 1) 36*e3ec6ff4SXiaoDong Huang 37*e3ec6ff4SXiaoDong Huang #define CENTER_GRF_REG_CNT (0x20 / 4 + 1) 38*e3ec6ff4SXiaoDong Huang 39*e3ec6ff4SXiaoDong Huang static struct psram_data_t *psram_sleep_cfg = 40*e3ec6ff4SXiaoDong Huang (struct psram_data_t *)&sys_sleep_flag_sram; 41*e3ec6ff4SXiaoDong Huang 42*e3ec6ff4SXiaoDong Huang static int8_t pd_repair_map[] = { 43*e3ec6ff4SXiaoDong Huang [PD_GPU] = PD_RPR_GPU, 44*e3ec6ff4SXiaoDong Huang [PD_NPU] = -1, 45*e3ec6ff4SXiaoDong Huang [PD_VCODEC] = -1, 46*e3ec6ff4SXiaoDong Huang [PD_NPUTOP] = PD_RPR_NPUTOP, 47*e3ec6ff4SXiaoDong Huang [PD_NPU1] = PD_RPR_NPU1, 48*e3ec6ff4SXiaoDong Huang [PD_NPU2] = PD_RPR_NPU2, 49*e3ec6ff4SXiaoDong Huang [PD_VENC0] = PD_RPR_VENC0, 50*e3ec6ff4SXiaoDong Huang [PD_VENC1] = PD_RPR_VENC1, 51*e3ec6ff4SXiaoDong Huang [PD_RKVDEC0] = PD_RPR_RKVDEC0, 52*e3ec6ff4SXiaoDong Huang [PD_RKVDEC1] = PD_RPR_RKVDEC1, 53*e3ec6ff4SXiaoDong Huang [PD_VDPU] = PD_RPR_VDPU, 54*e3ec6ff4SXiaoDong Huang [PD_RGA30] = PD_RPR_RGA30, 55*e3ec6ff4SXiaoDong Huang [PD_AV1] = PD_RPR_AV1, 56*e3ec6ff4SXiaoDong Huang [PD_VI] = PD_RPR_VI, 57*e3ec6ff4SXiaoDong Huang [PD_FEC] = PD_RPR_FEC, 58*e3ec6ff4SXiaoDong Huang [PD_ISP1] = PD_RPR_ISP1, 59*e3ec6ff4SXiaoDong Huang [PD_RGA31] = PD_RPR_RGA31, 60*e3ec6ff4SXiaoDong Huang [PD_VOP] = PD_RPR_VOP, 61*e3ec6ff4SXiaoDong Huang [PD_VO0] = PD_RPR_VO0, 62*e3ec6ff4SXiaoDong Huang [PD_VO1] = PD_RPR_VO1, 63*e3ec6ff4SXiaoDong Huang [PD_AUDIO] = PD_RPR_AUDIO, 64*e3ec6ff4SXiaoDong Huang [PD_PHP] = PD_RPR_PHP, 65*e3ec6ff4SXiaoDong Huang [PD_GMAC] = PD_RPR_GMAC, 66*e3ec6ff4SXiaoDong Huang [PD_PCIE] = PD_RPR_PCIE, 67*e3ec6ff4SXiaoDong Huang [PD_NVM] = -1, 68*e3ec6ff4SXiaoDong Huang [PD_NVM0] = PD_RPR_NVM0, 69*e3ec6ff4SXiaoDong Huang [PD_SDIO] = PD_RPR_SDIO, 70*e3ec6ff4SXiaoDong Huang [PD_USB] = PD_RPR_USB, 71*e3ec6ff4SXiaoDong Huang [PD_SECURE] = -1, 72*e3ec6ff4SXiaoDong Huang [PD_SDMMC] = PD_RPR_SDMMC, 73*e3ec6ff4SXiaoDong Huang [PD_CRYPTO] = PD_RPR_CRYPTO, 74*e3ec6ff4SXiaoDong Huang [PD_CENTER] = PD_RPR_CENTER, 75*e3ec6ff4SXiaoDong Huang [PD_DDR01] = PD_RPR_DDR01, 76*e3ec6ff4SXiaoDong Huang [PD_DDR23] = PD_RPR_DDR23, 77*e3ec6ff4SXiaoDong Huang }; 78*e3ec6ff4SXiaoDong Huang 79*e3ec6ff4SXiaoDong Huang struct rk3588_sleep_ddr_data { 80*e3ec6ff4SXiaoDong Huang uint32_t gpio0a_iomux_l, gpio0a_iomux_h, gpio0b_iomux_l; 81*e3ec6ff4SXiaoDong Huang uint32_t pmu_pd_st0, bus_idle_st0, qch_pwr_st; 82*e3ec6ff4SXiaoDong Huang uint32_t pmu2_vol_gate_con[3], pmu2_submem_gate_sft_con0; 83*e3ec6ff4SXiaoDong Huang uint32_t pmu2_bisr_con0; 84*e3ec6ff4SXiaoDong Huang uint32_t cpll_con0; 85*e3ec6ff4SXiaoDong Huang uint32_t cru_mode_con, busscru_mode_con; 86*e3ec6ff4SXiaoDong Huang uint32_t bussgrf_soc_con7; 87*e3ec6ff4SXiaoDong Huang uint32_t pmu0grf_soc_con0, pmu0grf_soc_con1, pmu0grf_soc_con3; 88*e3ec6ff4SXiaoDong Huang uint32_t pmu1grf_soc_con2, pmu1grf_soc_con7, pmu1grf_soc_con8, pmu1grf_soc_con9; 89*e3ec6ff4SXiaoDong Huang uint32_t pmu0sgrf_soc_con1; 90*e3ec6ff4SXiaoDong Huang uint32_t pmu1sgrf_soc_con14; 91*e3ec6ff4SXiaoDong Huang uint32_t ddrgrf_chn_con0[4], ddrgrf_chn_con1[4], 92*e3ec6ff4SXiaoDong Huang ddrgrf_chn_con2[4], pmu1_ddr_pwr_sft_con[4]; 93*e3ec6ff4SXiaoDong Huang uint32_t pmu1cru_clksel_con1; 94*e3ec6ff4SXiaoDong Huang }; 95*e3ec6ff4SXiaoDong Huang 96*e3ec6ff4SXiaoDong Huang static struct rk3588_sleep_ddr_data ddr_data; 97*e3ec6ff4SXiaoDong Huang 98*e3ec6ff4SXiaoDong Huang struct rk3588_sleep_pmusram_data { 99*e3ec6ff4SXiaoDong Huang uint32_t dsusgrf_soc_con[DSUSGRF_SOC_CON_CNT], 100*e3ec6ff4SXiaoDong Huang dsusgrf_ddr_hash_con[DSUSGRF_DDR_HASH_CON_CNT]; 101*e3ec6ff4SXiaoDong Huang uint32_t dsu_ddr_fw_rgn_reg[FIREWALL_DSU_RGN_CNT], 102*e3ec6ff4SXiaoDong Huang dsu_ddr_fw_mst_reg[FIREWALL_DSU_MST_CNT], 103*e3ec6ff4SXiaoDong Huang dsu_ddr_fw_con_reg[FIREWALL_DSU_CON_CNT]; 104*e3ec6ff4SXiaoDong Huang uint32_t busioc_gpio0b_iomux_h; 105*e3ec6ff4SXiaoDong Huang }; 106*e3ec6ff4SXiaoDong Huang 107*e3ec6ff4SXiaoDong Huang static __pmusramdata struct rk3588_sleep_pmusram_data pmusram_data; 108*e3ec6ff4SXiaoDong Huang 109*e3ec6ff4SXiaoDong Huang static __pmusramfunc void dsu_restore_early(void) 110*e3ec6ff4SXiaoDong Huang { 111*e3ec6ff4SXiaoDong Huang int i; 112*e3ec6ff4SXiaoDong Huang 113*e3ec6ff4SXiaoDong Huang /* dsusgrf */ 114*e3ec6ff4SXiaoDong Huang for (i = 0; i < DSUSGRF_SOC_CON_CNT; i++) 115*e3ec6ff4SXiaoDong Huang mmio_write_32(DSUSGRF_BASE + DSUSGRF_SOC_CON(i), 116*e3ec6ff4SXiaoDong Huang WITH_16BITS_WMSK(pmusram_data.dsusgrf_soc_con[i])); 117*e3ec6ff4SXiaoDong Huang 118*e3ec6ff4SXiaoDong Huang for (i = 0; i < DSUSGRF_DDR_HASH_CON_CNT; i++) 119*e3ec6ff4SXiaoDong Huang mmio_write_32(DSUSGRF_BASE + DSUSGRF_DDR_HASH_CON(i), 120*e3ec6ff4SXiaoDong Huang pmusram_data.dsusgrf_ddr_hash_con[i]); 121*e3ec6ff4SXiaoDong Huang 122*e3ec6ff4SXiaoDong Huang /* dsu ddr firewall */ 123*e3ec6ff4SXiaoDong Huang for (i = 0; i < FIREWALL_DSU_RGN_CNT; i++) 124*e3ec6ff4SXiaoDong Huang mmio_write_32(FIREWALL_DSU_BASE + FIREWALL_DSU_RGN(i), 125*e3ec6ff4SXiaoDong Huang pmusram_data.dsu_ddr_fw_rgn_reg[i]); 126*e3ec6ff4SXiaoDong Huang 127*e3ec6ff4SXiaoDong Huang for (i = 0; i < FIREWALL_DSU_MST_CNT; i++) 128*e3ec6ff4SXiaoDong Huang mmio_write_32(FIREWALL_DSU_BASE + FIREWALL_DSU_MST(i), 129*e3ec6ff4SXiaoDong Huang pmusram_data.dsu_ddr_fw_mst_reg[i]); 130*e3ec6ff4SXiaoDong Huang 131*e3ec6ff4SXiaoDong Huang for (i = 0; i < FIREWALL_DSU_CON_CNT; i++) 132*e3ec6ff4SXiaoDong Huang mmio_write_32(FIREWALL_DSU_BASE + FIREWALL_DSU_CON(i), 133*e3ec6ff4SXiaoDong Huang pmusram_data.dsu_ddr_fw_con_reg[i]); 134*e3ec6ff4SXiaoDong Huang } 135*e3ec6ff4SXiaoDong Huang 136*e3ec6ff4SXiaoDong Huang static __pmusramfunc void ddr_resume(void) 137*e3ec6ff4SXiaoDong Huang { 138*e3ec6ff4SXiaoDong Huang dsu_restore_early(); 139*e3ec6ff4SXiaoDong Huang } 140*e3ec6ff4SXiaoDong Huang 141*e3ec6ff4SXiaoDong Huang static void dsu_core_save(void) 142*e3ec6ff4SXiaoDong Huang { 143*e3ec6ff4SXiaoDong Huang int i; 144*e3ec6ff4SXiaoDong Huang 145*e3ec6ff4SXiaoDong Huang /* dsusgrf */ 146*e3ec6ff4SXiaoDong Huang for (i = 0; i < DSUSGRF_SOC_CON_CNT; i++) 147*e3ec6ff4SXiaoDong Huang pmusram_data.dsusgrf_soc_con[i] = 148*e3ec6ff4SXiaoDong Huang mmio_read_32(DSUSGRF_BASE + DSUSGRF_SOC_CON(i)); 149*e3ec6ff4SXiaoDong Huang 150*e3ec6ff4SXiaoDong Huang for (i = 0; i < DSUSGRF_DDR_HASH_CON_CNT; i++) 151*e3ec6ff4SXiaoDong Huang pmusram_data.dsusgrf_ddr_hash_con[i] = 152*e3ec6ff4SXiaoDong Huang mmio_read_32(DSUSGRF_BASE + DSUSGRF_DDR_HASH_CON(i)); 153*e3ec6ff4SXiaoDong Huang 154*e3ec6ff4SXiaoDong Huang /* dsu ddr firewall */ 155*e3ec6ff4SXiaoDong Huang for (i = 0; i < FIREWALL_DSU_RGN_CNT; i++) 156*e3ec6ff4SXiaoDong Huang pmusram_data.dsu_ddr_fw_rgn_reg[i] = 157*e3ec6ff4SXiaoDong Huang mmio_read_32(FIREWALL_DSU_BASE + FIREWALL_DSU_RGN(i)); 158*e3ec6ff4SXiaoDong Huang 159*e3ec6ff4SXiaoDong Huang for (i = 0; i < FIREWALL_DSU_MST_CNT; i++) 160*e3ec6ff4SXiaoDong Huang pmusram_data.dsu_ddr_fw_mst_reg[i] = 161*e3ec6ff4SXiaoDong Huang mmio_read_32(FIREWALL_DSU_BASE + FIREWALL_DSU_MST(i)); 162*e3ec6ff4SXiaoDong Huang 163*e3ec6ff4SXiaoDong Huang for (i = 0; i < FIREWALL_DSU_CON_CNT; i++) 164*e3ec6ff4SXiaoDong Huang pmusram_data.dsu_ddr_fw_con_reg[i] = 165*e3ec6ff4SXiaoDong Huang mmio_read_32(FIREWALL_DSU_BASE + FIREWALL_DSU_CON(i)); 166*e3ec6ff4SXiaoDong Huang 167*e3ec6ff4SXiaoDong Huang pd_dsu_core_save(); 168*e3ec6ff4SXiaoDong Huang } 169*e3ec6ff4SXiaoDong Huang 170*e3ec6ff4SXiaoDong Huang static void dsu_core_restore(void) 171*e3ec6ff4SXiaoDong Huang { 172*e3ec6ff4SXiaoDong Huang pd_dsu_core_restore(); 173*e3ec6ff4SXiaoDong Huang } 174*e3ec6ff4SXiaoDong Huang 175*e3ec6ff4SXiaoDong Huang static uint32_t clk_save[CRU_CLKGATE_CON_CNT + PHPCRU_CLKGATE_CON_CNT + 176*e3ec6ff4SXiaoDong Huang SECURECRU_CLKGATE_CON_CNT + PMU1CRU_CLKGATE_CON_CNT]; 177*e3ec6ff4SXiaoDong Huang 178*e3ec6ff4SXiaoDong Huang void clk_gate_con_save(void) 179*e3ec6ff4SXiaoDong Huang { 180*e3ec6ff4SXiaoDong Huang int i, j = 0; 181*e3ec6ff4SXiaoDong Huang 182*e3ec6ff4SXiaoDong Huang for (i = 0; i < CRU_CLKGATE_CON_CNT; i++, j++) 183*e3ec6ff4SXiaoDong Huang clk_save[j] = mmio_read_32(CRU_BASE + CRU_CLKGATE_CON(i)); 184*e3ec6ff4SXiaoDong Huang 185*e3ec6ff4SXiaoDong Huang clk_save[j] = mmio_read_32(PHP_CRU_BASE + PHPCRU_CLKGATE_CON); 186*e3ec6ff4SXiaoDong Huang 187*e3ec6ff4SXiaoDong Huang for (i = 0; i < SECURECRU_CLKGATE_CON_CNT; i++, j++) 188*e3ec6ff4SXiaoDong Huang clk_save[j] = mmio_read_32(SCRU_BASE + SECURECRU_CLKGATE_CON(i)); 189*e3ec6ff4SXiaoDong Huang 190*e3ec6ff4SXiaoDong Huang for (i = 0; i < PMU1CRU_CLKGATE_CON_CNT; i++, j++) 191*e3ec6ff4SXiaoDong Huang clk_save[j] = mmio_read_32(PMU1CRU_BASE + CRU_CLKGATE_CON(i)); 192*e3ec6ff4SXiaoDong Huang } 193*e3ec6ff4SXiaoDong Huang 194*e3ec6ff4SXiaoDong Huang void clk_gate_con_disable(void) 195*e3ec6ff4SXiaoDong Huang { 196*e3ec6ff4SXiaoDong Huang int i; 197*e3ec6ff4SXiaoDong Huang 198*e3ec6ff4SXiaoDong Huang for (i = 0; i < CRU_CLKGATE_CON_CNT; i++) 199*e3ec6ff4SXiaoDong Huang mmio_write_32(CRU_BASE + CRU_CLKGATE_CON(i), 0xffff0000); 200*e3ec6ff4SXiaoDong Huang 201*e3ec6ff4SXiaoDong Huang mmio_write_32(PHP_CRU_BASE + PHPCRU_CLKGATE_CON, 0xffff0000); 202*e3ec6ff4SXiaoDong Huang 203*e3ec6ff4SXiaoDong Huang for (i = 0; i < SECURECRU_CLKGATE_CON_CNT; i++) 204*e3ec6ff4SXiaoDong Huang mmio_write_32(SCRU_BASE + SECURECRU_CLKGATE_CON(i), 0xffff0000); 205*e3ec6ff4SXiaoDong Huang 206*e3ec6ff4SXiaoDong Huang for (i = 0; i < PMU1CRU_CLKGATE_CON_CNT; i++) 207*e3ec6ff4SXiaoDong Huang mmio_write_32(PMU1CRU_BASE + CRU_CLKGATE_CON(i), 0xffff0000); 208*e3ec6ff4SXiaoDong Huang } 209*e3ec6ff4SXiaoDong Huang 210*e3ec6ff4SXiaoDong Huang void clk_gate_con_restore(void) 211*e3ec6ff4SXiaoDong Huang { 212*e3ec6ff4SXiaoDong Huang int i, j = 0; 213*e3ec6ff4SXiaoDong Huang 214*e3ec6ff4SXiaoDong Huang for (i = 0; i < CRU_CLKGATE_CON_CNT; i++, j++) 215*e3ec6ff4SXiaoDong Huang mmio_write_32(CRU_BASE + CRU_CLKGATE_CON(i), 216*e3ec6ff4SXiaoDong Huang WITH_16BITS_WMSK(clk_save[j])); 217*e3ec6ff4SXiaoDong Huang 218*e3ec6ff4SXiaoDong Huang mmio_write_32(PHP_CRU_BASE + PHPCRU_CLKGATE_CON, 219*e3ec6ff4SXiaoDong Huang WITH_16BITS_WMSK(clk_save[j])); 220*e3ec6ff4SXiaoDong Huang 221*e3ec6ff4SXiaoDong Huang for (i = 0; i < SECURECRU_CLKGATE_CON_CNT; i++, j++) 222*e3ec6ff4SXiaoDong Huang mmio_write_32(SCRU_BASE + SECURECRU_CLKGATE_CON(i), 223*e3ec6ff4SXiaoDong Huang WITH_16BITS_WMSK(clk_save[j])); 224*e3ec6ff4SXiaoDong Huang 225*e3ec6ff4SXiaoDong Huang for (i = 0; i < PMU1CRU_CLKGATE_CON_CNT; i++, j++) 226*e3ec6ff4SXiaoDong Huang mmio_write_32(PMU1CRU_BASE + CRU_CLKGATE_CON(i), 227*e3ec6ff4SXiaoDong Huang WITH_16BITS_WMSK(clk_save[j])); 228*e3ec6ff4SXiaoDong Huang } 229*e3ec6ff4SXiaoDong Huang 230*e3ec6ff4SXiaoDong Huang static void pmu_bus_idle_req(uint32_t bus, uint32_t state) 231*e3ec6ff4SXiaoDong Huang { 232*e3ec6ff4SXiaoDong Huang uint32_t wait_cnt = 0; 233*e3ec6ff4SXiaoDong Huang 234*e3ec6ff4SXiaoDong Huang mmio_write_32(PMU_BASE + PMU2_BUS_IDLE_SFTCON(bus / 16), 235*e3ec6ff4SXiaoDong Huang BITS_WITH_WMASK(state, 0x1, bus % 16)); 236*e3ec6ff4SXiaoDong Huang 237*e3ec6ff4SXiaoDong Huang while (pmu_bus_idle_st(bus) != state || 238*e3ec6ff4SXiaoDong Huang pmu_bus_idle_ack(bus) != state) { 239*e3ec6ff4SXiaoDong Huang if (++wait_cnt > BUS_IDLE_LOOP) 240*e3ec6ff4SXiaoDong Huang break; 241*e3ec6ff4SXiaoDong Huang udelay(1); 242*e3ec6ff4SXiaoDong Huang } 243*e3ec6ff4SXiaoDong Huang 244*e3ec6ff4SXiaoDong Huang if (wait_cnt > BUS_IDLE_LOOP) 245*e3ec6ff4SXiaoDong Huang WARN("%s: can't wait state %d for bus %d (0x%x)\n", 246*e3ec6ff4SXiaoDong Huang __func__, state, bus, 247*e3ec6ff4SXiaoDong Huang mmio_read_32(PMU_BASE + PMU2_BUS_IDLE_ST(bus / 32))); 248*e3ec6ff4SXiaoDong Huang } 249*e3ec6ff4SXiaoDong Huang 250*e3ec6ff4SXiaoDong Huang static void pmu_qch_pwr_ctlr(uint32_t msk, uint32_t state) 251*e3ec6ff4SXiaoDong Huang { 252*e3ec6ff4SXiaoDong Huang uint32_t wait_cnt = 0; 253*e3ec6ff4SXiaoDong Huang 254*e3ec6ff4SXiaoDong Huang if (state != 0) 255*e3ec6ff4SXiaoDong Huang state = msk; 256*e3ec6ff4SXiaoDong Huang 257*e3ec6ff4SXiaoDong Huang mmio_write_32(PMU_BASE + PMU2_QCHANNEL_PWR_SFTCON, 258*e3ec6ff4SXiaoDong Huang BITS_WITH_WMASK(state, msk, 0)); 259*e3ec6ff4SXiaoDong Huang 260*e3ec6ff4SXiaoDong Huang while ((mmio_read_32(PMU_BASE + PMU2_QCHANNEL_STATUS) & msk) != state) { 261*e3ec6ff4SXiaoDong Huang if (++wait_cnt > QCH_PWR_LOOP) 262*e3ec6ff4SXiaoDong Huang break; 263*e3ec6ff4SXiaoDong Huang udelay(1); 264*e3ec6ff4SXiaoDong Huang } 265*e3ec6ff4SXiaoDong Huang 266*e3ec6ff4SXiaoDong Huang if (wait_cnt > BUS_IDLE_LOOP) 267*e3ec6ff4SXiaoDong Huang WARN("%s: can't wait qch:0x%x to state:0x%x (0x%x)\n", 268*e3ec6ff4SXiaoDong Huang __func__, msk, state, 269*e3ec6ff4SXiaoDong Huang mmio_read_32(PMU_BASE + PMU2_QCHANNEL_STATUS)); 270*e3ec6ff4SXiaoDong Huang } 271*e3ec6ff4SXiaoDong Huang 272*e3ec6ff4SXiaoDong Huang static inline uint32_t pmu_power_domain_chain_st(uint32_t pd) 273*e3ec6ff4SXiaoDong Huang { 274*e3ec6ff4SXiaoDong Huang return mmio_read_32(PMU_BASE + PMU2_PWR_CHAIN1_ST(pd / 32)) & BIT(pd % 32) ? 275*e3ec6ff4SXiaoDong Huang pmu_pd_on : 276*e3ec6ff4SXiaoDong Huang pmu_pd_off; 277*e3ec6ff4SXiaoDong Huang } 278*e3ec6ff4SXiaoDong Huang 279*e3ec6ff4SXiaoDong Huang static inline uint32_t pmu_power_domain_mem_st(uint32_t pd) 280*e3ec6ff4SXiaoDong Huang { 281*e3ec6ff4SXiaoDong Huang return mmio_read_32(PMU_BASE + PMU2_PWR_MEM_ST(pd / 32)) & BIT(pd % 32) ? 282*e3ec6ff4SXiaoDong Huang pmu_pd_off : 283*e3ec6ff4SXiaoDong Huang pmu_pd_on; 284*e3ec6ff4SXiaoDong Huang } 285*e3ec6ff4SXiaoDong Huang 286*e3ec6ff4SXiaoDong Huang static inline uint32_t pmu_power_domain_st(uint32_t pd) 287*e3ec6ff4SXiaoDong Huang { 288*e3ec6ff4SXiaoDong Huang int8_t pd_repair = pd_repair_map[pd]; 289*e3ec6ff4SXiaoDong Huang 290*e3ec6ff4SXiaoDong Huang if (pd_repair >= 0) 291*e3ec6ff4SXiaoDong Huang return mmio_read_32(PMU_BASE + PMU2_BISR_STATUS(4)) & BIT(pd_repair) ? 292*e3ec6ff4SXiaoDong Huang pmu_pd_on : 293*e3ec6ff4SXiaoDong Huang pmu_pd_off; 294*e3ec6ff4SXiaoDong Huang else 295*e3ec6ff4SXiaoDong Huang return mmio_read_32(PMU_BASE + PMU2_PWR_GATE_ST(pd / 32)) & BIT(pd % 32) ? 296*e3ec6ff4SXiaoDong Huang pmu_pd_off : 297*e3ec6ff4SXiaoDong Huang pmu_pd_on; 298*e3ec6ff4SXiaoDong Huang } 299*e3ec6ff4SXiaoDong Huang 300*e3ec6ff4SXiaoDong Huang static int pmu_power_domain_pd_to_mem_st(uint32_t pd, uint32_t *pd_mem_st) 301*e3ec6ff4SXiaoDong Huang { 302*e3ec6ff4SXiaoDong Huang uint32_t mem_st; 303*e3ec6ff4SXiaoDong Huang 304*e3ec6ff4SXiaoDong Huang switch (pd) { 305*e3ec6ff4SXiaoDong Huang case PD_NPUTOP: 306*e3ec6ff4SXiaoDong Huang mem_st = PD_NPU_TOP_MEM_ST; 307*e3ec6ff4SXiaoDong Huang break; 308*e3ec6ff4SXiaoDong Huang case PD_NPU1: 309*e3ec6ff4SXiaoDong Huang mem_st = PD_NPU1_MEM_ST; 310*e3ec6ff4SXiaoDong Huang break; 311*e3ec6ff4SXiaoDong Huang case PD_NPU2: 312*e3ec6ff4SXiaoDong Huang mem_st = PD_NPU2_MEM_ST; 313*e3ec6ff4SXiaoDong Huang break; 314*e3ec6ff4SXiaoDong Huang case PD_VENC0: 315*e3ec6ff4SXiaoDong Huang mem_st = PD_VENC0_MEM_ST; 316*e3ec6ff4SXiaoDong Huang break; 317*e3ec6ff4SXiaoDong Huang case PD_VENC1: 318*e3ec6ff4SXiaoDong Huang mem_st = PD_VENC1_MEM_ST; 319*e3ec6ff4SXiaoDong Huang break; 320*e3ec6ff4SXiaoDong Huang case PD_RKVDEC0: 321*e3ec6ff4SXiaoDong Huang mem_st = PD_RKVDEC0_MEM_ST; 322*e3ec6ff4SXiaoDong Huang break; 323*e3ec6ff4SXiaoDong Huang case PD_RKVDEC1: 324*e3ec6ff4SXiaoDong Huang mem_st = PD_RKVDEC1_MEM_ST; 325*e3ec6ff4SXiaoDong Huang break; 326*e3ec6ff4SXiaoDong Huang case PD_RGA30: 327*e3ec6ff4SXiaoDong Huang mem_st = PD_RGA30_MEM_ST; 328*e3ec6ff4SXiaoDong Huang break; 329*e3ec6ff4SXiaoDong Huang case PD_AV1: 330*e3ec6ff4SXiaoDong Huang mem_st = PD_AV1_MEM_ST; 331*e3ec6ff4SXiaoDong Huang break; 332*e3ec6ff4SXiaoDong Huang case PD_VI: 333*e3ec6ff4SXiaoDong Huang mem_st = PD_VI_MEM_ST; 334*e3ec6ff4SXiaoDong Huang break; 335*e3ec6ff4SXiaoDong Huang case PD_FEC: 336*e3ec6ff4SXiaoDong Huang mem_st = PD_FEC_MEM_ST; 337*e3ec6ff4SXiaoDong Huang break; 338*e3ec6ff4SXiaoDong Huang case PD_ISP1: 339*e3ec6ff4SXiaoDong Huang mem_st = PD_ISP1_MEM_ST; 340*e3ec6ff4SXiaoDong Huang break; 341*e3ec6ff4SXiaoDong Huang case PD_RGA31: 342*e3ec6ff4SXiaoDong Huang mem_st = PD_RGA31_MEM_ST; 343*e3ec6ff4SXiaoDong Huang break; 344*e3ec6ff4SXiaoDong Huang case PD_VOP: 345*e3ec6ff4SXiaoDong Huang mem_st = PD_VOP_MEM_ST; 346*e3ec6ff4SXiaoDong Huang break; 347*e3ec6ff4SXiaoDong Huang case PD_VO0: 348*e3ec6ff4SXiaoDong Huang mem_st = PD_VO0_MEM_ST; 349*e3ec6ff4SXiaoDong Huang break; 350*e3ec6ff4SXiaoDong Huang case PD_VO1: 351*e3ec6ff4SXiaoDong Huang mem_st = PD_VO1_MEM_ST; 352*e3ec6ff4SXiaoDong Huang break; 353*e3ec6ff4SXiaoDong Huang case PD_AUDIO: 354*e3ec6ff4SXiaoDong Huang mem_st = PD_AUDIO_MEM_ST; 355*e3ec6ff4SXiaoDong Huang break; 356*e3ec6ff4SXiaoDong Huang case PD_PHP: 357*e3ec6ff4SXiaoDong Huang mem_st = PD_PHP_MEM_ST; 358*e3ec6ff4SXiaoDong Huang break; 359*e3ec6ff4SXiaoDong Huang case PD_GMAC: 360*e3ec6ff4SXiaoDong Huang mem_st = PD_GMAC_MEM_ST; 361*e3ec6ff4SXiaoDong Huang break; 362*e3ec6ff4SXiaoDong Huang case PD_PCIE: 363*e3ec6ff4SXiaoDong Huang mem_st = PD_PCIE_MEM_ST; 364*e3ec6ff4SXiaoDong Huang break; 365*e3ec6ff4SXiaoDong Huang case PD_NVM0: 366*e3ec6ff4SXiaoDong Huang mem_st = PD_NVM0_MEM_ST; 367*e3ec6ff4SXiaoDong Huang break; 368*e3ec6ff4SXiaoDong Huang case PD_SDIO: 369*e3ec6ff4SXiaoDong Huang mem_st = PD_SDIO_MEM_ST; 370*e3ec6ff4SXiaoDong Huang break; 371*e3ec6ff4SXiaoDong Huang case PD_USB: 372*e3ec6ff4SXiaoDong Huang mem_st = PD_USB_MEM_ST; 373*e3ec6ff4SXiaoDong Huang break; 374*e3ec6ff4SXiaoDong Huang case PD_SDMMC: 375*e3ec6ff4SXiaoDong Huang mem_st = PD_SDMMC_MEM_ST; 376*e3ec6ff4SXiaoDong Huang break; 377*e3ec6ff4SXiaoDong Huang default: 378*e3ec6ff4SXiaoDong Huang return -EINVAL; 379*e3ec6ff4SXiaoDong Huang } 380*e3ec6ff4SXiaoDong Huang 381*e3ec6ff4SXiaoDong Huang *pd_mem_st = mem_st; 382*e3ec6ff4SXiaoDong Huang 383*e3ec6ff4SXiaoDong Huang return 0; 384*e3ec6ff4SXiaoDong Huang } 385*e3ec6ff4SXiaoDong Huang 386*e3ec6ff4SXiaoDong Huang static int pmu_power_domain_reset_mem(uint32_t pd, uint32_t pd_mem_st) 387*e3ec6ff4SXiaoDong Huang { 388*e3ec6ff4SXiaoDong Huang uint32_t loop = 0; 389*e3ec6ff4SXiaoDong Huang int ret = 0; 390*e3ec6ff4SXiaoDong Huang 391*e3ec6ff4SXiaoDong Huang while (pmu_power_domain_chain_st(pd_mem_st) != pmu_pd_on) { 392*e3ec6ff4SXiaoDong Huang udelay(1); 393*e3ec6ff4SXiaoDong Huang loop++; 394*e3ec6ff4SXiaoDong Huang if (loop >= PD_CTR_LOOP) { 395*e3ec6ff4SXiaoDong Huang WARN("%s: %d chain up time out\n", __func__, pd); 396*e3ec6ff4SXiaoDong Huang ret = -EINVAL; 397*e3ec6ff4SXiaoDong Huang goto error; 398*e3ec6ff4SXiaoDong Huang } 399*e3ec6ff4SXiaoDong Huang } 400*e3ec6ff4SXiaoDong Huang 401*e3ec6ff4SXiaoDong Huang udelay(60); 402*e3ec6ff4SXiaoDong Huang 403*e3ec6ff4SXiaoDong Huang mmio_write_32(PMU_BASE + PMU2_MEMPWR_GATE_SFTCON(pd / 16), 404*e3ec6ff4SXiaoDong Huang BITS_WITH_WMASK(pmu_pd_off, 0x1, pd % 16)); 405*e3ec6ff4SXiaoDong Huang dsb(); 406*e3ec6ff4SXiaoDong Huang 407*e3ec6ff4SXiaoDong Huang loop = 0; 408*e3ec6ff4SXiaoDong Huang while (pmu_power_domain_mem_st(pd_mem_st) != pmu_pd_off) { 409*e3ec6ff4SXiaoDong Huang udelay(1); 410*e3ec6ff4SXiaoDong Huang loop++; 411*e3ec6ff4SXiaoDong Huang if (loop >= PD_CTR_LOOP) { 412*e3ec6ff4SXiaoDong Huang WARN("%s: %d mem down time out\n", __func__, pd); 413*e3ec6ff4SXiaoDong Huang ret = -EINVAL; 414*e3ec6ff4SXiaoDong Huang goto error; 415*e3ec6ff4SXiaoDong Huang } 416*e3ec6ff4SXiaoDong Huang } 417*e3ec6ff4SXiaoDong Huang 418*e3ec6ff4SXiaoDong Huang mmio_write_32(PMU_BASE + PMU2_MEMPWR_GATE_SFTCON(pd / 16), 419*e3ec6ff4SXiaoDong Huang BITS_WITH_WMASK(pmu_pd_on, 0x1, pd % 16)); 420*e3ec6ff4SXiaoDong Huang dsb(); 421*e3ec6ff4SXiaoDong Huang 422*e3ec6ff4SXiaoDong Huang loop = 0; 423*e3ec6ff4SXiaoDong Huang while (pmu_power_domain_mem_st(pd_mem_st) != pmu_pd_on) { 424*e3ec6ff4SXiaoDong Huang udelay(1); 425*e3ec6ff4SXiaoDong Huang loop++; 426*e3ec6ff4SXiaoDong Huang if (loop >= PD_CTR_LOOP) { 427*e3ec6ff4SXiaoDong Huang WARN("%s: %d mem up time out\n", __func__, pd); 428*e3ec6ff4SXiaoDong Huang ret = -EINVAL; 429*e3ec6ff4SXiaoDong Huang goto error; 430*e3ec6ff4SXiaoDong Huang } 431*e3ec6ff4SXiaoDong Huang } 432*e3ec6ff4SXiaoDong Huang 433*e3ec6ff4SXiaoDong Huang return 0; 434*e3ec6ff4SXiaoDong Huang 435*e3ec6ff4SXiaoDong Huang error: 436*e3ec6ff4SXiaoDong Huang return ret; 437*e3ec6ff4SXiaoDong Huang } 438*e3ec6ff4SXiaoDong Huang 439*e3ec6ff4SXiaoDong Huang static int pmu_power_domain_ctr(uint32_t pd, uint32_t pd_state) 440*e3ec6ff4SXiaoDong Huang { 441*e3ec6ff4SXiaoDong Huang uint32_t loop = 0; 442*e3ec6ff4SXiaoDong Huang uint32_t is_mem_on = pmu_pd_off; 443*e3ec6ff4SXiaoDong Huang uint32_t pd_mem_st; 444*e3ec6ff4SXiaoDong Huang int ret = 0; 445*e3ec6ff4SXiaoDong Huang 446*e3ec6ff4SXiaoDong Huang if (pd_state == pmu_pd_on) { 447*e3ec6ff4SXiaoDong Huang ret = pmu_power_domain_pd_to_mem_st(pd, &pd_mem_st); 448*e3ec6ff4SXiaoDong Huang if (ret == 0) { 449*e3ec6ff4SXiaoDong Huang is_mem_on = pmu_power_domain_mem_st(pd_mem_st); 450*e3ec6ff4SXiaoDong Huang if (is_mem_on == pmu_pd_on) 451*e3ec6ff4SXiaoDong Huang WARN("%s: %d mem is up\n", __func__, pd); 452*e3ec6ff4SXiaoDong Huang } 453*e3ec6ff4SXiaoDong Huang } 454*e3ec6ff4SXiaoDong Huang 455*e3ec6ff4SXiaoDong Huang mmio_write_32(PMU_BASE + PMU2_PWR_GATE_SFTCON(pd / 16), 456*e3ec6ff4SXiaoDong Huang BITS_WITH_WMASK(pd_state, 0x1, pd % 16)); 457*e3ec6ff4SXiaoDong Huang dsb(); 458*e3ec6ff4SXiaoDong Huang 459*e3ec6ff4SXiaoDong Huang if (is_mem_on == pmu_pd_on) { 460*e3ec6ff4SXiaoDong Huang ret = pmu_power_domain_reset_mem(pd, pd_mem_st); 461*e3ec6ff4SXiaoDong Huang if (ret != 0) 462*e3ec6ff4SXiaoDong Huang goto out; 463*e3ec6ff4SXiaoDong Huang WARN("%s: %d mem reset ok\n", __func__, pd); 464*e3ec6ff4SXiaoDong Huang } 465*e3ec6ff4SXiaoDong Huang 466*e3ec6ff4SXiaoDong Huang while ((pmu_power_domain_st(pd) != pd_state) && (loop < PD_CTR_LOOP)) { 467*e3ec6ff4SXiaoDong Huang udelay(1); 468*e3ec6ff4SXiaoDong Huang loop++; 469*e3ec6ff4SXiaoDong Huang } 470*e3ec6ff4SXiaoDong Huang 471*e3ec6ff4SXiaoDong Huang if (pmu_power_domain_st(pd) != pd_state) { 472*e3ec6ff4SXiaoDong Huang WARN("%s: %d, %d, (0x%x, 0x%x) error!\n", __func__, pd, pd_state, 473*e3ec6ff4SXiaoDong Huang mmio_read_32(PMU_BASE + PMU2_PWR_GATE_ST(0)), 474*e3ec6ff4SXiaoDong Huang mmio_read_32(PMU_BASE + PMU2_BISR_STATUS(4))); 475*e3ec6ff4SXiaoDong Huang ret = -EINVAL; 476*e3ec6ff4SXiaoDong Huang } 477*e3ec6ff4SXiaoDong Huang 478*e3ec6ff4SXiaoDong Huang out: 479*e3ec6ff4SXiaoDong Huang return ret; 480*e3ec6ff4SXiaoDong Huang } 481*e3ec6ff4SXiaoDong Huang 482*e3ec6ff4SXiaoDong Huang static int pmu_set_power_domain(uint32_t pd_id, uint32_t pd_state) 483*e3ec6ff4SXiaoDong Huang { 484*e3ec6ff4SXiaoDong Huang uint32_t state; 485*e3ec6ff4SXiaoDong Huang 486*e3ec6ff4SXiaoDong Huang if (pmu_power_domain_st(pd_id) == pd_state) 487*e3ec6ff4SXiaoDong Huang goto out; 488*e3ec6ff4SXiaoDong Huang 489*e3ec6ff4SXiaoDong Huang if (pd_state == pmu_pd_on) 490*e3ec6ff4SXiaoDong Huang pmu_power_domain_ctr(pd_id, pd_state); 491*e3ec6ff4SXiaoDong Huang 492*e3ec6ff4SXiaoDong Huang state = (pd_state == pmu_pd_off) ? bus_idle : bus_active; 493*e3ec6ff4SXiaoDong Huang 494*e3ec6ff4SXiaoDong Huang switch (pd_id) { 495*e3ec6ff4SXiaoDong Huang case PD_GPU: 496*e3ec6ff4SXiaoDong Huang pmu_bus_idle_req(BUS_ID_GPU, state); 497*e3ec6ff4SXiaoDong Huang break; 498*e3ec6ff4SXiaoDong Huang case PD_NPUTOP: 499*e3ec6ff4SXiaoDong Huang pmu_bus_idle_req(BUS_ID_NPUTOP, state); 500*e3ec6ff4SXiaoDong Huang break; 501*e3ec6ff4SXiaoDong Huang case PD_NPU1: 502*e3ec6ff4SXiaoDong Huang pmu_bus_idle_req(BUS_ID_NPU1, state); 503*e3ec6ff4SXiaoDong Huang break; 504*e3ec6ff4SXiaoDong Huang case PD_NPU2: 505*e3ec6ff4SXiaoDong Huang pmu_bus_idle_req(BUS_ID_NPU2, state); 506*e3ec6ff4SXiaoDong Huang break; 507*e3ec6ff4SXiaoDong Huang case PD_VENC0: 508*e3ec6ff4SXiaoDong Huang pmu_bus_idle_req(BUS_ID_RKVENC0, state); 509*e3ec6ff4SXiaoDong Huang break; 510*e3ec6ff4SXiaoDong Huang case PD_VENC1: 511*e3ec6ff4SXiaoDong Huang pmu_bus_idle_req(BUS_ID_RKVENC1, state); 512*e3ec6ff4SXiaoDong Huang break; 513*e3ec6ff4SXiaoDong Huang case PD_RKVDEC0: 514*e3ec6ff4SXiaoDong Huang pmu_bus_idle_req(BUS_ID_RKVDEC0, state); 515*e3ec6ff4SXiaoDong Huang break; 516*e3ec6ff4SXiaoDong Huang case PD_RKVDEC1: 517*e3ec6ff4SXiaoDong Huang pmu_bus_idle_req(BUS_ID_RKVDEC1, state); 518*e3ec6ff4SXiaoDong Huang break; 519*e3ec6ff4SXiaoDong Huang case PD_VDPU: 520*e3ec6ff4SXiaoDong Huang pmu_bus_idle_req(BUS_ID_VDPU, state); 521*e3ec6ff4SXiaoDong Huang break; 522*e3ec6ff4SXiaoDong Huang case PD_AV1: 523*e3ec6ff4SXiaoDong Huang pmu_bus_idle_req(BUS_ID_AV1, state); 524*e3ec6ff4SXiaoDong Huang break; 525*e3ec6ff4SXiaoDong Huang case PD_VI: 526*e3ec6ff4SXiaoDong Huang pmu_bus_idle_req(BUS_ID_VI, state); 527*e3ec6ff4SXiaoDong Huang break; 528*e3ec6ff4SXiaoDong Huang case PD_ISP1: 529*e3ec6ff4SXiaoDong Huang pmu_bus_idle_req(BUS_ID_ISP, state); 530*e3ec6ff4SXiaoDong Huang break; 531*e3ec6ff4SXiaoDong Huang case PD_RGA31: 532*e3ec6ff4SXiaoDong Huang pmu_bus_idle_req(BUS_ID_RGA31, state); 533*e3ec6ff4SXiaoDong Huang break; 534*e3ec6ff4SXiaoDong Huang case PD_VOP: 535*e3ec6ff4SXiaoDong Huang pmu_bus_idle_req(BUS_ID_VOP_CHANNEL, state); 536*e3ec6ff4SXiaoDong Huang pmu_bus_idle_req(BUS_ID_VOP, state); 537*e3ec6ff4SXiaoDong Huang break; 538*e3ec6ff4SXiaoDong Huang case PD_VO0: 539*e3ec6ff4SXiaoDong Huang pmu_bus_idle_req(BUS_ID_VO0, state); 540*e3ec6ff4SXiaoDong Huang break; 541*e3ec6ff4SXiaoDong Huang case PD_VO1: 542*e3ec6ff4SXiaoDong Huang pmu_bus_idle_req(BUS_ID_VO1, state); 543*e3ec6ff4SXiaoDong Huang break; 544*e3ec6ff4SXiaoDong Huang case PD_AUDIO: 545*e3ec6ff4SXiaoDong Huang pmu_bus_idle_req(BUS_ID_AUDIO, state); 546*e3ec6ff4SXiaoDong Huang break; 547*e3ec6ff4SXiaoDong Huang case PD_PHP: 548*e3ec6ff4SXiaoDong Huang pmu_bus_idle_req(BUS_ID_PHP, state); 549*e3ec6ff4SXiaoDong Huang break; 550*e3ec6ff4SXiaoDong Huang case PD_NVM: 551*e3ec6ff4SXiaoDong Huang pmu_bus_idle_req(BUS_ID_NVM, state); 552*e3ec6ff4SXiaoDong Huang break; 553*e3ec6ff4SXiaoDong Huang case PD_SDIO: 554*e3ec6ff4SXiaoDong Huang pmu_bus_idle_req(BUS_ID_SDIO, state); 555*e3ec6ff4SXiaoDong Huang break; 556*e3ec6ff4SXiaoDong Huang case PD_USB: 557*e3ec6ff4SXiaoDong Huang pmu_bus_idle_req(BUS_ID_USB, state); 558*e3ec6ff4SXiaoDong Huang break; 559*e3ec6ff4SXiaoDong Huang case PD_SECURE: 560*e3ec6ff4SXiaoDong Huang pmu_bus_idle_req(BUS_ID_SECURE, state); 561*e3ec6ff4SXiaoDong Huang break; 562*e3ec6ff4SXiaoDong Huang default: 563*e3ec6ff4SXiaoDong Huang break; 564*e3ec6ff4SXiaoDong Huang } 565*e3ec6ff4SXiaoDong Huang 566*e3ec6ff4SXiaoDong Huang if (pd_state == pmu_pd_off) 567*e3ec6ff4SXiaoDong Huang pmu_power_domain_ctr(pd_id, pd_state); 568*e3ec6ff4SXiaoDong Huang 569*e3ec6ff4SXiaoDong Huang out: 570*e3ec6ff4SXiaoDong Huang return 0; 571*e3ec6ff4SXiaoDong Huang } 572*e3ec6ff4SXiaoDong Huang 573*e3ec6ff4SXiaoDong Huang static void pmu_power_domains_suspend(void) 574*e3ec6ff4SXiaoDong Huang { 575*e3ec6ff4SXiaoDong Huang ddr_data.qch_pwr_st = 576*e3ec6ff4SXiaoDong Huang mmio_read_32(PMU_BASE + PMU2_QCHANNEL_STATUS) & PMU2_QCH_PWR_MSK; 577*e3ec6ff4SXiaoDong Huang ddr_data.pmu_pd_st0 = mmio_read_32(PMU_BASE + PMU2_PWR_GATE_ST(0)); 578*e3ec6ff4SXiaoDong Huang ddr_data.bus_idle_st0 = mmio_read_32(PMU_BASE + PMU2_BUS_IDLE_ST(0)); 579*e3ec6ff4SXiaoDong Huang 580*e3ec6ff4SXiaoDong Huang qos_save(); 581*e3ec6ff4SXiaoDong Huang 582*e3ec6ff4SXiaoDong Huang if ((ddr_data.pmu_pd_st0 & BIT(PD_PHP)) == 0) 583*e3ec6ff4SXiaoDong Huang pd_php_save(); 584*e3ec6ff4SXiaoDong Huang 585*e3ec6ff4SXiaoDong Huang if ((ddr_data.pmu_pd_st0 & BIT(PD_CRYPTO)) == 0) 586*e3ec6ff4SXiaoDong Huang pd_crypto_save(); 587*e3ec6ff4SXiaoDong Huang 588*e3ec6ff4SXiaoDong Huang pmu_qch_pwr_ctlr(0x20, 1); 589*e3ec6ff4SXiaoDong Huang pmu_qch_pwr_ctlr(0x40, 1); 590*e3ec6ff4SXiaoDong Huang pmu_qch_pwr_ctlr(0x1, 1); 591*e3ec6ff4SXiaoDong Huang pmu_qch_pwr_ctlr(0x2, 1); 592*e3ec6ff4SXiaoDong Huang pmu_qch_pwr_ctlr(0x4, 1); 593*e3ec6ff4SXiaoDong Huang pmu_qch_pwr_ctlr(0x8, 1); 594*e3ec6ff4SXiaoDong Huang pmu_qch_pwr_ctlr(0x10, 1); 595*e3ec6ff4SXiaoDong Huang 596*e3ec6ff4SXiaoDong Huang pmu_bus_idle_req(BUS_ID_VO1USBTOP, bus_idle); 597*e3ec6ff4SXiaoDong Huang pmu_bus_idle_req(BUS_ID_SECURE_VO1USB_CHANNEL, bus_idle); 598*e3ec6ff4SXiaoDong Huang 599*e3ec6ff4SXiaoDong Huang pmu_bus_idle_req(BUS_ID_USB, bus_idle); 600*e3ec6ff4SXiaoDong Huang 601*e3ec6ff4SXiaoDong Huang pmu_set_power_domain(PD_GPU, pmu_pd_off); 602*e3ec6ff4SXiaoDong Huang 603*e3ec6ff4SXiaoDong Huang pmu_set_power_domain(PD_NPU1, pmu_pd_off); 604*e3ec6ff4SXiaoDong Huang pmu_set_power_domain(PD_NPU2, pmu_pd_off); 605*e3ec6ff4SXiaoDong Huang pmu_set_power_domain(PD_NPUTOP, pmu_pd_off); 606*e3ec6ff4SXiaoDong Huang pmu_set_power_domain(PD_NPU, pmu_pd_off); 607*e3ec6ff4SXiaoDong Huang 608*e3ec6ff4SXiaoDong Huang pmu_set_power_domain(PD_RKVDEC1, pmu_pd_off); 609*e3ec6ff4SXiaoDong Huang pmu_set_power_domain(PD_RKVDEC0, pmu_pd_off); 610*e3ec6ff4SXiaoDong Huang pmu_set_power_domain(PD_VENC1, pmu_pd_off); 611*e3ec6ff4SXiaoDong Huang pmu_set_power_domain(PD_VENC0, pmu_pd_off); 612*e3ec6ff4SXiaoDong Huang pmu_set_power_domain(PD_VCODEC, pmu_pd_off); 613*e3ec6ff4SXiaoDong Huang 614*e3ec6ff4SXiaoDong Huang pmu_set_power_domain(PD_RGA30, pmu_pd_off); 615*e3ec6ff4SXiaoDong Huang pmu_set_power_domain(PD_AV1, pmu_pd_off); 616*e3ec6ff4SXiaoDong Huang pmu_set_power_domain(PD_VDPU, pmu_pd_off); 617*e3ec6ff4SXiaoDong Huang 618*e3ec6ff4SXiaoDong Huang pmu_set_power_domain(PD_VO0, pmu_pd_off); 619*e3ec6ff4SXiaoDong Huang pmu_set_power_domain(PD_VO1, pmu_pd_off); 620*e3ec6ff4SXiaoDong Huang pmu_set_power_domain(PD_VOP, pmu_pd_off); 621*e3ec6ff4SXiaoDong Huang 622*e3ec6ff4SXiaoDong Huang pmu_set_power_domain(PD_FEC, pmu_pd_off); 623*e3ec6ff4SXiaoDong Huang pmu_set_power_domain(PD_ISP1, pmu_pd_off); 624*e3ec6ff4SXiaoDong Huang pmu_set_power_domain(PD_VI, pmu_pd_off); 625*e3ec6ff4SXiaoDong Huang 626*e3ec6ff4SXiaoDong Huang pmu_set_power_domain(PD_RGA31, pmu_pd_off); 627*e3ec6ff4SXiaoDong Huang 628*e3ec6ff4SXiaoDong Huang pmu_set_power_domain(PD_AUDIO, pmu_pd_off); 629*e3ec6ff4SXiaoDong Huang 630*e3ec6ff4SXiaoDong Huang pmu_set_power_domain(PD_GMAC, pmu_pd_off); 631*e3ec6ff4SXiaoDong Huang pmu_set_power_domain(PD_PCIE, pmu_pd_off); 632*e3ec6ff4SXiaoDong Huang pmu_set_power_domain(PD_PHP, pmu_pd_off); 633*e3ec6ff4SXiaoDong Huang 634*e3ec6ff4SXiaoDong Huang pmu_set_power_domain(PD_SDIO, pmu_pd_off); 635*e3ec6ff4SXiaoDong Huang 636*e3ec6ff4SXiaoDong Huang pmu_set_power_domain(PD_NVM0, pmu_pd_off); 637*e3ec6ff4SXiaoDong Huang pmu_set_power_domain(PD_NVM, pmu_pd_off); 638*e3ec6ff4SXiaoDong Huang 639*e3ec6ff4SXiaoDong Huang pmu_set_power_domain(PD_SDMMC, pmu_pd_off); 640*e3ec6ff4SXiaoDong Huang pmu_set_power_domain(PD_CRYPTO, pmu_pd_off); 641*e3ec6ff4SXiaoDong Huang } 642*e3ec6ff4SXiaoDong Huang 643*e3ec6ff4SXiaoDong Huang static void pmu_power_domains_resume(void) 644*e3ec6ff4SXiaoDong Huang { 645*e3ec6ff4SXiaoDong Huang int i; 646*e3ec6ff4SXiaoDong Huang 647*e3ec6ff4SXiaoDong Huang pmu_set_power_domain(PD_CRYPTO, !!(ddr_data.pmu_pd_st0 & BIT(PD_CRYPTO))); 648*e3ec6ff4SXiaoDong Huang pmu_set_power_domain(PD_SDMMC, !!(ddr_data.pmu_pd_st0 & BIT(PD_SDMMC))); 649*e3ec6ff4SXiaoDong Huang 650*e3ec6ff4SXiaoDong Huang pmu_set_power_domain(PD_NVM, !!(ddr_data.pmu_pd_st0 & BIT(PD_NVM))); 651*e3ec6ff4SXiaoDong Huang pmu_set_power_domain(PD_NVM0, !!(ddr_data.pmu_pd_st0 & BIT(PD_NVM0))); 652*e3ec6ff4SXiaoDong Huang 653*e3ec6ff4SXiaoDong Huang pmu_set_power_domain(PD_SDIO, !!(ddr_data.pmu_pd_st0 & BIT(PD_SDIO))); 654*e3ec6ff4SXiaoDong Huang 655*e3ec6ff4SXiaoDong Huang pmu_set_power_domain(PD_PHP, !!(ddr_data.pmu_pd_st0 & BIT(PD_PHP))); 656*e3ec6ff4SXiaoDong Huang pmu_set_power_domain(PD_PCIE, !!(ddr_data.pmu_pd_st0 & BIT(PD_PCIE))); 657*e3ec6ff4SXiaoDong Huang pmu_set_power_domain(PD_GMAC, !!(ddr_data.pmu_pd_st0 & BIT(PD_GMAC))); 658*e3ec6ff4SXiaoDong Huang 659*e3ec6ff4SXiaoDong Huang pmu_set_power_domain(PD_AUDIO, !!(ddr_data.pmu_pd_st0 & BIT(PD_AUDIO))); 660*e3ec6ff4SXiaoDong Huang 661*e3ec6ff4SXiaoDong Huang pmu_set_power_domain(PD_USB, !!(ddr_data.pmu_pd_st0 & BIT(PD_USB))); 662*e3ec6ff4SXiaoDong Huang 663*e3ec6ff4SXiaoDong Huang pmu_set_power_domain(PD_RGA31, !!(ddr_data.pmu_pd_st0 & BIT(PD_RGA31))); 664*e3ec6ff4SXiaoDong Huang 665*e3ec6ff4SXiaoDong Huang pmu_set_power_domain(PD_VI, !!(ddr_data.pmu_pd_st0 & BIT(PD_VI))); 666*e3ec6ff4SXiaoDong Huang pmu_set_power_domain(PD_ISP1, !!(ddr_data.pmu_pd_st0 & BIT(PD_ISP1))); 667*e3ec6ff4SXiaoDong Huang pmu_set_power_domain(PD_FEC, !!(ddr_data.pmu_pd_st0 & BIT(PD_FEC))); 668*e3ec6ff4SXiaoDong Huang 669*e3ec6ff4SXiaoDong Huang pmu_set_power_domain(PD_VOP, !!(ddr_data.pmu_pd_st0 & BIT(PD_VOP))); 670*e3ec6ff4SXiaoDong Huang 671*e3ec6ff4SXiaoDong Huang pmu_set_power_domain(PD_VO1, !!(ddr_data.pmu_pd_st0 & BIT(PD_VO1))); 672*e3ec6ff4SXiaoDong Huang 673*e3ec6ff4SXiaoDong Huang pmu_set_power_domain(PD_VO0, !!(ddr_data.pmu_pd_st0 & BIT(PD_VO0))); 674*e3ec6ff4SXiaoDong Huang 675*e3ec6ff4SXiaoDong Huang pmu_set_power_domain(PD_VDPU, !!(ddr_data.pmu_pd_st0 & BIT(PD_VDPU))); 676*e3ec6ff4SXiaoDong Huang pmu_set_power_domain(PD_AV1, !!(ddr_data.pmu_pd_st0 & BIT(PD_AV1))); 677*e3ec6ff4SXiaoDong Huang pmu_set_power_domain(PD_RGA30, !!(ddr_data.pmu_pd_st0 & BIT(PD_RGA30))); 678*e3ec6ff4SXiaoDong Huang 679*e3ec6ff4SXiaoDong Huang pmu_set_power_domain(PD_VCODEC, !!(ddr_data.pmu_pd_st0 & BIT(PD_VCODEC))); 680*e3ec6ff4SXiaoDong Huang pmu_set_power_domain(PD_VENC0, !!(ddr_data.pmu_pd_st0 & BIT(PD_VENC0))); 681*e3ec6ff4SXiaoDong Huang pmu_set_power_domain(PD_VENC1, !!(ddr_data.pmu_pd_st0 & BIT(PD_VENC1))); 682*e3ec6ff4SXiaoDong Huang pmu_set_power_domain(PD_RKVDEC0, !!(ddr_data.pmu_pd_st0 & BIT(PD_RKVDEC0))); 683*e3ec6ff4SXiaoDong Huang pmu_set_power_domain(PD_RKVDEC1, !!(ddr_data.pmu_pd_st0 & BIT(PD_RKVDEC1))); 684*e3ec6ff4SXiaoDong Huang 685*e3ec6ff4SXiaoDong Huang pmu_set_power_domain(PD_NPU, !!(ddr_data.pmu_pd_st0 & BIT(PD_NPU))); 686*e3ec6ff4SXiaoDong Huang pmu_set_power_domain(PD_NPUTOP, !!(ddr_data.pmu_pd_st0 & BIT(PD_NPUTOP))); 687*e3ec6ff4SXiaoDong Huang pmu_set_power_domain(PD_NPU2, !!(ddr_data.pmu_pd_st0 & BIT(PD_NPU2))); 688*e3ec6ff4SXiaoDong Huang pmu_set_power_domain(PD_NPU1, !!(ddr_data.pmu_pd_st0 & BIT(PD_NPU1))); 689*e3ec6ff4SXiaoDong Huang 690*e3ec6ff4SXiaoDong Huang pmu_set_power_domain(PD_GPU, !!(ddr_data.pmu_pd_st0 & BIT(PD_GPU))); 691*e3ec6ff4SXiaoDong Huang 692*e3ec6ff4SXiaoDong Huang for (i = 0; i < 32; i++) 693*e3ec6ff4SXiaoDong Huang pmu_bus_idle_req(i, !!(ddr_data.bus_idle_st0 & BIT(i))); 694*e3ec6ff4SXiaoDong Huang 695*e3ec6ff4SXiaoDong Huang pmu_qch_pwr_ctlr(0x10, !!(ddr_data.qch_pwr_st & 0x10)); 696*e3ec6ff4SXiaoDong Huang pmu_qch_pwr_ctlr(0x8, !!(ddr_data.qch_pwr_st & 0x8)); 697*e3ec6ff4SXiaoDong Huang pmu_qch_pwr_ctlr(0x4, !!(ddr_data.qch_pwr_st & 0x4)); 698*e3ec6ff4SXiaoDong Huang pmu_qch_pwr_ctlr(0x2, !!(ddr_data.qch_pwr_st & 0x2)); 699*e3ec6ff4SXiaoDong Huang pmu_qch_pwr_ctlr(0x1, !!(ddr_data.qch_pwr_st & 0x1)); 700*e3ec6ff4SXiaoDong Huang pmu_qch_pwr_ctlr(0x40, !!(ddr_data.qch_pwr_st & 0x40)); 701*e3ec6ff4SXiaoDong Huang pmu_qch_pwr_ctlr(0x20, !!(ddr_data.qch_pwr_st & 0x20)); 702*e3ec6ff4SXiaoDong Huang 703*e3ec6ff4SXiaoDong Huang if ((ddr_data.pmu_pd_st0 & BIT(PD_CRYPTO)) == 0) 704*e3ec6ff4SXiaoDong Huang pd_crypto_restore(); 705*e3ec6ff4SXiaoDong Huang 706*e3ec6ff4SXiaoDong Huang if ((ddr_data.pmu_pd_st0 & BIT(PD_PHP)) == 0) 707*e3ec6ff4SXiaoDong Huang pd_php_restore(); 708*e3ec6ff4SXiaoDong Huang 709*e3ec6ff4SXiaoDong Huang qos_restore(); 710*e3ec6ff4SXiaoDong Huang } 711*e3ec6ff4SXiaoDong Huang 712*e3ec6ff4SXiaoDong Huang static int cpus_power_domain_on(uint32_t cpu_id) 713*e3ec6ff4SXiaoDong Huang { 714*e3ec6ff4SXiaoDong Huang mmio_write_32(PMU_BASE + PMU2_CPU_AUTO_PWR_CON(cpu_id), 715*e3ec6ff4SXiaoDong Huang BITS_WITH_WMASK(0, 0x1, core_pm_en)); 716*e3ec6ff4SXiaoDong Huang mmio_write_32(PMU_BASE + PMU2_CPU_AUTO_PWR_CON(cpu_id), 717*e3ec6ff4SXiaoDong Huang BITS_WITH_WMASK(1, 0x1, core_pm_sft_wakeup_en)); 718*e3ec6ff4SXiaoDong Huang dsb(); 719*e3ec6ff4SXiaoDong Huang 720*e3ec6ff4SXiaoDong Huang return 0; 721*e3ec6ff4SXiaoDong Huang } 722*e3ec6ff4SXiaoDong Huang 723*e3ec6ff4SXiaoDong Huang static int cpus_power_domain_off(uint32_t cpu_id, uint32_t pd_cfg) 724*e3ec6ff4SXiaoDong Huang { 725*e3ec6ff4SXiaoDong Huang uint32_t apm_value = BIT(core_pm_en); 726*e3ec6ff4SXiaoDong Huang 727*e3ec6ff4SXiaoDong Huang if (pd_cfg == core_pwr_wfi_int) 728*e3ec6ff4SXiaoDong Huang apm_value |= BIT(core_pm_int_wakeup_en); 729*e3ec6ff4SXiaoDong Huang 730*e3ec6ff4SXiaoDong Huang mmio_write_32(PMU_BASE + PMU2_CPU_AUTO_PWR_CON(cpu_id), 731*e3ec6ff4SXiaoDong Huang BITS_WITH_WMASK(apm_value, 0x3, 0)); 732*e3ec6ff4SXiaoDong Huang dsb(); 733*e3ec6ff4SXiaoDong Huang 734*e3ec6ff4SXiaoDong Huang return 0; 735*e3ec6ff4SXiaoDong Huang } 736*e3ec6ff4SXiaoDong Huang 737*e3ec6ff4SXiaoDong Huang static inline void cpus_pd_req_enter_wfi(void) 738*e3ec6ff4SXiaoDong Huang { 739*e3ec6ff4SXiaoDong Huang /* CORTEX_A55_CPUACTLR_EL1 */ 740*e3ec6ff4SXiaoDong Huang __asm__ volatile ("msr DBGPRCR_EL1, xzr\n" 741*e3ec6ff4SXiaoDong Huang "mrs x0, S3_0_C15_C2_7\n" 742*e3ec6ff4SXiaoDong Huang "orr x0, x0, #0x1\n" 743*e3ec6ff4SXiaoDong Huang "msr S3_0_C15_C2_7, x0\n" 744*e3ec6ff4SXiaoDong Huang "wfi_loop:\n" 745*e3ec6ff4SXiaoDong Huang "isb\n" 746*e3ec6ff4SXiaoDong Huang "wfi\n" 747*e3ec6ff4SXiaoDong Huang "b wfi_loop\n"); 748*e3ec6ff4SXiaoDong Huang } 749*e3ec6ff4SXiaoDong Huang 750*e3ec6ff4SXiaoDong Huang static void nonboot_cpus_off(void) 751*e3ec6ff4SXiaoDong Huang { 752*e3ec6ff4SXiaoDong Huang uint32_t boot_cpu, cpu, tmp; 753*e3ec6ff4SXiaoDong Huang uint32_t exp_st; 754*e3ec6ff4SXiaoDong Huang uint32_t bcore0_rst_msk = 0, bcore1_rst_msk = 0; 755*e3ec6ff4SXiaoDong Huang int wait_cnt; 756*e3ec6ff4SXiaoDong Huang 757*e3ec6ff4SXiaoDong Huang bcore0_rst_msk = CRU_BIGCPU02_RST_MSK | CRU_BIGCPU13_RST_MSK; 758*e3ec6ff4SXiaoDong Huang bcore1_rst_msk = CRU_BIGCPU02_RST_MSK | CRU_BIGCPU13_RST_MSK; 759*e3ec6ff4SXiaoDong Huang 760*e3ec6ff4SXiaoDong Huang mmio_write_32(BIGCORE0CRU_BASE + 0xa00, BITS_WITH_WMASK(0, bcore0_rst_msk, 0)); 761*e3ec6ff4SXiaoDong Huang mmio_write_32(BIGCORE1CRU_BASE + 0xa00, BITS_WITH_WMASK(0, bcore1_rst_msk, 0)); 762*e3ec6ff4SXiaoDong Huang 763*e3ec6ff4SXiaoDong Huang wait_cnt = NONBOOT_CPUS_OFF_LOOP; 764*e3ec6ff4SXiaoDong Huang exp_st = SYS_GRF_BIG_CPUS_WFE; 765*e3ec6ff4SXiaoDong Huang do { 766*e3ec6ff4SXiaoDong Huang wait_cnt--; 767*e3ec6ff4SXiaoDong Huang tmp = mmio_read_32(SYSGRF_BASE + SYS_GRF_SOC_STATUS(3)); 768*e3ec6ff4SXiaoDong Huang tmp &= SYS_GRF_BIG_CPUS_WFE; 769*e3ec6ff4SXiaoDong Huang } while (tmp != exp_st && wait_cnt); 770*e3ec6ff4SXiaoDong Huang 771*e3ec6ff4SXiaoDong Huang boot_cpu = plat_my_core_pos(); 772*e3ec6ff4SXiaoDong Huang 773*e3ec6ff4SXiaoDong Huang /* turn off noboot cpus */ 774*e3ec6ff4SXiaoDong Huang for (cpu = 0; cpu < PLATFORM_CORE_COUNT; cpu++) { 775*e3ec6ff4SXiaoDong Huang if (cpu == boot_cpu) 776*e3ec6ff4SXiaoDong Huang continue; 777*e3ec6ff4SXiaoDong Huang cpus_power_domain_off(cpu, core_pwr_wfi); 778*e3ec6ff4SXiaoDong Huang } 779*e3ec6ff4SXiaoDong Huang 780*e3ec6ff4SXiaoDong Huang mmio_write_32(SRAM_BASE + 0x08, (uintptr_t)&cpus_pd_req_enter_wfi); 781*e3ec6ff4SXiaoDong Huang mmio_write_32(SRAM_BASE + 0x04, 0xdeadbeaf); 782*e3ec6ff4SXiaoDong Huang 783*e3ec6ff4SXiaoDong Huang dsb(); 784*e3ec6ff4SXiaoDong Huang isb(); 785*e3ec6ff4SXiaoDong Huang 786*e3ec6ff4SXiaoDong Huang sev(); 787*e3ec6ff4SXiaoDong Huang 788*e3ec6ff4SXiaoDong Huang wait_cnt = NONBOOT_CPUS_OFF_LOOP; 789*e3ec6ff4SXiaoDong Huang do { 790*e3ec6ff4SXiaoDong Huang wait_cnt--; 791*e3ec6ff4SXiaoDong Huang tmp = mmio_read_32(PMU_BASE + PMU2_CLUSTER_ST); 792*e3ec6ff4SXiaoDong Huang tmp &= CLUSTER_STS_NONBOOT_CPUS_DWN; 793*e3ec6ff4SXiaoDong Huang } while (tmp != CLUSTER_STS_NONBOOT_CPUS_DWN && wait_cnt); 794*e3ec6ff4SXiaoDong Huang 795*e3ec6ff4SXiaoDong Huang if (tmp != CLUSTER_STS_NONBOOT_CPUS_DWN) 796*e3ec6ff4SXiaoDong Huang ERROR("nonboot cpus status(%x) error!\n", tmp); 797*e3ec6ff4SXiaoDong Huang } 798*e3ec6ff4SXiaoDong Huang 799*e3ec6ff4SXiaoDong Huang int rockchip_soc_cores_pwr_dm_on(unsigned long mpidr, 800*e3ec6ff4SXiaoDong Huang uint64_t entrypoint) 801*e3ec6ff4SXiaoDong Huang { 802*e3ec6ff4SXiaoDong Huang uint32_t cpu_id = plat_core_pos_by_mpidr(mpidr); 803*e3ec6ff4SXiaoDong Huang 804*e3ec6ff4SXiaoDong Huang assert(cpu_id < PLATFORM_CORE_COUNT); 805*e3ec6ff4SXiaoDong Huang assert(cpuson_flags[cpu_id] == 0); 806*e3ec6ff4SXiaoDong Huang cpuson_flags[cpu_id] = PMU_CPU_HOTPLUG; 807*e3ec6ff4SXiaoDong Huang cpuson_entry_point[cpu_id] = entrypoint; 808*e3ec6ff4SXiaoDong Huang dsb(); 809*e3ec6ff4SXiaoDong Huang 810*e3ec6ff4SXiaoDong Huang flush_dcache_range((uintptr_t)cpuson_flags, sizeof(cpuson_flags)); 811*e3ec6ff4SXiaoDong Huang flush_dcache_range((uintptr_t)cpuson_entry_point, 812*e3ec6ff4SXiaoDong Huang sizeof(cpuson_entry_point)); 813*e3ec6ff4SXiaoDong Huang dsb(); 814*e3ec6ff4SXiaoDong Huang isb(); 815*e3ec6ff4SXiaoDong Huang 816*e3ec6ff4SXiaoDong Huang cpus_power_domain_on(cpu_id); 817*e3ec6ff4SXiaoDong Huang 818*e3ec6ff4SXiaoDong Huang return PSCI_E_SUCCESS; 819*e3ec6ff4SXiaoDong Huang } 820*e3ec6ff4SXiaoDong Huang 821*e3ec6ff4SXiaoDong Huang int rockchip_soc_cores_pwr_dm_on_finish(void) 822*e3ec6ff4SXiaoDong Huang { 823*e3ec6ff4SXiaoDong Huang uint32_t cpu_id = plat_my_core_pos(); 824*e3ec6ff4SXiaoDong Huang 825*e3ec6ff4SXiaoDong Huang mmio_write_32(PMU_BASE + PMU2_CPU_AUTO_PWR_CON(cpu_id), 826*e3ec6ff4SXiaoDong Huang BITS_WITH_WMASK(0, 0xf, 0)); 827*e3ec6ff4SXiaoDong Huang 828*e3ec6ff4SXiaoDong Huang return PSCI_E_SUCCESS; 829*e3ec6ff4SXiaoDong Huang } 830*e3ec6ff4SXiaoDong Huang 831*e3ec6ff4SXiaoDong Huang int rockchip_soc_cores_pwr_dm_off(void) 832*e3ec6ff4SXiaoDong Huang { 833*e3ec6ff4SXiaoDong Huang uint32_t cpu_id = plat_my_core_pos(); 834*e3ec6ff4SXiaoDong Huang 835*e3ec6ff4SXiaoDong Huang cpus_power_domain_off(cpu_id, core_pwr_wfi); 836*e3ec6ff4SXiaoDong Huang 837*e3ec6ff4SXiaoDong Huang return PSCI_E_SUCCESS; 838*e3ec6ff4SXiaoDong Huang } 839*e3ec6ff4SXiaoDong Huang 840*e3ec6ff4SXiaoDong Huang int rockchip_soc_cores_pwr_dm_suspend(void) 841*e3ec6ff4SXiaoDong Huang { 842*e3ec6ff4SXiaoDong Huang uint32_t cpu_id = plat_my_core_pos(); 843*e3ec6ff4SXiaoDong Huang 844*e3ec6ff4SXiaoDong Huang assert(cpu_id < PLATFORM_CORE_COUNT); 845*e3ec6ff4SXiaoDong Huang 846*e3ec6ff4SXiaoDong Huang cpuson_flags[cpu_id] = PMU_CPU_AUTO_PWRDN; 847*e3ec6ff4SXiaoDong Huang cpuson_entry_point[cpu_id] = plat_get_sec_entrypoint(); 848*e3ec6ff4SXiaoDong Huang dsb(); 849*e3ec6ff4SXiaoDong Huang flush_dcache_range((uintptr_t)cpuson_flags, sizeof(cpuson_flags)); 850*e3ec6ff4SXiaoDong Huang flush_dcache_range((uintptr_t)cpuson_entry_point, 851*e3ec6ff4SXiaoDong Huang sizeof(cpuson_entry_point)); 852*e3ec6ff4SXiaoDong Huang dsb(); 853*e3ec6ff4SXiaoDong Huang isb(); 854*e3ec6ff4SXiaoDong Huang 855*e3ec6ff4SXiaoDong Huang cpus_power_domain_off(cpu_id, core_pwr_wfi_int); 856*e3ec6ff4SXiaoDong Huang 857*e3ec6ff4SXiaoDong Huang __asm__ volatile ("msr DBGPRCR_EL1, xzr\n" 858*e3ec6ff4SXiaoDong Huang "mrs x0, S3_0_C15_C2_7\n" 859*e3ec6ff4SXiaoDong Huang "orr x0, x0, #0x1\n" 860*e3ec6ff4SXiaoDong Huang "msr S3_0_C15_C2_7, x0\n"); 861*e3ec6ff4SXiaoDong Huang 862*e3ec6ff4SXiaoDong Huang return PSCI_E_SUCCESS; 863*e3ec6ff4SXiaoDong Huang } 864*e3ec6ff4SXiaoDong Huang 865*e3ec6ff4SXiaoDong Huang int rockchip_soc_cores_pwr_dm_resume(void) 866*e3ec6ff4SXiaoDong Huang { 867*e3ec6ff4SXiaoDong Huang uint32_t cpu_id = plat_my_core_pos(); 868*e3ec6ff4SXiaoDong Huang 869*e3ec6ff4SXiaoDong Huang mmio_write_32(PMU_BASE + PMU2_CPU_AUTO_PWR_CON(cpu_id), 870*e3ec6ff4SXiaoDong Huang BITS_WITH_WMASK(0, 0x3, 0)); 871*e3ec6ff4SXiaoDong Huang 872*e3ec6ff4SXiaoDong Huang dsb(); 873*e3ec6ff4SXiaoDong Huang 874*e3ec6ff4SXiaoDong Huang return PSCI_E_SUCCESS; 875*e3ec6ff4SXiaoDong Huang } 876*e3ec6ff4SXiaoDong Huang 877*e3ec6ff4SXiaoDong Huang static void ddr_sleep_config(void) 878*e3ec6ff4SXiaoDong Huang { 879*e3ec6ff4SXiaoDong Huang int i; 880*e3ec6ff4SXiaoDong Huang 881*e3ec6ff4SXiaoDong Huang if (pmu_power_domain_st(PD_DDR01) == 0) { 882*e3ec6ff4SXiaoDong Huang ddr_data.ddrgrf_chn_con0[0] = 883*e3ec6ff4SXiaoDong Huang mmio_read_32(DDR01GRF_BASE + DDRGRF_CHA_CON(0)); 884*e3ec6ff4SXiaoDong Huang ddr_data.ddrgrf_chn_con0[1] = 885*e3ec6ff4SXiaoDong Huang mmio_read_32(DDR01GRF_BASE + DDRGRF_CHB_CON(0)); 886*e3ec6ff4SXiaoDong Huang ddr_data.ddrgrf_chn_con1[0] = 887*e3ec6ff4SXiaoDong Huang mmio_read_32(DDR01GRF_BASE + DDRGRF_CHA_CON(1)); 888*e3ec6ff4SXiaoDong Huang ddr_data.ddrgrf_chn_con1[1] = 889*e3ec6ff4SXiaoDong Huang mmio_read_32(DDR01GRF_BASE + DDRGRF_CHB_CON(1)); 890*e3ec6ff4SXiaoDong Huang ddr_data.ddrgrf_chn_con2[0] = 891*e3ec6ff4SXiaoDong Huang mmio_read_32(DDR01GRF_BASE + DDRGRF_CHA_CON(2)); 892*e3ec6ff4SXiaoDong Huang ddr_data.ddrgrf_chn_con2[1] = 893*e3ec6ff4SXiaoDong Huang mmio_read_32(DDR01GRF_BASE + DDRGRF_CHB_CON(2)); 894*e3ec6ff4SXiaoDong Huang 895*e3ec6ff4SXiaoDong Huang mmio_write_32(DDR01GRF_BASE + DDRGRF_CHA_CON(2), 0x20002000); 896*e3ec6ff4SXiaoDong Huang mmio_write_32(DDR01GRF_BASE + DDRGRF_CHB_CON(2), 0x20002000); 897*e3ec6ff4SXiaoDong Huang mmio_write_32(DDR01GRF_BASE + DDRGRF_CHA_CON(2), 0x08000000); 898*e3ec6ff4SXiaoDong Huang mmio_write_32(DDR01GRF_BASE + DDRGRF_CHB_CON(2), 0x08000000); 899*e3ec6ff4SXiaoDong Huang mmio_write_32(DDR01GRF_BASE + DDRGRF_CHA_CON(0), 0x00200020); 900*e3ec6ff4SXiaoDong Huang mmio_write_32(DDR01GRF_BASE + DDRGRF_CHB_CON(0), 0x00200020); 901*e3ec6ff4SXiaoDong Huang mmio_write_32(DDR01GRF_BASE + DDRGRF_CHA_CON(1), 0x00400040); 902*e3ec6ff4SXiaoDong Huang mmio_write_32(DDR01GRF_BASE + DDRGRF_CHB_CON(1), 0x00400040); 903*e3ec6ff4SXiaoDong Huang } 904*e3ec6ff4SXiaoDong Huang 905*e3ec6ff4SXiaoDong Huang if (pmu_power_domain_st(PD_DDR23) == 0) { 906*e3ec6ff4SXiaoDong Huang ddr_data.ddrgrf_chn_con0[2] = 907*e3ec6ff4SXiaoDong Huang mmio_read_32(DDR23GRF_BASE + DDRGRF_CHA_CON(0)); 908*e3ec6ff4SXiaoDong Huang ddr_data.ddrgrf_chn_con0[3] = 909*e3ec6ff4SXiaoDong Huang mmio_read_32(DDR23GRF_BASE + DDRGRF_CHB_CON(0)); 910*e3ec6ff4SXiaoDong Huang ddr_data.ddrgrf_chn_con1[2] = 911*e3ec6ff4SXiaoDong Huang mmio_read_32(DDR23GRF_BASE + DDRGRF_CHA_CON(1)); 912*e3ec6ff4SXiaoDong Huang ddr_data.ddrgrf_chn_con1[3] = 913*e3ec6ff4SXiaoDong Huang mmio_read_32(DDR23GRF_BASE + DDRGRF_CHB_CON(1)); 914*e3ec6ff4SXiaoDong Huang ddr_data.ddrgrf_chn_con2[2] = 915*e3ec6ff4SXiaoDong Huang mmio_read_32(DDR23GRF_BASE + DDRGRF_CHA_CON(2)); 916*e3ec6ff4SXiaoDong Huang ddr_data.ddrgrf_chn_con2[3] = 917*e3ec6ff4SXiaoDong Huang mmio_read_32(DDR23GRF_BASE + DDRGRF_CHB_CON(2)); 918*e3ec6ff4SXiaoDong Huang 919*e3ec6ff4SXiaoDong Huang mmio_write_32(DDR23GRF_BASE + DDRGRF_CHA_CON(2), 0x20002000); 920*e3ec6ff4SXiaoDong Huang mmio_write_32(DDR23GRF_BASE + DDRGRF_CHB_CON(2), 0x20002000); 921*e3ec6ff4SXiaoDong Huang mmio_write_32(DDR23GRF_BASE + DDRGRF_CHA_CON(2), 0x08000000); 922*e3ec6ff4SXiaoDong Huang mmio_write_32(DDR23GRF_BASE + DDRGRF_CHB_CON(2), 0x08000000); 923*e3ec6ff4SXiaoDong Huang mmio_write_32(DDR23GRF_BASE + DDRGRF_CHA_CON(0), 0x00200020); 924*e3ec6ff4SXiaoDong Huang mmio_write_32(DDR23GRF_BASE + DDRGRF_CHB_CON(0), 0x00200020); 925*e3ec6ff4SXiaoDong Huang mmio_write_32(DDR23GRF_BASE + DDRGRF_CHA_CON(1), 0x00400040); 926*e3ec6ff4SXiaoDong Huang mmio_write_32(DDR23GRF_BASE + DDRGRF_CHB_CON(1), 0x00400040); 927*e3ec6ff4SXiaoDong Huang } 928*e3ec6ff4SXiaoDong Huang 929*e3ec6ff4SXiaoDong Huang for (i = 0; i < DDR_CHN_CNT; i++) { 930*e3ec6ff4SXiaoDong Huang ddr_data.pmu1_ddr_pwr_sft_con[i] = 931*e3ec6ff4SXiaoDong Huang mmio_read_32(PMU_BASE + PMU1_DDR_PWR_SFTCON(i)); 932*e3ec6ff4SXiaoDong Huang mmio_write_32(PMU_BASE + PMU1_DDR_PWR_SFTCON(i), 0x0fff0900); 933*e3ec6ff4SXiaoDong Huang } 934*e3ec6ff4SXiaoDong Huang } 935*e3ec6ff4SXiaoDong Huang 936*e3ec6ff4SXiaoDong Huang static void ddr_sleep_config_restore(void) 937*e3ec6ff4SXiaoDong Huang { 938*e3ec6ff4SXiaoDong Huang int i; 939*e3ec6ff4SXiaoDong Huang 940*e3ec6ff4SXiaoDong Huang for (i = 0; i < DDR_CHN_CNT; i++) { 941*e3ec6ff4SXiaoDong Huang mmio_write_32(PMU_BASE + PMU1_DDR_PWR_SFTCON(i), 942*e3ec6ff4SXiaoDong Huang 0x0fff0000 | ddr_data.pmu1_ddr_pwr_sft_con[i]); 943*e3ec6ff4SXiaoDong Huang } 944*e3ec6ff4SXiaoDong Huang 945*e3ec6ff4SXiaoDong Huang if (pmu_power_domain_st(PD_DDR01) == 0) { 946*e3ec6ff4SXiaoDong Huang mmio_write_32(DDR01GRF_BASE + DDRGRF_CHA_CON(1), 947*e3ec6ff4SXiaoDong Huang 0x00400000 | ddr_data.ddrgrf_chn_con1[0]); 948*e3ec6ff4SXiaoDong Huang mmio_write_32(DDR01GRF_BASE + DDRGRF_CHB_CON(1), 949*e3ec6ff4SXiaoDong Huang 0x00400000 | ddr_data.ddrgrf_chn_con1[1]); 950*e3ec6ff4SXiaoDong Huang mmio_write_32(DDR01GRF_BASE + DDRGRF_CHA_CON(0), 951*e3ec6ff4SXiaoDong Huang 0x00200000 | ddr_data.ddrgrf_chn_con0[0]); 952*e3ec6ff4SXiaoDong Huang mmio_write_32(DDR01GRF_BASE + DDRGRF_CHB_CON(0), 953*e3ec6ff4SXiaoDong Huang 0x00200000 | ddr_data.ddrgrf_chn_con0[1]); 954*e3ec6ff4SXiaoDong Huang mmio_write_32(DDR01GRF_BASE + DDRGRF_CHA_CON(2), 955*e3ec6ff4SXiaoDong Huang 0x28000000 | ddr_data.ddrgrf_chn_con2[0]); 956*e3ec6ff4SXiaoDong Huang mmio_write_32(DDR01GRF_BASE + DDRGRF_CHB_CON(2), 957*e3ec6ff4SXiaoDong Huang 0x28000000 | ddr_data.ddrgrf_chn_con2[1]); 958*e3ec6ff4SXiaoDong Huang } 959*e3ec6ff4SXiaoDong Huang 960*e3ec6ff4SXiaoDong Huang if (pmu_power_domain_st(PD_DDR23) == 0) { 961*e3ec6ff4SXiaoDong Huang mmio_write_32(DDR23GRF_BASE + DDRGRF_CHA_CON(1), 962*e3ec6ff4SXiaoDong Huang 0x00400000 | ddr_data.ddrgrf_chn_con1[2]); 963*e3ec6ff4SXiaoDong Huang mmio_write_32(DDR23GRF_BASE + DDRGRF_CHB_CON(1), 964*e3ec6ff4SXiaoDong Huang 0x00400000 | ddr_data.ddrgrf_chn_con1[3]); 965*e3ec6ff4SXiaoDong Huang mmio_write_32(DDR23GRF_BASE + DDRGRF_CHA_CON(0), 966*e3ec6ff4SXiaoDong Huang 0x00200000 | ddr_data.ddrgrf_chn_con0[2]); 967*e3ec6ff4SXiaoDong Huang mmio_write_32(DDR23GRF_BASE + DDRGRF_CHB_CON(0), 968*e3ec6ff4SXiaoDong Huang 0x00200000 | ddr_data.ddrgrf_chn_con0[3]); 969*e3ec6ff4SXiaoDong Huang mmio_write_32(DDR23GRF_BASE + DDRGRF_CHA_CON(2), 970*e3ec6ff4SXiaoDong Huang 0x28000000 | ddr_data.ddrgrf_chn_con2[2]); 971*e3ec6ff4SXiaoDong Huang mmio_write_32(DDR23GRF_BASE + DDRGRF_CHB_CON(2), 972*e3ec6ff4SXiaoDong Huang 0x28000000 | ddr_data.ddrgrf_chn_con2[3]); 973*e3ec6ff4SXiaoDong Huang } 974*e3ec6ff4SXiaoDong Huang } 975*e3ec6ff4SXiaoDong Huang 976*e3ec6ff4SXiaoDong Huang static void pmu_sleep_config(void) 977*e3ec6ff4SXiaoDong Huang { 978*e3ec6ff4SXiaoDong Huang uint32_t pmu1_pwr_con, pmu1_wkup_int_con, pmu1_cru_pwr_con; 979*e3ec6ff4SXiaoDong Huang uint32_t pmu1_ddr_pwr_con, pmu1_pll_pd_con[2] = {0}; 980*e3ec6ff4SXiaoDong Huang uint32_t pmu2_dsu_pwr_con, pmu2_core_pwr_con, pmu2_clst_idle_con; 981*e3ec6ff4SXiaoDong Huang uint32_t pmu2_bus_idle_con[3] = {0}, pmu2_pwr_gate_con[3] = {0}; 982*e3ec6ff4SXiaoDong Huang uint32_t pmu2_vol_gate_con[3] = {0}, pmu2_qch_pwr_con = 0; 983*e3ec6ff4SXiaoDong Huang int i; 984*e3ec6ff4SXiaoDong Huang 985*e3ec6ff4SXiaoDong Huang ddr_data.pmu1grf_soc_con7 = mmio_read_32(PMU1GRF_BASE + PMU1_GRF_SOC_CON(7)); 986*e3ec6ff4SXiaoDong Huang ddr_data.pmu1grf_soc_con8 = mmio_read_32(PMU1GRF_BASE + PMU1_GRF_SOC_CON(8)); 987*e3ec6ff4SXiaoDong Huang ddr_data.pmu1grf_soc_con9 = mmio_read_32(PMU1GRF_BASE + PMU1_GRF_SOC_CON(9)); 988*e3ec6ff4SXiaoDong Huang ddr_data.pmu1sgrf_soc_con14 = mmio_read_32(PMU1SGRF_BASE + PMU1_SGRF_SOC_CON(14)); 989*e3ec6ff4SXiaoDong Huang ddr_data.pmu0sgrf_soc_con1 = mmio_read_32(PMU0SGRF_BASE + PMU0_SGRF_SOC_CON(1)); 990*e3ec6ff4SXiaoDong Huang ddr_data.pmu0grf_soc_con1 = mmio_read_32(PMU0GRF_BASE + PMU0_GRF_SOC_CON(1)); 991*e3ec6ff4SXiaoDong Huang 992*e3ec6ff4SXiaoDong Huang ddr_data.pmu2_vol_gate_con[0] = mmio_read_32(PMU_BASE + PMU2_VOL_GATE_CON(0)); 993*e3ec6ff4SXiaoDong Huang ddr_data.pmu2_vol_gate_con[1] = mmio_read_32(PMU_BASE + PMU2_VOL_GATE_CON(1)); 994*e3ec6ff4SXiaoDong Huang ddr_data.pmu2_vol_gate_con[2] = mmio_read_32(PMU_BASE + PMU2_VOL_GATE_CON(2)); 995*e3ec6ff4SXiaoDong Huang 996*e3ec6ff4SXiaoDong Huang ddr_data.pmu2_submem_gate_sft_con0 = 997*e3ec6ff4SXiaoDong Huang mmio_read_32(PMU_BASE + PMU2_MEMPWR_MD_GATE_SFTCON(0)); 998*e3ec6ff4SXiaoDong Huang 999*e3ec6ff4SXiaoDong Huang /* save pmic_sleep iomux gpio0_a4 */ 1000*e3ec6ff4SXiaoDong Huang ddr_data.gpio0a_iomux_l = mmio_read_32(PMU0IOC_BASE + 0); 1001*e3ec6ff4SXiaoDong Huang ddr_data.gpio0a_iomux_h = mmio_read_32(PMU0IOC_BASE + 4); 1002*e3ec6ff4SXiaoDong Huang ddr_data.pmu0grf_soc_con3 = mmio_read_32(PMU0GRF_BASE + PMU0_GRF_SOC_CON(3)); 1003*e3ec6ff4SXiaoDong Huang 1004*e3ec6ff4SXiaoDong Huang /* PMU1 repair disable */ 1005*e3ec6ff4SXiaoDong Huang mmio_write_32(PMU0GRF_BASE + PMU0_GRF_SOC_CON(0), 0x00010000); 1006*e3ec6ff4SXiaoDong Huang 1007*e3ec6ff4SXiaoDong Huang /* set pmic_sleep iomux */ 1008*e3ec6ff4SXiaoDong Huang mmio_write_32(PMU0IOC_BASE + 0, 1009*e3ec6ff4SXiaoDong Huang BITS_WITH_WMASK(1, 0xf, 8) | 1010*e3ec6ff4SXiaoDong Huang BITS_WITH_WMASK(1, 0xfu, 12)); 1011*e3ec6ff4SXiaoDong Huang 1012*e3ec6ff4SXiaoDong Huang /* set tsadc_shut_m0 pin iomux to gpio */ 1013*e3ec6ff4SXiaoDong Huang mmio_write_32(PMU0IOC_BASE + 0, 1014*e3ec6ff4SXiaoDong Huang BITS_WITH_WMASK(0, 0xf, 4)); 1015*e3ec6ff4SXiaoDong Huang 1016*e3ec6ff4SXiaoDong Huang /* set spi2_cs0/1 pin iomux to gpio */ 1017*e3ec6ff4SXiaoDong Huang mmio_write_32(PMU0IOC_BASE + 8, 1018*e3ec6ff4SXiaoDong Huang BITS_WITH_WMASK(0, 0xff, 0)); 1019*e3ec6ff4SXiaoDong Huang 1020*e3ec6ff4SXiaoDong Huang /* sleep 1~2 src select */ 1021*e3ec6ff4SXiaoDong Huang mmio_write_32(PMU0GRF_BASE + PMU0_GRF_SOC_CON(3), 1022*e3ec6ff4SXiaoDong Huang BITS_WITH_WMASK(0x8, 0xf, 0) | 1023*e3ec6ff4SXiaoDong Huang BITS_WITH_WMASK(0x8, 0xf, 4) | 1024*e3ec6ff4SXiaoDong Huang BITS_WITH_WMASK(0x0, 0x3, 8)); 1025*e3ec6ff4SXiaoDong Huang 1026*e3ec6ff4SXiaoDong Huang pmu1_wkup_int_con = BIT(WAKEUP_GPIO0_INT_EN) | 1027*e3ec6ff4SXiaoDong Huang BIT(WAKEUP_CPU0_INT_EN); 1028*e3ec6ff4SXiaoDong Huang 1029*e3ec6ff4SXiaoDong Huang pmu1_pwr_con = BIT(powermode_en); 1030*e3ec6ff4SXiaoDong Huang 1031*e3ec6ff4SXiaoDong Huang pmu1_cru_pwr_con = 1032*e3ec6ff4SXiaoDong Huang BIT(alive_osc_mode_en) | 1033*e3ec6ff4SXiaoDong Huang BIT(power_off_en) | 1034*e3ec6ff4SXiaoDong Huang BIT(pd_clk_src_gate_en); 1035*e3ec6ff4SXiaoDong Huang 1036*e3ec6ff4SXiaoDong Huang pmu1_ddr_pwr_con = 0; 1037*e3ec6ff4SXiaoDong Huang 1038*e3ec6ff4SXiaoDong Huang pmu2_dsu_pwr_con = 1039*e3ec6ff4SXiaoDong Huang BIT(DSU_PWRDN_EN) | 1040*e3ec6ff4SXiaoDong Huang BIT(DSU_PWROFF_EN); 1041*e3ec6ff4SXiaoDong Huang 1042*e3ec6ff4SXiaoDong Huang pmu2_core_pwr_con = BIT(CORE_PWRDN_EN); 1043*e3ec6ff4SXiaoDong Huang 1044*e3ec6ff4SXiaoDong Huang pmu2_clst_idle_con = 1045*e3ec6ff4SXiaoDong Huang BIT(IDLE_REQ_BIGCORE0_EN) | 1046*e3ec6ff4SXiaoDong Huang BIT(IDLE_REQ_BIGCORE1_EN) | 1047*e3ec6ff4SXiaoDong Huang BIT(IDLE_REQ_DSU_EN) | 1048*e3ec6ff4SXiaoDong Huang BIT(IDLE_REQ_LITDSU_EN) | 1049*e3ec6ff4SXiaoDong Huang BIT(IDLE_REQ_ADB400_CORE_QCH_EN); 1050*e3ec6ff4SXiaoDong Huang 1051*e3ec6ff4SXiaoDong Huang pmu1_pll_pd_con[0] = 1052*e3ec6ff4SXiaoDong Huang BIT(B0PLL_PD_EN) | 1053*e3ec6ff4SXiaoDong Huang BIT(B1PLL_PD_EN) | 1054*e3ec6ff4SXiaoDong Huang BIT(LPLL_PD_EN) | 1055*e3ec6ff4SXiaoDong Huang BIT(V0PLL_PD_EN) | 1056*e3ec6ff4SXiaoDong Huang BIT(AUPLL_PD_EN) | 1057*e3ec6ff4SXiaoDong Huang BIT(GPLL_PD_EN) | 1058*e3ec6ff4SXiaoDong Huang BIT(CPLL_PD_EN) | 1059*e3ec6ff4SXiaoDong Huang BIT(NPLL_PD_EN); 1060*e3ec6ff4SXiaoDong Huang 1061*e3ec6ff4SXiaoDong Huang pmu1_pll_pd_con[1] = 1062*e3ec6ff4SXiaoDong Huang BIT(PPLL_PD_EN) | 1063*e3ec6ff4SXiaoDong Huang BIT(SPLL_PD_EN); 1064*e3ec6ff4SXiaoDong Huang 1065*e3ec6ff4SXiaoDong Huang pmu2_bus_idle_con[0] = 0; 1066*e3ec6ff4SXiaoDong Huang 1067*e3ec6ff4SXiaoDong Huang pmu2_bus_idle_con[1] = 1068*e3ec6ff4SXiaoDong Huang BIT(BUS_ID_SECURE - 16) | 1069*e3ec6ff4SXiaoDong Huang BIT(BUS_ID_SECURE_CENTER_CHANNEL - 16) | 1070*e3ec6ff4SXiaoDong Huang BIT(BUS_ID_CENTER_CHANNEL - 16); 1071*e3ec6ff4SXiaoDong Huang 1072*e3ec6ff4SXiaoDong Huang pmu2_bus_idle_con[2] = 1073*e3ec6ff4SXiaoDong Huang BIT(BUS_ID_MSCH - 32) | 1074*e3ec6ff4SXiaoDong Huang BIT(BUS_ID_BUS - 32) | 1075*e3ec6ff4SXiaoDong Huang BIT(BUS_ID_TOP - 32); 1076*e3ec6ff4SXiaoDong Huang 1077*e3ec6ff4SXiaoDong Huang pmu2_pwr_gate_con[0] = 0; 1078*e3ec6ff4SXiaoDong Huang pmu2_pwr_gate_con[1] = BIT(PD_SECURE - 16); 1079*e3ec6ff4SXiaoDong Huang pmu2_pwr_gate_con[2] = 0; 1080*e3ec6ff4SXiaoDong Huang 1081*e3ec6ff4SXiaoDong Huang pmu2_qch_pwr_con = 0; 1082*e3ec6ff4SXiaoDong Huang 1083*e3ec6ff4SXiaoDong Huang pmu2_vol_gate_con[0] = 0x7; 1084*e3ec6ff4SXiaoDong Huang pmu2_vol_gate_con[2] = 0; 1085*e3ec6ff4SXiaoDong Huang 1086*e3ec6ff4SXiaoDong Huang mmio_write_32(PMU_BASE + PMU2_CORE_AUTO_PWR_CON(0), 0x00030000); 1087*e3ec6ff4SXiaoDong Huang mmio_write_32(PMU_BASE + PMU2_CORE_AUTO_PWR_CON(1), 0x00030000); 1088*e3ec6ff4SXiaoDong Huang mmio_write_32(PMU_BASE + PMU2_CORE_PWR_CON(0), 1089*e3ec6ff4SXiaoDong Huang WITH_16BITS_WMSK(pmu2_core_pwr_con)); 1090*e3ec6ff4SXiaoDong Huang mmio_write_32(PMU_BASE + PMU2_CORE_PWR_CON(1), 1091*e3ec6ff4SXiaoDong Huang WITH_16BITS_WMSK(pmu2_core_pwr_con)); 1092*e3ec6ff4SXiaoDong Huang mmio_write_32(PMU_BASE + PMU2_CLUSTER_IDLE_CON, 1093*e3ec6ff4SXiaoDong Huang WITH_16BITS_WMSK(pmu2_clst_idle_con)); 1094*e3ec6ff4SXiaoDong Huang mmio_write_32(PMU_BASE + PMU2_DSU_AUTO_PWR_CON, 0x00030000); 1095*e3ec6ff4SXiaoDong Huang mmio_write_32(PMU_BASE + PMU2_DSU_PWR_CON, 1096*e3ec6ff4SXiaoDong Huang WITH_16BITS_WMSK(pmu2_dsu_pwr_con)); 1097*e3ec6ff4SXiaoDong Huang 1098*e3ec6ff4SXiaoDong Huang mmio_write_32(PMU_BASE + PMU1_OSC_STABLE_CNT_THRESH, 24000); 1099*e3ec6ff4SXiaoDong Huang mmio_write_32(PMU_BASE + PMU1_STABLE_CNT_THRESH, 24000); 1100*e3ec6ff4SXiaoDong Huang mmio_write_32(PMU_BASE + PMU1_WAKEUP_RST_CLR_CNT_THRESH, 24000); 1101*e3ec6ff4SXiaoDong Huang mmio_write_32(PMU_BASE + PMU1_PLL_LOCK_CNT_THRESH, 24000); 1102*e3ec6ff4SXiaoDong Huang mmio_write_32(PMU_BASE + PMU1_PWM_SWITCH_CNT_THRESH, 24000); 1103*e3ec6ff4SXiaoDong Huang mmio_write_32(PMU_BASE + PMU2_CORE0_STABLE_CNT_THRESH, 24000); 1104*e3ec6ff4SXiaoDong Huang mmio_write_32(PMU_BASE + PMU2_CORE0_PWRUP_CNT_THRESH, 24000); 1105*e3ec6ff4SXiaoDong Huang mmio_write_32(PMU_BASE + PMU2_CORE0_PWRDN_CNT_THRESH, 24000); 1106*e3ec6ff4SXiaoDong Huang mmio_write_32(PMU_BASE + PMU2_CORE1_STABLE_CNT_THRESH, 24000); 1107*e3ec6ff4SXiaoDong Huang mmio_write_32(PMU_BASE + PMU2_CORE1_PWRUP_CNT_THRESH, 24000); 1108*e3ec6ff4SXiaoDong Huang mmio_write_32(PMU_BASE + PMU2_CORE1_PWRDN_CNT_THRESH, 24000); 1109*e3ec6ff4SXiaoDong Huang mmio_write_32(PMU_BASE + PMU2_DSU_STABLE_CNT_THRESH, 24000); 1110*e3ec6ff4SXiaoDong Huang mmio_write_32(PMU_BASE + PMU2_DSU_PWRUP_CNT_THRESH, 24000); 1111*e3ec6ff4SXiaoDong Huang mmio_write_32(PMU_BASE + PMU2_DSU_PWRDN_CNT_THRESH, 24000); 1112*e3ec6ff4SXiaoDong Huang 1113*e3ec6ff4SXiaoDong Huang /* Config pmu power mode and pmu wakeup source */ 1114*e3ec6ff4SXiaoDong Huang mmio_write_32(PMU_BASE + PMU1_INT_MASK_CON, 1115*e3ec6ff4SXiaoDong Huang BITS_WITH_WMASK(1, 0x1, 0)); 1116*e3ec6ff4SXiaoDong Huang 1117*e3ec6ff4SXiaoDong Huang /* pmu1_pwr_con */ 1118*e3ec6ff4SXiaoDong Huang mmio_write_32(PMU_BASE + PMU1_PWR_CON, 1119*e3ec6ff4SXiaoDong Huang WITH_16BITS_WMSK(pmu1_pwr_con)); 1120*e3ec6ff4SXiaoDong Huang 1121*e3ec6ff4SXiaoDong Huang /* cru_pwr_con */ 1122*e3ec6ff4SXiaoDong Huang mmio_write_32(PMU_BASE + PMU1_CRU_PWR_CON, 1123*e3ec6ff4SXiaoDong Huang WITH_16BITS_WMSK(pmu1_cru_pwr_con)); 1124*e3ec6ff4SXiaoDong Huang 1125*e3ec6ff4SXiaoDong Huang /* wakeup source */ 1126*e3ec6ff4SXiaoDong Huang mmio_write_32(PMU_BASE + PMU1_WAKEUP_INT_CON, pmu1_wkup_int_con); 1127*e3ec6ff4SXiaoDong Huang 1128*e3ec6ff4SXiaoDong Huang /* ddr pwr con */ 1129*e3ec6ff4SXiaoDong Huang for (i = 0; i < DDR_CHN_CNT; i++) { 1130*e3ec6ff4SXiaoDong Huang mmio_write_32(PMU_BASE + PMU1_DDR_PWR_CON(i), 1131*e3ec6ff4SXiaoDong Huang WITH_16BITS_WMSK(pmu1_ddr_pwr_con)); 1132*e3ec6ff4SXiaoDong Huang pmu2_bus_idle_con[1] |= 1133*e3ec6ff4SXiaoDong Huang BIT(BUS_ID_MSCH0 - 16 + i); 1134*e3ec6ff4SXiaoDong Huang } 1135*e3ec6ff4SXiaoDong Huang 1136*e3ec6ff4SXiaoDong Huang /* pll_pd */ 1137*e3ec6ff4SXiaoDong Huang mmio_write_32(PMU_BASE + PMU1_PLLPD_CON(0), 1138*e3ec6ff4SXiaoDong Huang WITH_16BITS_WMSK(pmu1_pll_pd_con[0])); 1139*e3ec6ff4SXiaoDong Huang mmio_write_32(PMU_BASE + PMU1_PLLPD_CON(1), 1140*e3ec6ff4SXiaoDong Huang WITH_16BITS_WMSK(pmu1_pll_pd_con[1])); 1141*e3ec6ff4SXiaoDong Huang 1142*e3ec6ff4SXiaoDong Huang /* bypass cpu1~7*/ 1143*e3ec6ff4SXiaoDong Huang mmio_write_32(PMU_BASE + PMU2_PWR_CON1, 0x00ff00fe); 1144*e3ec6ff4SXiaoDong Huang 1145*e3ec6ff4SXiaoDong Huang /* bus idle */ 1146*e3ec6ff4SXiaoDong Huang mmio_write_32(PMU_BASE + PMU2_BUS_IDLE_CON(0), 1147*e3ec6ff4SXiaoDong Huang WITH_16BITS_WMSK(pmu2_bus_idle_con[0])); 1148*e3ec6ff4SXiaoDong Huang mmio_write_32(PMU_BASE + PMU2_BUS_IDLE_CON(1), 1149*e3ec6ff4SXiaoDong Huang WITH_16BITS_WMSK(pmu2_bus_idle_con[1])); 1150*e3ec6ff4SXiaoDong Huang mmio_write_32(PMU_BASE + PMU2_BUS_IDLE_CON(2), 1151*e3ec6ff4SXiaoDong Huang WITH_16BITS_WMSK(pmu2_bus_idle_con[2])); 1152*e3ec6ff4SXiaoDong Huang mmio_write_32(PMU_BASE + PMU2_BUS_IDLE_CON(2), 1153*e3ec6ff4SXiaoDong Huang 0xf000f000); 1154*e3ec6ff4SXiaoDong Huang /* power gate */ 1155*e3ec6ff4SXiaoDong Huang mmio_write_32(PMU_BASE + PMU2_PWR_GATE_CON(0), 1156*e3ec6ff4SXiaoDong Huang WITH_16BITS_WMSK(pmu2_pwr_gate_con[0])); 1157*e3ec6ff4SXiaoDong Huang mmio_write_32(PMU_BASE + PMU2_PWR_GATE_CON(1), 1158*e3ec6ff4SXiaoDong Huang WITH_16BITS_WMSK(pmu2_pwr_gate_con[1])); 1159*e3ec6ff4SXiaoDong Huang mmio_write_32(PMU_BASE + PMU2_PWR_GATE_CON(2), 1160*e3ec6ff4SXiaoDong Huang WITH_16BITS_WMSK(pmu2_pwr_gate_con[2])); 1161*e3ec6ff4SXiaoDong Huang /* vol gate */ 1162*e3ec6ff4SXiaoDong Huang mmio_write_32(PMU_BASE + PMU2_VOL_GATE_CON(0), 1163*e3ec6ff4SXiaoDong Huang BITS_WITH_WMASK(pmu2_vol_gate_con[0], 0x7, 0)); 1164*e3ec6ff4SXiaoDong Huang mmio_write_32(PMU_BASE + PMU2_VOL_GATE_CON(1), 0); 1165*e3ec6ff4SXiaoDong Huang mmio_write_32(PMU_BASE + PMU2_VOL_GATE_CON(2), 1166*e3ec6ff4SXiaoDong Huang BITS_WITH_WMASK(pmu2_vol_gate_con[2], 0x3, 0)); 1167*e3ec6ff4SXiaoDong Huang /* qch */ 1168*e3ec6ff4SXiaoDong Huang mmio_write_32(PMU_BASE + PMU2_QCHANNEL_PWR_CON, 1169*e3ec6ff4SXiaoDong Huang BITS_WITH_WMASK(pmu2_qch_pwr_con, 0x7f, 0)); 1170*e3ec6ff4SXiaoDong Huang 1171*e3ec6ff4SXiaoDong Huang mmio_write_32(PMU_BASE + PMU2_MEMPWR_MD_GATE_SFTCON(0), 1172*e3ec6ff4SXiaoDong Huang 0x000f000f); 1173*e3ec6ff4SXiaoDong Huang } 1174*e3ec6ff4SXiaoDong Huang 1175*e3ec6ff4SXiaoDong Huang static void pmu_sleep_restore(void) 1176*e3ec6ff4SXiaoDong Huang { 1177*e3ec6ff4SXiaoDong Huang mmio_write_32(PMU1GRF_BASE + PMU1_GRF_SOC_CON(7), 1178*e3ec6ff4SXiaoDong Huang WITH_16BITS_WMSK(ddr_data.pmu1grf_soc_con7)); 1179*e3ec6ff4SXiaoDong Huang mmio_write_32(PMU1GRF_BASE + PMU1_GRF_SOC_CON(8), 1180*e3ec6ff4SXiaoDong Huang WITH_16BITS_WMSK(ddr_data.pmu1grf_soc_con8)); 1181*e3ec6ff4SXiaoDong Huang mmio_write_32(PMU1GRF_BASE + PMU1_GRF_SOC_CON(9), 1182*e3ec6ff4SXiaoDong Huang WITH_16BITS_WMSK(ddr_data.pmu1grf_soc_con9)); 1183*e3ec6ff4SXiaoDong Huang mmio_write_32(PMU1SGRF_BASE + PMU1_SGRF_SOC_CON(14), 1184*e3ec6ff4SXiaoDong Huang WITH_16BITS_WMSK(ddr_data.pmu1sgrf_soc_con14)); 1185*e3ec6ff4SXiaoDong Huang 1186*e3ec6ff4SXiaoDong Huang mmio_write_32(PMU0SGRF_BASE + PMU0_SGRF_SOC_CON(1), 1187*e3ec6ff4SXiaoDong Huang WITH_16BITS_WMSK(ddr_data.pmu0sgrf_soc_con1)); 1188*e3ec6ff4SXiaoDong Huang mmio_write_32(PMU0GRF_BASE + PMU0_GRF_SOC_CON(1), 1189*e3ec6ff4SXiaoDong Huang WITH_16BITS_WMSK(ddr_data.pmu0grf_soc_con1)); 1190*e3ec6ff4SXiaoDong Huang 1191*e3ec6ff4SXiaoDong Huang mmio_write_32(PMU_BASE + PMU2_CORE_PWR_CON(0), 0xffff0000); 1192*e3ec6ff4SXiaoDong Huang mmio_write_32(PMU_BASE + PMU2_CORE_PWR_CON(1), 0xffff0000); 1193*e3ec6ff4SXiaoDong Huang mmio_write_32(PMU_BASE + PMU2_CLUSTER_IDLE_CON, 0xffff0000); 1194*e3ec6ff4SXiaoDong Huang mmio_write_32(PMU_BASE + PMU2_DSU_PWR_CON, 0xffff0000); 1195*e3ec6ff4SXiaoDong Huang mmio_write_32(PMU_BASE + PMU2_PWR_CON1, 0xffff0000); 1196*e3ec6ff4SXiaoDong Huang 1197*e3ec6ff4SXiaoDong Huang /* Must clear PMU1_WAKEUP_INT_CON because the wakeup source 1198*e3ec6ff4SXiaoDong Huang * in PMU1_WAKEUP_INT_CON will wakeup cpus in cpu_auto_pd state. 1199*e3ec6ff4SXiaoDong Huang */ 1200*e3ec6ff4SXiaoDong Huang mmio_write_32(PMU_BASE + PMU1_WAKEUP_INT_CON, 0); 1201*e3ec6ff4SXiaoDong Huang mmio_write_32(PMU_BASE + PMU1_PWR_CON, 0xffff0000); 1202*e3ec6ff4SXiaoDong Huang mmio_write_32(PMU_BASE + PMU1_INT_MASK_CON, 0x00010000); 1203*e3ec6ff4SXiaoDong Huang mmio_write_32(PMU_BASE + PMU0_WAKEUP_INT_CON, 0x00010000); 1204*e3ec6ff4SXiaoDong Huang mmio_write_32(PMU_BASE + PMU0_PWR_CON, 0xffff0000); 1205*e3ec6ff4SXiaoDong Huang 1206*e3ec6ff4SXiaoDong Huang mmio_write_32(PMU_BASE + PMU2_VOL_GATE_CON(0), 1207*e3ec6ff4SXiaoDong Huang WITH_16BITS_WMSK(ddr_data.pmu2_vol_gate_con[0])); 1208*e3ec6ff4SXiaoDong Huang mmio_write_32(PMU_BASE + PMU2_VOL_GATE_CON(1), 1209*e3ec6ff4SXiaoDong Huang WITH_16BITS_WMSK(ddr_data.pmu2_vol_gate_con[1])); 1210*e3ec6ff4SXiaoDong Huang mmio_write_32(PMU_BASE + PMU2_VOL_GATE_CON(2), 1211*e3ec6ff4SXiaoDong Huang WITH_16BITS_WMSK(ddr_data.pmu2_vol_gate_con[2])); 1212*e3ec6ff4SXiaoDong Huang 1213*e3ec6ff4SXiaoDong Huang mmio_write_32(PMU_BASE + PMU2_MEMPWR_MD_GATE_SFTCON(0), 1214*e3ec6ff4SXiaoDong Huang WITH_16BITS_WMSK(ddr_data.pmu2_submem_gate_sft_con0)); 1215*e3ec6ff4SXiaoDong Huang 1216*e3ec6ff4SXiaoDong Huang mmio_write_32(PMU0GRF_BASE + PMU0_GRF_SOC_CON(3), 1217*e3ec6ff4SXiaoDong Huang WITH_16BITS_WMSK(ddr_data.pmu0grf_soc_con3)); 1218*e3ec6ff4SXiaoDong Huang mmio_write_32(PMU1GRF_BASE + PMU1_GRF_SOC_CON(2), 1219*e3ec6ff4SXiaoDong Huang WITH_16BITS_WMSK(ddr_data.pmu1grf_soc_con2)); 1220*e3ec6ff4SXiaoDong Huang 1221*e3ec6ff4SXiaoDong Huang mmio_write_32(PMU0IOC_BASE + 0x4, 1222*e3ec6ff4SXiaoDong Huang WITH_16BITS_WMSK(ddr_data.gpio0a_iomux_h)); 1223*e3ec6ff4SXiaoDong Huang mmio_write_32(PMU0IOC_BASE + 0, 1224*e3ec6ff4SXiaoDong Huang WITH_16BITS_WMSK(ddr_data.gpio0a_iomux_l)); 1225*e3ec6ff4SXiaoDong Huang } 1226*e3ec6ff4SXiaoDong Huang 1227*e3ec6ff4SXiaoDong Huang static void soc_sleep_config(void) 1228*e3ec6ff4SXiaoDong Huang { 1229*e3ec6ff4SXiaoDong Huang ddr_data.gpio0b_iomux_l = mmio_read_32(PMU0IOC_BASE + 0x8); 1230*e3ec6ff4SXiaoDong Huang 1231*e3ec6ff4SXiaoDong Huang pmu_sleep_config(); 1232*e3ec6ff4SXiaoDong Huang ddr_sleep_config(); 1233*e3ec6ff4SXiaoDong Huang } 1234*e3ec6ff4SXiaoDong Huang 1235*e3ec6ff4SXiaoDong Huang static void soc_sleep_restore(void) 1236*e3ec6ff4SXiaoDong Huang { 1237*e3ec6ff4SXiaoDong Huang ddr_sleep_config_restore(); 1238*e3ec6ff4SXiaoDong Huang pmu_sleep_restore(); 1239*e3ec6ff4SXiaoDong Huang 1240*e3ec6ff4SXiaoDong Huang mmio_write_32(PMU0IOC_BASE + 0x8, WITH_16BITS_WMSK(ddr_data.gpio0b_iomux_l)); 1241*e3ec6ff4SXiaoDong Huang } 1242*e3ec6ff4SXiaoDong Huang 1243*e3ec6ff4SXiaoDong Huang static void pm_pll_suspend(void) 1244*e3ec6ff4SXiaoDong Huang { 1245*e3ec6ff4SXiaoDong Huang ddr_data.cru_mode_con = mmio_read_32(CRU_BASE + 0x280); 1246*e3ec6ff4SXiaoDong Huang ddr_data.busscru_mode_con = mmio_read_32(BUSSCRU_BASE + 0x280); 1247*e3ec6ff4SXiaoDong Huang ddr_data.pmu2_bisr_con0 = mmio_read_32(PMU_BASE + PMU2_BISR_CON(0)); 1248*e3ec6ff4SXiaoDong Huang ddr_data.cpll_con0 = mmio_read_32(CRU_BASE + CRU_PLLS_CON(2, 0)); 1249*e3ec6ff4SXiaoDong Huang ddr_data.pmu1cru_clksel_con1 = mmio_read_32(PMU1CRU_BASE + CRU_CLKSEL_CON(1)); 1250*e3ec6ff4SXiaoDong Huang 1251*e3ec6ff4SXiaoDong Huang /* disable bisr_init */ 1252*e3ec6ff4SXiaoDong Huang mmio_write_32(PMU_BASE + PMU2_BISR_CON(0), BITS_WITH_WMASK(0, 0x1, 0)); 1253*e3ec6ff4SXiaoDong Huang /* cpll bypass */ 1254*e3ec6ff4SXiaoDong Huang mmio_write_32(CRU_BASE + CRU_PLLS_CON(2, 0), BITS_WITH_WMASK(1u, 1u, 15)); 1255*e3ec6ff4SXiaoDong Huang } 1256*e3ec6ff4SXiaoDong Huang 1257*e3ec6ff4SXiaoDong Huang static void pm_pll_restore(void) 1258*e3ec6ff4SXiaoDong Huang { 1259*e3ec6ff4SXiaoDong Huang pm_pll_wait_lock(CRU_BASE + CRU_PLLS_CON(2, 0)); 1260*e3ec6ff4SXiaoDong Huang 1261*e3ec6ff4SXiaoDong Huang mmio_write_32(CRU_BASE + 0x280, WITH_16BITS_WMSK(ddr_data.cru_mode_con)); 1262*e3ec6ff4SXiaoDong Huang mmio_write_32(BUSSCRU_BASE + 0x280, WITH_16BITS_WMSK(ddr_data.busscru_mode_con)); 1263*e3ec6ff4SXiaoDong Huang mmio_write_32(CRU_BASE + CRU_PLLS_CON(2, 0), WITH_16BITS_WMSK(ddr_data.cpll_con0)); 1264*e3ec6ff4SXiaoDong Huang dsb(); 1265*e3ec6ff4SXiaoDong Huang isb(); 1266*e3ec6ff4SXiaoDong Huang mmio_write_32(PMU_BASE + PMU2_BISR_CON(0), WITH_16BITS_WMSK(ddr_data.pmu2_bisr_con0)); 1267*e3ec6ff4SXiaoDong Huang } 1268*e3ec6ff4SXiaoDong Huang 1269*e3ec6ff4SXiaoDong Huang int rockchip_soc_sys_pwr_dm_suspend(void) 1270*e3ec6ff4SXiaoDong Huang { 1271*e3ec6ff4SXiaoDong Huang clk_gate_con_save(); 1272*e3ec6ff4SXiaoDong Huang clk_gate_con_disable(); 1273*e3ec6ff4SXiaoDong Huang 1274*e3ec6ff4SXiaoDong Huang psram_sleep_cfg->pm_flag &= ~PM_WARM_BOOT_BIT; 1275*e3ec6ff4SXiaoDong Huang 1276*e3ec6ff4SXiaoDong Huang pmu_power_domains_suspend(); 1277*e3ec6ff4SXiaoDong Huang soc_sleep_config(); 1278*e3ec6ff4SXiaoDong Huang dsu_core_save(); 1279*e3ec6ff4SXiaoDong Huang pm_pll_suspend(); 1280*e3ec6ff4SXiaoDong Huang 1281*e3ec6ff4SXiaoDong Huang return 0; 1282*e3ec6ff4SXiaoDong Huang } 1283*e3ec6ff4SXiaoDong Huang 1284*e3ec6ff4SXiaoDong Huang int rockchip_soc_sys_pwr_dm_resume(void) 1285*e3ec6ff4SXiaoDong Huang { 1286*e3ec6ff4SXiaoDong Huang pm_pll_restore(); 1287*e3ec6ff4SXiaoDong Huang dsu_core_restore(); 1288*e3ec6ff4SXiaoDong Huang soc_sleep_restore(); 1289*e3ec6ff4SXiaoDong Huang pmu_power_domains_resume(); 1290*e3ec6ff4SXiaoDong Huang plat_rockchip_gic_cpuif_enable(); 1291*e3ec6ff4SXiaoDong Huang 1292*e3ec6ff4SXiaoDong Huang psram_sleep_cfg->pm_flag |= PM_WARM_BOOT_BIT; 1293*e3ec6ff4SXiaoDong Huang 1294*e3ec6ff4SXiaoDong Huang clk_gate_con_restore(); 1295*e3ec6ff4SXiaoDong Huang 1296*e3ec6ff4SXiaoDong Huang return 0; 1297*e3ec6ff4SXiaoDong Huang } 1298*e3ec6ff4SXiaoDong Huang 1299*e3ec6ff4SXiaoDong Huang void __dead2 rockchip_soc_cores_pd_pwr_dn_wfi(const 1300*e3ec6ff4SXiaoDong Huang psci_power_state_t *target_state) 1301*e3ec6ff4SXiaoDong Huang { 1302*e3ec6ff4SXiaoDong Huang psci_power_down_wfi(); 1303*e3ec6ff4SXiaoDong Huang } 1304*e3ec6ff4SXiaoDong Huang 1305*e3ec6ff4SXiaoDong Huang void __dead2 rockchip_soc_sys_pd_pwr_dn_wfi(void) 1306*e3ec6ff4SXiaoDong Huang { 1307*e3ec6ff4SXiaoDong Huang cpus_pd_req_enter_wfi(); 1308*e3ec6ff4SXiaoDong Huang psci_power_down_wfi(); 1309*e3ec6ff4SXiaoDong Huang } 1310*e3ec6ff4SXiaoDong Huang 1311*e3ec6ff4SXiaoDong Huang void __dead2 rockchip_soc_soft_reset(void) 1312*e3ec6ff4SXiaoDong Huang { 1313*e3ec6ff4SXiaoDong Huang /* pll slow mode */ 1314*e3ec6ff4SXiaoDong Huang mmio_write_32(CRU_BASE + 0x280, 0x03ff0000); 1315*e3ec6ff4SXiaoDong Huang mmio_write_32(BIGCORE0CRU_BASE + 0x280, 0x00030000); 1316*e3ec6ff4SXiaoDong Huang mmio_write_32(BIGCORE0CRU_BASE + 0x300, 0x60000000); 1317*e3ec6ff4SXiaoDong Huang mmio_write_32(BIGCORE0CRU_BASE + 0x304, 0x00600000); 1318*e3ec6ff4SXiaoDong Huang mmio_write_32(BIGCORE1CRU_BASE + 0x280, 0x00030000); 1319*e3ec6ff4SXiaoDong Huang mmio_write_32(BIGCORE1CRU_BASE + 0x300, 0x60000000); 1320*e3ec6ff4SXiaoDong Huang mmio_write_32(BIGCORE1CRU_BASE + 0x304, 0x00600000); 1321*e3ec6ff4SXiaoDong Huang mmio_write_32(DSUCRU_BASE + 0x280, 0x00030000); 1322*e3ec6ff4SXiaoDong Huang mmio_write_32(DSUCRU_BASE + 0x318, 0x30600000); 1323*e3ec6ff4SXiaoDong Huang mmio_write_32(DSUCRU_BASE + 0x31c, 0x30600000); 1324*e3ec6ff4SXiaoDong Huang mmio_write_32(DSUCRU_BASE + 0x304, 0x00010000); 1325*e3ec6ff4SXiaoDong Huang mmio_write_32(BUSSCRU_BASE + 0x280, 0x0003000); 1326*e3ec6ff4SXiaoDong Huang dsb(); 1327*e3ec6ff4SXiaoDong Huang isb(); 1328*e3ec6ff4SXiaoDong Huang 1329*e3ec6ff4SXiaoDong Huang mmio_write_32(CRU_BASE + CRU_GLB_SRST_FST, GLB_SRST_FST_CFG_VAL); 1330*e3ec6ff4SXiaoDong Huang 1331*e3ec6ff4SXiaoDong Huang /* 1332*e3ec6ff4SXiaoDong Huang * Maybe the HW needs some times to reset the system, 1333*e3ec6ff4SXiaoDong Huang * so we do not hope the core to execute valid codes. 1334*e3ec6ff4SXiaoDong Huang */ 1335*e3ec6ff4SXiaoDong Huang psci_power_down_wfi(); 1336*e3ec6ff4SXiaoDong Huang } 1337*e3ec6ff4SXiaoDong Huang 1338*e3ec6ff4SXiaoDong Huang void __dead2 rockchip_soc_system_off(void) 1339*e3ec6ff4SXiaoDong Huang { 1340*e3ec6ff4SXiaoDong Huang /* set pmic_sleep pin(gpio0_a2) to gpio mode */ 1341*e3ec6ff4SXiaoDong Huang mmio_write_32(PMU0IOC_BASE + 0, BITS_WITH_WMASK(0, 0xf, 8)); 1342*e3ec6ff4SXiaoDong Huang 1343*e3ec6ff4SXiaoDong Huang /* config output */ 1344*e3ec6ff4SXiaoDong Huang mmio_write_32(GPIO0_BASE + GPIO_SWPORT_DDR_L, 1345*e3ec6ff4SXiaoDong Huang BITS_WITH_WMASK(1, 0x1, 2)); 1346*e3ec6ff4SXiaoDong Huang 1347*e3ec6ff4SXiaoDong Huang /* config output high level */ 1348*e3ec6ff4SXiaoDong Huang mmio_write_32(GPIO0_BASE + GPIO_SWPORT_DR_L, 1349*e3ec6ff4SXiaoDong Huang BITS_WITH_WMASK(1, 0x1, 2)); 1350*e3ec6ff4SXiaoDong Huang dsb(); 1351*e3ec6ff4SXiaoDong Huang 1352*e3ec6ff4SXiaoDong Huang /* 1353*e3ec6ff4SXiaoDong Huang * Maybe the HW needs some times to reset the system, 1354*e3ec6ff4SXiaoDong Huang * so we do not hope the core to execute valid codes. 1355*e3ec6ff4SXiaoDong Huang */ 1356*e3ec6ff4SXiaoDong Huang psci_power_down_wfi(); 1357*e3ec6ff4SXiaoDong Huang } 1358*e3ec6ff4SXiaoDong Huang 1359*e3ec6ff4SXiaoDong Huang static void rockchip_pmu_pd_init(void) 1360*e3ec6ff4SXiaoDong Huang { 1361*e3ec6ff4SXiaoDong Huang mmio_write_32(PMU_BASE + PMU2_BISR_CON(1), 0xffffffff); 1362*e3ec6ff4SXiaoDong Huang mmio_write_32(PMU_BASE + PMU2_BISR_CON(2), 0xffffffff); 1363*e3ec6ff4SXiaoDong Huang mmio_write_32(PMU_BASE + PMU2_BISR_CON(3), 0xffffffff); 1364*e3ec6ff4SXiaoDong Huang 1365*e3ec6ff4SXiaoDong Huang pmu_set_power_domain(PD_PHP, pmu_pd_on); 1366*e3ec6ff4SXiaoDong Huang pmu_set_power_domain(PD_PCIE, pmu_pd_on); 1367*e3ec6ff4SXiaoDong Huang pmu_set_power_domain(PD_GMAC, pmu_pd_on); 1368*e3ec6ff4SXiaoDong Huang pmu_set_power_domain(PD_SECURE, pmu_pd_on); 1369*e3ec6ff4SXiaoDong Huang pmu_set_power_domain(PD_VOP, pmu_pd_on); 1370*e3ec6ff4SXiaoDong Huang pmu_set_power_domain(PD_VO0, pmu_pd_on); 1371*e3ec6ff4SXiaoDong Huang pmu_set_power_domain(PD_VO1, pmu_pd_on); 1372*e3ec6ff4SXiaoDong Huang } 1373*e3ec6ff4SXiaoDong Huang 1374*e3ec6ff4SXiaoDong Huang #define PLL_LOCKED_TIMEOUT 600000U 1375*e3ec6ff4SXiaoDong Huang 1376*e3ec6ff4SXiaoDong Huang void pm_pll_wait_lock(uint32_t pll_base) 1377*e3ec6ff4SXiaoDong Huang { 1378*e3ec6ff4SXiaoDong Huang int delay = PLL_LOCKED_TIMEOUT; 1379*e3ec6ff4SXiaoDong Huang 1380*e3ec6ff4SXiaoDong Huang if ((mmio_read_32(pll_base + CRU_PLL_CON(1)) & CRU_PLLCON1_PWRDOWN) != 0) 1381*e3ec6ff4SXiaoDong Huang return; 1382*e3ec6ff4SXiaoDong Huang 1383*e3ec6ff4SXiaoDong Huang while (delay-- >= 0) { 1384*e3ec6ff4SXiaoDong Huang if (mmio_read_32(pll_base + CRU_PLL_CON(6)) & 1385*e3ec6ff4SXiaoDong Huang CRU_PLLCON6_LOCK_STATUS) 1386*e3ec6ff4SXiaoDong Huang break; 1387*e3ec6ff4SXiaoDong Huang udelay(1); 1388*e3ec6ff4SXiaoDong Huang } 1389*e3ec6ff4SXiaoDong Huang 1390*e3ec6ff4SXiaoDong Huang if (delay <= 0) 1391*e3ec6ff4SXiaoDong Huang ERROR("Can't wait pll(0x%x) lock\n", pll_base); 1392*e3ec6ff4SXiaoDong Huang } 1393*e3ec6ff4SXiaoDong Huang 1394*e3ec6ff4SXiaoDong Huang void rockchip_plat_mmu_el3(void) 1395*e3ec6ff4SXiaoDong Huang { 1396*e3ec6ff4SXiaoDong Huang /* Nothing todo */ 1397*e3ec6ff4SXiaoDong Huang } 1398*e3ec6ff4SXiaoDong Huang 1399*e3ec6ff4SXiaoDong Huang void plat_rockchip_pmu_init(void) 1400*e3ec6ff4SXiaoDong Huang { 1401*e3ec6ff4SXiaoDong Huang int cpu; 1402*e3ec6ff4SXiaoDong Huang 1403*e3ec6ff4SXiaoDong Huang for (cpu = 0; cpu < PLATFORM_CORE_COUNT; cpu++) 1404*e3ec6ff4SXiaoDong Huang cpuson_flags[cpu] = 0; 1405*e3ec6ff4SXiaoDong Huang 1406*e3ec6ff4SXiaoDong Huang psram_sleep_cfg->sp = PSRAM_SP_TOP; 1407*e3ec6ff4SXiaoDong Huang psram_sleep_cfg->ddr_func = (uint64_t)ddr_resume; 1408*e3ec6ff4SXiaoDong Huang psram_sleep_cfg->ddr_data = 0; 1409*e3ec6ff4SXiaoDong Huang psram_sleep_cfg->ddr_flag = 0; 1410*e3ec6ff4SXiaoDong Huang psram_sleep_cfg->boot_mpidr = read_mpidr_el1() & 0xffff; 1411*e3ec6ff4SXiaoDong Huang psram_sleep_cfg->pm_flag = PM_WARM_BOOT_BIT; 1412*e3ec6ff4SXiaoDong Huang 1413*e3ec6ff4SXiaoDong Huang nonboot_cpus_off(); 1414*e3ec6ff4SXiaoDong Huang 1415*e3ec6ff4SXiaoDong Huang /* 1416*e3ec6ff4SXiaoDong Huang * When perform idle operation, corresponding clock can be 1417*e3ec6ff4SXiaoDong Huang * opened or gated automatically. 1418*e3ec6ff4SXiaoDong Huang */ 1419*e3ec6ff4SXiaoDong Huang mmio_write_32(PMU_BASE + PMU2_BIU_AUTO_CON(0), 0xffffffff); 1420*e3ec6ff4SXiaoDong Huang mmio_write_32(PMU_BASE + PMU2_BIU_AUTO_CON(1), 0xffffffff); 1421*e3ec6ff4SXiaoDong Huang mmio_write_32(PMU_BASE + PMU2_BIU_AUTO_CON(2), 0x00070007); 1422*e3ec6ff4SXiaoDong Huang 1423*e3ec6ff4SXiaoDong Huang rockchip_pmu_pd_init(); 1424*e3ec6ff4SXiaoDong Huang 1425*e3ec6ff4SXiaoDong Huang /* grf_con_pmic_sleep_sel 1426*e3ec6ff4SXiaoDong Huang * pmic sleep function selection 1427*e3ec6ff4SXiaoDong Huang * 1'b0: From reset pulse generator, can reset external PMIC 1428*e3ec6ff4SXiaoDong Huang * 1'b1: From pmu block, only support sleep function for external PMIC 1429*e3ec6ff4SXiaoDong Huang */ 1430*e3ec6ff4SXiaoDong Huang mmio_write_32(PMU0GRF_BASE + PMU0_GRF_SOC_CON(3), 0x03ff0000); 1431*e3ec6ff4SXiaoDong Huang 1432*e3ec6ff4SXiaoDong Huang /* pmusram remap to 0xffff0000 */ 1433*e3ec6ff4SXiaoDong Huang mmio_write_32(PMU0SGRF_BASE + PMU0_SGRF_SOC_CON(2), 0x00030001); 1434*e3ec6ff4SXiaoDong Huang 1435*e3ec6ff4SXiaoDong Huang pm_reg_rgns_init(); 1436*e3ec6ff4SXiaoDong Huang } 1437