uboot/arch/arm/mach-omap2/omap3/sdrc.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0+
   2/*
   3 * Functions related to OMAP3 SDRC.
   4 *
   5 * This file has been created after exctracting and consolidating
   6 * the SDRC related content from mem.c and board.c, also created
   7 * generic init function (mem_init).
   8 *
   9 * Copyright (C) 2004-2010
  10 * Texas Instruments Incorporated - http://www.ti.com/
  11 *
  12 * Copyright (C) 2011
  13 * Corscience GmbH & Co. KG - Simon Schwarz <schwarz@corscience.de>
  14 *
  15 * Author :
  16 *     Vaibhav Hiremath <hvaibhav@ti.com>
  17 *
  18 * Original implementation by (mem.c, board.c) :
  19 *      Sunil Kumar <sunilsaini05@gmail.com>
  20 *      Shashi Ranjan <shashiranjanmca05@gmail.com>
  21 *      Manikandan Pillai <mani.pillai@ti.com>
  22 */
  23
  24#include <common.h>
  25#include <init.h>
  26#include <asm/global_data.h>
  27#include <asm/io.h>
  28#include <asm/arch/mem.h>
  29#include <asm/arch/sys_proto.h>
  30
  31DECLARE_GLOBAL_DATA_PTR;
  32extern omap3_sysinfo sysinfo;
  33
  34static struct sdrc *sdrc_base = (struct sdrc *)OMAP34XX_SDRC_BASE;
  35
  36/*
  37 * is_mem_sdr -
  38 *  - Return 1 if mem type in use is SDR
  39 */
  40u32 is_mem_sdr(void)
  41{
  42        if (readl(&sdrc_base->cs[CS0].mr) == SDRC_MR_0_SDR)
  43                return 1;
  44        return 0;
  45}
  46
  47/*
  48 * make_cs1_contiguous -
  49 * - When we have CS1 populated we want to have it mapped after cs0 to allow
  50 *   command line mem=xyz use all memory with out discontinuous support
  51 *   compiled in.  We could do it in the ATAG, but there really is two banks...
  52 */
  53void make_cs1_contiguous(void)
  54{
  55        u32 size, a_add_low, a_add_high;
  56
  57        size = get_sdr_cs_size(CS0);
  58        size >>= 25;    /* divide by 32 MiB to find size to offset CS1 */
  59        a_add_high = (size & 3) << 8;   /* set up low field */
  60        a_add_low = (size & 0x3C) >> 2; /* set up high field */
  61        writel((a_add_high | a_add_low), &sdrc_base->cs_cfg);
  62
  63}
  64
  65
  66/*
  67 * get_sdr_cs_size -
  68 *  - Get size of chip select 0/1
  69 */
  70u32 get_sdr_cs_size(u32 cs)
  71{
  72        u32 size;
  73
  74        /* get ram size field */
  75        size = readl(&sdrc_base->cs[cs].mcfg) >> 8;
  76        size &= 0x3FF;          /* remove unwanted bits */
  77        size <<= 21;            /* multiply by 2 MiB to find size in MB */
  78        return size;
  79}
  80
  81/*
  82 * get_sdr_cs_offset -
  83 *  - Get offset of cs from cs0 start
  84 */
  85u32 get_sdr_cs_offset(u32 cs)
  86{
  87        u32 offset;
  88
  89        if (!cs)
  90                return 0;
  91
  92        offset = readl(&sdrc_base->cs_cfg);
  93        offset = (offset & 15) << 27 | (offset & 0x300) << 17;
  94
  95        return offset;
  96}
  97
  98/*
  99 * write_sdrc_timings -
 100 *  - Takes CS and associated timings and initalize SDRAM
 101 *  - Test CS to make sure it's OK for use
 102 */
 103static void write_sdrc_timings(u32 cs, struct sdrc_actim *sdrc_actim_base,
 104                        struct board_sdrc_timings *timings)
 105{
 106        /* Setup timings we got from the board. */
 107        writel(timings->mcfg, &sdrc_base->cs[cs].mcfg);
 108        writel(timings->ctrla, &sdrc_actim_base->ctrla);
 109        writel(timings->ctrlb, &sdrc_actim_base->ctrlb);
 110        writel(timings->rfr_ctrl, &sdrc_base->cs[cs].rfr_ctrl);
 111        writel(CMD_NOP, &sdrc_base->cs[cs].manual);
 112        writel(CMD_PRECHARGE, &sdrc_base->cs[cs].manual);
 113        writel(CMD_AUTOREFRESH, &sdrc_base->cs[cs].manual);
 114        writel(CMD_AUTOREFRESH, &sdrc_base->cs[cs].manual);
 115        writel(timings->mr, &sdrc_base->cs[cs].mr);
 116
 117        /*
 118         * Test ram in this bank
 119         * Disable if bad or not present
 120         */
 121        if (!mem_ok(cs))
 122                writel(0, &sdrc_base->cs[cs].mcfg);
 123}
 124
 125/*
 126 * do_sdrc_init -
 127 *  - Code called once in C-Stack only context for CS0 and with early being
 128 *    true and a possible 2nd time depending on memory configuration from
 129 *    stack+global context.
 130 */
 131void do_sdrc_init(u32 cs, u32 early)
 132{
 133        struct sdrc_actim *sdrc_actim_base0, *sdrc_actim_base1;
 134        struct board_sdrc_timings timings;
 135
 136        sdrc_actim_base0 = (struct sdrc_actim *)SDRC_ACTIM_CTRL0_BASE;
 137        sdrc_actim_base1 = (struct sdrc_actim *)SDRC_ACTIM_CTRL1_BASE;
 138
 139        /* set some default timings */
 140        timings.sharing = SDRC_SHARING;
 141
 142        /*
 143         * When called in the early context this may be SPL and we will
 144         * need to set all of the timings.  This ends up being board
 145         * specific so we call a helper function to take care of this
 146         * for us.  Otherwise, to be safe, we need to copy the settings
 147         * from the first bank to the second.  We will setup CS0,
 148         * then set cs_cfg to the appropriate value then try and
 149         * setup CS1.
 150         */
 151#ifdef CONFIG_SPL_BUILD
 152        /* set/modify board-specific timings */
 153        get_board_mem_timings(&timings);
 154#endif
 155        if (early) {
 156                /* reset sdrc controller */
 157                writel(SOFTRESET, &sdrc_base->sysconfig);
 158                wait_on_value(RESETDONE, RESETDONE, &sdrc_base->status,
 159                                12000000);
 160                writel(0, &sdrc_base->sysconfig);
 161
 162                /* setup sdrc to ball mux */
 163                writel(timings.sharing, &sdrc_base->sharing);
 164
 165                /* Disable Power Down of CKE because of 1 CKE on combo part */
 166                writel(WAKEUPPROC | SRFRONRESET | PAGEPOLICY_HIGH,
 167                                &sdrc_base->power);
 168
 169                writel(ENADLL | DLLPHASE_90, &sdrc_base->dlla_ctrl);
 170                sdelay(0x20000);
 171#ifdef CONFIG_SPL_BUILD
 172                write_sdrc_timings(CS0, sdrc_actim_base0, &timings);
 173                make_cs1_contiguous();
 174                write_sdrc_timings(CS1, sdrc_actim_base1, &timings);
 175#endif
 176
 177        }
 178
 179        /*
 180         * If we aren't using SPL we have been loaded by some
 181         * other means which may not have correctly initialized
 182         * both CS0 and CS1 (such as some older versions of x-loader)
 183         * so we may be asked now to setup CS1.
 184         */
 185        if (cs == CS1) {
 186                timings.mcfg = readl(&sdrc_base->cs[CS0].mcfg),
 187                timings.rfr_ctrl = readl(&sdrc_base->cs[CS0].rfr_ctrl);
 188                timings.ctrla = readl(&sdrc_actim_base0->ctrla);
 189                timings.ctrlb = readl(&sdrc_actim_base0->ctrlb);
 190                timings.mr = readl(&sdrc_base->cs[CS0].mr);
 191                write_sdrc_timings(cs, sdrc_actim_base1, &timings);
 192        }
 193}
 194
 195/*
 196 * dram_init -
 197 *  - Sets uboots idea of sdram size
 198 */
 199int dram_init(void)
 200{
 201        unsigned int size0 = 0, size1 = 0;
 202
 203        size0 = get_sdr_cs_size(CS0);
 204        /*
 205         * We always need to have cs_cfg point at where the second
 206         * bank would be, if present.  Failure to do so can lead to
 207         * strange situations where memory isn't detected and
 208         * configured correctly.  CS0 will already have been setup
 209         * at this point.
 210         */
 211        make_cs1_contiguous();
 212        do_sdrc_init(CS1, NOT_EARLY);
 213        size1 = get_sdr_cs_size(CS1);
 214
 215        gd->ram_size = size0 + size1;
 216
 217        return 0;
 218}
 219
 220int dram_init_banksize(void)
 221{
 222        unsigned int size0 = 0, size1 = 0;
 223
 224        size0 = get_sdr_cs_size(CS0);
 225        size1 = get_sdr_cs_size(CS1);
 226
 227        gd->bd->bi_dram[0].start = PHYS_SDRAM_1;
 228        gd->bd->bi_dram[0].size = size0;
 229        gd->bd->bi_dram[1].start = PHYS_SDRAM_1 + get_sdr_cs_offset(CS1);
 230        gd->bd->bi_dram[1].size = size1;
 231
 232        return 0;
 233}
 234
 235/*
 236 * mem_init -
 237 *  - Init the sdrc chip,
 238 *  - Selects CS0 and CS1,
 239 */
 240void mem_init(void)
 241{
 242        /* only init up first bank here */
 243        do_sdrc_init(CS0, EARLY_INIT);
 244}
 245