1 // SPDX-License-Identifier: BSD-3-Clause 2 /* 3 * Copyright (c) 2025, Rockchip Electronics Co., Ltd. 4 */ 5 6 #include <assert.h> 7 #include <errno.h> 8 9 #include <arch_helpers.h> 10 #include <bl31/bl31.h> 11 #include <common/debug.h> 12 #include <drivers/console.h> 13 #include <drivers/delay_timer.h> 14 #include <lib/mmio.h> 15 #include <platform.h> 16 #include <platform_def.h> 17 18 #include <dmc_rk3576.h> 19 #include <rk3576_def.h> 20 #include <soc.h> 21 22 struct rk3576_dmc_config dmc_config; 23 24 /* DDR_PHY */ 25 #define LP_CON0 0x0018 26 #define DFI_LP_CON0 0x0e04 27 /* DDR_CTL */ 28 #define DDRCTL_STAT 0x10014 29 #define DDRCTL_PWRCTL 0x10180 30 #define DDRCTL_CLKGATECTL 0x1018c 31 32 /* LP_CON0 */ 33 #define DS_IO_PD BIT(14) 34 #define SCHD_HW_CLOCK_GATING_DISABLE BIT(13) 35 #define PCL_PD BIT(12) 36 #define DQS_ENABLE BIT(10) 37 #define WCK_ENABLE BIT(9) 38 #define CTRL_DQS_DRV_OFF BIT(8) 39 #define CTRL_SCHEDULER_EN BIT(6) 40 41 /* DFI_LP_CON0 0x0e04 */ 42 #define DFI_LP_MODE_APB BIT(31) 43 44 /* DDRCTL_STAT 0x10014 */ 45 #define CTL_SELFREF_STATE_SHIFT (12) 46 #define CTL_SELFREF_STATE_MASK (0x7 << CTL_SELFREF_STATE_SHIFT) 47 #define CTL_NOT_IN_SELF_REFRESH (0x0 << CTL_SELFREF_STATE_SHIFT) 48 #define CTL_SELF_REFRESH_1 (0x1 << CTL_SELFREF_STATE_SHIFT) 49 #define CTL_SELF_REFRESH_POWER_DOWN (0x2 << CTL_SELFREF_STATE_SHIFT) 50 #define CTL_SELF_REFRESH_2 (0x3 << CTL_SELFREF_STATE_SHIFT) 51 #define CTL_SELF_REFRESH_DEEP_SLEEP (0x4 << CTL_SELFREF_STATE_SHIFT) 52 #define CTL_SELFREF_TYPE_SHIFT (4) 53 #define CTL_SELFREF_TYPE_MASK (0x3 << CTL_SELFREF_TYPE_SHIFT) 54 #define CTL_SELFREF_NOT_BY_PHY (0x1 << CTL_SELFREF_TYPE_SHIFT) 55 #define CTL_SELFREF_NOT_BY_AUTO (0x2 << CTL_SELFREF_TYPE_SHIFT) 56 #define CTL_SELFREF_BY_AUTO (0x3 << CTL_SELFREF_TYPE_SHIFT) 57 #define CTL_OPERATING_MODE_MASK (0x7) 58 #define CTL_OPERATING_MODE_INIT (0x0) 59 #define CTL_OPERATING_MODE_NORMAL (0x1) 60 #define CTL_OPERATING_MODE_PD (0x2) 61 #define CTL_OPERATING_MODE_SR_SRPD (0x3) 62 63 /* DDRCTL_PWRCTL 0x10180 */ 64 #define CTL_DSM_EN BIT(18) 65 #define CTL_STAY_IN_SELFREF BIT(15) 66 #define CTL_SELFREF_SW BIT(11) 67 #define CTL_EN_DFI_DRAM_CLK_DISABLE BIT(9) 68 #define CTL_POWERDOWN_EN_MASK (0xf) 69 #define CTL_POWERDOWN_EN_SHIFT (4) 70 #define CTL_SELFREF_EN_MASK (0xf) 71 #define CTL_SELFREF_EN_SHIFT (0) 72 73 #define SYS_REG_DEC_CHINFO(n, ch) (((n) >> (28 + (ch))) & 0x1) 74 #define SYS_REG_DEC_CHINFO_V3(reg2, ch) SYS_REG_DEC_CHINFO(reg2, ch) 75 76 #define SYS_REG_DEC_NUM_CH(n) (1 + (((n) >> 12) & 0x1)) 77 #define SYS_REG_DEC_NUM_CH_V3(reg2) SYS_REG_DEC_NUM_CH(reg2) 78 79 static void exit_low_power(uint32_t ch, struct rk3576_dmc_config *configs) 80 { 81 /* LP_CON0: [12]pcl_pd */ 82 configs->low_power[ch].pcl_pd = mmio_read_32(DDRPHY_BASE_CH(0) + LP_CON0) & PCL_PD; 83 mmio_clrbits_32(DDRPHY_BASE_CH(ch) + LP_CON0, PCL_PD); 84 85 /* Disable low power activities */ 86 configs->low_power[ch].pwrctl = mmio_read_32(UMCTL_BASE_CH(ch) + DDRCTL_PWRCTL); 87 mmio_clrbits_32(UMCTL_BASE_CH(ch) + DDRCTL_PWRCTL, 88 CTL_DSM_EN | (CTL_POWERDOWN_EN_MASK << CTL_POWERDOWN_EN_SHIFT) | 89 (CTL_SELFREF_EN_MASK << CTL_SELFREF_EN_SHIFT)); 90 while ((mmio_read_32(UMCTL_BASE_CH(ch) + DDRCTL_STAT) & CTL_OPERATING_MODE_MASK) != 91 CTL_OPERATING_MODE_NORMAL) 92 continue; 93 94 /* DDR_GRF_CHA_CON6: [6:0]rd_lat_delay, [14:8]wr_lat_delay, [15]cmd_dly_eq0_en */ 95 configs->low_power[ch].grf_ddr_con6 = 96 mmio_read_32(DDR_GRF_BASE + GRF_CH_CON(ch, 6)) & 0xff7f; 97 mmio_write_32(DDR_GRF_BASE + GRF_CH_CON(ch, 6), (0x1ul << (15 + 16))); 98 99 /* DDR_GRF_CHA_CON0: [12:8]ddrctl_axi_cg_en */ 100 configs->low_power[ch].grf_ddr_con0 = 101 mmio_read_32(DDR_GRF_BASE + GRF_CH_CON(ch, 0)) & 0x1f00; 102 mmio_write_32(DDR_GRF_BASE + GRF_CH_CON(ch, 0), 0x1f000000); 103 104 /* 105 * DDR_GRF_CHA_CON1: 106 * [15]ddrctl_apb_pclk_cg_en, [12]ddrmon_pclk_cg_en, [7]dfi_scramble_cg_en, 107 * [6]ddrctl_mem_cg_en, [5]bsm_clk_cg_en, [2]ddrctl_core_cg_en, [1]ddrctl_apb_cg_en 108 */ 109 configs->low_power[ch].grf_ddr_con1 = 110 mmio_read_32(DDR_GRF_BASE + GRF_CH_CON(ch, 1)) & 0x90e6; 111 mmio_write_32(DDR_GRF_BASE + GRF_CH_CON(ch, 1), 0x90e60000); 112 113 configs->low_power[ch].hwlp_0 = mmio_read_32(HWLP_BASE_CH(ch) + 0x0); 114 mmio_write_32(HWLP_BASE_CH(ch) + 0x0, 0x0); 115 configs->low_power[ch].hwlp_c = mmio_read_32(HWLP_BASE_CH(ch) + 0xc); 116 mmio_write_32(HWLP_BASE_CH(ch) + 0xc, 0x0); 117 118 /* DDR_GRF_CHA_PHY_CON0: [14]ddrphy_pclk_cg_en */ 119 configs->low_power[ch].grf_ddrphy_con0 = 120 mmio_read_32(DDR_GRF_BASE + GRF_DDRPHY_CON0(ch)) & BIT(14); 121 mmio_write_32(DDR_GRF_BASE + GRF_DDRPHY_CON0(ch), BIT(14 + 16)); 122 123 /* CLKGATECTL: [5:0]bsm_clk_on */ 124 configs->low_power[ch].clkgatectl = 125 mmio_read_32(UMCTL_BASE_CH(ch) + DDRCTL_CLKGATECTL) & 0x3f; 126 /* DFI_LP_CON0: [31]dfi_lp_mode_apb */ 127 configs->low_power[ch].dfi_lp_mode_apb = 128 (mmio_read_32(DDRPHY_BASE_CH(ch) + DFI_LP_CON0) >> 31) & 0x1; 129 } 130 131 static void resume_low_power(uint32_t ch, struct rk3576_dmc_config *configs) 132 { 133 /* DFI_LP_CON0: [31]dfi_lp_mode_apb */ 134 if (configs->low_power[ch].dfi_lp_mode_apb != 0) 135 mmio_setbits_32(DDRPHY_BASE_CH(ch) + DFI_LP_CON0, DFI_LP_MODE_APB); 136 137 /* CLKGATECTL: [5:0]bsm_clk_on */ 138 mmio_clrsetbits_32(UMCTL_BASE_CH(ch) + DDRCTL_CLKGATECTL, 139 0x3f, configs->low_power[ch].clkgatectl & 0x3f); 140 141 /* DDR_GRF_CHA_CON6: [6:0]rd_lat_delay, [14:8]wr_lat_delay, [15]cmd_dly_eq0_en */ 142 mmio_write_32(DDR_GRF_BASE + GRF_CH_CON(ch, 6), 143 (0xff7ful << 16) | configs->low_power[ch].grf_ddr_con6); 144 145 mmio_write_32(HWLP_BASE_CH(ch) + 0xc, configs->low_power[ch].hwlp_c); 146 mmio_write_32(HWLP_BASE_CH(ch) + 0x0, configs->low_power[ch].hwlp_0); 147 148 /* DDR_GRF_CHA_CON0: [12:8]ddrctl_axi_cg_en */ 149 mmio_write_32(DDR_GRF_BASE + GRF_CH_CON(ch, 0), 150 (0x1f00ul << 16) | configs->low_power[ch].grf_ddr_con0); 151 152 /* 153 * DDR_GRF_CHA_CON1: 154 * [15]ddrctl_apb_pclk_cg_en, [12]ddrmon_pclk_cg_en, [7]dfi_scramble_cg_en, 155 * [6]ddrctl_mem_cg_en, [5]bsm_clk_cg_en, [2]ddrctl_core_cg_en, [1]ddrctl_apb_cg_en 156 */ 157 mmio_write_32(DDR_GRF_BASE + GRF_CH_CON(ch, 1), 158 (0x90e6ul << 16) | configs->low_power[ch].grf_ddr_con1); 159 160 /* DDR_GRF_CHA_PHY_CON0: [14]ddrphy_pclk_cg_en */ 161 mmio_write_32(DDR_GRF_BASE + GRF_DDRPHY_CON0(ch), 162 BIT(14 + 16) | configs->low_power[ch].grf_ddrphy_con0); 163 164 /* reset low power activities */ 165 mmio_write_32(UMCTL_BASE_CH(ch) + DDRCTL_PWRCTL, configs->low_power[ch].pwrctl); 166 167 /* LP_CON0: [12]pcl_pd */ 168 if (configs->low_power[ch].pcl_pd != 0) 169 mmio_setbits_32(DDRPHY_BASE_CH(ch) + LP_CON0, PCL_PD); 170 } 171 172 void dmc_save(void) 173 { 174 uint32_t i, channel_num; 175 176 channel_num = 177 SYS_REG_DEC_NUM_CH_V3(mmio_read_32(PMU1_GRF_BASE + PMUGRF_OS_REG(2))); 178 179 for (i = 0; i < channel_num; i++) 180 exit_low_power(i, &dmc_config); 181 } 182 183 void dmc_restore(void) 184 { 185 uint32_t i, channel_num; 186 187 channel_num = SYS_REG_DEC_NUM_CH_V3(mmio_read_32(PMU1_GRF_BASE + PMUGRF_OS_REG(2))); 188 189 for (i = 0; i < channel_num; i++) 190 resume_low_power(i, &dmc_config); 191 } 192