1 // SPDX-License-Identifier: GPL-2.0
2 /*
3  * (C) Copyright 2018 Rockchip Electronics Co., Ltd.
4  */
5 
6 #include <common.h>
7 #include <debug_uart.h>
8 #include <ram.h>
9 #include <asm/io.h>
10 #include <asm/arch-rockchip/sdram.h>
11 #include <asm/arch-rockchip/sdram_common.h>
12 
13 #ifdef CONFIG_RAM_ROCKCHIP_DEBUG
sdram_print_dram_type(unsigned char dramtype)14 void sdram_print_dram_type(unsigned char dramtype)
15 {
16 	switch (dramtype) {
17 	case DDR3:
18 		printascii("DDR3");
19 		break;
20 	case DDR4:
21 		printascii("DDR4");
22 		break;
23 	case LPDDR2:
24 		printascii("LPDDR2");
25 		break;
26 	case LPDDR3:
27 		printascii("LPDDR3");
28 		break;
29 	case LPDDR4:
30 		printascii("LPDDR4");
31 		break;
32 	default:
33 		printascii("Unknown Device");
34 		break;
35 	}
36 }
37 
sdram_print_ddr_info(struct sdram_cap_info * cap_info,struct sdram_base_params * base)38 void sdram_print_ddr_info(struct sdram_cap_info *cap_info,
39 			  struct sdram_base_params *base)
40 {
41 	u64 cap;
42 	u32 bg;
43 
44 	bg = (cap_info->dbw == 0) ? 2 : 1;
45 
46 	sdram_print_dram_type(base->dramtype);
47 
48 	printascii(", ");
49 	printdec(base->ddr_freq);
50 	printascii("MHz\n");
51 
52 	printascii("BW=");
53 	printdec(8 << cap_info->bw);
54 	printascii(" Col=");
55 	printdec(cap_info->col);
56 	printascii(" Bk=");
57 	printdec(0x1 << cap_info->bk);
58 	if (base->dramtype == DDR4) {
59 		printascii(" BG=");
60 		printdec(1 << bg);
61 	}
62 	printascii(" CS0 Row=");
63 	printdec(cap_info->cs0_row);
64 	if (cap_info->cs0_high16bit_row !=
65 		cap_info->cs0_row) {
66 		printascii("/");
67 		printdec(cap_info->cs0_high16bit_row);
68 	}
69 	if (cap_info->rank > 1) {
70 		printascii(" CS1 Row=");
71 		printdec(cap_info->cs1_row);
72 		if (cap_info->cs1_high16bit_row !=
73 			cap_info->cs1_row) {
74 			printascii("/");
75 			printdec(cap_info->cs1_high16bit_row);
76 		}
77 	}
78 	printascii(" CS=");
79 	printdec(cap_info->rank);
80 	printascii(" Die BW=");
81 	printdec(8 << cap_info->dbw);
82 
83 	cap = sdram_get_cs_cap(cap_info, 3, base->dramtype);
84 	if (cap_info->row_3_4)
85 		cap = cap * 3 / 4;
86 
87 	printascii(" Size=");
88 	printdec(cap >> 20);
89 	printascii("MB\n");
90 }
91 
sdram_print_stride(unsigned int stride)92 void sdram_print_stride(unsigned int stride)
93 {
94 	switch (stride) {
95 	case 0xc:
96 		printf("128B stride\n");
97 		break;
98 	case 5:
99 	case 9:
100 	case 0xd:
101 	case 0x11:
102 	case 0x19:
103 		printf("256B stride\n");
104 		break;
105 	case 0xa:
106 	case 0xe:
107 	case 0x12:
108 		printf("512B stride\n");
109 		break;
110 	case 0xf:
111 		printf("4K stride\n");
112 		break;
113 	case 0x1f:
114 		printf("32MB + 256B stride\n");
115 		break;
116 	default:
117 		printf("no stride\n");
118 	}
119 }
120 #else
sdram_print_dram_type(unsigned char dramtype)121 inline void sdram_print_dram_type(unsigned char dramtype)
122 {
123 }
124 
sdram_print_ddr_info(struct sdram_cap_info * cap_info,struct sdram_base_params * base)125 inline void sdram_print_ddr_info(struct sdram_cap_info *cap_info,
126 				 struct sdram_base_params *base)
127 {
128 }
129 
sdram_print_stride(unsigned int stride)130 inline void sdram_print_stride(unsigned int stride)
131 {
132 }
133 #endif
134 
135 /*
136  * cs: 0:cs0
137  *	   1:cs1
138  *     else cs0+cs1
139  * note: it didn't consider about row_3_4
140  */
sdram_get_cs_cap(struct sdram_cap_info * cap_info,u32 cs,u32 dram_type)141 u64 sdram_get_cs_cap(struct sdram_cap_info *cap_info, u32 cs, u32 dram_type)
142 {
143 	u32 bg;
144 	u64 cap[2];
145 
146 	if (dram_type == DDR4)
147 		/* DDR4 8bit dram BG = 2(4bank groups),
148 		 * 16bit dram BG = 1 (2 bank groups)
149 		 */
150 		bg = (cap_info->dbw == 0) ? 2 : 1;
151 	else
152 		bg = 0;
153 	cap[0] = 1llu << (cap_info->bw + cap_info->col +
154 		bg + cap_info->bk + cap_info->cs0_row);
155 
156 	if (cap_info->rank == 2)
157 		cap[1] = 1llu << (cap_info->bw + cap_info->col +
158 			bg + cap_info->bk + cap_info->cs1_row);
159 	else
160 		cap[1] = 0;
161 
162 	if (cs == 0)
163 		return cap[0];
164 	else if (cs == 1)
165 		return cap[1];
166 	else
167 		return (cap[0] + cap[1]);
168 }
169 
170 /* n: Unit bytes */
sdram_copy_to_reg(u32 * dest,const u32 * src,u32 n)171 void sdram_copy_to_reg(u32 *dest, const u32 *src, u32 n)
172 {
173 	int i;
174 
175 	for (i = 0; i < n / sizeof(u32); i++) {
176 		writel(*src, dest);
177 		src++;
178 		dest++;
179 	}
180 }
181 
sdram_org_config(struct sdram_cap_info * cap_info,struct sdram_base_params * base,u32 * p_os_reg2,u32 * p_os_reg3,u32 channel)182 void sdram_org_config(struct sdram_cap_info *cap_info,
183 		      struct sdram_base_params *base,
184 		      u32 *p_os_reg2, u32 *p_os_reg3, u32 channel)
185 {
186 	*p_os_reg2 |= SYS_REG_ENC_DDRTYPE(base->dramtype);
187 	*p_os_reg2 |= SYS_REG_ENC_NUM_CH(base->num_channels);
188 
189 	*p_os_reg2 |= SYS_REG_ENC_ROW_3_4(cap_info->row_3_4, channel);
190 	*p_os_reg2 |= SYS_REG_ENC_CHINFO(channel);
191 	*p_os_reg2 |= SYS_REG_ENC_RANK(cap_info->rank, channel);
192 	*p_os_reg2 |= SYS_REG_ENC_COL(cap_info->col, channel);
193 	*p_os_reg2 |= SYS_REG_ENC_BK(cap_info->bk, channel);
194 	*p_os_reg2 |= SYS_REG_ENC_BW(cap_info->bw, channel);
195 	*p_os_reg2 |= SYS_REG_ENC_DBW(cap_info->dbw, channel);
196 
197 	SYS_REG_ENC_CS0_ROW(cap_info->cs0_row, *p_os_reg2, *p_os_reg3, channel);
198 	if (cap_info->cs1_row)
199 		SYS_REG_ENC_CS1_ROW(cap_info->cs1_row, *p_os_reg2,
200 				    *p_os_reg3, channel);
201 	*p_os_reg3 |= SYS_REG_ENC_CS1_COL(cap_info->col, channel);
202 	*p_os_reg3 |= SYS_REG_ENC_VERSION(DDR_SYS_REG_VERSION);
203 }
204 
sdram_detect_bw(struct sdram_cap_info * cap_info)205 int sdram_detect_bw(struct sdram_cap_info *cap_info)
206 {
207 	return 0;
208 }
209 
sdram_detect_cs(struct sdram_cap_info * cap_info)210 int sdram_detect_cs(struct sdram_cap_info *cap_info)
211 {
212 	return 0;
213 }
214 
sdram_detect_col(struct sdram_cap_info * cap_info,u32 coltmp)215 int sdram_detect_col(struct sdram_cap_info *cap_info,
216 		     u32 coltmp)
217 {
218 	void __iomem *test_addr;
219 	u32 col;
220 	u32 bw = cap_info->bw;
221 
222 	for (col = coltmp; col >= 9; col -= 1) {
223 		writel(0, CONFIG_SYS_SDRAM_BASE);
224 		test_addr = (void __iomem *)(CONFIG_SYS_SDRAM_BASE +
225 				(1ul << (col + bw - 1ul)));
226 		writel(PATTERN, test_addr);
227 		if ((readl(test_addr) == PATTERN) &&
228 		    (readl(CONFIG_SYS_SDRAM_BASE) == 0))
229 			break;
230 	}
231 	if (col == 8) {
232 		printascii("col error\n");
233 		return -1;
234 	}
235 
236 	cap_info->col = col;
237 
238 	return 0;
239 }
240 
sdram_detect_bank(struct sdram_cap_info * cap_info,u32 coltmp,u32 bktmp)241 int sdram_detect_bank(struct sdram_cap_info *cap_info,
242 		      u32 coltmp, u32 bktmp)
243 {
244 	void __iomem *test_addr;
245 	u32 bk;
246 	u32 bw = cap_info->bw;
247 
248 	test_addr = (void __iomem *)(CONFIG_SYS_SDRAM_BASE +
249 			(1ul << (coltmp + bktmp + bw - 1ul)));
250 	writel(0, CONFIG_SYS_SDRAM_BASE);
251 	writel(PATTERN, test_addr);
252 	if ((readl(test_addr) == PATTERN) &&
253 	    (readl(CONFIG_SYS_SDRAM_BASE) == 0))
254 		bk = 3;
255 	else
256 		bk = 2;
257 
258 	cap_info->bk = bk;
259 
260 	return 0;
261 }
262 
263 /* detect bg for ddr4 */
sdram_detect_bg(struct sdram_cap_info * cap_info,u32 coltmp)264 int sdram_detect_bg(struct sdram_cap_info *cap_info,
265 		    u32 coltmp)
266 {
267 	void __iomem *test_addr;
268 	u32 dbw;
269 	u32 bw = cap_info->bw;
270 
271 	test_addr = (void __iomem *)(CONFIG_SYS_SDRAM_BASE +
272 			(1ul << (coltmp + bw + 1ul)));
273 	writel(0, CONFIG_SYS_SDRAM_BASE);
274 	writel(PATTERN, test_addr);
275 	if ((readl(test_addr) == PATTERN) &&
276 	    (readl(CONFIG_SYS_SDRAM_BASE) == 0))
277 		dbw = 0;
278 	else
279 		dbw = 1;
280 
281 	cap_info->dbw = dbw;
282 
283 	return 0;
284 }
285 
286 /* detect dbw for ddr3,lpddr2,lpddr3,lpddr4 */
sdram_detect_dbw(struct sdram_cap_info * cap_info,u32 dram_type)287 int sdram_detect_dbw(struct sdram_cap_info *cap_info, u32 dram_type)
288 {
289 	u32 row, col, bk, bw, cs_cap, cs;
290 	u32 die_bw_0 = 0, die_bw_1 = 0;
291 
292 	if (dram_type == DDR3 || dram_type == LPDDR4) {
293 		cap_info->dbw = 1;
294 	} else if (dram_type == LPDDR3 || dram_type == LPDDR2) {
295 		row = cap_info->cs0_row;
296 		col = cap_info->col;
297 		bk = cap_info->bk;
298 		cs = cap_info->rank;
299 		bw = cap_info->bw;
300 		cs_cap = (1 << (row + col + bk + bw - 20));
301 		if (bw == 2) {
302 			if (cs_cap <= 0x2000000) /* 256Mb */
303 				die_bw_0 = (col < 9) ? 2 : 1;
304 			else if (cs_cap <= 0x10000000) /* 2Gb */
305 				die_bw_0 = (col < 10) ? 2 : 1;
306 			else if (cs_cap <= 0x40000000) /* 8Gb */
307 				die_bw_0 = (col < 11) ? 2 : 1;
308 			else
309 				die_bw_0 = (col < 12) ? 2 : 1;
310 			if (cs > 1) {
311 				row = cap_info->cs1_row;
312 				cs_cap = (1 << (row + col + bk + bw - 20));
313 				if (cs_cap <= 0x2000000) /* 256Mb */
314 					die_bw_0 = (col < 9) ? 2 : 1;
315 				else if (cs_cap <= 0x10000000) /* 2Gb */
316 					die_bw_0 = (col < 10) ? 2 : 1;
317 				else if (cs_cap <= 0x40000000) /* 8Gb */
318 					die_bw_0 = (col < 11) ? 2 : 1;
319 				else
320 					die_bw_0 = (col < 12) ? 2 : 1;
321 			}
322 		} else {
323 			die_bw_1 = 1;
324 			die_bw_0 = 1;
325 		}
326 		cap_info->dbw = (die_bw_0 > die_bw_1) ? die_bw_0 : die_bw_1;
327 	}
328 
329 	return 0;
330 }
331 
sdram_detect_row(struct sdram_cap_info * cap_info,u32 coltmp,u32 bktmp,u32 rowtmp)332 int sdram_detect_row(struct sdram_cap_info *cap_info,
333 		     u32 coltmp, u32 bktmp, u32 rowtmp)
334 {
335 	u32 row;
336 	u32 bw = cap_info->bw;
337 	void __iomem *test_addr;
338 
339 	for (row = rowtmp; row > 12; row--) {
340 		writel(0, CONFIG_SYS_SDRAM_BASE);
341 		test_addr = (void __iomem *)(CONFIG_SYS_SDRAM_BASE +
342 				(1ul << (row + bktmp + coltmp + bw - 1ul)));
343 		writel(PATTERN, test_addr);
344 		if ((readl(test_addr) == PATTERN) &&
345 		    (readl(CONFIG_SYS_SDRAM_BASE) == 0))
346 			break;
347 	}
348 	if (row == 12) {
349 		printascii("row error");
350 		return -1;
351 	}
352 
353 	cap_info->cs0_row = row;
354 
355 	return 0;
356 }
357 
sdram_detect_row_3_4(struct sdram_cap_info * cap_info,u32 coltmp,u32 bktmp)358 int sdram_detect_row_3_4(struct sdram_cap_info *cap_info,
359 			 u32 coltmp, u32 bktmp)
360 {
361 	u32 row_3_4;
362 	u32 bw = cap_info->bw;
363 	u32 row = cap_info->cs0_row;
364 	void __iomem *test_addr, *test_addr1;
365 
366 	test_addr = CONFIG_SYS_SDRAM_BASE;
367 	test_addr1 = (void __iomem *)(CONFIG_SYS_SDRAM_BASE +
368 			(0x3ul << (row + bktmp + coltmp + bw - 1ul - 1ul)));
369 
370 	writel(0, test_addr);
371 	writel(PATTERN, test_addr1);
372 	if ((readl(test_addr) == 0) && (readl(test_addr1) == PATTERN))
373 		row_3_4 = 0;
374 	else
375 		row_3_4 = 1;
376 
377 	cap_info->row_3_4 = row_3_4;
378 
379 	return 0;
380 }
381 
sdram_detect_high_row(struct sdram_cap_info * cap_info)382 int sdram_detect_high_row(struct sdram_cap_info *cap_info)
383 {
384 	cap_info->cs0_high16bit_row = cap_info->cs0_row;
385 	cap_info->cs1_high16bit_row = cap_info->cs1_row;
386 
387 	return 0;
388 }
389 
sdram_detect_cs1_row(struct sdram_cap_info * cap_info,u32 dram_type)390 int sdram_detect_cs1_row(struct sdram_cap_info *cap_info, u32 dram_type)
391 {
392 	void __iomem *test_addr;
393 	u32 row = 0, bktmp, coltmp, bw;
394 	ulong cs0_cap;
395 	u32 byte_mask;
396 
397 	if (cap_info->rank == 2) {
398 		cs0_cap = sdram_get_cs_cap(cap_info, 0, dram_type);
399 
400 		if (dram_type == DDR4) {
401 			if (cap_info->dbw == 0)
402 				bktmp = cap_info->bk + 2;
403 			else
404 				bktmp = cap_info->bk + 1;
405 		} else {
406 			bktmp = cap_info->bk;
407 		}
408 		bw = cap_info->bw;
409 		coltmp = cap_info->col;
410 
411 		/*
412 		 * because px30 support axi split,min bandwidth
413 		 * is 8bit. if cs0 is 32bit, cs1 may 32bit or 16bit
414 		 * so we check low 16bit data when detect cs1 row.
415 		 * if cs0 is 16bit/8bit, we check low 8bit data.
416 		 */
417 		if (bw == 2)
418 			byte_mask = 0xFFFF;
419 		else
420 			byte_mask = 0xFF;
421 
422 		/* detect cs1 row */
423 		for (row = cap_info->cs0_row; row > 12; row--) {
424 			test_addr = (void __iomem *)(CONFIG_SYS_SDRAM_BASE +
425 				    cs0_cap +
426 				    (1ul << (row + bktmp + coltmp + bw - 1ul)));
427 			writel(0, CONFIG_SYS_SDRAM_BASE + cs0_cap);
428 			writel(PATTERN, test_addr);
429 
430 			if (((readl(test_addr) & byte_mask) ==
431 			     (PATTERN & byte_mask)) &&
432 			    ((readl(CONFIG_SYS_SDRAM_BASE + cs0_cap) &
433 			      byte_mask) == 0)) {
434 				break;
435 			}
436 		}
437 	}
438 
439 	cap_info->cs1_row = row;
440 
441 	return 0;
442 }
443