Skip to contentSkip to conversation

imx: mx6: support LPDDR2 and add mx6slevk spl

PATCH New Peng Fan 3 participants 15 messages Aug 17, 2015

Subsystems (2)
lore
Share & tools
lore

Peng Fan

author
#0 lore raw

cover imx: mx6: support LPDDR2 and add mx6slevk spl

This patch set is to support SPL for mx6slevk board.
But mx6slevk features one LPDDR2 chip. Then we need to first add LPDDR2 SPL support. Also introduce one ddr_type entry to differentiate DDR3 and LPDDR2. This patch set also correct tRFC and tXS for DDR3 4Gb chip.

The LPDDR2 part is implemented referencing MX6SL LPDDR2 Script Aid V0.04.xlsx and JESD209-2E. I am not DDR expert, can not guarantee that this can achieve production quality. Please review.

Patchset tested boot on mx6sxsabresd revb and mx6slevk board.

Peng Fan (9):
imx: mx6: ddr add more register entry for mmdc_p_regs
imx: mx6: ddr no support MMDC1 for i.MX6SL
imx: mx6: ddr correct tRFC and tXS
imx: mx6: ddr add dram io configuration and header file for i.MX6SL
imx: mx6: ddr add mpzqlp2ctl entry
imx: mx6: ddr add an entry ddr_type for mx6_ddr_sysinfo
imx: mx6: ddr init MMDC according to ddr_type
imx: mx6: ddr: add LPDDR2 support
imx: mx6slevk: add SPL support

 arch/arm/cpu/armv7/mx6/Kconfig                    |   1 +
 arch/arm/cpu/armv7/mx6/ddr.c                      | 379 +++++++++++++++++++++-
 arch/arm/include/asm/arch-mx6/mx6-ddr.h           | 135 +++++++-
 arch/arm/include/asm/arch-mx6/mx6sl-ddr.h         |  45 +++
 board/barco/platinum/spl_picon.c                  |   1 +
 board/barco/platinum/spl_titanium.c               |   1 +
 board/freescale/mx6sabresd/mx6sabresd.c           |   1 +
 board/freescale/mx6slevk/mx6slevk.c               | 164 ++++++++++
 board/freescale/mx6sxsabresd/mx6sxsabresd.c       |   1 +
 board/freescale/mx6ul_14x14_evk/mx6ul_14x14_evk.c |   1 +
 board/gateworks/gw_ventana/gw_ventana_spl.c       |   1 +
 board/solidrun/mx6cuboxi/mx6cuboxi.c              |   1 +
 configs/mx6slevk_spl_defconfig                    |   8 +
 include/configs/imx6_spl.h                        |   2 +-
 include/configs/mx6slevk.h                        |   7 +
 15 files changed, 728 insertions(+), 20 deletions(-)
 create mode 100644 arch/arm/include/asm/arch-mx6/mx6sl-ddr.h
 create mode 100644 configs/mx6slevk_spl_defconfig
Signature · 1 line
1.8.4
author
#1 lore raw

PATCH 1/9 imx: mx6: ddr add more register entry for mmdc_p_regs

Add more register entry for MMDC structure.

Cc Stefano Babic <[email protected]>
Cc Tim Harvey <[email protected]>
---
 arch/arm/include/asm/arch-mx6/mx6-ddr.h | 65 ++++++++++++++++++++++++++++-----
 1 file changed, 56 insertions(+), 9 deletions(-)
arch/arm/include/asm/arch-mx6/mx6-ddr.h +56 -9
index 7bfbdc3..f3194da 100644
@@ -40,30 +40,77 @@ struct mmdc_p_regs {
 	u32 res1[2];
 	u32 mdrwd;
 	u32 mdor;
-	u32 res2[3];
+	u32 mdmrr;
+	u32 mdcfg3lp;
+	u32 mdmr4;
 	u32 mdasp;
-	u32 res3[240];
+	u32 res2[239];
+	u32 maarcr;
 	u32 mapsr;
-	u32 res4[254];
+	u32 maexidr0;
+	u32 maexidr1;
+	u32 madpcr0;
+	u32 madpcr1;
+	u32 madpsr0;
+	u32 madpsr1;
+	u32 madpsr2;
+	u32 madpsr3;
+	u32 madpsr4;
+	u32 madpsr5;
+	u32 masbs0;
+	u32 masbs1;
+	u32 res3[2];
+	u32 magenp;
+	u32 res4[239];
 	u32 mpzqhwctrl;
-	u32 res5[2];
+	u32 mpzqswctrl;
+	u32 mpwlgcr;
 	u32 mpwldectrl0;
 	u32 mpwldectrl1;
-	u32 res6;
+	u32 mpwldlst;
 	u32 mpodtctrl;
 	u32 mprddqby0dl;
 	u32 mprddqby1dl;
 	u32 mprddqby2dl;
 	u32 mprddqby3dl;
-	u32 res7[4];
+	u32 mpwrdqby0dl;
+	u32 mpwrdqby1dl;
+	u32 mpwrdqby2dl;
+	u32 mpwrdqby3dl;
 	u32 mpdgctrl0;
 	u32 mpdgctrl1;
-	u32 res8;
+	u32 mpdgdlst0;
 	u32 mprddlctl;
-	u32 res9;
+	u32 mprddlst;
 	u32 mpwrdlctl;
-	u32 res10[25];
+	u32 mpwrdlst;
+	u32 mpsdctrl;
+	u32 mpzqlp2ctl;
+	u32 mprddlhwctl;
+	u32 mpwrdlhwctl;
+	u32 mprddlhwst0;
+	u32 mprddlhwst1;
+	u32 mpwrdlhwst0;
+	u32 mpwrdlhwst1;
+	u32 mpwlhwerr;
+	u32 mpdghwst0;
+	u32 mpdghwst1;
+	u32 mpdghwst2;
+	u32 mpdghwst3;
+	u32 mppdcmpr1;
+	u32 mppdcmpr2;
+	u32 mpswdar0;
+	u32 mpswdrdr0;
+	u32 mpswdrdr1;
+	u32 mpswdrdr2;
+	u32 mpswdrdr3;
+	u32 mpswdrdr4;
+	u32 mpswdrdr5;
+	u32 mpswdrdr6;
+	u32 mpswdrdr7;
 	u32 mpmur0;
+	u32 mpwrcadl;
+	u32 mpdccr;
 };
 
 #define MX6UL_IOM_DDR_BASE	0x020e0200
Signature · 1 line
1.8.4
author
#2 lore raw

PATCH 2/9 imx: mx6: ddr no support MMDC1 for i.MX6SL

In reply to Peng Fan

i.MX 6SoloLite only supports MMDC0, so do not access MMDC1 for i.MX 6SL.

Cc Stefano Babic <[email protected]>
Cc Tim Harvey <[email protected]>
---
 arch/arm/cpu/armv7/mx6/ddr.c | 6 ++++--
 1 file changed, 4 insertions(+), 2 deletions(-)
arch/arm/cpu/armv7/mx6/ddr.c +4 -2
index b808627..28fa3cf 100644
@@ -288,7 +288,8 @@ void mx6sdl_dram_iocfg(unsigned width,
 #define MR(val, ba, cmd, cs1) \
 	((val << 16) | (1 << 15) | (cmd << 4) | (cs1 << 3) | ba)
 #define MMDC1(entry, value) do {					  \
-	if (!is_cpu_type(MXC_CPU_MX6SX) && !is_cpu_type(MXC_CPU_MX6UL))	  \
+	if (!is_cpu_type(MXC_CPU_MX6SX) && !is_cpu_type(MXC_CPU_MX6UL) && \
+	    !is_cpu_type(MXC_CPU_MX6SL))				  \
 		mmdc1->entry = value;					  \
 	} while (0)
 
@@ -312,7 +313,8 @@ void mx6_dram_cfg(const struct mx6_ddr_sysinfo *sysinfo,
 	u16 mem_speed = ddr3_cfg->mem_speed;
 
 	mmdc0 = (struct mmdc_p_regs *)MMDC_P0_BASE_ADDR;
-	if (!is_cpu_type(MXC_CPU_MX6SX) && !is_cpu_type(MXC_CPU_MX6UL))
+	if (!is_cpu_type(MXC_CPU_MX6SX) && !is_cpu_type(MXC_CPU_MX6UL) &&
+	    !is_cpu_type(MXC_CPU_MX6SL))
 		mmdc1 = (struct mmdc_p_regs *)MMDC_P1_BASE_ADDR;
 
 	/* Limit mem_speed for MX6D/MX6Q */
Signature · 1 line
1.8.4
author
#3 lore raw

PATCH 3/9 imx: mx6: ddr correct tRFC and tXS

In reply to Peng Fan

To Chip density 4Gb, tRFC should be 300ns, see
"Table 61 ? Refresh parameters by device density" of JESD79-3E. tXS(min) is max(5nCK, tRFC(min) + 10ns).

Cc Stefano Babic <[email protected]>
Cc Tim Harvey <[email protected]>
---
 arch/arm/cpu/armv7/mx6/ddr.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)
arch/arm/cpu/armv7/mx6/ddr.c +2 -2
index 28fa3cf..3ec3e79 100644
@@ -357,8 +357,8 @@ void mx6_dram_cfg(const struct mx6_ddr_sysinfo *sysinfo,
 		txs = DIV_ROUND_UP(170000, clkper) - 1;
 		break;
 	case 4: /* 4Gb per chip */
-		trfc = DIV_ROUND_UP(260000, clkper) - 1;
-		txs = DIV_ROUND_UP(270000, clkper) - 1;
+		trfc = DIV_ROUND_UP(300000, clkper) - 1;
+		txs = DIV_ROUND_UP(310000, clkper) - 1;
 		break;
 	case 8: /* 8Gb per chip */
 		trfc = DIV_ROUND_UP(350000, clkper) - 1;
Signature · 1 line
1.8.4
author
#4 lore raw

PATCH 4/9 imx: mx6: ddr add dram io configuration and header file for i.MX6SL

In reply to Peng Fan

Define two structure mx6sl_iomux_ddr_regs and mx6sl_iomux_grp_regs. Add a new function mx6sl_dram_iocfg to configure dram io. Add header file to define macros for register address.

Cc Stefano Babic <[email protected]>
---
 arch/arm/cpu/armv7/mx6/ddr.c              | 55 +++++++++++++++++++++++++++++++
 arch/arm/include/asm/arch-mx6/mx6-ddr.h   | 50 ++++++++++++++++++++++++++++
 arch/arm/include/asm/arch-mx6/mx6sl-ddr.h | 45 +++++++++++++++++++++++++
 3 files changed, 150 insertions(+)
 create mode 100644 arch/arm/include/asm/arch-mx6/mx6sl-ddr.h
arch/arm/cpu/armv7/mx6/ddr.c +55 -0
index 3ec3e79..3f23abf 100644
@@ -115,6 +115,61 @@ void mx6ul_dram_iocfg(unsigned width,
 }
 #endif
 
+#if defined(CONFIG_MX6SL)
+void mx6sl_dram_iocfg(unsigned width,
+		      const struct mx6sl_iomux_ddr_regs *ddr,
+		      const struct mx6sl_iomux_grp_regs *grp)
+{
+	struct mx6sl_iomux_ddr_regs *mx6_ddr_iomux;
+	struct mx6sl_iomux_grp_regs *mx6_grp_iomux;
+
+	mx6_ddr_iomux = (struct mx6sl_iomux_ddr_regs *)MX6SL_IOM_DDR_BASE;
+	mx6_grp_iomux = (struct mx6sl_iomux_grp_regs *)MX6SL_IOM_GRP_BASE;
+
+	/* DDR IO TYPE */
+	mx6_grp_iomux->grp_ddr_type = grp->grp_ddr_type;
+	mx6_grp_iomux->grp_ddrpke = grp->grp_ddrpke;
+
+	/* CLOCK */
+	mx6_ddr_iomux->dram_sdclk_0 = ddr->dram_sdclk_0;
+
+	/* ADDRESS */
+	mx6_ddr_iomux->dram_cas = ddr->dram_cas;
+	mx6_ddr_iomux->dram_ras = ddr->dram_ras;
+	mx6_grp_iomux->grp_addds = grp->grp_addds;
+
+	/* Control */
+	mx6_ddr_iomux->dram_reset = ddr->dram_reset;
+	mx6_ddr_iomux->dram_sdba2 = ddr->dram_sdba2;
+	mx6_grp_iomux->grp_ctlds = grp->grp_ctlds;
+
+	/* Data Strobes */
+	mx6_grp_iomux->grp_ddrmode_ctl = grp->grp_ddrmode_ctl;
+	mx6_ddr_iomux->dram_sdqs0 = ddr->dram_sdqs0;
+	mx6_ddr_iomux->dram_sdqs1 = ddr->dram_sdqs1;
+	if (width >= 32) {
+		mx6_ddr_iomux->dram_sdqs2 = ddr->dram_sdqs2;
+		mx6_ddr_iomux->dram_sdqs3 = ddr->dram_sdqs3;
+	}
+
+	/* Data */
+	mx6_grp_iomux->grp_ddrmode = grp->grp_ddrmode;
+	mx6_grp_iomux->grp_b0ds = grp->grp_b0ds;
+	mx6_grp_iomux->grp_b1ds = grp->grp_b1ds;
+	if (width >= 32) {
+		mx6_grp_iomux->grp_b2ds = grp->grp_b2ds;
+		mx6_grp_iomux->grp_b3ds = grp->grp_b3ds;
+	}
+
+	mx6_ddr_iomux->dram_dqm0 = ddr->dram_dqm0;
+	mx6_ddr_iomux->dram_dqm1 = ddr->dram_dqm1;
+	if (width >= 32) {
+		mx6_ddr_iomux->dram_dqm2 = ddr->dram_dqm2;
+		mx6_ddr_iomux->dram_dqm3 = ddr->dram_dqm3;
+	}
+}
+#endif
+
 #if defined(CONFIG_MX6QDL) || defined(CONFIG_MX6Q) || defined(CONFIG_MX6D)
 /* Configure MX6DQ mmdc iomux */
 void mx6dq_dram_iocfg(unsigned width,
arch/arm/include/asm/arch-mx6/mx6-ddr.h +50 -0

69 lines not on this page · raw message

arch/arm/include/asm/arch-mx6/mx6sl-ddr.h new file +45 -0

45 lines not on this page · raw message

Signature · 1 line
1.8.4
author
#5 lore raw

PATCH 5/9 imx: mx6: ddr add mpzqlp2ctl entry

In reply to Peng Fan

Add mpzqlp2ctl entry for mx6_mmdc_calibration.
MMDC_MPZQLP2CTL register is for init tZQINIT, tZQCL, tZQCS for LPDDR2 chips.

Cc Stefano Babic <[email protected]>
Cc Tim Harvey <[email protected]>
---
 arch/arm/include/asm/arch-mx6/mx6-ddr.h | 2 ++
 1 file changed, 2 insertions(+)
arch/arm/include/asm/arch-mx6/mx6-ddr.h +2 -0
index 235a44a..b7bae7b 100644
@@ -414,6 +414,8 @@ struct mx6_mmdc_calibration {
 	/* write delay */
 	u32 p0_mpwrdlctl;
 	u32 p1_mpwrdlctl;
+	/* lpddr2 zq hw calibration */
+	u32 mpzqlp2ctl;
 };
 
 /* configure iomux (pinctl/padctl) */
Signature · 1 line
1.8.4
author
#6 lore raw

PATCH 6/9 imx: mx6: ddr add an entry ddr_type for mx6_ddr_sysinfo

In reply to Peng Fan

Add ddr_type entry for mx6_ddr_sysinfo. It will be used for differenrate DDR3 and LPDDR2.

Cc Stefano Babic <[email protected]>
Cc Tim Harvey <[email protected]>
---
 arch/arm/include/asm/arch-mx6/mx6-ddr.h | 1 +
 1 file changed, 1 insertion(+)
arch/arm/include/asm/arch-mx6/mx6-ddr.h +1 -0
index b7bae7b..49fc9e5 100644
@@ -387,6 +387,7 @@ struct mx6_ddr_sysinfo {
 	u8 rst_to_cke;	/* Time from SDE enable to CKE rise */
 	u8 sde_to_rst;	/* Time from SDE enable until DDR reset# is high */
 	u8 pd_fast_exit;/* enable precharge powerdown fast-exit */
+	u8 ddr_type;	/* DDR type: DDR3(0) or LPDDR2(1) */
 };
 
 /*
Signature · 1 line
1.8.4
author
#7 lore raw

PATCH 7/9 imx: mx6: ddr init MMDC according to ddr_type

In reply to Peng Fan

To i.MX6, DDR3 and LPDDR2 is supported, so rename function mx6_dram_cfg to mx6_ddr3_cfg and the original mx6_dram_cfg function only is a wrapper. The new reimplemented function mx6_dram_cfg only invokes mx6_ddr3_cfg when ddr_type is for DDR3. Later we can use ddr_type to initialize MMDC for LPDDR2.
Initialize ddr_type for different boards which enable SPL.

Cc Stefano Babic <[email protected]>
Cc Tim Harvey <[email protected]>
Cc Stefan Roese <[email protected]>
Cc Fabio Estevam <[email protected]>
---
 arch/arm/cpu/armv7/mx6/ddr.c                      | 14 +++++++++++++-
 arch/arm/include/asm/arch-mx6/mx6-ddr.h           |  2 +-
 board/barco/platinum/spl_picon.c                  |  1 +
 board/barco/platinum/spl_titanium.c               |  1 +
 board/freescale/mx6sabresd/mx6sabresd.c           |  1 +
 board/freescale/mx6sxsabresd/mx6sxsabresd.c       |  1 +
 board/freescale/mx6ul_14x14_evk/mx6ul_14x14_evk.c |  1 +
 board/gateworks/gw_ventana/gw_ventana_spl.c       |  1 +
 board/solidrun/mx6cuboxi/mx6cuboxi.c              |  1 +
 9 files changed, 21 insertions(+), 2 deletions(-)
arch/arm/cpu/armv7/mx6/ddr.c +13 -1
index 3f23abf..a6bef60 100644
@@ -348,7 +348,7 @@ void mx6sdl_dram_iocfg(unsigned width,
 		mmdc1->entry = value;					  \
 	} while (0)
 
-void mx6_dram_cfg(const struct mx6_ddr_sysinfo *sysinfo,
+void mx6_ddr3_cfg(const struct mx6_ddr_sysinfo *sysinfo,
 		  const struct mx6_mmdc_calibration *calib,
 		  const struct mx6_ddr3_cfg *ddr3_cfg)
 {
@@ -655,3 +655,15 @@ void mx6_dram_cfg(const struct mx6_ddr_sysinfo *sysinfo,
 	/* wait for auto-ZQ calibration to complete */
 	mdelay(1);
 }
+
+void mx6_dram_cfg(const struct mx6_ddr_sysinfo *sysinfo,
+		  const struct mx6_mmdc_calibration *calib,
+		  const void *ddr_cfg)
+{
+	if (sysinfo->ddr_type == 0) {
+		mx6_ddr3_cfg(sysinfo, calib, ddr_cfg);
+	} else {
+		puts("Unsupported ddr type\n");
+		hang();
+	}
+}
arch/arm/include/asm/arch-mx6/mx6-ddr.h +1 -1
index 49fc9e5..e3ba140 100644
@@ -439,7 +439,7 @@ void mx6sl_dram_iocfg(unsigned width,
 /* configure mx6 mmdc registers */
 void mx6_dram_cfg(const struct mx6_ddr_sysinfo *,
 		  const struct mx6_mmdc_calibration *,
-		  const struct mx6_ddr3_cfg *);
+		  const void *);
 
 #endif /* CONFIG_SPL_BUILD */
 
board/barco/platinum/spl_picon.c +1 -0
index f421c21..aac0948 100644
@@ -137,6 +137,7 @@ static void spl_dram_init(int width)
 		.bi_on = 1,	/* Bank interleaving enabled */
 		.sde_to_rst = 0x10,	/* 14 cycles, 200us (JEDEC default) */
 		.rst_to_cke = 0x23,	/* 33 cycles, 500us (JEDEC default) */
+		.ddr_type = 0,	/* DDR3 */
 	};
 
 	mx6sdl_dram_iocfg(width, &mx6sdl_ddr_ioregs, &mx6sdl_grp_ioregs);
board/barco/platinum/spl_titanium.c +1 -0
index 26fe26b..6a21155 100644
@@ -140,6 +140,7 @@ static void spl_dram_init(int width)
 		.bi_on = 1,	/* Bank interleaving enabled */
 		.sde_to_rst = 0x10,	/* 14 cycles, 200us (JEDEC default) */
 		.rst_to_cke = 0x23,	/* 33 cycles, 500us (JEDEC default) */
+		.ddr_type = 0,	/* DDR3 */
 	};
 
 	mx6dq_dram_iocfg(width, &mx6dq_ddr_ioregs, &mx6dq_grp_ioregs);
board/freescale/mx6sabresd/mx6sabresd.c +1 -0
index eb8a8b3..fabc5bb 100644
@@ -824,6 +824,7 @@ static void spl_dram_init(void)
 		.bi_on = 1,	/* Bank interleaving enabled */
 		.sde_to_rst = 0x10,	/* 14 cycles, 200us (JEDEC default) */
 		.rst_to_cke = 0x23,	/* 33 cycles, 500us (JEDEC default) */
+		.ddr_type = 0,	/* DDR3 */
 	};
 
 	mx6dq_dram_iocfg(64, &mx6_ddr_ioregs, &mx6_grp_ioregs);
board/freescale/mx6sxsabresd/mx6sxsabresd.c +1 -0
index d58a79a..cf973e7 100644
@@ -566,6 +566,7 @@ static void spl_dram_init(void)
 		.bi_on = 1,		/* Bank interleaving enabled */
 		.sde_to_rst = 0x10,	/* 14 cycles, 200us (JEDEC default) */
 		.rst_to_cke = 0x23,	/* 33 cycles, 500us (JEDEC default) */
+		.ddr_type = 0,		/* DDR3 */
 	};
 
 	mx6sx_dram_iocfg(mem_ddr.width, &mx6_ddr_ioregs, &mx6_grp_ioregs);
board/freescale/mx6ul_14x14_evk/mx6ul_14x14_evk.c +1 -0
index 8f712cb..a978503 100644
@@ -598,6 +598,7 @@ static void spl_dram_init(void)
 		.bi_on = 1,		/* Bank interleaving enabled */
 		.sde_to_rst = 0x10,	/* 14 cycles, 200us (JEDEC default) */
 		.rst_to_cke = 0x23,	/* 33 cycles, 500us (JEDEC default) */
+		.ddr_type = 0,		/* DDR3 */
 	};
 
 	mx6ul_dram_iocfg(mem_ddr.width, &mx6_ddr_ioregs, &mx6_grp_ioregs);
board/gateworks/gw_ventana/gw_ventana_spl.c +1 -0
index d4418e5..57b4f43 100644
@@ -365,6 +365,7 @@ static void spl_dram_init(int width, int size_mb, int board_model)
 		.sde_to_rst = 0x10,	/* 14 cycles, 200us (JEDEC default) */
 		.rst_to_cke = 0x23,	/* 33 cycles, 500us (JEDEC default) */
 		.pd_fast_exit = 1, /* enable precharge power-down fast exit */
+		.ddr_type = 0,	/* DDR3 */
 	};
 
 	/*
board/solidrun/mx6cuboxi/mx6cuboxi.c +1 -0
index 9b1ecf0..b4b290e 100644
@@ -615,6 +615,7 @@ static void spl_dram_init(int width)
 		.bi_on = 1,	/* Bank interleaving enabled */
 		.sde_to_rst = 0x10,	/* 14 cycles, 200us (JEDEC default) */
 		.rst_to_cke = 0x23,	/* 33 cycles, 500us (JEDEC default) */
+		.ddr_type = 0,	/* DDR3 */
 	};
 
 	if (is_cpu_type(MXC_CPU_MX6D) || is_cpu_type(MXC_CPU_MX6Q))
Signature · 1 line
1.8.4
#8 lore raw

PATCH 7/9 imx: mx6: ddr init MMDC according to ddr_type

Quoted 71 lines · Peng Fan

To i.MX6, DDR3 and LPDDR2 is supported, so rename function mx6_dram_cfg to mx6_ddr3_cfg and the original mx6_dram_cfg function only is a wrapper. The new reimplemented function mx6_dram_cfg only invokes mx6_ddr3_cfg when ddr_type is for DDR3. Later we can use ddr_type to initialize MMDC for LPDDR2.
Initialize ddr_type for different boards which enable SPL.

Cc Stefano Babic <[email protected]>
Cc Tim Harvey <[email protected]>
Cc Stefan Roese <[email protected]>
Cc Fabio Estevam <[email protected]>
---
  arch/arm/cpu/armv7/mx6/ddr.c                      | 14 +++++++++++++-
  arch/arm/include/asm/arch-mx6/mx6-ddr.h           |  2 +-
  board/barco/platinum/spl_picon.c                  |  1 +
  board/barco/platinum/spl_titanium.c               |  1 +
  board/freescale/mx6sabresd/mx6sabresd.c           |  1 +
  board/freescale/mx6sxsabresd/mx6sxsabresd.c       |  1 +
  board/freescale/mx6ul_14x14_evk/mx6ul_14x14_evk.c |  1 +
  board/gateworks/gw_ventana/gw_ventana_spl.c       |  1 +
  board/solidrun/mx6cuboxi/mx6cuboxi.c              |  1 +
  9 files changed, 21 insertions(+), 2 deletions(-)
arch/arm/cpu/armv7/mx6/ddr.c +13 -1
index 3f23abf..a6bef60 100644
@@ -348,7 +348,7 @@ void mx6sdl_dram_iocfg(unsigned width,
  		mmdc1->entry = value;					  \
  	} while (0)
 
-void mx6_dram_cfg(const struct mx6_ddr_sysinfo *sysinfo,
+void mx6_ddr3_cfg(const struct mx6_ddr_sysinfo *sysinfo,
  		  const struct mx6_mmdc_calibration *calib,
  		  const struct mx6_ddr3_cfg *ddr3_cfg)
  {
@@ -655,3 +655,15 @@ void mx6_dram_cfg(const struct mx6_ddr_sysinfo *sysinfo,
  	/* wait for auto-ZQ calibration to complete */
  	mdelay(1);
  }
+
+void mx6_dram_cfg(const struct mx6_ddr_sysinfo *sysinfo,
+		  const struct mx6_mmdc_calibration *calib,
+		  const void *ddr_cfg)
+{
+	if (sysinfo->ddr_type == 0) {
+		mx6_ddr3_cfg(sysinfo, calib, ddr_cfg);
+	} else {
+		puts("Unsupported ddr type\n");
+		hang();
+	}
+}
arch/arm/include/asm/arch-mx6/mx6-ddr.h +1 -1
index 49fc9e5..e3ba140 100644
@@ -439,7 +439,7 @@ void mx6sl_dram_iocfg(unsigned width,
  /* configure mx6 mmdc registers */
  void mx6_dram_cfg(const struct mx6_ddr_sysinfo *,
  		  const struct mx6_mmdc_calibration *,
-		  const struct mx6_ddr3_cfg *);
+		  const void *);
 
  #endif /* CONFIG_SPL_BUILD */
 
board/barco/platinum/spl_picon.c +0 -0
index f421c21..aac0948 100644

board/barco/platinum/spl_picon.c static void spl_dram_init(int width) · line 140

Quoted 4 lines
board/barco/platinum/spl_picon.c +1 -0
@@ -137,6 +137,7 @@ static void spl_dram_init(int width)
  		.bi_on = 1,	/* Bank interleaving enabled */
  		.sde_to_rst = 0x10,	/* 14 cycles, 200us (JEDEC default) */
  		.rst_to_cke = 0x23,	/* 33 cycles, 500us (JEDEC default) */
+		.ddr_type = 0,	/* DDR3 */

Perhaps adding an enum here would be better. You could remove the comment then as well.

Other than this:

Thanks,
Stefan

#9 lore raw

PATCH 7/9 imx: mx6: ddr init MMDC according to ddr_type

Quoted 67 lines · Stefan Roese
Quoted 66 lines · Peng Fan

To i.MX6, DDR3 and LPDDR2 is supported, so rename function mx6_dram_cfg to mx6_ddr3_cfg and the original mx6_dram_cfg function only is a wrapper. The new reimplemented function mx6_dram_cfg only invokes mx6_ddr3_cfg when ddr_type is for DDR3. Later we can use ddr_type to initialize MMDC for LPDDR2.
Initialize ddr_type for different boards which enable SPL.

Cc Stefano Babic <[email protected]>
Cc Tim Harvey <[email protected]>
Cc Stefan Roese <[email protected]>
Cc Fabio Estevam <[email protected]>
---
 arch/arm/cpu/armv7/mx6/ddr.c                      | 14 +++++++++++++-
 arch/arm/include/asm/arch-mx6/mx6-ddr.h           |  2 +-
 board/barco/platinum/spl_picon.c                  |  1 +
 board/barco/platinum/spl_titanium.c               |  1 +
 board/freescale/mx6sabresd/mx6sabresd.c           |  1 +
 board/freescale/mx6sxsabresd/mx6sxsabresd.c       |  1 +
 board/freescale/mx6ul_14x14_evk/mx6ul_14x14_evk.c |  1 +
 board/gateworks/gw_ventana/gw_ventana_spl.c       |  1 +
 board/solidrun/mx6cuboxi/mx6cuboxi.c              |  1 +
 9 files changed, 21 insertions(+), 2 deletions(-)
arch/arm/cpu/armv7/mx6/ddr.c +13 -1
index 3f23abf..a6bef60 100644
@@ -348,7 +348,7 @@ void mx6sdl_dram_iocfg(unsigned width,
 		mmdc1->entry = value;					  \
 	} while (0)
 
-void mx6_dram_cfg(const struct mx6_ddr_sysinfo *sysinfo,
+void mx6_ddr3_cfg(const struct mx6_ddr_sysinfo *sysinfo,
 		  const struct mx6_mmdc_calibration *calib,
 		  const struct mx6_ddr3_cfg *ddr3_cfg)
 {
@@ -655,3 +655,15 @@ void mx6_dram_cfg(const struct mx6_ddr_sysinfo *sysinfo,
 	/* wait for auto-ZQ calibration to complete */
 	mdelay(1);
 }
+
+void mx6_dram_cfg(const struct mx6_ddr_sysinfo *sysinfo,
+		  const struct mx6_mmdc_calibration *calib,
+		  const void *ddr_cfg)
+{
+	if (sysinfo->ddr_type == 0) {
+		mx6_ddr3_cfg(sysinfo, calib, ddr_cfg);
+	} else {
+		puts("Unsupported ddr type\n");
+		hang();
+	}
+}
arch/arm/include/asm/arch-mx6/mx6-ddr.h +1 -1
index 49fc9e5..e3ba140 100644
@@ -439,7 +439,7 @@ void mx6sl_dram_iocfg(unsigned width,
 /* configure mx6 mmdc registers */
 void mx6_dram_cfg(const struct mx6_ddr_sysinfo *,
 		  const struct mx6_mmdc_calibration *,
-		  const struct mx6_ddr3_cfg *);
+		  const void *);
 
 #endif /* CONFIG_SPL_BUILD */
 
Quoted 10 lines

board/barco/platinum/spl_picon.c static void spl_dram_init(int width) · line 140

Quoted 9 lines
board/barco/platinum/spl_picon.c +1 -0
index f421c21..aac0948 100644
@@ -137,6 +137,7 @@ static void spl_dram_init(int width)
 		.bi_on = 1,	/* Bank interleaving enabled */
 		.sde_to_rst = 0x10,	/* 14 cycles, 200us (JEDEC default) */
 		.rst_to_cke = 0x23,	/* 33 cycles, 500us (JEDEC default) */
+		.ddr_type = 0,	/* DDR3 */

Seems my patches are not posted to uboot mailist successfully.

Quoted 6 lines

Perhaps adding an enum here would be better. You could remove the comment then as well.

Other than this:

Will add your tag, and repost patch set to uboot mailist.

Quoted 4 lines

Thanks,
Stefan

Regards,
Peng.

#10 lore raw

PATCH 7/9 imx: mx6: ddr init MMDC according to ddr_type

Quoted 79 lines · Peng Fan
Quoted 67 lines · Stefan Roese
Quoted 66 lines · Peng Fan

To i.MX6, DDR3 and LPDDR2 is supported, so rename function mx6_dram_cfg to mx6_ddr3_cfg and the original mx6_dram_cfg function only is a wrapper. The new reimplemented function mx6_dram_cfg only invokes mx6_ddr3_cfg when ddr_type is for DDR3. Later we can use ddr_type to initialize MMDC for LPDDR2.
Initialize ddr_type for different boards which enable SPL.

Cc Stefano Babic <[email protected]>
Cc Tim Harvey <[email protected]>
Cc Stefan Roese <[email protected]>
Cc Fabio Estevam <[email protected]>
---
  arch/arm/cpu/armv7/mx6/ddr.c                      | 14 +++++++++++++-
  arch/arm/include/asm/arch-mx6/mx6-ddr.h           |  2 +-
  board/barco/platinum/spl_picon.c                  |  1 +
  board/barco/platinum/spl_titanium.c               |  1 +
  board/freescale/mx6sabresd/mx6sabresd.c           |  1 +
  board/freescale/mx6sxsabresd/mx6sxsabresd.c       |  1 +
  board/freescale/mx6ul_14x14_evk/mx6ul_14x14_evk.c |  1 +
  board/gateworks/gw_ventana/gw_ventana_spl.c       |  1 +
  board/solidrun/mx6cuboxi/mx6cuboxi.c              |  1 +
  9 files changed, 21 insertions(+), 2 deletions(-)
arch/arm/cpu/armv7/mx6/ddr.c +13 -1
index 3f23abf..a6bef60 100644
@@ -348,7 +348,7 @@ void mx6sdl_dram_iocfg(unsigned width,
  		mmdc1->entry = value;					  \
  	} while (0)
 
-void mx6_dram_cfg(const struct mx6_ddr_sysinfo *sysinfo,
+void mx6_ddr3_cfg(const struct mx6_ddr_sysinfo *sysinfo,
  		  const struct mx6_mmdc_calibration *calib,
  		  const struct mx6_ddr3_cfg *ddr3_cfg)
  {
@@ -655,3 +655,15 @@ void mx6_dram_cfg(const struct mx6_ddr_sysinfo *sysinfo,
  	/* wait for auto-ZQ calibration to complete */
  	mdelay(1);
  }
+
+void mx6_dram_cfg(const struct mx6_ddr_sysinfo *sysinfo,
+		  const struct mx6_mmdc_calibration *calib,
+		  const void *ddr_cfg)
+{
+	if (sysinfo->ddr_type == 0) {
+		mx6_ddr3_cfg(sysinfo, calib, ddr_cfg);
+	} else {
+		puts("Unsupported ddr type\n");
+		hang();
+	}
+}
arch/arm/include/asm/arch-mx6/mx6-ddr.h +1 -1
index 49fc9e5..e3ba140 100644
@@ -439,7 +439,7 @@ void mx6sl_dram_iocfg(unsigned width,
  /* configure mx6 mmdc registers */
  void mx6_dram_cfg(const struct mx6_ddr_sysinfo *,
  		  const struct mx6_mmdc_calibration *,
-		  const struct mx6_ddr3_cfg *);
+		  const void *);
 
  #endif /* CONFIG_SPL_BUILD */
 
Quoted 10 lines

board/barco/platinum/spl_picon.c static void spl_dram_init(int width) · line 140

Quoted 9 lines
board/barco/platinum/spl_picon.c +1 -0
index f421c21..aac0948 100644
@@ -137,6 +137,7 @@ static void spl_dram_init(int width)
  		.bi_on = 1,	/* Bank interleaving enabled */
  		.sde_to_rst = 0x10,	/* 14 cycles, 200us (JEDEC default) */
  		.rst_to_cke = 0x23,	/* 33 cycles, 500us (JEDEC default) */
+		.ddr_type = 0,	/* DDR3 */
Quoted 1 line

Seems my patches are not posted to uboot mailist successfully.

The list was stuck over the weekend. Please wait a bit. The messages start to arrive now.

Quoted 8 lines
Quoted 6 lines

Perhaps adding an enum here would be better. You could remove the comment then as well.

Other than this:

Will add your tag, and repost patch set to uboot mailist.

And please add the enum as well.

Thanks,
Stefan

#11 lore raw

PATCH 7/9 imx: mx6: ddr init MMDC according to ddr_type

Quoted 80 lines · Stefan Roese
Quoted 79 lines · Peng Fan
Quoted 77 lines · Stefan Roese
Quoted 75 lines · Peng Fan

To i.MX6, DDR3 and LPDDR2 is supported, so rename function mx6_dram_cfg to mx6_ddr3_cfg and the original mx6_dram_cfg function only is a wrapper. The new reimplemented function mx6_dram_cfg only invokes mx6_ddr3_cfg when ddr_type is for DDR3. Later we can use ddr_type to initialize MMDC for LPDDR2.
Initialize ddr_type for different boards which enable SPL.

Cc Stefano Babic <[email protected]>
Cc Tim Harvey <[email protected]>
Cc Stefan Roese <[email protected]>
Cc Fabio Estevam <[email protected]>
---
 arch/arm/cpu/armv7/mx6/ddr.c                      | 14 +++++++++++++-
 arch/arm/include/asm/arch-mx6/mx6-ddr.h           |  2 +-
 board/barco/platinum/spl_picon.c                  |  1 +
 board/barco/platinum/spl_titanium.c               |  1 +
 board/freescale/mx6sabresd/mx6sabresd.c           |  1 +
 board/freescale/mx6sxsabresd/mx6sxsabresd.c       |  1 +
 board/freescale/mx6ul_14x14_evk/mx6ul_14x14_evk.c |  1 +
 board/gateworks/gw_ventana/gw_ventana_spl.c       |  1 +
 board/solidrun/mx6cuboxi/mx6cuboxi.c              |  1 +
 9 files changed, 21 insertions(+), 2 deletions(-)
arch/arm/cpu/armv7/mx6/ddr.c +13 -1
index 3f23abf..a6bef60 100644
@@ -348,7 +348,7 @@ void mx6sdl_dram_iocfg(unsigned width,
 		mmdc1->entry = value;					  \
 	} while (0)
 
-void mx6_dram_cfg(const struct mx6_ddr_sysinfo *sysinfo,
+void mx6_ddr3_cfg(const struct mx6_ddr_sysinfo *sysinfo,
 		  const struct mx6_mmdc_calibration *calib,
 		  const struct mx6_ddr3_cfg *ddr3_cfg)
 {
@@ -655,3 +655,15 @@ void mx6_dram_cfg(const struct mx6_ddr_sysinfo *sysinfo,
 	/* wait for auto-ZQ calibration to complete */
 	mdelay(1);
 }
+
+void mx6_dram_cfg(const struct mx6_ddr_sysinfo *sysinfo,
+		  const struct mx6_mmdc_calibration *calib,
+		  const void *ddr_cfg)
+{
+	if (sysinfo->ddr_type == 0) {
+		mx6_ddr3_cfg(sysinfo, calib, ddr_cfg);
+	} else {
+		puts("Unsupported ddr type\n");
+		hang();
+	}
+}
arch/arm/include/asm/arch-mx6/mx6-ddr.h +1 -1
index 49fc9e5..e3ba140 100644
@@ -439,7 +439,7 @@ void mx6sl_dram_iocfg(unsigned width,
 /* configure mx6 mmdc registers */
 void mx6_dram_cfg(const struct mx6_ddr_sysinfo *,
 		  const struct mx6_mmdc_calibration *,
-		  const struct mx6_ddr3_cfg *);
+		  const void *);
 
 #endif /* CONFIG_SPL_BUILD */
 
board/barco/platinum/spl_picon.c +1 -0
index f421c21..aac0948 100644
@@ -137,6 +137,7 @@ static void spl_dram_init(int width)
 		.bi_on = 1,	/* Bank interleaving enabled */
 		.sde_to_rst = 0x10,	/* 14 cycles, 200us (JEDEC default) */
 		.rst_to_cke = 0x23,	/* 33 cycles, 500us (JEDEC default) */
+		.ddr_type = 0,	/* DDR3 */
Quoted 4 lines
Quoted 1 line

Seems my patches are not posted to uboot mailist successfully.

The list was stuck over the weekend. Please wait a bit. The messages start to arrive now.

Seems my patch are dropped, not sure :(

Quoted 11 lines
Quoted 9 lines
Quoted 7 lines

Perhaps adding an enum here would be better. You could remove the comment then as well.

Other than this:

Will add your tag, and repost patch set to uboot mailist.

And please add the enum as well.

How about using macros? saying "#define MX6_DDR3 0" and "#define MX6_LPDDR2 1"?

Quoted 4 lines

Thanks,
Stefan

Regards,
Peng.

#12 lore raw

PATCH 7/9 imx: mx6: ddr init MMDC according to ddr_type

Quoted 94 lines · Peng Fan
Quoted 80 lines · Stefan Roese
Quoted 79 lines · Peng Fan
Quoted 77 lines · Stefan Roese
Quoted 75 lines · Peng Fan

To i.MX6, DDR3 and LPDDR2 is supported, so rename function mx6_dram_cfg to mx6_ddr3_cfg and the original mx6_dram_cfg function only is a wrapper. The new reimplemented function mx6_dram_cfg only invokes mx6_ddr3_cfg when ddr_type is for DDR3. Later we can use ddr_type to initialize MMDC for LPDDR2.
Initialize ddr_type for different boards which enable SPL.

Cc Stefano Babic <[email protected]>
Cc Tim Harvey <[email protected]>
Cc Stefan Roese <[email protected]>
Cc Fabio Estevam <[email protected]>
---
  arch/arm/cpu/armv7/mx6/ddr.c                      | 14 +++++++++++++-
  arch/arm/include/asm/arch-mx6/mx6-ddr.h           |  2 +-
  board/barco/platinum/spl_picon.c                  |  1 +
  board/barco/platinum/spl_titanium.c               |  1 +
  board/freescale/mx6sabresd/mx6sabresd.c           |  1 +
  board/freescale/mx6sxsabresd/mx6sxsabresd.c       |  1 +
  board/freescale/mx6ul_14x14_evk/mx6ul_14x14_evk.c |  1 +
  board/gateworks/gw_ventana/gw_ventana_spl.c       |  1 +
  board/solidrun/mx6cuboxi/mx6cuboxi.c              |  1 +
  9 files changed, 21 insertions(+), 2 deletions(-)
arch/arm/cpu/armv7/mx6/ddr.c +13 -1
index 3f23abf..a6bef60 100644
@@ -348,7 +348,7 @@ void mx6sdl_dram_iocfg(unsigned width,
  		mmdc1->entry = value;					  \
  	} while (0)
 
-void mx6_dram_cfg(const struct mx6_ddr_sysinfo *sysinfo,
+void mx6_ddr3_cfg(const struct mx6_ddr_sysinfo *sysinfo,
  		  const struct mx6_mmdc_calibration *calib,
  		  const struct mx6_ddr3_cfg *ddr3_cfg)
  {
@@ -655,3 +655,15 @@ void mx6_dram_cfg(const struct mx6_ddr_sysinfo *sysinfo,
  	/* wait for auto-ZQ calibration to complete */
  	mdelay(1);
  }
+
+void mx6_dram_cfg(const struct mx6_ddr_sysinfo *sysinfo,
+		  const struct mx6_mmdc_calibration *calib,
+		  const void *ddr_cfg)
+{
+	if (sysinfo->ddr_type == 0) {
+		mx6_ddr3_cfg(sysinfo, calib, ddr_cfg);
+	} else {
+		puts("Unsupported ddr type\n");
+		hang();
+	}
+}
arch/arm/include/asm/arch-mx6/mx6-ddr.h +1 -1
index 49fc9e5..e3ba140 100644
@@ -439,7 +439,7 @@ void mx6sl_dram_iocfg(unsigned width,
  /* configure mx6 mmdc registers */
  void mx6_dram_cfg(const struct mx6_ddr_sysinfo *,
  		  const struct mx6_mmdc_calibration *,
-		  const struct mx6_ddr3_cfg *);
+		  const void *);
 
  #endif /* CONFIG_SPL_BUILD */
 
board/barco/platinum/spl_picon.c +1 -0
index f421c21..aac0948 100644
@@ -137,6 +137,7 @@ static void spl_dram_init(int width)
  		.bi_on = 1,	/* Bank interleaving enabled */
  		.sde_to_rst = 0x10,	/* 14 cycles, 200us (JEDEC default) */
  		.rst_to_cke = 0x23,	/* 33 cycles, 500us (JEDEC default) */
+		.ddr_type = 0,	/* DDR3 */
Quoted 4 lines
Quoted 1 line

Seems my patches are not posted to uboot mailist successfully.

The list was stuck over the weekend. Please wait a bit. The messages start to arrive now.

Seems my patch are dropped, not sure :(

Quoted 6 lines
Quoted 6 lines
Quoted 6 lines

Perhaps adding an enum here would be better. You could remove the comment then as well.

Other than this:

Quoted 7 lines
Quoted 5 lines
Quoted 3 lines
Quoted 1 line

Will add your tag, and repost patch set to uboot mailist.

And please add the enum as well.

How about using macros? saying "#define MX6_DDR3 0" and "#define MX6_LPDDR2 1"?

I think enums are here more appropriate. As we don't really care about the value. So something like this:

enum {
         DDR_TYPE_DDR3,
         DDR_TYPE_LPDDR2,
	...
};

Thanks,
Stefan

author
#13 lore raw

PATCH 8/9 imx: mx6: ddr: add LPDDR2 support

In reply to Peng Fan

Add LPDDR2 support:
1. Implement a function mx6_lpddr2_cfg to initialize MMDC for LPDDR2.
2. Introduce a structure mx6_lpddr2_cfg, most entrys are same to mx6_ddr3_cfg, but still keep it a single one for easy to choose parameters for LPDDR2.
3. If ddr_type is LPDDR2, use mx6_lpddr2_cfg to init MMDC.
4. Update comments.

Cc Stefano Babic <[email protected]>
Cc Tim Harvey <[email protected]>
---
 arch/arm/cpu/armv7/mx6/ddr.c            | 300 +++++++++++++++++++++++++++++++-
 arch/arm/include/asm/arch-mx6/mx6-ddr.h |  15 ++
 2 files changed, 311 insertions(+), 4 deletions(-)
arch/arm/cpu/armv7/mx6/ddr.c +296 -4
index a6bef60..1e78b9c 100644
@@ -7,6 +7,7 @@
 
 #include <common.h>
 #include <linux/types.h>
+#include <asm/arch/clock.h>
 #include <asm/arch/mx6-ddr.h>
 #include <asm/arch/sys_proto.h>
 #include <asm/io.h>
@@ -330,15 +331,20 @@ void mx6sdl_dram_iocfg(unsigned width,
  * Configure mx6 mmdc registers based on:
  *  - board-specific memory configuration
  *  - board-specific calibration data
- *  - ddr3 chip details
+ *  - ddr3/lpddr2 chip details
  *
  * The various calculations here are derived from the Freescale
- * i.Mx6DQSDL DDR3 Script Aid spreadsheet (DOC-94917) designed to generate MMDC
- * configuration registers based on memory system and memory chip parameters.
+ * 1. i.Mx6DQSDL DDR3 Script Aid spreadsheet (DOC-94917) designed to generate
+ *    MMDC configuration registers based on memory system and memory chip
+ *    parameters.
+ *
+ * 2. i.Mx6SL LPDDR2 Script Aid spreadsheet V0.04 designed to generate MMDC
+ *    configuration registers based on memory system and memory chip
+ *    parameters.
  *
  * The defaults here are those which were specified in the spreadsheet.
  * For details on each register, refer to the IMX6DQRM and/or IMX6SDLRM
- * section titled MMDC initialization
+ * and/or IMX6SLRM section titled MMDC initialization.
  */
 #define MR(val, ba, cmd, cs1) \
 	((val << 16) | (1 << 15) | (cmd << 4) | (cs1 << 3) | ba)
@@ -348,6 +354,290 @@ void mx6sdl_dram_iocfg(unsigned width,
 		mmdc1->entry = value;					  \
 	} while (0)
 
+/*
+ * According JESD209-2B-LPDDR2: Table 103
+ * WL: write latency
+ */
+static int lpddr2_wl(uint32_t mem_speed)
+{
+	switch (mem_speed) {
+	case 1066:
+	case 933:
+		return 4;
+	case 800:
+		return 3;
+	case 677:
+	case 533:
+		return 2;
+	case 400:
+	case 333:
+		return 1;
+	default:
+		puts("invalid memory speed\n");
+		hang();
+	}
+
+	return 0;
+}
+
+/*
+ * According JESD209-2B-LPDDR2: Table 103
+ * RL: read latency
+ */
+static int lpddr2_rl(uint32_t mem_speed)
+{
+	switch (mem_speed) {
+	case 1066:
+		return 8;
+	case 933:
+		return 7;
+	case 800:
+		return 6;
+	case 677:
+		return 5;
+	case 533:
+		return 4;
+	case 400:
+	case 333:
+		return 3;
+	default:
+		puts("invalid memory speed\n");
+		hang();
+	}
+
+	return 0;
+}
+
+void mx6_lpddr2_cfg(const struct mx6_ddr_sysinfo *sysinfo,
+		    const struct mx6_mmdc_calibration *calib,
+		    const struct mx6_lpddr2_cfg *lpddr2_cfg)
+{
+	volatile struct mmdc_p_regs *mmdc0;
+	u32 val;
+	u8 tcke, tcksrx, tcksre, trrd;
+	u8 twl, txp, tfaw, tcl;
+	u16 tras, twr, tmrd, trtp, twtr, trfc, txsr;
+	u16 trcd_lp, trppb_lp, trpab_lp, trc_lp;
+	u16 cs0_end;
+	u8 coladdr;
+	int clkper; /* clock period in picoseconds */
+	int clock;  /* clock freq in mHz */
+	int cs;
+
+	/* only support 16/32 bits */
+	if (sysinfo->dsize > 1)
+		hang();
+
+	mmdc0 = (struct mmdc_p_regs *)MMDC_P0_BASE_ADDR;
+
+	clock = mxc_get_clock(MXC_DDR_CLK) / 1000000U;
+	clkper = (1000 * 1000) / clock; /* pico seconds */
+
+	twl = lpddr2_wl(lpddr2_cfg->mem_speed) - 1;
+
+	/* LPDDR2-S2 and LPDDR2-S4 have the same tRFC value. */
+	switch (lpddr2_cfg->density) {
+	case 1:
+	case 2:
+	case 4:
+		trfc = DIV_ROUND_UP(130000, clkper) - 1;
+		txsr = DIV_ROUND_UP(140000, clkper) - 1;
+		break;
+	case 8:
+		trfc = DIV_ROUND_UP(210000, clkper) - 1;
+		txsr = DIV_ROUND_UP(220000, clkper) - 1;
+		break;
+	default:
+		/*
+		 * 64Mb, 128Mb, 256Mb, 512Mb are not supported currently.
+		 */
+		hang();
+		break;
+	}
+	/*
+	 * txpdll, txpr, taonpd and taofpd are not relevant in LPDDR2 mode,
+	 * set them to 0. */
+	txp = DIV_ROUND_UP(7500, clkper) - 1;
+	tcke = 3;
+	if (lpddr2_cfg->mem_speed == 333)
+		tfaw = DIV_ROUND_UP(60000, clkper) - 1;
+	else
+		tfaw = DIV_ROUND_UP(50000, clkper) - 1;
+	trrd = DIV_ROUND_UP(10000, clkper) - 1;
+
+	/* tckesr for LPDDR2 */
+	tcksre = DIV_ROUND_UP(15000, clkper);
+	tcksrx = tcksre;
+	twr  = DIV_ROUND_UP(15000, clkper) - 1;
+	/*
+	 * tMRR: 2, tMRW: 5
+	 * tMRD should be set to max(tMRR, tMRW)
+	 */
+	tmrd = 5;
+	tras = DIV_ROUND_UP(lpddr2_cfg->trasmin, clkper / 10) - 1;
+	/* LPDDR2 mode use tRCD_LP filed in MDCFG3. */
+	trcd_lp = DIV_ROUND_UP(lpddr2_cfg->trcd_lp, clkper / 10) - 1;
+	trc_lp = DIV_ROUND_UP(lpddr2_cfg->trasmin + lpddr2_cfg->trppb_lp,
+			      clkper / 10) - 1;
+	trppb_lp = DIV_ROUND_UP(lpddr2_cfg->trppb_lp, clkper / 10) - 1;
+	trpab_lp = DIV_ROUND_UP(lpddr2_cfg->trpab_lp, clkper / 10) - 1;
+	/* To LPDDR2, CL in MDCFG0 refers to RL */
+	tcl = lpddr2_rl(lpddr2_cfg->mem_speed) - 3;
+	twtr = DIV_ROUND_UP(7500, clkper) - 1;
+	trtp = DIV_ROUND_UP(7500, clkper) - 1;
+
+	cs0_end = 4 * sysinfo->cs_density - 1;
+
+	debug("density:%d Gb (%d Gb per chip)\n",
+	      sysinfo->cs_density, lpddr2_cfg->density);
+	debug("clock: %dMHz (%d ps)\n", clock, clkper);
+	debug("memspd:%d\n", lpddr2_cfg->mem_speed);
+	debug("trcd_lp=%d\n", trcd_lp);
+	debug("trppb_lp=%d\n", trppb_lp);
+	debug("trpab_lp=%d\n", trpab_lp);
+	debug("trc_lp=%d\n", trc_lp);
+	debug("tcke=%d\n", tcke);
+	debug("tcksrx=%d\n", tcksrx);
+	debug("tcksre=%d\n", tcksre);
+	debug("trfc=%d\n", trfc);
+	debug("txsr=%d\n", txsr);
+	debug("txp=%d\n", txp);
+	debug("tfaw=%d\n", tfaw);
+	debug("tcl=%d\n", tcl);
+	debug("tras=%d\n", tras);
+	debug("twr=%d\n", twr);
+	debug("tmrd=%d\n", tmrd);
+	debug("twl=%d\n", twl);
+	debug("trtp=%d\n", trtp);
+	debug("twtr=%d\n", twtr);
+	debug("trrd=%d\n", trrd);
+	debug("cs0_end=%d\n", cs0_end);
+	debug("ncs=%d\n", sysinfo->ncs);
+
+	/*
+	 * board-specific configuration:
+	 *  These values are determined empirically and vary per board layout
+	 */
+	mmdc0->mpwldectrl0 = calib->p0_mpwldectrl0;
+	mmdc0->mpwldectrl1 = calib->p0_mpwldectrl1;
+	mmdc0->mpdgctrl0 = calib->p0_mpdgctrl0;
+	mmdc0->mpdgctrl1 = calib->p0_mpdgctrl1;
+	mmdc0->mprddlctl = calib->p0_mprddlctl;
+	mmdc0->mpwrdlctl = calib->p0_mpwrdlctl;
+	mmdc0->mpzqlp2ctl = calib->mpzqlp2ctl;
+
+	/* Read data DQ Byte0-3 delay */
+	mmdc0->mprddqby0dl = 0x33333333;
+	mmdc0->mprddqby1dl = 0x33333333;
+	if (sysinfo->dsize > 0) {
+		mmdc0->mprddqby2dl = 0x33333333;
+		mmdc0->mprddqby3dl = 0x33333333;
+	}
+
+	/* Write data DQ Byte0-3 delay */
+	mmdc0->mpwrdqby0dl = 0xf3333333;
+	mmdc0->mpwrdqby1dl = 0xf3333333;
+	if (sysinfo->dsize > 0) {
+		mmdc0->mpwrdqby2dl = 0xf3333333;
+		mmdc0->mpwrdqby3dl = 0xf3333333;
+	}
+
+	/*
+	 * In LPDDR2 mode this register should be cleared,
+	 * so no termination will be activated.
+	 */
+	mmdc0->mpodtctrl = 0;
+
+	/* complete calibration */
+	val = (1 << 11); /* Force measurement on delay-lines */
+	mmdc0->mpmur0 = val;
+
+	/* Step 1: configuration request */
+	mmdc0->mdscr = (u32)(1 << 15); /* config request */
+
+	/* Step 2: Timing configuration */
+	mmdc0->mdcfg0 = (trfc << 24) | (txsr << 16) | (txp << 13) |
+			(tfaw << 4) | tcl;
+	mmdc0->mdcfg1 = (tras << 16) | (twr << 9) | (tmrd << 5) | twl;
+	mmdc0->mdcfg2 = (trtp << 6) | (twtr << 3) | trrd;
+	mmdc0->mdcfg3lp = (trc_lp << 16) | (trcd_lp << 8) |
+			  (trppb_lp << 4) | trpab_lp;
+	mmdc0->mdotc = 0;
+
+	mmdc0->mdasp = cs0_end; /* CS addressing */
+
+	/* Step 3: Configure DDR type */
+	mmdc0->mdmisc = (sysinfo->cs1_mirror << 19) | (sysinfo->walat << 16) |
+			(sysinfo->bi_on << 12) | (sysinfo->mif3_mode << 9) |
+			(sysinfo->ralat << 6) | (1 << 3);
+
+	/* Step 4: Configure delay while leaving reset */
+	mmdc0->mdor = (sysinfo->sde_to_rst << 8) |
+		      (sysinfo->rst_to_cke << 0);
+
+	/* Step 5: Configure DDR physical parameters (density and burst len) */
+	coladdr = lpddr2_cfg->coladdr;
+	if (lpddr2_cfg->coladdr == 8)		/* 8-bit COL is 0x3 */
+		coladdr += 4;
+	else if (lpddr2_cfg->coladdr == 12)	/* 12-bit COL is 0x4 */
+		coladdr += 1;
+	mmdc0->mdctl =  (lpddr2_cfg->rowaddr - 11) << 24 |	/* ROW */
+			(coladdr - 9) << 20 |			/* COL */
+			(0 << 19) |	/* Burst Length = 4 for LPDDR2 */
+			(sysinfo->dsize << 16);	/* DDR data bus size */
+
+	/* Step 6: Perform ZQ calibration */
+	val = 0xa1390003; /* one-time HW ZQ calib */
+	mmdc0->mpzqhwctrl = val;
+
+	/* Step 7: Enable MMDC with desired chip select */
+	mmdc0->mdctl |= (1 << 31) |			     /* SDE_0 for CS0 */
+			((sysinfo->ncs == 2) ? 1 : 0) << 30; /* SDE_1 for CS1 */
+
+	/* Step 8: Write Mode Registers to Init LPDDR2 devices */
+	for (cs = 0; cs < sysinfo->ncs; cs++) {
+		/* MR63: reset */
+		mmdc0->mdscr = MR(63, 0, 3, cs);
+		/* MR10: calibration,
+		 * 0xff is calibration command after intilization.
+		 */
+		val = 0xA | (0xff << 8);
+		mmdc0->mdscr = MR(val, 0, 3, cs);
+		/* MR1 */
+		val = 0x1 | (0x82 << 8);
+		mmdc0->mdscr = MR(val, 0, 3, cs);
+		/* MR2 */
+		val = 0x2 | (0x04 << 8);
+		mmdc0->mdscr = MR(val, 0, 3, cs);
+		/* MR3 */
+		val = 0x3 | (0x02 << 8);
+		mmdc0->mdscr = MR(val, 0, 3, cs);
+	}
+
+	/* Step 10: Power down control and self-refresh */
+	mmdc0->mdpdc = (tcke & 0x7) << 16 |
+			5            << 12 |  /* PWDT_1: 256 cycles */
+			5            <<  8 |  /* PWDT_0: 256 cycles */
+			1            <<  6 |  /* BOTH_CS_PD */
+			(tcksrx & 0x7) << 3 |
+			(tcksre & 0x7);
+	mmdc0->mapsr = 0x00001006; /* ADOPT power down enabled */
+
+	/* Step 11: Configure ZQ calibration: one-time and periodic 1ms */
+	val = 0xa1310003;
+	mmdc0->mpzqhwctrl = val;
+
+	/* Step 12: Configure and activate periodic refresh */
+	mmdc0->mdref = (0 << 14) | /* REF_SEL: Periodic refresh cycle: 64kHz */
+		       (3 << 11);  /* REFR: Refresh Rate - 4 refreshes */
+
+	/* Step 13: Deassert config request - init complete */
+	mmdc0->mdscr = 0x00000000;
+
+	/* wait for auto-ZQ calibration to complete */
+	mdelay(1);
+}
+
 void mx6_ddr3_cfg(const struct mx6_ddr_sysinfo *sysinfo,
 		  const struct mx6_mmdc_calibration *calib,
 		  const struct mx6_ddr3_cfg *ddr3_cfg)
@@ -662,6 +952,8 @@ void mx6_dram_cfg(const struct mx6_ddr_sysinfo *sysinfo,
 {
 	if (sysinfo->ddr_type == 0) {
 		mx6_ddr3_cfg(sysinfo, calib, ddr_cfg);
+	} else if (sysinfo->ddr_type == 1) {
+		mx6_lpddr2_cfg(sysinfo, calib, ddr_cfg);
 	} else {
 		puts("Unsupported ddr type\n");
 		hang();
arch/arm/include/asm/arch-mx6/mx6-ddr.h +15 -0
index e3ba140..fd029af 100644
@@ -372,6 +372,21 @@ struct mx6_ddr3_cfg {
 	u8 SRT;		/* self-refresh temperature: 0=normal, 1=extended */
 };
 
+/* Device Information: Varies per LPDDR2 part number and speed grade */
+struct mx6_lpddr2_cfg {
+	u16 mem_speed;	/* ie 800 for LPDDR2-800 */
+	u8 density;	/* chip density (Gb) (1,2,4,8) */
+	u8 width;	/* bus width (bits) (4,8,16) */
+	u8 banks;	/* number of banks */
+	u8 rowaddr;	/* row address bits (11-16)*/
+	u8 coladdr;	/* col address bits (9-12) */
+	u16 trcd_lp;
+	u16 trppb_lp;
+	u16 trpab_lp;
+	u16 trcmin;	/* tRC min (ns*100) */
+	u16 trasmin;	/* tRAS min (ns*100) */
+};
+
 /* System Information: Varies per board design, layout, and term choices */
 struct mx6_ddr_sysinfo {
 	u8 dsize;	/* size of bus (in dwords: 0=16bit,1=32bit,2=64bit) */
Signature · 1 line
1.8.4
author
#14 lore raw

PATCH 9/9 imx: mx6slevk: add SPL support

In reply to Peng Fan

Add SPL boot support for mx6slevk board.
1. Introduce a configuration file mx6slevk_spl_defconfig.
2. i.MX6SL has same DRAM space with i.MX6SX, need to change SPL DRAM SPACE.
3. Include imx6_spl.h and related SPL macro in mx6slevk.h.
4. select SUPPORT_SPL for TARGET_MX6SLEVK.
5. Add SPL board code to do related initialization.

Boot Log:

U-Boot SPL 2015.07-00544-g1594a76 (Aug 17 2015 - 01:56:59) reading u-boot.img
reading u-boot.img

U-Boot 2015.07-00544-g1594a76 (Aug 17 2015 - 01:56:59 +0000)

CPU:   Freescale i.MX6SL rev1.2 996 MHz (running at 396 MHz)
CPU:   Commercial temperature grade (0C to 95C) at 50C
Reset cause: POR
Board: MX6SLEVK
I2C:   ready
DRAM:  1 GiB
PMIC:  PFUZE100 ID=0x10
MMC:   FSL_SDHC: 0, FSL_SDHC: 1, FSL_SDHC: 2

*** Warning - bad CRC, using default environment

In:    serial
Out:   serial
Err:   serial
Net:   FEC [PRIME]
Hit any key to stop autoboot:  0
Cc Stefano Babic <[email protected]>
Cc Fabio Estevam <[email protected]>
---
 arch/arm/cpu/armv7/mx6/Kconfig      |   1 +
 board/freescale/mx6slevk/mx6slevk.c | 164 ++++++++++++++++++++++++++++++++++++
 configs/mx6slevk_spl_defconfig      |   8 ++
 include/configs/imx6_spl.h          |   2 +-
 include/configs/mx6slevk.h          |   7 ++
 5 files changed, 181 insertions(+), 1 deletion(-)
 create mode 100644 configs/mx6slevk_spl_defconfig
arch/arm/cpu/armv7/mx6/Kconfig +1 -0
index c43cea8..6c63277 100644
@@ -91,6 +91,7 @@ config TARGET_MX6SABRESD
 config TARGET_MX6SLEVK
 	bool "mx6slevk"
 	select CPU_V7
+	select SUPPORT_SPL
 
 config TARGET_MX6SXSABRESD
 	bool "mx6sxsabresd"
board/freescale/mx6slevk/mx6slevk.c +164 -0

186 lines not on this page · raw message

configs/mx6slevk_spl_defconfig new file +8 -0
new file mode 100644
index 0000000..1fbd0d1
@@ -0,0 +1,8 @@
+CONFIG_ARM=y
+CONFIG_ARCH_MX6=y
+CONFIG_TARGET_MX6SLEVK=y
+CONFIG_SPL=y
+CONFIG_SYS_EXTRA_OPTIONS="IMX_CONFIG=arch/arm/imx-common/spl_sd.cfg,SPL,MX6SL"
+CONFIG_DM=y
+CONFIG_SPI_FLASH=y
+CONFIG_DM_THERMAL=y
include/configs/imx6_spl.h +1 -1
index 0a585b7..1744f2c 100644
@@ -61,7 +61,7 @@
 #define CONFIG_SPL_LIBDISK_SUPPORT
 #endif
 
-#if defined(CONFIG_MX6SX) || defined(CONFIG_MX6UL)
+#if defined(CONFIG_MX6SX) || defined(CONFIG_MX6UL) || defined(CONFIG_MX6SL)
 #define CONFIG_SPL_BSS_START_ADDR      0x88200000
 #define CONFIG_SPL_BSS_MAX_SIZE        0x100000        /* 1 MB */
 #define CONFIG_SYS_SPL_MALLOC_START    0x88300000
include/configs/mx6slevk.h +7 -0
index 3cecd94..04d53a7 100644
@@ -11,6 +11,13 @@
 
 #include "mx6_common.h"
 
+#ifdef CONFIG_SPL
+#define CONFIG_SPL_LIBCOMMON_SUPPORT
+#define CONFIG_SPL_MMC_SUPPORT
+#define CONFIG_SPL_FAT_SUPPORT
+#include "imx6_spl.h"
+#endif
+
 #define MACH_TYPE_MX6SLEVK		4307
 #define CONFIG_MACH_TYPE		MACH_TYPE_MX6SLEVK
 
Signature · 1 line
1.8.4