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