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