• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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(&reg);
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(&reg);
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