1 /*
2 * Copyright (c) 2020 HiSilicon (Shanghai) Technologies CO., LIMITED.
3 *
4 * This program is free software; you can redistribute it and/or modify it
5 * under the terms of the GNU General Public License as published by the
6 * Free Software Foundation; either version 2 of the License, or (at your
7 * option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program. If not, see <http://www.gnu.org/licenses/>.
16 *
17
18 * Description:DDR training control
19 */
20
21 #include "ddr_interface.h"
22 #include "ddr_training_impl.h"
23
24 #ifdef DDR_SW_TRAINING_FUNC_PUBLIC
25 #ifdef DDR_TRAINING_CUT_CODE_CONFIG
26 /**
27 * Cut ddr training control code for less SRAM.
28 * Support DDRC500.
29 * Support DDRC510 with one PHY.
30 */
ddr_sw_training_func(void)31 int ddr_sw_training_func(void)
32 {
33 struct ddr_cfg_st ddr_cfg;
34 struct ddr_cfg_st *cfg = &ddr_cfg;
35
36 unsigned int base_dmc = DDR_REG_BASE_DMC0;
37 unsigned int base_phy = DDR_REG_BASE_PHY0;
38 int result = 0;
39 unsigned int auto_ref_timing = ddr_read(base_dmc + DDR_DMC_TIMING2);
40 unsigned int misc_scramb = ddr_read(base_phy + DDR_PHY_MISC);
41 unsigned int dramcfg_ma2t = ddr_read(base_phy + DDR_PHY_DRAMCFG)
42 & PHY_DRAMCFG_MA2T;
43 unsigned int acphyctl;
44
45 /* Static register have to read two times to get the right value. */
46 acphyctl = ddr_read(base_phy + DDR_PHY_ACPHYCTL4);
47 acphyctl = ddr_read(base_phy + DDR_PHY_ACPHYCTL4);
48
49 DDR_VARIABLE_DECLARE(swapdfibyte_en);
50
51 /* check sw ddr training enable */
52 if (DDR_BYPASS_ALL_MASK == ddr_read(DDR_REG_BASE_SYSCTRL
53 + SYSCTRL_DDR_TRAINING_CFG))
54 return 0;
55
56 ddr_training_start();
57 ddr_training_cfg_init(cfg);
58
59 #ifdef DDR_TRAINING_STAT_CONFIG
60 /* clear stat register */
61 ddr_write(0x0, DDR_REG_BASE_SYSCTRL + SYSCTRL_DDR_TRAINING_STAT);
62 #endif
63
64 /* disable scramb */
65 ddr_write(misc_scramb & PHY_MISC_SCRAMB_DIS,
66 base_phy + DDR_PHY_MISC);
67
68 /* disable rdqs swap */
69 DDR_DQSSWAP_SAVE_FUNC(swapdfibyte_en, base_phy);
70
71 /* check hardware gating */
72 if (ddr_read(base_phy + DDR_PHY_PHYINITSTATUS)
73 & PHY_INITSTATUS_GT_MASK) {
74 DDR_FATAL("PHY[%x] hw gating fail.", base_phy);
75 ddr_training_stat(DDR_ERR_HW_GATING,
76 base_phy, -1, -1);
77 }
78
79 #ifdef DDR_LPCA_TRAINING_CONFIG
80 /* lpca */
81 if (!ddr_training_check_bypass(cfg, DDR_BYPASS_LPCA_MASK)
82 && (PHY_DRAMCFG_TYPE_LPDDR3 ==
83 (ddr_read(base_phy + DDR_PHY_DRAMCFG)
84 & PHY_DRAMCFG_TYPE_LPDDR3))) {
85 /* disable auto refresh */
86 ddr_training_set_timing(base_dmc,
87 auto_ref_timing & DMC_AUTO_TIMING_DIS);
88
89 result += ddr_lpca_training(cfg);
90
91 /* enable auto refresh */
92 ddr_training_set_timing(base_dmc, auto_ref_timing);
93 }
94 #endif
95
96 #ifdef DDR_WL_TRAINING_CONFIG
97 /* write leveling */
98 if (!ddr_training_check_bypass(cfg, DDR_BYPASS_WL_MASK)) {
99 /* disable auto refresh */
100 ddr_training_set_timing(base_dmc,
101 auto_ref_timing & DMC_AUTO_TIMING_DIS);
102 result += ddr_write_leveling(cfg);
103 /* enable auto refresh */
104 ddr_training_set_timing(base_dmc, auto_ref_timing);
105 }
106 #endif
107
108 #ifdef DDR_DATAEYE_TRAINING_CONFIG
109 /* dataeye */
110 if (!ddr_training_check_bypass(cfg, DDR_BYPASS_DATAEYE_MASK)) {
111 ddr_training_switch_axi(cfg);
112 ddr_ddrt_init(cfg, DDR_DDRT_MODE_DATAEYE);
113 result += ddr_dataeye_training(cfg);
114 }
115 #endif
116
117 #ifdef DDR_HW_TRAINING_CONFIG
118 /* hardware read */
119 if (result && !ddr_training_check_bypass(cfg, DDR_BYPASS_HW_MASK)) {
120 if (!dramcfg_ma2t) /* set 1T */
121 ddr_write(0x0, base_phy + DDR_PHY_ACPHYCTL4);
122
123 result = ddr_hw_dataeye_read(cfg);
124 if (!dramcfg_ma2t) /* restore */
125 ddr_write(acphyctl, base_phy + DDR_PHY_ACPHYCTL4);
126
127 result += ddr_dataeye_training(cfg);
128 }
129 #endif
130
131 #ifdef DDR_MPR_TRAINING_CONFIG
132 /* mpr */
133 if (result && !ddr_training_check_bypass(cfg, DDR_BYPASS_MPR_MASK)) {
134 result = ddr_mpr_training(cfg);
135 result += ddr_dataeye_training(cfg);
136 }
137 #endif
138
139 #ifdef DDR_GATE_TRAINING_CONFIG
140 /* gate */
141 if (!ddr_training_check_bypass(cfg, DDR_BYPASS_GATE_MASK)) {
142 ddr_training_switch_axi(cfg);
143 ddr_ddrt_init(cfg, DDR_DDRT_MODE_GATE);
144 /* disable auto refresh */
145 ddr_training_set_timing(base_dmc,
146 auto_ref_timing & DMC_AUTO_TIMING_DIS);
147
148 if (!dramcfg_ma2t) /* set 1T */
149 ddr_write(0x0, base_phy + DDR_PHY_ACPHYCTL4);
150
151 result += ddr_gate_training(cfg);
152
153 /* enable auto refresh */
154 ddr_training_set_timing(base_dmc, auto_ref_timing);
155
156 if (!dramcfg_ma2t) /* restore */
157 ddr_write(acphyctl, base_phy + DDR_PHY_ACPHYCTL4);
158 }
159 #endif
160
161 #ifdef DDR_VREF_TRAINING_CONFIG
162 if (!ddr_training_check_bypass(cfg, DDR_BYPASS_VREF_MASK)) {
163 ddr_training_switch_axi(cfg);
164 ddr_ddrt_init(cfg, DDR_DDRT_MODE_DATAEYE);
165 result += ddr_vref_training(cfg);
166 }
167 #endif
168
169 /* restore scramb */
170 ddr_write(misc_scramb, base_phy + DDR_PHY_MISC);
171
172 /* restore rdqs swap */
173 DDR_DQSSWAP_RESTORE_FUNC(swapdfibyte_en, base_phy);
174
175 if (!result)
176 ddr_training_suc();
177 return result;
178 }
179 #else
ddr_training_boot_func(struct ddr_cfg_st * cfg)180 int ddr_training_boot_func(struct ddr_cfg_st *cfg)
181 {
182 int result = 0;
183
184 /* check hardware gating */
185 if (ddr_read(cfg->cur_phy + DDR_PHY_PHYINITSTATUS)
186 & PHY_INITSTATUS_GT_MASK) {
187 DDR_FATAL("PHY[%x] hw gating fail.", cfg->cur_phy);
188 ddr_training_stat(DDR_ERR_HW_GATING,
189 cfg->cur_phy, -1, -1);
190 }
191
192 /* lpca */
193 result = ddr_lpca_training_func(cfg);
194 /* write leveling */
195 result += ddr_wl_func(cfg);
196 /* dataeye/gate/vref need switch axi */
197 /* dataeye */
198 result += ddr_dataeye_training_func(cfg);
199 #ifdef DDR_HW_TRAINING_CONFIG
200 /* hardware read */
201 if (result && !ddr_training_check_bypass(cfg, DDR_BYPASS_HW_MASK)) {
202 struct tr_relate_reg relate_reg_ac;
203 ddr_training_save_reg(cfg, &relate_reg_ac,
204 DDR_BYPASS_HW_MASK);
205 result = ddr_hw_dataeye_read(cfg);
206 ddr_training_restore_reg(cfg, &relate_reg_ac);
207 cfg->adjust = DDR_DATAEYE_ABNORMAL_ADJUST;
208 result += ddr_dataeye_training(cfg);
209 }
210 #endif
211 /* mpr */
212 result += ddr_mpr_training_func(cfg);
213 /* gate */
214 result += ddr_gating_func(cfg);
215 /* vref */
216 result += ddr_vref_training_func(cfg);
217
218 return result;
219 }
220
221 /* Support DDRC510 with two PHY */
ddr_sw_training_func(void)222 int ddr_sw_training_func(void)
223 {
224 struct ddr_cfg_st ddr_cfg;
225 struct ddr_cfg_st *cfg = &ddr_cfg;
226 struct tr_relate_reg reg;
227 int result = 0;
228
229 #ifdef SYSCTRL_DDR_TRAINING_VERSION_FLAG
230 /* DDR training version flag */
231 unsigned int tmp_reg = ddr_read(DDR_REG_BASE_SYSCTRL + SYSCTRL_DDR_TRAINING_VERSION_FLAG);
232 tmp_reg = (tmp_reg & 0xffff0000) | DDR_VERSION;
233 ddr_write(tmp_reg, DDR_REG_BASE_SYSCTRL + SYSCTRL_DDR_TRAINING_VERSION_FLAG);
234 #endif
235
236 /* check sw ddr training enable */
237 if (DDR_BYPASS_ALL_MASK == ddr_read(DDR_REG_BASE_SYSCTRL + SYSCTRL_DDR_TRAINING_CFG)
238 #ifdef SYSCTRL_DDR_TRAINING_CFG_SEC
239 && DDR_BYPASS_ALL_MASK == ddr_read(DDR_REG_BASE_SYSCTRL + SYSCTRL_DDR_TRAINING_CFG_SEC)
240 #endif
241 )
242 return 0;
243
244 ddr_training_start();
245
246 /* save customer reg */
247 ddr_boot_cmd_save_func(®);
248
249 #ifdef DDR_TRAINING_STAT_CONFIG
250 /* clear stat register */
251 ddr_write(0x0, DDR_REG_BASE_SYSCTRL + SYSCTRL_DDR_TRAINING_STAT);
252 #endif
253
254 ddr_training_cfg_init(cfg);
255 cfg->cmd_st = 0;
256
257 result = ddr_training_all(cfg);
258 result += ddr_dcc_training_func(cfg);
259
260 if (!result)
261 ddr_training_suc();
262 else
263 ddr_training_console_if(0);
264
265 /* restore customer reg */
266 ddr_boot_cmd_restore_func(®);
267
268 return result;
269 }
270 #endif /* DDR_TRAINING_CUT_CODE_CONFIG */
271 #endif /* DDR_SW_TRAINING_FUNC_PUBLIC */
272
273 #ifdef DDR_PCODE_TRAINING_CONFIG
ddr_pcode_training_func(void)274 int ddr_pcode_training_func(void)
275 {
276 struct ddr_cfg_st ddr_cfg;
277 struct ddr_cfg_st *cfg = &ddr_cfg;
278
279 ddr_training_cfg_init(cfg);
280 return ddr_pcode_training(cfg);
281 }
282 #else
ddr_pcode_training_func(void)283 int ddr_pcode_training_func(void)
284 {
285 DDR_WARNING("Not support DDR pcode training.");
286 return 0;
287 }
288 #endif
289
290 #ifdef DDR_HW_TRAINING_CONFIG
ddr_hw_training_func(void)291 int ddr_hw_training_func(void)
292 {
293 struct ddr_cfg_st ddr_cfg;
294 struct ddr_cfg_st *cfg = &ddr_cfg;
295
296 ddr_training_cfg_init(cfg);
297 return ddr_hw_training(cfg);
298 }
299 #else
ddr_hw_training_func(void)300 int ddr_hw_training_func(void)
301 {
302 DDR_WARNING("Not support DDR HW training.");
303 return 0;
304 }
305 #endif /* DDR_HW_TRAINING_CONFIG */
306
ddr_sw_training_if(void)307 int ddr_sw_training_if(void)
308 {
309 return DDR_SW_TRAINING_FUNC();
310 }
311
ddr_hw_training_if(void)312 int ddr_hw_training_if(void)
313 {
314 return DDR_HW_TRAINING_FUNC();
315 }
316
ddr_pcode_training_if(void)317 int ddr_pcode_training_if(void)
318 {
319 return DDR_PCODE_TRAINING_FUNC();
320 }
321
322