uboot/drivers/ram/aspeed/sdram_ast2600.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0
   2/*
   3 * Copyright (C) ASPEED Technology Inc.
   4 */
   5#include <common.h>
   6#include <clk.h>
   7#include <dm.h>
   8#include <errno.h>
   9#include <ram.h>
  10#include <regmap.h>
  11#include <reset.h>
  12#include <asm/io.h>
  13#include <asm/arch/scu_ast2600.h>
  14#include <asm/arch/sdram_ast2600.h>
  15#include <asm/global_data.h>
  16#include <linux/err.h>
  17#include <linux/kernel.h>
  18#include <dt-bindings/clock/ast2600-clock.h>
  19
  20#define DDR_PHY_TBL_CHG_ADDR            0xaeeddeea
  21#define DDR_PHY_TBL_END                 0xaeededed
  22
  23#if defined(CONFIG_ASPEED_DDR4_800)
  24u32 ast2600_sdramphy_config[165] = {
  25        0x1e6e0100,     // start address
  26        0x00000000,     // phyr000
  27        0x0c002062,     // phyr004
  28        0x1a7a0063,     // phyr008
  29        0x5a7a0063,     // phyr00c
  30        0x1a7a0063,     // phyr010
  31        0x1a7a0063,     // phyr014
  32        0x20000000,     // phyr018
  33        0x20000000,     // phyr01c
  34        0x20000000,     // phyr020
  35        0x20000000,     // phyr024
  36        0x00000008,     // phyr028
  37        0x00000000,     // phyr02c
  38        0x00077600,     // phyr030
  39        0x00000000,     // phyr034
  40        0x00000000,     // phyr038
  41        0x20000000,     // phyr03c
  42        0x50506000,     // phyr040
  43        0x50505050,     // phyr044
  44        0x00002f07,     // phyr048
  45        0x00003080,     // phyr04c
  46        0x04000000,     // phyr050
  47        0x00000200,     // phyr054
  48        0x03140201,     // phyr058
  49        0x04800000,     // phyr05c
  50        0x0800044e,     // phyr060
  51        0x00000000,     // phyr064
  52        0x00180008,     // phyr068
  53        0x00e00400,     // phyr06c
  54        0x00140206,     // phyr070
  55        0x1d4c0000,     // phyr074
  56        0x493e0107,     // phyr078
  57        0x08060404,     // phyr07c
  58        0x90000a00,     // phyr080
  59        0x06420618,     // phyr084
  60        0x00001002,     // phyr088
  61        0x05701016,     // phyr08c
  62        0x10000000,     // phyr090
  63        0xaeeddeea,     // change address
  64        0x1e6e019c,     // new address
  65        0x20202020,     // phyr09c
  66        0x20202020,     // phyr0a0
  67        0x00002020,     // phyr0a4
  68        0x00002020,     // phyr0a8
  69        0x00000001,     // phyr0ac
  70        0xaeeddeea,     // change address
  71        0x1e6e01cc,     // new address
  72        0x01010101,     // phyr0cc
  73        0x01010101,     // phyr0d0
  74        0x80808080,     // phyr0d4
  75        0x80808080,     // phyr0d8
  76        0xaeeddeea,     // change address
  77        0x1e6e0288,     // new address
  78        0x80808080,     // phyr188
  79        0x80808080,     // phyr18c
  80        0x80808080,     // phyr190
  81        0x80808080,     // phyr194
  82        0xaeeddeea,     // change address
  83        0x1e6e02f8,     // new address
  84        0x90909090,     // phyr1f8
  85        0x88888888,     // phyr1fc
  86        0xaeeddeea,     // change address
  87        0x1e6e0300,     // new address
  88        0x00000000,     // phyr200
  89        0xaeeddeea,     // change address
  90        0x1e6e0194,     // new address
  91        0x80118260,     // phyr094
  92        0xaeeddeea,     // change address
  93        0x1e6e019c,     // new address
  94        0x20202020,     // phyr09c
  95        0x20202020,     // phyr0a0
  96        0x00002020,     // phyr0a4
  97        0x80000000,     // phyr0a8
  98        0x00000001,     // phyr0ac
  99        0xaeeddeea,     // change address
 100        0x1e6e0318,     // new address
 101        0x09222719,     // phyr218
 102        0x00aa4403,     // phyr21c
 103        0xaeeddeea,     // change address
 104        0x1e6e0198,     // new address
 105        0x08060000,     // phyr098
 106        0xaeeddeea,     // change address
 107        0x1e6e01b0,     // new address
 108        0x00000000,     // phyr0b0
 109        0x00000000,     // phyr0b4
 110        0x00000000,     // phyr0b8
 111        0x00000000,     // phyr0bc
 112        0x00000000,     // phyr0c0
 113        0x00000000,     // phyr0c4
 114        0x000aff2c,     // phyr0c8
 115        0xaeeddeea,     // change address
 116        0x1e6e01dc,     // new address
 117        0x00080000,     // phyr0dc
 118        0x00000000,     // phyr0e0
 119        0xaa55aa55,     // phyr0e4
 120        0x55aa55aa,     // phyr0e8
 121        0xaaaa5555,     // phyr0ec
 122        0x5555aaaa,     // phyr0f0
 123        0xaa55aa55,     // phyr0f4
 124        0x55aa55aa,     // phyr0f8
 125        0xaaaa5555,     // phyr0fc
 126        0x5555aaaa,     // phyr100
 127        0xaa55aa55,     // phyr104
 128        0x55aa55aa,     // phyr108
 129        0xaaaa5555,     // phyr10c
 130        0x5555aaaa,     // phyr110
 131        0xaa55aa55,     // phyr114
 132        0x55aa55aa,     // phyr118
 133        0xaaaa5555,     // phyr11c
 134        0x5555aaaa,     // phyr120
 135        0x20202020,     // phyr124
 136        0x20202020,     // phyr128
 137        0x20202020,     // phyr12c
 138        0x20202020,     // phyr130
 139        0x20202020,     // phyr134
 140        0x20202020,     // phyr138
 141        0x20202020,     // phyr13c
 142        0x20202020,     // phyr140
 143        0x20202020,     // phyr144
 144        0x20202020,     // phyr148
 145        0x20202020,     // phyr14c
 146        0x20202020,     // phyr150
 147        0x20202020,     // phyr154
 148        0x20202020,     // phyr158
 149        0x20202020,     // phyr15c
 150        0x20202020,     // phyr160
 151        0x20202020,     // phyr164
 152        0x20202020,     // phyr168
 153        0x20202020,     // phyr16c
 154        0x20202020,     // phyr170
 155        0xaeeddeea,     // change address
 156        0x1e6e0298,     // new address
 157        0x20200800,     // phyr198
 158        0x20202020,     // phyr19c
 159        0x20202020,     // phyr1a0
 160        0x20202020,     // phyr1a4
 161        0x20202020,     // phyr1a8
 162        0x20202020,     // phyr1ac
 163        0x20202020,     // phyr1b0
 164        0x20202020,     // phyr1b4
 165        0x20202020,     // phyr1b8
 166        0x20202020,     // phyr1bc
 167        0x20202020,     // phyr1c0
 168        0x20202020,     // phyr1c4
 169        0x20202020,     // phyr1c8
 170        0x20202020,     // phyr1cc
 171        0x20202020,     // phyr1d0
 172        0x20202020,     // phyr1d4
 173        0x20202020,     // phyr1d8
 174        0x20202020,     // phyr1dc
 175        0x20202020,     // phyr1e0
 176        0x20202020,     // phyr1e4
 177        0x00002020,     // phyr1e8
 178        0xaeeddeea,     // change address
 179        0x1e6e0304,     // new address
 180        0x00000800,     // phyr204
 181        0xaeeddeea,     // change address
 182        0x1e6e027c,     // new address
 183        0x4e400000,     // phyr17c
 184        0x59595959,     // phyr180
 185        0x40404040,     // phyr184
 186        0xaeeddeea,     // change address
 187        0x1e6e02f4,     // new address
 188        0x00000059,     // phyr1f4
 189        0xaeededed,     // end
 190};
 191#else
 192u32 ast2600_sdramphy_config[165] = {
 193        0x1e6e0100,     // start address
 194        0x00000000,     // phyr000
 195        0x0c002062,     // phyr004
 196        0x1a7a0063,     // phyr008
 197        0x5a7a0063,     // phyr00c
 198        0x1a7a0063,     // phyr010
 199        0x1a7a0063,     // phyr014
 200        0x20000000,     // phyr018
 201        0x20000000,     // phyr01c
 202        0x20000000,     // phyr020
 203        0x20000000,     // phyr024
 204        0x00000008,     // phyr028
 205        0x00000000,     // phyr02c
 206        0x00077600,     // phyr030
 207        0x00000000,     // phyr034
 208        0x00000000,     // phyr038
 209        0x20000000,     // phyr03c
 210        0x50506000,     // phyr040
 211        0x50505050,     // phyr044
 212        0x00002f07,     // phyr048
 213        0x00003080,     // phyr04c
 214        0x04000000,     // phyr050
 215        0x00000200,     // phyr054
 216        0x03140501,     // phyr058-rtt:40
 217        0x04800000,     // phyr05c
 218        0x0800044e,     // phyr060
 219        0x00000000,     // phyr064
 220        0x00180008,     // phyr068
 221        0x00e00400,     // phyr06c
 222        0x00140206,     // phyr070
 223        0x1d4c0000,     // phyr074
 224        0x493e0107,     // phyr078
 225        0x08060404,     // phyr07c
 226        0x90000a00,     // phyr080
 227        0x06420c30,     // phyr084
 228        0x00001002,     // phyr088
 229        0x05701016,     // phyr08c
 230        0x10000000,     // phyr090
 231        0xaeeddeea,     // change address
 232        0x1e6e019c,     // new address
 233        0x20202020,     // phyr09c
 234        0x20202020,     // phyr0a0
 235        0x00002020,     // phyr0a4
 236        0x00002020,     // phyr0a8
 237        0x00000001,     // phyr0ac
 238        0xaeeddeea,     // change address
 239        0x1e6e01cc,     // new address
 240        0x01010101,     // phyr0cc
 241        0x01010101,     // phyr0d0
 242        0x80808080,     // phyr0d4
 243        0x80808080,     // phyr0d8
 244        0xaeeddeea,     // change address
 245        0x1e6e0288,     // new address
 246        0x80808080,     // phyr188
 247        0x80808080,     // phyr18c
 248        0x80808080,     // phyr190
 249        0x80808080,     // phyr194
 250        0xaeeddeea,     // change address
 251        0x1e6e02f8,     // new address
 252        0x90909090,     // phyr1f8
 253        0x88888888,     // phyr1fc
 254        0xaeeddeea,     // change address
 255        0x1e6e0300,     // new address
 256        0x00000000,     // phyr200
 257        0xaeeddeea,     // change address
 258        0x1e6e0194,     // new address
 259        0x801112e0,     // phyr094 - bit12=1,15=0,- write window is ok
 260        0xaeeddeea,     // change address
 261        0x1e6e019c,     // new address
 262        0x20202020,     // phyr09c
 263        0x20202020,     // phyr0a0
 264        0x00002020,     // phyr0a4
 265        0x80000000,     // phyr0a8
 266        0x00000001,     // phyr0ac
 267        0xaeeddeea,     // change address
 268        0x1e6e0318,     // new address
 269        0x09222719,     // phyr218
 270        0x00aa4403,     // phyr21c
 271        0xaeeddeea,     // change address
 272        0x1e6e0198,     // new address
 273        0x08060000,     // phyr098
 274        0xaeeddeea,     // change address
 275        0x1e6e01b0,     // new address
 276        0x00000000,     // phyr0b0
 277        0x00000000,     // phyr0b4
 278        0x00000000,     // phyr0b8
 279        0x00000000,     // phyr0bc
 280        0x00000000,     // phyr0c0 - ori
 281        0x00000000,     // phyr0c4
 282        0x000aff2c,     // phyr0c8
 283        0xaeeddeea,     // change address
 284        0x1e6e01dc,     // new address
 285        0x00080000,     // phyr0dc
 286        0x00000000,     // phyr0e0
 287        0xaa55aa55,     // phyr0e4
 288        0x55aa55aa,     // phyr0e8
 289        0xaaaa5555,     // phyr0ec
 290        0x5555aaaa,     // phyr0f0
 291        0xaa55aa55,     // phyr0f4
 292        0x55aa55aa,     // phyr0f8
 293        0xaaaa5555,     // phyr0fc
 294        0x5555aaaa,     // phyr100
 295        0xaa55aa55,     // phyr104
 296        0x55aa55aa,     // phyr108
 297        0xaaaa5555,     // phyr10c
 298        0x5555aaaa,     // phyr110
 299        0xaa55aa55,     // phyr114
 300        0x55aa55aa,     // phyr118
 301        0xaaaa5555,     // phyr11c
 302        0x5555aaaa,     // phyr120
 303        0x20202020,     // phyr124
 304        0x20202020,     // phyr128
 305        0x20202020,     // phyr12c
 306        0x20202020,     // phyr130
 307        0x20202020,     // phyr134
 308        0x20202020,     // phyr138
 309        0x20202020,     // phyr13c
 310        0x20202020,     // phyr140
 311        0x20202020,     // phyr144
 312        0x20202020,     // phyr148
 313        0x20202020,     // phyr14c
 314        0x20202020,     // phyr150
 315        0x20202020,     // phyr154
 316        0x20202020,     // phyr158
 317        0x20202020,     // phyr15c
 318        0x20202020,     // phyr160
 319        0x20202020,     // phyr164
 320        0x20202020,     // phyr168
 321        0x20202020,     // phyr16c
 322        0x20202020,     // phyr170
 323        0xaeeddeea,     // change address
 324        0x1e6e0298,     // new address
 325        0x20200800,     // phyr198
 326        0x20202020,     // phyr19c
 327        0x20202020,     // phyr1a0
 328        0x20202020,     // phyr1a4
 329        0x20202020,     // phyr1a8
 330        0x20202020,     // phyr1ac
 331        0x20202020,     // phyr1b0
 332        0x20202020,     // phyr1b4
 333        0x20202020,     // phyr1b8
 334        0x20202020,     // phyr1bc
 335        0x20202020,     // phyr1c0
 336        0x20202020,     // phyr1c4
 337        0x20202020,     // phyr1c8
 338        0x20202020,     // phyr1cc
 339        0x20202020,     // phyr1d0
 340        0x20202020,     // phyr1d4
 341        0x20202020,     // phyr1d8
 342        0x20202020,     // phyr1dc
 343        0x20202020,     // phyr1e0
 344        0x20202020,     // phyr1e4
 345        0x00002020,     // phyr1e8
 346        0xaeeddeea,     // change address
 347        0x1e6e0304,     // new address
 348        0x00000800,     // phyr204
 349        0xaeeddeea,     // change address
 350        0x1e6e027c,     // new address
 351        0x4e400000,     // phyr17c
 352        0x59595959,     // phyr180
 353        0x40404040,     // phyr184
 354        0xaeeddeea,     // change address
 355        0x1e6e02f4,     // new address
 356        0x00000059,     // phyr1f4
 357        0xaeededed,     // end
 358};
 359#endif
 360
 361/* MPLL configuration */
 362#define SCU_MPLL_FREQ_400M      0x0008405F
 363#define SCU_MPLL_EXT_400M       0x0000002F
 364#define SCU_MPLL_FREQ_333M      0x00488299
 365#define SCU_MPLL_EXT_333M       0x0000014C
 366#define SCU_MPLL_FREQ_200M      0x0078007F
 367#define SCU_MPLL_EXT_200M       0x0000003F
 368#define SCU_MPLL_FREQ_100M      0x0078003F
 369#define SCU_MPLL_EXT_100M       0x0000001F
 370
 371#if defined(CONFIG_ASPEED_DDR4_1600)
 372#define SCU_MPLL_FREQ_CFG       SCU_MPLL_FREQ_400M
 373#define SCU_MPLL_EXT_CFG        SCU_MPLL_EXT_400M
 374#elif defined(CONFIG_ASPEED_DDR4_1333)
 375#define SCU_MPLL_FREQ_CFG       SCU_MPLL_FREQ_333M
 376#define SCU_MPLL_EXT_CFG        SCU_MPLL_EXT_333M
 377#elif defined(CONFIG_ASPEED_DDR4_800)
 378#define SCU_MPLL_FREQ_CFG       SCU_MPLL_FREQ_200M
 379#define SCU_MPLL_EXT_CFG        SCU_MPLL_EXT_200M
 380#elif defined(CONFIG_ASPEED_DDR4_400)
 381#define SCU_MPLL_FREQ_CFG       SCU_MPLL_FREQ_100M
 382#define SCU_MPLL_EXT_CFG        SCU_MPLL_EXT_100M
 383#else
 384#error "undefined DDR4 target rate\n"
 385#endif
 386
 387/*
 388 * AC timing and SDRAM mode register setting
 389 * for real chip are derived from the model GDDR4-1600
 390 */
 391#define DDR4_MR01_MODE  0x03010510
 392#define DDR4_MR23_MODE  0x00000000
 393#define DDR4_MR45_MODE  0x04000000
 394#define DDR4_MR6_MODE   0x00000400
 395#define DDR4_TRFC_1600  0x467299f1
 396#define DDR4_TRFC_1333  0x3a5f80c9
 397#define DDR4_TRFC_800   0x23394c78
 398#define DDR4_TRFC_400   0x111c263c
 399
 400#if defined(CONFIG_ASPEED_DDR4_1600)
 401#define DDR4_TRFC               DDR4_TRFC_1600
 402#define DDR4_PHY_TRAIN_TRFC     0xc30
 403#elif defined(CONFIG_ASPEED_DDR4_1333)
 404#define DDR4_TRFC               DDR4_TRFC_1333
 405#define DDR4_PHY_TRAIN_TRFC     0xa25
 406#elif defined(CONFIG_ASPEED_DDR4_800)
 407#define DDR4_TRFC               DDR4_TRFC_800
 408#define DDR4_PHY_TRAIN_TRFC     0x618
 409#elif defined(CONFIG_ASPEED_DDR4_400)
 410#define DDR4_TRFC               DDR4_TRFC_400
 411#define DDR4_PHY_TRAIN_TRFC     0x30c
 412#else
 413#error "undefined tRFC setting"
 414#endif
 415
 416/* supported SDRAM size */
 417#define SDRAM_SIZE_1KB          (1024U)
 418#define SDRAM_SIZE_1MB          (SDRAM_SIZE_1KB * SDRAM_SIZE_1KB)
 419#define SDRAM_MIN_SIZE          (256 * SDRAM_SIZE_1MB)
 420#define SDRAM_MAX_SIZE          (2048 * SDRAM_SIZE_1MB)
 421
 422DECLARE_GLOBAL_DATA_PTR;
 423
 424static const u32 ddr4_ac_timing[4] = {
 425        0x040e0307, 0x0f4711f1, 0x0e060304, 0x00001240 };
 426static const u32 ddr_max_grant_params[4] = {
 427        0x44444444, 0x44444444, 0x44444444, 0x44444444 };
 428
 429struct dram_info {
 430        struct ram_info info;
 431        struct clk ddr_clk;
 432        struct ast2600_sdrammc_regs *regs;
 433        struct ast2600_scu *scu;
 434        struct ast2600_ddr_phy *phy;
 435        void __iomem *phy_setting;
 436        void __iomem *phy_status;
 437        ulong clock_rate;
 438};
 439
 440static void ast2600_sdramphy_kick_training(struct dram_info *info)
 441{
 442        u32 data;
 443        struct ast2600_sdrammc_regs *regs = info->regs;
 444
 445        writel(SDRAM_PHYCTRL0_NRST, &regs->phy_ctrl[0]);
 446        udelay(5);
 447        writel(SDRAM_PHYCTRL0_NRST | SDRAM_PHYCTRL0_INIT, &regs->phy_ctrl[0]);
 448        udelay(1000);
 449
 450        while (1) {
 451                data = readl(&regs->phy_ctrl[0]) & SDRAM_PHYCTRL0_INIT;
 452                if (~data)
 453                        break;
 454        }
 455}
 456
 457/**
 458 * @brief       load DDR-PHY configurations table to the PHY registers
 459 * @param[in]   p_tbl - pointer to the configuration table
 460 * @param[in]   info - pointer to the DRAM info struct
 461 *
 462 * There are two sets of MRS (Mode Registers) configuration in ast2600 memory
 463 * system: one is in the SDRAM MC (memory controller) which is used in run
 464 * time, and the other is in the DDR-PHY IP which is used during DDR-PHY
 465 * training.
 466 */
 467static void ast2600_sdramphy_init(u32 *p_tbl, struct dram_info *info)
 468{
 469        u32 reg_base = (u32)info->phy_setting;
 470        u32 addr = p_tbl[0];
 471        u32 data;
 472        int i = 1;
 473
 474        writel(0, &info->regs->phy_ctrl[0]);
 475        udelay(10);
 476
 477        while (1) {
 478                if (addr < reg_base) {
 479                        debug("invalid DDR-PHY addr: 0x%08x\n", addr);
 480                        break;
 481                }
 482                data = p_tbl[i++];
 483
 484                if (data == DDR_PHY_TBL_END) {
 485                        break;
 486                } else if (data == DDR_PHY_TBL_CHG_ADDR) {
 487                        addr = p_tbl[i++];
 488                } else {
 489                        writel(data, addr);
 490                        addr += 4;
 491                }
 492        }
 493
 494        data = readl(info->phy_setting + 0x84) & ~GENMASK(16, 0);
 495        data |= DDR4_PHY_TRAIN_TRFC;
 496        writel(data, info->phy_setting + 0x84);
 497}
 498
 499static int ast2600_sdramphy_check_status(struct dram_info *info)
 500{
 501        u32 value, tmp;
 502        u32 reg_base = (u32)info->phy_status;
 503        int need_retrain = 0;
 504
 505        debug("\nSDRAM PHY training report:\n");
 506
 507        /* training status */
 508        value = readl(reg_base + 0x00);
 509        debug("rO_DDRPHY_reg offset 0x00 = 0x%08x\n", value);
 510
 511        if (value & BIT(3))
 512                debug("\tinitial PVT calibration fail\n");
 513
 514        if (value & BIT(5))
 515                debug("\truntime calibration fail\n");
 516
 517        /* PU & PD */
 518        value = readl(reg_base + 0x30);
 519        debug("rO_DDRPHY_reg offset 0x30 = 0x%08x\n", value);
 520        debug("  PU = 0x%02x\n", value & 0xff);
 521        debug("  PD = 0x%02x\n", (value >> 16) & 0xff);
 522
 523        /* read eye window */
 524        value = readl(reg_base + 0x68);
 525        if (0 == (value & GENMASK(7, 0)))
 526                need_retrain = 1;
 527
 528        debug("rO_DDRPHY_reg offset 0x68 = 0x%08x\n", value);
 529        debug("  rising edge of read data eye training pass window\n");
 530        tmp = (((value & GENMASK(7, 0)) >> 0) * 100) / 255;
 531        debug("    B0:%d%%\n", tmp);
 532        tmp = (((value & GENMASK(15, 8)) >> 8) * 100) / 255;
 533        debug("    B1:%d%%\n", tmp);
 534
 535        value = readl(reg_base + 0xC8);
 536        debug("rO_DDRPHY_reg offset 0xC8 = 0x%08x\n", value);
 537        debug("  falling edge of read data eye training pass window\n");
 538        tmp = (((value & GENMASK(7, 0)) >> 0) * 100) / 255;
 539        debug("    B0:%d%%\n", tmp);
 540        tmp = (((value & GENMASK(15, 8)) >> 8) * 100) / 255;
 541        debug("    B1:%d%%\n", tmp);
 542
 543        /* write eye window */
 544        value = readl(reg_base + 0x7c);
 545        if (0 == (value & GENMASK(7, 0)))
 546                need_retrain = 1;
 547
 548        debug("rO_DDRPHY_reg offset 0x7C = 0x%08x\n", value);
 549        debug("  rising edge of write data eye training pass window\n");
 550        tmp = (((value & GENMASK(7, 0)) >> 0) * 100) / 255;
 551        debug("    B0:%d%%\n", tmp);
 552        tmp = (((value & GENMASK(15, 8)) >> 8) * 100) / 255;
 553        debug("    B1:%d%%\n", tmp);
 554
 555        /* read Vref training result */
 556        value = readl(reg_base + 0x88);
 557        debug("rO_DDRPHY_reg offset 0x88 = 0x%08x\n", value);
 558        debug("  read Vref training result\n");
 559        tmp = (((value & GENMASK(7, 0)) >> 0) * 100) / 127;
 560        debug("    B0:%d%%\n", tmp);
 561        tmp = (((value & GENMASK(15, 8)) >> 8) * 100) / 127;
 562        debug("    B1:%d%%\n", tmp);
 563
 564        /* write Vref training result */
 565        value = readl(reg_base + 0x90);
 566        debug("rO_DDRPHY_reg offset 0x90 = 0x%08x\n", value);
 567
 568        /* gate train */
 569        value = readl(reg_base + 0x50);
 570        if ((0 == (value & GENMASK(15, 0))) ||
 571            (0 == (value & GENMASK(31, 16)))) {
 572                need_retrain = 1;
 573        }
 574
 575        debug("rO_DDRPHY_reg offset 0x50 = 0x%08x\n", value);
 576
 577        return need_retrain;
 578}
 579
 580#ifndef CONFIG_ASPEED_BYPASS_SELFTEST
 581#define MC_TEST_PATTERN_N 8
 582static u32 as2600_sdrammc_test_pattern[MC_TEST_PATTERN_N] = {
 583        0xcc33cc33, 0xff00ff00, 0xaa55aa55, 0x88778877,
 584        0x92cc4d6e, 0x543d3cde, 0xf1e843c7, 0x7c61d253 };
 585
 586#define TIMEOUT_DRAM    5000000
 587int ast2600_sdrammc_dg_test(struct dram_info *info, unsigned int datagen, u32 mode)
 588{
 589        unsigned int data;
 590        unsigned int timeout = 0;
 591        struct ast2600_sdrammc_regs *regs = info->regs;
 592
 593        writel(0, &regs->ecc_test_ctrl);
 594
 595        if (mode == 0)
 596                writel(0x00000085 | (datagen << 3), &regs->ecc_test_ctrl);
 597        else
 598                writel(0x000000C1 | (datagen << 3), &regs->ecc_test_ctrl);
 599
 600        do {
 601                data = readl(&regs->ecc_test_ctrl) & GENMASK(13, 12);
 602
 603                if (data & BIT(13))
 604                        return 0;
 605
 606                if (++timeout > TIMEOUT_DRAM) {
 607                        debug("Timeout!!\n");
 608                        writel(0, &regs->ecc_test_ctrl);
 609                        return -1;
 610                }
 611        } while (!data);
 612
 613        writel(0, &regs->ecc_test_ctrl);
 614
 615        return 0;
 616}
 617
 618int ast2600_sdrammc_cbr_test(struct dram_info *info)
 619{
 620        u32 i;
 621        struct ast2600_sdrammc_regs *regs = info->regs;
 622
 623        clrsetbits_le32(&regs->test_addr, GENMASK(30, 4), 0x7ffff0);
 624
 625        /* single */
 626        for (i = 0; i < 8; i++)
 627                if (ast2600_sdrammc_dg_test(info, i, 0))
 628                        return -1;
 629
 630        /* burst */
 631        for (i = 0; i < 8; i++)
 632                if (ast2600_sdrammc_dg_test(info, i, i))
 633                        return -1;
 634
 635        return 0;
 636}
 637
 638static int ast2600_sdrammc_test(struct dram_info *info)
 639{
 640        struct ast2600_sdrammc_regs *regs = info->regs;
 641
 642        u32 pass_cnt = 0;
 643        u32 fail_cnt = 0;
 644        u32 target_cnt = 2;
 645        u32 test_cnt = 0;
 646        u32 pattern;
 647        u32 i = 0;
 648        bool finish = false;
 649
 650        debug("sdram mc test:\n");
 651        while (!finish) {
 652                pattern = as2600_sdrammc_test_pattern[i++];
 653                i = i % MC_TEST_PATTERN_N;
 654                debug("  pattern = %08X : ", pattern);
 655                writel(pattern, &regs->test_init_val);
 656
 657                if (ast2600_sdrammc_cbr_test(info)) {
 658                        debug("fail\n");
 659                        fail_cnt++;
 660                } else {
 661                        debug("pass\n");
 662                        pass_cnt++;
 663                }
 664
 665                if (++test_cnt == target_cnt)
 666                        finish = true;
 667        }
 668        debug("statistics: pass/fail/total:%d/%d/%d\n", pass_cnt, fail_cnt,
 669              target_cnt);
 670
 671        return fail_cnt;
 672}
 673#endif
 674
 675/*
 676 * scu500[14:13]
 677 *      2b'00: VGA memory size = 16MB
 678 *      2b'01: VGA memory size = 16MB
 679 *      2b'10: VGA memory size = 32MB
 680 *      2b'11: VGA memory size = 64MB
 681 *
 682 * mcr04[3:2]
 683 *      2b'00: VGA memory size = 8MB
 684 *      2b'01: VGA memory size = 16MB
 685 *      2b'10: VGA memory size = 32MB
 686 *      2b'11: VGA memory size = 64MB
 687 */
 688static size_t ast2600_sdrammc_get_vga_mem_size(struct dram_info *info)
 689{
 690        u32 vga_hwconf;
 691        size_t vga_mem_size_base = 8 * 1024 * 1024;
 692
 693        vga_hwconf =
 694                (readl(&info->scu->hwstrap1) & SCU_HWSTRAP1_VGA_MEM_MASK) >>
 695                 SCU_HWSTRAP1_VGA_MEM_SHIFT;
 696
 697        if (vga_hwconf == 0) {
 698                vga_hwconf = 1;
 699                writel(vga_hwconf << SCU_HWSTRAP1_VGA_MEM_SHIFT,
 700                       &info->scu->hwstrap1);
 701        }
 702
 703        clrsetbits_le32(&info->regs->config, SDRAM_CONF_VGA_SIZE_MASK,
 704                        ((vga_hwconf << SDRAM_CONF_VGA_SIZE_SHIFT) &
 705                         SDRAM_CONF_VGA_SIZE_MASK));
 706
 707        /* no need to reserve VGA memory if efuse[VGA disable] is set */
 708        if (readl(&info->scu->efuse) & SCU_EFUSE_DIS_VGA)
 709                return 0;
 710
 711        return vga_mem_size_base << vga_hwconf;
 712}
 713
 714/*
 715 * Find out RAM size and save it in dram_info
 716 *
 717 * The procedure is taken from Aspeed SDK
 718 */
 719static void ast2600_sdrammc_calc_size(struct dram_info *info)
 720{
 721        /* The controller supports 256/512/1024/2048 MB ram */
 722        size_t ram_size = SDRAM_MIN_SIZE;
 723        const int write_test_offset = 0x100000;
 724        u32 test_pattern = 0xdeadbeef;
 725        u32 cap_param = SDRAM_CONF_CAP_2048M;
 726        u32 refresh_timing_param = DDR4_TRFC;
 727        const u32 write_addr_base = CONFIG_SYS_SDRAM_BASE + write_test_offset;
 728
 729        for (ram_size = SDRAM_MAX_SIZE; ram_size > SDRAM_MIN_SIZE;
 730             ram_size >>= 1) {
 731                writel(test_pattern, write_addr_base + (ram_size >> 1));
 732                test_pattern = (test_pattern >> 4) | (test_pattern << 28);
 733        }
 734
 735        /* One last write to overwrite all wrapped values */
 736        writel(test_pattern, write_addr_base);
 737
 738        /* Reset the pattern and see which value was really written */
 739        test_pattern = 0xdeadbeef;
 740        for (ram_size = SDRAM_MAX_SIZE; ram_size > SDRAM_MIN_SIZE;
 741             ram_size >>= 1) {
 742                if (readl(write_addr_base + (ram_size >> 1)) == test_pattern)
 743                        break;
 744
 745                --cap_param;
 746                refresh_timing_param >>= 8;
 747                test_pattern = (test_pattern >> 4) | (test_pattern << 28);
 748        }
 749
 750        clrsetbits_le32(&info->regs->ac_timing[1],
 751                        (SDRAM_AC_TRFC_MASK << SDRAM_AC_TRFC_SHIFT),
 752                        ((refresh_timing_param & SDRAM_AC_TRFC_MASK)
 753                         << SDRAM_AC_TRFC_SHIFT));
 754
 755        info->info.base = CONFIG_SYS_SDRAM_BASE;
 756        info->info.size = ram_size - ast2600_sdrammc_get_vga_mem_size(info);
 757
 758        clrsetbits_le32(&info->regs->config, SDRAM_CONF_CAP_MASK,
 759                        ((cap_param << SDRAM_CONF_CAP_SHIFT) & SDRAM_CONF_CAP_MASK));
 760}
 761
 762static int ast2600_sdrammc_init_ddr4(struct dram_info *info)
 763{
 764        const u32 power_ctrl = MCR34_CKE_EN | MCR34_AUTOPWRDN_EN |
 765                MCR34_MREQ_BYPASS_DIS | MCR34_RESETN_DIS |
 766                MCR34_ODT_EN | MCR34_ODT_AUTO_ON |
 767                (0x1 << MCR34_ODT_EXT_SHIFT);
 768
 769        /* init SDRAM-PHY only on real chip */
 770        ast2600_sdramphy_init(ast2600_sdramphy_config, info);
 771        writel((MCR34_CKE_EN | MCR34_MREQI_DIS | MCR34_RESETN_DIS),
 772               &info->regs->power_ctrl);
 773        udelay(5);
 774        ast2600_sdramphy_kick_training(info);
 775        udelay(500);
 776        writel(SDRAM_RESET_DLL_ZQCL_EN, &info->regs->refresh_timing);
 777
 778        writel(MCR30_SET_MR(3), &info->regs->mode_setting_control);
 779        writel(MCR30_SET_MR(6), &info->regs->mode_setting_control);
 780        writel(MCR30_SET_MR(5), &info->regs->mode_setting_control);
 781        writel(MCR30_SET_MR(4), &info->regs->mode_setting_control);
 782        writel(MCR30_SET_MR(2), &info->regs->mode_setting_control);
 783        writel(MCR30_SET_MR(1), &info->regs->mode_setting_control);
 784        writel(MCR30_SET_MR(0) | MCR30_RESET_DLL_DELAY_EN,
 785               &info->regs->mode_setting_control);
 786
 787        writel(SDRAM_REFRESH_EN | SDRAM_RESET_DLL_ZQCL_EN |
 788               (0x5f << SDRAM_REFRESH_PERIOD_SHIFT),
 789               &info->regs->refresh_timing);
 790
 791        /* wait self-refresh idle */
 792        while (readl(&info->regs->power_ctrl) &
 793               MCR34_SELF_REFRESH_STATUS_MASK)
 794                ;
 795
 796        writel(SDRAM_REFRESH_EN | SDRAM_LOW_PRI_REFRESH_EN |
 797               SDRAM_REFRESH_ZQCS_EN |
 798               (0x5f << SDRAM_REFRESH_PERIOD_SHIFT) |
 799               (0x42aa << SDRAM_REFRESH_PERIOD_ZQCS_SHIFT),
 800               &info->regs->refresh_timing);
 801
 802        writel(power_ctrl, &info->regs->power_ctrl);
 803        udelay(500);
 804
 805        return 0;
 806}
 807
 808static void ast2600_sdrammc_unlock(struct dram_info *info)
 809{
 810        writel(SDRAM_UNLOCK_KEY, &info->regs->protection_key);
 811        while (!readl(&info->regs->protection_key))
 812                ;
 813}
 814
 815static void ast2600_sdrammc_lock(struct dram_info *info)
 816{
 817        writel(~SDRAM_UNLOCK_KEY, &info->regs->protection_key);
 818        while (readl(&info->regs->protection_key))
 819                ;
 820}
 821
 822static void ast2600_sdrammc_common_init(struct ast2600_sdrammc_regs *regs)
 823{
 824        int i;
 825
 826        writel(MCR34_MREQI_DIS | MCR34_RESETN_DIS, &regs->power_ctrl);
 827        writel(SDRAM_VIDEO_UNLOCK_KEY, &regs->gm_protection_key);
 828        writel(0x10 << MCR38_RW_MAX_GRANT_CNT_RQ_SHIFT,
 829               &regs->arbitration_ctrl);
 830        writel(0xFFBBFFF4, &regs->req_limit_mask);
 831
 832        for (i = 0; i < ARRAY_SIZE(ddr_max_grant_params); ++i)
 833                writel(ddr_max_grant_params[i], &regs->max_grant_len[i]);
 834
 835        writel(MCR50_RESET_ALL_INTR, &regs->intr_ctrl);
 836
 837        writel(0x07FFFFFF, &regs->ecc_range_ctrl);
 838
 839        writel(0, &regs->ecc_test_ctrl);
 840        writel(0x80000001, &regs->test_addr);
 841        writel(0, &regs->test_fail_dq_bit);
 842        writel(0, &regs->test_init_val);
 843
 844        writel(0xFFFFFFFF, &regs->req_input_ctrl);
 845        writel(0, &regs->req_high_pri_ctrl);
 846
 847        udelay(600);
 848
 849#ifdef CONFIG_ASPEED_DDR4_DUALX8
 850        writel(0x37, &regs->config);
 851#else
 852        writel(0x17, &regs->config);
 853#endif
 854
 855        /* load controller setting */
 856        for (i = 0; i < ARRAY_SIZE(ddr4_ac_timing); ++i)
 857                writel(ddr4_ac_timing[i], &regs->ac_timing[i]);
 858
 859        writel(DDR4_MR01_MODE, &regs->mr01_mode_setting);
 860        writel(DDR4_MR23_MODE, &regs->mr23_mode_setting);
 861        writel(DDR4_MR45_MODE, &regs->mr45_mode_setting);
 862        writel(DDR4_MR6_MODE, &regs->mr6_mode_setting);
 863}
 864
 865/*
 866 * Update size info according to the ECC HW setting
 867 *
 868 * Assume SDRAM has been initialized by SPL or the host.  To get the RAM size, we
 869 * don't need to calculate the ECC size again but read from MCR04 and derive the
 870 * size from its value.
 871 */
 872static void ast2600_sdrammc_update_size(struct dram_info *info)
 873{
 874        struct ast2600_sdrammc_regs *regs = info->regs;
 875        u32 conf = readl(&regs->config);
 876        u32 cap_param;
 877        size_t ram_size = SDRAM_MAX_SIZE;
 878        size_t hw_size;
 879
 880        cap_param = (conf & SDRAM_CONF_CAP_MASK) >> SDRAM_CONF_CAP_SHIFT;
 881        switch (cap_param) {
 882        case SDRAM_CONF_CAP_2048M:
 883                ram_size = 2048 * SDRAM_SIZE_1MB;
 884                break;
 885        case SDRAM_CONF_CAP_1024M:
 886                ram_size = 1024 * SDRAM_SIZE_1MB;
 887                break;
 888        case SDRAM_CONF_CAP_512M:
 889                ram_size = 512 * SDRAM_SIZE_1MB;
 890                break;
 891        case SDRAM_CONF_CAP_256M:
 892                ram_size = 256 * SDRAM_SIZE_1MB;
 893                break;
 894        }
 895
 896        info->info.base = CONFIG_SYS_SDRAM_BASE;
 897        info->info.size = ram_size - ast2600_sdrammc_get_vga_mem_size(info);
 898
 899        if (0 == (conf & SDRAM_CONF_ECC_SETUP))
 900                return;
 901
 902        hw_size = readl(&regs->ecc_range_ctrl) & SDRAM_ECC_RANGE_ADDR_MASK;
 903        hw_size += (1 << SDRAM_ECC_RANGE_ADDR_SHIFT);
 904
 905        info->info.size = hw_size;
 906}
 907
 908#ifdef CONFIG_ASPEED_ECC
 909static void ast2600_sdrammc_ecc_enable(struct dram_info *info)
 910{
 911        struct ast2600_sdrammc_regs *regs = info->regs;
 912        size_t conf_size;
 913        u32 reg;
 914
 915        conf_size = CONFIG_ASPEED_ECC_SIZE * SDRAM_SIZE_1MB;
 916        if (conf_size > info->info.size) {
 917                printf("warning: ECC configured %dMB but actual size is %dMB\n",
 918                       CONFIG_ASPEED_ECC_SIZE,
 919                       info->info.size / SDRAM_SIZE_1MB);
 920                conf_size = info->info.size;
 921        } else if (conf_size == 0) {
 922                conf_size = info->info.size;
 923        }
 924
 925        info->info.size = (((conf_size / 9) * 8) >> 20) << 20;
 926        writel(((info->info.size >> 20) - 1) << 20, &regs->ecc_range_ctrl);
 927        reg = readl(&regs->config) | SDRAM_CONF_ECC_SETUP;
 928        writel(reg, &regs->config);
 929
 930        writel(0, &regs->test_init_val);
 931        writel(0x80000001, &regs->test_addr);
 932        writel(0x221, &regs->ecc_test_ctrl);
 933        while (0 == (readl(&regs->ecc_test_ctrl) & BIT(12)))
 934                ;
 935        writel(0, &regs->ecc_test_ctrl);
 936        writel(BIT(31), &regs->intr_ctrl);
 937        writel(0, &regs->intr_ctrl);
 938}
 939#endif
 940
 941static int ast2600_sdrammc_probe(struct udevice *dev)
 942{
 943        int ret;
 944        u32 reg;
 945        struct dram_info *priv = (struct dram_info *)dev_get_priv(dev);
 946        struct ast2600_sdrammc_regs *regs = priv->regs;
 947        struct udevice *clk_dev;
 948
 949        /* find SCU base address from clock device */
 950        ret = uclass_get_device_by_driver(UCLASS_CLK,
 951                                          DM_DRIVER_GET(aspeed_ast2600_scu), &clk_dev);
 952        if (ret) {
 953                debug("clock device not defined\n");
 954                return ret;
 955        }
 956
 957        priv->scu = devfdt_get_addr_ptr(clk_dev);
 958        if (IS_ERR(priv->scu)) {
 959                debug("%s(): can't get SCU\n", __func__);
 960                return PTR_ERR(priv->scu);
 961        }
 962
 963        if (readl(&priv->scu->dram_hdshk) & SCU_DRAM_HDSHK_RDY) {
 964                printf("already initialized, ");
 965                ast2600_sdrammc_update_size(priv);
 966                return 0;
 967        }
 968
 969        reg = readl(&priv->scu->mpll);
 970        reg &= ~(SCU_PLL_BYPASS | SCU_PLL_DIV_MASK |
 971                 SCU_PLL_DENUM_MASK | SCU_PLL_NUM_MASK);
 972        reg |= (SCU_PLL_RST | SCU_PLL_OFF | SCU_MPLL_FREQ_CFG);
 973        writel(reg, &priv->scu->mpll);
 974        writel(SCU_MPLL_EXT_CFG, &priv->scu->mpll_ext);
 975        udelay(100);
 976        reg &= ~(SCU_PLL_RST | SCU_PLL_OFF);
 977        writel(reg, &priv->scu->mpll);
 978
 979        while ((readl(&priv->scu->mpll_ext) & BIT(31)) == 0)
 980                ;
 981
 982        ast2600_sdrammc_unlock(priv);
 983        ast2600_sdrammc_common_init(regs);
 984L_ast2600_sdramphy_train:
 985        ast2600_sdrammc_init_ddr4(priv);
 986
 987        /* make sure DDR-PHY is ready before access */
 988        do {
 989                reg = readl(priv->phy_status) & BIT(1);
 990        } while (reg == 0);
 991
 992        if (ast2600_sdramphy_check_status(priv) != 0) {
 993                printf("DDR4 PHY training fail, retrain\n");
 994                goto L_ast2600_sdramphy_train;
 995        }
 996
 997        ast2600_sdrammc_calc_size(priv);
 998
 999#ifndef CONFIG_ASPEED_BYPASS_SELFTEST
1000        if (ast2600_sdrammc_test(priv) != 0) {
1001                printf("%s: DDR4 init fail\n", __func__);
1002                return -EINVAL;
1003        }
1004#endif
1005
1006#ifdef CONFIG_ASPEED_ECC
1007        ast2600_sdrammc_ecc_enable(priv);
1008#endif
1009
1010        writel(readl(&priv->scu->dram_hdshk) | SCU_DRAM_HDSHK_RDY,
1011               &priv->scu->dram_hdshk);
1012
1013        clrbits_le32(&regs->intr_ctrl, MCR50_RESET_ALL_INTR);
1014        ast2600_sdrammc_lock(priv);
1015        return 0;
1016}
1017
1018static int ast2600_sdrammc_of_to_plat(struct udevice *dev)
1019{
1020        struct dram_info *priv = dev_get_priv(dev);
1021
1022        priv->regs = (void *)(uintptr_t)devfdt_get_addr_index(dev, 0);
1023        priv->phy_setting = (void *)(uintptr_t)devfdt_get_addr_index(dev, 1);
1024        priv->phy_status = (void *)(uintptr_t)devfdt_get_addr_index(dev, 2);
1025
1026        priv->clock_rate = fdtdec_get_int(gd->fdt_blob, dev_of_offset(dev),
1027                                          "clock-frequency", 0);
1028        if (!priv->clock_rate) {
1029                debug("DDR Clock Rate not defined\n");
1030                return -EINVAL;
1031        }
1032
1033        return 0;
1034}
1035
1036static int ast2600_sdrammc_get_info(struct udevice *dev, struct ram_info *info)
1037{
1038        struct dram_info *priv = dev_get_priv(dev);
1039
1040        *info = priv->info;
1041
1042        return 0;
1043}
1044
1045static struct ram_ops ast2600_sdrammc_ops = {
1046        .get_info = ast2600_sdrammc_get_info,
1047};
1048
1049static const struct udevice_id ast2600_sdrammc_ids[] = {
1050        { .compatible = "aspeed,ast2600-sdrammc" },
1051        { }
1052};
1053
1054U_BOOT_DRIVER(sdrammc_ast2600) = {
1055        .name = "aspeed_ast2600_sdrammc",
1056        .id = UCLASS_RAM,
1057        .of_match = ast2600_sdrammc_ids,
1058        .ops = &ast2600_sdrammc_ops,
1059        .of_to_plat = ast2600_sdrammc_of_to_plat,
1060        .probe = ast2600_sdrammc_probe,
1061        .priv_auto = sizeof(struct dram_info),
1062};
1063