xref: /OK3568_Linux_fs/u-boot/drivers/ram/rockchip/sdram_common.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
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/sdram.h>
11 #include <asm/arch/sdram_common.h>
12 
sdram_print_dram_type(unsigned char dramtype)13 void sdram_print_dram_type(unsigned char dramtype)
14 {
15 	switch (dramtype) {
16 	case DDR3:
17 		printascii("DDR3");
18 		break;
19 	case DDR4:
20 		printascii("DDR4");
21 		break;
22 	case LPDDR2:
23 		printascii("LPDDR2");
24 		break;
25 	case LPDDR3:
26 		printascii("LPDDR3");
27 		break;
28 	case LPDDR4:
29 		printascii("LPDDR4");
30 		break;
31 	case LPDDR4X:
32 		printascii("LPDDR4X");
33 		break;
34 	default:
35 		printascii("Unknown Device");
36 		break;
37 	}
38 }
39 
sdram_print_ddr_info(struct sdram_cap_info * cap_info,struct sdram_base_params * base,u32 split)40 void sdram_print_ddr_info(struct sdram_cap_info *cap_info,
41 			  struct sdram_base_params *base, u32 split)
42 {
43 	u64 cap;
44 	u32 bg;
45 
46 	bg = (cap_info->dbw == 0) ? 2 : 1;
47 
48 	sdram_print_dram_type(base->dramtype);
49 
50 	printascii(", ");
51 	printdec(base->ddr_freq);
52 	printascii("MHz\n");
53 
54 	printascii("BW=");
55 	printdec(8 << cap_info->bw);
56 	printascii(" Col=");
57 	printdec(cap_info->col);
58 	printascii(" Bk=");
59 	printdec(0x1 << cap_info->bk);
60 	if (base->dramtype == DDR4) {
61 		printascii(" BG=");
62 		printdec(1 << bg);
63 	}
64 	printascii(" CS0 Row=");
65 	printdec(cap_info->cs0_row);
66 	if (cap_info->cs0_high16bit_row !=
67 		cap_info->cs0_row) {
68 		printascii("/");
69 		printdec(cap_info->cs0_high16bit_row);
70 	}
71 	if (cap_info->rank > 1) {
72 		printascii(" CS1 Row=");
73 		printdec(cap_info->cs1_row);
74 		if (cap_info->cs1_high16bit_row !=
75 			cap_info->cs1_row) {
76 			printascii("/");
77 			printdec(cap_info->cs1_high16bit_row);
78 		}
79 	}
80 	if (cap_info->rank > 2) {
81 		printascii(" CS2 Row=");
82 		printdec(cap_info->cs2_row);
83 		if (cap_info->cs2_high16bit_row !=
84 			cap_info->cs2_row) {
85 			printascii("/");
86 			printdec(cap_info->cs2_high16bit_row);
87 		}
88 		printascii(" CS3 Row=");
89 		printdec(cap_info->cs3_row);
90 		if (cap_info->cs3_high16bit_row !=
91 			cap_info->cs3_row) {
92 			printascii("/");
93 			printdec(cap_info->cs3_high16bit_row);
94 		}
95 	}
96 	printascii(" CS=");
97 	printdec(cap_info->rank);
98 	printascii(" Die BW=");
99 	printdec(8 << cap_info->dbw);
100 
101 	cap = sdram_get_cs_cap(cap_info, 3, base->dramtype);
102 	if (cap_info->row_3_4)
103 		cap = cap * 3 / 4;
104 	else if (split)
105 		cap = cap / 2 + (split << 24) / 2;
106 
107 	printascii(" Size=");
108 	printdec(cap >> 20);
109 	printascii("MB\n");
110 }
111 
112 /*
113  * cs: 0:cs0
114  *	   1:cs1
115  *     else cs0+cs1
116  * note: it didn't consider about row_3_4
117  */
sdram_get_cs_cap(struct sdram_cap_info * cap_info,u32 cs,u32 dram_type)118 u64 sdram_get_cs_cap(struct sdram_cap_info *cap_info, u32 cs, u32 dram_type)
119 {
120 	u32 bg;
121 	u64 cap[4];
122 
123 	if (dram_type == DDR4)
124 		/* DDR4 8bit dram BG = 2(4bank groups),
125 		 * 16bit dram BG = 1 (2 bank groups)
126 		 */
127 		bg = (cap_info->dbw == 0) ? 2 : 1;
128 	else
129 		bg = 0;
130 	cap[0] = 1llu << (cap_info->bw + cap_info->col +
131 		bg + cap_info->bk + cap_info->cs0_row);
132 
133 	if (cap_info->rank >= 2)
134 		cap[1] = 1llu << (cap_info->bw + cap_info->col +
135 			bg + cap_info->bk + cap_info->cs1_row);
136 	else
137 		cap[1] = 0;
138 
139 	if (cap_info->rank == 4) {
140 		cap[2] = 1llu << (cap_info->bw + cap_info->col +
141 			bg + cap_info->bk + cap_info->cs2_row);
142 		cap[3] = 1llu << (cap_info->bw + cap_info->col +
143 			bg + cap_info->bk + cap_info->cs3_row);
144 	} else {
145 		cap[2] = 0;
146 		cap[3] = 0;
147 	}
148 	if (cs == 0)
149 		return cap[0];
150 	else if (cs == 1)
151 		return cap[1];
152 	else
153 		return (cap[0] + cap[1] + cap[2] + cap[3]);
154 }
155 
156 /* n: Unit bytes */
sdram_copy_to_reg(u32 * dest,const u32 * src,u32 n)157 void sdram_copy_to_reg(u32 *dest, const u32 *src, u32 n)
158 {
159 	int i;
160 
161 	for (i = 0; i < n / sizeof(u32); i++) {
162 		writel(*src, dest);
163 		src++;
164 		dest++;
165 	}
166 }
167 
sdram_org_config(struct sdram_cap_info * cap_info,struct sdram_base_params * base,u32 * p_os_reg2,u32 * p_os_reg3,u32 channel)168 void sdram_org_config(struct sdram_cap_info *cap_info,
169 		      struct sdram_base_params *base,
170 		      u32 *p_os_reg2, u32 *p_os_reg3, u32 channel)
171 {
172 	*p_os_reg2 |= SYS_REG_ENC_DDRTYPE(base->dramtype);
173 	*p_os_reg2 |= SYS_REG_ENC_NUM_CH(base->num_channels);
174 
175 	*p_os_reg2 |= SYS_REG_ENC_ROW_3_4(cap_info->row_3_4, channel);
176 	*p_os_reg2 |= SYS_REG_ENC_CHINFO(channel);
177 	*p_os_reg2 |= SYS_REG_ENC_RANK(cap_info->rank, channel);
178 	*p_os_reg2 |= SYS_REG_ENC_COL(cap_info->col, channel);
179 	*p_os_reg2 |= SYS_REG_ENC_BK(cap_info->bk, channel);
180 	*p_os_reg2 |= SYS_REG_ENC_BW(cap_info->bw, channel);
181 	*p_os_reg2 |= SYS_REG_ENC_DBW(cap_info->dbw, channel);
182 
183 	SYS_REG_ENC_CS0_ROW(cap_info->cs0_row, *p_os_reg2, *p_os_reg3, channel);
184 	if (cap_info->cs1_row)
185 		SYS_REG_ENC_CS1_ROW(cap_info->cs1_row, *p_os_reg2,
186 				    *p_os_reg3, channel);
187 	*p_os_reg3 |= SYS_REG_ENC_CS1_COL(cap_info->col, channel);
188 	*p_os_reg3 |= SYS_REG_ENC_VERSION(DDR_SYS_REG_VERSION);
189 }
190 
sdram_org_config_v3(struct sdram_cap_info * cap_info,struct sdram_base_params * base,u32 * p_os_reg2,u32 * p_os_reg3,u32 channel)191 void sdram_org_config_v3(struct sdram_cap_info *cap_info,
192 			 struct sdram_base_params *base,
193 			 u32 *p_os_reg2, u32 *p_os_reg3, u32 channel)
194 {
195 	SYS_REG_ENC_DDRTYPE_V3(base->dramtype, *p_os_reg2, *p_os_reg3);
196 
197 	*p_os_reg2 |= SYS_REG_ENC_NUM_CH_V3((base->num_channels > 2) ?
198 					    2 : base->num_channels);
199 
200 	*p_os_reg2 |= SYS_REG_ENC_ROW_3_4_V3(cap_info->row_3_4, channel);
201 	*p_os_reg2 |= SYS_REG_ENC_CHINFO_V3((channel >= 2) ? channel - 2 : channel);
202 	if (channel == 0 || channel == 2)
203 		SYS_REG_ENC_CH0_2_RANK_V3(cap_info->rank,
204 					  *p_os_reg2, *p_os_reg3);
205 	else
206 		*p_os_reg2 |= SYS_REG_ENC_CH1_3_RANK(cap_info->rank);
207 
208 	*p_os_reg2 |= SYS_REG_ENC_COL_V3(cap_info->col, channel);
209 	*p_os_reg2 |= SYS_REG_ENC_BK_V3(cap_info->bk, channel);
210 	*p_os_reg2 |= SYS_REG_ENC_BW_V3(cap_info->bw, channel);
211 	*p_os_reg2 |= SYS_REG_ENC_DBW_V3(cap_info->dbw, channel);
212 
213 	SYS_REG_ENC_CS0_ROW_V3(cap_info->cs0_row, *p_os_reg2, *p_os_reg3, channel);
214 	if (cap_info->cs1_row)
215 		SYS_REG_ENC_CS1_ROW_V3(cap_info->cs1_row, *p_os_reg2,
216 				       *p_os_reg3, channel);
217 	if ((channel == 0 || channel == 2) && cap_info->rank > 2) {
218 		if (cap_info->cs2_row == cap_info->cs0_row)
219 			*p_os_reg3 |= SYS_REG_ENC_CS2_DELTA_ROW_V3(0);
220 		else
221 			*p_os_reg3 |= SYS_REG_ENC_CS2_DELTA_ROW_V3(1);
222 
223 		if (cap_info->cs3_row == cap_info->cs0_row)
224 			*p_os_reg3 |= SYS_REG_ENC_CS3_DELTA_ROW_V3(0);
225 		else
226 			*p_os_reg3 |= SYS_REG_ENC_CS3_DELTA_ROW_V3(1);
227 	}
228 
229 	*p_os_reg3 |= SYS_REG_ENC_CS1_COL_V3(cap_info->col, channel);
230 	*p_os_reg3 |= SYS_REG_ENC_VERSION(DDR_SYS_REG_VERSION_3);
231 }
232 
sdram_detect_bw(struct sdram_cap_info * cap_info)233 int sdram_detect_bw(struct sdram_cap_info *cap_info)
234 {
235 	return 0;
236 }
237 
sdram_detect_cs(struct sdram_cap_info * cap_info)238 int sdram_detect_cs(struct sdram_cap_info *cap_info)
239 {
240 	return 0;
241 }
242 
sdram_detect_col(struct sdram_cap_info * cap_info,u32 coltmp)243 int sdram_detect_col(struct sdram_cap_info *cap_info,
244 		     u32 coltmp)
245 {
246 	void __iomem *test_addr;
247 	u32 col;
248 	u32 bw = cap_info->bw;
249 
250 	for (col = coltmp; col >= 9; col -= 1) {
251 		writel(0, CONFIG_SYS_SDRAM_BASE);
252 		test_addr = (void __iomem *)(CONFIG_SYS_SDRAM_BASE +
253 				(1ul << (col + bw - 1ul)));
254 		writel(PATTERN, test_addr);
255 		if ((readl(test_addr) == PATTERN) &&
256 		    (readl(CONFIG_SYS_SDRAM_BASE) == 0))
257 			break;
258 	}
259 	if (col == 8) {
260 		printascii("col error\n");
261 		return -1;
262 	}
263 
264 	cap_info->col = col;
265 
266 	return 0;
267 }
268 
sdram_detect_bank(struct sdram_cap_info * cap_info,u32 coltmp,u32 bktmp)269 int sdram_detect_bank(struct sdram_cap_info *cap_info,
270 		      u32 coltmp, u32 bktmp)
271 {
272 	void __iomem *test_addr;
273 	u32 bk;
274 	u32 bw = cap_info->bw;
275 
276 	test_addr = (void __iomem *)(CONFIG_SYS_SDRAM_BASE +
277 			(1ul << (coltmp + bktmp + bw - 1ul)));
278 	writel(0, CONFIG_SYS_SDRAM_BASE);
279 	writel(PATTERN, test_addr);
280 	if ((readl(test_addr) == PATTERN) &&
281 	    (readl(CONFIG_SYS_SDRAM_BASE) == 0))
282 		bk = 3;
283 	else
284 		bk = 2;
285 
286 	cap_info->bk = bk;
287 
288 	return 0;
289 }
290 
291 /* detect bg for ddr4 */
sdram_detect_bg(struct sdram_cap_info * cap_info,u32 coltmp)292 int sdram_detect_bg(struct sdram_cap_info *cap_info,
293 		    u32 coltmp)
294 {
295 	void __iomem *test_addr;
296 	u32 dbw;
297 	u32 bw = cap_info->bw;
298 
299 	test_addr = (void __iomem *)(CONFIG_SYS_SDRAM_BASE +
300 			(1ul << (coltmp + bw + 1ul)));
301 	writel(0, CONFIG_SYS_SDRAM_BASE);
302 	writel(PATTERN, test_addr);
303 	if ((readl(test_addr) == PATTERN) &&
304 	    (readl(CONFIG_SYS_SDRAM_BASE) == 0))
305 		dbw = 0;
306 	else
307 		dbw = 1;
308 
309 	cap_info->dbw = dbw;
310 
311 	return 0;
312 }
313 
314 /* detect dbw for ddr3,lpddr2,lpddr3,lpddr4 */
sdram_detect_dbw(struct sdram_cap_info * cap_info,u32 dram_type)315 int sdram_detect_dbw(struct sdram_cap_info *cap_info, u32 dram_type)
316 {
317 	u32 row, col, bk, bw, cs_cap, cs;
318 	u32 die_bw_0 = 0, die_bw_1 = 0;
319 
320 	if (dram_type == DDR3) {
321 		if (cap_info->bw == 0)
322 			cap_info->dbw = 0;
323 		else
324 			cap_info->dbw = 1;
325 	} else if (dram_type == LPDDR4) {
326 		cap_info->dbw = 1;
327 	} else if (dram_type == LPDDR3 || dram_type == LPDDR2) {
328 		row = cap_info->cs0_row;
329 		col = cap_info->col;
330 		bk = cap_info->bk;
331 		cs = cap_info->rank;
332 		bw = cap_info->bw;
333 		cs_cap = (1 << (row + col + bk + bw - 20));
334 		if (bw == 2) {
335 			if (cs_cap <= 0x20) /* 256Mb */
336 				die_bw_0 = (col < 9) ? 2 : 1;
337 			else if (cs_cap <= 0x100) /* 2Gb */
338 				die_bw_0 = (col < 10) ? 2 : 1;
339 			else if (cs_cap <= 0x400) /* 8Gb */
340 				die_bw_0 = (col < 11) ? 2 : 1;
341 			else
342 				die_bw_0 = (col < 12) ? 2 : 1;
343 			if (cs > 1) {
344 				row = cap_info->cs1_row;
345 				cs_cap = (1 << (row + col + bk + bw - 20));
346 				if (cs_cap <= 0x20) /* 256Mb */
347 					die_bw_0 = (col < 9) ? 2 : 1;
348 				else if (cs_cap <= 0x100) /* 2Gb */
349 					die_bw_0 = (col < 10) ? 2 : 1;
350 				else if (cs_cap <= 0x400) /* 8Gb */
351 					die_bw_0 = (col < 11) ? 2 : 1;
352 				else
353 					die_bw_0 = (col < 12) ? 2 : 1;
354 			}
355 		} else {
356 			die_bw_1 = 1;
357 			die_bw_0 = 1;
358 		}
359 		cap_info->dbw = (die_bw_0 > die_bw_1) ? die_bw_0 : die_bw_1;
360 	}
361 
362 	return 0;
363 }
364 
sdram_detect_row(struct sdram_cap_info * cap_info,u32 coltmp,u32 bktmp,u32 rowtmp)365 int sdram_detect_row(struct sdram_cap_info *cap_info,
366 		     u32 coltmp, u32 bktmp, u32 rowtmp)
367 {
368 	u32 row;
369 	u32 bw = cap_info->bw;
370 	void __iomem *test_addr;
371 
372 	for (row = rowtmp; row > 12; row--) {
373 		writel(0, CONFIG_SYS_SDRAM_BASE);
374 		test_addr = (void __iomem *)(CONFIG_SYS_SDRAM_BASE +
375 				(1ul << (row + bktmp + coltmp + bw - 1ul)));
376 		writel(PATTERN, test_addr);
377 		if ((readl(test_addr) == PATTERN) &&
378 		    (readl(CONFIG_SYS_SDRAM_BASE) == 0))
379 			break;
380 	}
381 	if (row == 12) {
382 		printascii("row error");
383 		return -1;
384 	}
385 
386 	cap_info->cs0_row = row;
387 
388 	return 0;
389 }
390 
sdram_detect_row_3_4(struct sdram_cap_info * cap_info,u32 coltmp,u32 bktmp)391 int sdram_detect_row_3_4(struct sdram_cap_info *cap_info,
392 			 u32 coltmp, u32 bktmp)
393 {
394 	u32 row_3_4;
395 	u32 bw = cap_info->bw;
396 	u32 row = cap_info->cs0_row;
397 	void __iomem *test_addr, *test_addr1;
398 
399 	test_addr = CONFIG_SYS_SDRAM_BASE;
400 	test_addr1 = (void __iomem *)(CONFIG_SYS_SDRAM_BASE +
401 			(0x3ul << (row + bktmp + coltmp + bw - 1ul - 1ul)));
402 
403 	writel(0, test_addr);
404 	writel(PATTERN, test_addr1);
405 	if ((readl(test_addr) == 0) && (readl(test_addr1) == PATTERN))
406 		row_3_4 = 0;
407 	else
408 		row_3_4 = 1;
409 
410 	cap_info->row_3_4 = row_3_4;
411 
412 	return 0;
413 }
414 
sdram_detect_high_row(struct sdram_cap_info * cap_info,u32 dramtype)415 int sdram_detect_high_row(struct sdram_cap_info *cap_info, u32 dramtype)
416 {
417 	unsigned long base_addr;
418 	u32 cs0_high_row, cs1_high_row, cs;
419 	u64 cap = 0, cs0_cap = 0;
420 	u32 i;
421 	void __iomem *test_addr, *test_addr1;
422 #ifdef CONFIG_ROCKCHIP_RK3568
423 	u32 cs2_high_row, cs3_high_row;
424 #endif
425 
426 	cs = cap_info->rank;
427 	/* 8bit bandwidth no enable axi split*/
428 	if (!cap_info->bw) {
429 		cs0_high_row = cap_info->cs0_row;
430 		cs1_high_row = cap_info->cs1_row;
431 	#ifdef CONFIG_ROCKCHIP_RK3568
432 		if (cs > 2) {
433 			cs2_high_row = cap_info->cs2_row;
434 			cs3_high_row = cap_info->cs3_row;
435 		}
436 	#endif
437 		goto out;
438 	}
439 #ifdef CONFIG_ROCKCHIP_RK3568
440 	if (cs > 2) {
441 		cs0_high_row = cap_info->cs0_row;
442 		cs1_high_row = cap_info->cs1_row;
443 		cs2_high_row = cap_info->cs2_row;
444 		cs3_high_row = cap_info->cs3_row;
445 
446 		goto out;
447 	}
448 #endif
449 
450 	cs0_cap = sdram_get_cs_cap(cap_info, 0, dramtype);
451 	if (cs == 2) {
452 		base_addr = CONFIG_SYS_SDRAM_BASE + cs0_cap;
453 		cap = sdram_get_cs_cap(cap_info, 1, dramtype);
454 	} else {
455 		base_addr = CONFIG_SYS_SDRAM_BASE;
456 		cap = cs0_cap;
457 	}
458 	/* detect full bandwidth size */
459 	for (i = 0; i < 4; i++) {
460 		test_addr = (void __iomem *)base_addr;
461 		test_addr1 = (void __iomem *)(base_addr +
462 			     (unsigned long)(cap / (1ul << (i + 1))));
463 		writel(0x0, test_addr);
464 		writel(PATTERN, test_addr1);
465 		if ((readl(test_addr) == 0x0) &&
466 		    (readl(test_addr1) == PATTERN))
467 			break;
468 	}
469 	if (i == 4 && cs == 1) {
470 		printascii("can't support this cap\n");
471 		return -1;
472 	}
473 
474 	if (cs == 2) {
475 		cs0_high_row = cap_info->cs0_row;
476 		if (i == 4)
477 			cs1_high_row = 0;
478 		else
479 			cs1_high_row = cap_info->cs1_row - i;
480 	} else {
481 		cs0_high_row = cap_info->cs0_row - i;
482 		cs1_high_row = 0;
483 	}
484 
485 out:
486 	cap_info->cs0_high16bit_row = cs0_high_row;
487 	cap_info->cs1_high16bit_row = cs1_high_row;
488 #ifdef CONFIG_ROCKCHIP_RK3568
489 	if (cs > 2) {
490 		cap_info->cs2_high16bit_row = cs2_high_row;
491 		cap_info->cs3_high16bit_row = cs3_high_row;
492 	}
493 #endif
494 
495 	return 0;
496 }
497 
sdram_detect_cs1_row(struct sdram_cap_info * cap_info,u32 dram_type)498 int sdram_detect_cs1_row(struct sdram_cap_info *cap_info, u32 dram_type)
499 {
500 	void __iomem *test_addr;
501 	u32 row = 0, bktmp, coltmp, bw;
502 	ulong cs0_cap;
503 	u32 byte_mask;
504 
505 	if (cap_info->rank == 2) {
506 		cs0_cap = sdram_get_cs_cap(cap_info, 0, dram_type);
507 
508 		if (dram_type == DDR4) {
509 			if (cap_info->dbw == 0)
510 				bktmp = cap_info->bk + 2;
511 			else
512 				bktmp = cap_info->bk + 1;
513 		} else {
514 			bktmp = cap_info->bk;
515 		}
516 		bw = cap_info->bw;
517 		coltmp = cap_info->col;
518 
519 		/*
520 		 * because px30 support axi split,min bandwidth
521 		 * is 8bit. if cs0 is 32bit, cs1 may 32bit or 16bit
522 		 * so we check low 16bit data when detect cs1 row.
523 		 * if cs0 is 16bit/8bit, we check low 8bit data.
524 		 */
525 		if (bw == 2)
526 			byte_mask = 0xFFFF;
527 		else
528 			byte_mask = 0xFF;
529 
530 		/* detect cs1 row */
531 		for (row = cap_info->cs0_row; row > 12; row--) {
532 			test_addr = (void __iomem *)(CONFIG_SYS_SDRAM_BASE +
533 				    cs0_cap +
534 				    (1ul << (row + bktmp + coltmp + bw - 1ul)));
535 			writel(0, CONFIG_SYS_SDRAM_BASE + cs0_cap);
536 			writel(PATTERN, test_addr);
537 
538 			if (((readl(test_addr) & byte_mask) ==
539 			     (PATTERN & byte_mask)) &&
540 			    ((readl(CONFIG_SYS_SDRAM_BASE + cs0_cap) &
541 			      byte_mask) == 0)) {
542 				break;
543 			}
544 		}
545 	}
546 
547 	cap_info->cs1_row = row;
548 
549 	return 0;
550 }
551 
552