uboot/arch/arm/cpu/arm926ejs/mxs/spl_mem_init.c
<<
>>
Prefs
   1/*
   2 * Freescale i.MX28 RAM init
   3 *
   4 * Copyright (C) 2011 Marek Vasut <marek.vasut@gmail.com>
   5 * on behalf of DENX Software Engineering GmbH
   6 *
   7 * See file CREDITS for list of people who contributed to this
   8 * project.
   9 *
  10 * This program is free software; you can redistribute it and/or
  11 * modify it under the terms of the GNU General Public License as
  12 * published by the Free Software Foundation; either version 2 of
  13 * the License, or (at your option) any later version.
  14 *
  15 * This program is distributed in the hope that it will be useful,
  16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
  17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  18 * GNU General Public License for more details.
  19 *
  20 * You should have received a copy of the GNU General Public License
  21 * along with this program; if not, write to the Free Software
  22 * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
  23 * MA 02111-1307 USA
  24 */
  25
  26#include <common.h>
  27#include <config.h>
  28#include <asm/io.h>
  29#include <asm/arch/imx-regs.h>
  30
  31#include "mxs_init.h"
  32
  33static uint32_t dram_vals[] = {
  34/*
  35 * i.MX28 DDR2 at 200MHz
  36 */
  37#if defined(CONFIG_MX28)
  38        0x00000000, 0x00000000, 0x00000000, 0x00000000,
  39        0x00000000, 0x00000000, 0x00000000, 0x00000000,
  40        0x00000000, 0x00000000, 0x00000000, 0x00000000,
  41        0x00000000, 0x00000000, 0x00000000, 0x00000000,
  42        0x00000000, 0x00000100, 0x00000000, 0x00000000,
  43        0x00000000, 0x00000000, 0x00000000, 0x00000000,
  44        0x00000000, 0x00000000, 0x00010101, 0x01010101,
  45        0x000f0f01, 0x0f02020a, 0x00000000, 0x00010101,
  46        0x00000100, 0x00000100, 0x00000000, 0x00000002,
  47        0x01010000, 0x05060302, 0x06005003, 0x0a0000c8,
  48        0x02009c40, 0x0000030c, 0x0036a609, 0x031a0612,
  49        0x02030202, 0x00c8001c, 0x00000000, 0x00000000,
  50        0x00012100, 0xffff0303, 0x00012100, 0xffff0303,
  51        0x00012100, 0xffff0303, 0x00012100, 0xffff0303,
  52        0x00000003, 0x00000000, 0x00000000, 0x00000000,
  53        0x00000000, 0x00000000, 0x00000000, 0x00000000,
  54        0x00000000, 0x00000000, 0x00000612, 0x01000F02,
  55        0x06120612, 0x00000200, 0x00020007, 0xf5014b27,
  56        0xf5014b27, 0xf5014b27, 0xf5014b27, 0x07000300,
  57        0x07000300, 0x07000300, 0x07000300, 0x00000006,
  58        0x00000000, 0x00000000, 0x01000000, 0x01020408,
  59        0x08040201, 0x000f1133, 0x00000000, 0x00001f04,
  60        0x00001f04, 0x00001f04, 0x00001f04, 0x00001f04,
  61        0x00001f04, 0x00001f04, 0x00001f04, 0x00000000,
  62        0x00000000, 0x00000000, 0x00000000, 0x00000000,
  63        0x00000000, 0x00000000, 0x00000000, 0x00000000,
  64        0x00000000, 0x00000000, 0x00000000, 0x00000000,
  65        0x00000000, 0x00000000, 0x00000000, 0x00000000,
  66        0x00000000, 0x00000000, 0x00000000, 0x00000000,
  67        0x00000000, 0x00000000, 0x00000000, 0x00000000,
  68        0x00000000, 0x00000000, 0x00000000, 0x00000000,
  69        0x00000000, 0x00000000, 0x00000000, 0x00000000,
  70        0x00000000, 0x00000000, 0x00000000, 0x00000000,
  71        0x00000000, 0x00000000, 0x00000000, 0x00000000,
  72        0x00000000, 0x00000000, 0x00000000, 0x00000000,
  73        0x00000000, 0x00000000, 0x00000000, 0x00000000,
  74        0x00000000, 0x00000000, 0x00000000, 0x00000000,
  75        0x00000000, 0x00000000, 0x00000000, 0x00000000,
  76        0x00000000, 0x00000000, 0x00000000, 0x00000000,
  77        0x00000000, 0x00000000, 0x00000000, 0x00000000,
  78        0x00000000, 0x00000000, 0x00010000, 0x00020304,
  79        0x00000004, 0x00000000, 0x00000000, 0x00000000,
  80        0x00000000, 0x00000000, 0x00000000, 0x01010000,
  81        0x01000000, 0x03030000, 0x00010303, 0x01020202,
  82        0x00000000, 0x02040303, 0x21002103, 0x00061200,
  83        0x06120612, 0x04320432, 0x04320432, 0x00040004,
  84        0x00040004, 0x00000000, 0x00000000, 0x00000000,
  85        0x00000000, 0x00010001
  86#else
  87#error Unsupported memory initialization
  88#endif
  89};
  90
  91void __mxs_adjust_memory_params(uint32_t *dram_vals)
  92{
  93}
  94void mxs_adjust_memory_params(uint32_t *dram_vals)
  95        __attribute__((weak, alias("__mxs_adjust_memory_params")));
  96
  97static void initialize_dram_values(void)
  98{
  99        int i;
 100
 101        mxs_adjust_memory_params(dram_vals);
 102
 103        for (i = 0; i < ARRAY_SIZE(dram_vals); i++)
 104                writel(dram_vals[i], MXS_DRAM_BASE + (4 * i));
 105}
 106
 107static void mxs_mem_init_clock(void)
 108{
 109        struct mxs_clkctrl_regs *clkctrl_regs =
 110                (struct mxs_clkctrl_regs *)MXS_CLKCTRL_BASE;
 111
 112        /* Gate EMI clock */
 113        writeb(CLKCTRL_FRAC_CLKGATE,
 114                &clkctrl_regs->hw_clkctrl_frac0_set[CLKCTRL_FRAC0_EMI]);
 115
 116        /* Set fractional divider for ref_emi to 480 * 18 / 21 = 411MHz */
 117        writeb(CLKCTRL_FRAC_CLKGATE | (21 & CLKCTRL_FRAC_FRAC_MASK),
 118                &clkctrl_regs->hw_clkctrl_frac0[CLKCTRL_FRAC0_EMI]);
 119
 120        /* Ungate EMI clock */
 121        writeb(CLKCTRL_FRAC_CLKGATE,
 122                &clkctrl_regs->hw_clkctrl_frac0_clr[CLKCTRL_FRAC0_EMI]);
 123
 124        early_delay(11000);
 125
 126        /* Set EMI clock divider for EMI clock to 411 / 2 = 205MHz */
 127        writel((2 << CLKCTRL_EMI_DIV_EMI_OFFSET) |
 128                (1 << CLKCTRL_EMI_DIV_XTAL_OFFSET),
 129                &clkctrl_regs->hw_clkctrl_emi);
 130
 131        /* Unbypass EMI */
 132        writel(CLKCTRL_CLKSEQ_BYPASS_EMI,
 133                &clkctrl_regs->hw_clkctrl_clkseq_clr);
 134
 135        early_delay(10000);
 136}
 137
 138static void mxs_mem_setup_cpu_and_hbus(void)
 139{
 140        struct mxs_clkctrl_regs *clkctrl_regs =
 141                (struct mxs_clkctrl_regs *)MXS_CLKCTRL_BASE;
 142
 143        /* Set fractional divider for ref_cpu to 480 * 18 / 19 = 454MHz
 144         * and ungate CPU clock */
 145        writeb(19 & CLKCTRL_FRAC_FRAC_MASK,
 146                (uint8_t *)&clkctrl_regs->hw_clkctrl_frac0[CLKCTRL_FRAC0_CPU]);
 147
 148        /* Set CPU bypass */
 149        writel(CLKCTRL_CLKSEQ_BYPASS_CPU,
 150                &clkctrl_regs->hw_clkctrl_clkseq_set);
 151
 152        /* HBUS = 151MHz */
 153        writel(CLKCTRL_HBUS_DIV_MASK, &clkctrl_regs->hw_clkctrl_hbus_set);
 154        writel(((~3) << CLKCTRL_HBUS_DIV_OFFSET) & CLKCTRL_HBUS_DIV_MASK,
 155                &clkctrl_regs->hw_clkctrl_hbus_clr);
 156
 157        early_delay(10000);
 158
 159        /* CPU clock divider = 1 */
 160        clrsetbits_le32(&clkctrl_regs->hw_clkctrl_cpu,
 161                        CLKCTRL_CPU_DIV_CPU_MASK, 1);
 162
 163        /* Disable CPU bypass */
 164        writel(CLKCTRL_CLKSEQ_BYPASS_CPU,
 165                &clkctrl_regs->hw_clkctrl_clkseq_clr);
 166
 167        early_delay(15000);
 168}
 169
 170static void mxs_mem_setup_vdda(void)
 171{
 172        struct mxs_power_regs *power_regs =
 173                (struct mxs_power_regs *)MXS_POWER_BASE;
 174
 175        writel((0xc << POWER_VDDACTRL_TRG_OFFSET) |
 176                (0x7 << POWER_VDDACTRL_BO_OFFSET_OFFSET) |
 177                POWER_VDDACTRL_LINREG_OFFSET_1STEPS_BELOW,
 178                &power_regs->hw_power_vddactrl);
 179}
 180
 181uint32_t mxs_mem_get_size(void)
 182{
 183        uint32_t sz, da;
 184        uint32_t *vt = (uint32_t *)0x20;
 185        /* The following is "subs pc, r14, #4", used as return from DABT. */
 186        const uint32_t data_abort_memdetect_handler = 0xe25ef004;
 187
 188        /* Replace the DABT handler. */
 189        da = vt[4];
 190        vt[4] = data_abort_memdetect_handler;
 191
 192        sz = get_ram_size((long *)PHYS_SDRAM_1, PHYS_SDRAM_1_SIZE);
 193
 194        /* Restore the old DABT handler. */
 195        vt[4] = da;
 196
 197        return sz;
 198}
 199
 200void mxs_mem_init(void)
 201{
 202        struct mxs_clkctrl_regs *clkctrl_regs =
 203                (struct mxs_clkctrl_regs *)MXS_CLKCTRL_BASE;
 204        struct mxs_pinctrl_regs *pinctrl_regs =
 205                (struct mxs_pinctrl_regs *)MXS_PINCTRL_BASE;
 206
 207        /* Set DDR2 mode */
 208        writel(PINCTRL_EMI_DS_CTRL_DDR_MODE_DDR2,
 209                &pinctrl_regs->hw_pinctrl_emi_ds_ctrl_set);
 210
 211        /* Power up PLL0 */
 212        writel(CLKCTRL_PLL0CTRL0_POWER,
 213                &clkctrl_regs->hw_clkctrl_pll0ctrl0_set);
 214
 215        early_delay(11000);
 216
 217        mxs_mem_init_clock();
 218
 219        mxs_mem_setup_vdda();
 220
 221        /*
 222         * Configure the DRAM registers
 223         */
 224
 225        /* Clear START bit from DRAM_CTL16 */
 226        clrbits_le32(MXS_DRAM_BASE + 0x40, 1);
 227
 228        initialize_dram_values();
 229
 230        /* Clear SREFRESH bit from DRAM_CTL17 */
 231        clrbits_le32(MXS_DRAM_BASE + 0x44, 1);
 232
 233        /* Set START bit in DRAM_CTL16 */
 234        setbits_le32(MXS_DRAM_BASE + 0x40, 1);
 235
 236        /* Wait for bit 20 (DRAM init complete) in DRAM_CTL58 */
 237        while (!(readl(MXS_DRAM_BASE + 0xe8) & (1 << 20)))
 238                ;
 239
 240        early_delay(10000);
 241
 242        mxs_mem_setup_cpu_and_hbus();
 243}
 244