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 14void 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 38void 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 94void 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 123inline void sdram_print_dram_type(unsigned char dramtype) 124{ 125} 126 127inline void sdram_print_ddr_info(struct sdram_cap_info *cap_info, 128 struct sdram_base_params *base, u32 split) 129{ 130} 131 132inline 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 */ 143u64 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 */ 173void 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 184void 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 207int sdram_detect_bw(struct sdram_cap_info *cap_info) 208{ 209 return 0; 210} 211 212int sdram_detect_cs(struct sdram_cap_info *cap_info) 213{ 214 return 0; 215} 216 217int 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 243int 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 */ 266int 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 */ 289int 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 334int 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 360int 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 384int 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 392int 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