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