uboot/arch/arm/mach-mvebu/dram.c
<<
>>
Prefs
   1/*
   2 * (C) Copyright 2009
   3 * Marvell Semiconductor <www.marvell.com>
   4 * Written-by: Prafulla Wadaskar <prafulla@marvell.com>
   5 *
   6 * SPDX-License-Identifier:     GPL-2.0+
   7 */
   8
   9#include <config.h>
  10#include <common.h>
  11#include <asm/io.h>
  12#include <asm/arch/cpu.h>
  13#include <asm/arch/soc.h>
  14
  15#if defined(CONFIG_ARCH_MVEBU)
  16/* Use common XOR definitions for A3x and AXP */
  17#include "../../../drivers/ddr/marvell/axp/xor.h"
  18#include "../../../drivers/ddr/marvell/axp/xor_regs.h"
  19#endif
  20
  21DECLARE_GLOBAL_DATA_PTR;
  22
  23struct sdram_bank {
  24        u32     win_bar;
  25        u32     win_sz;
  26};
  27
  28struct sdram_addr_dec {
  29        struct sdram_bank sdram_bank[4];
  30};
  31
  32#define REG_CPUCS_WIN_ENABLE            (1 << 0)
  33#define REG_CPUCS_WIN_WR_PROTECT        (1 << 1)
  34#define REG_CPUCS_WIN_WIN0_CS(x)        (((x) & 0x3) << 2)
  35#define REG_CPUCS_WIN_SIZE(x)           (((x) & 0xff) << 24)
  36
  37#define SDRAM_SIZE_MAX                  0xc0000000
  38
  39#define SCRUB_MAGIC             0xbeefdead
  40
  41#define SCRB_XOR_UNIT           0
  42#define SCRB_XOR_CHAN           1
  43#define SCRB_XOR_WIN            0
  44
  45#define XEBARX_BASE_OFFS        16
  46
  47/*
  48 * mvebu_sdram_bar - reads SDRAM Base Address Register
  49 */
  50u32 mvebu_sdram_bar(enum memory_bank bank)
  51{
  52        struct sdram_addr_dec *base =
  53                (struct sdram_addr_dec *)MVEBU_SDRAM_BASE;
  54        u32 result = 0;
  55        u32 enable = 0x01 & readl(&base->sdram_bank[bank].win_sz);
  56
  57        if ((!enable) || (bank > BANK3))
  58                return 0;
  59
  60        result = readl(&base->sdram_bank[bank].win_bar);
  61        return result;
  62}
  63
  64/*
  65 * mvebu_sdram_bs_set - writes SDRAM Bank size
  66 */
  67static void mvebu_sdram_bs_set(enum memory_bank bank, u32 size)
  68{
  69        struct sdram_addr_dec *base =
  70                (struct sdram_addr_dec *)MVEBU_SDRAM_BASE;
  71        /* Read current register value */
  72        u32 reg = readl(&base->sdram_bank[bank].win_sz);
  73
  74        /* Clear window size */
  75        reg &= ~REG_CPUCS_WIN_SIZE(0xFF);
  76
  77        /* Set new window size */
  78        reg |= REG_CPUCS_WIN_SIZE((size - 1) >> 24);
  79
  80        writel(reg, &base->sdram_bank[bank].win_sz);
  81}
  82
  83/*
  84 * mvebu_sdram_bs - reads SDRAM Bank size
  85 */
  86u32 mvebu_sdram_bs(enum memory_bank bank)
  87{
  88        struct sdram_addr_dec *base =
  89                (struct sdram_addr_dec *)MVEBU_SDRAM_BASE;
  90        u32 result = 0;
  91        u32 enable = 0x01 & readl(&base->sdram_bank[bank].win_sz);
  92
  93        if ((!enable) || (bank > BANK3))
  94                return 0;
  95        result = 0xff000000 & readl(&base->sdram_bank[bank].win_sz);
  96        result += 0x01000000;
  97        return result;
  98}
  99
 100void mvebu_sdram_size_adjust(enum memory_bank bank)
 101{
 102        u32 size;
 103
 104        /* probe currently equipped RAM size */
 105        size = get_ram_size((void *)mvebu_sdram_bar(bank),
 106                            mvebu_sdram_bs(bank));
 107
 108        /* adjust SDRAM window size accordingly */
 109        mvebu_sdram_bs_set(bank, size);
 110}
 111
 112#if defined(CONFIG_ARCH_MVEBU)
 113static u32 xor_ctrl_save;
 114static u32 xor_base_save;
 115static u32 xor_mask_save;
 116
 117static void mv_xor_init2(u32 cs)
 118{
 119        u32 reg, base, size, base2;
 120        u32 bank_attr[4] = { 0xe00, 0xd00, 0xb00, 0x700 };
 121
 122        xor_ctrl_save = reg_read(XOR_WINDOW_CTRL_REG(SCRB_XOR_UNIT,
 123                                                     SCRB_XOR_CHAN));
 124        xor_base_save = reg_read(XOR_BASE_ADDR_REG(SCRB_XOR_UNIT,
 125                                                   SCRB_XOR_WIN));
 126        xor_mask_save = reg_read(XOR_SIZE_MASK_REG(SCRB_XOR_UNIT,
 127                                                   SCRB_XOR_WIN));
 128
 129        /* Enable Window x for each CS */
 130        reg = 0x1;
 131        reg |= (0x3 << 16);
 132        reg_write(XOR_WINDOW_CTRL_REG(SCRB_XOR_UNIT, SCRB_XOR_CHAN), reg);
 133
 134        base = 0;
 135        size = mvebu_sdram_bs(cs) - 1;
 136        if (size) {
 137                base2 = ((base / (64 << 10)) << XEBARX_BASE_OFFS) |
 138                        bank_attr[cs];
 139                reg_write(XOR_BASE_ADDR_REG(SCRB_XOR_UNIT, SCRB_XOR_WIN),
 140                          base2);
 141
 142                base += size + 1;
 143                size = (size / (64 << 10)) << 16;
 144                /* Window x - size - 256 MB */
 145                reg_write(XOR_SIZE_MASK_REG(SCRB_XOR_UNIT, SCRB_XOR_WIN), size);
 146        }
 147
 148        mv_xor_hal_init(0);
 149
 150        return;
 151}
 152
 153static void mv_xor_finish2(void)
 154{
 155        reg_write(XOR_WINDOW_CTRL_REG(SCRB_XOR_UNIT, SCRB_XOR_CHAN),
 156                  xor_ctrl_save);
 157        reg_write(XOR_BASE_ADDR_REG(SCRB_XOR_UNIT, SCRB_XOR_WIN),
 158                  xor_base_save);
 159        reg_write(XOR_SIZE_MASK_REG(SCRB_XOR_UNIT, SCRB_XOR_WIN),
 160                  xor_mask_save);
 161}
 162
 163static void dram_ecc_scrubbing(void)
 164{
 165        int cs;
 166        u32 size, temp;
 167        u32 total_mem = 0;
 168        u64 total;
 169        u32 start_addr;
 170
 171        /*
 172         * The DDR training code from the bin_hdr / SPL already
 173         * scrubbed the DDR till 0x1000000. And the main U-Boot
 174         * is loaded to an address < 0x1000000. So we need to
 175         * skip this range to not re-scrub this area again.
 176         */
 177        temp = reg_read(REG_SDRAM_CONFIG_ADDR);
 178        temp |= (1 << REG_SDRAM_CONFIG_IERR_OFFS);
 179        reg_write(REG_SDRAM_CONFIG_ADDR, temp);
 180
 181        for (cs = 0; cs < CONFIG_NR_DRAM_BANKS; cs++) {
 182                size = mvebu_sdram_bs(cs) - 1;
 183                if (size == 0)
 184                        continue;
 185
 186                total = (u64)size + 1;
 187                total_mem += (u32)(total / (1 << 30));
 188                start_addr = 0;
 189                mv_xor_init2(cs);
 190
 191                /* Skip first 16 MiB */
 192                if (0 == cs) {
 193                        start_addr = 0x1000000;
 194                        size -= start_addr;
 195                }
 196
 197                mv_xor_mem_init(SCRB_XOR_CHAN, start_addr, size,
 198                                SCRUB_MAGIC, SCRUB_MAGIC);
 199
 200                /* Wait for previous transfer completion */
 201                while (mv_xor_state_get(SCRB_XOR_CHAN) != MV_IDLE)
 202                        ;
 203
 204                mv_xor_finish2();
 205        }
 206
 207        temp = reg_read(REG_SDRAM_CONFIG_ADDR);
 208        temp &= ~(1 << REG_SDRAM_CONFIG_IERR_OFFS);
 209        reg_write(REG_SDRAM_CONFIG_ADDR, temp);
 210}
 211
 212static int ecc_enabled(void)
 213{
 214        if (reg_read(REG_SDRAM_CONFIG_ADDR) & (1 << REG_SDRAM_CONFIG_ECC_OFFS))
 215                return 1;
 216
 217        return 0;
 218}
 219#else
 220static void dram_ecc_scrubbing(void)
 221{
 222}
 223
 224static int ecc_enabled(void)
 225{
 226        return 0;
 227}
 228#endif
 229
 230int dram_init(void)
 231{
 232        u64 size = 0;
 233        int i;
 234
 235        for (i = 0; i < CONFIG_NR_DRAM_BANKS; i++) {
 236                /*
 237                 * It is assumed that all memory banks are consecutive
 238                 * and without gaps.
 239                 * If the gap is found, ram_size will be reported for
 240                 * consecutive memory only
 241                 */
 242                if (mvebu_sdram_bar(i) != size)
 243                        break;
 244
 245                /*
 246                 * Don't report more than 3GiB of SDRAM, otherwise there is no
 247                 * address space left for the internal registers etc.
 248                 */
 249                size += mvebu_sdram_bs(i);
 250                if (size > SDRAM_SIZE_MAX)
 251                        size = SDRAM_SIZE_MAX;
 252        }
 253
 254        for (; i < CONFIG_NR_DRAM_BANKS; i++) {
 255                /* If above loop terminated prematurely, we need to set
 256                 * remaining banks' start address & size as 0. Otherwise other
 257                 * u-boot functions and Linux kernel gets wrong values which
 258                 * could result in crash */
 259                gd->bd->bi_dram[i].start = 0;
 260                gd->bd->bi_dram[i].size = 0;
 261        }
 262
 263
 264        if (ecc_enabled())
 265                dram_ecc_scrubbing();
 266
 267        gd->ram_size = size;
 268
 269        return 0;
 270}
 271
 272/*
 273 * If this function is not defined here,
 274 * board.c alters dram bank zero configuration defined above.
 275 */
 276void dram_init_banksize(void)
 277{
 278        u64 size = 0;
 279        int i;
 280
 281        for (i = 0; i < CONFIG_NR_DRAM_BANKS; i++) {
 282                gd->bd->bi_dram[i].start = mvebu_sdram_bar(i);
 283                gd->bd->bi_dram[i].size = mvebu_sdram_bs(i);
 284
 285                /* Clip the banksize to 1GiB if it exceeds the max size */
 286                size += gd->bd->bi_dram[i].size;
 287                if (size > SDRAM_SIZE_MAX)
 288                        mvebu_sdram_bs_set(i, 0x40000000);
 289        }
 290}
 291
 292#if defined(CONFIG_ARCH_MVEBU)
 293void board_add_ram_info(int use_default)
 294{
 295        struct sar_freq_modes sar_freq;
 296
 297        get_sar_freq(&sar_freq);
 298        printf(" (%d MHz, ", sar_freq.d_clk);
 299
 300        if (ecc_enabled())
 301                printf("ECC");
 302        else
 303                printf("ECC not");
 304        printf(" enabled)");
 305}
 306#endif
 307