U-Boot
Threads by month
- ----- 2025 -----
- May
- April
- March
- February
- January
- ----- 2024 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2023 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2022 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2021 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2020 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2019 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2018 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2017 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2016 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2015 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2014 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2013 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2012 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2011 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2010 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2009 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2008 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2007 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2006 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2005 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2004 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2003 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2002 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2001 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2000 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
April 2014
- 180 participants
- 558 discussions

24 Apr '14
We use dynamical mtdparts partition instead of directly puting
mtd partitions nodes in device tree.
Signed-off-by: Shengzhou Liu <Shengzhou.Liu(a)freescale.com>
---
v2: update nand name to u64.
include/configs/T208xQDS.h | 17 +++++++++++++++++
1 file changed, 17 insertions(+)
diff --git a/include/configs/T208xQDS.h b/include/configs/T208xQDS.h
index 5ab4de6..639cc4e 100644
--- a/include/configs/T208xQDS.h
+++ b/include/configs/T208xQDS.h
@@ -708,6 +708,23 @@ unsigned long get_board_ddr_clk(void);
#define CONFIG_DOS_PARTITION
#endif
+
+/*
+ * Dynamic MTD Partition support with mtdparts
+ */
+#ifndef CONFIG_SYS_NO_FLASH
+#define CONFIG_MTD_DEVICE
+#define CONFIG_MTD_PARTITIONS
+#define CONFIG_CMD_MTDPARTS
+#define CONFIG_FLASH_CFI_MTD
+#define MTDIDS_DEFAULT "nor0=fe8000000.nor,nand0=fff800000.flash," \
+ "spi0=spife110000.0"
+#define MTDPARTS_DEFAULT "mtdparts=fe8000000.nor:1m(uboot),5m(kernel)," \
+ "128k(dtb),96m(fs),-(user);fff800000.flash:1m(uboot)," \
+ "5m(kernel),128k(dtb),96m(fs),-(user);spife110000.0:" \
+ "1m(uboot),5m(kernel),128k(dtb),-(user)"
+#endif
+
/*
* Environment
*/
--
1.8.0
2
3

[U-Boot] [PATCH][v2] driver/net/fm/memac_phy: Initialize mdio_clock for SoCs wih FMANv3
by Priyanka Jain 24 Apr '14
by Priyanka Jain 24 Apr '14
24 Apr '14
MDIO clock needs to be initialized in u-boot code for SoCs
having FMAN-v3(v3H or v3L) controller due to below reasons
-On SoCs that have FMAN-v3H like B4860, default value of
MDIO_CLK_DIV bits in mdio_stat(mdio_cfg) register generates
mdio clock too high (much higher than 2.5MHz), violating the
IEEE specs.
-On SOCs that have FMAN-v3L like T1040, default value of
MDIO_CLK_DIV bits is zero, so MDIO clock is disabled.
So, for proper functioninig of MDIO, MDIO_CLK_DIV bits needs to
be properly initialized.
Also this type of initialization is generally done in
PBI(pre-bootloader) phase using rcw.But for chips like T1040
which support deep-sleep, such type of initialization cannot be
done in PBI phase due to the limitation that during deep-sleep
resume, FMAN (MDIO) registers are not accessible in PBI phase.
So, mdio clock initailization must be done as part of u-boot.
This initialization code is implemented in memac_phy.c which
gets compiled only for SoCs having FMANv3, so no extra compilation
flag is required.
Signed-off-by: Priyanka Jain <Priyanka.Jain(a)freescale.com>
---
Changes for v2: Corrected Signed-off footer
drivers/net/fm/memac_phy.c | 12 ++++++++++++
1 files changed, 12 insertions(+), 0 deletions(-)
diff --git a/drivers/net/fm/memac_phy.c b/drivers/net/fm/memac_phy.c
index 140e59b..2f4bc11 100644
--- a/drivers/net/fm/memac_phy.c
+++ b/drivers/net/fm/memac_phy.c
@@ -133,5 +133,17 @@ int fm_memac_mdio_init(bd_t *bis, struct memac_mdio_info *info)
bus->priv = info->regs;
+ /*
+ * On some platforms like B4860, default value of MDIO_CLK_DIV bits
+ * in mdio_stat(mdio_cfg) register generates MDIO clock too high
+ * (much higher than 2.5MHz), violating the IEEE specs.
+ * On other platforms like T1040, default value of MDIO_CLK_DIV bits
+ * is zero, so MDIO clock is disabled.
+ * So, for proper functioning of MDIO, MDIO_CLK_DIV bits needs to
+ * be properly initialized.
+ */
+ setbits_be32(&((struct memac_mdio_controller *)info->regs)->mdio_stat,
+ MDIO_STAT_CLKDIV(258));
+
return mdio_register(bus);
}
--
1.7.4.1
2
1

[U-Boot] [PATCH] fsl/usb: Increase TXFIFOTHRESH value for usb write in T4 Rev 2.0
by Nikhil Badola 24 Apr '14
by Nikhil Badola 24 Apr '14
24 Apr '14
Increase TXFIFOTHRES field value in TXFILLTUNING register of usb for T4 Rev 2.0.
This decreases data burst rate with which data packets are posted from the TX
latency FIFO to compensate for latencies in DDR pipeline during DMA.
This avoids Tx buffer underruns and leads to successful usb writes
Signed-off-by: Ramneek Mehresh <ramneek.mehresh(a)freescale.com>
Signed-off-by: Nikhil Badola <nikhil.badola(a)freescale.com>
---
drivers/usb/host/ehci-fsl.c | 20 ++++++++++++++++++++
include/usb/ehci-fsl.h | 7 +++++++
2 files changed, 27 insertions(+)
diff --git a/drivers/usb/host/ehci-fsl.c b/drivers/usb/host/ehci-fsl.c
index 1ca7cf5..991b43b 100644
--- a/drivers/usb/host/ehci-fsl.c
+++ b/drivers/usb/host/ehci-fsl.c
@@ -17,6 +17,8 @@
#include "ehci.h"
+static void set_txfifothresh(struct usb_ehci *, u32);
+
/* Check USB PHY clock valid */
static int usb_phy_clk_valid(struct usb_ehci *ehci)
{
@@ -109,6 +111,10 @@ int ehci_hcd_init(int index, enum usb_init_type init,
in_le32(&ehci->usbmode);
+ if (SVR_SOC_VER(get_svr()) == SVR_T4240 &&
+ IS_SVR_REV(get_svr(), 2, 0))
+ set_txfifothresh(ehci, TXFIFOTHRESH);
+
return 0;
}
@@ -120,3 +126,17 @@ int ehci_hcd_stop(int index)
{
return 0;
}
+
+/*
+ * Setting the value of TXFIFO_THRESH field in TXFILLTUNING register
+ * to counter DDR latencies in writing data into Tx buffer.
+ * This prevents Tx buffer from getting underrun
+ */
+static void set_txfifothresh(struct usb_ehci *ehci, u32 txfifo_thresh)
+{
+ u32 cmd;
+ cmd = ehci_readl(&ehci->txfilltuning);
+ cmd &= ~TXFIFO_THRESH_MASK;
+ cmd |= TXFIFO_THRESH(txfifo_thresh);
+ ehci_writel(&ehci->txfilltuning, cmd);
+}
diff --git a/include/usb/ehci-fsl.h b/include/usb/ehci-fsl.h
index 734305b..c9ee1d5 100644
--- a/include/usb/ehci-fsl.h
+++ b/include/usb/ehci-fsl.h
@@ -164,6 +164,13 @@
#endif
/*
+ * Increasing TX FIFO threshold value from 2 to 4 decreases
+ * data burst rate with which data packets are posted from the TX
+ * latency FIFO to compensate for latencies in DDR pipeline during DMA
+ */
+#define TXFIFOTHRESH 4
+
+/*
* USB Registers
*/
struct usb_ehci {
--
1.7.11.7
2
1
Fix following compile warnings
fsl_esdhc_spl.c: In function 'mmc_boot':
fsl_esdhc_spl.c:35:10: warning: unused variable 'byte_num' [-Wunused-variable]
fsl_esdhc_spl.c:35:7: warning: unused variable 'i' [-Wunused-variable]
fsl_esdhc_spl.c:34:8: warning: unused variable 'val' [-Wunused-variable]
fsl_esdhc_spl.c:33:6: warning: unused variable 'blklen' [-Wunused-variable]
fsl_esdhc_spl.c:105:7: warning: 'tmp_buf' may be used uninitialized in this
function [-Wuninitialized]
Signed-off-by: Prabhakar Kushwaha <prabhakar(a)freescale.com>
---
drivers/mmc/fsl_esdhc_spl.c | 6 +++++-
1 file changed, 5 insertions(+), 1 deletion(-)
diff --git a/drivers/mmc/fsl_esdhc_spl.c b/drivers/mmc/fsl_esdhc_spl.c
index 8fc263f..e0bbf21 100644
--- a/drivers/mmc/fsl_esdhc_spl.c
+++ b/drivers/mmc/fsl_esdhc_spl.c
@@ -29,10 +29,12 @@ void __noreturn mmc_boot(void)
{
__attribute__((noreturn)) void (*uboot)(void);
uint blk_start, blk_cnt, err;
- u32 blklen;
+#ifndef CONFIG_FSL_CORENET
uchar *tmp_buf;
+ u32 blklen;
uchar val;
uint i, byte_num;
+#endif
u32 offset, code_len;
struct mmc *mmc;
@@ -102,7 +104,9 @@ void __noreturn mmc_boot(void)
(uchar *)CONFIG_SYS_MMC_U_BOOT_DST);
if (err != blk_cnt) {
puts("spl: mmc read failed!!\n");
+#ifndef CONFIG_FSL_CORENET
free(tmp_buf);
+#endif
hang();
}
--
1.7.9.5
2
1

[U-Boot] [PATCH] powerpc/t208xqds: fix nor chip selection when nand boot
by Shengzhou Liu 23 Apr '14
by Shengzhou Liu 23 Apr '14
23 Apr '14
NOR flash is on CS1 instead of CS2 when NAND boot.
So correct NOR chip selection to CS1 from CS2.
Signed-off-by: Shengzhou Liu <Shengzhou.Liu(a)freescale.com>
---
include/configs/T208xQDS.h | 28 ++++++++++++++++++----------
1 file changed, 18 insertions(+), 10 deletions(-)
diff --git a/include/configs/T208xQDS.h b/include/configs/T208xQDS.h
index c6d0b06..7c5f57c 100644
--- a/include/configs/T208xQDS.h
+++ b/include/configs/T208xQDS.h
@@ -301,8 +301,16 @@ unsigned long get_board_ddr_clk(void);
#define CONFIG_SYS_CS0_FTIM1 CONFIG_SYS_NAND_FTIM1
#define CONFIG_SYS_CS0_FTIM2 CONFIG_SYS_NAND_FTIM2
#define CONFIG_SYS_CS0_FTIM3 CONFIG_SYS_NAND_FTIM3
-#define CONFIG_SYS_CSPR2_EXT CONFIG_SYS_NOR0_CSPR_EXT
-#define CONFIG_SYS_CSPR2 CONFIG_SYS_NOR0_CSPR
+#define CONFIG_SYS_CSPR1_EXT CONFIG_SYS_NOR0_CSPR_EXT
+#define CONFIG_SYS_CSPR1 CONFIG_SYS_NOR0_CSPR
+#define CONFIG_SYS_AMASK1 CONFIG_SYS_NOR_AMASK
+#define CONFIG_SYS_CSOR1 CONFIG_SYS_NOR_CSOR
+#define CONFIG_SYS_CS1_FTIM0 CONFIG_SYS_NOR_FTIM0
+#define CONFIG_SYS_CS1_FTIM1 CONFIG_SYS_NOR_FTIM1
+#define CONFIG_SYS_CS1_FTIM2 CONFIG_SYS_NOR_FTIM2
+#define CONFIG_SYS_CS1_FTIM3 CONFIG_SYS_NOR_FTIM3
+#define CONFIG_SYS_CSPR2_EXT CONFIG_SYS_NOR1_CSPR_EXT
+#define CONFIG_SYS_CSPR2 CONFIG_SYS_NOR1_CSPR
#define CONFIG_SYS_AMASK2 CONFIG_SYS_NOR_AMASK
#define CONFIG_SYS_CSOR2 CONFIG_SYS_NOR_CSOR
#define CONFIG_SYS_CS2_FTIM0 CONFIG_SYS_NOR_FTIM0
@@ -318,6 +326,14 @@ unsigned long get_board_ddr_clk(void);
#define CONFIG_SYS_CS0_FTIM1 CONFIG_SYS_NOR_FTIM1
#define CONFIG_SYS_CS0_FTIM2 CONFIG_SYS_NOR_FTIM2
#define CONFIG_SYS_CS0_FTIM3 CONFIG_SYS_NOR_FTIM3
+#define CONFIG_SYS_CSPR1_EXT CONFIG_SYS_NOR1_CSPR_EXT
+#define CONFIG_SYS_CSPR1 CONFIG_SYS_NOR1_CSPR
+#define CONFIG_SYS_AMASK1 CONFIG_SYS_NOR_AMASK
+#define CONFIG_SYS_CSOR1 CONFIG_SYS_NOR_CSOR
+#define CONFIG_SYS_CS1_FTIM0 CONFIG_SYS_NOR_FTIM0
+#define CONFIG_SYS_CS1_FTIM1 CONFIG_SYS_NOR_FTIM1
+#define CONFIG_SYS_CS1_FTIM2 CONFIG_SYS_NOR_FTIM2
+#define CONFIG_SYS_CS1_FTIM3 CONFIG_SYS_NOR_FTIM3
#define CONFIG_SYS_CSPR2_EXT CONFIG_SYS_NAND_CSPR_EXT
#define CONFIG_SYS_CSPR2 CONFIG_SYS_NAND_CSPR
#define CONFIG_SYS_AMASK2 CONFIG_SYS_NAND_AMASK
@@ -327,14 +343,6 @@ unsigned long get_board_ddr_clk(void);
#define CONFIG_SYS_CS2_FTIM2 CONFIG_SYS_NAND_FTIM2
#define CONFIG_SYS_CS2_FTIM3 CONFIG_SYS_NAND_FTIM3
#endif
-#define CONFIG_SYS_CSPR1_EXT CONFIG_SYS_NOR1_CSPR_EXT
-#define CONFIG_SYS_CSPR1 CONFIG_SYS_NOR1_CSPR
-#define CONFIG_SYS_AMASK1 CONFIG_SYS_NOR_AMASK
-#define CONFIG_SYS_CSOR1 CONFIG_SYS_NOR_CSOR
-#define CONFIG_SYS_CS1_FTIM0 CONFIG_SYS_NOR_FTIM0
-#define CONFIG_SYS_CS1_FTIM1 CONFIG_SYS_NOR_FTIM1
-#define CONFIG_SYS_CS1_FTIM2 CONFIG_SYS_NOR_FTIM2
-#define CONFIG_SYS_CS1_FTIM3 CONFIG_SYS_NOR_FTIM3
#if defined(CONFIG_RAMBOOT_PBL)
#define CONFIG_SYS_RAMBOOT
--
1.8.0
2
1

[U-Boot] [PATCH][v2] board/b4860qds:Slow MDC clock to comply IEEE specs in PBI config
by Prabhakar Kushwaha 23 Apr '14
by Prabhakar Kushwaha 23 Apr '14
23 Apr '14
The MDC generate by default value of MDIO_CLK_DIV is too high i.e. higher
than 2.5 MHZ. It violates the IEEE specs.
So Slow MDC clock to comply IEEE specs
Signed-off-by: Prabhakar Kushwaha <prabhakar(a)freescale.com>
---
Changes for v2: Update commit message
board/freescale/b4860qds/b4_pbi.cfg | 3 +++
1 file changed, 3 insertions(+)
diff --git a/board/freescale/b4860qds/b4_pbi.cfg b/board/freescale/b4860qds/b4_pbi.cfg
index 57b726e..05377ba 100644
--- a/board/freescale/b4860qds/b4_pbi.cfg
+++ b/board/freescale/b4860qds/b4_pbi.cfg
@@ -22,6 +22,9 @@
09110024 00100008
09110028 00100008
0911002c 00100008
+#slowing down the MDC clock to make it <= 2.5 MHZ
+094fc030 00008148
+094fd030 00008148
#Flush PBL data
09138000 00000000
091380c0 00000000
--
1.7.9.5
2
1
Put a delay of 5 millisecond after reset so that ULPI phy
gets enough time to come out of reset. Erratum A007075 applies
to following SOCs and their variants, if any
P1010 rev 1.0
B4860 rev 1.0, 2.0
P4080 rev 2.0, 3.0
Signed-off-by: Nikhil Badola <nikhil.badola(a)freescale.com>
---
arch/powerpc/cpu/mpc85xx/cmd_errata.c | 4 ++++
arch/powerpc/include/asm/config_mpc85xx.h | 3 +++
arch/powerpc/include/asm/fsl_errata.h | 16 ++++++++++++++++
drivers/usb/host/ehci-fsl.c | 9 +++++++++
4 files changed, 32 insertions(+)
diff --git a/arch/powerpc/cpu/mpc85xx/cmd_errata.c b/arch/powerpc/cpu/mpc85xx/cmd_errata.c
index 7693899..c23707b 100644
--- a/arch/powerpc/cpu/mpc85xx/cmd_errata.c
+++ b/arch/powerpc/cpu/mpc85xx/cmd_errata.c
@@ -260,6 +260,10 @@ static int do_errata(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
#ifdef CONFIG_SYS_FSL_ERRATUM_A005125
puts("Work-around for Erratum A005125 enabled\n");
#endif
+#ifdef CONFIG_SYS_FSL_ERRATUM_A007075
+ if (has_erratum_a007075())
+ puts("Work-around for Erratum A007075 enabled\n");
+#endif
#ifdef CONFIG_SYS_FSL_ERRATUM_I2C_A004447
if ((SVR_SOC_VER(svr) == SVR_8548 && IS_SVR_REV(svr, 3, 1)) ||
(SVR_REV(svr) <= CONFIG_SYS_FSL_A004447_SVR_REV))
diff --git a/arch/powerpc/include/asm/config_mpc85xx.h b/arch/powerpc/include/asm/config_mpc85xx.h
index 56587ae..9d41d3b 100644
--- a/arch/powerpc/include/asm/config_mpc85xx.h
+++ b/arch/powerpc/include/asm/config_mpc85xx.h
@@ -154,6 +154,7 @@
#define CONFIG_SYS_FSL_ERRATUM_IFC_A003399
#define CONFIG_SYS_FSL_ERRATUM_A005125
#define CONFIG_SYS_FSL_ERRATUM_I2C_A004447
+#define CONFIG_SYS_FSL_ERRATUM_A007075
#define CONFIG_SYS_FSL_A004447_SVR_REV 0x10
#define CONFIG_ESDHC_HC_BLK_ADDR
@@ -473,6 +474,7 @@
#define CONFIG_SYS_P4080_ERRATUM_PCIE_A003
#define CONFIG_SYS_FSL_ERRATUM_A005812
#define CONFIG_SYS_FSL_ERRATUM_I2C_A004447
+#define CONFIG_SYS_FSL_ERRATUM_A007075
#define CONFIG_SYS_FSL_A004447_SVR_REV 0x20
#elif defined(CONFIG_PPC_P5020) /* also supports P5010 */
@@ -662,6 +664,7 @@
#define CONFIG_SYS_FSL_ERRATUM_A005871
#define CONFIG_SYS_FSL_ERRATUM_A006379
#define CONFIG_SYS_FSL_ERRATUM_A006593
+#define CONFIG_SYS_FSL_ERRATUM_A007075
#define CONFIG_SYS_CCSRBAR_DEFAULT 0xfe000000
#ifdef CONFIG_PPC_B4860
diff --git a/arch/powerpc/include/asm/fsl_errata.h b/arch/powerpc/include/asm/fsl_errata.h
index a590919..5599680 100644
--- a/arch/powerpc/include/asm/fsl_errata.h
+++ b/arch/powerpc/include/asm/fsl_errata.h
@@ -26,4 +26,20 @@ static inline bool has_erratum_a006379(void)
}
#endif
+static inline bool has_erratum_a007075(void)
+{
+ u32 svr = get_svr();
+ u32 soc = SVR_SOC_VER(svr);
+
+ switch (soc) {
+ case SVR_B4860:
+ case SVR_B4420:
+ return IS_SVR_REV(svr, 1, 0) || IS_SVR_REV(svr, 2, 0);
+ case SVR_P1010:
+ return IS_SVR_REV(svr, 1, 0);
+ case SVR_P4080:
+ return IS_SVR_REV(svr, 2, 0) || IS_SVR_REV(svr, 3, 0);
+ }
+ return false;
+}
#endif
diff --git a/drivers/usb/host/ehci-fsl.c b/drivers/usb/host/ehci-fsl.c
index 45e5d6a..afd61f1 100644
--- a/drivers/usb/host/ehci-fsl.c
+++ b/drivers/usb/host/ehci-fsl.c
@@ -14,6 +14,7 @@
#include <asm/io.h>
#include <usb/ehci-fsl.h>
#include <hwconfig.h>
+#include <asm/fsl_errata.h>
#include "ehci.h"
@@ -46,6 +47,14 @@ int ehci_hcd_init(int index, enum usb_init_type init,
usb_phy[0] = '\0';
#endif
+ if (has_erratum_a007075())
+ /*
+ * A 5ms delay is needed after applying soft-reset to the
+ * controller to let external ULPI phy come out of reset.
+ * This delay needs to be added before re-initializing
+ * the controller after soft-resetting completes
+ */
+ mdelay(5);
switch (index) {
case 0:
--
1.7.11.7
2
1

[U-Boot] [PATCH 1/2] driver/ddr/fsl: Add DDR4 support to Freescale DDR driver
by York Sun 23 Apr '14
by York Sun 23 Apr '14
23 Apr '14
Mostly reusing DDR3 driver, this patch adds DDR4 SPD handling, register
calculation and programming.
Signed-off-by: York Sun <yorksun(a)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
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 */
--
1.7.9.5
1
3

[U-Boot] [PATCH] powerpc/mpc85xx:Update FM1 clock select and shift for B4420
by Prabhakar Kushwaha 23 Apr '14
by Prabhakar Kushwaha 23 Apr '14
23 Apr '14
B4420 is a personality of B4860.
It should have same FM1_CLK_SEK and FM1_CLK_SHIFT as B4860
Signed-off-by: Prabhakar Kushwaha <prabhakar(a)freescale.com>
---
arch/powerpc/cpu/mpc85xx/speed.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/arch/powerpc/cpu/mpc85xx/speed.c b/arch/powerpc/cpu/mpc85xx/speed.c
index 2d6c668..d516d4e 100644
--- a/arch/powerpc/cpu/mpc85xx/speed.c
+++ b/arch/powerpc/cpu/mpc85xx/speed.c
@@ -163,8 +163,8 @@ void get_sys_info(sys_info_t *sys_info)
sys_info->freq_processor[cpu] =
freq_c_pll[cplx_pll] / core_cplx_pll_div[c_pll_sel];
}
-#if defined(CONFIG_PPC_B4860) || defined(CONFIG_PPC_T2080) || \
- defined(CONFIG_PPC_T2081)
+#if defined(CONFIG_PPC_B4860) || defined(CONFIG_PPC_B4420) || \
+ defined(CONFIG_PPC_T2080) || defined(CONFIG_PPC_T2081)
#define FM1_CLK_SEL 0xe0000000
#define FM1_CLK_SHIFT 29
#else
--
1.7.9.5
2
1

[U-Boot] [PATCH] board/t1042rdb_pi: Disable CONFIG_QE and CONFIG_U_QE
by Prabhakar Kushwaha 23 Apr '14
by Prabhakar Kushwaha 23 Apr '14
23 Apr '14
T1042RDB_PI board does not have QE connector.
So disable CONFIG_QE and CONFIG_U_QE for T1042RDB_PI
Signed-off-by: Prabhakar Kushwaha <prabhakar(a)freescale.com>
---
include/configs/T104xRDB.h | 2 ++
1 file changed, 2 insertions(+)
diff --git a/include/configs/T104xRDB.h b/include/configs/T104xRDB.h
index 1f9a255..81b4f31 100644
--- a/include/configs/T104xRDB.h
+++ b/include/configs/T104xRDB.h
@@ -597,8 +597,10 @@
#define CONFIG_SYS_DPAA_FMAN
#define CONFIG_SYS_DPAA_PME
+#ifdef CONFIG_T1040RDB
#define CONFIG_QE
#define CONFIG_U_QE
+#endif
/* Default address of microcode for the Linux Fman driver */
#if defined(CONFIG_SPIFLASH)
--
1.7.9.5
2
1