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