[U-Boot] [PATCH 04/12 V3] Exynos5420: Add DDR3 initialization for 5420

Simon Glass sjg at chromium.org
Thu Sep 19 07:56:11 CEST 2013


On Wed, Sep 11, 2013 at 4:01 AM, Rajeshwari S Shinde <
rajeshwari.s at samsung.com> wrote:

> This patch intends to add DDR3 initialization code for Exynos5420.
>
> Signed-off-by: Rajeshwari S Shinde <rajeshwari.s at samsung.com>
> Signed-off-by: Akshay Saraswat <akshay.s at samsung.com>
>

A few nits in comments, but it looks reasonable.

Acked-by: Simon Glass <sjg at chromium.org>


> ---
> Changes in V2:
>         - Corrected a compilation issue for SMDK5250.
> Changes in V3:
>         - None
>  arch/arm/cpu/armv7/exynos/dmc_common.c    |   8 -
>  arch/arm/cpu/armv7/exynos/dmc_init_ddr3.c | 413
> +++++++++++++++++++++++++++++-
>  arch/arm/include/asm/arch-exynos/cpu.h    |   4 +
>  arch/arm/include/asm/arch-exynos/dmc.h    | 121 ++++++---
>  4 files changed, 503 insertions(+), 43 deletions(-)
>
> diff --git a/arch/arm/cpu/armv7/exynos/dmc_common.c
> b/arch/arm/cpu/armv7/exynos/dmc_common.c
> index 53cfe6e..882cd1e 100644
> --- a/arch/arm/cpu/armv7/exynos/dmc_common.c
> +++ b/arch/arm/cpu/armv7/exynos/dmc_common.c
> @@ -152,14 +152,6 @@ void dmc_config_prech(struct mem_timings *mem, struct
> exynos5_dmc *dmc)
>         }
>  }
>
> -void dmc_config_memory(struct mem_timings *mem, struct exynos5_dmc *dmc)
> -{
> -       writel(mem->memconfig, &dmc->memconfig0);
> -       writel(mem->memconfig, &dmc->memconfig1);
> -       writel(DMC_MEMBASECONFIG0_VAL, &dmc->membaseconfig0);
> -       writel(DMC_MEMBASECONFIG1_VAL, &dmc->membaseconfig1);
> -}
> -
>  void mem_ctrl_init(int reset)
>  {
>         struct spl_machine_param *param = spl_get_machine_params();
> diff --git a/arch/arm/cpu/armv7/exynos/dmc_init_ddr3.c
> b/arch/arm/cpu/armv7/exynos/dmc_init_ddr3.c
> index 5f5914e..0ca5350 100644
> --- a/arch/arm/cpu/armv7/exynos/dmc_init_ddr3.c
> +++ b/arch/arm/cpu/armv7/exynos/dmc_init_ddr3.c
> @@ -15,8 +15,9 @@
>  #include "exynos5_setup.h"
>  #include "clock_init.h"
>
> -#define RDLVL_COMPLETE_TIMEOUT 10000
> +#define TIMEOUT        10000
>
> +#ifdef CONFIG_EXYNOS5250
>  static void reset_phy_ctrl(void)
>  {
>         struct exynos5_clock *clk =
> @@ -108,7 +109,7 @@ int ddr3_mem_ctrl_init(struct mem_timings *mem,
> unsigned long mem_iv_size,
>
>         /* Precharge Configuration */
>         writel(mem->prechconfig_tp_cnt << PRECHCONFIG_TP_CNT_SHIFT,
> -              &dmc->prechconfig);
> +              &dmc->prechconfig0);
>
>         /* Power Down mode Configuration */
>         writel(mem->dpwrdn_cyc << PWRDNCONFIG_DPWRDN_CYC_SHIFT |
> @@ -174,7 +175,7 @@ int ddr3_mem_ctrl_init(struct mem_timings *mem,
> unsigned long mem_iv_size,
>                 writel(val, &phy1_ctrl->phy_con1);
>
>                 writel(CTRL_RDLVL_GATE_ENABLE, &dmc->rdlvl_config);
> -               i = RDLVL_COMPLETE_TIMEOUT;
> +               i = TIMEOUT;
>                 while ((readl(&dmc->phystatus) &
>                         (RDLVL_COMPLETE_CHO | RDLVL_COMPLETE_CH1)) !=
>                         (RDLVL_COMPLETE_CHO | RDLVL_COMPLETE_CH1) && i >
> 0) {
> @@ -215,3 +216,409 @@ int ddr3_mem_ctrl_init(struct mem_timings *mem,
> unsigned long mem_iv_size,
>                 | (mem->aref_en << CONCONTROL_AREF_EN_SHIFT),
> &dmc->concontrol);
>         return 0;
>  }
> +#endif
> +
> +#ifdef CONFIG_EXYNOS5420
> +int ddr3_mem_ctrl_init(struct mem_timings *mem, unsigned long mem_iv_size,
> +                      int reset)
> +{
> +       struct exynos5420_clock *clk =
> +               (struct exynos5420_clock *)EXYNOS5_CLOCK_BASE;
> +       struct exynos5_phy_control *phy0_ctrl, *phy1_ctrl;
> +       struct exynos5_dmc *drex0, *drex1;
> +       struct exynos5_tzasc *tzasc0, *tzasc1;
> +       uint32_t val, n_lock_r, n_lock_w_phy0, n_lock_w_phy1;
> +       int chip;
> +       int i;
> +
> +       phy0_ctrl = (struct exynos5_phy_control
> *)samsung_get_base_dmc_phy();
> +       phy1_ctrl = (struct exynos5_phy_control
> *)(samsung_get_base_dmc_phy()
> +                                                       + DMC_OFFSET);
> +       drex0 = (struct exynos5_dmc *)samsung_get_base_dmc_ctrl();
> +       drex1 = (struct exynos5_dmc *)(samsung_get_base_dmc_ctrl()
> +                                                       + DMC_OFFSET);
> +       tzasc0 = (struct exynos5_tzasc *)EXYNOS5420_DMC_TZASC0_BASE;
> +       tzasc1 = (struct exynos5_tzasc *)EXYNOS5420_DMC_TZASC1_BASE;
> +
> +       /* Enable PAUSE for DREX */
> +       setbits_le32(&clk->pause, ENABLE_BIT);
> +
> +       /* Enable BYPASS mode */
> +       setbits_le32(&clk->bpll_con1, BYPASS_EN);
> +
> +       writel(MUX_BPLL_SEL_FOUTBPLL, &clk->src_cdrex);
> +       do {
> +               val = readl(&clk->mux_stat_cdrex);
> +               val &= BPLL_SEL_MASK;
> +       } while (val != FOUTBPLL);
> +
> +       clrbits_le32(&clk->bpll_con1, BYPASS_EN);
> +
> +       /* Specify the DDR memory type as DDR3 */
> +       val = readl(&phy0_ctrl->phy_con0);
> +       val &= ~(PHY_CON0_CTRL_DDR_MODE_MASK <<
> PHY_CON0_CTRL_DDR_MODE_SHIFT);
> +       val |= (DDR_MODE_DDR3 << PHY_CON0_CTRL_DDR_MODE_SHIFT);
> +       writel(val, &phy0_ctrl->phy_con0);
> +
> +       val = readl(&phy1_ctrl->phy_con0);
> +       val &= ~(PHY_CON0_CTRL_DDR_MODE_MASK <<
> PHY_CON0_CTRL_DDR_MODE_SHIFT);
> +       val |= (DDR_MODE_DDR3 << PHY_CON0_CTRL_DDR_MODE_SHIFT);
> +       writel(val, &phy1_ctrl->phy_con0);
> +
> +       /* Set Read Latency and Burst Length for PHY0 and PHY1 */
> +       val = (mem->ctrl_bstlen << PHY_CON42_CTRL_BSTLEN_SHIFT) |
> +               (mem->ctrl_rdlat << PHY_CON42_CTRL_RDLAT_SHIFT);
> +       writel(val, &phy0_ctrl->phy_con42);
> +       writel(val, &phy1_ctrl->phy_con42);
> +
> +       val = readl(&phy0_ctrl->phy_con26);
> +       val &= ~(T_WRDATA_EN_MASK << T_WRDATA_EN_OFFSET);
> +       val |= (T_WRDATA_EN_DDR3 << T_WRDATA_EN_OFFSET);
> +       writel(val, &phy0_ctrl->phy_con26);
> +
> +       val = readl(&phy1_ctrl->phy_con26);
> +       val &= ~(T_WRDATA_EN_MASK << T_WRDATA_EN_OFFSET);
> +       val |= (T_WRDATA_EN_DDR3 << T_WRDATA_EN_OFFSET);
> +       writel(val, &phy1_ctrl->phy_con26);
> +
> +       /* Set Driver strength for CK, CKE, CS & CA to 0x7
>

Comment style

/*
 * Set Driver ...
 * ...
 */

Please fix globally.


> +        * Set Driver strength for Data Slice 0~3 to 0x7
> +        */
> +       val = (0x7 << CA_CK_DRVR_DS_OFFSET) | (0x7 <<
> CA_CKE_DRVR_DS_OFFSET) |
> +               (0x7 << CA_CS_DRVR_DS_OFFSET) | (0x7 <<
> CA_ADR_DRVR_DS_OFFSET);
> +       val |= (0x7 << DA_3_DS_OFFSET) | (0x7 << DA_2_DS_OFFSET) |
> +               (0x7 << DA_1_DS_OFFSET) | (0x7 << DA_0_DS_OFFSET);
> +       writel(val, &phy0_ctrl->phy_con39);
> +       writel(val, &phy1_ctrl->phy_con39);
> +
> +       /* ZQ Calibration */
> +       if (dmc_config_zq(mem, phy0_ctrl, phy1_ctrl))
> +               return SETUP_ERR_ZQ_CALIBRATION_FAILURE;
> +
> +       clrbits_le32(&phy0_ctrl->phy_con16, ZQ_CLK_DIV_EN);
> +       clrbits_le32(&phy1_ctrl->phy_con16, ZQ_CLK_DIV_EN);
> +
> +       /* DQ Signal */
> +       val = readl(&phy0_ctrl->phy_con14);
> +       val |= mem->phy0_pulld_dqs;
> +       writel(val, &phy0_ctrl->phy_con14);
> +       val = readl(&phy1_ctrl->phy_con14);
> +       val |= mem->phy1_pulld_dqs;
> +       writel(val, &phy1_ctrl->phy_con14);
> +
> +       val = MEM_TERM_EN | PHY_TERM_EN;
> +       writel(val, &drex0->phycontrol0);
> +       writel(val, &drex1->phycontrol0);
> +
> +       writel(mem->concontrol |
> +               (mem->dfi_init_start << CONCONTROL_DFI_INIT_START_SHIFT) |
> +               (mem->rd_fetch << CONCONTROL_RD_FETCH_SHIFT),
> +               &drex0->concontrol);
> +       writel(mem->concontrol |
> +               (mem->dfi_init_start << CONCONTROL_DFI_INIT_START_SHIFT) |
> +               (mem->rd_fetch << CONCONTROL_RD_FETCH_SHIFT),
> +               &drex1->concontrol);
> +
> +       do {
> +               val = readl(&drex0->phystatus);
> +       } while ((val & DFI_INIT_COMPLETE) != DFI_INIT_COMPLETE);
> +       do {
> +               val = readl(&drex1->phystatus);
> +       } while ((val & DFI_INIT_COMPLETE) != DFI_INIT_COMPLETE);
> +
> +       clrbits_le32(&drex0->concontrol, DFI_INIT_START);
> +       clrbits_le32(&drex1->concontrol, DFI_INIT_START);
> +
> +       update_reset_dll(drex0, DDR_MODE_DDR3);
> +       update_reset_dll(drex1, DDR_MODE_DDR3);
> +
> +       /* Set Base Address:
> +        * 0x2000_0000 ~ 0x5FFF_FFFF
> +        * 0x6000_0000 ~ 0x9FFF_FFFF
> +        */
> +       /* MEMBASECONFIG0 */
> +       val = DMC_MEMBASECONFIGX_CHIP_BASE(DMC_CHIP_BASE_0) |
> +               DMC_MEMBASECONFIGX_CHIP_MASK(DMC_CHIP_MASK);
> +       writel(val, &tzasc0->membaseconfig0);
> +       writel(val, &tzasc1->membaseconfig0);
> +
> +       /* MEMBASECONFIG1 */
> +       val = DMC_MEMBASECONFIGX_CHIP_BASE(DMC_CHIP_BASE_1) |
> +               DMC_MEMBASECONFIGX_CHIP_MASK(DMC_CHIP_MASK);
> +       writel(val, &tzasc0->membaseconfig1);
> +       writel(val, &tzasc1->membaseconfig1);
> +
> +       /* Memory Channel Inteleaving Size
> +        * Ares Channel interleaving = 128 bytes
> +        */
> +       /* MEMCONFIG0/1 */
> +       writel(mem->memconfig, &tzasc0->memconfig0);
> +       writel(mem->memconfig, &tzasc1->memconfig0);
> +       writel(mem->memconfig, &tzasc0->memconfig1);
> +       writel(mem->memconfig, &tzasc1->memconfig1);
> +
> +       /* Precharge Configuration */
> +       writel(mem->prechconfig_tp_cnt << PRECHCONFIG_TP_CNT_SHIFT,
> +              &drex0->prechconfig0);
> +       writel(mem->prechconfig_tp_cnt << PRECHCONFIG_TP_CNT_SHIFT,
> +              &drex1->prechconfig0);
> +
> +       /* TimingRow, TimingData, TimingPower and Timingaref
> +        * values as per Memory AC parameters
> +        */
> +       writel(mem->timing_ref, &drex0->timingref);
> +       writel(mem->timing_ref, &drex1->timingref);
> +       writel(mem->timing_row, &drex0->timingrow);
> +       writel(mem->timing_row, &drex1->timingrow);
> +       writel(mem->timing_data, &drex0->timingdata);
> +       writel(mem->timing_data, &drex1->timingdata);
> +       writel(mem->timing_power, &drex0->timingpower);
> +       writel(mem->timing_power, &drex1->timingpower);
> +
> +       if (reset) {
> +               /* Send NOP, MRS and ZQINIT commands
> +                * Sending MRS command will reset the DRAM. We should not
> be
> +                * reseting the DRAM after resume, this will lead to memory
> +                * corruption as DRAM content is lost after DRAM reset
> +                */
> +               dmc_config_mrs(mem, drex0);
> +               dmc_config_mrs(mem, drex1);
> +       } else {
> +               /*
> +                * During Suspend-Resume & S/W-Reset, as soon as PMU
> releases
> +                * pad retention, CKE goes high. This causes memory
> contents
> +                * not to be retained during DRAM initialization. Therfore,
> +                * there is a new control register(0x100431e8[28]) which
> lets us
> +                * release pad retention and retain the memory content
> until the
> +                * initialization is complete.
> +                */
> +               writel(PAD_RETENTION_DRAM_COREBLK_VAL,
> +                      PAD_RETENTION_DRAM_COREBLK_OPTION);
> +               do {
> +                       val = readl(PAD_RETENTION_DRAM_STATUS);
> +               } while (val != 0x1);
> +
> +               /*
> +                * CKE PAD retention disables DRAM self-refresh mode.
> +                * Send auto refresh command for DRAM refresh.
> +                */
> +               for (i = 0; i < 128; i++) {
> +                       for (chip = 0; chip < mem->chips_to_configure;
> chip++) {
> +                               writel(DIRECT_CMD_REFA |
> +                                      (chip << DIRECT_CMD_CHIP_SHIFT),
> +                                      &drex0->directcmd);
> +                               writel(DIRECT_CMD_REFA |
> +                                      (chip << DIRECT_CMD_CHIP_SHIFT),
> +                                      &drex1->directcmd);
> +                       }
> +               }
> +       }
> +
> +       if (mem->gate_leveling_enable) {
> +               writel(PHY_CON0_RESET_VAL, &phy0_ctrl->phy_con0);
> +               writel(PHY_CON0_RESET_VAL, &phy1_ctrl->phy_con0);
> +
> +               setbits_le32(&phy0_ctrl->phy_con0, P0_CMD_EN);
> +               setbits_le32(&phy1_ctrl->phy_con0, P0_CMD_EN);
> +
> +               val = PHY_CON2_RESET_VAL;
> +               val |= INIT_DESKEW_EN;
> +               writel(val, &phy0_ctrl->phy_con2);
> +               writel(val, &phy1_ctrl->phy_con2);
> +
> +               val =  readl(&phy0_ctrl->phy_con1);
> +               val |= (RDLVL_PASS_ADJ_VAL << RDLVL_PASS_ADJ_OFFSET);
> +               writel(val, &phy0_ctrl->phy_con1);
> +
> +               val =  readl(&phy1_ctrl->phy_con1);
> +               val |= (RDLVL_PASS_ADJ_VAL << RDLVL_PASS_ADJ_OFFSET);
> +               writel(val, &phy1_ctrl->phy_con1);
> +
> +               n_lock_r = readl(&phy0_ctrl->phy_con13);
> +               n_lock_w_phy0 = (n_lock_r & CTRL_LOCK_COARSE_MASK) >> 2;
> +               n_lock_r = readl(&phy0_ctrl->phy_con12);
> +               n_lock_r &= ~CTRL_DLL_ON;
> +               n_lock_r |= n_lock_w_phy0;
> +               writel(n_lock_r, &phy0_ctrl->phy_con12);
> +
> +               n_lock_r = readl(&phy1_ctrl->phy_con13);
> +               n_lock_w_phy1 = (n_lock_r & CTRL_LOCK_COARSE_MASK) >> 2;
> +               n_lock_r = readl(&phy1_ctrl->phy_con12);
> +               n_lock_r &= ~CTRL_DLL_ON;
> +               n_lock_r |= n_lock_w_phy1;
> +               writel(n_lock_r, &phy1_ctrl->phy_con12);
> +
> +               val = (0x3 << DIRECT_CMD_BANK_SHIFT) | 0x4;
> +               for (chip = 0; chip < mem->chips_to_configure; chip++) {
> +                       writel(val | (chip << DIRECT_CMD_CHIP_SHIFT),
> +                              &drex0->directcmd);
> +                       writel(val | (chip << DIRECT_CMD_CHIP_SHIFT),
> +                              &drex1->directcmd);
> +               }
> +
> +               setbits_le32(&phy0_ctrl->phy_con2, RDLVL_GATE_EN);
> +               setbits_le32(&phy1_ctrl->phy_con2, RDLVL_GATE_EN);
> +
> +               setbits_le32(&phy0_ctrl->phy_con0, CTRL_SHGATE);
> +               setbits_le32(&phy1_ctrl->phy_con0, CTRL_SHGATE);
> +
> +               val = readl(&phy0_ctrl->phy_con1);
> +               val &= ~(CTRL_GATEDURADJ_MASK);
> +               writel(val, &phy0_ctrl->phy_con1);
> +
> +               val = readl(&phy1_ctrl->phy_con1);
> +               val &= ~(CTRL_GATEDURADJ_MASK);
> +               writel(val, &phy1_ctrl->phy_con1);
> +
> +               writel(CTRL_RDLVL_GATE_ENABLE, &drex0->rdlvl_config);
> +               i = TIMEOUT;
> +               while (((readl(&drex0->phystatus) & RDLVL_COMPLETE_CHO) !=
> +                       RDLVL_COMPLETE_CHO) && (i > 0)) {
> +                       /*
> +                        * TODO(waihong): Comment on how long this take to
> +                        * timeout
> +                        */
> +                       sdelay(100);
> +                       i--;
> +               }
> +               if (!i)
> +                       return SETUP_ERR_RDLV_COMPLETE_TIMEOUT;
> +               writel(CTRL_RDLVL_GATE_DISABLE, &drex0->rdlvl_config);
> +
> +               writel(CTRL_RDLVL_GATE_ENABLE, &drex1->rdlvl_config);
> +               i = TIMEOUT;
> +               while (((readl(&drex1->phystatus) & RDLVL_COMPLETE_CHO) !=
> +                       RDLVL_COMPLETE_CHO) && (i > 0)) {
> +                       /*
> +                        * TODO(waihong): Comment on how long this take to
> +                        * timeout
> +                        */
> +                       sdelay(100);
> +                       i--;
> +               }
> +               if (!i)
> +                       return SETUP_ERR_RDLV_COMPLETE_TIMEOUT;
> +               writel(CTRL_RDLVL_GATE_DISABLE, &drex1->rdlvl_config);
> +
> +               writel(0, &phy0_ctrl->phy_con14);
> +               writel(0, &phy1_ctrl->phy_con14);
> +
> +               val = (0x3 << DIRECT_CMD_BANK_SHIFT);
> +               for (chip = 0; chip < mem->chips_to_configure; chip++) {
> +                       writel(val | (chip << DIRECT_CMD_CHIP_SHIFT),
> +                              &drex0->directcmd);
> +                       writel(val | (chip << DIRECT_CMD_CHIP_SHIFT),
> +                              &drex1->directcmd);
> +               }
> +
> +               if (mem->read_leveling_enable) {
> +                       /* Set Read DQ Calibration */
> +                       val = (0x3 << DIRECT_CMD_BANK_SHIFT) | 0x4;
> +                       for (chip = 0; chip < mem->chips_to_configure;
> chip++) {
> +                               writel(val | (chip <<
> DIRECT_CMD_CHIP_SHIFT),
> +                                      &drex0->directcmd);
> +                               writel(val | (chip <<
> DIRECT_CMD_CHIP_SHIFT),
> +                                      &drex1->directcmd);
> +                       }
> +
> +                       val = readl(&phy0_ctrl->phy_con1);
> +                       val |= READ_LEVELLING_DDR3;
> +                       writel(val, &phy0_ctrl->phy_con1);
> +                       val = readl(&phy1_ctrl->phy_con1);
> +                       val |= READ_LEVELLING_DDR3;
> +                       writel(val, &phy1_ctrl->phy_con1);
> +
> +                       val = readl(&phy0_ctrl->phy_con2);
> +                       val |= (RDLVL_EN | RDLVL_INCR_ADJ);
> +                       writel(val, &phy0_ctrl->phy_con2);
> +                       val = readl(&phy1_ctrl->phy_con2);
> +                       val |= (RDLVL_EN | RDLVL_INCR_ADJ);
> +                       writel(val, &phy1_ctrl->phy_con2);
> +
> +                       setbits_le32(&drex0->rdlvl_config,
> +                                    CTRL_RDLVL_DATA_ENABLE);
> +                       i = TIMEOUT;
> +                       while (((readl(&drex0->phystatus) &
> RDLVL_COMPLETE_CHO)
> +                                != RDLVL_COMPLETE_CHO) && (i > 0)) {
> +                               /*
> +                                * TODO(waihong): Comment on how long this
> take
> +                                * to timeout
> +                                */
> +                               sdelay(100);
> +                               i--;
> +                       }
> +                       if (!i)
> +                               return SETUP_ERR_RDLV_COMPLETE_TIMEOUT;
> +
> +                       clrbits_le32(&drex0->rdlvl_config,
> +                                    CTRL_RDLVL_DATA_ENABLE);
> +                       setbits_le32(&drex1->rdlvl_config,
> +                                    CTRL_RDLVL_DATA_ENABLE);
> +                       i = TIMEOUT;
> +                       while (((readl(&drex1->phystatus) &
> RDLVL_COMPLETE_CHO)
> +                                != RDLVL_COMPLETE_CHO) && (i > 0)) {
> +                               /*
> +                                * TODO(waihong): Comment on how long this
> take
> +                                * to timeout
> +                                */
> +                               sdelay(100);
> +                               i--;
> +                       }
> +                       if (!i)
> +                               return SETUP_ERR_RDLV_COMPLETE_TIMEOUT;
> +
> +                       clrbits_le32(&drex1->rdlvl_config,
> +                                    CTRL_RDLVL_DATA_ENABLE);
> +
> +                       val = (0x3 << DIRECT_CMD_BANK_SHIFT);
> +                       for (chip = 0; chip < mem->chips_to_configure;
> chip++) {
> +                               writel(val | (chip <<
> DIRECT_CMD_CHIP_SHIFT),
> +                                      &drex0->directcmd);
> +                               writel(val | (chip <<
> DIRECT_CMD_CHIP_SHIFT),
> +                                      &drex1->directcmd);
> +                       }
> +
> +                       update_reset_dll(drex0, DDR_MODE_DDR3);
> +                       update_reset_dll(drex1, DDR_MODE_DDR3);
> +               }
> +
> +               /* Common Settings for Leveling */
> +               val = PHY_CON12_RESET_VAL;
> +               writel((val + n_lock_w_phy0), &phy0_ctrl->phy_con12);
> +               writel((val + n_lock_w_phy1), &phy1_ctrl->phy_con12);
> +
> +               setbits_le32(&phy0_ctrl->phy_con2, DLL_DESKEW_EN);
> +               setbits_le32(&phy1_ctrl->phy_con2, DLL_DESKEW_EN);
> +       }
> +
> +       /* Send PALL command */
> +       dmc_config_prech(mem, drex0);
> +       dmc_config_prech(mem, drex1);
> +
> +       writel(mem->memcontrol, &drex0->memcontrol);
> +       writel(mem->memcontrol, &drex1->memcontrol);
> +
> +       /*
> +        * Set DMC Concontrol: Enable auto-refresh counter, provide
> +        * read data fetch cycles and enable DREX auto set powerdown
> +        * for input buffer of I/O in none read memory state.
> +        */
> +       writel(mem->concontrol | (mem->aref_en <<
> CONCONTROL_AREF_EN_SHIFT) |
> +               (mem->rd_fetch << CONCONTROL_RD_FETCH_SHIFT)|
> +               DMC_CONCONTROL_IO_PD_CON(0x2),
> +               &drex0->concontrol);
> +       writel(mem->concontrol | (mem->aref_en <<
> CONCONTROL_AREF_EN_SHIFT) |
> +               (mem->rd_fetch << CONCONTROL_RD_FETCH_SHIFT)|
> +               DMC_CONCONTROL_IO_PD_CON(0x2),
> +               &drex1->concontrol);
> +
> +       /* Enable Clock Gating Control for DMC
> +        * this saves around 25 mw dmc power as compared to the power
> +        * consumption without these bits enabled
> +        */
> +       setbits_le32(&drex0->cgcontrol, DMC_INTERNAL_CG);
> +       setbits_le32(&drex1->cgcontrol, DMC_INTERNAL_CG);
> +
> +       return 0;
> +}
> +#endif
> diff --git a/arch/arm/include/asm/arch-exynos/cpu.h
> b/arch/arm/include/asm/arch-exynos/cpu.h
> index e988251..a110240 100644
> --- a/arch/arm/include/asm/arch-exynos/cpu.h
> +++ b/arch/arm/include/asm/arch-exynos/cpu.h
> @@ -160,6 +160,10 @@
>  #define EXYNOS5420_MODEM_BASE          DEVICE_NOT_AVAILABLE
>  #define EXYNOS5420_TZPC_BASE           DEVICE_NOT_AVAILABLE
>
> +#define PAD_RETENTION_DRAM_STATUS      (EXYNOS5420_POWER_BASE + 0x3004)
> +#define PAD_RETENTION_DRAM_COREBLK_OPTION      (EXYNOS5420_POWER_BASE +
> 0x31E8)
> +#define PAD_RETENTION_DRAM_COREBLK_VAL 0x10000000
> +
>  #ifndef __ASSEMBLY__
>  #include <asm/io.h>
>  /* CPU detection macros */
> diff --git a/arch/arm/include/asm/arch-exynos/dmc.h
> b/arch/arm/include/asm/arch-exynos/dmc.h
> index f65c676..b947de1 100644
> --- a/arch/arm/include/asm/arch-exynos/dmc.h
> +++ b/arch/arm/include/asm/arch-exynos/dmc.h
> @@ -114,13 +114,22 @@ struct exynos4_dmc {
>  struct exynos5_dmc {
>         unsigned int concontrol;
>         unsigned int memcontrol;
> +
> +/* Between 5250 and 5420, the DMC Register differs only at 0x8 offset.
> + * So to use the same structure and simplify the code put a define to
> + * distinguish between memconfig0 and cgcontrol register */
> +#ifdef CONFIG_EXYNOS5250
>         unsigned int memconfig0;
> +#else
> +       unsigned int cgcontrol;
> +#endif
>

It would be nice to be able to build an SPL that works on both 5250 and
5420, but that can wait...



>         unsigned int memconfig1;
>         unsigned int directcmd;
> -       unsigned int prechconfig;
> +       unsigned int prechconfig0;
>         unsigned int phycontrol0;
> -       unsigned char res1[0xc];
> -       unsigned int pwrdnconfig;
> +       unsigned int prechconfig1;
> +       unsigned char res1[0x8];
> +       unsigned int pwrdnconfig;       /* 0x0028*/
>         unsigned int timingpzq;
>         unsigned int timingref;
>         unsigned int timingrow;
> @@ -128,12 +137,12 @@ struct exynos5_dmc {
>         unsigned int timingpower;
>         unsigned int phystatus;
>         unsigned char res2[0x4];
> -       unsigned int chipstatus_ch0;
> +       unsigned int chipstatus_ch0;    /* 0x0048 */
>         unsigned int chipstatus_ch1;
>         unsigned char res3[0x4];
>         unsigned int mrstatus;
>         unsigned char res4[0x8];
> -       unsigned int qoscontrol0;
> +       unsigned int qoscontrol0;       /* 0x0060 */
>         unsigned char resr5[0x4];
>         unsigned int qoscontrol1;
>         unsigned char res6[0x4];
> @@ -164,45 +173,83 @@ struct exynos5_dmc {
>         unsigned int qoscontrol14;
>         unsigned char res19[0x4];
>         unsigned int qoscontrol15;
> -       unsigned char res20[0x14];
> +       unsigned char res20[0x4];
> +       unsigned int timing_set_sw;     /* 0x00e0 */
> +       unsigned int timingrow1;
> +       unsigned int timingdata1;
> +       unsigned int timingpower1;
>         unsigned int ivcontrol;
>         unsigned int wrtra_config;
>         unsigned int rdlvl_config;
> -       unsigned char res21[0x8];
> +       unsigned char res21[0x4];
> +       unsigned int brbrsvcontrol;     /* 0x0100*/
>         unsigned int brbrsvconfig;
>         unsigned int brbqosconfig;
>         unsigned int membaseconfig0;
> -       unsigned int membaseconfig1;
> +       unsigned int membaseconfig1;    /* 0x0110 */
>         unsigned char res22[0xc];
> -       unsigned int wrlvl_config;
> -       unsigned char res23[0xc];
> -       unsigned int perevcontrol;
> +       unsigned int wrlvl_config0;     /* 0x0120 */
> +       unsigned int wrlvl_config1;
> +       unsigned int wrlvl_status;
> +       unsigned char res23[0x4];
> +       unsigned int perevcontrol;      /* 0x0130 */
>         unsigned int perev0config;
>         unsigned int perev1config;
>         unsigned int perev2config;
>         unsigned int perev3config;
> -       unsigned char res24[0xdebc];
> -       unsigned int pmnc_ppc_a;
> -       unsigned char res25[0xc];
> -       unsigned int cntens_ppc_a;
> -       unsigned char res26[0xc];
> -       unsigned int cntenc_ppc_a;
> -       unsigned char res27[0xc];
> -       unsigned int intens_ppc_a;
> -       unsigned char res28[0xc];
> -       unsigned int intenc_ppc_a;
> -       unsigned char res29[0xc];
> -       unsigned int flag_ppc_a;
> -       unsigned char res30[0xac];
> -       unsigned int ccnt_ppc_a;
> -       unsigned char res31[0xc];
> -       unsigned int pmcnt0_ppc_a;
> +       unsigned char res22a[0xc];
> +       unsigned int ctrl_io_rdata_ch0;
> +       unsigned int ctrl_io_rdata_ch1;
> +       unsigned char res23a[0x8];
> +       unsigned int cacal_config0;
> +       unsigned int cacal_config1;
> +       unsigned int cacal_status;
> +       unsigned char res24[0x94];
> +       unsigned int emergent_config0;  /* 0x0200 */
> +       unsigned int emergent_config1;
> +       unsigned char res25[0x8];
> +       unsigned int bp_control0;
> +       unsigned int bp_control0_r;
> +       unsigned int bp_control0_w;
> +       unsigned char res26[0x4];
> +       unsigned int bp_control1;
> +       unsigned int bp_control1_r;
> +       unsigned int bp_control1_w;
> +       unsigned char res27[0x4];
> +       unsigned int bp_control2;
> +       unsigned int bp_control2_r;
> +       unsigned int bp_control2_w;
> +       unsigned char res28[0x4];
> +       unsigned int bp_control3;
> +       unsigned int bp_control3_r;
> +       unsigned int bp_control3_w;
> +       unsigned char res29[0xb4];
> +       unsigned int winconfig_odt_w;   /* 0x0300 */
> +       unsigned char res30[0x4];
> +       unsigned int winconfig_ctrl_read;
> +       unsigned int winconfig_ctrl_gate;
> +       unsigned char res31[0xdcf0];
> +       unsigned int pmnc_ppc;
>         unsigned char res32[0xc];
> -       unsigned int pmcnt1_ppc_a;
> +       unsigned int cntens_ppc;
>         unsigned char res33[0xc];
> -       unsigned int pmcnt2_ppc_a;
> +       unsigned int cntenc_ppc;
>         unsigned char res34[0xc];
> -       unsigned int pmcnt3_ppc_a;
> +       unsigned int intens_ppc;
> +       unsigned char res35[0xc];
> +       unsigned int intenc_ppc;
> +       unsigned char res36[0xc];
> +       unsigned int flag_ppc;          /* 0xe050 */
> +       unsigned char res37[0xac];
> +       unsigned int ccnt_ppc;
> +       unsigned char res38[0xc];
> +       unsigned int pmcnt0_ppc;
> +       unsigned char res39[0xc];
> +       unsigned int pmcnt1_ppc;
> +       unsigned char res40[0xc];
> +       unsigned int pmcnt2_ppc;
> +       unsigned char res41[0xc];
> +       unsigned int pmcnt3_ppc;        /* 0xe140 */
>  };
>
>  struct exynos5_phy_control {
> @@ -211,13 +258,13 @@ struct exynos5_phy_control {
>         unsigned int phy_con2;
>         unsigned int phy_con3;
>         unsigned int phy_con4;
> -       unsigned char res1[4];
> +       unsigned int phy_con5;
>         unsigned int phy_con6;
>         unsigned char res2[4];
>         unsigned int phy_con8;
>         unsigned int phy_con9;
>         unsigned int phy_con10;
> -       unsigned char res3[4];
> +       unsigned int phy_con11;
>         unsigned int phy_con12;
>         unsigned int phy_con13;
>         unsigned int phy_con14;
> @@ -252,6 +299,15 @@ struct exynos5_phy_control {
>         unsigned int phy_con42;
>  };
>
> +struct exynos5_tzasc {
> +       unsigned char res1[0xf00];
> +       unsigned int membaseconfig0;
> +       unsigned int membaseconfig1;
> +       unsigned char res2[0x8];
> +       unsigned int memconfig0;
> +       unsigned int memconfig1;
> +};
> +
>  enum ddr_mode {
>         DDR_MODE_DDR2,
>         DDR_MODE_DDR3,
> @@ -286,6 +342,7 @@ enum mem_manuf {
>  #define PHY_CON0_T_WRRDCMD_SHIFT       17
>  #define PHY_CON0_T_WRRDCMD_MASK                (0x7 <<
> PHY_CON0_T_WRRDCMD_SHIFT)
>  #define PHY_CON0_CTRL_DDR_MODE_SHIFT   11
> +#define PHY_CON0_CTRL_DDR_MODE_MASK    0x3
>
>  /* PHY_CON1 register fields */
>  #define PHY_CON1_RDLVL_RDDATA_ADJ_SHIFT        0
> --
> 1.7.12.4
>
>


More information about the U-Boot mailing list