uboot/arch/arm/cpu/armv7/exynos/dmc_init_ddr3.c
<<
>>
Prefs
   1/*
   2 * DDR3 mem setup file for SMDK5250 board based on EXYNOS5
   3 *
   4 * Copyright (C) 2012 Samsung Electronics
   5 *
   6 * See file CREDITS for list of people who contributed to this
   7 * project.
   8 *
   9 * This program is free software; you can redistribute it and/or
  10 * modify it under the terms of the GNU General Public License as
  11 * published by the Free Software Foundation; either version 2 of
  12 * the License, or (at your option) any later version.
  13 *
  14 * This program is distributed in the hope that it will be useful,
  15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
  16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  17 * GNU General Public License for more details.
  18 *
  19 * You should have received a copy of the GNU General Public License
  20 * along with this program; if not, write to the Free Software
  21 * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
  22 * MA 02111-1307 USA
  23 */
  24
  25#include <config.h>
  26#include <asm/io.h>
  27#include <asm/arch/clock.h>
  28#include <asm/arch/cpu.h>
  29#include <asm/arch/dmc.h>
  30#include "common_setup.h"
  31#include "exynos5_setup.h"
  32#include "clock_init.h"
  33
  34#define RDLVL_COMPLETE_TIMEOUT  10000
  35
  36static void reset_phy_ctrl(void)
  37{
  38        struct exynos5_clock *clk =
  39                (struct exynos5_clock *)samsung_get_base_clock();
  40
  41        writel(DDR3PHY_CTRL_PHY_RESET_OFF, &clk->lpddr3phy_ctrl);
  42        writel(DDR3PHY_CTRL_PHY_RESET, &clk->lpddr3phy_ctrl);
  43}
  44
  45int ddr3_mem_ctrl_init(struct mem_timings *mem, unsigned long mem_iv_size,
  46                       int reset)
  47{
  48        unsigned int val;
  49        struct exynos5_phy_control *phy0_ctrl, *phy1_ctrl;
  50        struct exynos5_dmc *dmc;
  51        int i;
  52
  53        phy0_ctrl = (struct exynos5_phy_control *)samsung_get_base_dmc_phy();
  54        phy1_ctrl = (struct exynos5_phy_control *)(samsung_get_base_dmc_phy()
  55                                                        + DMC_OFFSET);
  56        dmc = (struct exynos5_dmc *)samsung_get_base_dmc_ctrl();
  57
  58        if (reset)
  59                reset_phy_ctrl();
  60
  61        /* Set Impedance Output Driver */
  62        val = (mem->impedance << CA_CK_DRVR_DS_OFFSET) |
  63                (mem->impedance << CA_CKE_DRVR_DS_OFFSET) |
  64                (mem->impedance << CA_CS_DRVR_DS_OFFSET) |
  65                (mem->impedance << CA_ADR_DRVR_DS_OFFSET);
  66        writel(val, &phy0_ctrl->phy_con39);
  67        writel(val, &phy1_ctrl->phy_con39);
  68
  69        /* Set Read Latency and Burst Length for PHY0 and PHY1 */
  70        val = (mem->ctrl_bstlen << PHY_CON42_CTRL_BSTLEN_SHIFT) |
  71                (mem->ctrl_rdlat << PHY_CON42_CTRL_RDLAT_SHIFT);
  72        writel(val, &phy0_ctrl->phy_con42);
  73        writel(val, &phy1_ctrl->phy_con42);
  74
  75        /* ZQ Calibration */
  76        if (dmc_config_zq(mem, phy0_ctrl, phy1_ctrl))
  77                return SETUP_ERR_ZQ_CALIBRATION_FAILURE;
  78
  79        /* DQ Signal */
  80        writel(mem->phy0_pulld_dqs, &phy0_ctrl->phy_con14);
  81        writel(mem->phy1_pulld_dqs, &phy1_ctrl->phy_con14);
  82
  83        writel(mem->concontrol | (mem->rd_fetch << CONCONTROL_RD_FETCH_SHIFT)
  84                | (mem->dfi_init_start << CONCONTROL_DFI_INIT_START_SHIFT),
  85                &dmc->concontrol);
  86
  87        update_reset_dll(dmc, DDR_MODE_DDR3);
  88
  89        /* DQS Signal */
  90        writel(mem->phy0_dqs, &phy0_ctrl->phy_con4);
  91        writel(mem->phy1_dqs, &phy1_ctrl->phy_con4);
  92
  93        writel(mem->phy0_dq, &phy0_ctrl->phy_con6);
  94        writel(mem->phy1_dq, &phy1_ctrl->phy_con6);
  95
  96        writel(mem->phy0_tFS, &phy0_ctrl->phy_con10);
  97        writel(mem->phy1_tFS, &phy1_ctrl->phy_con10);
  98
  99        val = (mem->ctrl_start_point << PHY_CON12_CTRL_START_POINT_SHIFT) |
 100                (mem->ctrl_inc << PHY_CON12_CTRL_INC_SHIFT) |
 101                (mem->ctrl_dll_on << PHY_CON12_CTRL_DLL_ON_SHIFT) |
 102                (mem->ctrl_ref << PHY_CON12_CTRL_REF_SHIFT);
 103        writel(val, &phy0_ctrl->phy_con12);
 104        writel(val, &phy1_ctrl->phy_con12);
 105
 106        /* Start DLL locking */
 107        writel(val | (mem->ctrl_start << PHY_CON12_CTRL_START_SHIFT),
 108               &phy0_ctrl->phy_con12);
 109        writel(val | (mem->ctrl_start << PHY_CON12_CTRL_START_SHIFT),
 110               &phy1_ctrl->phy_con12);
 111
 112        update_reset_dll(dmc, DDR_MODE_DDR3);
 113
 114        writel(mem->concontrol | (mem->rd_fetch << CONCONTROL_RD_FETCH_SHIFT),
 115               &dmc->concontrol);
 116
 117        /* Memory Channel Inteleaving Size */
 118        writel(mem->iv_size, &dmc->ivcontrol);
 119
 120        writel(mem->memconfig, &dmc->memconfig0);
 121        writel(mem->memconfig, &dmc->memconfig1);
 122        writel(mem->membaseconfig0, &dmc->membaseconfig0);
 123        writel(mem->membaseconfig1, &dmc->membaseconfig1);
 124
 125        /* Precharge Configuration */
 126        writel(mem->prechconfig_tp_cnt << PRECHCONFIG_TP_CNT_SHIFT,
 127               &dmc->prechconfig);
 128
 129        /* Power Down mode Configuration */
 130        writel(mem->dpwrdn_cyc << PWRDNCONFIG_DPWRDN_CYC_SHIFT |
 131                mem->dsref_cyc << PWRDNCONFIG_DSREF_CYC_SHIFT,
 132                &dmc->pwrdnconfig);
 133
 134        /* TimingRow, TimingData, TimingPower and Timingaref
 135         * values as per Memory AC parameters
 136         */
 137        writel(mem->timing_ref, &dmc->timingref);
 138        writel(mem->timing_row, &dmc->timingrow);
 139        writel(mem->timing_data, &dmc->timingdata);
 140        writel(mem->timing_power, &dmc->timingpower);
 141
 142        /* Send PALL command */
 143        dmc_config_prech(mem, dmc);
 144
 145        /* Send NOP, MRS and ZQINIT commands */
 146        dmc_config_mrs(mem, dmc);
 147
 148        if (mem->gate_leveling_enable) {
 149                val = PHY_CON0_RESET_VAL;
 150                val |= P0_CMD_EN;
 151                writel(val, &phy0_ctrl->phy_con0);
 152                writel(val, &phy1_ctrl->phy_con0);
 153
 154                val = PHY_CON2_RESET_VAL;
 155                val |= INIT_DESKEW_EN;
 156                writel(val, &phy0_ctrl->phy_con2);
 157                writel(val, &phy1_ctrl->phy_con2);
 158
 159                val = PHY_CON0_RESET_VAL;
 160                val |= P0_CMD_EN;
 161                val |= BYTE_RDLVL_EN;
 162                writel(val, &phy0_ctrl->phy_con0);
 163                writel(val, &phy1_ctrl->phy_con0);
 164
 165                val = (mem->ctrl_start_point <<
 166                                PHY_CON12_CTRL_START_POINT_SHIFT) |
 167                        (mem->ctrl_inc << PHY_CON12_CTRL_INC_SHIFT) |
 168                        (mem->ctrl_force << PHY_CON12_CTRL_FORCE_SHIFT) |
 169                        (mem->ctrl_start << PHY_CON12_CTRL_START_SHIFT) |
 170                        (mem->ctrl_ref << PHY_CON12_CTRL_REF_SHIFT);
 171                writel(val, &phy0_ctrl->phy_con12);
 172                writel(val, &phy1_ctrl->phy_con12);
 173
 174                val = PHY_CON2_RESET_VAL;
 175                val |= INIT_DESKEW_EN;
 176                val |= RDLVL_GATE_EN;
 177                writel(val, &phy0_ctrl->phy_con2);
 178                writel(val, &phy1_ctrl->phy_con2);
 179
 180                val = PHY_CON0_RESET_VAL;
 181                val |= P0_CMD_EN;
 182                val |= BYTE_RDLVL_EN;
 183                val |= CTRL_SHGATE;
 184                writel(val, &phy0_ctrl->phy_con0);
 185                writel(val, &phy1_ctrl->phy_con0);
 186
 187                val = PHY_CON1_RESET_VAL;
 188                val &= ~(CTRL_GATEDURADJ_MASK);
 189                writel(val, &phy0_ctrl->phy_con1);
 190                writel(val, &phy1_ctrl->phy_con1);
 191
 192                writel(CTRL_RDLVL_GATE_ENABLE, &dmc->rdlvl_config);
 193                i = RDLVL_COMPLETE_TIMEOUT;
 194                while ((readl(&dmc->phystatus) &
 195                        (RDLVL_COMPLETE_CHO | RDLVL_COMPLETE_CH1)) !=
 196                        (RDLVL_COMPLETE_CHO | RDLVL_COMPLETE_CH1) && i > 0) {
 197                        /*
 198                         * TODO(waihong): Comment on how long this take to
 199                         * timeout
 200                         */
 201                        sdelay(100);
 202                        i--;
 203                }
 204                if (!i)
 205                        return SETUP_ERR_RDLV_COMPLETE_TIMEOUT;
 206                writel(CTRL_RDLVL_GATE_DISABLE, &dmc->rdlvl_config);
 207
 208                writel(0, &phy0_ctrl->phy_con14);
 209                writel(0, &phy1_ctrl->phy_con14);
 210
 211                val = (mem->ctrl_start_point <<
 212                                PHY_CON12_CTRL_START_POINT_SHIFT) |
 213                        (mem->ctrl_inc << PHY_CON12_CTRL_INC_SHIFT) |
 214                        (mem->ctrl_force << PHY_CON12_CTRL_FORCE_SHIFT) |
 215                        (mem->ctrl_start << PHY_CON12_CTRL_START_SHIFT) |
 216                        (mem->ctrl_dll_on << PHY_CON12_CTRL_DLL_ON_SHIFT) |
 217                        (mem->ctrl_ref << PHY_CON12_CTRL_REF_SHIFT);
 218                writel(val, &phy0_ctrl->phy_con12);
 219                writel(val, &phy1_ctrl->phy_con12);
 220
 221                update_reset_dll(dmc, DDR_MODE_DDR3);
 222        }
 223
 224        /* Send PALL command */
 225        dmc_config_prech(mem, dmc);
 226
 227        writel(mem->memcontrol, &dmc->memcontrol);
 228
 229        /* Set DMC Concontrol and enable auto-refresh counter */
 230        writel(mem->concontrol | (mem->rd_fetch << CONCONTROL_RD_FETCH_SHIFT)
 231                | (mem->aref_en << CONCONTROL_AREF_EN_SHIFT), &dmc->concontrol);
 232        return 0;
 233}
 234