imx: mx6: support LPDDR2 and add mx6slevk spl
Subsystems (2)
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
PATCH 1/9 imx: mx6: ddr add more register entry for mmdc_p_regs
Add more register entry for MMDC structure.
--- 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
@@ -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
PATCH 2/9 imx: mx6: ddr no support MMDC1 for i.MX6SL
In reply to Peng Fani.MX 6SoloLite only supports MMDC0, so do not access MMDC1 for i.MX 6SL.
--- arch/arm/cpu/armv7/mx6/ddr.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-)
arch/arm/cpu/armv7/mx6/ddr.c +4 -2
@@ -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
PATCH 3/9 imx: mx6: ddr correct tRFC and tXS
In reply to Peng FanTo 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).
--- arch/arm/cpu/armv7/mx6/ddr.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
arch/arm/cpu/armv7/mx6/ddr.c +2 -2
@@ -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
PATCH 4/9 imx: mx6: ddr add dram io configuration and header file for i.MX6SL
In reply to Peng FanDefine 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.
--- 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
@@ -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
PATCH 5/9 imx: mx6: ddr add mpzqlp2ctl entry
In reply to Peng FanAdd mpzqlp2ctl entry for mx6_mmdc_calibration.MMDC_MPZQLP2CTL register is for init tZQINIT, tZQCL, tZQCS for LPDDR2 chips.
--- 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
@@ -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
PATCH 6/9 imx: mx6: ddr add an entry ddr_type for mx6_ddr_sysinfo
In reply to Peng FanAdd ddr_type entry for mx6_ddr_sysinfo. It will be used for differenrate DDR3 and LPDDR2.
--- 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
@@ -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
PATCH 7/9 imx: mx6: ddr init MMDC according to ddr_type
In reply to Peng FanTo 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.
--- 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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
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_cfgtomx6_ddr3_cfgand the originalmx6_dram_cfgfunction only is a wrapper. The new reimplemented functionmx6_dram_cfgonly invokesmx6_ddr3_cfgwhenddr_typeis for DDR3. Later we can useddr_typeto initialize MMDC for LPDDR2.
Initializeddr_typefor different boards which enable SPL.Signed-off-by Peng Fan <[email protected]>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@@ -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@@ -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
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
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_cfgtomx6_ddr3_cfgand the originalmx6_dram_cfgfunction only is a wrapper. The new reimplemented functionmx6_dram_cfgonly invokesmx6_ddr3_cfgwhenddr_typeis for DDR3. Later we can useddr_typeto initialize MMDC for LPDDR2.
Initializeddr_typefor different boards which enable SPL.Signed-off-by Peng Fan <[email protected]>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@@ -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@@ -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@@ -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:
Reviewed-by Stefan Roese <[email protected]>
Will add your tag, and repost patch set to uboot mailist.
Quoted 4 lines
Thanks,
Stefan
Regards,
Peng.
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_cfgtomx6_ddr3_cfgand the originalmx6_dram_cfgfunction only is a wrapper. The new reimplemented functionmx6_dram_cfgonly invokesmx6_ddr3_cfgwhenddr_typeis for DDR3. Later we can useddr_typeto initialize MMDC for LPDDR2.
Initializeddr_typefor different boards which enable SPL.Signed-off-by Peng Fan <[email protected]>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@@ -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@@ -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@@ -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:
Reviewed-by Stefan Roese <[email protected]>Will add your tag, and repost patch set to uboot mailist.
And please add the enum as well.
Thanks,
Stefan
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_cfgtomx6_ddr3_cfgand the originalmx6_dram_cfgfunction only is a wrapper. The new reimplemented functionmx6_dram_cfgonly invokesmx6_ddr3_cfgwhenddr_typeis for DDR3. Later we can useddr_typeto initialize MMDC for LPDDR2.
Initializeddr_typefor different boards which enable SPL.Signed-off-by Peng Fan <[email protected]>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@@ -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@@ -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@@ -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:
Reviewed-by Stefan Roese <[email protected]>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.
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_cfgtomx6_ddr3_cfgand the originalmx6_dram_cfgfunction only is a wrapper. The new reimplemented functionmx6_dram_cfgonly invokesmx6_ddr3_cfgwhenddr_typeis for DDR3. Later we can useddr_typeto initialize MMDC for LPDDR2.
Initializeddr_typefor different boards which enable SPL.Signed-off-by Peng Fan <[email protected]>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@@ -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@@ -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@@ -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
Reviewed-by Stefan Roese <[email protected]>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_DDR30" and "#defineMX6_LPDDR21"?
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
PATCH 8/9 imx: mx6: ddr: add LPDDR2 support
In reply to Peng FanAdd 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.
--- 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
@@ -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
@@ -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
PATCH 9/9 imx: mx6slevk: add SPL support
In reply to Peng FanAdd 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
--- 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
@@ -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
@@ -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
@@ -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
@@ -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