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