diff mbox

[U-Boot,1/2] driver/ddr/fsl: Add DDR4 support to Freescale DDR driver

Message ID 1395968088-5558-1-git-send-email-yorksun@freescale.com
State Accepted
Delegated to: York Sun
Headers show

Commit Message

York Sun March 28, 2014, 12:54 a.m. UTC
Mostly reusing DDR3 driver, this patch adds DDR4 SPD handling, register
calculation and programming.

Signed-off-by: York Sun <yorksun@freescale.com>
---
Tested on T1040QDS_D4 (patch following).

 README                                             |   13 +-
 arch/powerpc/include/asm/config_mpc85xx.h          |   17 +-
 common/ddr_spd.c                                   |   45 +-
 drivers/ddr/fsl/Makefile                           |   19 +-
 drivers/ddr/fsl/ctrl_regs.c                        |  739 ++++++++++++++++++--
 drivers/ddr/fsl/ddr4_dimm_params.c                 |  300 ++++++++
 drivers/ddr/fsl/{arm_ddr_gen3.c => fsl_ddr_gen4.c} |   56 +-
 drivers/ddr/fsl/interactive.c                      |  391 ++++++++++-
 drivers/ddr/fsl/lc_common_dimm_params.c            |  407 ++++++-----
 drivers/ddr/fsl/main.c                             |   25 +-
 drivers/ddr/fsl/options.c                          |   34 +-
 drivers/ddr/fsl/util.c                             |   26 +-
 include/common_timing_params.h                     |   23 +-
 include/ddr_spd.h                                  |  226 +++++-
 include/fsl_ddr.h                                  |    7 +-
 include/fsl_ddr_dimm_params.h                      |   77 +-
 include/fsl_ddr_sdram.h                            |   63 +-
 include/fsl_ddrc_version.h                         |   18 +
 include/fsl_immap.h                                |   35 +-
 19 files changed, 2182 insertions(+), 339 deletions(-)
 create mode 100644 drivers/ddr/fsl/ddr4_dimm_params.c
 copy drivers/ddr/fsl/{arm_ddr_gen3.c => fsl_ddr_gen4.c} (81%)
 create mode 100644 include/fsl_ddrc_version.h

Comments

York Sun April 23, 2014, 9:54 p.m. UTC | #1
On 03/27/2014 05:54 PM, York Sun wrote:
> Mostly reusing DDR3 driver, this patch adds DDR4 SPD handling, register
> calculation and programming.
> 
> Signed-off-by: York Sun <yorksun@freescale.com>
> ---

Applied to u-boot-mpc85xx/master.

York
diff mbox

Patch

diff --git a/README b/README
index 216f0c7..349d982 100644
--- a/README
+++ b/README
@@ -454,6 +454,9 @@  The following options need to be configured:
 		CONFIG_SYS_FSL_DDRC_GEN3
 		Freescale DDR3 controller.
 
+		CONFIG_SYS_FSL_DDRC_GEN4
+		Freescale DDR4 controller.
+
 		CONFIG_SYS_FSL_DDRC_ARM_GEN3
 		Freescale DDR3 controller for ARM-based SoCs.
 
@@ -469,7 +472,15 @@  The following options need to be configured:
 
 		CONFIG_SYS_FSL_DDR3
 		Board config to use DDR3. It can be enabled for SoCs with
-		Freescale DDR3 controllers.
+		Freescale DDR3 or DDR3L controllers.
+
+		CONFIG_SYS_FSL_DDR3L
+		Board config to use DDR3L. It can be enabled for SoCs with
+		DDR3L controllers.
+
+		CONFIG_SYS_FSL_DDR4
+		Board config to use DDR4. It can be enabled for SoCs with
+		DDR4 controllers.
 
 		CONFIG_SYS_FSL_IFC_BE
 		Defines the IFC controller register space as Big Endian
diff --git a/arch/powerpc/include/asm/config_mpc85xx.h b/arch/powerpc/include/asm/config_mpc85xx.h
index 9a20b97..727e981 100644
--- a/arch/powerpc/include/asm/config_mpc85xx.h
+++ b/arch/powerpc/include/asm/config_mpc85xx.h
@@ -19,8 +19,8 @@ 
  */
 #define CONFIG_PPC_SPINTABLE_COMPATIBLE
 
-#define FSL_DDR_VER_4_7	47
-#define FSL_DDR_VER_5_0	50
+#include <fsl_ddrc_version.h>
+#define CONFIG_SYS_FSL_DDR_BE
 
 /* IP endianness */
 #define CONFIG_SYS_FSL_IFC_BE
@@ -401,6 +401,7 @@ 
 #define CONFIG_SYS_NUM_FM1_DTSEC	5
 #define CONFIG_SYS_NUM_FM1_10GEC	1
 #define CONFIG_NUM_DDR_CONTROLLERS	1
+#define CONFIG_SYS_FSL_DDR_VER		FSL_DDR_VER_4_5
 #define CONFIG_SYS_FM_MURAM_SIZE	0x28000
 #define CONFIG_SYS_FSL_TBCLK_DIV	32
 #define CONFIG_SYS_FSL_PCIE_COMPAT	"fsl,qoriq-pcie-v2.2"
@@ -442,6 +443,7 @@ 
 #define CONFIG_SYS_NUM_FM1_10GEC	1
 #define CONFIG_SYS_NUM_FM2_10GEC	1
 #define CONFIG_NUM_DDR_CONTROLLERS	2
+#define CONFIG_SYS_FSL_DDR_VER		FSL_DDR_VER_4_4
 #define CONFIG_USB_MAX_CONTROLLER_COUNT	2
 #define CONFIG_SYS_FM_MURAM_SIZE	0x28000
 #define CONFIG_SYS_FSL_TBCLK_DIV	16
@@ -490,6 +492,7 @@ 
 #define CONFIG_SYS_NUM_FM1_DTSEC	5
 #define CONFIG_SYS_NUM_FM1_10GEC	1
 #define CONFIG_NUM_DDR_CONTROLLERS	2
+#define CONFIG_SYS_FSL_DDR_VER		FSL_DDR_VER_4_4
 #define CONFIG_USB_MAX_CONTROLLER_COUNT	2
 #define CONFIG_SYS_FM_MURAM_SIZE	0x28000
 #define CONFIG_SYS_FSL_TBCLK_DIV	32
@@ -527,6 +530,7 @@ 
 #define CONFIG_SYS_NUM_FM2_DTSEC	5
 #define CONFIG_SYS_NUM_FM2_10GEC	1
 #define CONFIG_NUM_DDR_CONTROLLERS	2
+#define CONFIG_SYS_FSL_DDR_VER		FSL_DDR_VER_4_4
 #define CONFIG_USB_MAX_CONTROLLER_COUNT	2
 #define CONFIG_SYS_FM_MURAM_SIZE	0x28000
 #define CONFIG_SYS_FSL_TBCLK_DIV	16
@@ -553,6 +557,7 @@ 
 #define CONFIG_TSECV2
 #define CONFIG_SYS_FSL_SEC_COMPAT	4
 #define CONFIG_NUM_DDR_CONTROLLERS	1
+#define CONFIG_SYS_FSL_DDR_VER		FSL_DDR_VER_4_4
 #define CONFIG_USB_MAX_CONTROLLER_COUNT	1
 #define CONFIG_SYS_FSL_DSP_M2_RAM_ADDR	0xb0000000
 #define CONFIG_SYS_FSL_DSP_CCSRBAR_DEFAULT	0xff600000
@@ -571,6 +576,7 @@ 
 #define CONFIG_TSECV2
 #define CONFIG_SYS_FSL_SEC_COMPAT	4
 #define CONFIG_NUM_DDR_CONTROLLERS	2
+#define CONFIG_SYS_FSL_DDR_VER		FSL_DDR_VER_4_6
 #define CONFIG_USB_MAX_CONTROLLER_COUNT	1
 #define CONFIG_SYS_FSL_DSP_DDR_ADDR	0x40000000
 #define CONFIG_SYS_FSL_DSP_M2_RAM_ADDR	0xb0000000
@@ -704,6 +710,9 @@  defined(CONFIG_PPC_T1020) || defined(CONFIG_PPC_T1022)
 #define CONFIG_SYS_FSL_QORIQ_CHASSIS2	/* Freescale Chassis generation 2 */
 #define CONFIG_SYS_FSL_CORES_PER_CLUSTER 1
 #define CONFIG_SYS_FSL_QMAN_V3		/* QMAN version 3 */
+#ifdef CONFIG_SYS_FSL_DDR4
+#define CONFIG_SYS_FSL_DDRC_GEN4
+#endif
 #if defined(CONFIG_PPC_T1040) || defined(CONFIG_PPC_T1042)
 #define CONFIG_MAX_CPUS			4
 #elif defined(CONFIG_PPC_T1020) || defined(CONFIG_PPC_T1022)
@@ -788,6 +797,7 @@  defined(CONFIG_PPC_T1020) || defined(CONFIG_PPC_T1022)
 #define CONFIG_SYS_FSL_SEC_COMPAT	6
 #define CONFIG_SYS_FSL_ERRATUM_ESDHC111
 #define CONFIG_NUM_DDR_CONTROLLERS	1
+#define CONFIG_SYS_FSL_DDR_VER		FSL_DDR_VER_4_6
 #define CONFIG_SYS_FSL_IFC_BANK_COUNT	8
 #define CONFIG_SYS_CCSRBAR_DEFAULT	0xff700000
 #define CONFIG_SYS_FSL_ERRATUM_A005125
@@ -808,7 +818,8 @@  defined(CONFIG_PPC_T1020) || defined(CONFIG_PPC_T1022)
 
 #if !defined(CONFIG_SYS_FSL_DDRC_GEN1) && \
 	!defined(CONFIG_SYS_FSL_DDRC_GEN2) && \
-	!defined(CONFIG_SYS_FSL_DDRC_GEN3)
+	!defined(CONFIG_SYS_FSL_DDRC_GEN3) && \
+	!defined(CONFIG_SYS_FSL_DDRC_GEN4)
 #define CONFIG_SYS_FSL_DDRC_GEN3
 #endif
 
diff --git a/common/ddr_spd.c b/common/ddr_spd.c
index 7a388bb..438e71a 100644
--- a/common/ddr_spd.c
+++ b/common/ddr_spd.c
@@ -1,5 +1,5 @@ 
 /*
- * Copyright 2008 Freescale Semiconductor, Inc.
+ * Copyright 2008-2014 Freescale Semiconductor, Inc.
  *
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU General Public License
@@ -116,3 +116,46 @@  ddr3_spd_check(const ddr3_spd_eeprom_t *spd)
 		return 1;
 	}
 }
+
+unsigned int ddr4_spd_check(const struct ddr4_spd_eeprom_s *spd)
+{
+	char *p = (char *)spd;
+	int csum16;
+	int len;
+	char crc_lsb;	/* byte 126 */
+	char crc_msb;	/* byte 127 */
+
+	len = 126;
+	csum16 = crc16(p, len);
+
+	crc_lsb = (char) (csum16 & 0xff);
+	crc_msb = (char) (csum16 >> 8);
+
+	if (spd->crc[0] != crc_lsb || spd->crc[1] != crc_msb) {
+		printf("SPD checksum unexpected.\n"
+			"Checksum lsb in SPD = %02X, computed SPD = %02X\n"
+			"Checksum msb in SPD = %02X, computed SPD = %02X\n",
+			spd->crc[0], crc_lsb, spd->crc[1], crc_msb);
+		return 1;
+	}
+
+	p = (char *)((ulong)spd + 128);
+	len = 126;
+	csum16 = crc16(p, len);
+
+	crc_lsb = (char) (csum16 & 0xff);
+	crc_msb = (char) (csum16 >> 8);
+
+	if (spd->mod_section.uc[126] != crc_lsb ||
+	    spd->mod_section.uc[127] != crc_msb) {
+		printf("SPD checksum unexpected.\n"
+			"Checksum lsb in SPD = %02X, computed SPD = %02X\n"
+			"Checksum msb in SPD = %02X, computed SPD = %02X\n",
+			spd->mod_section.uc[126],
+			crc_lsb, spd->mod_section.uc[127],
+			crc_msb);
+		return 1;
+	}
+
+	return 0;
+}
diff --git a/drivers/ddr/fsl/Makefile b/drivers/ddr/fsl/Makefile
index 265204f..df66c07 100644
--- a/drivers/ddr/fsl/Makefile
+++ b/drivers/ddr/fsl/Makefile
@@ -1,19 +1,20 @@ 
 #
-# Copyright 2008-2011 Freescale Semiconductor, Inc.
+# Copyright 2008-2014 Freescale Semiconductor, Inc.
 #
 # This program is free software; you can redistribute it and/or
 # modify it under the terms of the GNU General Public License
 # Version 2 as published by the Free Software Foundation.
 #
 
-obj-$(CONFIG_SYS_FSL_DDR1)	+= main.o util.o ctrl_regs.o options.o \
-				   lc_common_dimm_params.o
+obj-$(CONFIG_SYS_FSL_DDR1) += main.o util.o ctrl_regs.o options.o \
+				lc_common_dimm_params.o
+obj-$(CONFIG_SYS_FSL_DDR2) += main.o util.o ctrl_regs.o options.o \
+				lc_common_dimm_params.o
+obj-$(CONFIG_SYS_FSL_DDR3) += main.o util.o ctrl_regs.o options.o \
+				lc_common_dimm_params.o
+obj-$(CONFIG_SYS_FSL_DDR4) += main.o util.o ctrl_regs.o options.o \
+				lc_common_dimm_params.o
 
-obj-$(CONFIG_SYS_FSL_DDR2)	+= main.o util.o ctrl_regs.o options.o \
-				   lc_common_dimm_params.o
-
-obj-$(CONFIG_SYS_FSL_DDR3)	+= main.o util.o ctrl_regs.o options.o \
-				   lc_common_dimm_params.o
 ifdef CONFIG_DDR_SPD
 SPD := y
 endif
@@ -24,6 +25,7 @@  ifdef SPD
 obj-$(CONFIG_SYS_FSL_DDR1)	+= ddr1_dimm_params.o
 obj-$(CONFIG_SYS_FSL_DDR2)	+= ddr2_dimm_params.o
 obj-$(CONFIG_SYS_FSL_DDR3)	+= ddr3_dimm_params.o
+obj-$(CONFIG_SYS_FSL_DDR4)	+= ddr4_dimm_params.o
 endif
 
 obj-$(CONFIG_FSL_DDR_INTERACTIVE)	+= interactive.o
@@ -32,3 +34,4 @@  obj-$(CONFIG_SYS_FSL_DDRC_GEN2)	+= mpc85xx_ddr_gen2.o
 obj-$(CONFIG_SYS_FSL_DDRC_GEN3)	+= mpc85xx_ddr_gen3.o
 obj-$(CONFIG_SYS_FSL_DDR_86XX)		+= mpc86xx_ddr.o
 obj-$(CONFIG_SYS_FSL_DDRC_ARM_GEN3)	+= arm_ddr_gen3.o
+obj-$(CONFIG_SYS_FSL_DDRC_GEN4) += fsl_ddr_gen4.o
diff --git a/drivers/ddr/fsl/ctrl_regs.c b/drivers/ddr/fsl/ctrl_regs.c
index 0882932..d01eea0 100644
--- a/drivers/ddr/fsl/ctrl_regs.c
+++ b/drivers/ddr/fsl/ctrl_regs.c
@@ -1,5 +1,5 @@ 
 /*
- * Copyright 2008-2012 Freescale Semiconductor, Inc.
+ * Copyright 2008-2014 Freescale Semiconductor, Inc.
  *
  * SPDX-License-Identifier:	GPL-2.0+
  */
@@ -17,20 +17,6 @@ 
 #include <fsl_immap.h>
 #include <asm/io.h>
 
-#define _DDR_ADDR CONFIG_SYS_FSL_DDR_ADDR
-
-static u32 fsl_ddr_get_version(void)
-{
-	struct ccsr_ddr __iomem *ddr;
-	u32 ver_major_minor_errata;
-
-	ddr = (void *)_DDR_ADDR;
-	ver_major_minor_errata = (ddr_in32(&ddr->ip_rev1) & 0xFFFF) << 8;
-	ver_major_minor_errata |= (ddr_in32(&ddr->ip_rev2) & 0xFF00) >> 8;
-
-	return ver_major_minor_errata;
-}
-
 unsigned int picos_to_mclk(unsigned int picos);
 
 /*
@@ -81,6 +67,39 @@  static inline int fsl_ddr_get_rtt(void)
 	return rtt;
 }
 
+#ifdef CONFIG_SYS_FSL_DDR4
+/*
+ * compute CAS write latency according to DDR4 spec
+ * CWL = 9 for <= 1600MT/s
+ *       10 for <= 1866MT/s
+ *       11 for <= 2133MT/s
+ *       12 for <= 2400MT/s
+ *       14 for <= 2667MT/s
+ *       16 for <= 2933MT/s
+ *       18 for higher
+ */
+static inline unsigned int compute_cas_write_latency(void)
+{
+	unsigned int cwl;
+	const unsigned int mclk_ps = get_memory_clk_period_ps();
+	if (mclk_ps >= 1250)
+		cwl = 9;
+	else if (mclk_ps >= 1070)
+		cwl = 10;
+	else if (mclk_ps >= 935)
+		cwl = 11;
+	else if (mclk_ps >= 833)
+		cwl = 12;
+	else if (mclk_ps >= 750)
+		cwl = 14;
+	else if (mclk_ps >= 681)
+		cwl = 16;
+	else
+		cwl = 18;
+
+	return cwl;
+}
+#else
 /*
  * compute the CAS write latency according to DDR3 spec
  * CWL = 5 if tCK >= 2.5ns
@@ -119,6 +138,7 @@  static inline unsigned int compute_cas_write_latency(void)
 	}
 	return cwl;
 }
+#endif
 
 /* Chip Select Configuration (CSn_CONFIG) */
 static void set_csn_config(int dimm_number, int i, fsl_ddr_cfg_regs_t *ddr,
@@ -135,6 +155,11 @@  static void set_csn_config(int dimm_number, int i, fsl_ddr_cfg_regs_t *ddr,
 	unsigned int row_bits_cs_n = 0; /* Num of row bits for SDRAM on CSn */
 	unsigned int col_bits_cs_n = 0; /* Num of ocl bits for SDRAM on CSn */
 	int go_config = 0;
+#ifdef CONFIG_SYS_FSL_DDR4
+	unsigned int bg_bits_cs_n = 0; /* Num of bank group bits */
+#else
+	unsigned int n_banks_per_sdram_device;
+#endif
 
 	/* Compute CS_CONFIG only for existing ranks of each DIMM.  */
 	switch (i) {
@@ -178,14 +203,18 @@  static void set_csn_config(int dimm_number, int i, fsl_ddr_cfg_regs_t *ddr,
 		break;
 	}
 	if (go_config) {
-		unsigned int n_banks_per_sdram_device;
 		cs_n_en = 1;
 		ap_n_en = popts->cs_local_opts[i].auto_precharge;
 		odt_rd_cfg = popts->cs_local_opts[i].odt_rd_cfg;
 		odt_wr_cfg = popts->cs_local_opts[i].odt_wr_cfg;
+#ifdef CONFIG_SYS_FSL_DDR4
+		ba_bits_cs_n = dimm_params[dimm_number].bank_addr_bits;
+		bg_bits_cs_n = dimm_params[dimm_number].bank_group_bits;
+#else
 		n_banks_per_sdram_device
 			= dimm_params[dimm_number].n_banks_per_sdram_device;
 		ba_bits_cs_n = __ilog2(n_banks_per_sdram_device) - 2;
+#endif
 		row_bits_cs_n = dimm_params[dimm_number].n_row_addr - 12;
 		col_bits_cs_n = dimm_params[dimm_number].n_col_addr - 8;
 	}
@@ -203,6 +232,9 @@  static void set_csn_config(int dimm_number, int i, fsl_ddr_cfg_regs_t *ddr,
 
 		| ((ba_bits_cs_n & 0x3) << 14)
 		| ((row_bits_cs_n & 0x7) << 8)
+#ifdef CONFIG_SYS_FSL_DDR4
+		| ((bg_bits_cs_n & 0x3) << 4)
+#endif
 		| ((col_bits_cs_n & 0x7) << 0)
 		);
 	debug("FSLDDR: cs[%d]_config = 0x%08x\n", i,ddr->cs[i].config);
@@ -262,11 +294,23 @@  static void set_timing_cfg_0(fsl_ddr_cfg_regs_t *ddr,
 	/* Precharge powerdown exit timing (tXP). */
 	unsigned char pre_pd_exit_mclk;
 	/* ODT powerdown exit timing (tAXPD). */
-	unsigned char taxpd_mclk;
+	unsigned char taxpd_mclk = 0;
 	/* Mode register set cycle time (tMRD). */
 	unsigned char tmrd_mclk;
 
-#ifdef CONFIG_SYS_FSL_DDR3
+#ifdef CONFIG_SYS_FSL_DDR4
+	/* tXP=max(4nCK, 6ns) */
+	int txp = max((get_memory_clk_period_ps() * 4), 6000); /* unit=ps */
+	trwt_mclk = 2;
+	twrt_mclk = 1;
+	act_pd_exit_mclk = picos_to_mclk(txp);
+	pre_pd_exit_mclk = act_pd_exit_mclk;
+	/*
+	 * MRS_CYC = max(tMRD, tMOD)
+	 * tMRD = 8nCK, tMOD = max(24nCK, 15ns)
+	 */
+	tmrd_mclk = max(24, picos_to_mclk(15000));
+#elif defined(CONFIG_SYS_FSL_DDR3)
 	/*
 	 * (tXARD and tXARDS). Empirical?
 	 * The DDR3 spec has not tXARD,
@@ -275,7 +319,7 @@  static void set_timing_cfg_0(fsl_ddr_cfg_regs_t *ddr,
 	 * spec has not the tAXPD, we use
 	 * tAXPD=1, need design to confirm.
 	 */
-	int tXP = max((get_memory_clk_period_ps() * 3), 7500); /* unit=ps */
+	int txp = max((get_memory_clk_period_ps() * 3), 7500); /* unit=ps */
 	unsigned int data_rate = get_ddr_freq(0);
 	tmrd_mclk = 4;
 	/* set the turnaround time */
@@ -300,7 +344,7 @@  static void set_timing_cfg_0(fsl_ddr_cfg_regs_t *ddr,
 		taxpd_mclk = 1;
 	} else {
 		/* act_pd_exit_mclk = tXARD, see above */
-		act_pd_exit_mclk = picos_to_mclk(tXP);
+		act_pd_exit_mclk = picos_to_mclk(txp);
 		/* Mode register MR0[A12] is '1' - fast exit */
 		pre_pd_exit_mclk = act_pd_exit_mclk;
 		taxpd_mclk = 1;
@@ -364,8 +408,12 @@  static void set_timing_cfg_3(fsl_ddr_cfg_regs_t *ddr,
 	ext_acttorw = picos_to_mclk(common_dimm->trcd_ps) >> 4;
 	ext_caslat = (2 * cas_latency - 1) >> 4;
 	ext_add_lat = additive_latency >> 4;
+#ifdef CONFIG_SYS_FSL_DDR4
+	ext_refrec = (picos_to_mclk(common_dimm->trfc1_ps) - 8) >> 4;
+#else
 	ext_refrec = (picos_to_mclk(common_dimm->trfc_ps) - 8) >> 4;
 	/* ext_wrrec only deals with 16 clock and above, or 14 with OTF */
+#endif
 	ext_wrrec = (picos_to_mclk(common_dimm->twr_ps) +
 		(popts->otf_burst_chop_en ? 2 : 0)) >> 4;
 
@@ -404,9 +452,19 @@  static void set_timing_cfg_1(fsl_ddr_cfg_regs_t *ddr,
 	unsigned char acttoact_mclk;
 	/* Last write data pair to read command issue interval (tWTR) */
 	unsigned char wrtord_mclk;
+#ifdef CONFIG_SYS_FSL_DDR4
+	/* DDR4 supports 10, 12, 14, 16, 18, 20, 24 */
+	static const u8 wrrec_table[] = {
+		10, 10, 10, 10, 10,
+		10, 10, 10, 10, 10,
+		12, 12, 14, 14, 16,
+		16, 18, 18, 20, 20,
+		24, 24, 24, 24};
+#else
 	/* DDR_SDRAM_MODE doesn't support 9,11,13,15 */
 	static const u8 wrrec_table[] = {
 		1, 2, 3, 4, 5, 6, 7, 8, 10, 10, 12, 12, 14, 14, 0, 0};
+#endif
 
 	pretoact_mclk = picos_to_mclk(common_dimm->trp_ps);
 	acttopre_mclk = picos_to_mclk(common_dimm->tras_ps);
@@ -438,20 +496,34 @@  static void set_timing_cfg_1(fsl_ddr_cfg_regs_t *ddr,
 	 * we need set extend bit for it at
 	 * TIMING_CFG_3[EXT_CASLAT]
 	 */
-	caslat_ctrl = 2 * cas_latency - 1;
+	if (fsl_ddr_get_version() <= 0x40400)
+		caslat_ctrl = 2 * cas_latency - 1;
+	else
+		caslat_ctrl = (cas_latency - 1) << 1;
 #endif
 
+#ifdef CONFIG_SYS_FSL_DDR4
+	refrec_ctrl = picos_to_mclk(common_dimm->trfc1_ps) - 8;
+	wrrec_mclk = picos_to_mclk(common_dimm->twr_ps);
+	acttoact_mclk = max(picos_to_mclk(common_dimm->trrds_ps), 4);
+	wrtord_mclk = max(2, picos_to_mclk(2500));
+	if (wrrec_mclk > 24)
+		printf("Error: WRREC doesn't support more than 24 clocks\n");
+	else
+		wrrec_mclk = wrrec_table[wrrec_mclk - 1];
+#else
 	refrec_ctrl = picos_to_mclk(common_dimm->trfc_ps) - 8;
 	wrrec_mclk = picos_to_mclk(common_dimm->twr_ps);
-
+	acttoact_mclk = picos_to_mclk(common_dimm->trrd_ps);
+	wrtord_mclk = picos_to_mclk(common_dimm->twtr_ps);
 	if (wrrec_mclk > 16)
 		printf("Error: WRREC doesn't support more than 16 clocks\n");
 	else
 		wrrec_mclk = wrrec_table[wrrec_mclk - 1];
+#endif
 	if (popts->otf_burst_chop_en)
 		wrrec_mclk += 2;
 
-	acttoact_mclk = picos_to_mclk(common_dimm->trrd_ps);
 	/*
 	 * JEDEC has min requirement for tRRD
 	 */
@@ -459,7 +531,6 @@  static void set_timing_cfg_1(fsl_ddr_cfg_regs_t *ddr,
 	if (acttoact_mclk < 4)
 		acttoact_mclk = 4;
 #endif
-	wrtord_mclk = picos_to_mclk(common_dimm->twtr_ps);
 	/*
 	 * JEDEC has some min requirements for tWTR
 	 */
@@ -526,14 +597,18 @@  static void set_timing_cfg_2(fsl_ddr_cfg_regs_t *ddr,
 	wr_lat = compute_cas_write_latency();
 #endif
 
+#ifdef CONFIG_SYS_FSL_DDR4
+	rd_to_pre = picos_to_mclk(7500);
+#else
 	rd_to_pre = picos_to_mclk(common_dimm->trtp_ps);
+#endif
 	/*
 	 * JEDEC has some min requirements for tRTP
 	 */
 #if defined(CONFIG_SYS_FSL_DDR2)
 	if (rd_to_pre  < 2)
 		rd_to_pre  = 2;
-#elif defined(CONFIG_SYS_FSL_DDR3)
+#elif defined(CONFIG_SYS_FSL_DDR3) || defined(CONFIG_SYS_FSL_DDR4)
 	if (rd_to_pre < 4)
 		rd_to_pre = 4;
 #endif
@@ -541,13 +616,20 @@  static void set_timing_cfg_2(fsl_ddr_cfg_regs_t *ddr,
 		rd_to_pre += 2; /* according to UM */
 
 	wr_data_delay = popts->write_data_delay;
+#ifdef CONFIG_SYS_FSL_DDR4
+	cpo = 0;
+	cke_pls = max(3, picos_to_mclk(5000));
+#else
 	cke_pls = picos_to_mclk(popts->tcke_clock_pulse_width_ps);
+#endif
+
 	four_act = picos_to_mclk(popts->tfaw_window_four_activates_ps);
 
 	ddr->timing_cfg_2 = (0
 		| ((add_lat_mclk & 0xf) << 28)
 		| ((cpo & 0x1f) << 23)
 		| ((wr_lat & 0xf) << 19)
+		| ((wr_lat & 0x10) << 14)
 		| ((rd_to_pre & RD_TO_PRE_MASK) << RD_TO_PRE_SHIFT)
 		| ((wr_data_delay & WR_DATA_DELAY_MASK) << WR_DATA_DELAY_SHIFT)
 		| ((cke_pls & 0x7) << 6)
@@ -640,7 +722,8 @@  static void set_ddr_sdram_cfg(fsl_ddr_cfg_regs_t *ddr,
 	 * we must clear it when use the on-the-fly mode,
 	 * must set it when use the 32-bits bus mode.
 	 */
-	if (sdram_type == SDRAM_TYPE_DDR3) {
+	if ((sdram_type == SDRAM_TYPE_DDR3) ||
+	    (sdram_type == SDRAM_TYPE_DDR4)) {
 		if (popts->burst_length == DDR_BL8)
 			eight_be = 1;
 		if (popts->burst_length == DDR_OTF)
@@ -682,8 +765,6 @@  static void set_ddr_sdram_cfg_2(fsl_ddr_cfg_regs_t *ddr,
 {
 	unsigned int frc_sr = 0;	/* Force self refresh */
 	unsigned int sr_ie = 0;		/* Self-refresh interrupt enable */
-	unsigned int dll_rst_dis;	/* DLL reset disable */
-	unsigned int dqs_cfg;		/* DQS configuration */
 	unsigned int odt_cfg = 0;	/* ODT configuration */
 	unsigned int num_pr;		/* Number of posted refreshes */
 	unsigned int slow = 0;		/* DDR will be run less than 1250 */
@@ -695,9 +776,12 @@  static void set_ddr_sdram_cfg_2(fsl_ddr_cfg_regs_t *ddr,
 	unsigned int md_en = 0;		/* Mirrored DIMM Enable */
 	unsigned int qd_en = 0;		/* quad-rank DIMM Enable */
 	int i;
+#ifndef CONFIG_SYS_FSL_DDR4
+	unsigned int dll_rst_dis = 1;	/* DLL reset disable */
+	unsigned int dqs_cfg;		/* DQS configuration */
 
-	dll_rst_dis = 1;	/* Make this configurable */
 	dqs_cfg = popts->dqs_config;
+#endif
 	for (i = 0; i < CONFIG_CHIP_SELECTS_PER_CTRL; i++) {
 		if (popts->cs_local_opts[i].odt_rd_cfg
 			|| popts->cs_local_opts[i].odt_wr_cfg) {
@@ -715,7 +799,7 @@  static void set_ddr_sdram_cfg_2(fsl_ddr_cfg_regs_t *ddr,
 	 *        * ({EXT_REFREC || REFREC} + 8 + 2)]}
 	 *      << DDR_SDRAM_INTERVAL[REFINT]
 	 */
-#if defined(CONFIG_SYS_FSL_DDR3)
+#if defined(CONFIG_SYS_FSL_DDR3) || defined(CONFIG_SYS_FSL_DDR4)
 	obc_cfg = popts->otf_burst_chop_en;
 #else
 	obc_cfg = 0;
@@ -744,15 +828,17 @@  static void set_ddr_sdram_cfg_2(fsl_ddr_cfg_regs_t *ddr,
 	d_init = 0;
 #endif
 
-#if defined(CONFIG_SYS_FSL_DDR3)
+#if defined(CONFIG_SYS_FSL_DDR3) || defined(CONFIG_SYS_FSL_DDR4)
 	md_en = popts->mirrored_dimm;
 #endif
 	qd_en = popts->quad_rank_present ? 1 : 0;
 	ddr->ddr_sdram_cfg_2 = (0
 		| ((frc_sr & 0x1) << 31)
 		| ((sr_ie & 0x1) << 30)
+#ifndef CONFIG_SYS_FSL_DDR4
 		| ((dll_rst_dis & 0x1) << 29)
 		| ((dqs_cfg & 0x3) << 26)
+#endif
 		| ((odt_cfg & 0x3) << 21)
 		| ((num_pr & 0xf) << 12)
 		| ((slow & 1) << 11)
@@ -768,6 +854,7 @@  static void set_ddr_sdram_cfg_2(fsl_ddr_cfg_regs_t *ddr,
 	debug("FSLDDR: ddr_sdram_cfg_2 = 0x%08x\n", ddr->ddr_sdram_cfg_2);
 }
 
+#ifdef CONFIG_SYS_FSL_DDR4
 /* DDR SDRAM Mode configuration 2 (DDR_SDRAM_MODE_2) */
 static void set_ddr_sdram_mode_2(fsl_ddr_cfg_regs_t *ddr,
 				const memctl_options_t *popts,
@@ -776,8 +863,93 @@  static void set_ddr_sdram_mode_2(fsl_ddr_cfg_regs_t *ddr,
 {
 	unsigned short esdmode2 = 0;	/* Extended SDRAM mode 2 */
 	unsigned short esdmode3 = 0;	/* Extended SDRAM mode 3 */
+	int i;
+	unsigned int wr_crc = 0;	/* Disable */
+	unsigned int rtt_wr = 0;	/* Rtt_WR - dynamic ODT off */
+	unsigned int srt = 0;	/* self-refresh temerature, normal range */
+	unsigned int cwl = compute_cas_write_latency() - 9;
+	unsigned int mpr = 0;	/* serial */
+	unsigned int wc_lat;
+	const unsigned int mclk_ps = get_memory_clk_period_ps();
 
-#if defined(CONFIG_SYS_FSL_DDR3)
+	if (popts->rtt_override)
+		rtt_wr = popts->rtt_wr_override_value;
+	else
+		rtt_wr = popts->cs_local_opts[0].odt_rtt_wr;
+
+	if (common_dimm->extended_op_srt)
+		srt = common_dimm->extended_op_srt;
+
+	esdmode2 = (0
+		| ((wr_crc & 0x1) << 12)
+		| ((rtt_wr & 0x3) << 9)
+		| ((srt & 0x3) << 6)
+		| ((cwl & 0x7) << 3));
+
+	if (mclk_ps >= 1250)
+		wc_lat = 0;
+	else if (mclk_ps >= 833)
+		wc_lat = 1;
+	else
+		wc_lat = 2;
+
+	esdmode3 = (0
+		| ((mpr & 0x3) << 11)
+		| ((wc_lat & 0x3) << 9));
+
+	ddr->ddr_sdram_mode_2 = (0
+				 | ((esdmode2 & 0xFFFF) << 16)
+				 | ((esdmode3 & 0xFFFF) << 0)
+				 );
+	debug("FSLDDR: ddr_sdram_mode_2 = 0x%08x\n", ddr->ddr_sdram_mode_2);
+
+	if (unq_mrs_en) {	/* unique mode registers are supported */
+		for (i = 1; i < CONFIG_CHIP_SELECTS_PER_CTRL; i++) {
+			if (popts->rtt_override)
+				rtt_wr = popts->rtt_wr_override_value;
+			else
+				rtt_wr = popts->cs_local_opts[i].odt_rtt_wr;
+
+			esdmode2 &= 0xF9FF;	/* clear bit 10, 9 */
+			esdmode2 |= (rtt_wr & 0x3) << 9;
+			switch (i) {
+			case 1:
+				ddr->ddr_sdram_mode_4 = (0
+					| ((esdmode2 & 0xFFFF) << 16)
+					| ((esdmode3 & 0xFFFF) << 0)
+					);
+				break;
+			case 2:
+				ddr->ddr_sdram_mode_6 = (0
+					| ((esdmode2 & 0xFFFF) << 16)
+					| ((esdmode3 & 0xFFFF) << 0)
+					);
+				break;
+			case 3:
+				ddr->ddr_sdram_mode_8 = (0
+					| ((esdmode2 & 0xFFFF) << 16)
+					| ((esdmode3 & 0xFFFF) << 0)
+					);
+				break;
+			}
+		}
+		debug("FSLDDR: ddr_sdram_mode_4 = 0x%08x\n",
+		      ddr->ddr_sdram_mode_4);
+		debug("FSLDDR: ddr_sdram_mode_6 = 0x%08x\n",
+		      ddr->ddr_sdram_mode_6);
+		debug("FSLDDR: ddr_sdram_mode_8 = 0x%08x\n",
+		      ddr->ddr_sdram_mode_8);
+	}
+}
+#elif defined(CONFIG_SYS_FSL_DDR3)
+/* DDR SDRAM Mode configuration 2 (DDR_SDRAM_MODE_2) */
+static void set_ddr_sdram_mode_2(fsl_ddr_cfg_regs_t *ddr,
+				const memctl_options_t *popts,
+				const common_timing_params_t *common_dimm,
+				const unsigned int unq_mrs_en)
+{
+	unsigned short esdmode2 = 0;	/* Extended SDRAM mode 2 */
+	unsigned short esdmode3 = 0;	/* Extended SDRAM mode 3 */
 	int i;
 	unsigned int rtt_wr = 0;	/* Rtt_WR - dynamic ODT off */
 	unsigned int srt = 0;	/* self-refresh temerature, normal range */
@@ -799,14 +971,12 @@  static void set_ddr_sdram_mode_2(fsl_ddr_cfg_regs_t *ddr,
 		| ((asr & 0x1) << 6)
 		| ((cwl & 0x7) << 3)
 		| ((pasr & 0x7) << 0));
-#endif
 	ddr->ddr_sdram_mode_2 = (0
 				 | ((esdmode2 & 0xFFFF) << 16)
 				 | ((esdmode3 & 0xFFFF) << 0)
 				 );
 	debug("FSLDDR: ddr_sdram_mode_2 = 0x%08x\n", ddr->ddr_sdram_mode_2);
 
-#ifdef CONFIG_SYS_FSL_DDR3
 	if (unq_mrs_en) {	/* unique mode registers are supported */
 		for (i = 1; i < CONFIG_CHIP_SELECTS_PER_CTRL; i++) {
 			if (popts->rtt_override)
@@ -844,9 +1014,128 @@  static void set_ddr_sdram_mode_2(fsl_ddr_cfg_regs_t *ddr,
 		debug("FSLDDR: ddr_sdram_mode_8 = 0x%08x\n",
 			ddr->ddr_sdram_mode_8);
 	}
+}
+
+#else /* for DDR2 and DDR1 */
+/* DDR SDRAM Mode configuration 2 (DDR_SDRAM_MODE_2) */
+static void set_ddr_sdram_mode_2(fsl_ddr_cfg_regs_t *ddr,
+				const memctl_options_t *popts,
+				const common_timing_params_t *common_dimm,
+				const unsigned int unq_mrs_en)
+{
+	unsigned short esdmode2 = 0;	/* Extended SDRAM mode 2 */
+	unsigned short esdmode3 = 0;	/* Extended SDRAM mode 3 */
+
+	ddr->ddr_sdram_mode_2 = (0
+				 | ((esdmode2 & 0xFFFF) << 16)
+				 | ((esdmode3 & 0xFFFF) << 0)
+				 );
+	debug("FSLDDR: ddr_sdram_mode_2 = 0x%08x\n", ddr->ddr_sdram_mode_2);
+}
 #endif
+
+#ifdef CONFIG_SYS_FSL_DDR4
+/* DDR SDRAM Mode configuration 9 (DDR_SDRAM_MODE_9) */
+static void set_ddr_sdram_mode_9(fsl_ddr_cfg_regs_t *ddr,
+				const memctl_options_t *popts,
+				const common_timing_params_t *common_dimm,
+				const unsigned int unq_mrs_en)
+{
+	int i;
+	unsigned short esdmode4 = 0;	/* Extended SDRAM mode 4 */
+	unsigned short esdmode5;	/* Extended SDRAM mode 5 */
+
+	esdmode5 = 0x00000400;		/* Data mask enabled */
+
+	ddr->ddr_sdram_mode_9 = (0
+				 | ((esdmode4 & 0xffff) << 16)
+				 | ((esdmode5 & 0xffff) << 0)
+				);
+	debug("FSLDDR: ddr_sdram_mode_9) = 0x%08x\n", ddr->ddr_sdram_mode_9);
+	if (unq_mrs_en) {	/* unique mode registers are supported */
+		for (i = 1; i < CONFIG_CHIP_SELECTS_PER_CTRL; i++) {
+			switch (i) {
+			case 1:
+				ddr->ddr_sdram_mode_11 = (0
+					| ((esdmode4 & 0xFFFF) << 16)
+					| ((esdmode5 & 0xFFFF) << 0)
+					);
+				break;
+			case 2:
+				ddr->ddr_sdram_mode_13 = (0
+					| ((esdmode4 & 0xFFFF) << 16)
+					| ((esdmode5 & 0xFFFF) << 0)
+					);
+				break;
+			case 3:
+				ddr->ddr_sdram_mode_15 = (0
+					| ((esdmode4 & 0xFFFF) << 16)
+					| ((esdmode5 & 0xFFFF) << 0)
+					);
+				break;
+			}
+		}
+		debug("FSLDDR: ddr_sdram_mode_11 = 0x%08x\n",
+		      ddr->ddr_sdram_mode_11);
+		debug("FSLDDR: ddr_sdram_mode_13 = 0x%08x\n",
+		      ddr->ddr_sdram_mode_13);
+		debug("FSLDDR: ddr_sdram_mode_15 = 0x%08x\n",
+		      ddr->ddr_sdram_mode_15);
+	}
+}
+
+/* DDR SDRAM Mode configuration 10 (DDR_SDRAM_MODE_10) */
+static void set_ddr_sdram_mode_10(fsl_ddr_cfg_regs_t *ddr,
+				const memctl_options_t *popts,
+				const common_timing_params_t *common_dimm,
+				const unsigned int unq_mrs_en)
+{
+	int i;
+	unsigned short esdmode6 = 0;	/* Extended SDRAM mode 6 */
+	unsigned short esdmode7 = 0;	/* Extended SDRAM mode 7 */
+	unsigned int tccdl_min = picos_to_mclk(common_dimm->tccdl_ps);
+
+	esdmode6 = ((tccdl_min - 4) & 0x7) << 10;
+
+	ddr->ddr_sdram_mode_10 = (0
+				 | ((esdmode6 & 0xffff) << 16)
+				 | ((esdmode7 & 0xffff) << 0)
+				);
+	debug("FSLDDR: ddr_sdram_mode_10) = 0x%08x\n", ddr->ddr_sdram_mode_10);
+	if (unq_mrs_en) {	/* unique mode registers are supported */
+		for (i = 1; i < CONFIG_CHIP_SELECTS_PER_CTRL; i++) {
+			switch (i) {
+			case 1:
+				ddr->ddr_sdram_mode_12 = (0
+					| ((esdmode6 & 0xFFFF) << 16)
+					| ((esdmode7 & 0xFFFF) << 0)
+					);
+				break;
+			case 2:
+				ddr->ddr_sdram_mode_14 = (0
+					| ((esdmode6 & 0xFFFF) << 16)
+					| ((esdmode7 & 0xFFFF) << 0)
+					);
+				break;
+			case 3:
+				ddr->ddr_sdram_mode_16 = (0
+					| ((esdmode6 & 0xFFFF) << 16)
+					| ((esdmode7 & 0xFFFF) << 0)
+					);
+				break;
+			}
+		}
+		debug("FSLDDR: ddr_sdram_mode_12 = 0x%08x\n",
+		      ddr->ddr_sdram_mode_12);
+		debug("FSLDDR: ddr_sdram_mode_14 = 0x%08x\n",
+		      ddr->ddr_sdram_mode_14);
+		debug("FSLDDR: ddr_sdram_mode_16 = 0x%08x\n",
+		      ddr->ddr_sdram_mode_16);
+	}
 }
 
+#endif
+
 /* DDR SDRAM Interval Configuration (DDR_SDRAM_INTERVAL) */
 static void set_ddr_sdram_interval(fsl_ddr_cfg_regs_t *ddr,
 			       const memctl_options_t *popts,
@@ -867,7 +1156,7 @@  static void set_ddr_sdram_interval(fsl_ddr_cfg_regs_t *ddr,
 	debug("FSLDDR: ddr_sdram_interval = 0x%08x\n", ddr->ddr_sdram_interval);
 }
 
-#if defined(CONFIG_SYS_FSL_DDR3)
+#ifdef CONFIG_SYS_FSL_DDR4
 /* DDR SDRAM Mode configuration set (DDR_SDRAM_MODE) */
 static void set_ddr_sdram_mode(fsl_ddr_cfg_regs_t *ddr,
 			       const memctl_options_t *popts,
@@ -876,6 +1165,177 @@  static void set_ddr_sdram_mode(fsl_ddr_cfg_regs_t *ddr,
 			       unsigned int additive_latency,
 			       const unsigned int unq_mrs_en)
 {
+	int i;
+	unsigned short esdmode;		/* Extended SDRAM mode */
+	unsigned short sdmode;		/* SDRAM mode */
+
+	/* Mode Register - MR1 */
+	unsigned int qoff = 0;		/* Output buffer enable 0=yes, 1=no */
+	unsigned int tdqs_en = 0;	/* TDQS Enable: 0=no, 1=yes */
+	unsigned int rtt;
+	unsigned int wrlvl_en = 0;	/* Write level enable: 0=no, 1=yes */
+	unsigned int al = 0;		/* Posted CAS# additive latency (AL) */
+	unsigned int dic = 0;		/* Output driver impedance, 40ohm */
+	unsigned int dll_en = 1;	/* DLL Enable  1=Enable (Normal),
+						       0=Disable (Test/Debug) */
+
+	/* Mode Register - MR0 */
+	unsigned int wr = 0;	/* Write Recovery */
+	unsigned int dll_rst;	/* DLL Reset */
+	unsigned int mode;	/* Normal=0 or Test=1 */
+	unsigned int caslat = 4;/* CAS# latency, default set as 6 cycles */
+	/* BT: Burst Type (0=Nibble Sequential, 1=Interleaved) */
+	unsigned int bt;
+	unsigned int bl;	/* BL: Burst Length */
+
+	unsigned int wr_mclk;
+	/* DDR4 support WR 10, 12, 14, 16, 18, 20, 24 */
+	static const u8 wr_table[] = {
+		0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 6, 6};
+	/* DDR4 support CAS 9, 10, 11, 12, 13, 14, 15, 16, 18, 20, 22, 24 */
+	static const u8 cas_latency_table[] = {
+		0, 1, 2, 3, 4, 5, 6, 7, 8, 8,
+		9, 9, 10, 10, 11, 11};
+
+	if (popts->rtt_override)
+		rtt = popts->rtt_override_value;
+	else
+		rtt = popts->cs_local_opts[0].odt_rtt_norm;
+
+	if (additive_latency == (cas_latency - 1))
+		al = 1;
+	if (additive_latency == (cas_latency - 2))
+		al = 2;
+
+	if (popts->quad_rank_present)
+		dic = 1;	/* output driver impedance 240/7 ohm */
+
+	/*
+	 * The esdmode value will also be used for writing
+	 * MR1 during write leveling for DDR3, although the
+	 * bits specifically related to the write leveling
+	 * scheme will be handled automatically by the DDR
+	 * controller. so we set the wrlvl_en = 0 here.
+	 */
+	esdmode = (0
+		| ((qoff & 0x1) << 12)
+		| ((tdqs_en & 0x1) << 11)
+		| ((rtt & 0x7) << 8)
+		| ((wrlvl_en & 0x1) << 7)
+		| ((al & 0x3) << 3)
+		| ((dic & 0x3) << 1)   /* DIC field is split */
+		| ((dll_en & 0x1) << 0)
+		);
+
+	/*
+	 * DLL control for precharge PD
+	 * 0=slow exit DLL off (tXPDLL)
+	 * 1=fast exit DLL on (tXP)
+	 */
+
+	wr_mclk = picos_to_mclk(common_dimm->twr_ps);
+	if (wr_mclk <= 24) {
+		wr = wr_table[wr_mclk - 10];
+	} else {
+		printf("Error: unsupported write recovery for mode register wr_mclk = %d\n",
+		       wr_mclk);
+	}
+
+	dll_rst = 0;	/* dll no reset */
+	mode = 0;	/* normal mode */
+
+	/* look up table to get the cas latency bits */
+	if (cas_latency >= 9 && cas_latency <= 24)
+		caslat = cas_latency_table[cas_latency - 9];
+	else
+		printf("Error: unsupported cas latency for mode register\n");
+
+	bt = 0;	/* Nibble sequential */
+
+	switch (popts->burst_length) {
+	case DDR_BL8:
+		bl = 0;
+		break;
+	case DDR_OTF:
+		bl = 1;
+		break;
+	case DDR_BC4:
+		bl = 2;
+		break;
+	default:
+		printf("Error: invalid burst length of %u specified. ",
+		       popts->burst_length);
+		puts("Defaulting to on-the-fly BC4 or BL8 beats.\n");
+		bl = 1;
+		break;
+	}
+
+	sdmode = (0
+		  | ((wr & 0x7) << 9)
+		  | ((dll_rst & 0x1) << 8)
+		  | ((mode & 0x1) << 7)
+		  | (((caslat >> 1) & 0x7) << 4)
+		  | ((bt & 0x1) << 3)
+		  | ((caslat & 1) << 2)
+		  | ((bl & 0x3) << 0)
+		  );
+
+	ddr->ddr_sdram_mode = (0
+			       | ((esdmode & 0xFFFF) << 16)
+			       | ((sdmode & 0xFFFF) << 0)
+			       );
+
+	debug("FSLDDR: ddr_sdram_mode = 0x%08x\n", ddr->ddr_sdram_mode);
+
+	if (unq_mrs_en) {	/* unique mode registers are supported */
+		for (i = 1; i < CONFIG_CHIP_SELECTS_PER_CTRL; i++) {
+			if (popts->rtt_override)
+				rtt = popts->rtt_override_value;
+			else
+				rtt = popts->cs_local_opts[i].odt_rtt_norm;
+
+			esdmode &= 0xF8FF;	/* clear bit 10,9,8 for rtt */
+			esdmode |= (rtt & 0x7) << 8;
+			switch (i) {
+			case 1:
+				ddr->ddr_sdram_mode_3 = (0
+				       | ((esdmode & 0xFFFF) << 16)
+				       | ((sdmode & 0xFFFF) << 0)
+				       );
+				break;
+			case 2:
+				ddr->ddr_sdram_mode_5 = (0
+				       | ((esdmode & 0xFFFF) << 16)
+				       | ((sdmode & 0xFFFF) << 0)
+				       );
+				break;
+			case 3:
+				ddr->ddr_sdram_mode_7 = (0
+				       | ((esdmode & 0xFFFF) << 16)
+				       | ((sdmode & 0xFFFF) << 0)
+				       );
+				break;
+			}
+		}
+		debug("FSLDDR: ddr_sdram_mode_3 = 0x%08x\n",
+		      ddr->ddr_sdram_mode_3);
+		debug("FSLDDR: ddr_sdram_mode_5 = 0x%08x\n",
+		      ddr->ddr_sdram_mode_5);
+		debug("FSLDDR: ddr_sdram_mode_5 = 0x%08x\n",
+		      ddr->ddr_sdram_mode_5);
+	}
+}
+
+#elif defined(CONFIG_SYS_FSL_DDR3)
+/* DDR SDRAM Mode configuration set (DDR_SDRAM_MODE) */
+static void set_ddr_sdram_mode(fsl_ddr_cfg_regs_t *ddr,
+			       const memctl_options_t *popts,
+			       const common_timing_params_t *common_dimm,
+			       unsigned int cas_latency,
+			       unsigned int additive_latency,
+			       const unsigned int unq_mrs_en)
+{
+	int i;
 	unsigned short esdmode;		/* Extended SDRAM mode */
 	unsigned short sdmode;		/* SDRAM mode */
 
@@ -907,9 +1367,6 @@  static void set_ddr_sdram_mode(fsl_ddr_cfg_regs_t *ddr,
 	 */
 	static const u8 wr_table[] = {1, 2, 3, 4, 5, 5, 6, 6, 7, 7, 0, 0};
 
-	const unsigned int mclk_ps = get_memory_clk_period_ps();
-	int i;
-
 	if (popts->rtt_override)
 		rtt = popts->rtt_override_value;
 	else
@@ -950,7 +1407,7 @@  static void set_ddr_sdram_mode(fsl_ddr_cfg_regs_t *ddr,
 	 */
 	dll_on = 1;
 
-	wr_mclk = (common_dimm->twr_ps + mclk_ps - 1) / mclk_ps;
+	wr_mclk = picos_to_mclk(common_dimm->twr_ps);
 	if (wr_mclk <= 16) {
 		wr = wr_table[wr_mclk - 5];
 	} else {
@@ -1109,9 +1566,6 @@  static void set_ddr_sdram_mode(fsl_ddr_cfg_regs_t *ddr,
 	unsigned int bt;
 	unsigned int bl;	/* BL: Burst Length */
 
-#if defined(CONFIG_SYS_FSL_DDR2)
-	const unsigned int mclk_ps = get_memory_clk_period_ps();
-#endif
 	dqs_en = !popts->dqs_config;
 	rtt = fsl_ddr_get_rtt();
 
@@ -1141,7 +1595,7 @@  static void set_ddr_sdram_mode(fsl_ddr_cfg_regs_t *ddr,
 #if defined(CONFIG_SYS_FSL_DDR1)
 	wr = 0;       /* Historical */
 #elif defined(CONFIG_SYS_FSL_DDR2)
-	wr = (common_dimm->twr_ps + mclk_ps - 1) / mclk_ps - 1;
+	wr = picos_to_mclk(common_dimm->twr_ps);
 #endif
 	dll_res = 0;
 	mode = 0;
@@ -1255,7 +1709,7 @@  static void set_timing_cfg_4(fsl_ddr_cfg_regs_t *ddr,
 	unsigned int wwt = 0; /* Write-to-write turnaround for same CS */
 	unsigned int dll_lock = 0; /* DDR SDRAM DLL Lock Time */
 
-#if defined(CONFIG_SYS_FSL_DDR3)
+#if defined(CONFIG_SYS_FSL_DDR3) || defined(CONFIG_SYS_FSL_DDR4)
 	if (popts->burst_length == DDR_BL8) {
 		/* We set BL/2 for fixed BL8 */
 		rrt = 0;	/* BL/2 clocks */
@@ -1265,6 +1719,11 @@  static void set_timing_cfg_4(fsl_ddr_cfg_regs_t *ddr,
 		rrt = 2;	/* BL/2 + 2 clocks */
 		wwt = 2;	/* BL/2 + 2 clocks */
 	}
+#endif
+
+#ifdef CONFIG_SYS_FSL_DDR4
+	dll_lock = 2;	/* tDLLK = 1024 clocks */
+#elif defined(CONFIG_SYS_FSL_DDR3)
 	dll_lock = 1;	/* tDLLK = 512 clocks from spec */
 #endif
 	ddr->timing_cfg_4 = (0
@@ -1285,9 +1744,12 @@  static void set_timing_cfg_5(fsl_ddr_cfg_regs_t *ddr, unsigned int cas_latency)
 	unsigned int wodt_on = 0;	/* Write to ODT on */
 	unsigned int wodt_off = 0;	/* Write to ODT off */
 
-#if defined(CONFIG_SYS_FSL_DDR3)
+#if defined(CONFIG_SYS_FSL_DDR3) || defined(CONFIG_SYS_FSL_DDR4)
+	unsigned int wr_lat = ((ddr->timing_cfg_2 & 0x00780000) >> 19) +
+			      ((ddr->timing_cfg_2 & 0x00040000) >> 14);
 	/* rodt_on = timing_cfg_1[caslat] - timing_cfg_2[wrlat] + 1 */
-	rodt_on = cas_latency - ((ddr->timing_cfg_2 & 0x00780000) >> 19) + 1;
+	if (cas_latency >= wr_lat)
+		rodt_on = cas_latency - wr_lat + 1;
 	rodt_off = 4;	/*  4 clocks */
 	wodt_on = 1;	/*  1 clocks */
 	wodt_off = 4;	/*  4 clocks */
@@ -1302,6 +1764,164 @@  static void set_timing_cfg_5(fsl_ddr_cfg_regs_t *ddr, unsigned int cas_latency)
 	debug("FSLDDR: timing_cfg_5 = 0x%08x\n", ddr->timing_cfg_5);
 }
 
+#ifdef CONFIG_SYS_FSL_DDR4
+static void set_timing_cfg_6(fsl_ddr_cfg_regs_t *ddr)
+{
+	unsigned int hs_caslat = 0;
+	unsigned int hs_wrlat = 0;
+	unsigned int hs_wrrec = 0;
+	unsigned int hs_clkadj = 0;
+	unsigned int hs_wrlvl_start = 0;
+
+	ddr->timing_cfg_6 = (0
+			     | ((hs_caslat & 0x1f) << 24)
+			     | ((hs_wrlat & 0x1f) << 19)
+			     | ((hs_wrrec & 0x1f) << 12)
+			     | ((hs_clkadj & 0x1f) << 6)
+			     | ((hs_wrlvl_start & 0x1f) << 0)
+			    );
+	debug("FSLDDR: timing_cfg_6 = 0x%08x\n", ddr->timing_cfg_6);
+}
+
+static void set_timing_cfg_7(fsl_ddr_cfg_regs_t *ddr,
+			const common_timing_params_t *common_dimm)
+{
+	unsigned int txpr, tcksre, tcksrx;
+	unsigned int cke_rst, cksre, cksrx, par_lat, cs_to_cmd;
+
+	txpr = max(5, picos_to_mclk(common_dimm->trfc1_ps + 10000));
+	tcksre = max(5, picos_to_mclk(10000));
+	tcksrx = max(5, picos_to_mclk(10000));
+	par_lat = 0;
+	cs_to_cmd = 0;
+
+	if (txpr <= 200)
+		cke_rst = 0;
+	else if (txpr <= 256)
+		cke_rst = 1;
+	else if (txpr <= 512)
+		cke_rst = 2;
+	else
+		cke_rst = 3;
+
+	if (tcksre <= 19)
+		cksre = tcksre - 5;
+	else
+		cksre = 15;
+
+	if (tcksrx <= 19)
+		cksrx = tcksrx - 5;
+	else
+		cksrx = 15;
+
+	ddr->timing_cfg_7 = (0
+			     | ((cke_rst & 0x3) << 28)
+			     | ((cksre & 0xf) << 24)
+			     | ((cksrx & 0xf) << 20)
+			     | ((par_lat & 0xf) << 16)
+			     | ((cs_to_cmd & 0xf) << 4)
+			    );
+	debug("FSLDDR: timing_cfg_7 = 0x%08x\n", ddr->timing_cfg_7);
+}
+
+static void set_timing_cfg_8(fsl_ddr_cfg_regs_t *ddr,
+			     const memctl_options_t *popts,
+			     const common_timing_params_t *common_dimm,
+			     unsigned int cas_latency)
+{
+	unsigned int rwt_bg, wrt_bg, rrt_bg, wwt_bg;
+	unsigned int acttoact_bg, wrtord_bg, pre_all_rec;
+	unsigned int tccdl = picos_to_mclk(common_dimm->tccdl_ps);
+	unsigned int wr_lat = ((ddr->timing_cfg_2 & 0x00780000) >> 19) +
+			      ((ddr->timing_cfg_2 & 0x00040000) >> 14);
+
+	rwt_bg = cas_latency + 2 + 4 - wr_lat;
+	if (rwt_bg < tccdl)
+		rwt_bg = tccdl - rwt_bg;
+	else
+		rwt_bg = 0;
+
+	wrt_bg = wr_lat + 4 + 1 - cas_latency;
+	if (wrt_bg < tccdl)
+		wrt_bg = tccdl - wrt_bg;
+	else
+		wrt_bg = 0;
+
+	if (popts->burst_length == DDR_BL8) {
+		rrt_bg = tccdl - 4;
+		wwt_bg = tccdl - 4;
+	} else {
+		rrt_bg = tccdl - 2;
+		wwt_bg = tccdl - 4;
+	}
+
+	acttoact_bg = picos_to_mclk(common_dimm->trrdl_ps);
+	wrtord_bg = max(4, picos_to_mclk(7500));
+	pre_all_rec = 0;
+
+	ddr->timing_cfg_8 = (0
+			     | ((rwt_bg & 0xf) << 28)
+			     | ((wrt_bg & 0xf) << 24)
+			     | ((rrt_bg & 0xf) << 20)
+			     | ((wwt_bg & 0xf) << 16)
+			     | ((acttoact_bg & 0xf) << 12)
+			     | ((wrtord_bg & 0xf) << 8)
+			     | ((pre_all_rec & 0x1f) << 0)
+			    );
+
+	debug("FSLDDR: timing_cfg_8 = 0x%08x\n", ddr->timing_cfg_8);
+}
+
+static void set_timing_cfg_9(fsl_ddr_cfg_regs_t *ddr)
+{
+	ddr->timing_cfg_9 = 0;
+	debug("FSLDDR: timing_cfg_9 = 0x%08x\n", ddr->timing_cfg_9);
+}
+
+static void set_ddr_dq_mapping(fsl_ddr_cfg_regs_t *ddr,
+			       const dimm_params_t *dimm_params)
+{
+	ddr->dq_map_0 = ((dimm_params->dq_mapping[0] & 0x3F) << 26) |
+			((dimm_params->dq_mapping[1] & 0x3F) << 20) |
+			((dimm_params->dq_mapping[2] & 0x3F) << 14) |
+			((dimm_params->dq_mapping[3] & 0x3F) << 8) |
+			((dimm_params->dq_mapping[4] & 0x3F) << 2);
+
+	ddr->dq_map_1 = ((dimm_params->dq_mapping[5] & 0x3F) << 26) |
+			((dimm_params->dq_mapping[6] & 0x3F) << 20) |
+			((dimm_params->dq_mapping[7] & 0x3F) << 14) |
+			((dimm_params->dq_mapping[10] & 0x3F) << 8) |
+			((dimm_params->dq_mapping[11] & 0x3F) << 2);
+
+	ddr->dq_map_2 = ((dimm_params->dq_mapping[12] & 0x3F) << 26) |
+			((dimm_params->dq_mapping[13] & 0x3F) << 20) |
+			((dimm_params->dq_mapping[14] & 0x3F) << 14) |
+			((dimm_params->dq_mapping[15] & 0x3F) << 8) |
+			((dimm_params->dq_mapping[16] & 0x3F) << 2);
+
+	ddr->dq_map_3 = ((dimm_params->dq_mapping[17] & 0x3F) << 26) |
+			((dimm_params->dq_mapping[8] & 0x3F) << 20) |
+			((dimm_params->dq_mapping[9] & 0x3F) << 14) |
+			dimm_params->dq_mapping_ors;
+
+	debug("FSLDDR: dq_map_0 = 0x%08x\n", ddr->dq_map_0);
+	debug("FSLDDR: dq_map_1 = 0x%08x\n", ddr->dq_map_1);
+	debug("FSLDDR: dq_map_2 = 0x%08x\n", ddr->dq_map_2);
+	debug("FSLDDR: dq_map_3 = 0x%08x\n", ddr->dq_map_3);
+}
+static void set_ddr_sdram_cfg_3(fsl_ddr_cfg_regs_t *ddr,
+			       const memctl_options_t *popts)
+{
+	int rd_pre;
+
+	rd_pre = popts->quad_rank_present ? 1 : 0;
+
+	ddr->ddr_sdram_cfg_3 = (rd_pre & 0x1) << 16;
+
+	debug("FSLDDR: ddr_sdram_cfg_3 = 0x%08x\n", ddr->ddr_sdram_cfg_3);
+}
+#endif	/* CONFIG_SYS_FSL_DDR4 */
+
 /* DDR ZQ Calibration Control (DDR_ZQ_CNTL) */
 static void set_ddr_zq_cntl(fsl_ddr_cfg_regs_t *ddr, unsigned int zq_en)
 {
@@ -1310,11 +1930,21 @@  static void set_ddr_zq_cntl(fsl_ddr_cfg_regs_t *ddr, unsigned int zq_en)
 	unsigned int zqoper = 0;
 	/* Normal Operation Short Calibration Time (tZQCS) */
 	unsigned int zqcs = 0;
+#ifdef CONFIG_SYS_FSL_DDR4
+	unsigned int zqcs_init;
+#endif
 
 	if (zq_en) {
+#ifdef CONFIG_SYS_FSL_DDR4
+		zqinit = 10;	/* 1024 clocks */
+		zqoper = 9;	/* 512 clocks */
+		zqcs = 7;	/* 128 clocks */
+		zqcs_init = 5;	/* 1024 refresh sequences */
+#else
 		zqinit = 9;	/* 512 clocks */
 		zqoper = 8;	/* 256 clocks */
 		zqcs = 6;	/* 64 clocks */
+#endif
 	}
 
 	ddr->ddr_zq_cntl = (0
@@ -1322,6 +1952,9 @@  static void set_ddr_zq_cntl(fsl_ddr_cfg_regs_t *ddr, unsigned int zq_en)
 			    | ((zqinit & 0xF) << 24)
 			    | ((zqoper & 0xF) << 16)
 			    | ((zqcs & 0xF) << 8)
+#ifdef CONFIG_SYS_FSL_DDR4
+			    | ((zqcs_init & 0xF) << 0)
+#endif
 			    );
 	debug("FSLDDR: zq_cntl = 0x%08x\n", ddr->ddr_zq_cntl);
 }
@@ -1478,7 +2111,7 @@  compute_fsl_memctl_config_regs(const memctl_options_t *popts,
 	 */
 	cas_latency = (popts->cas_latency_override)
 		? popts->cas_latency_override_value
-		: common_dimm->lowest_common_SPD_caslat;
+		: common_dimm->lowest_common_spd_caslat;
 
 	additive_latency = (popts->additive_latency_override)
 		? popts->additive_latency_override_value
@@ -1639,6 +2272,10 @@  compute_fsl_memctl_config_regs(const memctl_options_t *popts,
 	set_ddr_sdram_mode(ddr, popts, common_dimm,
 				cas_latency, additive_latency, unq_mrs_en);
 	set_ddr_sdram_mode_2(ddr, popts, common_dimm, unq_mrs_en);
+#ifdef CONFIG_SYS_FSL_DDR4
+	set_ddr_sdram_mode_9(ddr, popts, common_dimm, unq_mrs_en);
+	set_ddr_sdram_mode_10(ddr, popts, common_dimm, unq_mrs_en);
+#endif
 	set_ddr_sdram_interval(ddr, popts, common_dimm);
 	set_ddr_data_init(ddr);
 	set_ddr_sdram_clk_cntl(ddr, popts);
@@ -1646,6 +2283,14 @@  compute_fsl_memctl_config_regs(const memctl_options_t *popts,
 	set_ddr_init_ext_addr(ddr);
 	set_timing_cfg_4(ddr, popts);
 	set_timing_cfg_5(ddr, cas_latency);
+#ifdef CONFIG_SYS_FSL_DDR4
+	set_ddr_sdram_cfg_3(ddr, popts);
+	set_timing_cfg_6(ddr);
+	set_timing_cfg_7(ddr, common_dimm);
+	set_timing_cfg_8(ddr, popts, common_dimm, cas_latency);
+	set_timing_cfg_9(ddr);
+	set_ddr_dq_mapping(ddr, dimm_params);
+#endif
 
 	set_ddr_zq_cntl(ddr, zq_en);
 	set_ddr_wrlvl_cntl(ddr, wrlvl_en, popts);
diff --git a/drivers/ddr/fsl/ddr4_dimm_params.c b/drivers/ddr/fsl/ddr4_dimm_params.c
new file mode 100644
index 0000000..4745b7f
--- /dev/null
+++ b/drivers/ddr/fsl/ddr4_dimm_params.c
@@ -0,0 +1,300 @@ 
+/*
+ * Copyright 2014 Freescale Semiconductor, Inc.
+ *
+ * calculate the organization and timing parameter
+ * from ddr3 spd, please refer to the spec
+ * JEDEC standard No.21-C 4_01_02_12R23A.pdf
+ *
+ *
+ */
+
+#include <common.h>
+#include <fsl_ddr_sdram.h>
+
+#include <fsl_ddr.h>
+
+/*
+ * Calculate the Density of each Physical Rank.
+ * Returned size is in bytes.
+ *
+ * Total DIMM size =
+ * sdram capacity(bit) / 8 * primary bus width / sdram width
+ *                     * Logical Ranks per DIMM
+ *
+ * where: sdram capacity  = spd byte4[3:0]
+ *        primary bus width = spd byte13[2:0]
+ *        sdram width = spd byte12[2:0]
+ *        Logical Ranks per DIMM = spd byte12[5:3] for SDP, DDP, QDP
+ *                                 spd byte12{5:3] * spd byte6[6:4] for 3DS
+ *
+ * To simplify each rank size = total DIMM size / Number of Package Ranks
+ * where Number of Package Ranks = spd byte12[5:3]
+ *
+ * SPD byte4 - sdram density and banks
+ *	bit[3:0]	size(bit)	size(byte)
+ *	0000		256Mb		32MB
+ *	0001		512Mb		64MB
+ *	0010		1Gb		128MB
+ *	0011		2Gb		256MB
+ *	0100		4Gb		512MB
+ *	0101		8Gb		1GB
+ *	0110		16Gb		2GB
+ *      0111		32Gb		4GB
+ *
+ * SPD byte13 - module memory bus width
+ *	bit[2:0]	primary bus width
+ *	000		8bits
+ *	001		16bits
+ *	010		32bits
+ *	011		64bits
+ *
+ * SPD byte12 - module organization
+ *	bit[2:0]	sdram device width
+ *	000		4bits
+ *	001		8bits
+ *	010		16bits
+ *	011		32bits
+ *
+ * SPD byte12 - module organization
+ *	bit[5:3]	number of package ranks per DIMM
+ *	000		1
+ *	001		2
+ *	010		3
+ *	011		4
+ *
+ * SPD byte6 - SDRAM package type
+ *	bit[6:4]	Die count
+ *	000		1
+ *	001		2
+ *	010		3
+ *	011		4
+ *	100		5
+ *	101		6
+ *	110		7
+ *	111		8
+ *
+ * SPD byte6 - SRAM package type
+ *	bit[1:0]	Signal loading
+ *	00		Not specified
+ *	01		Multi load stack
+ *	10		Sigle load stack (3DS)
+ *	11		Reserved
+ */
+static unsigned long long
+compute_ranksize(const struct ddr4_spd_eeprom_s *spd)
+{
+	unsigned long long bsize;
+
+	int nbit_sdram_cap_bsize = 0;
+	int nbit_primary_bus_width = 0;
+	int nbit_sdram_width = 0;
+	int die_count = 0;
+	bool package_3ds;
+
+	if ((spd->density_banks & 0xf) <= 7)
+		nbit_sdram_cap_bsize = (spd->density_banks & 0xf) + 28;
+	if ((spd->bus_width & 0x7) < 4)
+		nbit_primary_bus_width = (spd->bus_width & 0x7) + 3;
+	if ((spd->organization & 0x7) < 4)
+		nbit_sdram_width = (spd->organization & 0x7) + 2;
+	package_3ds = (spd->package_type & 0x3) == 0x2;
+	if (package_3ds)
+		die_count = (spd->package_type >> 4) & 0x7;
+
+	bsize = 1ULL << (nbit_sdram_cap_bsize - 3 +
+			 nbit_primary_bus_width - nbit_sdram_width +
+			 die_count);
+
+	debug("DDR: DDR III rank density = 0x%16llx\n", bsize);
+
+	return bsize;
+}
+
+#define spd_to_ps(mtb, ftb)	\
+	(mtb * pdimm->mtb_ps + (ftb * pdimm->ftb_10th_ps) / 10)
+/*
+ * ddr_compute_dimm_parameters for DDR3 SPD
+ *
+ * Compute DIMM parameters based upon the SPD information in spd.
+ * Writes the results to the dimm_params_t structure pointed by pdimm.
+ *
+ */
+unsigned int
+ddr_compute_dimm_parameters(const generic_spd_eeprom_t *spd,
+			    dimm_params_t *pdimm,
+			    unsigned int dimm_number)
+{
+	unsigned int retval;
+	int i;
+
+	if (spd->mem_type) {
+		if (spd->mem_type != SPD_MEMTYPE_DDR4) {
+			printf("DIMM %u: is not a DDR4 SPD.\n", dimm_number);
+			return 1;
+		}
+	} else {
+		memset(pdimm, 0, sizeof(dimm_params_t));
+		return 1;
+	}
+
+	retval = ddr4_spd_check(spd);
+	if (retval) {
+		printf("DIMM %u: failed checksum\n", dimm_number);
+		return 2;
+	}
+
+	/*
+	 * The part name in ASCII in the SPD EEPROM is not null terminated.
+	 * Guarantee null termination here by presetting all bytes to 0
+	 * and copying the part name in ASCII from the SPD onto it
+	 */
+	memset(pdimm->mpart, 0, sizeof(pdimm->mpart));
+	if ((spd->info_size_crc & 0xF) > 2)
+		memcpy(pdimm->mpart, spd->mpart, sizeof(pdimm->mpart) - 1);
+
+	/* DIMM organization parameters */
+	pdimm->n_ranks = ((spd->organization >> 3) & 0x7) + 1;
+	pdimm->rank_density = compute_ranksize(spd);
+	pdimm->capacity = pdimm->n_ranks * pdimm->rank_density;
+	pdimm->primary_sdram_width = 1 << (3 + (spd->bus_width & 0x7));
+	if ((spd->bus_width >> 3) & 0x3)
+		pdimm->ec_sdram_width = 8;
+	else
+		pdimm->ec_sdram_width = 0;
+	pdimm->data_width = pdimm->primary_sdram_width
+			  + pdimm->ec_sdram_width;
+	pdimm->device_width = 1 << ((spd->organization & 0x7) + 2);
+
+	/* These are the types defined by the JEDEC DDR3 SPD spec */
+	pdimm->mirrored_dimm = 0;
+	pdimm->registered_dimm = 0;
+	switch (spd->module_type & DDR3_SPD_MODULETYPE_MASK) {
+	case DDR3_SPD_MODULETYPE_RDIMM:
+		/* Registered/buffered DIMMs */
+		pdimm->registered_dimm = 1;
+		break;
+
+	case DDR3_SPD_MODULETYPE_UDIMM:
+	case DDR3_SPD_MODULETYPE_SO_DIMM:
+		/* Unbuffered DIMMs */
+		if (spd->mod_section.unbuffered.addr_mapping & 0x1)
+			pdimm->mirrored_dimm = 1;
+		break;
+
+	default:
+		printf("unknown module_type 0x%02X\n", spd->module_type);
+		return 1;
+	}
+
+	/* SDRAM device parameters */
+	pdimm->n_row_addr = ((spd->addressing >> 3) & 0x7) + 12;
+	pdimm->n_col_addr = (spd->addressing & 0x7) + 9;
+	pdimm->bank_addr_bits = (spd->density_banks >> 4) & 0x3;
+	pdimm->bank_group_bits = (spd->density_banks >> 6) & 0x3;
+
+	/*
+	 * The SPD spec has not the ECC bit,
+	 * We consider the DIMM as ECC capability
+	 * when the extension bus exist
+	 */
+	if (pdimm->ec_sdram_width)
+		pdimm->edc_config = 0x02;
+	else
+		pdimm->edc_config = 0x00;
+
+	/*
+	 * The SPD spec has not the burst length byte
+	 * but DDR4 spec has nature BL8 and BC4,
+	 * BL8 -bit3, BC4 -bit2
+	 */
+	pdimm->burst_lengths_bitmask = 0x0c;
+	pdimm->row_density = __ilog2(pdimm->rank_density);
+
+	/* MTB - medium timebase
+	 * The MTB in the SPD spec is 125ps,
+	 *
+	 * FTB - fine timebase
+	 * use 1/10th of ps as our unit to avoid floating point
+	 * eg, 10 for 1ps, 25 for 2.5ps, 50 for 5ps
+	 */
+	if ((spd->timebases & 0xf) == 0x0) {
+		pdimm->mtb_ps = 125;
+		pdimm->ftb_10th_ps = 10;
+
+	} else {
+		printf("Unknown Timebases\n");
+	}
+
+	/* sdram minimum cycle time */
+	pdimm->tckmin_x_ps = spd_to_ps(spd->tck_min, spd->fine_tck_min);
+
+	/* sdram max cycle time */
+	pdimm->tckmax_ps = spd_to_ps(spd->tck_max, spd->fine_tck_max);
+
+	/*
+	 * CAS latency supported
+	 * bit0 - CL7
+	 * bit4 - CL11
+	 * bit8 - CL15
+	 * bit12- CL19
+	 * bit16- CL23
+	 */
+	pdimm->caslat_x  = (spd->caslat_b1 << 7)	|
+			   (spd->caslat_b2 << 15)	|
+			   (spd->caslat_b3 << 23);
+
+	BUG_ON(spd->caslat_b4 != 0);
+
+	/*
+	 * min CAS latency time
+	 */
+	pdimm->taa_ps = spd_to_ps(spd->taa_min, spd->fine_taa_min);
+
+	/*
+	 * min RAS to CAS delay time
+	 */
+	pdimm->trcd_ps = spd_to_ps(spd->trcd_min, spd->fine_trcd_min);
+
+	/*
+	 * Min Row Precharge Delay Time
+	 */
+	pdimm->trp_ps = spd_to_ps(spd->trp_min, spd->fine_trp_min);
+
+	/* min active to precharge delay time */
+	pdimm->tras_ps = (((spd->tras_trc_ext & 0xf) << 8) +
+			  spd->tras_min_lsb) * pdimm->mtb_ps;
+
+	/* min active to actice/refresh delay time */
+	pdimm->trc_ps = spd_to_ps((((spd->tras_trc_ext & 0xf0) << 4) +
+				   spd->trc_min_lsb), spd->fine_trc_min);
+	/* Min Refresh Recovery Delay Time */
+	pdimm->trfc1_ps = ((spd->trfc1_min_msb << 8) | (spd->trfc1_min_lsb)) *
+		       pdimm->mtb_ps;
+	pdimm->trfc2_ps = ((spd->trfc2_min_msb << 8) | (spd->trfc2_min_lsb)) *
+		       pdimm->mtb_ps;
+	pdimm->trfc4_ps = ((spd->trfc4_min_msb << 8) | (spd->trfc4_min_lsb)) *
+			pdimm->mtb_ps;
+	/* min four active window delay time */
+	pdimm->tfaw_ps = (((spd->tfaw_msb & 0xf) << 8) | spd->tfaw_min) *
+			pdimm->mtb_ps;
+
+	/* min row active to row active delay time, different bank group */
+	pdimm->trrds_ps = spd_to_ps(spd->trrds_min, spd->fine_trrds_min);
+	/* min row active to row active delay time, same bank group */
+	pdimm->trrdl_ps = spd_to_ps(spd->trrdl_min, spd->fine_trrdl_min);
+	/* min CAS to CAS Delay Time (tCCD_Lmin), same bank group */
+	pdimm->tccdl_ps = spd_to_ps(spd->tccdl_min, spd->fine_tccdl_min);
+
+	/*
+	 * Average periodic refresh interval
+	 * tREFI = 7.8 us at normal temperature range
+	 */
+	pdimm->refresh_rate_ps = 7800000;
+
+	for (i = 0; i < 18; i++)
+		pdimm->dq_mapping[i] = spd->mapping[i];
+
+	pdimm->dq_mapping_ors = ((spd->mapping[0] >> 6) & 0x3) == 0 ? 1 : 0;
+
+	return 0;
+}
diff --git a/drivers/ddr/fsl/arm_ddr_gen3.c b/drivers/ddr/fsl/fsl_ddr_gen4.c
similarity index 81%
copy from drivers/ddr/fsl/arm_ddr_gen3.c
copy to drivers/ddr/fsl/fsl_ddr_gen4.c
index d4ed9ae..7cd878a 100644
--- a/drivers/ddr/fsl/arm_ddr_gen3.c
+++ b/drivers/ddr/fsl/fsl_ddr_gen4.c
@@ -1,23 +1,19 @@ 
 /*
- * Copyright 2013 Freescale Semiconductor, Inc.
+ * Copyright 2014 Freescale Semiconductor, Inc.
  *
  * SPDX-License-Identifier:	GPL-2.0+
- *
- * Derived from mpc85xx_ddr_gen3.c, removed all workarounds
  */
 
 #include <common.h>
 #include <asm/io.h>
 #include <fsl_ddr_sdram.h>
 #include <asm/processor.h>
-#include <fsl_immap.h>
 #include <fsl_ddr.h>
 
 #if (CONFIG_CHIP_SELECTS_PER_CTRL > 4)
 #error Invalid setting for CONFIG_CHIP_SELECTS_PER_CTRL
 #endif
 
-
 /*
  * regs has the to-be-set values for DDR controller registers
  * ctrl_num is the DDR controller number
@@ -65,6 +61,9 @@  void fsl_ddr_set_memctl_regs(const fsl_ddr_cfg_regs_t *regs,
 
 	if (regs->ddr_eor)
 		ddr_out32(&ddr->eor, regs->ddr_eor);
+
+	ddr_out32(&ddr->sdram_clk_cntl, regs->ddr_sdram_clk_cntl);
+
 	for (i = 0; i < CONFIG_CHIP_SELECTS_PER_CTRL; i++) {
 		if (i == 0) {
 			ddr_out32(&ddr->cs0_bnds, regs->cs[i].bnds);
@@ -92,7 +91,19 @@  void fsl_ddr_set_memctl_regs(const fsl_ddr_cfg_regs_t *regs,
 	ddr_out32(&ddr->timing_cfg_0, regs->timing_cfg_0);
 	ddr_out32(&ddr->timing_cfg_1, regs->timing_cfg_1);
 	ddr_out32(&ddr->timing_cfg_2, regs->timing_cfg_2);
+	ddr_out32(&ddr->timing_cfg_4, regs->timing_cfg_4);
+	ddr_out32(&ddr->timing_cfg_5, regs->timing_cfg_5);
+	ddr_out32(&ddr->timing_cfg_6, regs->timing_cfg_6);
+	ddr_out32(&ddr->timing_cfg_7, regs->timing_cfg_7);
+	ddr_out32(&ddr->timing_cfg_8, regs->timing_cfg_8);
+	ddr_out32(&ddr->timing_cfg_9, regs->timing_cfg_9);
+	ddr_out32(&ddr->ddr_zq_cntl, regs->ddr_zq_cntl);
+	ddr_out32(&ddr->dq_map_0, regs->dq_map_0);
+	ddr_out32(&ddr->dq_map_1, regs->dq_map_1);
+	ddr_out32(&ddr->dq_map_2, regs->dq_map_2);
+	ddr_out32(&ddr->dq_map_3, regs->dq_map_3);
 	ddr_out32(&ddr->sdram_cfg_2, regs->ddr_sdram_cfg_2);
+	ddr_out32(&ddr->sdram_cfg_3, regs->ddr_sdram_cfg_3);
 	ddr_out32(&ddr->sdram_mode, regs->ddr_sdram_mode);
 	ddr_out32(&ddr->sdram_mode_2, regs->ddr_sdram_mode_2);
 	ddr_out32(&ddr->sdram_mode_3, regs->ddr_sdram_mode_3);
@@ -101,16 +112,19 @@  void fsl_ddr_set_memctl_regs(const fsl_ddr_cfg_regs_t *regs,
 	ddr_out32(&ddr->sdram_mode_6, regs->ddr_sdram_mode_6);
 	ddr_out32(&ddr->sdram_mode_7, regs->ddr_sdram_mode_7);
 	ddr_out32(&ddr->sdram_mode_8, regs->ddr_sdram_mode_8);
+	ddr_out32(&ddr->sdram_mode_9, regs->ddr_sdram_mode_9);
+	ddr_out32(&ddr->sdram_mode_10, regs->ddr_sdram_mode_10);
+	ddr_out32(&ddr->sdram_mode_11, regs->ddr_sdram_mode_11);
+	ddr_out32(&ddr->sdram_mode_12, regs->ddr_sdram_mode_12);
+	ddr_out32(&ddr->sdram_mode_13, regs->ddr_sdram_mode_13);
+	ddr_out32(&ddr->sdram_mode_14, regs->ddr_sdram_mode_14);
+	ddr_out32(&ddr->sdram_mode_15, regs->ddr_sdram_mode_15);
+	ddr_out32(&ddr->sdram_mode_16, regs->ddr_sdram_mode_16);
 	ddr_out32(&ddr->sdram_md_cntl, regs->ddr_sdram_md_cntl);
 	ddr_out32(&ddr->sdram_interval, regs->ddr_sdram_interval);
 	ddr_out32(&ddr->sdram_data_init, regs->ddr_data_init);
-	ddr_out32(&ddr->sdram_clk_cntl, regs->ddr_sdram_clk_cntl);
 	ddr_out32(&ddr->init_addr, regs->ddr_init_addr);
 	ddr_out32(&ddr->init_ext_addr, regs->ddr_init_ext_addr);
-
-	ddr_out32(&ddr->timing_cfg_4, regs->timing_cfg_4);
-	ddr_out32(&ddr->timing_cfg_5, regs->timing_cfg_5);
-	ddr_out32(&ddr->ddr_zq_cntl, regs->ddr_zq_cntl);
 	ddr_out32(&ddr->ddr_wrlvl_cntl, regs->ddr_wrlvl_cntl);
 #ifndef CONFIG_SYS_FSL_DDR_EMU
 	/*
@@ -127,14 +141,18 @@  void fsl_ddr_set_memctl_regs(const fsl_ddr_cfg_regs_t *regs,
 	ddr_out32(&ddr->ddr_sr_cntr, regs->ddr_sr_cntr);
 	ddr_out32(&ddr->ddr_sdram_rcw_1, regs->ddr_sdram_rcw_1);
 	ddr_out32(&ddr->ddr_sdram_rcw_2, regs->ddr_sdram_rcw_2);
+	ddr_out32(&ddr->ddr_sdram_rcw_3, regs->ddr_sdram_rcw_3);
+	ddr_out32(&ddr->ddr_sdram_rcw_4, regs->ddr_sdram_rcw_4);
+	ddr_out32(&ddr->ddr_sdram_rcw_5, regs->ddr_sdram_rcw_5);
+	ddr_out32(&ddr->ddr_sdram_rcw_6, regs->ddr_sdram_rcw_6);
 	ddr_out32(&ddr->ddr_cdr1, regs->ddr_cdr1);
 	ddr_out32(&ddr->ddr_cdr2, regs->ddr_cdr2);
 	ddr_out32(&ddr->err_disable, regs->err_disable);
 	ddr_out32(&ddr->err_int_en, regs->err_int_en);
 	for (i = 0; i < 32; i++) {
 		if (regs->debug[i]) {
-			debug("Write to debug_%d as %08x\n", i + 1,
-			      regs->debug[i]);
+			debug("Write to debug_%d as %08x\n",
+			      i+1, regs->debug[i]);
 			ddr_out32(&ddr->debug[i], regs->debug[i]);
 		}
 	}
@@ -165,12 +183,12 @@  step2:
 	 * we choose the max, that is 500 us for all of case.
 	 */
 	udelay(500);
-	asm volatile("dsb sy;isb");
+	asm volatile("sync;isync");
 
 	/* Let the controller go */
 	temp_sdram_cfg = ddr_in32(&ddr->sdram_cfg) & ~SDRAM_CFG_BI;
 	ddr_out32(&ddr->sdram_cfg, temp_sdram_cfg | SDRAM_CFG_MEM_EN);
-	asm volatile("dsb sy;isb");
+	asm volatile("sync;isync");
 
 	total_gb_size_per_controller = 0;
 	for (i = 0; i < CONFIG_CHIP_SELECTS_PER_CTRL; i++) {
@@ -179,14 +197,15 @@  step2:
 		total_gb_size_per_controller += 1 << (
 			((regs->cs[i].config >> 14) & 0x3) + 2 +
 			((regs->cs[i].config >> 8) & 0x7) + 12 +
+			((regs->cs[i].config >> 4) & 0x3) + 0 +
 			((regs->cs[i].config >> 0) & 0x7) + 8 +
 			3 - ((regs->ddr_sdram_cfg >> 19) & 0x3) -
 			26);			/* minus 26 (count of 64M) */
 	}
-	if (regs->cs[0].config & 0x20000000) {
-		/* 2-way interleaving */
+	if (fsl_ddr_get_intl3r() & 0x80000000)	/* 3-way interleaving */
+		total_gb_size_per_controller *= 3;
+	else if (regs->cs[0].config & 0x20000000) /* 2-way interleaving */
 		total_gb_size_per_controller <<= 1;
-	}
 	/*
 	 * total memory / bus width = transactions needed
 	 * transactions needed / data rate = seconds
@@ -197,7 +216,7 @@  step2:
 	bus_width = 3 - ((ddr->sdram_cfg & SDRAM_CFG_DBW_MASK)
 			>> SDRAM_CFG_DBW_SHIFT);
 	timeout = ((total_gb_size_per_controller << (6 - bus_width)) * 100 /
-		(get_ddr_freq(0) >> 20)) << 1;
+		(get_ddr_freq(0) >> 20)) << 2;
 	total_gb_size_per_controller >>= 4;	/* shift down to gb size */
 	debug("total %d GB\n", total_gb_size_per_controller);
 	debug("Need to wait up to %d * 10ms\n", timeout);
@@ -211,4 +230,5 @@  step2:
 
 	if (timeout <= 0)
 		printf("Waiting for D_INIT timeout. Memory may not work.\n");
+
 }
diff --git a/drivers/ddr/fsl/interactive.c b/drivers/ddr/fsl/interactive.c
index ebf3ed6..cfe1e1f 100644
--- a/drivers/ddr/fsl/interactive.c
+++ b/drivers/ddr/fsl/interactive.c
@@ -1,5 +1,5 @@ 
 /*
- * Copyright 2010-2012 Freescale Semiconductor, Inc.
+ * Copyright 2010-2014 Freescale Semiconductor, Inc.
  *
  * SPDX-License-Identifier:	GPL-2.0+
  */
@@ -153,25 +153,38 @@  static void lowest_common_dimm_parameters_edit(fsl_ddr_info_t *pinfo,
 	static const struct options_string options[] = {
 		COMMON_TIMING(tckmin_x_ps),
 		COMMON_TIMING(tckmax_ps),
-		COMMON_TIMING(tckmax_max_ps),
+		COMMON_TIMING(taamin_ps),
 		COMMON_TIMING(trcd_ps),
 		COMMON_TIMING(trp_ps),
 		COMMON_TIMING(tras_ps),
-		COMMON_TIMING(twr_ps),
+
+#ifdef CONFIG_SYS_FSL_DDR4
+		COMMON_TIMING(trfc1_ps),
+		COMMON_TIMING(trfc2_ps),
+		COMMON_TIMING(trfc4_ps),
+		COMMON_TIMING(trrds_ps),
+		COMMON_TIMING(trrdl_ps),
+		COMMON_TIMING(tccdl_ps),
+#else
 		COMMON_TIMING(twtr_ps),
 		COMMON_TIMING(trfc_ps),
 		COMMON_TIMING(trrd_ps),
+		COMMON_TIMING(trtp_ps),
+#endif
+		COMMON_TIMING(twr_ps),
 		COMMON_TIMING(trc_ps),
 		COMMON_TIMING(refresh_rate_ps),
+		COMMON_TIMING(extended_op_srt),
+#if defined(CONFIG_SYS_FSL_DDR1) || defined(CONFIG_SYS_FSL_DDR2)
 		COMMON_TIMING(tis_ps),
 		COMMON_TIMING(tih_ps),
 		COMMON_TIMING(tds_ps),
 		COMMON_TIMING(tdh_ps),
-		COMMON_TIMING(trtp_ps),
 		COMMON_TIMING(tdqsq_max_ps),
 		COMMON_TIMING(tqhs_ps),
+#endif
 		COMMON_TIMING(ndimms_present),
-		COMMON_TIMING(lowest_common_SPD_caslat),
+		COMMON_TIMING(lowest_common_spd_caslat),
 		COMMON_TIMING(highest_common_derated_caslat),
 		COMMON_TIMING(additive_latency),
 		COMMON_TIMING(all_dimms_burst_lengths_bitmask),
@@ -211,7 +224,12 @@  static void fsl_ddr_dimm_parameters_edit(fsl_ddr_info_t *pinfo,
 		DIMM_PARM(n_row_addr),
 		DIMM_PARM(n_col_addr),
 		DIMM_PARM(edc_config),
+#ifdef CONFIG_SYS_FSL_DDR4
+		DIMM_PARM(bank_addr_bits),
+		DIMM_PARM(bank_group_bits),
+#else
 		DIMM_PARM(n_banks_per_sdram_device),
+#endif
 		DIMM_PARM(burst_lengths_bitmask),
 		DIMM_PARM(row_density),
 
@@ -229,20 +247,32 @@  static void fsl_ddr_dimm_parameters_edit(fsl_ddr_info_t *pinfo,
 		DIMM_PARM(trcd_ps),
 		DIMM_PARM(trp_ps),
 		DIMM_PARM(tras_ps),
+#ifdef CONFIG_SYS_FSL_DDR4
+		DIMM_PARM(trfc1_ps),
+		DIMM_PARM(trfc2_ps),
+		DIMM_PARM(trfc4_ps),
+		DIMM_PARM(trrds_ps),
+		DIMM_PARM(trrdl_ps),
+		DIMM_PARM(tccdl_ps),
+#else
 		DIMM_PARM(twr_ps),
 		DIMM_PARM(twtr_ps),
 		DIMM_PARM(trfc_ps),
 		DIMM_PARM(trrd_ps),
+		DIMM_PARM(trtp_ps),
+#endif
 		DIMM_PARM(trc_ps),
 		DIMM_PARM(refresh_rate_ps),
+		DIMM_PARM(extended_op_srt),
 
+#if defined(CONFIG_SYS_FSL_DDR1) || defined(CONFIG_SYS_FSL_DDR2)
 		DIMM_PARM(tis_ps),
 		DIMM_PARM(tih_ps),
 		DIMM_PARM(tds_ps),
 		DIMM_PARM(tdh_ps),
-		DIMM_PARM(trtp_ps),
 		DIMM_PARM(tdqsq_max_ps),
 		DIMM_PARM(tqhs_ps),
+#endif
 
 		DIMM_PARM(rank_density),
 		DIMM_PARM(capacity),
@@ -270,7 +300,12 @@  static void print_dimm_parameters(const dimm_params_t *pdimm)
 		DIMM_PARM(n_row_addr),
 		DIMM_PARM(n_col_addr),
 		DIMM_PARM(edc_config),
+#ifdef CONFIG_SYS_FSL_DDR4
+		DIMM_PARM(bank_addr_bits),
+		DIMM_PARM(bank_group_bits),
+#else
 		DIMM_PARM(n_banks_per_sdram_device),
+#endif
 
 		DIMM_PARM(tckmin_x_ps),
 		DIMM_PARM(tckmin_x_minus_1_ps),
@@ -286,20 +321,31 @@  static void print_dimm_parameters(const dimm_params_t *pdimm)
 		DIMM_PARM(trcd_ps),
 		DIMM_PARM(trp_ps),
 		DIMM_PARM(tras_ps),
+#ifdef CONFIG_SYS_FSL_DDR4
+		DIMM_PARM(trfc1_ps),
+		DIMM_PARM(trfc2_ps),
+		DIMM_PARM(trfc4_ps),
+		DIMM_PARM(trrds_ps),
+		DIMM_PARM(trrdl_ps),
+		DIMM_PARM(tccdl_ps),
+#else
 		DIMM_PARM(twr_ps),
 		DIMM_PARM(twtr_ps),
 		DIMM_PARM(trfc_ps),
 		DIMM_PARM(trrd_ps),
+		DIMM_PARM(trtp_ps),
+#endif
 		DIMM_PARM(trc_ps),
 		DIMM_PARM(refresh_rate_ps),
 
+#if defined(CONFIG_SYS_FSL_DDR1) || defined(CONFIG_SYS_FSL_DDR2)
 		DIMM_PARM(tis_ps),
 		DIMM_PARM(tih_ps),
 		DIMM_PARM(tds_ps),
 		DIMM_PARM(tdh_ps),
-		DIMM_PARM(trtp_ps),
 		DIMM_PARM(tdqsq_max_ps),
 		DIMM_PARM(tqhs_ps),
+#endif
 	};
 	static const unsigned int n_opts = ARRAY_SIZE(options);
 
@@ -326,23 +372,36 @@  static void print_lowest_common_dimm_parameters(
 		const common_timing_params_t *plcd_dimm_params)
 {
 	static const struct options_string options[] = {
-		COMMON_TIMING(tckmax_max_ps),
+		COMMON_TIMING(taamin_ps),
 		COMMON_TIMING(trcd_ps),
 		COMMON_TIMING(trp_ps),
 		COMMON_TIMING(tras_ps),
-		COMMON_TIMING(twr_ps),
+#ifdef CONFIG_SYS_FSL_DDR4
+		COMMON_TIMING(trfc1_ps),
+		COMMON_TIMING(trfc2_ps),
+		COMMON_TIMING(trfc4_ps),
+		COMMON_TIMING(trrds_ps),
+		COMMON_TIMING(trrdl_ps),
+		COMMON_TIMING(tccdl_ps),
+#else
 		COMMON_TIMING(twtr_ps),
 		COMMON_TIMING(trfc_ps),
 		COMMON_TIMING(trrd_ps),
+		COMMON_TIMING(trtp_ps),
+#endif
+		COMMON_TIMING(twr_ps),
 		COMMON_TIMING(trc_ps),
 		COMMON_TIMING(refresh_rate_ps),
+		COMMON_TIMING(extended_op_srt),
+#if defined(CONFIG_SYS_FSL_DDR1) || defined(CONFIG_SYS_FSL_DDR2)
 		COMMON_TIMING(tis_ps),
+		COMMON_TIMING(tih_ps),
 		COMMON_TIMING(tds_ps),
 		COMMON_TIMING(tdh_ps),
-		COMMON_TIMING(trtp_ps),
 		COMMON_TIMING(tdqsq_max_ps),
 		COMMON_TIMING(tqhs_ps),
-		COMMON_TIMING(lowest_common_SPD_caslat),
+#endif
+		COMMON_TIMING(lowest_common_spd_caslat),
 		COMMON_TIMING(highest_common_derated_caslat),
 		COMMON_TIMING(additive_latency),
 		COMMON_TIMING(ndimms_present),
@@ -460,6 +519,9 @@  static void fsl_ddr_options_edit(fsl_ddr_info_t *pinfo,
 		CTRL_OPTIONS(tfaw_window_four_activates_ps),
 		CTRL_OPTIONS(trwt_override),
 		CTRL_OPTIONS(trwt),
+		CTRL_OPTIONS(rtt_override),
+		CTRL_OPTIONS(rtt_override_value),
+		CTRL_OPTIONS(rtt_wr_override_value),
 	};
 
 	static const unsigned int n_opts = ARRAY_SIZE(options);
@@ -505,6 +567,7 @@  static void print_fsl_memctl_config_regs(const fsl_ddr_cfg_regs_t *ddr)
 		CFG_REGS(timing_cfg_2),
 		CFG_REGS(ddr_sdram_cfg),
 		CFG_REGS(ddr_sdram_cfg_2),
+		CFG_REGS(ddr_sdram_cfg_3),
 		CFG_REGS(ddr_sdram_mode),
 		CFG_REGS(ddr_sdram_mode_2),
 		CFG_REGS(ddr_sdram_mode_3),
@@ -513,6 +576,16 @@  static void print_fsl_memctl_config_regs(const fsl_ddr_cfg_regs_t *ddr)
 		CFG_REGS(ddr_sdram_mode_6),
 		CFG_REGS(ddr_sdram_mode_7),
 		CFG_REGS(ddr_sdram_mode_8),
+#ifdef CONFIG_SYS_FSL_DDR4
+		CFG_REGS(ddr_sdram_mode_9),
+		CFG_REGS(ddr_sdram_mode_10),
+		CFG_REGS(ddr_sdram_mode_11),
+		CFG_REGS(ddr_sdram_mode_12),
+		CFG_REGS(ddr_sdram_mode_13),
+		CFG_REGS(ddr_sdram_mode_14),
+		CFG_REGS(ddr_sdram_mode_15),
+		CFG_REGS(ddr_sdram_mode_16),
+#endif
 		CFG_REGS(ddr_sdram_interval),
 		CFG_REGS(ddr_data_init),
 		CFG_REGS(ddr_sdram_clk_cntl),
@@ -520,6 +593,12 @@  static void print_fsl_memctl_config_regs(const fsl_ddr_cfg_regs_t *ddr)
 		CFG_REGS(ddr_init_ext_addr),
 		CFG_REGS(timing_cfg_4),
 		CFG_REGS(timing_cfg_5),
+#ifdef CONFIG_SYS_FSL_DDR4
+		CFG_REGS(timing_cfg_6),
+		CFG_REGS(timing_cfg_7),
+		CFG_REGS(timing_cfg_8),
+		CFG_REGS(timing_cfg_9),
+#endif
 		CFG_REGS(ddr_zq_cntl),
 		CFG_REGS(ddr_wrlvl_cntl),
 		CFG_REGS(ddr_wrlvl_cntl_2),
@@ -529,6 +608,10 @@  static void print_fsl_memctl_config_regs(const fsl_ddr_cfg_regs_t *ddr)
 		CFG_REGS(ddr_sdram_rcw_2),
 		CFG_REGS(ddr_cdr1),
 		CFG_REGS(ddr_cdr2),
+		CFG_REGS(dq_map_0),
+		CFG_REGS(dq_map_1),
+		CFG_REGS(dq_map_2),
+		CFG_REGS(dq_map_3),
 		CFG_REGS(err_disable),
 		CFG_REGS(err_int_en),
 		CFG_REGS(ddr_eor),
@@ -574,6 +657,7 @@  static void fsl_ddr_regs_edit(fsl_ddr_info_t *pinfo,
 		CFG_REGS(timing_cfg_2),
 		CFG_REGS(ddr_sdram_cfg),
 		CFG_REGS(ddr_sdram_cfg_2),
+		CFG_REGS(ddr_sdram_cfg_3),
 		CFG_REGS(ddr_sdram_mode),
 		CFG_REGS(ddr_sdram_mode_2),
 		CFG_REGS(ddr_sdram_mode_3),
@@ -582,6 +666,16 @@  static void fsl_ddr_regs_edit(fsl_ddr_info_t *pinfo,
 		CFG_REGS(ddr_sdram_mode_6),
 		CFG_REGS(ddr_sdram_mode_7),
 		CFG_REGS(ddr_sdram_mode_8),
+#ifdef CONFIG_SYS_FSL_DDR4
+		CFG_REGS(ddr_sdram_mode_9),
+		CFG_REGS(ddr_sdram_mode_10),
+		CFG_REGS(ddr_sdram_mode_11),
+		CFG_REGS(ddr_sdram_mode_12),
+		CFG_REGS(ddr_sdram_mode_13),
+		CFG_REGS(ddr_sdram_mode_14),
+		CFG_REGS(ddr_sdram_mode_15),
+		CFG_REGS(ddr_sdram_mode_16),
+#endif
 		CFG_REGS(ddr_sdram_interval),
 		CFG_REGS(ddr_data_init),
 		CFG_REGS(ddr_sdram_clk_cntl),
@@ -589,6 +683,12 @@  static void fsl_ddr_regs_edit(fsl_ddr_info_t *pinfo,
 		CFG_REGS(ddr_init_ext_addr),
 		CFG_REGS(timing_cfg_4),
 		CFG_REGS(timing_cfg_5),
+#ifdef CONFIG_SYS_FSL_DDR4
+		CFG_REGS(timing_cfg_6),
+		CFG_REGS(timing_cfg_7),
+		CFG_REGS(timing_cfg_8),
+		CFG_REGS(timing_cfg_9),
+#endif
 		CFG_REGS(ddr_zq_cntl),
 		CFG_REGS(ddr_wrlvl_cntl),
 		CFG_REGS(ddr_wrlvl_cntl_2),
@@ -598,6 +698,10 @@  static void fsl_ddr_regs_edit(fsl_ddr_info_t *pinfo,
 		CFG_REGS(ddr_sdram_rcw_2),
 		CFG_REGS(ddr_cdr1),
 		CFG_REGS(ddr_cdr2),
+		CFG_REGS(dq_map_0),
+		CFG_REGS(dq_map_1),
+		CFG_REGS(dq_map_2),
+		CFG_REGS(dq_map_3),
 		CFG_REGS(err_disable),
 		CFG_REGS(err_int_en),
 		CFG_REGS(ddr_sdram_rcw_2),
@@ -705,6 +809,9 @@  static void print_memctl_options(const memctl_options_t *popts)
 		CTRL_OPTIONS(tfaw_window_four_activates_ps),
 		CTRL_OPTIONS(trwt_override),
 		CTRL_OPTIONS(trwt),
+		CTRL_OPTIONS(rtt_override),
+		CTRL_OPTIONS(rtt_override_value),
+		CTRL_OPTIONS(rtt_wr_override_value),
 	};
 	static const unsigned int n_opts = ARRAY_SIZE(options);
 
@@ -1245,6 +1352,266 @@  void ddr3_spd_dump(const ddr3_spd_eeprom_t *spd)
 }
 #endif
 
+#ifdef CONFIG_SYS_FSL_DDR4
+void ddr4_spd_dump(const struct ddr4_spd_eeprom_s *spd)
+{
+	unsigned int i;
+
+	/* General Section: Bytes 0-127 */
+
+#define PRINT_NXS(x, y, z...) printf("%-3d    : %02x " z "\n", x, (u8)y);
+#define PRINT_NNXXS(n0, n1, x0, x1, s) \
+	printf("%-3d-%3d: %02x %02x " s "\n", n0, n1, x0, x1);
+
+	PRINT_NXS(0, spd->info_size_crc,
+		  "info_size_crc  bytes written into serial memory, CRC coverage");
+	PRINT_NXS(1, spd->spd_rev,
+		  "spd_rev        SPD Revision");
+	PRINT_NXS(2, spd->mem_type,
+		  "mem_type       Key Byte / DRAM Device Type");
+	PRINT_NXS(3, spd->module_type,
+		  "module_type    Key Byte / Module Type");
+	PRINT_NXS(4, spd->density_banks,
+		  "density_banks  SDRAM Density and Banks");
+	PRINT_NXS(5, spd->addressing,
+		  "addressing     SDRAM Addressing");
+	PRINT_NXS(6, spd->package_type,
+		  "package_type   Package type");
+	PRINT_NXS(7, spd->opt_feature,
+		  "opt_feature    Optional features");
+	PRINT_NXS(8, spd->thermal_ref,
+		  "thermal_ref    Thermal and Refresh options");
+	PRINT_NXS(9, spd->oth_opt_features,
+		  "oth_opt_features Other SDRAM optional features");
+	PRINT_NXS(10, spd->res_10,
+		  "res_10         Reserved");
+	PRINT_NXS(11, spd->module_vdd,
+		  "module_vdd     Module Nominal Voltage, VDD");
+	PRINT_NXS(12, spd->organization,
+		  "organization Module Organization");
+	PRINT_NXS(13, spd->bus_width,
+		  "bus_width      Module Memory Bus Width");
+	PRINT_NXS(14, spd->therm_sensor,
+		  "therm_sensor   Module Thermal Sensor");
+	PRINT_NXS(15, spd->ext_type,
+		  "ext_type       Extended module type");
+	PRINT_NXS(16, spd->res_16,
+		  "res_16       Reserved");
+	PRINT_NXS(17, spd->timebases,
+		  "timebases    MTb and FTB");
+	PRINT_NXS(18, spd->tck_min,
+		  "tck_min      tCKAVGmin");
+	PRINT_NXS(19, spd->tck_max,
+		  "tck_max      TCKAVGmax");
+	PRINT_NXS(20, spd->caslat_b1,
+		  "caslat_b1    CAS latencies, 1st byte");
+	PRINT_NXS(21, spd->caslat_b2,
+		  "caslat_b2    CAS latencies, 2nd byte");
+	PRINT_NXS(22, spd->caslat_b3,
+		  "caslat_b3    CAS latencies, 3rd byte ");
+	PRINT_NXS(23, spd->caslat_b4,
+		  "caslat_b4    CAS latencies, 4th byte");
+	PRINT_NXS(24, spd->taa_min,
+		  "taa_min      Min CAS Latency Time");
+	PRINT_NXS(25, spd->trcd_min,
+		  "trcd_min     Min RAS# to CAS# Delay Time");
+	PRINT_NXS(26, spd->trp_min,
+		  "trp_min      Min Row Precharge Delay Time");
+	PRINT_NXS(27, spd->tras_trc_ext,
+		  "tras_trc_ext Upper Nibbles for tRAS and tRC");
+	PRINT_NXS(28, spd->tras_min_lsb,
+		  "tras_min_lsb tRASmin, lsb");
+	PRINT_NXS(29, spd->trc_min_lsb,
+		  "trc_min_lsb  tRCmin, lsb");
+	PRINT_NXS(30, spd->trfc1_min_lsb,
+		  "trfc1_min_lsb  Min Refresh Recovery Delay Time, LSB");
+	PRINT_NXS(31, spd->trfc1_min_msb,
+		  "trfc1_min_msb  Min Refresh Recovery Delay Time, MSB ");
+	PRINT_NXS(32, spd->trfc2_min_lsb,
+		  "trfc2_min_lsb  Min Refresh Recovery Delay Time, LSB");
+	PRINT_NXS(33, spd->trfc2_min_msb,
+		  "trfc2_min_msb  Min Refresh Recovery Delay Time, MSB");
+	PRINT_NXS(34, spd->trfc4_min_lsb,
+		  "trfc4_min_lsb Min Refresh Recovery Delay Time, LSB");
+	PRINT_NXS(35, spd->trfc4_min_msb,
+		  "trfc4_min_msb Min Refresh Recovery Delay Time, MSB");
+	PRINT_NXS(36, spd->tfaw_msb,
+		  "tfaw_msb      Upper Nibble for tFAW");
+	PRINT_NXS(37, spd->tfaw_min,
+		  "tfaw_min      tFAW, lsb");
+	PRINT_NXS(38, spd->trrds_min,
+		  "trrds_min     tRRD_Smin, MTB");
+	PRINT_NXS(39, spd->trrdl_min,
+		  "trrdl_min     tRRD_Lmin, MTB");
+	PRINT_NXS(40, spd->tccdl_min,
+		  "tccdl_min     tCCS_Lmin, MTB");
+
+	printf("%-3d-%3d: ", 41, 59);  /* Reserved, General Section */
+	for (i = 41; i <= 59; i++)
+		printf("%02x ", spd->res_41[i - 41]);
+
+	puts("\n");
+	printf("%-3d-%3d: ", 60, 77);
+	for (i = 60; i <= 77; i++)
+		printf("%02x ", spd->mapping[i - 60]);
+	puts("   mapping[] Connector to SDRAM bit map\n");
+
+	PRINT_NXS(117, spd->fine_tccdl_min,
+		  "fine_tccdl_min Fine offset for tCCD_Lmin");
+	PRINT_NXS(118, spd->fine_trrdl_min,
+		  "fine_trrdl_min Fine offset for tRRD_Lmin");
+	PRINT_NXS(119, spd->fine_trrds_min,
+		  "fine_trrds_min Fine offset for tRRD_Smin");
+	PRINT_NXS(120, spd->fine_trc_min,
+		  "fine_trc_min   Fine offset for tRCmin");
+	PRINT_NXS(121, spd->fine_trp_min,
+		  "fine_trp_min   Fine offset for tRPmin");
+	PRINT_NXS(122, spd->fine_trcd_min,
+		  "fine_trcd_min  Fine offset for tRCDmin");
+	PRINT_NXS(123, spd->fine_taa_min,
+		  "fine_taa_min   Fine offset for tAAmin");
+	PRINT_NXS(124, spd->fine_tck_max,
+		  "fine_tck_max   Fine offset for tCKAVGmax");
+	PRINT_NXS(125, spd->fine_tck_min,
+		  "fine_tck_min   Fine offset for tCKAVGmin");
+
+	/* CRC: Bytes 126-127 */
+	PRINT_NNXXS(126, 127, spd->crc[0], spd->crc[1], "  SPD CRC");
+
+	switch (spd->module_type) {
+	case 0x02:  /* UDIMM */
+	case 0x03:  /* SO-DIMM */
+		PRINT_NXS(128, spd->mod_section.unbuffered.mod_height,
+			  "mod_height    (Unbuffered) Module Nominal Height");
+		PRINT_NXS(129, spd->mod_section.unbuffered.mod_thickness,
+			  "mod_thickness (Unbuffered) Module Maximum Thickness");
+		PRINT_NXS(130, spd->mod_section.unbuffered.ref_raw_card,
+			  "ref_raw_card  (Unbuffered) Reference Raw Card Used");
+		PRINT_NXS(131, spd->mod_section.unbuffered.addr_mapping,
+			  "addr_mapping  (Unbuffered) Address mapping from Edge Connector to DRAM");
+		PRINT_NNXXS(254, 255, spd->mod_section.unbuffered.crc[0],
+			    spd->mod_section.unbuffered.crc[1], "  Module CRC");
+		break;
+	case 0x01:  /* RDIMM */
+		PRINT_NXS(128, spd->mod_section.registered.mod_height,
+			  "mod_height    (Registered) Module Nominal Height");
+		PRINT_NXS(129, spd->mod_section.registered.mod_thickness,
+			  "mod_thickness (Registered) Module Maximum Thickness");
+		PRINT_NXS(130, spd->mod_section.registered.ref_raw_card,
+			  "ref_raw_card  (Registered) Reference Raw Card Used");
+		PRINT_NXS(131, spd->mod_section.registered.modu_attr,
+			  "modu_attr     (Registered) DIMM Module Attributes");
+		PRINT_NXS(132, spd->mod_section.registered.thermal,
+			  "thermal       (Registered) Thermal Heat Spreader Solution");
+		PRINT_NXS(133, spd->mod_section.registered.reg_id_lo,
+			  "reg_id_lo     (Registered) Register Manufacturer ID Code, LSB");
+		PRINT_NXS(134, spd->mod_section.registered.reg_id_hi,
+			  "reg_id_hi     (Registered) Register Manufacturer ID Code, MSB");
+		PRINT_NXS(135, spd->mod_section.registered.reg_rev,
+			  "reg_rev       (Registered) Register Revision Number");
+		PRINT_NXS(136, spd->mod_section.registered.reg_map,
+			  "reg_map       (Registered) Address mapping");
+		PRINT_NNXXS(254, 255, spd->mod_section.registered.crc[0],
+			    spd->mod_section.registered.crc[1], "  Module CRC");
+		break;
+	case 0x04:  /* LRDIMM */
+		PRINT_NXS(128, spd->mod_section.loadreduced.mod_height,
+			  "mod_height    (Loadreduced) Module Nominal Height");
+		PRINT_NXS(129, spd->mod_section.loadreduced.mod_thickness,
+			  "mod_thickness (Loadreduced) Module Maximum Thickness");
+		PRINT_NXS(130, spd->mod_section.loadreduced.ref_raw_card,
+			  "ref_raw_card  (Loadreduced) Reference Raw Card Used");
+		PRINT_NXS(131, spd->mod_section.loadreduced.modu_attr,
+			  "modu_attr     (Loadreduced) DIMM Module Attributes");
+		PRINT_NXS(132, spd->mod_section.loadreduced.thermal,
+			  "thermal       (Loadreduced) Thermal Heat Spreader Solution");
+		PRINT_NXS(133, spd->mod_section.loadreduced.reg_id_lo,
+			  "reg_id_lo     (Loadreduced) Register Manufacturer ID Code, LSB");
+		PRINT_NXS(134, spd->mod_section.loadreduced.reg_id_hi,
+			  "reg_id_hi     (Loadreduced) Register Manufacturer ID Code, MSB");
+		PRINT_NXS(135, spd->mod_section.loadreduced.reg_rev,
+			  "reg_rev       (Loadreduced) Register Revision Number");
+		PRINT_NXS(136, spd->mod_section.loadreduced.reg_map,
+			  "reg_map       (Loadreduced) Address mapping");
+		PRINT_NXS(137, spd->mod_section.loadreduced.reg_drv,
+			  "reg_drv       (Loadreduced) Reg output drive strength");
+		PRINT_NXS(138, spd->mod_section.loadreduced.reg_drv_ck,
+			  "reg_drv_ck    (Loadreduced) Reg output drive strength for CK");
+		PRINT_NXS(139, spd->mod_section.loadreduced.data_buf_rev,
+			  "data_buf_rev  (Loadreduced) Data Buffer Revision Numbe");
+		PRINT_NXS(140, spd->mod_section.loadreduced.vrefqe_r0,
+			  "vrefqe_r0     (Loadreduced) DRAM VrefDQ for Package Rank 0");
+		PRINT_NXS(141, spd->mod_section.loadreduced.vrefqe_r1,
+			  "vrefqe_r1     (Loadreduced) DRAM VrefDQ for Package Rank 1");
+		PRINT_NXS(142, spd->mod_section.loadreduced.vrefqe_r2,
+			  "vrefqe_r2     (Loadreduced) DRAM VrefDQ for Package Rank 2");
+		PRINT_NXS(143, spd->mod_section.loadreduced.vrefqe_r3,
+			  "vrefqe_r3     (Loadreduced) DRAM VrefDQ for Package Rank 3");
+		PRINT_NXS(144, spd->mod_section.loadreduced.data_intf,
+			  "data_intf     (Loadreduced) Data Buffer VrefDQ for DRAM Interface");
+		PRINT_NXS(145, spd->mod_section.loadreduced.data_drv_1866,
+			  "data_drv_1866 (Loadreduced) Data Buffer MDQ Drive Strength and RTT");
+		PRINT_NXS(146, spd->mod_section.loadreduced.data_drv_2400,
+			  "data_drv_2400 (Loadreduced) Data Buffer MDQ Drive Strength and RTT");
+		PRINT_NXS(147, spd->mod_section.loadreduced.data_drv_3200,
+			  "data_drv_3200 (Loadreduced) Data Buffer MDQ Drive Strength and RTT");
+		PRINT_NXS(148, spd->mod_section.loadreduced.dram_drv,
+			  "dram_drv      (Loadreduced) DRAM Drive Strength");
+		PRINT_NXS(149, spd->mod_section.loadreduced.dram_odt_1866,
+			  "dram_odt_1866 (Loadreduced) DRAM ODT (RTT_WR, RTT_NOM)");
+		PRINT_NXS(150, spd->mod_section.loadreduced.dram_odt_2400,
+			  "dram_odt_2400 (Loadreduced) DRAM ODT (RTT_WR, RTT_NOM)");
+		PRINT_NXS(151, spd->mod_section.loadreduced.dram_odt_3200,
+			  "dram_odt_3200 (Loadreduced) DRAM ODT (RTT_WR, RTT_NOM)");
+		PRINT_NXS(152, spd->mod_section.loadreduced.dram_odt_park_1866,
+			  "dram_odt_park_1866 (Loadreduced) DRAM ODT (RTT_PARK)");
+		PRINT_NXS(153, spd->mod_section.loadreduced.dram_odt_park_2400,
+			  "dram_odt_park_2400 (Loadreduced) DRAM ODT (RTT_PARK)");
+		PRINT_NXS(154, spd->mod_section.loadreduced.dram_odt_park_3200,
+			  "dram_odt_park_3200 (Loadreduced) DRAM ODT (RTT_PARK)");
+		PRINT_NNXXS(254, 255, spd->mod_section.loadreduced.crc[0],
+			    spd->mod_section.loadreduced.crc[1],
+			    "  Module CRC");
+		break;
+	default:
+		/* Module-specific Section, Unsupported Module Type */
+		printf("%-3d-%3d: ", 128, 255);
+
+		for (i = 128; i <= 255; i++)
+			printf("%02x", spd->mod_section.uc[i - 60]);
+
+		break;
+	}
+
+	/* Unique Module ID: Bytes 320-383 */
+	PRINT_NXS(320, spd->mmid_lsb, "Module MfgID Code LSB - JEP-106");
+	PRINT_NXS(321, spd->mmid_msb, "Module MfgID Code MSB - JEP-106");
+	PRINT_NXS(322, spd->mloc,     "Mfg Location");
+	PRINT_NNXXS(323, 324, spd->mdate[0], spd->mdate[1], "Mfg Date");
+
+	printf("%-3d-%3d: ", 325, 328);
+
+	for (i = 325; i <= 328; i++)
+		printf("%02x ", spd->sernum[i - 325]);
+	printf("   Module Serial Number\n");
+
+	printf("%-3d-%3d: ", 329, 348);
+	for (i = 329; i <= 348; i++)
+		printf("%02x ", spd->mpart[i - 329]);
+	printf("   Mfg's Module Part Number\n");
+
+	PRINT_NXS(349, spd->mrev, "Module Revision code");
+	PRINT_NXS(350, spd->dmid_lsb, "DRAM MfgID Code LSB - JEP-106");
+	PRINT_NXS(351, spd->dmid_msb, "DRAM MfgID Code MSB - JEP-106");
+	PRINT_NXS(352, spd->stepping, "DRAM stepping");
+
+	printf("%-3d-%3d: ", 353, 381);
+	for (i = 353; i <= 381; i++)
+		printf("%02x ", spd->msd[i - 353]);
+	printf("   Mfg's Specific Data\n");
+}
+#endif
+
 static inline void generic_spd_dump(const generic_spd_eeprom_t *spd)
 {
 #if defined(CONFIG_SYS_FSL_DDR1)
@@ -1253,6 +1620,8 @@  static inline void generic_spd_dump(const generic_spd_eeprom_t *spd)
 	ddr2_spd_dump(spd);
 #elif defined(CONFIG_SYS_FSL_DDR3)
 	ddr3_spd_dump(spd);
+#elif defined(CONFIG_SYS_FSL_DDR4)
+	ddr4_spd_dump(spd);
 #endif
 }
 
diff --git a/drivers/ddr/fsl/lc_common_dimm_params.c b/drivers/ddr/fsl/lc_common_dimm_params.c
index 610318a..05a24dd 100644
--- a/drivers/ddr/fsl/lc_common_dimm_params.c
+++ b/drivers/ddr/fsl/lc_common_dimm_params.c
@@ -1,5 +1,5 @@ 
 /*
- * Copyright 2008-2012 Freescale Semiconductor, Inc.
+ * Copyright 2008-2014 Freescale Semiconductor, Inc.
  *
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU General Public License
@@ -11,20 +11,23 @@ 
 
 #include <fsl_ddr.h>
 
-#if defined(CONFIG_SYS_FSL_DDR3)
+#if defined(CONFIG_SYS_FSL_DDR3) || defined(CONFIG_SYS_FSL_DDR4)
 static unsigned int
-compute_cas_latency_ddr3(const dimm_params_t *dimm_params,
-			 common_timing_params_t *outpdimm,
-			 unsigned int number_of_dimms)
+compute_cas_latency(const dimm_params_t *dimm_params,
+		    common_timing_params_t *outpdimm,
+		    unsigned int number_of_dimms)
 {
 	unsigned int i;
-	unsigned int taamin_ps = 0;
-	unsigned int tckmin_x_ps = 0;
 	unsigned int common_caslat;
 	unsigned int caslat_actual;
 	unsigned int retry = 16;
 	unsigned int tmp;
 	const unsigned int mclk_ps = get_memory_clk_period_ps();
+#ifdef CONFIG_SYS_FSL_DDR3
+	const unsigned int taamax = 20000;
+#else
+	const unsigned int taamax = 18000;
+#endif
 
 	/* compute the common CAS latency supported between slots */
 	tmp = dimm_params[0].caslat_x;
@@ -34,19 +37,20 @@  compute_cas_latency_ddr3(const dimm_params_t *dimm_params,
 	}
 	common_caslat = tmp;
 
-	/* compute the max tAAmin tCKmin between slots */
-	for (i = 0; i < number_of_dimms; i++) {
-		taamin_ps = max(taamin_ps, dimm_params[i].taa_ps);
-		tckmin_x_ps = max(tckmin_x_ps, dimm_params[i].tckmin_x_ps);
-	}
 	/* validate if the memory clk is in the range of dimms */
-	if (mclk_ps < tckmin_x_ps) {
+	if (mclk_ps < outpdimm->tckmin_x_ps) {
 		printf("DDR clock (MCLK cycle %u ps) is faster than "
 			"the slowest DIMM(s) (tCKmin %u ps) can support.\n",
-			mclk_ps, tckmin_x_ps);
+			mclk_ps, outpdimm->tckmin_x_ps);
+	}
+#ifdef CONFIG_SYS_FSL_DDR4
+	if (mclk_ps > outpdimm->tckmax_ps) {
+		printf("DDR clock (MCLK cycle %u ps) is slower than DIMM(s) (tCKmax %u ps) can support.\n",
+		       mclk_ps, outpdimm->tckmax_ps);
 	}
+#endif
 	/* determine the acutal cas latency */
-	caslat_actual = (taamin_ps + mclk_ps - 1) / mclk_ps;
+	caslat_actual = (outpdimm->taamin_ps + mclk_ps - 1) / mclk_ps;
 	/* check if the dimms support the CAS latency */
 	while (!(common_caslat & (1 << caslat_actual)) && retry > 0) {
 		caslat_actual++;
@@ -54,13 +58,147 @@  compute_cas_latency_ddr3(const dimm_params_t *dimm_params,
 	}
 	/* once the caculation of caslat_actual is completed
 	 * we must verify that this CAS latency value does not
-	 * exceed tAAmax, which is 20 ns for all DDR3 speed grades
+	 * exceed tAAmax, which is 20 ns for all DDR3 speed grades,
+	 * 18ns for all DDR4 speed grades.
 	 */
-	if (caslat_actual * mclk_ps > 20000) {
+	if (caslat_actual * mclk_ps > taamax) {
 		printf("The choosen cas latency %d is too large\n",
 			caslat_actual);
 	}
-	outpdimm->lowest_common_SPD_caslat = caslat_actual;
+	outpdimm->lowest_common_spd_caslat = caslat_actual;
+	debug("lowest_common_spd_caslat is 0x%x\n", caslat_actual);
+
+	return 0;
+}
+#else	/* for DDR1 and DDR2 */
+static unsigned int
+compute_cas_latency(const dimm_params_t *dimm_params,
+		    common_timing_params_t *outpdimm,
+		    unsigned int number_of_dimms)
+{
+	int i;
+	const unsigned int mclk_ps = get_memory_clk_period_ps();
+	unsigned int lowest_good_caslat;
+	unsigned int not_ok;
+	unsigned int temp1, temp2;
+
+	debug("using mclk_ps = %u\n", mclk_ps);
+	if (mclk_ps > outpdimm->tckmax_ps) {
+		printf("Warning: DDR clock (%u ps) is slower than DIMM(s) (tCKmax %u ps)\n",
+		       mclk_ps, outpdimm->tckmax_ps);
+	}
+
+	/*
+	 * Compute a CAS latency suitable for all DIMMs
+	 *
+	 * Strategy for SPD-defined latencies: compute only
+	 * CAS latency defined by all DIMMs.
+	 */
+
+	/*
+	 * Step 1: find CAS latency common to all DIMMs using bitwise
+	 * operation.
+	 */
+	temp1 = 0xFF;
+	for (i = 0; i < number_of_dimms; i++) {
+		if (dimm_params[i].n_ranks) {
+			temp2 = 0;
+			temp2 |= 1 << dimm_params[i].caslat_x;
+			temp2 |= 1 << dimm_params[i].caslat_x_minus_1;
+			temp2 |= 1 << dimm_params[i].caslat_x_minus_2;
+			/*
+			 * If there was no entry for X-2 (X-1) in
+			 * the SPD, then caslat_x_minus_2
+			 * (caslat_x_minus_1) contains either 255 or
+			 * 0xFFFFFFFF because that's what the glorious
+			 * __ilog2 function returns for an input of 0.
+			 * On 32-bit PowerPC, left shift counts with bit
+			 * 26 set (that the value of 255 or 0xFFFFFFFF
+			 * will have), cause the destination register to
+			 * be 0.  That is why this works.
+			 */
+			temp1 &= temp2;
+		}
+	}
+
+	/*
+	 * Step 2: check each common CAS latency against tCK of each
+	 * DIMM's SPD.
+	 */
+	lowest_good_caslat = 0;
+	temp2 = 0;
+	while (temp1) {
+		not_ok = 0;
+		temp2 =  __ilog2(temp1);
+		debug("checking common caslat = %u\n", temp2);
+
+		/* Check if this CAS latency will work on all DIMMs at tCK. */
+		for (i = 0; i < number_of_dimms; i++) {
+			if (!dimm_params[i].n_ranks)
+				continue;
+
+			if (dimm_params[i].caslat_x == temp2) {
+				if (mclk_ps >= dimm_params[i].tckmin_x_ps) {
+					debug("CL = %u ok on DIMM %u at tCK=%u ps with tCKmin_X_ps of %u\n",
+					      temp2, i, mclk_ps,
+					      dimm_params[i].tckmin_x_ps);
+					continue;
+				} else {
+					not_ok++;
+				}
+			}
+
+			if (dimm_params[i].caslat_x_minus_1 == temp2) {
+				unsigned int tckmin_x_minus_1_ps
+					= dimm_params[i].tckmin_x_minus_1_ps;
+				if (mclk_ps >= tckmin_x_minus_1_ps) {
+					debug("CL = %u ok on DIMM %u at tCK=%u ps with tckmin_x_minus_1_ps of %u\n",
+					      temp2, i, mclk_ps,
+					      tckmin_x_minus_1_ps);
+					continue;
+				} else {
+					not_ok++;
+				}
+			}
+
+			if (dimm_params[i].caslat_x_minus_2 == temp2) {
+				unsigned int tckmin_x_minus_2_ps
+					= dimm_params[i].tckmin_x_minus_2_ps;
+				if (mclk_ps >= tckmin_x_minus_2_ps) {
+					debug("CL = %u ok on DIMM %u at tCK=%u ps with tckmin_x_minus_2_ps of %u\n",
+					      temp2, i, mclk_ps,
+					      tckmin_x_minus_2_ps);
+					continue;
+				} else {
+					not_ok++;
+				}
+			}
+		}
+
+		if (!not_ok)
+			lowest_good_caslat = temp2;
+
+		temp1 &= ~(1 << temp2);
+	}
+
+	debug("lowest common SPD-defined CAS latency = %u\n",
+	      lowest_good_caslat);
+	outpdimm->lowest_common_spd_caslat = lowest_good_caslat;
+
+
+	/*
+	 * Compute a common 'de-rated' CAS latency.
+	 *
+	 * The strategy here is to find the *highest* dereated cas latency
+	 * with the assumption that all of the DIMMs will support a dereated
+	 * CAS latency higher than or equal to their lowest dereated value.
+	 */
+	temp1 = 0;
+	for (i = 0; i < number_of_dimms; i++)
+		temp1 = max(temp1, dimm_params[i].caslat_lowest_derated);
+
+	outpdimm->highest_common_derated_caslat = temp1;
+	debug("highest common dereated CAS latency = %u\n", temp1);
 
 	return 0;
 }
@@ -82,34 +220,40 @@  compute_lowest_common_dimm_parameters(const dimm_params_t *dimm_params,
 
 	unsigned int tckmin_x_ps = 0;
 	unsigned int tckmax_ps = 0xFFFFFFFF;
-	unsigned int tckmax_max_ps = 0;
 	unsigned int trcd_ps = 0;
 	unsigned int trp_ps = 0;
 	unsigned int tras_ps = 0;
+#if defined(CONFIG_SYS_FSL_DDR3) || defined(CONFIG_SYS_FSL_DDR4)
+	unsigned int taamin_ps = 0;
+#endif
+#ifdef CONFIG_SYS_FSL_DDR4
+	unsigned int twr_ps = 15000;
+	unsigned int trfc1_ps = 0;
+	unsigned int trfc2_ps = 0;
+	unsigned int trfc4_ps = 0;
+	unsigned int trrds_ps = 0;
+	unsigned int trrdl_ps = 0;
+	unsigned int tccdl_ps = 0;
+#else
 	unsigned int twr_ps = 0;
 	unsigned int twtr_ps = 0;
 	unsigned int trfc_ps = 0;
 	unsigned int trrd_ps = 0;
+	unsigned int trtp_ps = 0;
+#endif
 	unsigned int trc_ps = 0;
 	unsigned int refresh_rate_ps = 0;
 	unsigned int extended_op_srt = 1;
+#if defined(CONFIG_SYS_FSL_DDR1) || defined(CONFIG_SYS_FSL_DDR2)
 	unsigned int tis_ps = 0;
 	unsigned int tih_ps = 0;
 	unsigned int tds_ps = 0;
 	unsigned int tdh_ps = 0;
-	unsigned int trtp_ps = 0;
 	unsigned int tdqsq_max_ps = 0;
 	unsigned int tqhs_ps = 0;
-
+#endif
 	unsigned int temp1, temp2;
 	unsigned int additive_latency = 0;
-#if !defined(CONFIG_SYS_FSL_DDR3)
-	const unsigned int mclk_ps = get_memory_clk_period_ps();
-	unsigned int lowest_good_caslat;
-	unsigned int not_ok;
-
-	debug("using mclk_ps = %u\n", mclk_ps);
-#endif
 
 	temp1 = 0;
 	for (i = 0; i < number_of_dimms; i++) {
@@ -146,31 +290,34 @@  compute_lowest_common_dimm_parameters(const dimm_params_t *dimm_params,
 		 * i.e., this is the slowest the whole system can go.
 		 */
 		tckmax_ps = min(tckmax_ps, dimm_params[i].tckmax_ps);
-
-		/* Either find maximum value to determine slowest
-		 * speed, delay, time, period, etc */
+#if defined(CONFIG_SYS_FSL_DDR3) || defined(CONFIG_SYS_FSL_DDR4)
+		taamin_ps = max(taamin_ps, dimm_params[i].taa_ps);
+#endif
 		tckmin_x_ps = max(tckmin_x_ps, dimm_params[i].tckmin_x_ps);
-		tckmax_max_ps = max(tckmax_max_ps, dimm_params[i].tckmax_ps);
 		trcd_ps = max(trcd_ps, dimm_params[i].trcd_ps);
 		trp_ps = max(trp_ps, dimm_params[i].trp_ps);
 		tras_ps = max(tras_ps, dimm_params[i].tras_ps);
+#ifdef CONFIG_SYS_FSL_DDR4
+		trfc1_ps = max(trfc1_ps, dimm_params[i].trfc1_ps);
+		trfc2_ps = max(trfc2_ps, dimm_params[i].trfc2_ps);
+		trfc4_ps = max(trfc4_ps, dimm_params[i].trfc4_ps);
+		trrds_ps = max(trrds_ps, dimm_params[i].trrds_ps);
+		trrdl_ps = max(trrdl_ps, dimm_params[i].trrdl_ps);
+		tccdl_ps = max(tccdl_ps, dimm_params[i].tccdl_ps);
+#else
 		twr_ps = max(twr_ps, dimm_params[i].twr_ps);
 		twtr_ps = max(twtr_ps, dimm_params[i].twtr_ps);
 		trfc_ps = max(trfc_ps, dimm_params[i].trfc_ps);
 		trrd_ps = max(trrd_ps, dimm_params[i].trrd_ps);
+		trtp_ps = max(trtp_ps, dimm_params[i].trtp_ps);
+#endif
 		trc_ps = max(trc_ps, dimm_params[i].trc_ps);
+#if defined(CONFIG_SYS_FSL_DDR1) || defined(CONFIG_SYS_FSL_DDR2)
 		tis_ps = max(tis_ps, dimm_params[i].tis_ps);
 		tih_ps = max(tih_ps, dimm_params[i].tih_ps);
 		tds_ps = max(tds_ps, dimm_params[i].tds_ps);
 		tdh_ps = max(tdh_ps, dimm_params[i].tdh_ps);
-		trtp_ps = max(trtp_ps, dimm_params[i].trtp_ps);
 		tqhs_ps = max(tqhs_ps, dimm_params[i].tqhs_ps);
-		refresh_rate_ps = max(refresh_rate_ps,
-				      dimm_params[i].refresh_rate_ps);
-		/* extended_op_srt is either 0 or 1, 0 having priority */
-		extended_op_srt = min(extended_op_srt,
-				      dimm_params[i].extended_op_srt);
-
 		/*
 		 * Find maximum tdqsq_max_ps to find slowest.
 		 *
@@ -178,6 +325,12 @@  compute_lowest_common_dimm_parameters(const dimm_params_t *dimm_params,
 		 * strategy for this parameter?
 		 */
 		tdqsq_max_ps = max(tdqsq_max_ps, dimm_params[i].tdqsq_max_ps);
+#endif
+		refresh_rate_ps = max(refresh_rate_ps,
+				      dimm_params[i].refresh_rate_ps);
+		/* extended_op_srt is either 0 or 1, 0 having priority */
+		extended_op_srt = min(extended_op_srt,
+				      dimm_params[i].extended_op_srt);
 	}
 
 	outpdimm->ndimms_present = number_of_dimms - temp1;
@@ -189,24 +342,37 @@  compute_lowest_common_dimm_parameters(const dimm_params_t *dimm_params,
 
 	outpdimm->tckmin_x_ps = tckmin_x_ps;
 	outpdimm->tckmax_ps = tckmax_ps;
-	outpdimm->tckmax_max_ps = tckmax_max_ps;
+#if defined(CONFIG_SYS_FSL_DDR3) || defined(CONFIG_SYS_FSL_DDR4)
+	outpdimm->taamin_ps = taamin_ps;
+#endif
 	outpdimm->trcd_ps = trcd_ps;
 	outpdimm->trp_ps = trp_ps;
 	outpdimm->tras_ps = tras_ps;
-	outpdimm->twr_ps = twr_ps;
+#ifdef CONFIG_SYS_FSL_DDR4
+	outpdimm->trfc1_ps = trfc1_ps;
+	outpdimm->trfc2_ps = trfc2_ps;
+	outpdimm->trfc4_ps = trfc4_ps;
+	outpdimm->trrds_ps = trrds_ps;
+	outpdimm->trrdl_ps = trrdl_ps;
+	outpdimm->tccdl_ps = tccdl_ps;
+#else
 	outpdimm->twtr_ps = twtr_ps;
 	outpdimm->trfc_ps = trfc_ps;
 	outpdimm->trrd_ps = trrd_ps;
+	outpdimm->trtp_ps = trtp_ps;
+#endif
+	outpdimm->twr_ps = twr_ps;
 	outpdimm->trc_ps = trc_ps;
 	outpdimm->refresh_rate_ps = refresh_rate_ps;
 	outpdimm->extended_op_srt = extended_op_srt;
+#if defined(CONFIG_SYS_FSL_DDR1) || defined(CONFIG_SYS_FSL_DDR2)
 	outpdimm->tis_ps = tis_ps;
 	outpdimm->tih_ps = tih_ps;
 	outpdimm->tds_ps = tds_ps;
 	outpdimm->tdh_ps = tdh_ps;
-	outpdimm->trtp_ps = trtp_ps;
 	outpdimm->tdqsq_max_ps = tdqsq_max_ps;
 	outpdimm->tqhs_ps = tqhs_ps;
+#endif
 
 	/* Determine common burst length for all DIMMs. */
 	temp1 = 0xff;
@@ -265,128 +431,9 @@  compute_lowest_common_dimm_parameters(const dimm_params_t *dimm_params,
 	if (temp1 != 0)
 		printf("ERROR: Mix different RDIMM detected!\n");
 
-#if defined(CONFIG_SYS_FSL_DDR3)
-	if (compute_cas_latency_ddr3(dimm_params, outpdimm, number_of_dimms))
+	/* calculate cas latency for all DDR types */
+	if (compute_cas_latency(dimm_params, outpdimm, number_of_dimms))
 		return 1;
-#else
-	/*
-	 * Compute a CAS latency suitable for all DIMMs
-	 *
-	 * Strategy for SPD-defined latencies: compute only
-	 * CAS latency defined by all DIMMs.
-	 */
-
-	/*
-	 * Step 1: find CAS latency common to all DIMMs using bitwise
-	 * operation.
-	 */
-	temp1 = 0xFF;
-	for (i = 0; i < number_of_dimms; i++) {
-		if (dimm_params[i].n_ranks) {
-			temp2 = 0;
-			temp2 |= 1 << dimm_params[i].caslat_x;
-			temp2 |= 1 << dimm_params[i].caslat_x_minus_1;
-			temp2 |= 1 << dimm_params[i].caslat_x_minus_2;
-			/*
-			 * FIXME: If there was no entry for X-2 (X-1) in
-			 * the SPD, then caslat_x_minus_2
-			 * (caslat_x_minus_1) contains either 255 or
-			 * 0xFFFFFFFF because that's what the glorious
-			 * __ilog2 function returns for an input of 0.
-			 * On 32-bit PowerPC, left shift counts with bit
-			 * 26 set (that the value of 255 or 0xFFFFFFFF
-			 * will have), cause the destination register to
-			 * be 0.  That is why this works.
-			 */
-			temp1 &= temp2;
-		}
-	}
-
-	/*
-	 * Step 2: check each common CAS latency against tCK of each
-	 * DIMM's SPD.
-	 */
-	lowest_good_caslat = 0;
-	temp2 = 0;
-	while (temp1) {
-		not_ok = 0;
-		temp2 =  __ilog2(temp1);
-		debug("checking common caslat = %u\n", temp2);
-
-		/* Check if this CAS latency will work on all DIMMs at tCK. */
-		for (i = 0; i < number_of_dimms; i++) {
-			if (!dimm_params[i].n_ranks) {
-				continue;
-			}
-			if (dimm_params[i].caslat_x == temp2) {
-				if (mclk_ps >= dimm_params[i].tckmin_x_ps) {
-					debug("CL = %u ok on DIMM %u at tCK=%u"
-					    " ps with its tCKmin_X_ps of %u\n",
-					       temp2, i, mclk_ps,
-					       dimm_params[i].tckmin_x_ps);
-					continue;
-				} else {
-					not_ok++;
-				}
-			}
-
-			if (dimm_params[i].caslat_x_minus_1 == temp2) {
-				unsigned int tckmin_x_minus_1_ps
-					= dimm_params[i].tckmin_x_minus_1_ps;
-				if (mclk_ps >= tckmin_x_minus_1_ps) {
-					debug("CL = %u ok on DIMM %u at "
-						"tCK=%u ps with its "
-						"tckmin_x_minus_1_ps of %u\n",
-					       temp2, i, mclk_ps,
-					       tckmin_x_minus_1_ps);
-					continue;
-				} else {
-					not_ok++;
-				}
-			}
-
-			if (dimm_params[i].caslat_x_minus_2 == temp2) {
-				unsigned int tckmin_x_minus_2_ps
-					= dimm_params[i].tckmin_x_minus_2_ps;
-				if (mclk_ps >= tckmin_x_minus_2_ps) {
-					debug("CL = %u ok on DIMM %u at "
-						"tCK=%u ps with its "
-						"tckmin_x_minus_2_ps of %u\n",
-					       temp2, i, mclk_ps,
-					       tckmin_x_minus_2_ps);
-					continue;
-				} else {
-					not_ok++;
-				}
-			}
-		}
-
-		if (!not_ok) {
-			lowest_good_caslat = temp2;
-		}
-
-		temp1 &= ~(1 << temp2);
-	}
-
-	debug("lowest common SPD-defined CAS latency = %u\n",
-	       lowest_good_caslat);
-	outpdimm->lowest_common_SPD_caslat = lowest_good_caslat;
-
-
-	/*
-	 * Compute a common 'de-rated' CAS latency.
-	 *
-	 * The strategy here is to find the *highest* dereated cas latency
-	 * with the assumption that all of the DIMMs will support a dereated
-	 * CAS latency higher than or equal to their lowest dereated value.
-	 */
-	temp1 = 0;
-	for (i = 0; i < number_of_dimms; i++) {
-		temp1 = max(temp1, dimm_params[i].caslat_lowest_derated);
-	}
-	outpdimm->highest_common_derated_caslat = temp1;
-	debug("highest common dereated CAS latency = %u\n", temp1);
-#endif /* #if defined(CONFIG_SYS_FSL_DDR3) */
 
 	/* Determine if all DIMMs ECC capable. */
 	temp1 = 1;
@@ -404,14 +451,6 @@  compute_lowest_common_dimm_parameters(const dimm_params_t *dimm_params,
 	}
 	outpdimm->all_dimms_ecc_capable = temp1;
 
-#ifndef CONFIG_SYS_FSL_DDR3
-	/* FIXME: move to somewhere else to validate. */
-	if (mclk_ps > tckmax_max_ps) {
-		printf("Warning: some of the installed DIMMs "
-				"can not operate this slowly.\n");
-		return 1;
-	}
-#endif
 	/*
 	 * Compute additive latency.
 	 *
@@ -468,27 +507,20 @@  compute_lowest_common_dimm_parameters(const dimm_params_t *dimm_params,
 	additive_latency = 0;
 
 #if defined(CONFIG_SYS_FSL_DDR2)
-	if (lowest_good_caslat < 4) {
-		additive_latency = (picos_to_mclk(trcd_ps) > lowest_good_caslat)
-			? picos_to_mclk(trcd_ps) - lowest_good_caslat : 0;
+	if ((outpdimm->lowest_common_spd_caslat < 4) &&
+	    (picos_to_mclk(trcd_ps) > outpdimm->lowest_common_spd_caslat)) {
+		additive_latency = picos_to_mclk(trcd_ps) -
+				   outpdimm->lowest_common_spd_caslat;
 		if (mclk_to_picos(additive_latency) > trcd_ps) {
 			additive_latency = picos_to_mclk(trcd_ps);
 			debug("setting additive_latency to %u because it was "
 				" greater than tRCD_ps\n", additive_latency);
 		}
 	}
-
-#elif defined(CONFIG_SYS_FSL_DDR3)
-	/*
-	 * The system will not use the global auto-precharge mode.
-	 * However, it uses the page mode, so we set AL=0
-	 */
-	additive_latency = 0;
 #endif
 
 	/*
 	 * Validate additive latency
-	 * FIXME: move to somewhere else to validate
 	 *
 	 * AL <= tRCD(min)
 	 */
@@ -516,10 +548,19 @@  compute_lowest_common_dimm_parameters(const dimm_params_t *dimm_params,
 	debug("trcd_ps   = %u\n", outpdimm->trcd_ps);
 	debug("trp_ps    = %u\n", outpdimm->trp_ps);
 	debug("tras_ps   = %u\n", outpdimm->tras_ps);
-	debug("twr_ps    = %u\n", outpdimm->twr_ps);
+#ifdef CONFIG_SYS_FSL_DDR4
+	debug("trfc1_ps = %u\n", trfc1_ps);
+	debug("trfc2_ps = %u\n", trfc2_ps);
+	debug("trfc4_ps = %u\n", trfc4_ps);
+	debug("trrds_ps = %u\n", trrds_ps);
+	debug("trrdl_ps = %u\n", trrdl_ps);
+	debug("tccdl_ps = %u\n", tccdl_ps);
+#else
 	debug("twtr_ps   = %u\n", outpdimm->twtr_ps);
 	debug("trfc_ps   = %u\n", outpdimm->trfc_ps);
 	debug("trrd_ps   = %u\n", outpdimm->trrd_ps);
+#endif
+	debug("twr_ps    = %u\n", outpdimm->twr_ps);
 	debug("trc_ps    = %u\n", outpdimm->trc_ps);
 
 	return 0;
diff --git a/drivers/ddr/fsl/main.c b/drivers/ddr/fsl/main.c
index d62ca63..f95704f 100644
--- a/drivers/ddr/fsl/main.c
+++ b/drivers/ddr/fsl/main.c
@@ -1,5 +1,5 @@ 
 /*
- * Copyright 2008-2012 Freescale Semiconductor, Inc.
+ * Copyright 2008-2014 Freescale Semiconductor, Inc.
  *
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU General Public License
@@ -81,14 +81,37 @@  u8 spd_i2c_addr[CONFIG_NUM_DDR_CONTROLLERS][CONFIG_DIMM_SLOTS_PER_CTLR] = {
 
 #endif
 
+#define SPD_SPA0_ADDRESS	0x36
+#define SPD_SPA1_ADDRESS	0x37
+
 static void __get_spd(generic_spd_eeprom_t *spd, u8 i2c_address)
 {
 	int ret;
+#ifdef CONFIG_SYS_FSL_DDR4
+	uint8_t dummy = 0;
+#endif
 
 	i2c_set_bus_num(CONFIG_SYS_SPD_BUS_NUM);
 
+#ifdef CONFIG_SYS_FSL_DDR4
+	/*
+	 * DDR4 SPD has 384 to 512 bytes
+	 * To access the lower 256 bytes, we need to set EE page address to 0
+	 * To access the upper 256 bytes, we need to set EE page address to 1
+	 * See Jedec standar No. 21-C for detail
+	 */
+	i2c_write(SPD_SPA0_ADDRESS, 0, 1, &dummy, 1);
+	ret = i2c_read(i2c_address, 0, 1, (uchar *)spd, 256);
+	if (!ret) {
+		i2c_write(SPD_SPA1_ADDRESS, 0, 1, &dummy, 1);
+		ret = i2c_read(i2c_address, 0, 1,
+			       (uchar *)((ulong)spd + 256),
+			       min(256, sizeof(generic_spd_eeprom_t) - 256));
+	}
+#else
 	ret = i2c_read(i2c_address, 0, 1, (uchar *)spd,
 				sizeof(generic_spd_eeprom_t));
+#endif
 
 	if (ret) {
 		if (i2c_address ==
diff --git a/drivers/ddr/fsl/options.c b/drivers/ddr/fsl/options.c
index b0cf046..bf0d1da 100644
--- a/drivers/ddr/fsl/options.c
+++ b/drivers/ddr/fsl/options.c
@@ -1,5 +1,5 @@ 
 /*
- * Copyright 2008, 2010-2012 Freescale Semiconductor, Inc.
+ * Copyright 2008, 2010-2014 Freescale Semiconductor, Inc.
  *
  * SPDX-License-Identifier:	GPL-2.0+
  */
@@ -29,7 +29,7 @@  struct dynamic_odt {
 	unsigned int odt_rtt_wr;
 };
 
-#ifdef CONFIG_SYS_FSL_DDR3
+#if defined(CONFIG_SYS_FSL_DDR3) || defined(CONFIG_SYS_FSL_DDR4)
 static const struct dynamic_odt single_Q[4] = {
 	{	/* cs0 */
 		FSL_DDR_ODT_NEVER,
@@ -259,7 +259,7 @@  static const struct dynamic_odt odt_unknown[4] = {
 		DDR3_RTT_OFF
 	}
 };
-#else	/* CONFIG_SYS_FSL_DDR3 */
+#else	/* CONFIG_SYS_FSL_DDR3 || CONFIG_SYS_FSL_DDR4 */
 static const struct dynamic_odt single_Q[4] = {
 	{0, 0, 0, 0},
 	{0, 0, 0, 0},
@@ -507,7 +507,9 @@  unsigned int populate_memctl_options(int all_dimms_registered,
 	unsigned int i;
 	char buffer[HWCONFIG_BUFFER_SIZE];
 	char *buf = NULL;
-#if defined(CONFIG_SYS_FSL_DDR3) || defined(CONFIG_SYS_FSL_DDR2)
+#if defined(CONFIG_SYS_FSL_DDR3) || \
+	defined(CONFIG_SYS_FSL_DDR2) || \
+	defined(CONFIG_SYS_FSL_DDR4)
 	const struct dynamic_odt *pdodt = odt_unknown;
 #endif
 	ulong ddr_freq;
@@ -519,7 +521,9 @@  unsigned int populate_memctl_options(int all_dimms_registered,
 	if (getenv_f("hwconfig", buffer, sizeof(buffer)) > 0)
 		buf = buffer;
 
-#if defined(CONFIG_SYS_FSL_DDR3) || defined(CONFIG_SYS_FSL_DDR2)
+#if defined(CONFIG_SYS_FSL_DDR3) || \
+	defined(CONFIG_SYS_FSL_DDR2) || \
+	defined(CONFIG_SYS_FSL_DDR4)
 	/* Chip select options. */
 	if (CONFIG_DIMM_SLOTS_PER_CTLR == 1) {
 		switch (pdimm[0].n_ranks) {
@@ -585,7 +589,9 @@  unsigned int populate_memctl_options(int all_dimms_registered,
 
 	/* Pick chip-select local options. */
 	for (i = 0; i < CONFIG_CHIP_SELECTS_PER_CTRL; i++) {
-#if defined(CONFIG_SYS_FSL_DDR3) || defined(CONFIG_SYS_FSL_DDR2)
+#if defined(CONFIG_SYS_FSL_DDR3) || \
+	defined(CONFIG_SYS_FSL_DDR2) || \
+	defined(CONFIG_SYS_FSL_DDR4)
 		popts->cs_local_opts[i].odt_rd_cfg = pdodt[i].odt_rd_cfg;
 		popts->cs_local_opts[i].odt_wr_cfg = pdodt[i].odt_wr_cfg;
 		popts->cs_local_opts[i].odt_rtt_norm = pdodt[i].odt_rtt_norm;
@@ -703,7 +709,7 @@  unsigned int populate_memctl_options(int all_dimms_registered,
 	popts->x4_en = (pdimm[0].device_width == 4) ? 1 : 0;
 
 	/* Choose burst length. */
-#if defined(CONFIG_SYS_FSL_DDR3)
+#if defined(CONFIG_SYS_FSL_DDR3) || defined(CONFIG_SYS_FSL_DDR4)
 #if defined(CONFIG_E500MC)
 	popts->otf_burst_chop_en = 0;	/* on-the-fly burst chop disable */
 	popts->burst_length = DDR_BL8;	/* Fixed 8-beat burst len */
@@ -722,7 +728,7 @@  unsigned int populate_memctl_options(int all_dimms_registered,
 #endif
 
 	/* Choose ddr controller address mirror mode */
-#if defined(CONFIG_SYS_FSL_DDR3)
+#if defined(CONFIG_SYS_FSL_DDR3) || defined(CONFIG_SYS_FSL_DDR4)
 	popts->mirrored_dimm = pdimm[0].mirrored_dimm;
 #endif
 
@@ -766,11 +772,9 @@  unsigned int populate_memctl_options(int all_dimms_registered,
 	 * BSTTOPRE precharge interval
 	 *
 	 * Set this to 0 for global auto precharge
-	 *
-	 * FIXME: Should this be configured in picoseconds?
-	 * Why it should be in ps:  better understanding of this
-	 * relative to actual DRAM timing parameters such as tRAS.
-	 * e.g. tRAS(min) = 40 ns
+	 * The value of 0x100 has been used for DDR1, DDR2, DDR3.
+	 * It is not wrong. Any value should be OK. The performance depends on
+	 * applications. There is no one good value for all.
 	 */
 	popts->bstopre = 0x100;
 
@@ -795,12 +799,12 @@  unsigned int populate_memctl_options(int all_dimms_registered,
 	 */
 	popts->tfaw_window_four_activates_ps = 37500;
 
-#elif defined(CONFIG_SYS_FSL_DDR3)
+#else
 	popts->tfaw_window_four_activates_ps = pdimm[0].tfaw_ps;
 #endif
 	popts->zq_en = 0;
 	popts->wrlvl_en = 0;
-#if defined(CONFIG_SYS_FSL_DDR3)
+#if defined(CONFIG_SYS_FSL_DDR3) || defined(CONFIG_SYS_FSL_DDR4)
 	/*
 	 * due to ddr3 dimm is fly-by topology
 	 * we suggest to enable write leveling to
diff --git a/drivers/ddr/fsl/util.c b/drivers/ddr/fsl/util.c
index ad53658..7a22aa3 100644
--- a/drivers/ddr/fsl/util.c
+++ b/drivers/ddr/fsl/util.c
@@ -1,5 +1,5 @@ 
 /*
- * Copyright 2008-2012 Freescale Semiconductor, Inc.
+ * Copyright 2008-2014 Freescale Semiconductor, Inc.
  *
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU General Public License
@@ -23,6 +23,18 @@ 
 
 #define ULL_8FS 0xFFFFFFFFULL
 
+u32 fsl_ddr_get_version(void)
+{
+	struct ccsr_ddr __iomem *ddr;
+	u32 ver_major_minor_errata;
+
+	ddr = (void *)_DDR_ADDR;
+	ver_major_minor_errata = (ddr_in32(&ddr->ip_rev1) & 0xFFFF) << 8;
+	ver_major_minor_errata |= (ddr_in32(&ddr->ip_rev2) & 0xFF00) >> 8;
+
+	return ver_major_minor_errata;
+}
+
 /*
  * Round up mclk_ps to nearest 1 ps in memory controller code
  * if the error is 0.5ps or more.
@@ -175,6 +187,9 @@  void board_add_ram_info(int use_default)
 	case SDRAM_TYPE_DDR3:
 		puts("3");
 		break;
+	case SDRAM_TYPE_DDR4:
+		puts("4");
+		break;
 	default:
 		puts("?");
 		break;
@@ -188,9 +203,12 @@  void board_add_ram_info(int use_default)
 		puts(", 64-bit");
 
 	/* Calculate CAS latency based on timing cfg values */
-	cas_lat = ((ddr_in32(&ddr->timing_cfg_1) >> 16) & 0xf) + 1;
-	if ((ddr_in32(&ddr->timing_cfg_3) >> 12) & 1)
-		cas_lat += (8 << 1);
+	cas_lat = ((ddr_in32(&ddr->timing_cfg_1) >> 16) & 0xf);
+	if (fsl_ddr_get_version() <= 0x40400)
+		cas_lat += 1;
+	else
+		cas_lat += 2;
+	cas_lat += ((ddr_in32(&ddr->timing_cfg_3) >> 12) & 3) << 4;
 	printf(", CL=%d", cas_lat >> 1);
 	if (cas_lat & 0x1)
 		puts(".5");
diff --git a/include/common_timing_params.h b/include/common_timing_params.h
index 76338d4..821de21 100644
--- a/include/common_timing_params.h
+++ b/include/common_timing_params.h
@@ -1,5 +1,5 @@ 
 /*
- * Copyright 2008 Freescale Semiconductor, Inc.
+ * Copyright 2008-2014 Freescale Semiconductor, Inc.
  *
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU General Public License
@@ -14,32 +14,45 @@  typedef struct {
 
 	unsigned int tckmin_x_ps;
 	unsigned int tckmax_ps;
-	unsigned int tckmax_max_ps;
 	unsigned int trcd_ps;
 	unsigned int trp_ps;
 	unsigned int tras_ps;
+#if defined(CONFIG_SYS_FSL_DDR3) || defined(CONFIG_SYS_FSL_DDR4)
+	unsigned int taamin_ps;
+#endif
 
-	unsigned int twr_ps;	/* maximum = 63750 ps */
+#ifdef CONFIG_SYS_FSL_DDR4
+	unsigned int trfc1_ps;
+	unsigned int trfc2_ps;
+	unsigned int trfc4_ps;
+	unsigned int trrds_ps;
+	unsigned int trrdl_ps;
+	unsigned int tccdl_ps;
+#else
 	unsigned int twtr_ps;	/* maximum = 63750 ps */
 	unsigned int trfc_ps;	/* maximum = 255 ns + 256 ns + .75 ns
 					   = 511750 ps */
 
 	unsigned int trrd_ps;	/* maximum = 63750 ps */
+	unsigned int trtp_ps;	/* byte 38, spd->trtp */
+#endif
+	unsigned int twr_ps;	/* maximum = 63750 ps */
 	unsigned int trc_ps;	/* maximum = 254 ns + .75 ns = 254750 ps */
 
 	unsigned int refresh_rate_ps;
 	unsigned int extended_op_srt;
 
+#if defined(CONFIG_SYS_FSL_DDR1) || defined(CONFIG_SYS_FSL_DDR2)
 	unsigned int tis_ps;	/* byte 32, spd->ca_setup */
 	unsigned int tih_ps;	/* byte 33, spd->ca_hold */
 	unsigned int tds_ps;	/* byte 34, spd->data_setup */
 	unsigned int tdh_ps;	/* byte 35, spd->data_hold */
-	unsigned int trtp_ps;	/* byte 38, spd->trtp */
 	unsigned int tdqsq_max_ps;	/* byte 44, spd->tdqsq */
 	unsigned int tqhs_ps;	/* byte 45, spd->tqhs */
+#endif
 
 	unsigned int ndimms_present;
-	unsigned int lowest_common_SPD_caslat;
+	unsigned int lowest_common_spd_caslat;
 	unsigned int highest_common_derated_caslat;
 	unsigned int additive_latency;
 	unsigned int all_dimms_burst_lengths_bitmask;
diff --git a/include/ddr_spd.h b/include/ddr_spd.h
index 15a3e8d..cf2aac6 100644
--- a/include/ddr_spd.h
+++ b/include/ddr_spd.h
@@ -1,5 +1,5 @@ 
 /*
- * Copyright 2008 Freescale Semiconductor, Inc.
+ * Copyright 2008-2014 Freescale Semiconductor, Inc.
  *
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU General Public License
@@ -290,11 +290,220 @@  typedef struct ddr3_spd_eeprom_s {
 
 } ddr3_spd_eeprom_t;
 
+/* From JEEC Standard No. 21-C release 23A */
+struct ddr4_spd_eeprom_s {
+	/* General Section: Bytes 0-127 */
+	uint8_t info_size_crc;		/*  0 # bytes */
+	uint8_t spd_rev;		/*  1 Total # bytes of SPD */
+	uint8_t mem_type;		/*  2 Key Byte / mem type */
+	uint8_t module_type;		/*  3 Key Byte / Module Type */
+	uint8_t density_banks;		/*  4 Density and Banks	*/
+	uint8_t addressing;		/*  5 Addressing */
+	uint8_t package_type;		/*  6 Package type */
+	uint8_t opt_feature;		/*  7 Optional features */
+	uint8_t thermal_ref;		/*  8 Thermal and refresh */
+	uint8_t oth_opt_features;	/*  9 Other optional features */
+	uint8_t res_10;			/* 10 Reserved */
+	uint8_t module_vdd;		/* 11 Module nominal voltage */
+	uint8_t organization;		/* 12 Module Organization */
+	uint8_t bus_width;		/* 13 Module Memory Bus Width */
+	uint8_t therm_sensor;		/* 14 Module Thermal Sensor */
+	uint8_t ext_type;		/* 15 Extended module type */
+	uint8_t res_16;
+	uint8_t timebases;		/* 17 MTb and FTB */
+	uint8_t tck_min;		/* 18 tCKAVGmin */
+	uint8_t tck_max;		/* 19 TCKAVGmax */
+	uint8_t caslat_b1;		/* 20 CAS latencies, 1st byte */
+	uint8_t caslat_b2;		/* 21 CAS latencies, 2nd byte */
+	uint8_t caslat_b3;		/* 22 CAS latencies, 3rd byte */
+	uint8_t caslat_b4;		/* 23 CAS latencies, 4th byte */
+	uint8_t taa_min;		/* 24 Min CAS Latency Time */
+	uint8_t trcd_min;		/* 25 Min RAS# to CAS# Delay Time */
+	uint8_t trp_min;		/* 26 Min Row Precharge Delay Time */
+	uint8_t tras_trc_ext;		/* 27 Upper Nibbles for tRAS and tRC */
+	uint8_t tras_min_lsb;		/* 28 tRASmin, lsb */
+	uint8_t trc_min_lsb;		/* 29 tRCmin, lsb */
+	uint8_t trfc1_min_lsb;		/* 30 Min Refresh Recovery Delay Time */
+	uint8_t trfc1_min_msb;		/* 31 Min Refresh Recovery Delay Time */
+	uint8_t trfc2_min_lsb;		/* 32 Min Refresh Recovery Delay Time */
+	uint8_t trfc2_min_msb;		/* 33 Min Refresh Recovery Delay Time */
+	uint8_t trfc4_min_lsb;		/* 34 Min Refresh Recovery Delay Time */
+	uint8_t trfc4_min_msb;		/* 35 Min Refresh Recovery Delay Time */
+	uint8_t tfaw_msb;		/* 36 Upper Nibble for tFAW */
+	uint8_t tfaw_min;		/* 37 tFAW, lsb */
+	uint8_t trrds_min;		/* 38 tRRD_Smin, MTB */
+	uint8_t trrdl_min;		/* 39 tRRD_Lmin, MTB */
+	uint8_t tccdl_min;		/* 40 tCCS_Lmin, MTB */
+	uint8_t res_41[60-41];		/* 41 Rserved */
+	uint8_t mapping[78-60];		/* 60~77 Connector to SDRAM bit map */
+	uint8_t res_78[117-78];		/* 78~116, Reserved */
+	int8_t fine_tccdl_min;		/* 117 Fine offset for tCCD_Lmin */
+	int8_t fine_trrdl_min;		/* 118 Fine offset for tRRD_Lmin */
+	int8_t fine_trrds_min;		/* 119 Fine offset for tRRD_Smin */
+	int8_t fine_trc_min;		/* 120 Fine offset for tRCmin */
+	int8_t fine_trp_min;		/* 121 Fine offset for tRPmin */
+	int8_t fine_trcd_min;		/* 122 Fine offset for tRCDmin */
+	int8_t fine_taa_min;		/* 123 Fine offset for tAAmin */
+	int8_t fine_tck_max;		/* 124 Fine offset for tCKAVGmax */
+	int8_t fine_tck_min;		/* 125 Fine offset for tCKAVGmin */
+	/* CRC: Bytes 126-127 */
+	uint8_t crc[2];			/* 126-127 SPD CRC */
+
+	/* Module-Specific Section: Bytes 128-255 */
+	union {
+		struct {
+			/* 128 (Unbuffered) Module Nominal Height */
+			uint8_t mod_height;
+			/* 129 (Unbuffered) Module Maximum Thickness */
+			uint8_t mod_thickness;
+			/* 130 (Unbuffered) Reference Raw Card Used */
+			uint8_t ref_raw_card;
+			/* 131 (Unbuffered) Address Mapping from
+			      Edge Connector to DRAM */
+			uint8_t addr_mapping;
+			/* 132~253 (Unbuffered) Reserved */
+			uint8_t res_132[254-132];
+			/* 254~255 CRC */
+			uint8_t crc[2];
+		} unbuffered;
+		struct {
+			/* 128 (Registered) Module Nominal Height */
+			uint8_t mod_height;
+			/* 129 (Registered) Module Maximum Thickness */
+			uint8_t mod_thickness;
+			/* 130 (Registered) Reference Raw Card Used */
+			uint8_t ref_raw_card;
+			/* 131 DIMM Module Attributes */
+			uint8_t modu_attr;
+			/* 132 RDIMM Thermal Heat Spreader Solution */
+			uint8_t thermal;
+			/* 133 Register Manufacturer ID Code, LSB */
+			uint8_t reg_id_lo;
+			/* 134 Register Manufacturer ID Code, MSB */
+			uint8_t reg_id_hi;
+			/* 135 Register Revision Number */
+			uint8_t reg_rev;
+			/* 136 Address mapping from register to DRAM */
+			uint8_t reg_map;
+			/* 137~253 Reserved */
+			uint8_t res_137[254-137];
+			/* 254~255 CRC */
+			uint8_t crc[2];
+		} registered;
+		struct {
+			/* 128 (Loadreduced) Module Nominal Height */
+			uint8_t mod_height;
+			/* 129 (Loadreduced) Module Maximum Thickness */
+			uint8_t mod_thickness;
+			/* 130 (Loadreduced) Reference Raw Card Used */
+			uint8_t ref_raw_card;
+			/* 131 DIMM Module Attributes */
+			uint8_t modu_attr;
+			/* 132 RDIMM Thermal Heat Spreader Solution */
+			uint8_t thermal;
+			/* 133 Register Manufacturer ID Code, LSB */
+			uint8_t reg_id_lo;
+			/* 134 Register Manufacturer ID Code, MSB */
+			uint8_t reg_id_hi;
+			/* 135 Register Revision Number */
+			uint8_t reg_rev;
+			/* 136 Address mapping from register to DRAM */
+			uint8_t reg_map;
+			/* 137 Register Output Drive Strength for CMD/Add*/
+			uint8_t reg_drv;
+			/* 138 Register Output Drive Strength for CK */
+			uint8_t reg_drv_ck;
+			/* 139 Data Buffer Revision Number */
+			uint8_t data_buf_rev;
+			/* 140 DRAM VrefDQ for Package Rank 0 */
+			uint8_t vrefqe_r0;
+			/* 141 DRAM VrefDQ for Package Rank 1 */
+			uint8_t vrefqe_r1;
+			/* 142 DRAM VrefDQ for Package Rank 2 */
+			uint8_t vrefqe_r2;
+			/* 143 DRAM VrefDQ for Package Rank 3 */
+			uint8_t vrefqe_r3;
+			/* 144 Data Buffer VrefDQ for DRAM Interface */
+			uint8_t data_intf;
+			/*
+			 * 145 Data Buffer MDQ Drive Strength and RTT
+			 * for data rate <= 1866
+			 */
+			uint8_t data_drv_1866;
+			/*
+			 * 146 Data Buffer MDQ Drive Strength and RTT
+			 * for 1866 < data rate <= 2400
+			 */
+			uint8_t data_drv_2400;
+			/*
+			 * 147 Data Buffer MDQ Drive Strength and RTT
+			 * for 2400 < data rate <= 3200
+			 */
+			uint8_t data_drv_3200;
+			/* 148 DRAM Drive Strength */
+			uint8_t dram_drv;
+			/*
+			 * 149 DRAM ODT (RTT_WR, RTT_NOM)
+			 * for data rate <= 1866
+			 */
+			uint8_t dram_odt_1866;
+			/*
+			 * 150 DRAM ODT (RTT_WR, RTT_NOM)
+			 * for 1866 < data rate <= 2400
+			 */
+			uint8_t dram_odt_2400;
+			/*
+			 * 151 DRAM ODT (RTT_WR, RTT_NOM)
+			 * for 2400 < data rate <= 3200
+			 */
+			uint8_t dram_odt_3200;
+			/*
+			 * 152 DRAM ODT (RTT_PARK)
+			 * for data rate <= 1866
+			 */
+			uint8_t dram_odt_park_1866;
+			/*
+			 * 153 DRAM ODT (RTT_PARK)
+			 * for 1866 < data rate <= 2400
+			 */
+			uint8_t dram_odt_park_2400;
+			/*
+			 * 154 DRAM ODT (RTT_PARK)
+			 * for 2400 < data rate <= 3200
+			 */
+			uint8_t dram_odt_park_3200;
+			uint8_t res_155[254-155];	/* Reserved */
+			/* 254~255 CRC */
+			uint8_t crc[2];
+		} loadreduced;
+		uint8_t uc[128]; /* 128-255 Module-Specific Section */
+	} mod_section;
+
+	uint8_t res_256[320-256];	/* 256~319 Reserved */
+
+	/* Module supplier's data: Byte 320~383 */
+	uint8_t mmid_lsb;		/* 320 Module MfgID Code LSB */
+	uint8_t mmid_msb;		/* 321 Module MfgID Code MSB */
+	uint8_t mloc;			/* 322 Mfg Location */
+	uint8_t mdate[2];		/* 323~324 Mfg Date */
+	uint8_t sernum[4];		/* 325~328 Module Serial Number */
+	uint8_t mpart[20];		/* 329~348 Mfg's Module Part Number */
+	uint8_t mrev;			/* 349 Module Revision Code */
+	uint8_t dmid_lsb;		/* 350 DRAM MfgID Code LSB */
+	uint8_t dmid_msb;		/* 351 DRAM MfgID Code MSB */
+	uint8_t stepping;		/* 352 DRAM stepping */
+	uint8_t msd[29];		/* 353~381 Mfg's Specific Data */
+	uint8_t res_382[2];		/* 382~383 Reserved */
+
+	uint8_t user[512-384];		/* 384~511 End User Programmable */
+};
+
 extern unsigned int ddr1_spd_check(const ddr1_spd_eeprom_t *spd);
 extern void ddr1_spd_dump(const ddr1_spd_eeprom_t *spd);
 extern unsigned int ddr2_spd_check(const ddr2_spd_eeprom_t *spd);
 extern void ddr2_spd_dump(const ddr2_spd_eeprom_t *spd);
 extern unsigned int ddr3_spd_check(const ddr3_spd_eeprom_t *spd);
+unsigned int ddr4_spd_check(const struct ddr4_spd_eeprom_s *spd);
 
 /*
  * Byte 2 Fundamental Memory Types.
@@ -310,6 +519,7 @@  extern unsigned int ddr3_spd_check(const ddr3_spd_eeprom_t *spd);
 #define SPD_MEMTYPE_DDR2_FBDIMM	(0x09)
 #define SPD_MEMTYPE_DDR2_FBDIMM_PROBE	(0x0A)
 #define SPD_MEMTYPE_DDR3	(0x0B)
+#define SPD_MEMTYPE_DDR4	(0x0C)
 
 /* DIMM Type for DDR2 SPD (according to v1.3) */
 #define DDR2_SPD_DIMMTYPE_UNDEFINED	(0x00)
@@ -338,4 +548,18 @@  extern unsigned int ddr3_spd_check(const ddr3_spd_eeprom_t *spd);
 #define DDR3_SPD_MODULETYPE_16B_SO_DIMM	(0x0C)
 #define DDR3_SPD_MODULETYPE_32B_SO_DIMM	(0x0D)
 
+/* DIMM Type for DDR4 SPD */
+#define DDR4_SPD_MODULETYPE_MASK	(0x0f)
+#define DDR4_SPD_MODULETYPE_EXT		(0x00)
+#define DDR4_SPD_MODULETYPE_RDIMM	(0x01)
+#define DDR4_SPD_MODULETYPE_UDIMM	(0x02)
+#define DDR4_SPD_MODULETYPE_SO_DIMM	(0x03)
+#define DDR4_SPD_MODULETYPE_LRDIMM	(0x04)
+#define DDR4_SPD_MODULETYPE_MINI_RDIMM	(0x05)
+#define DDR4_SPD_MODULETYPE_MINI_UDIMM	(0x06)
+#define DDR4_SPD_MODULETYPE_72B_SO_UDIMM	(0x08)
+#define DDR4_SPD_MODULETYPE_72B_SO_RDIMM	(0x09)
+#define DDR4_SPD_MODULETYPE_16B_SO_DIMM	(0x0C)
+#define DDR4_SPD_MODULETYPE_32B_SO_DIMM	(0x0D)
+
 #endif /* _DDR_SPD_H_ */
diff --git a/include/fsl_ddr.h b/include/fsl_ddr.h
index 72c0b2e..5c49b22 100644
--- a/include/fsl_ddr.h
+++ b/include/fsl_ddr.h
@@ -1,5 +1,5 @@ 
 /*
- * Copyright 2008-2011 Freescale Semiconductor, Inc.
+ * Copyright 2008-2014 Freescale Semiconductor, Inc.
  *
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU General Public License
@@ -9,6 +9,7 @@ 
 #ifndef FSL_DDR_MAIN_H
 #define FSL_DDR_MAIN_H
 
+#include <fsl_ddrc_version.h>
 #include <fsl_ddr_sdram.h>
 #include <fsl_ddr_dimm_params.h>
 
@@ -22,6 +23,10 @@ 
 #define ddr_out32(a, v)	out_be32(a, v)
 #endif
 
+#define _DDR_ADDR CONFIG_SYS_FSL_DDR_ADDR
+
+u32 fsl_ddr_get_version(void);
+
 #if defined(CONFIG_DDR_SPD) || defined(CONFIG_SPD_EEPROM)
 /*
  * Bind the main DDR setup driver's generic names
diff --git a/include/fsl_ddr_dimm_params.h b/include/fsl_ddr_dimm_params.h
index 99a72bc..09a67a6 100644
--- a/include/fsl_ddr_dimm_params.h
+++ b/include/fsl_ddr_dimm_params.h
@@ -1,5 +1,5 @@ 
 /*
- * Copyright 2008 Freescale Semiconductor, Inc.
+ * Copyright 2008-2014 Freescale Semiconductor, Inc.
  *
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU General Public License
@@ -13,7 +13,7 @@ 
 #define EDC_ECC		2
 #define EDC_AC_PARITY	4
 
-/* Parameters for a DDR2 dimm computed from the SPD */
+/* Parameters for a DDR dimm computed from the SPD */
 typedef struct dimm_params_s {
 
 	/* DIMM organization parameters */
@@ -32,7 +32,12 @@  typedef struct dimm_params_s {
 	unsigned int n_row_addr;
 	unsigned int n_col_addr;
 	unsigned int edc_config;	/* 0 = none, 1 = parity, 2 = ECC */
+#ifdef CONFIG_SYS_FSL_DDR4
+	unsigned int bank_addr_bits;
+	unsigned int bank_group_bits;
+#else
 	unsigned int n_banks_per_sdram_device;
+#endif
 	unsigned int burst_lengths_bitmask;	/* BL=4 bit 2, BL=8 = bit 3 */
 	unsigned int row_density;
 
@@ -43,19 +48,19 @@  typedef struct dimm_params_s {
 
 	/* DIMM timing parameters */
 
-	unsigned int mtb_ps;	/* medium timebase ps, only for ddr3 */
-	unsigned int ftb_10th_ps; /* fine timebase, in 1/10 ps, only for ddr3 */
-	unsigned int taa_ps;	/* minimum CAS latency time, only for ddr3 */
-	unsigned int tfaw_ps;	/* four active window delay, only for ddr3 */
+	int mtb_ps;	/* medium timebase ps */
+	int ftb_10th_ps; /* fine timebase, in 1/10 ps */
+	int taa_ps;	/* minimum CAS latency time */
+	int tfaw_ps;	/* four active window delay */
 
 	/*
 	 * SDRAM clock periods
 	 * The range for these are 1000-10000 so a short should be sufficient
 	 */
-	unsigned int tckmin_x_ps;
-	unsigned int tckmin_x_minus_1_ps;
-	unsigned int tckmin_x_minus_2_ps;
-	unsigned int tckmax_ps;
+	int tckmin_x_ps;
+	int tckmin_x_minus_1_ps;
+	int tckmin_x_minus_2_ps;
+	int tckmax_ps;
 
 	/* SPD-defined CAS latencies */
 	unsigned int caslat_x;
@@ -65,32 +70,46 @@  typedef struct dimm_params_s {
 	unsigned int caslat_lowest_derated;	/* Derated CAS latency */
 
 	/* basic timing parameters */
-	unsigned int trcd_ps;
-	unsigned int trp_ps;
-	unsigned int tras_ps;
-
-	unsigned int twr_ps;	/* maximum = 63750 ps */
-	unsigned int twtr_ps;	/* maximum = 63750 ps */
-	unsigned int trfc_ps;   /* max = 255 ns + 256 ns + .75 ns
+	int trcd_ps;
+	int trp_ps;
+	int tras_ps;
+
+#ifdef CONFIG_SYS_FSL_DDR4
+	int trfc1_ps;
+	int trfc2_ps;
+	int trfc4_ps;
+	int trrds_ps;
+	int trrdl_ps;
+	int tccdl_ps;
+#else
+	int twr_ps;	/* maximum = 63750 ps */
+	int trfc_ps;	/* max = 255 ns + 256 ns + .75 ns
 				       = 511750 ps */
+	int trrd_ps;	/* maximum = 63750 ps */
+	int twtr_ps;	/* maximum = 63750 ps */
+	int trtp_ps;	/* byte 38, spd->trtp */
+#endif
 
-	unsigned int trrd_ps;	/* maximum = 63750 ps */
-	unsigned int trc_ps;	/* maximum = 254 ns + .75 ns = 254750 ps */
+	int trc_ps;	/* maximum = 254 ns + .75 ns = 254750 ps */
 
-	unsigned int refresh_rate_ps;
-	unsigned int extended_op_srt;
+	int refresh_rate_ps;
+	int extended_op_srt;
 
-	/* DDR3 doesn't need these as below */
-	unsigned int tis_ps;	/* byte 32, spd->ca_setup */
-	unsigned int tih_ps;	/* byte 33, spd->ca_hold */
-	unsigned int tds_ps;	/* byte 34, spd->data_setup */
-	unsigned int tdh_ps;	/* byte 35, spd->data_hold */
-	unsigned int trtp_ps;	/* byte 38, spd->trtp */
-	unsigned int tdqsq_max_ps;	/* byte 44, spd->tdqsq */
-	unsigned int tqhs_ps;	/* byte 45, spd->tqhs */
+#if defined(CONFIG_SYS_FSL_DDR1) || defined(CONFIG_SYS_FSL_DDR2)
+	int tis_ps;	/* byte 32, spd->ca_setup */
+	int tih_ps;	/* byte 33, spd->ca_hold */
+	int tds_ps;	/* byte 34, spd->data_setup */
+	int tdh_ps;	/* byte 35, spd->data_hold */
+	int tdqsq_max_ps;	/* byte 44, spd->tdqsq */
+	int tqhs_ps;	/* byte 45, spd->tqhs */
+#endif
 
 	/* DDR3 RDIMM */
 	unsigned char rcw[16];	/* Register Control Word 0-15 */
+#ifdef CONFIG_SYS_FSL_DDR4
+	unsigned int dq_mapping[18];
+	unsigned int dq_mapping_ors;
+#endif
 } dimm_params_t;
 
 extern unsigned int ddr_compute_dimm_parameters(
diff --git a/include/fsl_ddr_sdram.h b/include/fsl_ddr_sdram.h
index 2a36431..e39b716 100644
--- a/include/fsl_ddr_sdram.h
+++ b/include/fsl_ddr_sdram.h
@@ -1,5 +1,5 @@ 
 /*
- * Copyright 2008-2011 Freescale Semiconductor, Inc.
+ * Copyright 2008-2014 Freescale Semiconductor, Inc.
  *
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU General Public License
@@ -13,11 +13,13 @@ 
  * Pick a basic DDR Technology.
  */
 #include <ddr_spd.h>
+#include <fsl_ddrc_version.h>
 
-#define SDRAM_TYPE_DDR1    2
-#define SDRAM_TYPE_DDR2    3
-#define SDRAM_TYPE_LPDDR1  6
-#define SDRAM_TYPE_DDR3    7
+#define SDRAM_TYPE_DDR1		2
+#define SDRAM_TYPE_DDR2		3
+#define SDRAM_TYPE_LPDDR1	6
+#define SDRAM_TYPE_DDR3		7
+#define SDRAM_TYPE_DDR4		5
 
 #define DDR_BL4		4	/* burst length 4 */
 #define DDR_BC4		DDR_BL4	/* burst chop for ddr3 */
@@ -54,6 +56,12 @@  typedef ddr3_spd_eeprom_t generic_spd_eeprom_t;
 #ifndef CONFIG_FSL_SDRAM_TYPE
 #define CONFIG_FSL_SDRAM_TYPE	SDRAM_TYPE_DDR3
 #endif
+#elif defined(CONFIG_SYS_FSL_DDR4)
+#define FSL_DDR_MIN_TCKE_PULSE_WIDTH_DDR	(3)	/* FIXME */
+typedef struct ddr4_spd_eeprom_s generic_spd_eeprom_t;
+#ifndef CONFIG_FSL_SDRAM_TYPE
+#define CONFIG_FSL_SDRAM_TYPE	SDRAM_TYPE_DDR4
+#endif
 #endif	/* #if defined(CONFIG_SYS_FSL_DDR1) */
 
 #define FSL_DDR_ODT_NEVER		0x0
@@ -116,7 +124,8 @@  typedef ddr3_spd_eeprom_t generic_spd_eeprom_t;
 
 #define TIMING_CFG_2_CPO_MASK	0x0F800000
 
-#if defined(CONFIG_P4080)
+#if defined(CONFIG_SYS_FSL_DDR_VER) && \
+	(CONFIG_SYS_FSL_DDR_VER > FSL_DDR_VER_4_4)
 #define RD_TO_PRE_MASK		0xf
 #define RD_TO_PRE_SHIFT		13
 #define WR_DATA_DELAY_MASK	0xf
@@ -154,9 +163,27 @@  typedef ddr3_spd_eeprom_t generic_spd_eeprom_t;
 #define DDR_CDR2_ODT_MASK	0x1
 #define DDR_CDR1_ODT(x) ((x & DDR_CDR1_ODT_MASK) << DDR_CDR1_ODT_SHIFT)
 #define DDR_CDR2_ODT(x) (x & DDR_CDR2_ODT_MASK)
+#define DDR_CDR2_VREF_OVRD(x)	(0x00008080 | ((((x) - 37) & 0x3F) << 8))
 
 #if (defined(CONFIG_SYS_FSL_DDR_VER) && \
 	(CONFIG_SYS_FSL_DDR_VER >= FSL_DDR_VER_4_7))
+#ifdef CONFIG_SYS_FSL_DDR3L
+#define DDR_CDR_ODT_OFF		0x0
+#define DDR_CDR_ODT_120ohm	0x1
+#define DDR_CDR_ODT_200ohm	0x2
+#define DDR_CDR_ODT_75ohm	0x3
+#define DDR_CDR_ODT_60ohm	0x5
+#define DDR_CDR_ODT_46ohm	0x7
+#elif defined(CONFIG_SYS_FSL_DDR4)
+#define DDR_CDR_ODT_OFF		0x0
+#define DDR_CDR_ODT_100ohm	0x1
+#define DDR_CDR_ODT_120OHM	0x2
+#define DDR_CDR_ODT_80ohm	0x3
+#define DDR_CDR_ODT_60ohm	0x4
+#define DDR_CDR_ODT_40ohm	0x5
+#define DDR_CDR_ODT_50ohm	0x6
+#define DDR_CDR_ODT_30ohm	0x7
+#else
 #define DDR_CDR_ODT_OFF		0x0
 #define DDR_CDR_ODT_120ohm	0x1
 #define DDR_CDR_ODT_180ohm	0x2
@@ -165,6 +192,7 @@  typedef ddr3_spd_eeprom_t generic_spd_eeprom_t;
 #define DDR_CDR_ODT_60hm	0x5
 #define DDR_CDR_ODT_70ohm	0x6
 #define DDR_CDR_ODT_47ohm	0x7
+#endif /* DDR3L */
 #else
 #define DDR_CDR_ODT_75ohm	0x0
 #define DDR_CDR_ODT_55ohm	0x1
@@ -188,6 +216,7 @@  typedef struct fsl_ddr_cfg_regs_s {
 	unsigned int timing_cfg_2;
 	unsigned int ddr_sdram_cfg;
 	unsigned int ddr_sdram_cfg_2;
+	unsigned int ddr_sdram_cfg_3;
 	unsigned int ddr_sdram_mode;
 	unsigned int ddr_sdram_mode_2;
 	unsigned int ddr_sdram_mode_3;
@@ -196,6 +225,14 @@  typedef struct fsl_ddr_cfg_regs_s {
 	unsigned int ddr_sdram_mode_6;
 	unsigned int ddr_sdram_mode_7;
 	unsigned int ddr_sdram_mode_8;
+	unsigned int ddr_sdram_mode_9;
+	unsigned int ddr_sdram_mode_10;
+	unsigned int ddr_sdram_mode_11;
+	unsigned int ddr_sdram_mode_12;
+	unsigned int ddr_sdram_mode_13;
+	unsigned int ddr_sdram_mode_14;
+	unsigned int ddr_sdram_mode_15;
+	unsigned int ddr_sdram_mode_16;
 	unsigned int ddr_sdram_md_cntl;
 	unsigned int ddr_sdram_interval;
 	unsigned int ddr_data_init;
@@ -204,6 +241,10 @@  typedef struct fsl_ddr_cfg_regs_s {
 	unsigned int ddr_init_ext_addr;
 	unsigned int timing_cfg_4;
 	unsigned int timing_cfg_5;
+	unsigned int timing_cfg_6;
+	unsigned int timing_cfg_7;
+	unsigned int timing_cfg_8;
+	unsigned int timing_cfg_9;
 	unsigned int ddr_zq_cntl;
 	unsigned int ddr_wrlvl_cntl;
 	unsigned int ddr_wrlvl_cntl_2;
@@ -211,6 +252,14 @@  typedef struct fsl_ddr_cfg_regs_s {
 	unsigned int ddr_sr_cntr;
 	unsigned int ddr_sdram_rcw_1;
 	unsigned int ddr_sdram_rcw_2;
+	unsigned int ddr_sdram_rcw_3;
+	unsigned int ddr_sdram_rcw_4;
+	unsigned int ddr_sdram_rcw_5;
+	unsigned int ddr_sdram_rcw_6;
+	unsigned int dq_map_0;
+	unsigned int dq_map_1;
+	unsigned int dq_map_2;
+	unsigned int dq_map_3;
 	unsigned int ddr_eor;
 	unsigned int ddr_cdr1;
 	unsigned int ddr_cdr2;
@@ -225,7 +274,7 @@  typedef struct memctl_options_partial_s {
 	unsigned int all_dimms_burst_lengths_bitmask;
 	unsigned int all_dimms_registered;
 	unsigned int all_dimms_unbuffered;
-	/*	unsigned int lowest_common_SPD_caslat; */
+	/*	unsigned int lowest_common_spd_caslat; */
 	unsigned int all_dimms_minimum_trcd_ps;
 } memctl_options_partial_t;
 
diff --git a/include/fsl_ddrc_version.h b/include/fsl_ddrc_version.h
new file mode 100644
index 0000000..60ba98b
--- /dev/null
+++ b/include/fsl_ddrc_version.h
@@ -0,0 +1,18 @@ 
+/*
+ * Copyright 2014 Freescale Semiconductor, Inc.
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#ifndef __FSL_DDRC_VER_H
+#define __FSL_DDRC_VER_H
+
+/*
+ * Only the versions with distinct features or registers are listed here.
+ */
+#define FSL_DDR_VER_4_4 44
+#define FSL_DDR_VER_4_6 46
+#define FSL_DDR_VER_4_7	47
+#define FSL_DDR_VER_5_0	50
+
+#endif /* __FSL_DDRC_VER_H */
diff --git a/include/fsl_immap.h b/include/fsl_immap.h
index 00902ca..d63cc19 100644
--- a/include/fsl_immap.h
+++ b/include/fsl_immap.h
@@ -1,7 +1,7 @@ 
 /*
  * Common internal memory map for some Freescale SoCs
  *
- * Copyright 2013 Freescale Semiconductor, Inc.
+ * Copyright 2013-2014 Freescale Semiconductor, Inc.
  *
  * SPDX-License-Identifier:	GPL-2.0+
  */
@@ -50,7 +50,8 @@  struct ccsr_ddr {
 	u8	res_150[16];
 	u32	timing_cfg_4;		/* SDRAM Timing Configuration 4 */
 	u32	timing_cfg_5;		/* SDRAM Timing Configuration 5 */
-	u8	reg_168[8];
+	u32	timing_cfg_6;		/* SDRAM Timing Configuration 6 */
+	u32	timing_cfg_7;		/* SDRAM Timing Configuration 7 */
 	u32	ddr_zq_cntl;		/* ZQ calibration control*/
 	u32	ddr_wrlvl_cntl;		/* write leveling control*/
 	u8	reg_178[4];
@@ -60,14 +61,40 @@  struct ccsr_ddr {
 	u8	reg_188[8];
 	u32	ddr_wrlvl_cntl_2;	/* write leveling control 2 */
 	u32	ddr_wrlvl_cntl_3;	/* write leveling control 3 */
-	u8	res_198[104];
+	u8	res_198[0x1a0-0x198];
+	u32	ddr_sdram_rcw_3;
+	u32	ddr_sdram_rcw_4;
+	u32	ddr_sdram_rcw_5;
+	u32	ddr_sdram_rcw_6;
+	u8	res_1b0[0x200-0x1b0];
 	u32	sdram_mode_3;		/* SDRAM Mode Configuration 3 */
 	u32	sdram_mode_4;		/* SDRAM Mode Configuration 4 */
 	u32	sdram_mode_5;		/* SDRAM Mode Configuration 5 */
 	u32	sdram_mode_6;		/* SDRAM Mode Configuration 6 */
 	u32	sdram_mode_7;		/* SDRAM Mode Configuration 7 */
 	u32	sdram_mode_8;		/* SDRAM Mode Configuration 8 */
-	u8	res_218[0x908];
+	u8	res_218[0x220-0x218];
+	u32	sdram_mode_9;		/* SDRAM Mode Configuration 9 */
+	u32	sdram_mode_10;		/* SDRAM Mode Configuration 10 */
+	u32	sdram_mode_11;		/* SDRAM Mode Configuration 11 */
+	u32	sdram_mode_12;		/* SDRAM Mode Configuration 12 */
+	u32	sdram_mode_13;		/* SDRAM Mode Configuration 13 */
+	u32	sdram_mode_14;		/* SDRAM Mode Configuration 14 */
+	u32	sdram_mode_15;		/* SDRAM Mode Configuration 15 */
+	u32	sdram_mode_16;		/* SDRAM Mode Configuration 16 */
+	u8	res_240[0x250-0x240];
+	u32	timing_cfg_8;		/* SDRAM Timing Configuration 8 */
+	u32	timing_cfg_9;		/* SDRAM Timing Configuration 9 */
+	u8	res_258[0x260-0x258];
+	u32	sdram_cfg_3;
+	u8	res_264[0x2a0-0x264];
+	u32	deskew_cntl;
+	u8	res_2a4[0x400-0x2a4];
+	u32	dq_map_0;
+	u32	dq_map_1;
+	u32	dq_map_2;
+	u32	dq_map_3;
+	u8	res_410[0xb20-0x410];
 	u32	ddr_dsr1;		/* Debug Status 1 */
 	u32	ddr_dsr2;		/* Debug Status 2 */
 	u32	ddr_cdr1;		/* Control Driver 1 */