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
exit_low_power(uint32_t ch,struct rk3576_dmc_config * configs)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
resume_low_power(uint32_t ch,struct rk3576_dmc_config * configs)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
dmc_save(void)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
dmc_restore(void)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