1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3  * Copyright 2018-2019 NXP
4  */
5 
6 #include <common.h>
7 #include <errno.h>
8 #include <log.h>
9 #include <asm/io.h>
10 #include <asm/arch/ddr.h>
11 #include <asm/arch/clock.h>
12 #include <asm/arch/sys_proto.h>
13 
ddr_cfg_umctl2(struct dram_cfg_param * ddrc_cfg,int num)14 void ddr_cfg_umctl2(struct dram_cfg_param *ddrc_cfg, int num)
15 {
16 	int i = 0;
17 
18 	for (i = 0; i < num; i++) {
19 		reg32_write(ddrc_cfg->reg, ddrc_cfg->val);
20 		ddrc_cfg++;
21 	}
22 }
23 
24 #ifdef CONFIG_IMX8M_DRAM_INLINE_ECC
ddrc_inline_ecc_scrub(unsigned int start_address,unsigned int range_address)25 void ddrc_inline_ecc_scrub(unsigned int start_address,
26 			   unsigned int range_address)
27 {
28 	unsigned int tmp;
29 
30 	/* Step1: Enable quasi-dynamic programming */
31 	reg32_write(DDRC_SWCTL(0), 0x00000000);
32 	/* Step2: Set ECCCFG1.ecc_parity_region_lock to 1 */
33 	reg32setbit(DDRC_ECCCFG1(0), 0x4);
34 	/* Step3: Block the AXI ports from taking the transaction */
35 	reg32_write(DDRC_PCTRL_0(0), 0x0);
36 	/* Step4: Set scrub start address */
37 	reg32_write(DDRC_SBRSTART0(0), start_address);
38 	/* Step5: Set scrub range address */
39 	reg32_write(DDRC_SBRRANGE0(0), range_address);
40 	/* Step6: Set scrub_mode to write */
41 	reg32_write(DDRC_SBRCTL(0), 0x00000014);
42 	/* Step7: Set the desired pattern through SBRWDATA0 registers */
43 	reg32_write(DDRC_SBRWDATA0(0), 0x55aa55aa);
44 	/* Step8: Enable the SBR by programming SBRCTL.scrub_en=1 */
45 	reg32setbit(DDRC_SBRCTL(0), 0x0);
46 	/* Step9: Poll SBRSTAT.scrub_done=1 */
47 	tmp = reg32_read(DDRC_SBRSTAT(0));
48 	while (tmp != 0x00000002)
49 		tmp = reg32_read(DDRC_SBRSTAT(0)) & 0x2;
50 	/* Step10: Poll SBRSTAT.scrub_busy=0 */
51 	tmp = reg32_read(DDRC_SBRSTAT(0));
52 	while (tmp != 0x0)
53 		tmp = reg32_read(DDRC_SBRSTAT(0)) & 0x1;
54 	/* Step11: Disable SBR by programming SBRCTL.scrub_en=0 */
55 	clrbits_le32(DDRC_SBRCTL(0), 0x1);
56 	/* Step12: Prepare for normal scrub operation(Read) and set scrub_interval*/
57 	reg32_write(DDRC_SBRCTL(0), 0x100);
58 	/* Step13: Enable the SBR by programming SBRCTL.scrub_en=1 */
59 	reg32_write(DDRC_SBRCTL(0), 0x101);
60 	/* Step14: Enable AXI ports by programming */
61 	reg32_write(DDRC_PCTRL_0(0), 0x1);
62 	/* Step15: Disable quasi-dynamic programming */
63 	reg32_write(DDRC_SWCTL(0), 0x00000001);
64 }
65 
ddrc_inline_ecc_scrub_end(unsigned int start_address,unsigned int range_address)66 void ddrc_inline_ecc_scrub_end(unsigned int start_address,
67 			       unsigned int range_address)
68 {
69 	/* Step1: Enable quasi-dynamic programming */
70 	reg32_write(DDRC_SWCTL(0), 0x00000000);
71 	/* Step2: Block the AXI ports from taking the transaction */
72 	reg32_write(DDRC_PCTRL_0(0), 0x0);
73 	/* Step3: Set scrub start address */
74 	reg32_write(DDRC_SBRSTART0(0), start_address);
75 	/* Step4: Set scrub range address */
76 	reg32_write(DDRC_SBRRANGE0(0), range_address);
77 	/* Step5: Disable SBR by programming SBRCTL.scrub_en=0 */
78 	clrbits_le32(DDRC_SBRCTL(0), 0x1);
79 	/* Step6: Prepare for normal scrub operation(Read) and set scrub_interval */
80 	reg32_write(DDRC_SBRCTL(0), 0x100);
81 	/* Step7: Enable the SBR by programming SBRCTL.scrub_en=1 */
82 	reg32_write(DDRC_SBRCTL(0), 0x101);
83 	/* Step8: Enable AXI ports by programming */
84 	reg32_write(DDRC_PCTRL_0(0), 0x1);
85 	/* Step9: Disable quasi-dynamic programming */
86 	reg32_write(DDRC_SWCTL(0), 0x00000001);
87 }
88 #endif
89 
board_dram_ecc_scrub(void)90 void __weak board_dram_ecc_scrub(void)
91 {
92 }
93 
ddr_init(struct dram_timing_info * dram_timing)94 int ddr_init(struct dram_timing_info *dram_timing)
95 {
96 	unsigned int tmp, initial_drate, target_freq;
97 	int ret;
98 
99 	debug("DDRINFO: start DRAM init\n");
100 
101 	/* Step1: Follow the power up procedure */
102 	if (is_imx8mq()) {
103 		reg32_write(SRC_DDRC_RCR_ADDR + 0x04, 0x8F00000F);
104 		reg32_write(SRC_DDRC_RCR_ADDR, 0x8F00000F);
105 		reg32_write(SRC_DDRC_RCR_ADDR + 0x04, 0x8F000000);
106 	} else {
107 		reg32_write(SRC_DDRC_RCR_ADDR, 0x8F00001F);
108 		reg32_write(SRC_DDRC_RCR_ADDR, 0x8F00000F);
109 	}
110 
111 	debug("DDRINFO: cfg clk\n");
112 	/* change the clock source of dram_apb_clk_root: source 4 800MHz /4 = 200MHz */
113 	clock_set_target_val(DRAM_APB_CLK_ROOT, CLK_ROOT_ON | CLK_ROOT_SOURCE_SEL(4) |
114 			     CLK_ROOT_PRE_DIV(CLK_ROOT_PRE_DIV4));
115 
116 	/* disable iso */
117 	reg32_write(0x303A00EC, 0x0000ffff); /* PGC_CPU_MAPPING */
118 	reg32setbit(0x303A00F8, 5); /* PU_PGC_SW_PUP_REQ */
119 
120 	initial_drate = dram_timing->fsp_msg[0].drate;
121 	/* default to the frequency point 0 clock */
122 	ddrphy_init_set_dfi_clk(initial_drate);
123 
124 	/* D-aasert the presetn */
125 	reg32_write(SRC_DDRC_RCR_ADDR, 0x8F000006);
126 
127 	/* Step2: Program the dwc_ddr_umctl2 registers */
128 	debug("DDRINFO: ddrc config start\n");
129 	ddr_cfg_umctl2(dram_timing->ddrc_cfg, dram_timing->ddrc_cfg_num);
130 	debug("DDRINFO: ddrc config done\n");
131 
132 	/* Step3: De-assert reset signal(core_ddrc_rstn & aresetn_n) */
133 	reg32_write(SRC_DDRC_RCR_ADDR, 0x8F000004);
134 	reg32_write(SRC_DDRC_RCR_ADDR, 0x8F000000);
135 
136 	/*
137 	 * Step4: Disable auto-refreshes, self-refresh, powerdown, and
138 	 * assertion of dfi_dram_clk_disable by setting RFSHCTL3.dis_auto_refresh = 1,
139 	 * PWRCTL.powerdown_en = 0, and PWRCTL.selfref_en = 0, PWRCTL.en_dfi_dram_clk_disable = 0
140 	 */
141 	reg32_write(DDRC_DBG1(0), 0x00000000);
142 	reg32_write(DDRC_RFSHCTL3(0), 0x0000001);
143 	reg32_write(DDRC_PWRCTL(0), 0xa0);
144 
145 	/* if ddr type is LPDDR4, do it */
146 	tmp = reg32_read(DDRC_MSTR(0));
147 	if (tmp & (0x1 << 5) && !is_imx8mn())
148 		reg32_write(DDRC_DDR_SS_GPR0, 0x01); /* LPDDR4 mode */
149 
150 	/* determine the initial boot frequency */
151 	target_freq = reg32_read(DDRC_MSTR2(0)) & 0x3;
152 	target_freq = (tmp & (0x1 << 29)) ? target_freq : 0x0;
153 
154 	/* Step5: Set SWCT.sw_done to 0 */
155 	reg32_write(DDRC_SWCTL(0), 0x00000000);
156 
157 	/* Set the default boot frequency point */
158 	clrsetbits_le32(DDRC_DFIMISC(0), (0x1f << 8), target_freq << 8);
159 	/* Step6: Set DFIMISC.dfi_init_complete_en to 0 */
160 	clrbits_le32(DDRC_DFIMISC(0), 0x1);
161 
162 	/* Step7: Set SWCTL.sw_done to 1; need to polling SWSTAT.sw_done_ack */
163 	reg32_write(DDRC_SWCTL(0), 0x00000001);
164 	do {
165 		tmp = reg32_read(DDRC_SWSTAT(0));
166 	} while ((tmp & 0x1) == 0x0);
167 
168 	/*
169 	 * Step8 ~ Step13: Start PHY initialization and training by
170 	 * accessing relevant PUB registers
171 	 */
172 	debug("DDRINFO:ddrphy config start\n");
173 
174 	ret = ddr_cfg_phy(dram_timing);
175 	if (ret)
176 		return ret;
177 
178 	debug("DDRINFO: ddrphy config done\n");
179 
180 	/*
181 	 * step14 CalBusy.0 =1, indicates the calibrator is actively
182 	 * calibrating. Wait Calibrating done.
183 	 */
184 	do {
185 		tmp = reg32_read(DDRPHY_CalBusy(0));
186 	} while ((tmp & 0x1));
187 
188 	debug("DDRINFO:ddrphy calibration done\n");
189 
190 	/* Step15: Set SWCTL.sw_done to 0 */
191 	reg32_write(DDRC_SWCTL(0), 0x00000000);
192 
193 	/* Apply rank-to-rank workaround */
194 	update_umctl2_rank_space_setting(dram_timing->fsp_msg_num - 1);
195 
196 	/* Step16: Set DFIMISC.dfi_init_start to 1 */
197 	setbits_le32(DDRC_DFIMISC(0), (0x1 << 5));
198 
199 	/* Step17: Set SWCTL.sw_done to 1; need to polling SWSTAT.sw_done_ack */
200 	reg32_write(DDRC_SWCTL(0), 0x00000001);
201 	do {
202 		tmp = reg32_read(DDRC_SWSTAT(0));
203 	} while ((tmp & 0x1) == 0x0);
204 
205 	/* Step18: Polling DFISTAT.dfi_init_complete = 1 */
206 	do {
207 		tmp = reg32_read(DDRC_DFISTAT(0));
208 	} while ((tmp & 0x1) == 0x0);
209 
210 	/* Step19: Set SWCTL.sw_done to 0 */
211 	reg32_write(DDRC_SWCTL(0), 0x00000000);
212 
213 	/* Step20: Set DFIMISC.dfi_init_start to 0 */
214 	clrbits_le32(DDRC_DFIMISC(0), (0x1 << 5));
215 
216 	/* Step21: optional */
217 
218 	/* Step22: Set DFIMISC.dfi_init_complete_en to 1 */
219 	setbits_le32(DDRC_DFIMISC(0), 0x1);
220 
221 	/* Step23: Set PWRCTL.selfref_sw to 0 */
222 	clrbits_le32(DDRC_PWRCTL(0), (0x1 << 5));
223 
224 	/* Step24: Set SWCTL.sw_done to 1; need polling SWSTAT.sw_done_ack */
225 	reg32_write(DDRC_SWCTL(0), 0x00000001);
226 	do {
227 		tmp = reg32_read(DDRC_SWSTAT(0));
228 	} while ((tmp & 0x1) == 0x0);
229 
230 	/* Step25: Wait for dwc_ddr_umctl2 to move to normal operating mode by monitoring
231 	 * STAT.operating_mode signal */
232 	do {
233 		tmp = reg32_read(DDRC_STAT(0));
234 	} while ((tmp & 0x3) != 0x1);
235 
236 	/* Step26: Set back register in Step4 to the original values if desired */
237 	reg32_write(DDRC_RFSHCTL3(0), 0x0000000);
238 
239 	/* enable port 0 */
240 	reg32_write(DDRC_PCTRL_0(0), 0x00000001);
241 	debug("DDRINFO: ddrmix config done\n");
242 
243 	board_dram_ecc_scrub();
244 
245 	/* enable selfref_en by default */
246 	setbits_le32(DDRC_PWRCTL(0), 0x1);
247 
248 	/* save the dram timing config into memory */
249 	dram_config_save(dram_timing, CONFIG_SAVED_DRAM_TIMING_BASE);
250 
251 	return 0;
252 }
253