[coreboot-gerrit] Patch set updated for coreboot: cb4f394 PIT: memory setup

Gabe Black (gabeblack@chromium.org) gerrit at coreboot.org
Wed Jul 10 04:01:09 CEST 2013


Gabe Black (gabeblack at chromium.org) just uploaded a new patch set to gerrit, which you can find at http://review.coreboot.org/3677

-gerrit

commit cb4f3947ef2c4bc8cfa196c8e884d2f115efedec
Author: Ronald G. Minnich <rminnich at google.com>
Date:   Mon Jun 3 13:03:50 2013 -0700

    PIT: memory setup
    
    Tested and working. Gets us to ramstage.
    
    Change-Id: Ib9ea4a6c912e8152246aaf4f1f084a4aa1626053
    Signed-off-by: Ronald G. Minnich <rminnich at google.com>
    Signed-off-by: Gabe Black <gabeblack at chromium.org>
---
 src/cpu/samsung/exynos5420/clock_init.c    |   1 +
 src/cpu/samsung/exynos5420/cpu.h           |  76 +++++
 src/cpu/samsung/exynos5420/dmc.h           | 208 ++++++++-----
 src/cpu/samsung/exynos5420/dmc_common.c    |  11 +-
 src/cpu/samsung/exynos5420/dmc_init_ddr3.c | 459 +++++++++++++++++------------
 src/cpu/samsung/exynos5420/power.c         |   1 +
 src/cpu/samsung/exynos5420/setup.h         | 158 +++++++++-
 src/mainboard/google/pit/Kconfig           |   1 +
 src/mainboard/google/pit/memory.c          | 457 +---------------------------
 src/mainboard/google/pit/romstage.c        |  97 +++++-
 10 files changed, 738 insertions(+), 731 deletions(-)

diff --git a/src/cpu/samsung/exynos5420/clock_init.c b/src/cpu/samsung/exynos5420/clock_init.c
index 0a13c9e..2ce975c 100644
--- a/src/cpu/samsung/exynos5420/clock_init.c
+++ b/src/cpu/samsung/exynos5420/clock_init.c
@@ -24,6 +24,7 @@
 #include "clk.h"
 #include "cpu.h"
 #include "dp.h"
+#include "dmc.h"
 #include "setup.h"
 
 void system_clock_init(void)
diff --git a/src/cpu/samsung/exynos5420/cpu.h b/src/cpu/samsung/exynos5420/cpu.h
index 7cdd35e..05be3cc 100644
--- a/src/cpu/samsung/exynos5420/cpu.h
+++ b/src/cpu/samsung/exynos5420/cpu.h
@@ -93,6 +93,82 @@
 /* Distance between each Trust Zone PC register set */
 #define TZPC_BASE_OFFSET		0x10000
 
+/* EXYNOS5420 Common*/
+#define EXYNOS5420_I2C_SPACING		0x10000
+
+#define EXYNOS5420_GPIO_PART6_BASE	0x03860000
+#define EXYNOS5420_PRO_ID		0x10000000
+#define EXYNOS5420_CLOCK_BASE		0x10010000
+#define EXYNOS5420_POWER_BASE		0x10040000
+#define EXYNOS5420_SWRESET		0x10040400
+#define EXYNOS5420_SYSREG_BASE		0x10050000
+#define EXYNOS5420_WATCHDOG_BASE	0x101D0000
+#define EXYNOS5420_DMC_PHY0_BASE	0x10C00000
+#define EXYNOS5420_DMC_PHY1_BASE	0x10C10000
+#define EXYNOS5420_DMC_DREXI_0		0x10C20000
+#define EXYNOS5420_DMC_DREXI_1		0x10C30000
+#define EXYNOS5420_DMC_TZASC_0		0x10D40000
+#define EXYNOS5420_DMC_TZASC_1		0x10D50000
+#define EXYNOS5420_USB_HOST_XHCI_BASE	0x12000000
+#define EXYNOS5420_USB3PHY_BASE		0x12100000
+#define EXYNOS5420_USB_HOST_EHCI_BASE	0x12110000
+#define EXYNOS5420_MMC_BASE		0x12200000
+#define EXYNOS5420_SROMC_BASE		0x12250000
+#define EXYNOS5420_UART_BASE		0x12C00000
+#define EXYNOS5420_I2C_BASE		0x12C60000
+#define EXYNOS5420_I2C_8910_BASE	0x12E00000
+#define EXYNOS5420_SPI_BASE		0x12D20000
+#define EXYNOS5420_I2S_BASE		0x12D60000
+#define EXYNOS5420_PWMTIMER_BASE	0x12DD0000
+#define EXYNOS5420_SPI_ISP_BASE		0x131A0000
+#define EXYNOS5420_GPIO_PART2_BASE	0x13400000
+#define EXYNOS5420_GPIO_PART3_BASE	0x13400C00
+#define EXYNOS5420_GPIO_PART4_BASE	0x13410000
+#define EXYNOS5420_GPIO_PART5_BASE	0x14000000
+#define EXYNOS5420_GPIO_PART1_BASE	0x14010000
+#define EXYNOS5420_MIPI_DSIM_BASE	0x14500000
+#define EXYNOS5420_DP_BASE		0x145B0000
+#define EXYNOS5420_INF_REG_BASE		0x10040800
+
+#define EXYNOS5420_USBPHY_BASE		DEVICE_NOT_AVAILABLE
+#define EXYNOS5420_USBOTG_BASE		DEVICE_NOT_AVAILABLE
+#define EXYNOS5420_FIMD_BASE		DEVICE_NOT_AVAILABLE
+#define EXYNOS5420_ADC_BASE		DEVICE_NOT_AVAILABLE
+#define EXYNOS5420_MODEM_BASE		DEVICE_NOT_AVAILABLE
+
+#define ARM_CORE0_CONFIG		(EXYNOS5420_POWER_BASE + 0x2000)
+#define ARM_CORE0_STATUS		(EXYNOS5420_POWER_BASE + 0x2004)
+#define CORE_CONFIG_OFFSET		0x80
+#define CORE_COUNT			0x8
+
+/*
+ * POWER
+ */
+#define PMU_BASE			EXYNOS5420_POWER_BASE
+#define SW_RST_REG_OFFSET		0x400
+
+#define INF_REG_BASE			EXYNOS5420_INF_REG_BASE
+#define INF_REG0_OFFSET			0x00
+#define INF_REG1_OFFSET			0x04
+#define INF_REG2_OFFSET			0x08
+#define INF_REG3_OFFSET			0x0C
+#define INF_REG4_OFFSET			0x10
+#define INF_REG5_OFFSET			0x14
+#define INF_REG6_OFFSET			0x18
+#define INF_REG7_OFFSET			0x1C
+
+#define PMU_SPARE_BASE			(EXYNOS5420_INF_REG_BASE + 0x100)
+#define PMU_SPARE_0			PMU_SPARE_BASE
+#define PMU_SPARE_1			(PMU_SPARE_BASE + 0x4)
+#define PMU_SPARE_2			(PMU_SPARE_BASE + 0x8)
+#define PMU_SPARE_3			(PMU_SPARE_BASE + 0xc)
+#define RST_FLAG_REG			PMU_SPARE_BASE
+#define RST_FLAG_VAL			0xfcba0d10
+
+#define PAD_RETENTION_DRAM_STATUS	(EXYNOS5420_POWER_BASE + 0x3004)
+#define PAD_RETENTION_DRAM_COREBLK_OPTION	(EXYNOS5420_POWER_BASE + 0x31E8)
+#define PAD_RETENTION_DRAM_COREBLK_VAL	0x10000000
+
 #define samsung_get_base_adc() ((struct exynos5_adc *)EXYNOS5_ADC_BASE)
 #define samsung_get_base_clock() ((struct exynos5_clock *)EXYNOS5_CLOCK_BASE)
 #define samsung_get_base_ace_sfr() ((struct exynos5_ace_sfr *)EXYNOS5_ACE_SFR_BASE)
diff --git a/src/cpu/samsung/exynos5420/dmc.h b/src/cpu/samsung/exynos5420/dmc.h
index cd5ff23..df7797d 100644
--- a/src/cpu/samsung/exynos5420/dmc.h
+++ b/src/cpu/samsung/exynos5420/dmc.h
@@ -18,17 +18,68 @@
 #ifndef CPU_SAMSUNG_EXYNOS5420_DMC_H
 #define CPU_SAMSUNG_EXYNOS5420_DMC_H
 
+#define DMC_INTERLEAVE_SIZE		0x1f
+
+/* CONCONTROL register fields */
+#define CONCONTROL_DFI_INIT_START_SHIFT	28
+#define CONCONTROL_RD_FETCH_SHIFT	12
+#define CONCONTROL_RD_FETCH_MASK	(0x7 << CONCONTROL_RD_FETCH_SHIFT)
+#define CONCONTROL_AREF_EN_SHIFT	5
+
+/* PRECHCONFIG register field */
+#define PRECHCONFIG_TP_CNT_SHIFT	24
+
+/* PWRDNCONFIG register field */
+#define PWRDNCONFIG_DPWRDN_CYC_SHIFT	0
+#define PWRDNCONFIG_DSREF_CYC_SHIFT	16
+
+/* PHY_CON0 register fields */
+#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_MASK	0x3
+#define PHY_CON0_CTRL_DDR_MODE_SHIFT	11
+
+/* PHY_CON1 register fields */
+#define PHY_CON1_RDLVL_RDDATA_ADJ_SHIFT	0
+
+/* PHY_CON12 register fields */
+#define PHY_CON12_CTRL_START_POINT_SHIFT	24
+#define PHY_CON12_CTRL_INC_SHIFT	16
+#define PHY_CON12_CTRL_FORCE_SHIFT	8
+#define PHY_CON12_CTRL_START_SHIFT	6
+#define PHY_CON12_CTRL_START_MASK	(1 << PHY_CON12_CTRL_START_SHIFT)
+#define PHY_CON12_CTRL_DLL_ON_SHIFT	5
+#define PHY_CON12_CTRL_DLL_ON_MASK	(1 << PHY_CON12_CTRL_DLL_ON_SHIFT)
+#define PHY_CON12_CTRL_REF_SHIFT	1
+
+/* PHY_CON16 register fields */
+#define PHY_CON16_ZQ_MODE_DDS_SHIFT	24
+#define PHY_CON16_ZQ_MODE_DDS_MASK	(0x7 << PHY_CON16_ZQ_MODE_DDS_SHIFT)
+
+#define PHY_CON16_ZQ_MODE_TERM_SHIFT 21
+#define PHY_CON16_ZQ_MODE_TERM_MASK	(0x7 << PHY_CON16_ZQ_MODE_TERM_SHIFT)
+
+#define PHY_CON16_ZQ_MODE_NOTERM_MASK	(1 << 19)
+
+/* PHY_CON42 register fields */
+#define PHY_CON42_CTRL_BSTLEN_SHIFT	8
+#define PHY_CON42_CTRL_BSTLEN_MASK	(0xff << PHY_CON42_CTRL_BSTLEN_SHIFT)
+
+#define PHY_CON42_CTRL_RDLAT_SHIFT	0
+#define PHY_CON42_CTRL_RDLAT_MASK	(0x1f << PHY_CON42_CTRL_RDLAT_SHIFT)
+
 #ifndef __ASSEMBLER__
 struct exynos5_dmc {
 	unsigned int concontrol;
 	unsigned int memcontrol;
-	unsigned int memconfig0;
+	unsigned int cgcontrol;
 	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;
@@ -36,12 +87,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];
@@ -72,45 +123,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 {
@@ -160,6 +249,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,
@@ -196,54 +294,6 @@ enum {
 	MEM_TIMINGS_MSR_COUNT	= 4,
 };
 
-#define DMC_INTERLEAVE_SIZE		0x1f
-
-/* CONCONTROL register fields */
-#define CONCONTROL_DFI_INIT_START_SHIFT	28
-#define CONCONTROL_RD_FETCH_SHIFT	12
-#define CONCONTROL_RD_FETCH_MASK	(0x7 << CONCONTROL_RD_FETCH_SHIFT)
-#define CONCONTROL_AREF_EN_SHIFT	5
-
-/* PRECHCONFIG register field */
-#define PRECHCONFIG_TP_CNT_SHIFT	24
-
-/* PWRDNCONFIG register field */
-#define PWRDNCONFIG_DPWRDN_CYC_SHIFT	0
-#define PWRDNCONFIG_DSREF_CYC_SHIFT	16
-
-/* PHY_CON0 register fields */
-#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
-
-/* PHY_CON1 register fields */
-#define PHY_CON1_RDLVL_RDDATA_ADJ_SHIFT	0
-
-/* PHY_CON12 register fields */
-#define PHY_CON12_CTRL_START_POINT_SHIFT	24
-#define PHY_CON12_CTRL_INC_SHIFT	16
-#define PHY_CON12_CTRL_FORCE_SHIFT	8
-#define PHY_CON12_CTRL_START_SHIFT	6
-#define PHY_CON12_CTRL_START_MASK	(1 << PHY_CON12_CTRL_START_SHIFT)
-#define PHY_CON12_CTRL_DLL_ON_SHIFT	5
-#define PHY_CON12_CTRL_DLL_ON_MASK	(1 << PHY_CON12_CTRL_DLL_ON_SHIFT)
-#define PHY_CON12_CTRL_REF_SHIFT	1
-
-/* PHY_CON16 register fields */
-#define PHY_CON16_ZQ_MODE_DDS_SHIFT	24
-#define PHY_CON16_ZQ_MODE_DDS_MASK	(0x7 << PHY_CON16_ZQ_MODE_DDS_SHIFT)
-
-#define PHY_CON16_ZQ_MODE_TERM_SHIFT 21
-#define PHY_CON16_ZQ_MODE_TERM_MASK	(0x7 << PHY_CON16_ZQ_MODE_TERM_SHIFT)
-
-#define PHY_CON16_ZQ_MODE_NOTERM_MASK	(1 << 19)
-
-/* PHY_CON42 register fields */
-#define PHY_CON42_CTRL_BSTLEN_SHIFT	8
-#define PHY_CON42_CTRL_BSTLEN_MASK	(0xff << PHY_CON42_CTRL_BSTLEN_SHIFT)
-
-#define PHY_CON42_CTRL_RDLAT_SHIFT	0
-#define PHY_CON42_CTRL_RDLAT_MASK	(0x1f << PHY_CON42_CTRL_RDLAT_SHIFT)
 
 /* These are the memory timings for a particular memory type and speed */
 struct mem_timings {
diff --git a/src/cpu/samsung/exynos5420/dmc_common.c b/src/cpu/samsung/exynos5420/dmc_common.c
index 3abc3d3..bef76d1 100644
--- a/src/cpu/samsung/exynos5420/dmc_common.c
+++ b/src/cpu/samsung/exynos5420/dmc_common.c
@@ -23,10 +23,9 @@
 #include <console/console.h>
 #include <arch/io.h>
 #include <delay.h>
-#include "setup.h"
 #include "dmc.h"
-#include "clk.h"
 #include "setup.h"
+#include "clk.h"
 
 #define ZQ_INIT_TIMEOUT	10000
 
@@ -173,11 +172,3 @@ 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);
-}
-
diff --git a/src/cpu/samsung/exynos5420/dmc_init_ddr3.c b/src/cpu/samsung/exynos5420/dmc_init_ddr3.c
index 2d78087..74ee7e9 100644
--- a/src/cpu/samsung/exynos5420/dmc_init_ddr3.c
+++ b/src/cpu/samsung/exynos5420/dmc_init_ddr3.c
@@ -1,11 +1,17 @@
 /*
  * This file is part of the coreboot project.
  *
+ * DDR3 mem setup file for EXYNOS5 based board
+ *
  * Copyright (C) 2012 Samsung Electronics
  *
- * 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; version 2 of the License.
+ * 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
@@ -14,181 +20,181 @@
  *
  * 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
  */
 
-/* DDR3 mem setup file for SMDK5420 board based on EXYNOS5 */
-
 #include <console/console.h>
 #include <delay.h>
 #include <arch/io.h>
-#include "clk.h"
-#include "cpu.h"
 #include "dmc.h"
 #include "setup.h"
+#include "cpu.h"
+#include "clk.h"
 
-#define RDLVL_COMPLETE_TIMEOUT	10000
+#define TIMEOUT	10000
 
-static void reset_phy_ctrl(void)
-{
-	struct exynos5_clock *clk = (struct exynos5_clock *)EXYNOS5_CLOCK_BASE;
-
-	writel(LPDDR3PHY_CTRL_PHY_RESET_OFF, &clk->lpddr3phy_ctrl);
-	writel(LPDDR3PHY_CTRL_PHY_RESET, &clk->lpddr3phy_ctrl);
-
-#if 0
-	/*
-	 * For proper memory initialization there should be a minimum delay of
-	 * 500us after the LPDDR3PHY_CTRL_PHY_RESET signal.
-	 * The below value is an approximate value whose calculation in done
-	 * considering that sdelay takes 2 instruction for every 1 delay cycle.
-	 * And assuming each instruction takes 1 clock cycle i.e 1/(1.7 Ghz)sec
-	 * So for 500 usec, the number of delay cycle should be
-	 * (500 * 10^-6) * (1.7 * 10^9) / 2 = 425000
-	 *
-	 * TODO(hatim.rv at samsung.com): Implement the delay using timer/counter
-	 */
-	sdelay(425000);
-#endif
-	udelay(500);
-}
+/* 'reset' field is currently ignored. */
 
-int ddr3_mem_ctrl_init(struct mem_timings *mem, unsigned long mem_iv_size,
-		       int mem_reset)
+int ddr3_mem_ctrl_init(struct mem_timings *mem, int interleave_size, int reset)
 {
-	unsigned int val;
+	struct exynos5420_clock *clk =
+		(struct exynos5420_clock *)EXYNOS5_CLOCK_BASE;
 	struct exynos5_phy_control *phy0_ctrl, *phy1_ctrl;
-	struct exynos5_dmc *dmc;
+	struct exynos5_dmc *drex0, *drex1;
+	struct exynos5_tzasc *tzasc0, *tzasc1;
+	u32 val, nLockR, nLockW_phy0, nLockW_phy1;
 	int i;
 
 	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;
-
-	if (mem_reset) {
-		printk(BIOS_SPEW, "%s: reset phy: ", __func__);
-		reset_phy_ctrl();
-		printk(BIOS_SPEW, "done\n");
-	} else {
-		printk(BIOS_SPEW, "%s: skip mem_reset.\n", __func__);
-	}
+	drex0 = (struct exynos5_dmc *)EXYNOS5420_DMC_DREXI_0;
+	drex1 = (struct exynos5_dmc *)EXYNOS5420_DMC_DREXI_1;
+	tzasc0 = (struct exynos5_tzasc *)EXYNOS5420_DMC_TZASC_0;
+	tzasc1 = (struct exynos5_tzasc *)EXYNOS5420_DMC_TZASC_1;
 
-	/* Set Impedance Output Driver */
-	printk(BIOS_SPEW, "ddr3_mem_ctrl_init: Set Impedance Output Driver\n");
-	printk(BIOS_SPEW, "ddr3_mem_ctrl_init: mem->impedance 0x%x\n",
-	       mem->impedance);
-	val = (mem->impedance << CA_CK_DRVR_DS_OFFSET) |
-		(mem->impedance << CA_CKE_DRVR_DS_OFFSET) |
-		(mem->impedance << CA_CS_DRVR_DS_OFFSET) |
-		(mem->impedance << CA_ADR_DRVR_DS_OFFSET);
-	printk(BIOS_SPEW, "ddr3_mem_ctrl_init: val 0x%x\n", val);
-	writel(val, &phy0_ctrl->phy_con39);
-	writel(val, &phy1_ctrl->phy_con39);
+	/* 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->clk_src_cdrex);
+	do {
+		val = readl(&clk->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 */
-	printk(BIOS_SPEW, "ddr3_mem_ctrl_init: "
-	       "Set Read Latency and Burst Length for PHY0 and PHY1\n");
 	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 0x6
+	 */
+	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 |= (0x6 << DA_3_DS_OFFSET) | (0x6 << DA_2_DS_OFFSET) |
+		(0x6 << DA_1_DS_OFFSET) | (0x6 << DA_0_DS_OFFSET);
+	writel(val, &phy0_ctrl->phy_con39);
+	writel(val, &phy1_ctrl->phy_con39);
+
 	/* ZQ Calibration */
-	printk(BIOS_SPEW, "ddr3_mem_ctrl_init: ZQ Calibration\n");
 	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 */
-	printk(BIOS_SPEW, "ddr3_mem_ctrl_init: DQ Signal\n");
 	writel(mem->phy0_pulld_dqs, &phy0_ctrl->phy_con14);
 	writel(mem->phy1_pulld_dqs, &phy1_ctrl->phy_con14);
 
-	writel(mem->concontrol | (mem->rd_fetch << CONCONTROL_RD_FETCH_SHIFT)
-		| (mem->dfi_init_start << CONCONTROL_DFI_INIT_START_SHIFT),
-		&dmc->concontrol);
-
-	update_reset_dll(dmc, DDR_MODE_DDR3);
-
-	/* DQS Signal */
-	printk(BIOS_SPEW, "ddr3_mem_ctrl_init: DQS Signal\n");
-	writel(mem->phy0_dqs, &phy0_ctrl->phy_con4);
-	writel(mem->phy1_dqs, &phy1_ctrl->phy_con4);
-
-	writel(mem->phy0_dq, &phy0_ctrl->phy_con6);
-	writel(mem->phy1_dq, &phy1_ctrl->phy_con6);
-
-	writel(mem->phy0_tFS, &phy0_ctrl->phy_con10);
-	writel(mem->phy1_tFS, &phy1_ctrl->phy_con10);
-
-	val = (mem->ctrl_start_point << PHY_CON12_CTRL_START_POINT_SHIFT) |
-		(mem->ctrl_inc << PHY_CON12_CTRL_INC_SHIFT) |
-		(mem->ctrl_dll_on << PHY_CON12_CTRL_DLL_ON_SHIFT) |
-		(mem->ctrl_ref << PHY_CON12_CTRL_REF_SHIFT);
-	writel(val, &phy0_ctrl->phy_con12);
-	writel(val, &phy1_ctrl->phy_con12);
-
-	/* Start DLL locking */
-	printk(BIOS_SPEW, "ddr3_mem_ctrl_init: Start DLL Locking\n");
-	writel(val | (mem->ctrl_start << PHY_CON12_CTRL_START_SHIFT),
-		&phy0_ctrl->phy_con12);
-	writel(val | (mem->ctrl_start << PHY_CON12_CTRL_START_SHIFT),
-		&phy1_ctrl->phy_con12);
-
-	update_reset_dll(dmc, DDR_MODE_DDR3);
-
-	writel(mem->concontrol | (mem->rd_fetch << CONCONTROL_RD_FETCH_SHIFT),
-		&dmc->concontrol);
-
-	/* Memory Channel Inteleaving Size */
-	printk(BIOS_SPEW, "ddr3_mem_ctrl_init: "
-	       "Memory Channel Inteleaving Size\n");
-	writel(mem->iv_size, &dmc->ivcontrol);
-
-	/* Set DMC MEMCONTROL register */
-	printk(BIOS_SPEW, "ddr3_mem_ctrl_init: Set DMC MEMCONTROL register\n");
-	val = mem->memcontrol & ~DMC_MEMCONTROL_DSREF_ENABLE;
-	writel(val, &dmc->memcontrol);
-
-	writel(mem->memconfig, &dmc->memconfig0);
-	writel(mem->memconfig, &dmc->memconfig1);
-	writel(mem->membaseconfig0, &dmc->membaseconfig0);
-	writel(mem->membaseconfig1, &dmc->membaseconfig1);
+	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
+	 * Exynos5420 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 */
-	printk(BIOS_SPEW, "ddr3_mem_ctrl_init: Precharge Configuration\n");
 	writel(mem->prechconfig_tp_cnt << PRECHCONFIG_TP_CNT_SHIFT,
-		&dmc->prechconfig);
-
-	/* Power Down mode Configuration */
-	printk(BIOS_SPEW, "ddr3_mem_ctrl_init: "
-	       "Power Down mode Configuraation\n");
-	writel(mem->dpwrdn_cyc << PWRDNCONFIG_DPWRDN_CYC_SHIFT |
-		mem->dsref_cyc << PWRDNCONFIG_DSREF_CYC_SHIFT,
-		&dmc->pwrdnconfig);
+		&drex0->prechconfig0);
+	writel(mem->prechconfig_tp_cnt << PRECHCONFIG_TP_CNT_SHIFT,
+		&drex1->prechconfig0);
 
 	/* TimingRow, TimingData, TimingPower and Timingaref
 	 * values as per Memory AC parameters
 	 */
-	printk(BIOS_SPEW, "ddr3_mem_ctrl_init: "
-	       "TimingRow, TimingData, TimingPower and Timingaref\n");
-	writel(mem->timing_ref, &dmc->timingref);
-	writel(mem->timing_row, &dmc->timingrow);
-	writel(mem->timing_data, &dmc->timingdata);
-	writel(mem->timing_power, &dmc->timingpower);
-
-	/* Send PALL command */
-	printk(BIOS_SPEW, "ddr3_mem_ctrl_init: Send PALL Command\n");
-	dmc_config_prech(mem, dmc);
+	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);
 
 	/* Send NOP, MRS and ZQINIT commands */
-	printk(BIOS_SPEW, "ddr3_mem_ctrl_init: Send NOP, MRS, and ZQINIT\n");
-	dmc_config_mrs(mem, dmc);
+	dmc_config_mrs(mem, drex0);
+	dmc_config_mrs(mem, drex1);
 
 	if (mem->gate_leveling_enable) {
-		val = PHY_CON0_RESET_VAL;
-		val |= P0_CMD_EN;
-		writel(val, &phy0_ctrl->phy_con0);
-		writel(val, &phy1_ctrl->phy_con0);
+
+		setbits_le32(&phy0_ctrl->phy_con0, CTRL_ATGATE);
+		setbits_le32(&phy1_ctrl->phy_con0, CTRL_ATGATE);
+
+		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;
@@ -201,38 +207,51 @@ int ddr3_mem_ctrl_init(struct mem_timings *mem, unsigned long mem_iv_size,
 		writel(val, &phy0_ctrl->phy_con0);
 		writel(val, &phy1_ctrl->phy_con0);
 
-		val = (mem->ctrl_start_point <<
-				PHY_CON12_CTRL_START_POINT_SHIFT) |
-			(mem->ctrl_inc << PHY_CON12_CTRL_INC_SHIFT) |
-			(mem->ctrl_force << PHY_CON12_CTRL_FORCE_SHIFT) |
-			(mem->ctrl_start << PHY_CON12_CTRL_START_SHIFT) |
-			(mem->ctrl_ref << PHY_CON12_CTRL_REF_SHIFT);
-		writel(val, &phy0_ctrl->phy_con12);
-		writel(val, &phy1_ctrl->phy_con12);
+		val =  readl(&phy0_ctrl->phy_con1);
+		val |= (RDLVL_PASS_ADJ_VAL << RDLVL_PASS_ADJ_OFFSET);
+		writel(val, &phy0_ctrl->phy_con1);
 
-		val = PHY_CON2_RESET_VAL;
-		val |= INIT_DESKEW_EN;
-		val |= RDLVL_GATE_EN;
-		writel(val, &phy0_ctrl->phy_con2);
-		writel(val, &phy1_ctrl->phy_con2);
+		val =  readl(&phy1_ctrl->phy_con1);
+		val |= (RDLVL_PASS_ADJ_VAL << RDLVL_PASS_ADJ_OFFSET);
+		writel(val, &phy1_ctrl->phy_con1);
 
-		val = PHY_CON0_RESET_VAL;
-		val |= P0_CMD_EN;
-		val |= BYTE_RDLVL_EN;
-		val |= CTRL_SHGATE;
-		writel(val, &phy0_ctrl->phy_con0);
-		writel(val, &phy1_ctrl->phy_con0);
+		nLockR = readl(&phy0_ctrl->phy_con13);
+		nLockW_phy0 = (nLockR & CTRL_LOCK_COARSE_MASK) >> 2;
+		nLockR = readl(&phy0_ctrl->phy_con12);
+		nLockR &= ~CTRL_DLL_ON;
+		nLockR |= nLockW_phy0;
+		writel(nLockR, &phy0_ctrl->phy_con12);
 
-		val = PHY_CON1_RESET_VAL;
+		nLockR = readl(&phy1_ctrl->phy_con13);
+		nLockW_phy1 = (nLockR & CTRL_LOCK_COARSE_MASK) >> 2;
+		nLockR = readl(&phy1_ctrl->phy_con12);
+		nLockR &= ~CTRL_DLL_ON;
+		nLockR |= nLockW_phy1;
+		writel(nLockR, &phy1_ctrl->phy_con12);
+
+		writel(0x00030004, &drex0->directcmd);
+		writel(0x00130004, &drex0->directcmd);
+		writel(0x00030004, &drex1->directcmd);
+		writel(0x00130004, &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, &dmc->rdlvl_config);
-		i = RDLVL_COMPLETE_TIMEOUT;
-		while ((readl(&dmc->phystatus) &
-			(RDLVL_COMPLETE_CHO | RDLVL_COMPLETE_CH1)) !=
-			(RDLVL_COMPLETE_CHO | RDLVL_COMPLETE_CH1) && i > 0) {
+		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
@@ -240,38 +259,116 @@ int ddr3_mem_ctrl_init(struct mem_timings *mem, unsigned long mem_iv_size,
 			udelay(1);
 			i--;
 		}
-		if (!i){
-			printk(BIOS_SPEW, "Timeout on RDLVL. No DRAM.\n");
+		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
+			 */
+			udelay(1);
+			i--;
 		}
-		writel(CTRL_RDLVL_GATE_DISABLE, &dmc->rdlvl_config);
+		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 = (mem->ctrl_start_point <<
-				PHY_CON12_CTRL_START_POINT_SHIFT) |
-			(mem->ctrl_inc << PHY_CON12_CTRL_INC_SHIFT) |
-			(mem->ctrl_force << PHY_CON12_CTRL_FORCE_SHIFT) |
-			(mem->ctrl_start << PHY_CON12_CTRL_START_SHIFT) |
-			(mem->ctrl_dll_on << PHY_CON12_CTRL_DLL_ON_SHIFT) |
-			(mem->ctrl_ref << PHY_CON12_CTRL_REF_SHIFT);
-		writel(val, &phy0_ctrl->phy_con12);
-		writel(val, &phy1_ctrl->phy_con12);
-
-		update_reset_dll(dmc, DDR_MODE_DDR3);
+		writel(0x00030000, &drex0->directcmd);
+		writel(0x00130000, &drex0->directcmd);
+		writel(0x00030000, &drex1->directcmd);
+		writel(0x00130000, &drex1->directcmd);
+
+		/* Set Read DQ Calibration */
+		writel(0x00030004, &drex0->directcmd);
+		writel(0x00130004, &drex0->directcmd);
+		writel(0x00030004, &drex1->directcmd);
+		writel(0x00130004, &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
+			 */
+			udelay(1);
+			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
+			 */
+			udelay(1);
+			i--;
+		}
+		if (!i)
+			return SETUP_ERR_RDLV_COMPLETE_TIMEOUT;
+		clrbits_le32(&drex1->rdlvl_config, CTRL_RDLVL_DATA_ENABLE);
+
+		writel(0x00030000, &drex0->directcmd);
+		writel(0x00130000, &drex0->directcmd);
+		writel(0x00030000, &drex1->directcmd);
+		writel(0x00130000, &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 + nLockW_phy0), &phy0_ctrl->phy_con12);
+		writel((val + nLockW_phy1), &phy1_ctrl->phy_con12);
+
+		setbits_le32(&phy0_ctrl->phy_con2, DLL_DESKEW_EN);
+		setbits_le32(&phy1_ctrl->phy_con2, DLL_DESKEW_EN);
+
+		update_reset_dll(drex0, DDR_MODE_DDR3);
+		update_reset_dll(drex1, DDR_MODE_DDR3);
 	}
 
 	/* Send PALL command */
-	printk(BIOS_SPEW, "ddr3_mem_ctrl_init: Send PALL Command\n");
-	dmc_config_prech(mem, dmc);
+	dmc_config_prech(mem, drex0);
+	dmc_config_prech(mem, drex1);
 
-	writel(mem->memcontrol, &dmc->memcontrol);
+	writel(mem->memcontrol, &drex0->memcontrol);
+	writel(mem->memcontrol, &drex1->memcontrol);
 
 	/* Set DMC Concontrol and enable auto-refresh counter */
-	printk(BIOS_SPEW, "ddr3_mem_ctrl_init: "
-	       "Set DMC Concontrol and enable auto-refresh counter\n");
-	writel(mem->concontrol | (mem->rd_fetch << CONCONTROL_RD_FETCH_SHIFT)
-		| (mem->aref_en << CONCONTROL_AREF_EN_SHIFT), &dmc->concontrol);
+	writel(mem->concontrol | (mem->aref_en << CONCONTROL_AREF_EN_SHIFT) |
+		(mem->rd_fetch << CONCONTROL_RD_FETCH_SHIFT),
+		&drex0->concontrol);
+	writel(mem->concontrol | (mem->aref_en << CONCONTROL_AREF_EN_SHIFT) |
+		(mem->rd_fetch << CONCONTROL_RD_FETCH_SHIFT),
+		&drex1->concontrol);
 	return 0;
 }
diff --git a/src/cpu/samsung/exynos5420/power.c b/src/cpu/samsung/exynos5420/power.c
index 82791b6..18e0299 100644
--- a/src/cpu/samsung/exynos5420/power.c
+++ b/src/cpu/samsung/exynos5420/power.c
@@ -23,6 +23,7 @@
 #include <arch/io.h>
 #include <arch/hlt.h>
 #include "cpu.h"
+#include "dmc.h"
 #include "power.h"
 #include "setup.h"
 #include "sysreg.h"
diff --git a/src/cpu/samsung/exynos5420/setup.h b/src/cpu/samsung/exynos5420/setup.h
index 34056f3..7d486f0 100644
--- a/src/cpu/samsung/exynos5420/setup.h
+++ b/src/cpu/samsung/exynos5420/setup.h
@@ -1,4 +1,4 @@
-/*
+ /*
  * This file is part of the coreboot project.
  *
  * Copyright (C) 2012 Samsung Electronics
@@ -27,6 +27,11 @@ enum ddr_mode;
 struct exynos5_phy_control;
 
 #define NOT_AVAILABLE		0
+#define DATA_MASK		0xFFFFF
+
+#define ENABLE_BIT		0x1
+#define DISABLE_BIT		0x0
+#define CA_SWAP_EN		(1 << 0)
 
 /* TZPC : Register Offsets */
 #define TZPC0_BASE		0x10100000
@@ -122,6 +127,7 @@ struct exynos5_phy_control;
 
 /* MEMCONFIG0 register bit fields */
 #define DMC_MEMCONFIGx_CHIP_MAP_INTERLEAVED     (1 << 12)
+#define DMC_MEMCONFIG_CHIP_MAP_SPLIT		(2 << 12)
 #define DMC_MEMCONFIGx_CHIP_COL_10              (3 << 8)
 #define DMC_MEMCONFIGx_CHIP_ROW_14              (2 << 4)
 #define DMC_MEMCONFIGx_CHIP_ROW_15              (3 << 4)
@@ -201,6 +207,10 @@ struct exynos5_phy_control;
 
 /* CLK_SRC_CDREX */
 #define CLK_SRC_CDREX_VAL       0x00000001
+#define MUX_MCLK_CDR_MSPLL	(1 << 4)
+#define MUX_BPLL_SEL_FOUTBPLL   (1 << 0)
+#define BPLL_SEL_MASK   0x7
+#define FOUTBPLL        2
 
 /* CLK_DIV_CDREX */
 #define CLK_DIV_CDREX0_VAL	0x30010100
@@ -620,39 +630,177 @@ struct exynos5_phy_control;
 #define CTRL_SHGATE		(1 << 8)
 
 #define PHY_CON1_RESET_VAL	0x09210100
+#define RDLVL_PASS_ADJ_VAL	0x6
+#define RDLVL_PASS_ADJ_OFFSET	16
 #define CTRL_GATEDURADJ_MASK	(0xf << 20)
+#define READ_LEVELLING_DDR3	0x0100
 
 #define PHY_CON2_RESET_VAL	0x00010004
 #define INIT_DESKEW_EN		(1 << 6)
+#define DLL_DESKEW_EN		(1 << 12)
 #define RDLVL_GATE_EN		(1 << 24)
+#define RDLVL_EN		(1 << 25)
+#define RDLVL_INCR_ADJ		(0x1 << 16)
+
+/* DREX_PAUSE */
+#define DREX_PAUSE_EN	(1 << 0)
+
+#define BYPASS_EN	(1 << 22)
+
+/********-----MEMMORY VAL----------***/
+#define PHY_CON0_VAL	0x17021A00
+
+#define PHY_CON12_RESET_VAL	0x10100070
+#define PHY_CON12_VAL		0x10107F50
+#define CTRL_START		(1 << 6)
+#define CTRL_DLL_ON		(1 << 5)
+#define CTRL_FORCE_MASK		(0x7F << 8)
+#define CTRL_LOCK_COARSE_MASK	(0x7F << 10)
+
+
+#define CTRL_OFFSETD_RESET_VAL	0x8
+#define CTRL_OFFSETD_VAL	0x7F
+
+#define CTRL_OFFSETR0		0x7F
+#define CTRL_OFFSETR1		0x7F
+#define CTRL_OFFSETR2		0x7F
+#define CTRL_OFFSETR3		0x7F
+#define PHY_CON4_VAL	(CTRL_OFFSETR0 << 0 | \
+				CTRL_OFFSETR1 << 8 | \
+				CTRL_OFFSETR2 << 16 | \
+				CTRL_OFFSETR3 << 24)
+#define PHY_CON4_RESET_VAL	0x08080808
+
+#define CTRL_OFFSETW0		0x7F
+#define CTRL_OFFSETW1		0x7F
+#define CTRL_OFFSETW2		0x7F
+#define CTRL_OFFSETW3		0x7F
+#define PHY_CON6_VAL	(CTRL_OFFSETW0 << 0 | \
+				CTRL_OFFSETW1 << 8 | \
+				CTRL_OFFSETW2 << 16 | \
+				CTRL_OFFSETW3 << 24)
+#define PHY_CON6_RESET_VAL	0x08080808
+
+#define PHY_CON14_RESET_VAL	0x001F0000
+#define CTRL_PULLD_DQS		0xF
+#define CTRL_PULLD_DQS_OFFSET	0
 
 /*ZQ Configurations */
 #define PHY_CON16_RESET_VAL	0x08000304
 
+#define ZQ_CLK_EN		(1 << 27)
 #define ZQ_CLK_DIV_EN		(1 << 18)
+#define ZQ_MANUAL_MODE_OFFSET	2
+#define ZQ_LONG_CALIBRATION	0x1
 #define ZQ_MANUAL_STR		(1 << 1)
 #define ZQ_DONE			(1 << 0)
+#define ZQ_MODE_DDS_OFFSET	24
+
+#define LONG_CALIBRATION	(ZQ_LONG_CALIBRATION << ZQ_MANUAL_MODE_OFFSET)
 
 #define CTRL_RDLVL_GATE_ENABLE	1
-#define CTRL_RDLVL_GATE_DISABLE	1
+#define CTRL_RDLVL_GATE_DISABLE	0
 
+#define CTRL_RDLVL_DATA_ENABLE	(1 << 1)
 /* Direct Command */
 #define DIRECT_CMD_NOP			0x07000000
 #define DIRECT_CMD_PALL			0x01000000
 #define DIRECT_CMD_ZQINIT		0x0a000000
 #define DIRECT_CMD_CHANNEL_SHIFT	28
 #define DIRECT_CMD_CHIP_SHIFT		20
+#define DIRECT_CMD_REFA		(5 << 24)
+#define DIRECT_CMD_MRS1		0x71C00
+#define DIRECT_CMD_MRS2		0x10BFC
+#define DIRECT_CMD_MRS3		0x0050C
+#define DIRECT_CMD_MRS4		0x00868
+#define DIRECT_CMD_MRS5		0x00C04
+
+/* Drive Strength */
+#define IMPEDANCE_48_OHM	4
+#define IMPEDANCE_40_OHM	5
+#define IMPEDANCE_34_OHM	6
+#define IMPEDANCE_30_OHM	7
+#define PHY_CON39_VAL_48_OHM	0x09240924
+#define PHY_CON39_VAL_40_OHM	0x0B6D0B6D
+#define PHY_CON39_VAL_34_OHM	0x0DB60DB6
+#define PHY_CON39_VAL_30_OHM	0x0FFF0FFF
+
+
+#define CTRL_BSTLEN_OFFSET	8
+#define CTRL_RDLAT_OFFSET	0
+
+#define CMD_DEFAULT_LPDDR3	0xF
+#define CMD_DEFUALT_OFFSET	0
+#define T_WRDATA_EN		0x7
+#define T_WRDATA_EN_DDR3	0x8
+#define T_WRDATA_EN_OFFSET	16
+#define T_WRDATA_EN_MASK	0x1f
+
+#define PHY_CON31_VAL	0x0C183060
+#define PHY_CON32_VAL	0x60C18306
+#define PHY_CON33_VAL	0x00000030
+
+#define PHY_CON31_RESET_VAL	0x0
+#define PHY_CON32_RESET_VAL	0x0
+#define PHY_CON33_RESET_VAL	0x0
+
+#define SL_DLL_DYN_CON_EN	(1 << 1)
+#define FP_RESYNC	(1 << 3)
+#define CTRL_START	(1 << 6)
+
+#define DMC_AREF_EN		(1 << 5)
+#define DMC_CONCONTROL_EMPTY	(1 << 8)
+#define DFI_INIT_START		(1 << 28)
+
+#define DMC_MEMCONTROL_VAL	0x00312700
+#define CLK_STOP_EN		(1 << 0)
+#define DPWRDN_EN		(1 << 1)
+#define DSREF_EN		(1 << 5)
+
+/* As we use channel interleaving, therefore value of the base address
+ * register must be set as half of the bus base address
+ * RAM start addess is 0x2000_0000 which means chip_base is 0x20, so
+ * we need to set half 0x10 to the membaseconfigx registers
+ * see exynos5420 UM section 17.17.3.21 for more
+ */
+#define DMC_CHIP_BASE_0 0x10
+#define DMC_CHIP_BASE_1 0x50
+#define DMC_CHIP_MASK	0x7C0
+
+#define MEMBASECONFIG_CHIP_MASK_VAL	0x7E0
+#define MEMBASECONFIG_CHIP_MASK_OFFSET	0
+#define MEMBASECONFIG0_CHIP_BASE_VAL	0x20
+#define MEMBASECONFIG1_CHIP_BASE_VAL	0x40
+#define CHIP_BASE_OFFSET		16
+
+#define MEMCONFIG_VAL	0x1323
+#define PRECHCONFIG_DEFAULT_VAL	0xFF000000
+#define PWRDNCONFIG_DEFAULT_VAL	0xFFFF00FF
+
+#define TIMINGAREF_VAL	0x5d
+#define TIMINGROW_VAL	0x345A8692
+#define TIMINGDATA_VAL	0x3630065C
+#define TIMINGPOWER_VAL	0x50380336
+#define DFI_INIT_COMPLETE	(1 << 3)
+
+#define BRBRSVCONTROL_VAL	0x00000033
+#define BRBRSVCONFIG_VAL	0x88778877
 
 /* 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 DMC_CTRL_SHGATE	(1 << 29)	/* Duration of DQS gating signal */
+#define CTRL_ATGATE		(1 << 6)
 #define FP_RSYNC	(1 << 3)	/* Force DLL resyncronization */
 
 /* Driver strength for CK, CKE, CS & CA */
 #define IMP_OUTPUT_DRV_40_OHM	0x5
 #define IMP_OUTPUT_DRV_30_OHM	0x7
+#define DA_3_DS_OFFSET		25
+#define DA_2_DS_OFFSET		22
+#define DA_1_DS_OFFSET		19
+#define DA_0_DS_OFFSET		16
 #define CA_CK_DRVR_DS_OFFSET	9
 #define CA_CKE_DRVR_DS_OFFSET	6
 #define CA_CS_DRVR_DS_OFFSET	3
@@ -687,8 +835,10 @@ void mem_ctrl_init(void);
  * @param mem_reset	Reset memory during initialization.
  * @return 0 if ok, SETUP_ERR_... if there is a problem
  */
-int ddr3_mem_ctrl_init(struct mem_timings *mem, unsigned long mem_iv_size,
-		       int mem_reset);
+int ddr3_mem_ctrl_init(struct mem_timings *mem, int interleave_size, int reset);
+
+/* Memory variant specific initialization code for LPDDR3 */
+int lpddr3_mem_ctrl_init(int reset);
 
 /*
  * Configure ZQ I/O interface
diff --git a/src/mainboard/google/pit/Kconfig b/src/mainboard/google/pit/Kconfig
index 8aed0a0..0dc013b 100644
--- a/src/mainboard/google/pit/Kconfig
+++ b/src/mainboard/google/pit/Kconfig
@@ -32,6 +32,7 @@ config BOARD_SPECIFIC_OPTIONS # dummy
 	select DRIVER_TI_TPS65090
 	select MAINBOARD_HAS_NATIVE_VGA_INIT
 	select MAINBOARD_DO_NATIVE_VGA_INIT
+	select HAVE_INIT_TIMER
 
 config MAINBOARD_DIR
 	string
diff --git a/src/mainboard/google/pit/memory.c b/src/mainboard/google/pit/memory.c
index 68c2bd6..74f3e6e 100644
--- a/src/mainboard/google/pit/memory.c
+++ b/src/mainboard/google/pit/memory.c
@@ -23,147 +23,21 @@
 #include <console/console.h>
 
 #include <cpu/samsung/exynos5420/gpio.h>
-#include <cpu/samsung/exynos5420/setup.h>
 #include <cpu/samsung/exynos5420/dmc.h>
+#include <cpu/samsung/exynos5420/setup.h>
 #include <cpu/samsung/exynos5420/clk.h>
 
-const struct mem_timings mem_timings[] = {
-	{
-		.mem_manuf = MEM_MANUF_ELPIDA,
-		.mem_type = DDR_MODE_DDR3,
-		.frequency_mhz = 800,
-		.mpll_mdiv = 0x64,
-		.mpll_pdiv = 0x3,
-		.mpll_sdiv = 0x0,
-		.cpll_mdiv = 0xde,
-		.cpll_pdiv = 0x4,
-		.cpll_sdiv = 0x2,
-		.gpll_mdiv = 0x215,
-		.gpll_pdiv = 0xc,
-		.gpll_sdiv = 0x1,
-		.epll_mdiv = 0x60,
-		.epll_pdiv = 0x3,
-		.epll_sdiv = 0x3,
-		.vpll_mdiv = 0x96,
-		.vpll_pdiv = 0x3,
-		.vpll_sdiv = 0x2,
-
-		.bpll_mdiv = 0x64,
-		.bpll_pdiv = 0x3,
-		.bpll_sdiv = 0x0,
-		.use_bpll = 0,
-		.pclk_cdrex_ratio = 0x5,
-		.direct_cmd_msr = {
-			0x00020018, 0x00030000, 0x00010042, 0x00000d70
-		},
-		.timing_ref = 0x000000bb,
-		.timing_row = 0x8c36660f,
-		.timing_data = 0x3630580b,
-		.timing_power = 0x41000a44,
-		.phy0_dqs = 0x08080808,
-		.phy1_dqs = 0x08080808,
-		.phy0_dq = 0x08080808,
-		.phy1_dq = 0x08080808,
-		.phy0_tFS = 0x4,
-		.phy1_tFS = 0x4,
-		.phy0_pulld_dqs = 0xf,
-		.phy1_pulld_dqs = 0xf,
-
-		.lpddr3_ctrl_phy_reset = 0x1,
-		.ctrl_start_point = 0x10,
-		.ctrl_inc = 0x10,
-		.ctrl_start = 0x1,
-		.ctrl_dll_on = 0x1,
-		.ctrl_ref = 0x8,
-
-		.ctrl_force = 0x1a,
-		.ctrl_rdlat = 0x0b,
-		.ctrl_bstlen = 0x08,
-
-		.fp_resync = 0x8,
-		.iv_size = 0x7,
-		.dfi_init_start = 1,
-		.aref_en = 1,
-
-		.rd_fetch = 0x3,
-
-		.zq_mode_dds = 0x7,
-		.zq_mode_term = 0x1,
-		.zq_mode_noterm = 0,
-
-		/*
-		* 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
-		*/
-		.memcontrol = DMC_MEMCONTROL_CLK_STOP_DISABLE |
-			DMC_MEMCONTROL_DPWRDN_DISABLE |
-			DMC_MEMCONTROL_DPWRDN_ACTIVE_PRECHARGE |
-			DMC_MEMCONTROL_TP_DISABLE |
-			DMC_MEMCONTROL_DSREF_ENABLE |
-			DMC_MEMCONTROL_ADD_LAT_PALL_CYCLE(0) |
-			DMC_MEMCONTROL_MEM_TYPE_DDR3 |
-			DMC_MEMCONTROL_MEM_WIDTH_32BIT |
-			DMC_MEMCONTROL_NUM_CHIP_1 |
-			DMC_MEMCONTROL_BL_8 |
-			DMC_MEMCONTROL_PZQ_DISABLE |
-			DMC_MEMCONTROL_MRR_BYTE_7_0,
-		.memconfig = DMC_MEMCONFIGx_CHIP_MAP_INTERLEAVED |
-			DMC_MEMCONFIGx_CHIP_COL_10 |
-			DMC_MEMCONFIGx_CHIP_ROW_15 |
-			DMC_MEMCONFIGx_CHIP_BANK_8,
-		.membaseconfig0 = DMC_MEMBASECONFIG_VAL(0x40),
-		.membaseconfig1 = DMC_MEMBASECONFIG_VAL(0x80),
-		.prechconfig_tp_cnt = 0xff,
-		.dpwrdn_cyc = 0xff,
-		.dsref_cyc = 0xffff,
-		.concontrol = DMC_CONCONTROL_DFI_INIT_START_DISABLE |
-			DMC_CONCONTROL_TIMEOUT_LEVEL0 |
-			DMC_CONCONTROL_RD_FETCH_DISABLE |
-			DMC_CONCONTROL_EMPTY_DISABLE |
-			DMC_CONCONTROL_AREF_EN_DISABLE |
-			DMC_CONCONTROL_IO_PD_CON_DISABLE,
-		.dmc_channels = 2,
-		.chips_per_channel = 2,
-		.chips_to_configure = 1,
-		.send_zq_init = 1,
-		.impedance = IMP_OUTPUT_DRV_30_OHM,
-		.gate_leveling_enable = 0,
-	}, {
+const struct mem_timings mem_timings = {
 		.mem_manuf = MEM_MANUF_SAMSUNG,
 		.mem_type = DDR_MODE_DDR3,
 		.frequency_mhz = 800,
-		.mpll_mdiv = 0x64,
-		.mpll_pdiv = 0x3,
-		.mpll_sdiv = 0x0,
-		.cpll_mdiv = 0xde,
-		.cpll_pdiv = 0x4,
-		.cpll_sdiv = 0x2,
-		.gpll_mdiv = 0x215,
-		.gpll_pdiv = 0xc,
-		.gpll_sdiv = 0x1,
-		.epll_mdiv = 0x60,
-		.epll_pdiv = 0x3,
-		.epll_sdiv = 0x3,
-		.vpll_mdiv = 0x96,
-		.vpll_pdiv = 0x3,
-		.vpll_sdiv = 0x2,
-
-		.bpll_mdiv = 0x64,
-		.bpll_pdiv = 0x3,
-		.bpll_sdiv = 0x0,
-		.use_bpll = 0,
-		.pclk_cdrex_ratio = 0x5,
 		.direct_cmd_msr = {
-			0x00020018, 0x00030000, 0x00010000, 0x00000d70
+			0x00020018, 0x00030000, 0x00010002, 0x00000d70
 		},
 		.timing_ref = 0x000000bb,
-		.timing_row = 0x8c36660f,
+		.timing_row = 0x6836650f,
 		.timing_data = 0x3630580b,
-		.timing_power = 0x41000a44,
+		.timing_power = 0x41000a26,
 		.phy0_dqs = 0x08080808,
 		.phy1_dqs = 0x08080808,
 		.phy0_dq = 0x08080808,
@@ -191,7 +65,7 @@ const struct mem_timings mem_timings[] = {
 
 		.rd_fetch = 0x3,
 
-		.zq_mode_dds = 0x5,
+		.zq_mode_dds = 0x6,
 		.zq_mode_term = 0x1,
 		.zq_mode_noterm = 1,
 
@@ -207,20 +81,18 @@ const struct mem_timings mem_timings[] = {
 			DMC_MEMCONTROL_DPWRDN_DISABLE |
 			DMC_MEMCONTROL_DPWRDN_ACTIVE_PRECHARGE |
 			DMC_MEMCONTROL_TP_DISABLE |
-			DMC_MEMCONTROL_DSREF_ENABLE |
+			DMC_MEMCONTROL_DSREF_DISABLE |
 			DMC_MEMCONTROL_ADD_LAT_PALL_CYCLE(0) |
 			DMC_MEMCONTROL_MEM_TYPE_DDR3 |
 			DMC_MEMCONTROL_MEM_WIDTH_32BIT |
-			DMC_MEMCONTROL_NUM_CHIP_1 |
+			DMC_MEMCONTROL_NUM_CHIP_2 |
 			DMC_MEMCONTROL_BL_8 |
 			DMC_MEMCONTROL_PZQ_DISABLE |
 			DMC_MEMCONTROL_MRR_BYTE_7_0,
-		.memconfig = DMC_MEMCONFIGx_CHIP_MAP_INTERLEAVED |
+		.memconfig = DMC_MEMCONFIG_CHIP_MAP_SPLIT |
 			DMC_MEMCONFIGx_CHIP_COL_10 |
 			DMC_MEMCONFIGx_CHIP_ROW_15 |
 			DMC_MEMCONFIGx_CHIP_BANK_8,
-		.membaseconfig0 = DMC_MEMBASECONFIG_VAL(0x40),
-		.membaseconfig1 = DMC_MEMBASECONFIG_VAL(0x80),
 		.prechconfig_tp_cnt = 0xff,
 		.dpwrdn_cyc = 0xff,
 		.dsref_cyc = 0xffff,
@@ -230,316 +102,9 @@ const struct mem_timings mem_timings[] = {
 			DMC_CONCONTROL_EMPTY_DISABLE |
 			DMC_CONCONTROL_AREF_EN_DISABLE |
 			DMC_CONCONTROL_IO_PD_CON_DISABLE,
-		.dmc_channels = 2,
+		.dmc_channels = 1,
 		.chips_per_channel = 2,
-		.chips_to_configure = 1,
+		.chips_to_configure = 2,
 		.send_zq_init = 1,
-		.impedance = IMP_OUTPUT_DRV_40_OHM,
 		.gate_leveling_enable = 1,
-	},
-	{
-		.mem_manuf = MEM_MANUF_ELPIDA,
-		.mem_type = DDR_MODE_DDR3,
-		.frequency_mhz = 780,
-		.mpll_mdiv = 0x64,
-		.mpll_pdiv = 0x3,
-		.mpll_sdiv = 0x0,
-		.cpll_mdiv = 0xde,
-		.cpll_pdiv = 0x4,
-		.cpll_sdiv = 0x2,
-		.gpll_mdiv = 0x215,
-		.gpll_pdiv = 0xc,
-		.gpll_sdiv = 0x1,
-		.epll_mdiv = 0x60,
-		.epll_pdiv = 0x3,
-		.epll_sdiv = 0x3,
-		.vpll_mdiv = 0x96,
-		.vpll_pdiv = 0x3,
-		.vpll_sdiv = 0x2,
-
-		.bpll_mdiv = 0x82,
-		.bpll_pdiv = 0x4,
-		.bpll_sdiv = 0x0,
-		.use_bpll = 1,
-		.pclk_cdrex_ratio = 0x5,
-		.direct_cmd_msr = {
-			0x00020018, 0x00030000, 0x00010042, 0x00000d70
-		},
-		.timing_ref = 0x000000bb,
-		.timing_row = 0x8c36660f,
-		.timing_data = 0x3630580b,
-		.timing_power = 0x41000a44,
-		.phy0_dqs = 0x08080808,
-		.phy1_dqs = 0x08080808,
-		.phy0_dq = 0x08080808,
-		.phy1_dq = 0x08080808,
-		.phy0_tFS = 0x4,
-		.phy1_tFS = 0x4,
-		.phy0_pulld_dqs = 0xf,
-		.phy1_pulld_dqs = 0xf,
-
-		.lpddr3_ctrl_phy_reset = 0x1,
-		.ctrl_start_point = 0x10,
-		.ctrl_inc = 0x10,
-		.ctrl_start = 0x1,
-		.ctrl_dll_on = 0x1,
-		.ctrl_ref = 0x8,
-
-		.ctrl_force = 0x1a,
-		.ctrl_rdlat = 0x0b,
-		.ctrl_bstlen = 0x08,
-
-		.fp_resync = 0x8,
-		.iv_size = 0x7,
-		.dfi_init_start = 1,
-		.aref_en = 1,
-
-		.rd_fetch = 0x3,
-
-		.zq_mode_dds = 0x7,
-		.zq_mode_term = 0x1,
-		.zq_mode_noterm = 0,
-
-		/*
-		* 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
-		*/
-		.memcontrol = DMC_MEMCONTROL_CLK_STOP_DISABLE |
-			DMC_MEMCONTROL_DPWRDN_DISABLE |
-			DMC_MEMCONTROL_DPWRDN_ACTIVE_PRECHARGE |
-			DMC_MEMCONTROL_TP_DISABLE |
-			DMC_MEMCONTROL_DSREF_ENABLE |
-			DMC_MEMCONTROL_ADD_LAT_PALL_CYCLE(0) |
-			DMC_MEMCONTROL_MEM_TYPE_DDR3 |
-			DMC_MEMCONTROL_MEM_WIDTH_32BIT |
-			DMC_MEMCONTROL_NUM_CHIP_1 |
-			DMC_MEMCONTROL_BL_8 |
-			DMC_MEMCONTROL_PZQ_DISABLE |
-			DMC_MEMCONTROL_MRR_BYTE_7_0,
-		.memconfig = DMC_MEMCONFIGx_CHIP_MAP_INTERLEAVED |
-			DMC_MEMCONFIGx_CHIP_COL_10 |
-			DMC_MEMCONFIGx_CHIP_ROW_15 |
-			DMC_MEMCONFIGx_CHIP_BANK_8,
-		.membaseconfig0 = DMC_MEMBASECONFIG_VAL(0x40),
-		.membaseconfig1 = DMC_MEMBASECONFIG_VAL(0x80),
-		.prechconfig_tp_cnt = 0xff,
-		.dpwrdn_cyc = 0xff,
-		.dsref_cyc = 0xffff,
-		.concontrol = DMC_CONCONTROL_DFI_INIT_START_DISABLE |
-			DMC_CONCONTROL_TIMEOUT_LEVEL0 |
-			DMC_CONCONTROL_RD_FETCH_DISABLE |
-			DMC_CONCONTROL_EMPTY_DISABLE |
-			DMC_CONCONTROL_AREF_EN_DISABLE |
-			DMC_CONCONTROL_IO_PD_CON_DISABLE,
-		.dmc_channels = 2,
-		.chips_per_channel = 2,
-		.chips_to_configure = 1,
-		.send_zq_init = 1,
-		.impedance = IMP_OUTPUT_DRV_30_OHM,
-		.gate_leveling_enable = 0,
-	}, {
-		.mem_manuf = MEM_MANUF_SAMSUNG,
-		.mem_type = DDR_MODE_DDR3,
-		.frequency_mhz = 780,
-		.mpll_mdiv = 0x64,
-		.mpll_pdiv = 0x3,
-		.mpll_sdiv = 0x0,
-		.cpll_mdiv = 0xde,
-		.cpll_pdiv = 0x4,
-		.cpll_sdiv = 0x2,
-		.gpll_mdiv = 0x215,
-		.gpll_pdiv = 0xc,
-		.gpll_sdiv = 0x1,
-		.epll_mdiv = 0x60,
-		.epll_pdiv = 0x3,
-		.epll_sdiv = 0x3,
-		.vpll_mdiv = 0x96,
-		.vpll_pdiv = 0x3,
-		.vpll_sdiv = 0x2,
-
-		.bpll_mdiv = 0x82,
-		.bpll_pdiv = 0x4,
-		.bpll_sdiv = 0x0,
-		.use_bpll = 1,
-		.pclk_cdrex_ratio = 0x5,
-		.direct_cmd_msr = {
-			0x00020018, 0x00030000, 0x00010000, 0x00000d70
-		},
-		.timing_ref = 0x000000bb,
-		.timing_row = 0x8c36660f,
-		.timing_data = 0x3630580b,
-		.timing_power = 0x41000a44,
-		.phy0_dqs = 0x08080808,
-		.phy1_dqs = 0x08080808,
-		.phy0_dq = 0x08080808,
-		.phy1_dq = 0x08080808,
-		.phy0_tFS = 0x8,
-		.phy1_tFS = 0x8,
-		.phy0_pulld_dqs = 0xf,
-		.phy1_pulld_dqs = 0xf,
-
-		.lpddr3_ctrl_phy_reset = 0x1,
-		.ctrl_start_point = 0x10,
-		.ctrl_inc = 0x10,
-		.ctrl_start = 0x1,
-		.ctrl_dll_on = 0x1,
-		.ctrl_ref = 0x8,
-
-		.ctrl_force = 0x1a,
-		.ctrl_rdlat = 0x0b,
-		.ctrl_bstlen = 0x08,
-
-		.fp_resync = 0x8,
-		.iv_size = 0x7,
-		.dfi_init_start = 1,
-		.aref_en = 1,
-
-		.rd_fetch = 0x3,
-
-		.zq_mode_dds = 0x5,
-		.zq_mode_term = 0x1,
-		.zq_mode_noterm = 1,
-
-		/*
-		* 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
-		*/
-		.memcontrol = DMC_MEMCONTROL_CLK_STOP_DISABLE |
-			DMC_MEMCONTROL_DPWRDN_DISABLE |
-			DMC_MEMCONTROL_DPWRDN_ACTIVE_PRECHARGE |
-			DMC_MEMCONTROL_TP_DISABLE |
-			DMC_MEMCONTROL_DSREF_ENABLE |
-			DMC_MEMCONTROL_ADD_LAT_PALL_CYCLE(0) |
-			DMC_MEMCONTROL_MEM_TYPE_DDR3 |
-			DMC_MEMCONTROL_MEM_WIDTH_32BIT |
-			DMC_MEMCONTROL_NUM_CHIP_1 |
-			DMC_MEMCONTROL_BL_8 |
-			DMC_MEMCONTROL_PZQ_DISABLE |
-			DMC_MEMCONTROL_MRR_BYTE_7_0,
-		.memconfig = DMC_MEMCONFIGx_CHIP_MAP_INTERLEAVED |
-			DMC_MEMCONFIGx_CHIP_COL_10 |
-			DMC_MEMCONFIGx_CHIP_ROW_15 |
-			DMC_MEMCONFIGx_CHIP_BANK_8,
-		.membaseconfig0 = DMC_MEMBASECONFIG_VAL(0x40),
-		.membaseconfig1 = DMC_MEMBASECONFIG_VAL(0x80),
-		.prechconfig_tp_cnt = 0xff,
-		.dpwrdn_cyc = 0xff,
-		.dsref_cyc = 0xffff,
-		.concontrol = DMC_CONCONTROL_DFI_INIT_START_DISABLE |
-			DMC_CONCONTROL_TIMEOUT_LEVEL0 |
-			DMC_CONCONTROL_RD_FETCH_DISABLE |
-			DMC_CONCONTROL_EMPTY_DISABLE |
-			DMC_CONCONTROL_AREF_EN_DISABLE |
-			DMC_CONCONTROL_IO_PD_CON_DISABLE,
-		.dmc_channels = 2,
-		.chips_per_channel = 2,
-		.chips_to_configure = 1,
-		.send_zq_init = 1,
-		.impedance = IMP_OUTPUT_DRV_40_OHM,
-		.gate_leveling_enable = 1,
-	}
 };
-
-#define BOARD_ID0_GPIO	88	/* GPD0, pin 0 */
-#define BOARD_ID1_GPIO	89	/* GPD0, pin 1 */
-
-enum board_config {
-	PIT_CONFIG_UNKNOWN = -1,
-	PIT_CONFIG_SAMSUNG_EVT,
-	PIT_CONFIG_ELPIDA_EVT,
-	PIT_CONFIG_SAMSUNG_DVT,
-	PIT_CONFIG_ELPIDA_DVT,
-	PIT_CONFIG_SAMSUNG_PVT,
-	PIT_CONFIG_ELPIDA_PVT,
-	PIT_CONFIG_SAMSUNG_MP,
-	PIT_CONFIG_ELPIDA_MP,
-	PIT_CONFIG_RSVD,
-};
-
-struct {
-	enum mvl3 id0, id1;
-	enum board_config config;
-} id_map[] = {
-	/*  ID0      ID1         config */
-	{ LOGIC_0, LOGIC_0, PIT_CONFIG_SAMSUNG_MP },
-	{ LOGIC_0, LOGIC_1, PIT_CONFIG_ELPIDA_MP },
-	{ LOGIC_1, LOGIC_0, PIT_CONFIG_SAMSUNG_DVT },
-	{ LOGIC_1, LOGIC_1, PIT_CONFIG_ELPIDA_DVT },
-	{ LOGIC_0, LOGIC_Z, PIT_CONFIG_SAMSUNG_PVT },
-	{ LOGIC_1, LOGIC_Z, PIT_CONFIG_ELPIDA_PVT },
-	{ LOGIC_Z, LOGIC_0, PIT_CONFIG_SAMSUNG_MP },
-	{ LOGIC_Z, LOGIC_Z, PIT_CONFIG_ELPIDA_MP },
-	{ LOGIC_Z, LOGIC_1, PIT_CONFIG_RSVD },
-};
-
-static int board_get_config(void)
-{
-	int i;
-	int id0, id1;
-	enum board_config config = PIT_CONFIG_UNKNOWN;
-
-	id0 = gpio_read_mvl3(BOARD_ID0_GPIO);
-	id1 = gpio_read_mvl3(BOARD_ID1_GPIO);
-	if (id0 < 0 || id1 < 0)
-		return -1;
-
-	for (i = 0; i < ARRAY_SIZE(id_map); i++) {
-		if (id0 == id_map[i].id0 && id1 == id_map[i].id1) {
-			config = id_map[i].config;
-			break;
-		}
-	}
-
-	return config;
-}
-
-struct mem_timings *get_mem_timings(void)
-{
-	int i;
-	enum board_config config;
-	enum ddr_mode mem_type;
-	unsigned int frequency_mhz;
-	enum mem_manuf mem_manuf;
-	const struct mem_timings *mem;
-
-	config = board_get_config();
-	switch (config) {
-	case PIT_CONFIG_ELPIDA_EVT:
-	case PIT_CONFIG_ELPIDA_DVT:
-	case PIT_CONFIG_ELPIDA_PVT:
-	case PIT_CONFIG_ELPIDA_MP:
-		mem_manuf = MEM_MANUF_ELPIDA;
-		mem_type = DDR_MODE_DDR3;
-		frequency_mhz = 800;
-		break;
-	case PIT_CONFIG_SAMSUNG_EVT:
-	case PIT_CONFIG_SAMSUNG_DVT:
-	case PIT_CONFIG_SAMSUNG_PVT:
-	case PIT_CONFIG_SAMSUNG_MP:
-		mem_manuf = MEM_MANUF_SAMSUNG;
-		mem_type = DDR_MODE_DDR3;
-		frequency_mhz = 800;
-		break;
-	default:
-		printk(BIOS_CRIT, "Unknown board configuration.\n");
-		return NULL;
-	}
-
-	for (i = 0, mem = mem_timings; i < ARRAY_SIZE(mem_timings);
-			i++, mem++) {
-		if (mem->mem_type == mem_type &&
-			mem->frequency_mhz == frequency_mhz &&
-			mem->mem_manuf == mem_manuf)
-			return (struct mem_timings *)mem;
-	}
-
-	return NULL;
-}
diff --git a/src/mainboard/google/pit/romstage.c b/src/mainboard/google/pit/romstage.c
index 8a5a1dd..1ff8d51 100644
--- a/src/mainboard/google/pit/romstage.c
+++ b/src/mainboard/google/pit/romstage.c
@@ -130,7 +130,7 @@ static void setup_gpio(void)
 
 static void setup_memory(struct mem_timings *mem, int is_resume)
 {
-	printk(BIOS_SPEW, "man: 0x%x type: 0x%x, div: 0x%x, mhz: %d\n",
+	printk(BIOS_SPEW, "manufacturer: 0x%x type: 0x%x, div: 0x%x, mhz: %d\n",
 	       mem->mem_manuf,
 	       mem->mem_type,
 	       mem->mpll_mdiv,
@@ -148,27 +148,97 @@ static void setup_memory(struct mem_timings *mem, int is_resume)
 	}
 }
 
-static struct mem_timings *setup_clock(void)
+#define PRIMITIVE_MEM_TEST 0
+#if PRIMITIVE_MEM_TEST
+static unsigned long primitive_mem_test(void)
 {
-	struct mem_timings *mem = get_mem_timings();
-	if (!mem) {
-		die("Unable to auto-detect memory timings\n");
+	unsigned long *l = (void *)0x40000000;
+	int bad = 0;
+	unsigned long i;
+	for(i = 0; i < 256*1048576; i++){
+		if (! (i%1048576))
+			printk(BIOS_SPEW, "%lu ...", i);
+		l[i] = 0xffffffff - i;
 	}
 
-	system_clock_init();
+	for(i = 0; i < 256*1048576; i++){
+		if (! (i%1048576))
+			printk(BIOS_SPEW, "%lu ...", i);
+		if (l[i] != (0xffffffff - i)){
+			printk(BIOS_SPEW, "%p: want %08lx got %08lx\n", l, l[i], 0xffffffff - i);
+			bad++;
+		}
+	}
+
+	printk(BIOS_SPEW, "%d errors\n", bad);
 
-	return mem;
+	return bad;
 }
+#else
+#define primitive_mem_test()
+#endif
+
+#define SIMPLE_SPI_TEST 0
+#if SIMPLE_SPI_TEST
+/* here is a simple SPI debug test, known to fid trouble */
+static void simple_spi_test(void)
+{
+	struct cbfs_media default_media, *media;
+	int i, amt = 4 * MiB, errors = 0;
+	//u32 *data = (void *)0x40000000;
+	u32 data[1024];
+	u32 in;
+
+	amt = sizeof(data);
+	media = &default_media;
+	if (init_default_cbfs_media(media) != 0) {
+		printk(BIOS_SPEW, "Failed to initialize default media.\n");
+		return;
+	}
+
+
+	media->open(media);
+	if (media->read(media, data, (size_t) 0, amt) < amt){
+		printk(BIOS_SPEW, "simple_spi_test fails\n");
+		return;
+	}
+
+
+	for(i = 0; i < amt; i += 4){
+		if (media->read(media, &in, (size_t) i, 4) < 1){
+			printk(BIOS_SPEW, "simple_spi_test fails at %d\n", i);
+			return;
+		}
+		if (data[i/4] != in){
+		  errors++;
+			printk(BIOS_SPEW, "BAD at %d(%p):\nRAM %08lx\nSPI %08lx\n",
+			       i, &data[i/4], (unsigned long)data[i/4], (unsigned long)in);
+			/* reread it to see which is wrong. */
+			if (media->read(media, &in, (size_t) i, 4) < 1){
+				printk(BIOS_SPEW, "simple_spi_test fails at %d\n", i);
+				return;
+			}
+			printk(BIOS_SPEW, "RTRY at %d(%p):\nRAM %08lx\nSPI %08lx\n",
+			       i, &data[i/4], (unsigned long)data[i/4], (unsigned long)in);
+		}
+
+	}
+	printk(BIOS_SPEW, "%d errors\n", errors);
+}
+#else
+#define simple_spi_test()
+#endif
 
 void main(void)
 {
-	struct mem_timings *mem;
+
+	extern struct mem_timings mem_timings;
 	void *entry;
 	int is_resume = (get_wakeup_state() != IS_NOT_WAKEUP);
 
 	/* Clock must be initialized before console_init, otherwise you may need
 	 * to re-initialize serial console drivers again. */
-	mem = setup_clock();
+	system_clock_init();
 
 	console_init();
 
@@ -176,7 +246,9 @@ void main(void)
 		setup_power();
 	}
 
-	setup_memory(mem, is_resume);
+	setup_memory(&mem_timings, is_resume);
+
+	primitive_mem_test();
 
 	if (is_resume) {
 		wakeup();
@@ -186,9 +258,12 @@ void main(void)
 	setup_gpio();
 	setup_graphics();
 
+	simple_spi_test();
 	/* Set SPI (primary CBFS media) clock to 50MHz. */
+	/* if this is uncommented SPI will not work correctly. */
 	clock_set_rate(PERIPH_ID_SPI1, 50000000);
-
+	simple_spi_test();
 	entry = cbfs_load_stage(CBFS_DEFAULT_MEDIA, "fallback/coreboot_ram");
+	simple_spi_test();
 	stage_exit(entry);
 }



More information about the coreboot-gerrit mailing list