[U-Boot] [PATCH] EXYNOS: SMDK5250: Add support for DDR3 memory.

Hatim Ali hatim.rv at samsung.com
Wed Feb 8 12:44:35 CET 2012


SMDK5250 development boards have different memory variants like
DDR3, LPDDR2 and LPDDR3. This patch adds supports for DDR3.
The DDR3 is configured for 667Mhz and is being enabled by default.

This patch is based on Chander Kashyap's v9 patchset.
(http://comments.gmane.org/gmane.comp.boot-loaders.u-boot/124396)

Signed-off-by: Hatim Ali <hatim.rv at samsung.com>

diff --git a/board/samsung/smdk5250/Makefile b/board/samsung/smdk5250/Makefile
index 226db1f..50a17cb 100644
--- a/board/samsung/smdk5250/Makefile
+++ b/board/samsung/smdk5250/Makefile
@@ -27,7 +27,11 @@ LIB	= $(obj)lib$(BOARD).o
 SOBJS	:= lowlevel_init.o
 
 COBJS	:= clock_init.o
+ifdef CONFIG_DDR3
+COBJS	+= dmc_init_ddr3.o
+else
 COBJS	+= dmc_init.o
+endif
 COBJS	+= tzpc_init.o
 
 ifndef CONFIG_SPL_BUILD
diff --git a/board/samsung/smdk5250/dmc_init.c b/board/samsung/smdk5250/dmc_init.c
index 7881074..160d86e 100644
--- a/board/samsung/smdk5250/dmc_init.c
+++ b/board/samsung/smdk5250/dmc_init.c
@@ -248,7 +248,7 @@ static void config_rdlvl(struct exynos5_dmc *dmc,
 	 * ctrl_gateduradj, rdlvl_pass_adj
 	 * rdlvl_rddataPadj
 	 */
-	val = SET_RDLVL_RDDATAPADJ;
+	val = SET_RDLVL_RDDATA_ADJ;
 	writel(val, &phy0_ctrl->phy_con1);
 	writel(val, &phy1_ctrl->phy_con1);
 
@@ -361,8 +361,8 @@ void mem_ctrl_init()
 	config_zq(phy0_ctrl, phy1_ctrl);
 
 	/* Operation Mode : LPDDR2 */
-	val = PHY_CON0_RESET_VAL;
-	SET_CTRL_DDR_MODE(val, DDR_MODE_LPDDR2);
+	val = CTRL_DDR_MODE(LPDDR2);
+	val |= BYTE_RDLVL_EN;
 	writel(val, &phy0_ctrl->phy_con0);
 	writel(val, &phy1_ctrl->phy_con0);
 
diff --git a/board/samsung/smdk5250/dmc_init_ddr3.c b/board/samsung/smdk5250/dmc_init_ddr3.c
new file mode 100644
index 0000000..da42dd2
--- /dev/null
+++ b/board/samsung/smdk5250/dmc_init_ddr3.c
@@ -0,0 +1,464 @@
+/*
+ * DDR3 Memory setup for SMDK5250 board based on EXYNOS5
+ *
+ * Copyright (C) 2012 Samsung Electronics
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#include <config.h>
+#include <asm/io.h>
+#include <asm/arch/dmc.h>
+#include <asm/arch/clock.h>
+#include <asm/arch/cpu.h>
+#include "setup.h"
+
+/* APLL : 1GHz */
+/* MCLK_CDREX: MCLK_CDREX_677*/
+/* LPDDR support: DDR3 */
+
+static void dmc_directcmd_PALL(struct exynos5_dmc *dmc)
+{
+	unsigned long channel, chip, mask = 0, val;
+
+	/* Sending PALL cmd on
+	* Channel0-Chip0
+	* Channel0-Chip1
+	* Channel1-Chip0
+	* Channel1-Chip1
+	*/
+	for (channel = 0; channel < CONFIG_DMC_CHANNELS; channel++) {
+		SET_CMD_CHANNEL(mask, channel);
+		for (chip = 0; chip < CONFIG_CHIPS_PER_CHANNEL; chip++) {
+			SET_CMD_CHIP(mask, chip);
+			val = DIRECT_CMD_PALL | mask;
+			writel(val, &dmc->directcmd);
+			sdelay(0x10000);
+		}
+	}
+
+}
+
+
+static void dmc_directcmd(struct exynos5_dmc *dmc)
+{
+	unsigned long channel, mask = 0, val;
+
+	/* Selecting Channel0-Chip0 */
+	SET_CMD_CHANNEL(mask, 0);
+	SET_CMD_CHIP(mask, 0);
+
+	/* Sending NOP cmd on Channel0-Chip0 */
+	val = DIRECT_CMD_NOP | mask;
+	writel(val, &dmc->directcmd);
+	sdelay(0x10000);
+
+	dmc_directcmd_PALL(dmc);
+
+	/* Selecting Chip 0*/
+	mask = 0;
+	SET_CMD_CHIP(mask, 0);
+	for (channel = 0; channel < CONFIG_DMC_CHANNELS; channel++) {
+		/* Selecting Channel */
+		SET_CMD_CHANNEL(mask, channel);
+
+		if (channel == 1) {
+			/* Sending NOP cmd on Channel1-Chip0 */
+			val = DIRECT_CMD_NOP | mask;
+			writel(val, &dmc->directcmd);
+			sdelay(0x10000);
+		}
+		/* Sending MRS/EMRS command and ZQINIT command
+		*  on Channel0-Chip0
+		*/
+		val = DIRECT_CMD_MRS1 | mask;
+		writel(val, &dmc->directcmd);
+		sdelay(0x10000);
+
+		val = DIRECT_CMD_MRS2 | mask;
+		writel(val, &dmc->directcmd);
+		sdelay(0x10000);
+
+		val = DIRECT_CMD_MRS3 | mask;
+		writel(val, &dmc->directcmd);
+		sdelay(0x10000);
+
+		val = DIRECT_CMD_MRS4 | mask;
+		writel(val, &dmc->directcmd);
+		sdelay(0x10000);
+
+		val = DIRECT_CMD_ZQINIT | mask;
+		writel(val, &dmc->directcmd);
+		sdelay(0x10000);
+	}
+}
+
+static void update_reset_dll(struct exynos5_dmc *dmc)
+{
+	unsigned long val;
+	val = (PHY_CONTROL0_RESET_VAL | MEM_TERM_EN |
+		PHY_TERM_EN | CTRL_SHGATE);
+	/*
+	 * Update DLL Information:
+	 * Force DLL Resyncronization
+	 */
+	val |= FP_RSYNC;
+	writel(val, &dmc->phycontrol0);
+
+	/* Reset Force DLL Resyncronization */
+	val &= ~FP_RSYNC;
+	writel(val, &dmc->phycontrol0);
+}
+
+static void config_memory(struct exynos5_dmc *dmc)
+{
+	/*
+	 * Dynamic Clock: Always Running
+	 * Memory Burst length: 8
+	 * Number of chips: 1
+	 * Memory Bus width: 32 bit
+	 * Memory Type: DDR3
+	 * Additional Latancy for PLL: 0 Cycle
+	 */
+	writel(DMC_MEMCONTROL_VAL, &dmc->memcontrol);
+
+	/*
+	 * Memory Configuration Chip 0
+	 * Address Mapping: Interleaved
+	 * Number of Column address Bits: 10 bits
+	 * Number of Rows Address Bits: 15
+	 * Number of Banks: 8
+	 */
+	writel(DMC_MEMCONFIG0_VAL, &dmc->memconfig0);
+
+	/*
+	 * Memory Configuration Chip 1
+	 * Address Mapping: Interleaved
+	 * Number of Column address Bits: 10 bits
+	 * Number of Rows Address Bits: 15
+	 * Number of Banks: 8
+	 */
+	writel(DMC_MEMCONFIG1_VAL, &dmc->memconfig1);
+
+	/*
+	 * Chip0: AXI
+	 * AXI Base Address: 0x40000000
+	 * AXI Base Address Mask: 0x7C0
+	 */
+	writel(DMC_MEMBASECONFIG0_VAL, &dmc->membaseconfig0);
+
+	/*
+	 * Chip1: AXI
+	 * AXI Base Address: 0x80000000
+	 * AXI Base Address Mask: 0x7C0
+	 */
+	writel(DMC_MEMBASECONFIG1_VAL, &dmc->membaseconfig1);
+}
+
+static void reset_phy_ctrl(void)
+{
+	struct exynos5_clock *clk = (struct exynos5_clock *)EXYNOS5_CLOCK_BASE;
+	writel(PHY_RESET_VAL, &clk->lpddr3phy_ctrl);
+	writel(PHY_SET_VAL, &clk->lpddr3phy_ctrl);
+	writel(PHY_RESET_VAL, &clk->lpddr3phy_ctrl);
+	writel(PHY_SET_VAL, &clk->lpddr3phy_ctrl);
+}
+
+static void config_zq(struct exynos5_phy_control *phy0_ctrl,
+			struct exynos5_phy_control *phy1_ctrl)
+{
+	unsigned long val = 0;
+	/*
+	 * ZQ Calibration:
+	 * Select Driver Strength,
+	 * long calibration for manual calibration
+	 */
+	val = PHY_CON16_RESET_VAL;
+	SET_ZQ_MODE_DDS_VAL(val);
+	SET_ZQ_MODE_TERM_VAL(val);
+	val = val | ZQ_CLK_DIV_EN | ZQ_CLK_EN;
+	writel(val, &phy0_ctrl->phy_con16);
+	writel(val, &phy1_ctrl->phy_con16);
+
+	writel(val, &phy0_ctrl->phy_con16);
+	writel(val, &phy1_ctrl->phy_con16);
+
+	/* ZQ_MANUAL_START: Enable */
+	val |= ZQ_MANUAL_STR;
+	writel(val, &phy0_ctrl->phy_con16);
+	writel(val, &phy1_ctrl->phy_con16);
+
+	sdelay(0x10000);
+	sdelay(0x10000);
+
+	/* ZQ_MANUAL_START: Disable */
+	val &= ~ZQ_MANUAL_STR;
+	writel(val, &phy0_ctrl->phy_con16);
+	writel(val, &phy1_ctrl->phy_con16);
+}
+
+void mem_ctrl_init()
+{
+	struct exynos5_clock *clk = (struct exynos5_clock *)EXYNOS5_CLOCK_BASE;
+	struct exynos5_phy_control *phy0_ctrl, *phy1_ctrl;
+	struct exynos5_dmc *dmc;
+	unsigned int val, tmp;
+
+	phy0_ctrl = (struct exynos5_phy_control *)EXYNOS5_DMC_PHY0_BASE;
+	phy1_ctrl = (struct exynos5_phy_control *)EXYNOS5_DMC_PHY1_BASE;
+	dmc = (struct exynos5_dmc *)EXYNOS5_DMC_CTRL_BASE;
+
+	writel(0x0, &clk->src_cdrex);
+	writel(CLK_DIV_CDREX_VAL, &clk->div_cdrex);
+
+	writel(MPLL_CON1_VAL, &clk->mpll_con1);
+	writel(MPLL_CON0_VAL, &clk->mpll_con0);
+	writel(BPLL_CON1_VAL, &clk->bpll_con1);
+	writel(BPLL_CON0_VAL, &clk->bpll_con0);
+
+	sdelay(0x10000);
+	sdelay(0x10000);
+	sdelay(0x10000);
+
+	writel(CLK_SRC_CDREX_VAL, &clk->src_cdrex);
+
+	sdelay(0x10000);
+
+	reset_phy_ctrl();
+
+	sdelay(0x10000);
+
+	/* Setting CTRL_FORCE value in MDLL control register*/
+	val = PHY_CON12_RESET_VAL;
+	SET_CTRL_FORCE_VAL(val, 0x33);
+	writel(val, &phy0_ctrl->phy_con12);
+	writel(val, &phy1_ctrl->phy_con12);
+
+	sdelay(0x10000);
+
+	update_reset_dll(dmc);
+
+	/*set Read Latance and Burst Length for PHY0 and PHY1 */
+	writel(PHY_CON42_VAL, &phy0_ctrl->phy_con42);
+	writel(PHY_CON42_VAL, &phy1_ctrl->phy_con42);
+
+	/* Setting Operation Mode: DDR3
+	*  Enabling byte_rdlvl
+	*/
+	val = CTRL_DDR_MODE(DDR3);
+	val |= BYTE_RDLVL_EN;
+	writel(val, &phy0_ctrl->phy_con0);
+	writel(val, &phy1_ctrl->phy_con0);
+
+	/* ZQ Calibration */
+	config_zq(phy0_ctrl, phy1_ctrl);
+
+	/* DQS, DQ: Signal, for LPDDR3: Always Set */
+	val = CTRL_PULLD_DQ | CTRL_PULLD_DQS;
+	writel(val, &phy0_ctrl->phy_con14);
+	writel(val, &phy1_ctrl->phy_con14);
+
+	/* Set DMC Concontrol
+	*  dfi_init_start = 1
+	*  rd_fetch = 0x3
+	*  empty = 0
+	*/
+	val = DMC_CONCONTROL_RESET_VAL;
+	SET_RD_FETCH(val);
+	val |= DFI_INIT_START;
+	val &= ~EMPTY;
+	writel(val, &dmc->concontrol);
+
+	update_reset_dll(dmc);
+
+	/* Set DQS offsets */
+	writel(DDR3_PHY0_DQS, &phy0_ctrl->phy_con4);
+	writel(DDR3_PHY1_DQS, &phy1_ctrl->phy_con4);
+
+	/* Set DQS offsets */
+	writel(DDR3_PHY0_DQ, &phy0_ctrl->phy_con6);
+	writel(DDR3_PHY1_DQ, &phy1_ctrl->phy_con6);
+
+	/* Set Debug offsets */
+	writel(RESET_DEBUG_OFFSET_VAL, &phy0_ctrl->phy_con10);
+	writel(RESET_DEBUG_OFFSET_VAL, &phy1_ctrl->phy_con10);
+
+	/* Reset DLL Locking */
+	val = PHY_CON12_RESET_VAL;
+	CONFIG_CTRL_START(val, RESET);
+	writel(val, &phy0_ctrl->phy_con12);
+	writel(val, &phy1_ctrl->phy_con12);
+	sdelay(0x10000);
+	val = PHY_CON12_RESET_VAL;
+	CONFIG_CTRL_START(val, SET);
+	writel(val, &phy0_ctrl->phy_con12);
+	writel(val, &phy1_ctrl->phy_con12);
+
+	sdelay(0x10000);
+	sdelay(0x10000);
+
+	update_reset_dll(dmc);
+	update_reset_dll(dmc);
+
+	/* Set DMC Concontrol
+	*  rd_fetch = 0x3
+	*  empty = 0
+	*  Basically here we are stopping dfi_init_start done above.
+	*/
+	val = DMC_CONCONTROL_RESET_VAL;
+	SET_RD_FETCH(val);
+	val &= ~EMPTY;
+	writel(val, &dmc->concontrol);
+
+	config_memory(dmc);
+
+	/* Memory Channel Inteleaving Size: 128 Bytes */
+	writel(CONFIG_IV_SIZE, &dmc->ivcontrol);
+
+	/* Precharge Configuration */
+	writel(DMC_PRECHCONFIG_VAL, &dmc->prechconfig);
+
+	/* Power Down mode Configuration */
+	writel(DMC_PWRDNCONFIG_VAL, &dmc->pwrdnconfig);
+
+	/* Periodic Refresh Interval */
+	writel(DMC_TIMINGREF_VAL, &dmc->timingref);
+
+	/*
+	 * TimingRow, TimingData, TimingPower Setting:
+	 * Values as per Memory AC Parameters
+	 */
+	writel(DMC_TIMINGROW_VAL, &dmc->timingrow);
+
+	writel(DMC_TIMINGDATA_VAL, &dmc->timingdata);
+
+	writel(DMC_TIMINGPOWER_VAL, &dmc->timingpower);
+
+	dmc_directcmd(dmc);
+
+	/* Updating MDLL control register*/
+	val = readl(&phy0_ctrl->phy_con13);
+	val &= (0x3F << 10);
+	val >>= 2;
+	tmp = PHY_CON12_RESET_VAL;
+	CONFIG_CTRL_DLL_ON(tmp, RESET);
+	val += tmp;
+	writel(val, &phy0_ctrl->phy_con12);
+
+	val = readl(&phy1_ctrl->phy_con13);
+	val &= (0x3F << 10);
+	val >>= 2;
+	tmp = PHY_CON12_RESET_VAL;
+	CONFIG_CTRL_DLL_ON(tmp, RESET);
+	val += tmp;
+	writel(val, &phy1_ctrl->phy_con12);
+
+	sdelay(0x10000);
+
+	update_reset_dll(dmc);
+
+	writel(SET_RDLVL_RDDATA_ADJ, &phy0_ctrl->phy_con1);
+	writel(SET_RDLVL_RDDATA_ADJ, &phy1_ctrl->phy_con1);
+
+	writel(DDR3_ADDR, &phy0_ctrl->phy_con24);
+	writel(DDR3_ADDR, &phy1_ctrl->phy_con24);
+
+	/* Set rddata margin as 0x2
+	*  Enabling byte_rdlvl
+	*/
+	val = SET_T_RDDATA_MARGIN(0x2);
+	val |= BYTE_RDLVL_EN;
+	writel(val, &phy0_ctrl->phy_con0);
+	writel(val, &phy1_ctrl->phy_con0);
+
+	/* Enable Read Leveling */
+	val = PHY_CON2_RESET_VAL | RDLVL_EN;
+	writel(val, &phy0_ctrl->phy_con2);
+	writel(val, &phy1_ctrl->phy_con2);
+
+	/* Enable data eye training*/
+	val = RDLVL_CONFIG_RESET_VAL | CTRL_RDLVL_DATA_EN;
+	writel(val, &dmc->rdlvl_config);
+
+	sdelay(0x10000);
+
+	/* Disable data eye training*/
+	val = RDLVL_CONFIG_RESET_VAL & ~CTRL_RDLVL_DATA_EN;
+	writel(val, &dmc->rdlvl_config);
+
+	/* Updating MDLL control register*/
+	val = readl(&phy0_ctrl->phy_con13);
+	val &= (0x3F << 10);
+	val >>= 2;
+	tmp = PHY_CON12_RESET_VAL;
+	CONFIG_CTRL_DLL_ON(tmp, SET);
+	val += tmp;
+	writel(val, &phy0_ctrl->phy_con12);
+
+	val = readl(&phy1_ctrl->phy_con13);
+	val &= (0x3F << 10);
+	val >>= 2;
+	tmp = PHY_CON12_RESET_VAL;
+	CONFIG_CTRL_DLL_ON(tmp, SET);
+	val += tmp;
+	writel(val, &phy1_ctrl->phy_con12);
+
+	sdelay(0x10000);
+
+	update_reset_dll(dmc);
+
+	dmc_directcmd_PALL(dmc);
+
+	update_reset_dll(dmc);
+
+	sdelay(0x10000);
+
+	/* Set rddata margin as 0x2
+	*  Enabling byte_rdlvl
+	*/
+	val = SET_T_RDDATA_MARGIN(0x2);
+	val |= BYTE_RDLVL_EN;
+	writel(val, &phy0_ctrl->phy_con0);
+	writel(val, &phy1_ctrl->phy_con0);
+
+	/* Enable Read Leveling */
+	writel(SET_RDLVL_RDDATA_ADJ, &phy0_ctrl->phy_con1);
+	writel(SET_RDLVL_RDDATA_ADJ, &phy1_ctrl->phy_con1);
+
+	/*
+	 * Dynamic Clock: Always Running
+	 * Memory Burst length: 8
+	 * Number of chips: 1
+	 * Memory Bus width: 32 bit
+	 * Memory Type: DDR3
+	 * Additional Latancy for PLL: 0 Cycle
+	 */
+	writel(DMC_MEMCONTROL_VAL, &dmc->memcontrol);
+
+	/* Set DMC Concontrol
+	*  rd_fetch = 0x3
+	*  empty = 0
+	*  Auto refresh counter enable
+	*/
+	val = DMC_CONCONTROL_RESET_VAL;
+	SET_RD_FETCH(val);
+	val &= ~EMPTY;
+	val |= AREF_EN;
+	writel(val, &dmc->concontrol);
+}
diff --git a/board/samsung/smdk5250/setup.h b/board/samsung/smdk5250/setup.h
index 1276fd3..2d7e5a4 100644
--- a/board/samsung/smdk5250/setup.h
+++ b/board/samsung/smdk5250/setup.h
@@ -113,8 +113,13 @@
 #define VPLL_CON1_VAL	0x00000000
 #define VPLL_CON2_VAL	0x00000080
 
+#ifdef CONFIG_LPDDR2
 #define BPLL_MDIV	0x215
 #define BPLL_PDIV	0xC
+#elif defined CONFIG_DDR3
+#define BPLL_MDIV	0x185
+#define BPLL_PDIV	0x7
+#endif
 #define BPLL_SDIV	0x1
 
 #define BPLL_CON1_VAL	0x00203800
@@ -154,13 +159,19 @@
 #define MCLK_CDREX_RATIO	0x0
 #define ACLK_C2C_200_RATIO	0x1
 #define C2C_CLK_400_RATIO	0x1
+#ifdef CONFIG_DDR3
+#define PCLK_CDREX_RATIO	0x4	/* CDREX = 667 Mhz*/
+#else
 #define PCLK_CDREX_RATIO	0x3
+#endif
 #define ACLK_CDREX_RATIO	0x1
-#define CLK_DIV_CDREX_VAL	((MCLK_DPHY_RATIO << 20) \
-				| (MCLK_CDREX_RATIO << 16) \
+#define CLK_DIV_CDREX_VAL	((MCLK_CDREX2_RATIO << 28)   \
+				| (ACLK_EFCON_RATIO << 24)   \
+				| (MCLK_DPHY_RATIO << 20)    \
+				| (MCLK_CDREX_RATIO << 16)   \
 				| (ACLK_C2C_200_RATIO << 12) \
-				| (C2C_CLK_400_RATIO << 8) \
-				| (PCLK_CDREX_RATIO << 4) \
+				| (C2C_CLK_400_RATIO << 8)   \
+				| (PCLK_CDREX_RATIO << 4)    \
 				| (ACLK_CDREX_RATIO))
 
 #define MCLK_EFPHY_RATIO	0x4
@@ -354,12 +365,18 @@
 #define CONFIG_IV_SIZE		0x07
 
 #define PHY_RESET_VAL	(0 << 0)
+#define PHY_SET_VAL	(1 << 0)
 
 /*ZQ Configurations */
 #define PHY_CON16_RESET_VAL	0x08000304
-
+#define ZQ_CLK_EN		(1 << 27)
+#ifdef CONFIG_LPDDR2
 #define ZQ_MODE_DDS_VAL		(0x5 << 24)
 #define ZQ_MODE_TERM_VAL	(0x5 << 21)
+#elif defined CONFIG_DDR3
+#define ZQ_MODE_DDS_VAL		(0x7 << 24)
+#define ZQ_MODE_TERM_VAL	(0x2 << 21)
+#endif
 #define SET_ZQ_MODE_DDS_VAL(x)	(x = (x & ~(0x7 << 24)) | ZQ_MODE_DDS_VAL)
 #define SET_ZQ_MODE_TERM_VAL(x)	(x = (x & ~(0x7 << 21)) | ZQ_MODE_TERM_VAL)
 
@@ -376,55 +393,107 @@
 
 /* Diret Command */
 #define	DIRECT_CMD_NOP		0x07000000
+#define	DIRECT_CMD_PALL		0x01000000
+#define	DIRECT_CMD_ZQINIT	0x0A000000
+#ifdef CONFIG_LPDDR2
 #define DIRECT_CMD_MRS1		0x00071C00
 #define DIRECT_CMD_MRS2		0x00010BFC
 #define DIRECT_CMD_MRS3		0x00000708
 #define DIRECT_CMD_MRS4		0x00000818
-#define	DIRECT_CMD_PALL		0x01000000
+#elif defined CONFIG_DDR3
+#define DIRECT_CMD_MRS1		0x00020010	/* CDREX = 667Mhz*/
+#define DIRECT_CMD_MRS2		0x00030000
+#define DIRECT_CMD_MRS3		0x00010042
+#define DIRECT_CMD_MRS4		0x00000B50	/* CDREX = 667Mhz*/
+#endif
 
-/* DLL Resync */
-#define FP_RSYNC		(1 << 3)
+/* DMC PHY Control0 register */
+#define PHY_CONTROL0_RESET_VAL	0x0
+#define MEM_TERM_EN	(1 << 31)	/*Termination enable for memory*/
+#define PHY_TERM_EN	(1 << 30)	/*Termination enable for PHY*/
+#define CTRL_SHGATE	(1 << 29)	/*Duration of DQS gating signal*/
+#define FP_RSYNC	(1 << 3)	/*Force DLL resyncronization*/
 
+/* MDLL control */
+#define PHY_CON12_RESET_VAL		0x10100070
 #define CONFIG_CTRL_DLL_ON(x, y)	(x = (x & ~(1 << 5)) | y << 5)
 #define CONFIG_CTRL_START(x, y)		(x = (x & ~(1 << 6)) | y << 6)
 #define SET_CTRL_FORCE_VAL(x, y)	(x = (x & ~(0x7F << 8)) | y << 8)
 
-/* RDLVL */
-#define PHY_CON0_RESET_VAL	0x17023240
-#define DDR_MODE_LPDDR2		0x2
+/* PHY Control */
+#define PHY_CON0_RESET_VAL	0x17020A40
+#define DDR3			0x1
+#define LPDDR2			0x2
+#define LPDDR3			0x3
 #define BYTE_RDLVL_EN		(1 << 13)
 #define CTRL_ATGATE		(1 << 6)
-#define SET_CTRL_DDR_MODE(x, y)	(x = (x & ~(0x3 << 11)) | y << 11)
+#define CTRL_DDR_MODE(x)	((PHY_CON0_RESET_VAL & ~(0x3 << 11))	\
+				|(x << 11))
+#define SET_T_RDDATA_MARGIN(x)	((PHY_CON0_RESET_VAL & ~(0x7 << 17))	\
+				|(x << 17))
+
+#define PHY_CON1_RESET_VAL	0x09210100
+#ifdef CONFIG_DDR3
+#define RDLVL_RDDATA_ADJ	0xFF00
+#elif defined CONFIG_LPDDR2
+#define RDLVL_RDDATA_ADJ	0x1
+#endif
+#define SET_RDLVL_RDDATA_ADJ	((PHY_CON1_RESET_VAL & ~(0xFFFF << 0))\
+					| RDLVL_RDDATA_ADJ << 0)
 
-#define PHY_CON1_RESET_VAL	0x9210100
-#define RDLVL_RDDATAPADJ	0x1
-#define SET_RDLVL_RDDATAPADJ	((PHY_CON1_RESET_VAL & ~(0xFFFF << 0))\
-					| RDLVL_RDDATAPADJ << 0)
+#define DDR3_ADDR		0x0208
 
 #define PHY_CON2_RESET_VAL	0x00010004
 #define RDLVL_EN		(1 << 25)
 #define RDDSKEW_CLEAR		(1 << 13)
 
+#define RDLVL_CONFIG_RESET_VAL	0x0
 #define CTRL_RDLVL_DATA_EN	(1 << 1)
 #define LPDDR2_ADDR		0x00000208
 
-#define DMC_MEMCONFIG0_VAL	0x00001323
-#define DMC_MEMCONFIG1_VAL	0x00001323
 #define DMC_MEMBASECONFIG0_VAL	0x00400780
 #define DMC_MEMBASECONFIG1_VAL	0x00800780
+#ifdef CONFIG_LPDDR2
 #define DMC_MEMCONTROL_VAL	0x00212500
+#define DMC_MEMCONFIG0_VAL	0x00001323
+#define DMC_MEMCONFIG1_VAL	0x00001323
+#elif defined CONFIG_DDR3
+#define DMC_MEMCONTROL_VAL	0x00302600
+#define DMC_MEMCONFIG0_VAL	0x00001333
+#define DMC_MEMCONFIG1_VAL	0x00001333
+#endif
+
 #define DMC_PRECHCONFIG_VAL		0xFF000000
 #define DMC_PWRDNCONFIG_VAL		0xFFFF00FF
+#ifdef CONFIG_LPDDR2
 #define DMC_TIMINGREF_VAL		0x0000005D
 #define DMC_TIMINGROW_VAL		0x2336544C
 #define DMC_TIMINGDATA_VAL		0x24202408
 #define DMC_TIMINGPOWER_VAL		0x38260235
+#elif defined CONFIG_DDR3
+#define DMC_TIMINGREF_VAL		0x000000BB
+#define DMC_TIMINGROW_VAL		0x7645644d	/* CDREX = 667 Mhz*/
+#define DMC_TIMINGDATA_VAL		0x45414709	/* CDREX = 667 Mhz*/
+#define DMC_TIMINGPOWER_VAL		0x3a000a3c	/* CDREX = 667 Mhz*/
+#endif
 
+#ifdef CONFIG_LPDDR2
 #define CTRL_BSTLEN		0x04
 #define CTRL_RDLAT		0x08
+#elif defined CONFIG_DDR3
+#define CTRL_BSTLEN		0x08
+#define CTRL_RDLAT		0x09	/* CDREX = 667 Mhz*/
+#endif
 #define PHY_CON42_VAL		(CTRL_BSTLEN << 8 | CTRL_RDLAT << 0)
 
 /* DQS, DQ, DEBUG offsets */
+#ifdef CONFIG_DDR3		/* CDREX = 667 Mhz */
+#define DDR3_PHY0_DQS		0x08080808
+#define DDR3_PHY1_DQS		0x08080808
+#define DDR3_PHY0_DQ		0x08080808
+#define DDR3_PHY1_DQ		0x00080808
+#endif
+
 #define	SET_DQS_OFFSET_VAL	0x7F7F7F7F
 #define	SET_DQ_OFFSET_VAL	0x7F7F7F7F
 #define	SET_DEBUG_OFFSET_VAL	0x7F
@@ -436,13 +505,21 @@
 #define CTRL_PULLD_DQ		(0x0F << 8)
 #define CTRL_PULLD_DQS		(0x0F << 0)
 
+#define DMC_CONCONTROL_RESET_VAL	0x0FFF1100
+#ifdef CONFIG_LPDDR2
+#define RD_FETCH			0x3
+#elif defined CONFIG_DDR3
+#define RD_FETCH			0x2	/* CDREX = 667 Mhz */
+#endif
+#define SET_RD_FETCH(x)		(x = (x & ~(0x7 << 12)) | RD_FETCH << 12)
 #define DFI_INIT_START		(1 << 28)
+#define EMPTY			(1 << 8)
+#define AREF_EN			(1 << 5)
 
 #define CLK_STOP_EN	(1 << 0)
 #define DPWRDN_EN	(1 << 1)
 #define DSREF_EN	(1 << 5)
 
-#define AREF_EN			(1 << 5)
 void sdelay(unsigned long);
 void mem_ctrl_init(void);
 void system_clock_init(void);
diff --git a/include/configs/smdk5250.h b/include/configs/smdk5250.h
index f54d7ac..11a8f4d 100644
--- a/include/configs/smdk5250.h
+++ b/include/configs/smdk5250.h
@@ -37,6 +37,14 @@
 #define CONFIG_DISPLAY_CPUINFO
 #define CONFIG_DISPLAY_BOARDINFO
 
+/* Choose DDR Type below
+ *  * Uncomment the type of DDR present on your board
+ *   */
+#define CONFIG_DDR3
+/*
+ * #define CONFIG_LPDDR2
+ */
+
 /* Keep L2 Cache Disabled */
 #define CONFIG_SYS_DCACHE_OFF
 
-- 
1.7.2.3



More information about the U-Boot mailing list