From fc46bae2ae38c8d0b1570427b5c9520281eaae4f Mon Sep 17 00:00:00 2001 From: James Doublesin Date: Mon, 22 Dec 2014 16:26:11 -0600 Subject: arm: am437x: Enable hardware leveling for EMIF Switch to using hardware leveling for certain parameters on the EMIF rather than using precalculated values. Doing this also means we have a common place now between am437x and am335x for setting emif_sdram_ref_ctrl with a value for the correct delay length. Tested-by: Felipe Balbi Tested-by: Tom Rini Signed-off-by: James Doublesin Signed-off-by: Felipe Balbi --- arch/arm/cpu/armv7/am33xx/ddr.c | 134 +++++++++++++++++++++++++------------- arch/arm/cpu/armv7/am33xx/emif4.c | 5 +- 2 files changed, 93 insertions(+), 46 deletions(-) (limited to 'arch/arm/cpu') diff --git a/arch/arm/cpu/armv7/am33xx/ddr.c b/arch/arm/cpu/armv7/am33xx/ddr.c index fc66872a31..85cceae152 100644 --- a/arch/arm/cpu/armv7/am33xx/ddr.c +++ b/arch/arm/cpu/armv7/am33xx/ddr.c @@ -76,13 +76,13 @@ static void configure_mr(int nr, u32 cs) } /* - * Configure EMIF4D5 registers and MR registers + * Configure EMIF4D5 registers and MR registers For details about these magic + * values please see the EMIF registers section of the TRM. */ void config_sdram_emif4d5(const struct emif_regs *regs, int nr) { writel(0xA0, &emif_reg[nr]->emif_pwr_mgmt_ctrl); writel(0xA0, &emif_reg[nr]->emif_pwr_mgmt_ctrl_shdw); - writel(0x1, &emif_reg[nr]->emif_iodft_tlgc); writel(regs->zq_config, &emif_reg[nr]->emif_zq_config); writel(regs->temp_alert_config, &emif_reg[nr]->emif_temp_alert_config); @@ -106,10 +106,45 @@ void config_sdram_emif4d5(const struct emif_regs *regs, int nr) writel(regs->emif_cos_config, &emif_reg[nr]->emif_cos_config); } - writel(regs->ref_ctrl, &emif_reg[nr]->emif_sdram_ref_ctrl); - writel(regs->ref_ctrl, &emif_reg[nr]->emif_sdram_ref_ctrl_shdw); + /* + * Sequence to ensure that the PHY is in a known state prior to + * startting hardware leveling. Also acts as to latch some state from + * the EMIF into the PHY. + */ + writel(0x2011, &emif_reg[nr]->emif_iodft_tlgc); + writel(0x2411, &emif_reg[nr]->emif_iodft_tlgc); + writel(0x2011, &emif_reg[nr]->emif_iodft_tlgc); + + clrbits_le32(&emif_reg[nr]->emif_sdram_ref_ctrl, + EMIF_REG_INITREF_DIS_MASK); + writel(regs->sdram_config, &emif_reg[nr]->emif_sdram_config); writel(regs->sdram_config, &cstat->secure_emif_sdram_config); + writel(regs->ref_ctrl, &emif_reg[nr]->emif_sdram_ref_ctrl); + writel(regs->ref_ctrl, &emif_reg[nr]->emif_sdram_ref_ctrl_shdw); + + /* Perform hardware leveling. */ + udelay(1000); + writel(readl(&emif_reg[nr]->emif_ddr_ext_phy_ctrl_36) | + 0x100, &emif_reg[nr]->emif_ddr_ext_phy_ctrl_36); + writel(readl(&emif_reg[nr]->emif_ddr_ext_phy_ctrl_36_shdw) | + 0x100, &emif_reg[nr]->emif_ddr_ext_phy_ctrl_36_shdw); + + writel(0x80000000, &emif_reg[nr]->emif_rd_wr_lvl_rmp_ctl); + + /* Enable read leveling */ + writel(0x80000000, &emif_reg[nr]->emif_rd_wr_lvl_ctl); + + /* + * Enable full read and write leveling. Wait for read and write + * leveling bit to clear RDWRLVLFULL_START bit 31 + */ + while((readl(&emif_reg[nr]->emif_rd_wr_lvl_ctl) & 0x80000000) != 0) + ; + + /* Check the timeout register to see if leveling is complete */ + if((readl(&emif_reg[nr]->emif_status) & 0x70) != 0) + puts("DDR3 H/W leveling incomplete with errors\n"); if (emif_sdram_type() == EMIF_SDRAM_TYPE_LPDDR2) { configure_mr(nr, 0); @@ -123,21 +158,15 @@ void config_sdram_emif4d5(const struct emif_regs *regs, int nr) void config_sdram(const struct emif_regs *regs, int nr) { if (regs->zq_config) { - /* - * A value of 0x2800 for the REF CTRL will give us - * about 570us for a delay, which will be long enough - * to configure things. - */ - writel(0x2800, &emif_reg[nr]->emif_sdram_ref_ctrl); writel(regs->zq_config, &emif_reg[nr]->emif_zq_config); writel(regs->sdram_config, &cstat->secure_emif_sdram_config); writel(regs->sdram_config, &emif_reg[nr]->emif_sdram_config); writel(regs->ref_ctrl, &emif_reg[nr]->emif_sdram_ref_ctrl); writel(regs->ref_ctrl, &emif_reg[nr]->emif_sdram_ref_ctrl_shdw); } + writel(regs->sdram_config, &emif_reg[nr]->emif_sdram_config); writel(regs->ref_ctrl, &emif_reg[nr]->emif_sdram_ref_ctrl); writel(regs->ref_ctrl, &emif_reg[nr]->emif_sdram_ref_ctrl_shdw); - writel(regs->sdram_config, &emif_reg[nr]->emif_sdram_config); } /** @@ -153,46 +182,55 @@ void set_sdram_timings(const struct emif_regs *regs, int nr) writel(regs->sdram_tim3, &emif_reg[nr]->emif_sdram_tim_3_shdw); } -void __weak emif_get_ext_phy_ctrl_const_regs(const u32 **regs, u32 *size) -{ -} - /* - * Configure EXT PHY registers + * Configure EXT PHY registers for hardware leveling */ static void ext_phy_settings(const struct emif_regs *regs, int nr) { - u32 *ext_phy_ctrl_base = 0; - u32 *emif_ext_phy_ctrl_base = 0; - const u32 *ext_phy_ctrl_const_regs; - u32 i = 0; - u32 size; - - ext_phy_ctrl_base = (u32 *)&(regs->emif_ddr_ext_phy_ctrl_1); - emif_ext_phy_ctrl_base = - (u32 *)&(emif_reg[nr]->emif_ddr_ext_phy_ctrl_1); - - /* Configure external phy control timing registers */ - for (i = 0; i < EMIF_EXT_PHY_CTRL_TIMING_REG; i++) { - writel(*ext_phy_ctrl_base, emif_ext_phy_ctrl_base++); - /* Update shadow registers */ - writel(*ext_phy_ctrl_base++, emif_ext_phy_ctrl_base++); - } - /* - * external phy 6-24 registers do not change with - * ddr frequency + * Enable hardware leveling on the EMIF. For details about these + * magic values please see the EMIF registers section of the TRM. */ - emif_get_ext_phy_ctrl_const_regs(&ext_phy_ctrl_const_regs, &size); - - if (!size) - return; + writel(0x08020080, &emif_reg[nr]->emif_ddr_ext_phy_ctrl_1); + writel(0x08020080, &emif_reg[nr]->emif_ddr_ext_phy_ctrl_1_shdw); + writel(0x00000000, &emif_reg[nr]->emif_ddr_ext_phy_ctrl_22); + writel(0x00000000, &emif_reg[nr]->emif_ddr_ext_phy_ctrl_22_shdw); + writel(0x00600020, &emif_reg[nr]->emif_ddr_ext_phy_ctrl_23); + writel(0x00600020, &emif_reg[nr]->emif_ddr_ext_phy_ctrl_23_shdw); + writel(0x40010080, &emif_reg[nr]->emif_ddr_ext_phy_ctrl_24); + writel(0x40010080, &emif_reg[nr]->emif_ddr_ext_phy_ctrl_24_shdw); + writel(0x08102040, &emif_reg[nr]->emif_ddr_ext_phy_ctrl_25); + writel(0x08102040, &emif_reg[nr]->emif_ddr_ext_phy_ctrl_25_shdw); + writel(0x00200020, &emif_reg[nr]->emif_ddr_ext_phy_ctrl_26); + writel(0x00200020, &emif_reg[nr]->emif_ddr_ext_phy_ctrl_26_shdw); + writel(0x00200020, &emif_reg[nr]->emif_ddr_ext_phy_ctrl_27); + writel(0x00200020, &emif_reg[nr]->emif_ddr_ext_phy_ctrl_27_shdw); + writel(0x00200020, &emif_reg[nr]->emif_ddr_ext_phy_ctrl_28); + writel(0x00200020, &emif_reg[nr]->emif_ddr_ext_phy_ctrl_28_shdw); + writel(0x00200020, &emif_reg[nr]->emif_ddr_ext_phy_ctrl_29); + writel(0x00200020, &emif_reg[nr]->emif_ddr_ext_phy_ctrl_29_shdw); + writel(0x00200020, &emif_reg[nr]->emif_ddr_ext_phy_ctrl_30); + writel(0x00200020, &emif_reg[nr]->emif_ddr_ext_phy_ctrl_30_shdw); + writel(0x00000000, &emif_reg[nr]->emif_ddr_ext_phy_ctrl_31); + writel(0x00000000, &emif_reg[nr]->emif_ddr_ext_phy_ctrl_31_shdw); + writel(0x00000000, &emif_reg[nr]->emif_ddr_ext_phy_ctrl_32); + writel(0x00000000, &emif_reg[nr]->emif_ddr_ext_phy_ctrl_32_shdw); + writel(0x00000000, &emif_reg[nr]->emif_ddr_ext_phy_ctrl_33); + writel(0x00000000, &emif_reg[nr]->emif_ddr_ext_phy_ctrl_33_shdw); + writel(0x00000000, &emif_reg[nr]->emif_ddr_ext_phy_ctrl_34); + writel(0x00000000, &emif_reg[nr]->emif_ddr_ext_phy_ctrl_34_shdw); + writel(0x00000000, &emif_reg[nr]->emif_ddr_ext_phy_ctrl_35); + writel(0x00000000, &emif_reg[nr]->emif_ddr_ext_phy_ctrl_35_shdw); + writel(0x000000FF, &emif_reg[nr]->emif_ddr_ext_phy_ctrl_36); + writel(0x000000FF, &emif_reg[nr]->emif_ddr_ext_phy_ctrl_36_shdw); - for (i = 0; i < size; i++) { - writel(ext_phy_ctrl_const_regs[i], emif_ext_phy_ctrl_base++); - /* Update shadow registers */ - writel(ext_phy_ctrl_const_regs[i], emif_ext_phy_ctrl_base++); - } + /* + * Sequence to ensure that the PHY is again in a known state after + * hardware leveling. + */ + writel(0x2011, &emif_reg[nr]->emif_iodft_tlgc); + writel(0x2411, &emif_reg[nr]->emif_iodft_tlgc); + writel(0x2011, &emif_reg[nr]->emif_iodft_tlgc); } /** @@ -201,11 +239,17 @@ static void ext_phy_settings(const struct emif_regs *regs, int nr) void config_ddr_phy(const struct emif_regs *regs, int nr) { /* - * disable initialization and refreshes for now until we + * Disable initialization and refreshes for now until we * finish programming EMIF regs. + * Also set time between rising edge of DDR_RESET to rising + * edge of DDR_CKE to > 500us per memory spec. */ +#ifndef CONFIG_AM43XX setbits_le32(&emif_reg[nr]->emif_sdram_ref_ctrl, EMIF_REG_INITREF_DIS_MASK); +#endif + if (regs->zq_config) + writel(0x80003100, &emif_reg[nr]->emif_sdram_ref_ctrl); writel(regs->emif_ddr_phy_ctlr_1, &emif_reg[nr]->emif_ddr_phy_ctrl_1); diff --git a/arch/arm/cpu/armv7/am33xx/emif4.c b/arch/arm/cpu/armv7/am33xx/emif4.c index 8b7527c5b4..9cf816c89a 100644 --- a/arch/arm/cpu/armv7/am33xx/emif4.c +++ b/arch/arm/cpu/armv7/am33xx/emif4.c @@ -112,17 +112,20 @@ void config_ddr(unsigned int pll, const struct ctrl_ioregs *ioregs, /* Set CKE to be controlled by EMIF/DDR PHY */ writel(DDR_CKE_CTRL_NORMAL, &ddrctrl->ddrckectrl); + #endif #ifdef CONFIG_AM43XX writel(readl(&cm_device->cm_dll_ctrl) & ~0x1, &cm_device->cm_dll_ctrl); while ((readl(&cm_device->cm_dll_ctrl) & CM_DLL_READYST) == 0) ; - writel(0x80000000, &ddrctrl->ddrioctrl); config_io_ctrl(ioregs); /* Set CKE to be controlled by EMIF/DDR PHY */ writel(DDR_CKE_CTRL_NORMAL, &ddrctrl->ddrckectrl); + + /* Allow EMIF to control DDR_RESET */ + writel(0x00000000, &ddrctrl->ddrioctrl); #endif /* Program EMIF instance */ -- cgit v1.2.1