Message ID | 1385984858-30816-5-git-send-email-rajeshwari.s@samsung.com |
---|---|
State | New |
Headers | show |
Dear Rajeshwari S Shinde, On 02/12/13 20:47, Rajeshwari S Shinde wrote: > This patch intends to add DDR3 initialization code for Exynos5420. > > Signed-off-by: Rajeshwari S Shinde <rajeshwari.s@samsung.com> > Signed-off-by: Akshay Saraswat <akshay.s@samsung.com> > Acked-by: Simon Glass <sjg@chromium.org> > --- > Changes in V2: > - Corrected a compilation issue for SMDK5250. > Changes in V3: > - None > Changes in V4: > - None > Changes in V5: > - None > Changes in V6: > - None > Changes in V7: > - Fixed multi line comment. > Changes in V8: > - None > Changes in V9: > - Used samsung_get base to get the dmc base address > arch/arm/cpu/armv7/exynos/dmc_common.c | 10 +- > arch/arm/cpu/armv7/exynos/dmc_init_ddr3.c | 425 +++++++++++++++++++++++++++++- > arch/arm/cpu/armv7/exynos/exynos5_setup.h | 2 + > arch/arm/include/asm/arch-exynos/cpu.h | 4 + > arch/arm/include/asm/arch-exynos/dmc.h | 123 ++++++--- > arch/arm/include/asm/arch-exynos/power.h | 6 + > 6 files changed, 525 insertions(+), 45 deletions(-) > > diff --git a/arch/arm/cpu/armv7/exynos/dmc_common.c b/arch/arm/cpu/armv7/exynos/dmc_common.c > index 53cfe6e..9e432c2 100644 > --- a/arch/arm/cpu/armv7/exynos/dmc_common.c > +++ b/arch/arm/cpu/armv7/exynos/dmc_common.c > @@ -1,5 +1,5 @@ > /* > - * Mem setup common file for different types of DDR present on SMDK5250 boards. > + * Mem setup common file for different types of DDR present on Exynos boards. > * > * Copyright (C) 2012 Samsung Electronics > * > @@ -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..aa46a43 100644 > --- a/arch/arm/cpu/armv7/exynos/dmc_init_ddr3.c > +++ b/arch/arm/cpu/armv7/exynos/dmc_init_ddr3.c > @@ -1,5 +1,5 @@ > /* > - * DDR3 mem setup file for SMDK5250 board based on EXYNOS5 > + * DDR3 mem setup file for board based on EXYNOS5 > * > * Copyright (C) 2012 Samsung Electronics > * > @@ -11,12 +11,14 @@ > #include <asm/arch/clock.h> > #include <asm/arch/cpu.h> > #include <asm/arch/dmc.h> > +#include <asm/arch/power.h> > #include "common_setup.h" > #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 +110,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 +176,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 +217,418 @@ 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 we can avoid ifdef here. int ddr3_mem_ctrl_init(...) { if (proid_is_exynos5250()) exynos5250_ddr3_mem_ctrl_init(); else exynos5420_ddr3_mem_ctrl_init(); } > +int ddr3_mem_ctrl_init(struct mem_timings *mem, unsigned long mem_iv_size, > + int reset) > +{ > + struct exynos5420_clock *clk = > + (struct exynos5420_clock *)samsung_get_base_clock(); > + struct exynos5_power *power = > + (struct exynos5_power *)samsung_get_base_power(); > + 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 *)samsung_get_base_dmc_tzasc0(); > + tzasc1 = (struct exynos5_tzasc *)(samsung_get_base_dmc_tzasc0() > + + DMC_OFFSET); > + > + /* 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 > + * 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, > + &power->pad_retention_dram_coreblk_option); > + do { > + val = readl(&power->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/cpu/armv7/exynos/exynos5_setup.h b/arch/arm/cpu/armv7/exynos/exynos5_setup.h > index c8d6515..42a7fb8 100644 > --- a/arch/arm/cpu/armv7/exynos/exynos5_setup.h > +++ b/arch/arm/cpu/armv7/exynos/exynos5_setup.h > @@ -436,6 +436,7 @@ > */ > #ifndef CONFIG_SMDK5420 > > + unnecessary blank line. > /* APLL_CON1 */ > #define APLL_CON1_VAL (0x00203800) > > @@ -696,6 +697,7 @@ > #define CLK_DIV_CPERI1_VAL NOT_AVAILABLE > > #else > +#define PAD_RETENTION_DRAM_COREBLK_VAL 0x10000000 > > /* APLL_CON1 */ > #define APLL_CON1_VAL (0x0020F300) > diff --git a/arch/arm/include/asm/arch-exynos/cpu.h b/arch/arm/include/asm/arch-exynos/cpu.h > index 2b44210..2c642ba 100644 > --- a/arch/arm/include/asm/arch-exynos/cpu.h > +++ b/arch/arm/include/asm/arch-exynos/cpu.h > @@ -53,6 +53,7 @@ > #define EXYNOS4_AUDIOSS_BASE DEVICE_NOT_AVAILABLE > #define EXYNOS4_USB_HOST_XHCI_BASE DEVICE_NOT_AVAILABLE > #define EXYNOS4_USB3PHY_BASE DEVICE_NOT_AVAILABLE > +#define EXYNOS4_DMC_TZASC0_BASE DEVICE_NOT_AVAILABLE > > /* EXYNOS4X12 */ > #define EXYNOS4X12_GPIO_PART3_BASE 0x03860000 > @@ -91,6 +92,7 @@ > #define EXYNOS4X12_AUDIOSS_BASE DEVICE_NOT_AVAILABLE > #define EXYNOS4X12_USB_HOST_XHCI_BASE DEVICE_NOT_AVAILABLE > #define EXYNOS4X12_USB3PHY_BASE DEVICE_NOT_AVAILABLE > +#define EXYNOS4X12_DMC_TZASC0_BASE DEVICE_NOT_AVAILABLE > > /* EXYNOS5 */ > #define EXYNOS5_I2C_SPACING 0x10000 > @@ -129,6 +131,7 @@ > > #define EXYNOS5_ADC_BASE DEVICE_NOT_AVAILABLE > #define EXYNOS5_MODEM_BASE DEVICE_NOT_AVAILABLE > +#define EXYNOS5_DMC_TZASC0_BASE DEVICE_NOT_AVAILABLE > > /* EXYNOS5420 */ > #define EXYNOS5420_AUDIOSS_BASE 0x03810000 > @@ -284,6 +287,7 @@ SAMSUNG_BASE(spi_isp, SPI_ISP_BASE) > SAMSUNG_BASE(tzpc, TZPC_BASE) > SAMSUNG_BASE(dmc_ctrl, DMC_CTRL_BASE) > SAMSUNG_BASE(dmc_phy, DMC_PHY_BASE) > +SAMSUNG_BASE(dmc_tzasc0, DMC_TZASC0_BASE) then do we need to define two base addresses for TZASC? you never use TZASC1. > SAMSUNG_BASE(audio_ass, AUDIOSS_BASE) > #endif > > diff --git a/arch/arm/include/asm/arch-exynos/dmc.h b/arch/arm/include/asm/arch-exynos/dmc.h > index f65c676..0913299 100644 > --- a/arch/arm/include/asm/arch-exynos/dmc.h > +++ b/arch/arm/include/asm/arch-exynos/dmc.h > @@ -114,13 +114,24 @@ 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 No. we don't allow ifdef. > unsigned int memconfig0; > +#else > + unsigned int cgcontrol; > +#endif > 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 +139,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 +175,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 +260,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 +301,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 +344,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 > diff --git a/arch/arm/include/asm/arch-exynos/power.h b/arch/arm/include/asm/arch-exynos/power.h > index 8db18c5..6077fc3 100644 > --- a/arch/arm/include/asm/arch-exynos/power.h > +++ b/arch/arm/include/asm/arch-exynos/power.h > @@ -690,9 +690,15 @@ struct exynos5_power { > unsigned int pad_retention_spi_status; > unsigned int pad_retention_spi_option; > unsigned char res117[0x14]; > + #ifdef CONFIG_EXYNOS5250 ditto. > unsigned int pad_retention_gpio_dmc_configuration; > unsigned int pad_retention_gpio_dmc_status; > unsigned int pad_retention_gpio_dmc_option; > + #else > + unsigned int pad_retention_dram_coreblk_configuration; > + unsigned int pad_retention_dram_coreblk_status; > + unsigned int pad_retention_dram_coreblk_option; > + #endif > unsigned char res118[0x14]; > unsigned int pad_isolation_configuration; > unsigned int pad_isolation_status; > Thanks, Minkyu Kang.
Hi Minkyu Kang, Thank you for comments. On Tue, Dec 3, 2013 at 11:45 AM, Minkyu Kang <mk7.kang@samsung.com> wrote: > Dear Rajeshwari S Shinde, > > On 02/12/13 20:47, Rajeshwari S Shinde wrote: >> This patch intends to add DDR3 initialization code for Exynos5420. >> >> Signed-off-by: Rajeshwari S Shinde <rajeshwari.s@samsung.com> >> Signed-off-by: Akshay Saraswat <akshay.s@samsung.com> >> Acked-by: Simon Glass <sjg@chromium.org> >> --- >> Changes in V2: >> - Corrected a compilation issue for SMDK5250. >> Changes in V3: >> - None >> Changes in V4: >> - None >> Changes in V5: >> - None >> Changes in V6: >> - None >> Changes in V7: >> - Fixed multi line comment. >> Changes in V8: >> - None >> Changes in V9: >> - Used samsung_get base to get the dmc base address >> arch/arm/cpu/armv7/exynos/dmc_common.c | 10 +- >> arch/arm/cpu/armv7/exynos/dmc_init_ddr3.c | 425 +++++++++++++++++++++++++++++- >> arch/arm/cpu/armv7/exynos/exynos5_setup.h | 2 + >> arch/arm/include/asm/arch-exynos/cpu.h | 4 + >> arch/arm/include/asm/arch-exynos/dmc.h | 123 ++++++--- >> arch/arm/include/asm/arch-exynos/power.h | 6 + >> 6 files changed, 525 insertions(+), 45 deletions(-) >> >> diff --git a/arch/arm/cpu/armv7/exynos/dmc_common.c b/arch/arm/cpu/armv7/exynos/dmc_common.c >> index 53cfe6e..9e432c2 100644 >> --- a/arch/arm/cpu/armv7/exynos/dmc_common.c >> +++ b/arch/arm/cpu/armv7/exynos/dmc_common.c >> @@ -1,5 +1,5 @@ >> /* >> - * Mem setup common file for different types of DDR present on SMDK5250 boards. >> + * Mem setup common file for different types of DDR present on Exynos boards. >> * >> * Copyright (C) 2012 Samsung Electronics >> * >> @@ -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..aa46a43 100644 >> --- a/arch/arm/cpu/armv7/exynos/dmc_init_ddr3.c >> +++ b/arch/arm/cpu/armv7/exynos/dmc_init_ddr3.c >> @@ -1,5 +1,5 @@ >> /* >> - * DDR3 mem setup file for SMDK5250 board based on EXYNOS5 >> + * DDR3 mem setup file for board based on EXYNOS5 >> * >> * Copyright (C) 2012 Samsung Electronics >> * >> @@ -11,12 +11,14 @@ >> #include <asm/arch/clock.h> >> #include <asm/arch/cpu.h> >> #include <asm/arch/dmc.h> >> +#include <asm/arch/power.h> >> #include "common_setup.h" >> #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 +110,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 +176,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 +217,418 @@ 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 > > we can avoid ifdef here. > > int ddr3_mem_ctrl_init(...) > { > if (proid_is_exynos5250()) > exynos5250_ddr3_mem_ctrl_init(); > else > exynos5420_ddr3_mem_ctrl_init(); > } > Will do it this way >> +int ddr3_mem_ctrl_init(struct mem_timings *mem, unsigned long mem_iv_size, >> + int reset) >> +{ >> + struct exynos5420_clock *clk = >> + (struct exynos5420_clock *)samsung_get_base_clock(); >> + struct exynos5_power *power = >> + (struct exynos5_power *)samsung_get_base_power(); >> + 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 *)samsung_get_base_dmc_tzasc0(); >> + tzasc1 = (struct exynos5_tzasc *)(samsung_get_base_dmc_tzasc0() >> + + DMC_OFFSET); >> + >> + /* 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 >> + * 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, >> + &power->pad_retention_dram_coreblk_option); >> + do { >> + val = readl(&power->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/cpu/armv7/exynos/exynos5_setup.h b/arch/arm/cpu/armv7/exynos/exynos5_setup.h >> index c8d6515..42a7fb8 100644 >> --- a/arch/arm/cpu/armv7/exynos/exynos5_setup.h >> +++ b/arch/arm/cpu/armv7/exynos/exynos5_setup.h >> @@ -436,6 +436,7 @@ >> */ >> #ifndef CONFIG_SMDK5420 >> >> + > > unnecessary blank line. will remove this > >> /* APLL_CON1 */ >> #define APLL_CON1_VAL (0x00203800) >> >> @@ -696,6 +697,7 @@ >> #define CLK_DIV_CPERI1_VAL NOT_AVAILABLE >> >> #else >> +#define PAD_RETENTION_DRAM_COREBLK_VAL 0x10000000 >> >> /* APLL_CON1 */ >> #define APLL_CON1_VAL (0x0020F300) >> diff --git a/arch/arm/include/asm/arch-exynos/cpu.h b/arch/arm/include/asm/arch-exynos/cpu.h >> index 2b44210..2c642ba 100644 >> --- a/arch/arm/include/asm/arch-exynos/cpu.h >> +++ b/arch/arm/include/asm/arch-exynos/cpu.h >> @@ -53,6 +53,7 @@ >> #define EXYNOS4_AUDIOSS_BASE DEVICE_NOT_AVAILABLE >> #define EXYNOS4_USB_HOST_XHCI_BASE DEVICE_NOT_AVAILABLE >> #define EXYNOS4_USB3PHY_BASE DEVICE_NOT_AVAILABLE >> +#define EXYNOS4_DMC_TZASC0_BASE DEVICE_NOT_AVAILABLE >> >> /* EXYNOS4X12 */ >> #define EXYNOS4X12_GPIO_PART3_BASE 0x03860000 >> @@ -91,6 +92,7 @@ >> #define EXYNOS4X12_AUDIOSS_BASE DEVICE_NOT_AVAILABLE >> #define EXYNOS4X12_USB_HOST_XHCI_BASE DEVICE_NOT_AVAILABLE >> #define EXYNOS4X12_USB3PHY_BASE DEVICE_NOT_AVAILABLE >> +#define EXYNOS4X12_DMC_TZASC0_BASE DEVICE_NOT_AVAILABLE >> >> /* EXYNOS5 */ >> #define EXYNOS5_I2C_SPACING 0x10000 >> @@ -129,6 +131,7 @@ >> >> #define EXYNOS5_ADC_BASE DEVICE_NOT_AVAILABLE >> #define EXYNOS5_MODEM_BASE DEVICE_NOT_AVAILABLE >> +#define EXYNOS5_DMC_TZASC0_BASE DEVICE_NOT_AVAILABLE >> >> /* EXYNOS5420 */ >> #define EXYNOS5420_AUDIOSS_BASE 0x03810000 >> @@ -284,6 +287,7 @@ SAMSUNG_BASE(spi_isp, SPI_ISP_BASE) >> SAMSUNG_BASE(tzpc, TZPC_BASE) >> SAMSUNG_BASE(dmc_ctrl, DMC_CTRL_BASE) >> SAMSUNG_BASE(dmc_phy, DMC_PHY_BASE) >> +SAMSUNG_BASE(dmc_tzasc0, DMC_TZASC0_BASE) > > then do we need to define two base addresses for TZASC? > you never use TZASC1. Acessing base address for TZASC1 in following manner. Hence added only SAMSUNG_BASE(dmc_tzasc0, DMC_TZASC0_BASE) "tzasc1 = (struct exynos5_tzasc *)(samsung_get_base_dmc_tzasc0() + DMC_OFFSET);" > >> SAMSUNG_BASE(audio_ass, AUDIOSS_BASE) >> #endif >> >> diff --git a/arch/arm/include/asm/arch-exynos/dmc.h b/arch/arm/include/asm/arch-exynos/dmc.h >> index f65c676..0913299 100644 >> --- a/arch/arm/include/asm/arch-exynos/dmc.h >> +++ b/arch/arm/include/asm/arch-exynos/dmc.h >> @@ -114,13 +114,24 @@ 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 > > No. we don't allow ifdef. Will add separate structure for 5420 > >> unsigned int memconfig0; >> +#else >> + unsigned int cgcontrol; >> +#endif >> 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 +139,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 +175,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 +260,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 +301,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 +344,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 >> diff --git a/arch/arm/include/asm/arch-exynos/power.h b/arch/arm/include/asm/arch-exynos/power.h >> index 8db18c5..6077fc3 100644 >> --- a/arch/arm/include/asm/arch-exynos/power.h >> +++ b/arch/arm/include/asm/arch-exynos/power.h >> @@ -690,9 +690,15 @@ struct exynos5_power { >> unsigned int pad_retention_spi_status; >> unsigned int pad_retention_spi_option; >> unsigned char res117[0x14]; >> + #ifdef CONFIG_EXYNOS5250 > > ditto. Will add separate structure for 5420 >> unsigned int pad_retention_gpio_dmc_configuration; >> unsigned int pad_retention_gpio_dmc_status; >> unsigned int pad_retention_gpio_dmc_option; >> + #else >> + unsigned int pad_retention_dram_coreblk_configuration; >> + unsigned int pad_retention_dram_coreblk_status; >> + unsigned int pad_retention_dram_coreblk_option; >> + #endif >> unsigned char res118[0x14]; >> unsigned int pad_isolation_configuration; >> unsigned int pad_isolation_status; >> > > Thanks, > Minkyu Kang. > _______________________________________________ > U-Boot mailing list > U-Boot@lists.denx.de > http://lists.denx.de/mailman/listinfo/u-boot
On 05/12/13 16:25, Rajeshwari Birje wrote: > Hi Minkyu Kang, > > Thank you for comments. > > On Tue, Dec 3, 2013 at 11:45 AM, Minkyu Kang <mk7.kang@samsung.com> wrote: >> Dear Rajeshwari S Shinde, >> >> On 02/12/13 20:47, Rajeshwari S Shinde wrote: >>> This patch intends to add DDR3 initialization code for Exynos5420. >>> >>> Signed-off-by: Rajeshwari S Shinde <rajeshwari.s@samsung.com> >>> Signed-off-by: Akshay Saraswat <akshay.s@samsung.com> >>> Acked-by: Simon Glass <sjg@chromium.org> >>> --- >>> Changes in V2: >>> - Corrected a compilation issue for SMDK5250. >>> Changes in V3: >>> - None >>> Changes in V4: >>> - None >>> Changes in V5: >>> - None >>> Changes in V6: >>> - None >>> Changes in V7: >>> - Fixed multi line comment. >>> Changes in V8: >>> - None >>> Changes in V9: >>> - Used samsung_get base to get the dmc base address >>> arch/arm/cpu/armv7/exynos/dmc_common.c | 10 +- >>> arch/arm/cpu/armv7/exynos/dmc_init_ddr3.c | 425 +++++++++++++++++++++++++++++- >>> arch/arm/cpu/armv7/exynos/exynos5_setup.h | 2 + >>> arch/arm/include/asm/arch-exynos/cpu.h | 4 + >>> arch/arm/include/asm/arch-exynos/dmc.h | 123 ++++++--- >>> arch/arm/include/asm/arch-exynos/power.h | 6 + >>> 6 files changed, 525 insertions(+), 45 deletions(-) >>> >>> diff --git a/arch/arm/cpu/armv7/exynos/exynos5_setup.h b/arch/arm/cpu/armv7/exynos/exynos5_setup.h >>> index c8d6515..42a7fb8 100644 >>> --- a/arch/arm/cpu/armv7/exynos/exynos5_setup.h >>> +++ b/arch/arm/cpu/armv7/exynos/exynos5_setup.h >>> @@ -436,6 +436,7 @@ >>> */ >>> #ifndef CONFIG_SMDK5420 >>> >>> + >> >> unnecessary blank line. > will remove this >> >>> /* APLL_CON1 */ >>> #define APLL_CON1_VAL (0x00203800) >>> >>> @@ -696,6 +697,7 @@ >>> #define CLK_DIV_CPERI1_VAL NOT_AVAILABLE >>> >>> #else >>> +#define PAD_RETENTION_DRAM_COREBLK_VAL 0x10000000 >>> >>> /* APLL_CON1 */ >>> #define APLL_CON1_VAL (0x0020F300) >>> diff --git a/arch/arm/include/asm/arch-exynos/cpu.h b/arch/arm/include/asm/arch-exynos/cpu.h >>> index 2b44210..2c642ba 100644 >>> --- a/arch/arm/include/asm/arch-exynos/cpu.h >>> +++ b/arch/arm/include/asm/arch-exynos/cpu.h >>> @@ -53,6 +53,7 @@ >>> #define EXYNOS4_AUDIOSS_BASE DEVICE_NOT_AVAILABLE >>> #define EXYNOS4_USB_HOST_XHCI_BASE DEVICE_NOT_AVAILABLE >>> #define EXYNOS4_USB3PHY_BASE DEVICE_NOT_AVAILABLE >>> +#define EXYNOS4_DMC_TZASC0_BASE DEVICE_NOT_AVAILABLE >>> >>> /* EXYNOS4X12 */ >>> #define EXYNOS4X12_GPIO_PART3_BASE 0x03860000 >>> @@ -91,6 +92,7 @@ >>> #define EXYNOS4X12_AUDIOSS_BASE DEVICE_NOT_AVAILABLE >>> #define EXYNOS4X12_USB_HOST_XHCI_BASE DEVICE_NOT_AVAILABLE >>> #define EXYNOS4X12_USB3PHY_BASE DEVICE_NOT_AVAILABLE >>> +#define EXYNOS4X12_DMC_TZASC0_BASE DEVICE_NOT_AVAILABLE >>> >>> /* EXYNOS5 */ >>> #define EXYNOS5_I2C_SPACING 0x10000 >>> @@ -129,6 +131,7 @@ >>> >>> #define EXYNOS5_ADC_BASE DEVICE_NOT_AVAILABLE >>> #define EXYNOS5_MODEM_BASE DEVICE_NOT_AVAILABLE >>> +#define EXYNOS5_DMC_TZASC0_BASE DEVICE_NOT_AVAILABLE >>> >>> /* EXYNOS5420 */ >>> #define EXYNOS5420_AUDIOSS_BASE 0x03810000 >>> @@ -284,6 +287,7 @@ SAMSUNG_BASE(spi_isp, SPI_ISP_BASE) >>> SAMSUNG_BASE(tzpc, TZPC_BASE) >>> SAMSUNG_BASE(dmc_ctrl, DMC_CTRL_BASE) >>> SAMSUNG_BASE(dmc_phy, DMC_PHY_BASE) >>> +SAMSUNG_BASE(dmc_tzasc0, DMC_TZASC0_BASE) >> >> then do we need to define two base addresses for TZASC? >> you never use TZASC1. > Acessing base address for TZASC1 in following manner. Hence added only > SAMSUNG_BASE(dmc_tzasc0, DMC_TZASC0_BASE) > "tzasc1 = (struct exynos5_tzasc *)(samsung_get_base_dmc_tzasc0() > + DMC_OFFSET);" Yes, so my suggestion is defining TZASC only. #define EXYNOS5420_DMC_TZASC_BASE 0x10D40000 SAMSUNG_BASE(dmc_tzasc, DMC_TZASC_BASE) >> >>> SAMSUNG_BASE(audio_ass, AUDIOSS_BASE) >>> #endif >>> Thanks, Minkyu Kang.
Hi Minkyu Kang, Please do find the comment bellow. On Thu, Dec 5, 2013 at 12:55 PM, Rajeshwari Birje <rajeshwari.birje@gmail.com> wrote: > Hi Minkyu Kang, > > Thank you for comments. > > On Tue, Dec 3, 2013 at 11:45 AM, Minkyu Kang <mk7.kang@samsung.com> wrote: >> Dear Rajeshwari S Shinde, >> >> On 02/12/13 20:47, Rajeshwari S Shinde wrote: >>> This patch intends to add DDR3 initialization code for Exynos5420. >>> >>> Signed-off-by: Rajeshwari S Shinde <rajeshwari.s@samsung.com> >>> Signed-off-by: Akshay Saraswat <akshay.s@samsung.com> >>> Acked-by: Simon Glass <sjg@chromium.org> >>> --- >>> Changes in V2: >>> - Corrected a compilation issue for SMDK5250. >>> Changes in V3: >>> - None >>> Changes in V4: >>> - None >>> Changes in V5: >>> - None >>> Changes in V6: >>> - None >>> Changes in V7: >>> - Fixed multi line comment. >>> Changes in V8: >>> - None >>> Changes in V9: >>> - Used samsung_get base to get the dmc base address >>> arch/arm/cpu/armv7/exynos/dmc_common.c | 10 +- >>> arch/arm/cpu/armv7/exynos/dmc_init_ddr3.c | 425 +++++++++++++++++++++++++++++- >>> arch/arm/cpu/armv7/exynos/exynos5_setup.h | 2 + >>> arch/arm/include/asm/arch-exynos/cpu.h | 4 + >>> arch/arm/include/asm/arch-exynos/dmc.h | 123 ++++++--- >>> arch/arm/include/asm/arch-exynos/power.h | 6 + >>> 6 files changed, 525 insertions(+), 45 deletions(-) >>> >>> diff --git a/arch/arm/cpu/armv7/exynos/dmc_common.c b/arch/arm/cpu/armv7/exynos/dmc_common.c >>> index 53cfe6e..9e432c2 100644 >>> --- a/arch/arm/cpu/armv7/exynos/dmc_common.c >>> +++ b/arch/arm/cpu/armv7/exynos/dmc_common.c >>> @@ -1,5 +1,5 @@ >>> /* >>> - * Mem setup common file for different types of DDR present on SMDK5250 boards. >>> + * Mem setup common file for different types of DDR present on Exynos boards. >>> * >>> * Copyright (C) 2012 Samsung Electronics >>> * >>> @@ -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..aa46a43 100644 >>> --- a/arch/arm/cpu/armv7/exynos/dmc_init_ddr3.c >>> +++ b/arch/arm/cpu/armv7/exynos/dmc_init_ddr3.c >>> @@ -1,5 +1,5 @@ >>> /* >>> - * DDR3 mem setup file for SMDK5250 board based on EXYNOS5 >>> + * DDR3 mem setup file for board based on EXYNOS5 >>> * >>> * Copyright (C) 2012 Samsung Electronics >>> * >>> @@ -11,12 +11,14 @@ >>> #include <asm/arch/clock.h> >>> #include <asm/arch/cpu.h> >>> #include <asm/arch/dmc.h> >>> +#include <asm/arch/power.h> >>> #include "common_setup.h" >>> #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 +110,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 +176,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 +217,418 @@ 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 >> >> we can avoid ifdef here. >> >> int ddr3_mem_ctrl_init(...) >> { >> if (proid_is_exynos5250()) >> exynos5250_ddr3_mem_ctrl_init(); >> else >> exynos5420_ddr3_mem_ctrl_init(); >> } >> > Will do it this way Doing it this way increases the spl size. hence will keep the #ifdef defines.
diff --git a/arch/arm/cpu/armv7/exynos/dmc_common.c b/arch/arm/cpu/armv7/exynos/dmc_common.c index 53cfe6e..9e432c2 100644 --- a/arch/arm/cpu/armv7/exynos/dmc_common.c +++ b/arch/arm/cpu/armv7/exynos/dmc_common.c @@ -1,5 +1,5 @@ /* - * Mem setup common file for different types of DDR present on SMDK5250 boards. + * Mem setup common file for different types of DDR present on Exynos boards. * * Copyright (C) 2012 Samsung Electronics * @@ -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..aa46a43 100644 --- a/arch/arm/cpu/armv7/exynos/dmc_init_ddr3.c +++ b/arch/arm/cpu/armv7/exynos/dmc_init_ddr3.c @@ -1,5 +1,5 @@ /* - * DDR3 mem setup file for SMDK5250 board based on EXYNOS5 + * DDR3 mem setup file for board based on EXYNOS5 * * Copyright (C) 2012 Samsung Electronics * @@ -11,12 +11,14 @@ #include <asm/arch/clock.h> #include <asm/arch/cpu.h> #include <asm/arch/dmc.h> +#include <asm/arch/power.h> #include "common_setup.h" #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 +110,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 +176,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 +217,418 @@ 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 *)samsung_get_base_clock(); + struct exynos5_power *power = + (struct exynos5_power *)samsung_get_base_power(); + 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 *)samsung_get_base_dmc_tzasc0(); + tzasc1 = (struct exynos5_tzasc *)(samsung_get_base_dmc_tzasc0() + + DMC_OFFSET); + + /* 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 + * 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, + &power->pad_retention_dram_coreblk_option); + do { + val = readl(&power->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/cpu/armv7/exynos/exynos5_setup.h b/arch/arm/cpu/armv7/exynos/exynos5_setup.h index c8d6515..42a7fb8 100644 --- a/arch/arm/cpu/armv7/exynos/exynos5_setup.h +++ b/arch/arm/cpu/armv7/exynos/exynos5_setup.h @@ -436,6 +436,7 @@ */ #ifndef CONFIG_SMDK5420 + /* APLL_CON1 */ #define APLL_CON1_VAL (0x00203800) @@ -696,6 +697,7 @@ #define CLK_DIV_CPERI1_VAL NOT_AVAILABLE #else +#define PAD_RETENTION_DRAM_COREBLK_VAL 0x10000000 /* APLL_CON1 */ #define APLL_CON1_VAL (0x0020F300) diff --git a/arch/arm/include/asm/arch-exynos/cpu.h b/arch/arm/include/asm/arch-exynos/cpu.h index 2b44210..2c642ba 100644 --- a/arch/arm/include/asm/arch-exynos/cpu.h +++ b/arch/arm/include/asm/arch-exynos/cpu.h @@ -53,6 +53,7 @@ #define EXYNOS4_AUDIOSS_BASE DEVICE_NOT_AVAILABLE #define EXYNOS4_USB_HOST_XHCI_BASE DEVICE_NOT_AVAILABLE #define EXYNOS4_USB3PHY_BASE DEVICE_NOT_AVAILABLE +#define EXYNOS4_DMC_TZASC0_BASE DEVICE_NOT_AVAILABLE /* EXYNOS4X12 */ #define EXYNOS4X12_GPIO_PART3_BASE 0x03860000 @@ -91,6 +92,7 @@ #define EXYNOS4X12_AUDIOSS_BASE DEVICE_NOT_AVAILABLE #define EXYNOS4X12_USB_HOST_XHCI_BASE DEVICE_NOT_AVAILABLE #define EXYNOS4X12_USB3PHY_BASE DEVICE_NOT_AVAILABLE +#define EXYNOS4X12_DMC_TZASC0_BASE DEVICE_NOT_AVAILABLE /* EXYNOS5 */ #define EXYNOS5_I2C_SPACING 0x10000 @@ -129,6 +131,7 @@ #define EXYNOS5_ADC_BASE DEVICE_NOT_AVAILABLE #define EXYNOS5_MODEM_BASE DEVICE_NOT_AVAILABLE +#define EXYNOS5_DMC_TZASC0_BASE DEVICE_NOT_AVAILABLE /* EXYNOS5420 */ #define EXYNOS5420_AUDIOSS_BASE 0x03810000 @@ -284,6 +287,7 @@ SAMSUNG_BASE(spi_isp, SPI_ISP_BASE) SAMSUNG_BASE(tzpc, TZPC_BASE) SAMSUNG_BASE(dmc_ctrl, DMC_CTRL_BASE) SAMSUNG_BASE(dmc_phy, DMC_PHY_BASE) +SAMSUNG_BASE(dmc_tzasc0, DMC_TZASC0_BASE) SAMSUNG_BASE(audio_ass, AUDIOSS_BASE) #endif diff --git a/arch/arm/include/asm/arch-exynos/dmc.h b/arch/arm/include/asm/arch-exynos/dmc.h index f65c676..0913299 100644 --- a/arch/arm/include/asm/arch-exynos/dmc.h +++ b/arch/arm/include/asm/arch-exynos/dmc.h @@ -114,13 +114,24 @@ 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 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 +139,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 +175,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 +260,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 +301,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 +344,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 diff --git a/arch/arm/include/asm/arch-exynos/power.h b/arch/arm/include/asm/arch-exynos/power.h index 8db18c5..6077fc3 100644 --- a/arch/arm/include/asm/arch-exynos/power.h +++ b/arch/arm/include/asm/arch-exynos/power.h @@ -690,9 +690,15 @@ struct exynos5_power { unsigned int pad_retention_spi_status; unsigned int pad_retention_spi_option; unsigned char res117[0x14]; + #ifdef CONFIG_EXYNOS5250 unsigned int pad_retention_gpio_dmc_configuration; unsigned int pad_retention_gpio_dmc_status; unsigned int pad_retention_gpio_dmc_option; + #else + unsigned int pad_retention_dram_coreblk_configuration; + unsigned int pad_retention_dram_coreblk_status; + unsigned int pad_retention_dram_coreblk_option; + #endif unsigned char res118[0x14]; unsigned int pad_isolation_configuration; unsigned int pad_isolation_status;