[v2,1/4] board: bsh: imx6ulz_smm_m2: Match SPL DDR settings to DCD table

Message ID 20250520150709.988904-1-dario.binacchi@amarulasolutions.com
State New
Headers show
Series
  • [v2,1/4] board: bsh: imx6ulz_smm_m2: Match SPL DDR settings to DCD table
Related show

Commit Message

Dario Binacchi May 20, 2025, 3:06 p.m. UTC
From: Michael Trimarchi <michael@amarulasolutions.com>

When using SPL on i.mx6 we frequently notice some DDR initialization
mismatches between the SPL code and the non-SPL code.

As the non-SPL code have been tested for long time and proves to be
reliable, let's configure the DDR in the exact same way as the non-SPL
case.

The idea is simple: just use the DCD table and write directly to the DDR
registers.

Signed-off-by: Michael Trimarchi <michael@amarulasolutions.com>
Signed-off-by: Dario Binacchi <dario.binacchi@amarulasolutions.com>

---

Changes in v2:
- Add 'static struct' globally in the module where the definitions
  can mabe static.
- Use standard C comment style

 arch/arm/include/asm/arch-mx6/mx6-ddr.h |   2 +
 arch/arm/mach-imx/mx6/ddr.c             |   3 +
 board/bsh/imx6ulz_smm_m2/spl.c          | 260 ++++++++++++++++++------
 3 files changed, 203 insertions(+), 62 deletions(-)

Comments

Michael Trimarchi May 20, 2025, 5:07 p.m. UTC | #1
Hi Dario

On Tue, May 20, 2025 at 5:07 PM Dario Binacchi
<dario.binacchi@amarulasolutions.com> wrote:
>
> From: Michael Trimarchi <michael@amarulasolutions.com>
>
> When using SPL on i.mx6 we frequently notice some DDR initialization
> mismatches between the SPL code and the non-SPL code.
>
> As the non-SPL code have been tested for long time and proves to be
> reliable, let's configure the DDR in the exact same way as the non-SPL
> case.
>
> The idea is simple: just use the DCD table and write directly to the DDR
> registers.
>
> Signed-off-by: Michael Trimarchi <michael@amarulasolutions.com>
> Signed-off-by: Dario Binacchi <dario.binacchi@amarulasolutions.com>
>
> ---
>
> Changes in v2:
> - Add 'static struct' globally in the module where the definitions
>   can mabe static.
> - Use standard C comment style
>
>  arch/arm/include/asm/arch-mx6/mx6-ddr.h |   2 +
>  arch/arm/mach-imx/mx6/ddr.c             |   3 +
>  board/bsh/imx6ulz_smm_m2/spl.c          | 260 ++++++++++++++++++------
>  3 files changed, 203 insertions(+), 62 deletions(-)
>
> diff --git a/arch/arm/include/asm/arch-mx6/mx6-ddr.h b/arch/arm/include/asm/arch-mx6/mx6-ddr.h
> index ad9c1ac906a3..bd3ff65bcd96 100644
> --- a/arch/arm/include/asm/arch-mx6/mx6-ddr.h
> +++ b/arch/arm/include/asm/arch-mx6/mx6-ddr.h
> @@ -457,6 +457,8 @@ struct mx6_mmdc_calibration {
>         u32 p1_mpwrdlctl;
>         /* lpddr2 zq hw calibration */
>         u32 mpzqlp2ctl;
> +       /* MDC Duty Cycle Control Register */
> +       u32 mpdccr;
>  };
>
>  /* configure iomux (pinctl/padctl) */
> diff --git a/arch/arm/mach-imx/mx6/ddr.c b/arch/arm/mach-imx/mx6/ddr.c
> index 5a1258e002d2..749ceee0cdbf 100644
> --- a/arch/arm/mach-imx/mx6/ddr.c
> +++ b/arch/arm/mach-imx/mx6/ddr.c
> @@ -1444,6 +1444,9 @@ void mx6_ddr3_cfg(const struct mx6_ddr_sysinfo *sysinfo,
>         mmdc0->mpdgctrl1 = calib->p0_mpdgctrl1;
>         mmdc0->mprddlctl = calib->p0_mprddlctl;
>         mmdc0->mpwrdlctl = calib->p0_mpwrdlctl;
> +       if (calib->mpdccr)
> +               mmdc0->mpdccr = calib->mpdccr;
> +

This should be in this patch? Don't think so

Michael

>         if (sysinfo->dsize > 1) {
>                 MMDC1(mpwldectrl0, calib->p1_mpwldectrl0);
>                 MMDC1(mpwldectrl1, calib->p1_mpwldectrl1);
> diff --git a/board/bsh/imx6ulz_smm_m2/spl.c b/board/bsh/imx6ulz_smm_m2/spl.c
> index 724841b57456..936e54662e98 100644
> --- a/board/bsh/imx6ulz_smm_m2/spl.c
> +++ b/board/bsh/imx6ulz_smm_m2/spl.c
> @@ -31,70 +31,209 @@ static void setup_iomux_uart(void)
>         imx_iomux_v3_setup_multiple_pads(uart4_pads, ARRAY_SIZE(uart4_pads));
>  }
>
> -static struct mx6ul_iomux_grp_regs mx6_grp_ioregs = {
> -       .grp_addds              = 0x00000028,
> -       .grp_ddrmode_ctl        = 0x00020000,
> -       .grp_b0ds               = 0x00000028,
> -       .grp_ctlds              = 0x00000028,
> -       .grp_b1ds               = 0x00000028,
> -       .grp_ddrpke             = 0x00000000,
> -       .grp_ddrmode            = 0x00020000,
> -       .grp_ddr_type           = 0x000c0000,
> +struct dram_cfg_param {
> +       unsigned int reg;
> +       unsigned int val;
>  };
>
> -static struct mx6ul_iomux_ddr_regs mx6_ddr_ioregs = {
> -       .dram_dqm0              = 0x00000028,
> -       .dram_dqm1              = 0x00000028,
> -       .dram_ras               = 0x00000028,
> -       .dram_cas               = 0x00000028,
> -       .dram_odt0              = 0x00000028,
> -       .dram_odt1              = 0x00000028,
> -       .dram_sdba2             = 0x00000000,
> -       .dram_sdclk_0           = 0x00000028,
> -       .dram_sdqs0             = 0x00000028,
> -       .dram_sdqs1             = 0x00000028,
> -       .dram_reset             = 0x000c0028,
> +struct dram_timing_info {
> +       const struct dram_cfg_param *ddrc_cfg;
> +       unsigned int ddrc_cfg_num;
>  };
>
> -static struct mx6_mmdc_calibration mx6_mmcd_calib = {
> -       .p0_mpwldectrl0         = 0x00000000,
> -       .p0_mpwldectrl1         = 0x00100010,
> -       .p0_mpdgctrl0           = 0x414c014c,
> -       .p0_mpdgctrl1           = 0x00000000,
> -       .p0_mprddlctl           = 0x40403a42,
> -       .p0_mpwrdlctl           = 0x4040342e,
> -};
> +static const struct dram_cfg_param ddr_ddrc_cfg_128mb[] = {
> +       /* IOMUX */
> +
> +       /* DDR IO Type: */
> +       {0x020e04b4, 0x000C0000},       /* IOMUXC_SW_PAD_CTL_GRP_DDR_TYPE */
> +       {0x020e04ac, 0x00000000},       /* IOMUXC_SW_PAD_CTL_GRP_DDRPKE */
> +
> +       /* Clock: */
> +       {0x020e027c, 0x00000028},       /* IOMUXC_SW_PAD_CTL_PAD_DRAM_SDCLK_0 */
> +
> +       /* Address: */
> +       {0x020e0250, 0x00000028},       /* IOMUXC_SW_PAD_CTL_PAD_DRAM_CAS */
> +       {0x020e024c, 0x00000028},       /* IOMUXC_SW_PAD_CTL_PAD_DRAM_RAS */
> +       {0x020e0490, 0x00000028},       /* IOMUXC_SW_PAD_CTL_GRP_ADDDS */
> +
> +       /* Control: */
> +       {0x020e0288, 0x000C0028},       /* IOMUXC_SW_PAD_CTL_PAD_DRAM_RESET */
> +
> +       {0x020e0270, 0x00000000},       /*
> +                                        * IOMUXC_SW_PAD_CTL_PAD_DRAM_SDBA2 - DSE can be configured
> +                                        * using Group Control Register: IOMUXC_SW_PAD_CTL_GRP_CTLDS
> +                                        */
> +
> +       {0x020e0260, 0x00000028},       /* IOMUXC_SW_PAD_CTL_PAD_DRAM_SDODT0 */
> +       {0x020e0264, 0x00000028},       /* IOMUXC_SW_PAD_CTL_PAD_DRAM_SDODT1 */
> +       {0x020e04a0, 0x00000028},       /* IOMUXC_SW_PAD_CTL_GRP_CTLDS */
> +
> +       /* Data Strobes: */
> +       {0x020e0494, 0x00020000},       /* IOMUXC_SW_PAD_CTL_GRP_DDRMODE_CTL */
> +       {0x020e0280, 0x00000028},       /* IOMUXC_SW_PAD_CTL_PAD_DRAM_SDQS0 */
> +       {0x020e0284, 0x00000028},       /* IOMUXC_SW_PAD_CTL_PAD_DRAM_SDQS1 */
> +
> +       /* Data: */
> +       {0x020e04b0, 0x00020000},       /* IOMUXC_SW_PAD_CTL_GRP_DDRMODE */
> +       {0x020e0498, 0x00000028},       /* IOMUXC_SW_PAD_CTL_GRP_B0DS */
> +       {0x020e04a4, 0x00000028},       /* IOMUXC_SW_PAD_CTL_GRP_B1DS */
> +
> +       {0x020e0244, 0x00000028},       /* IOMUXC_SW_PAD_CTL_PAD_DRAM_DQM0 */
> +       {0x020e0248, 0x00000028},       /* IOMUXC_SW_PAD_CTL_PAD_DRAM_DQM1 */
> +
> +       /*
> +        * =============================================================================
> +        * DDR Controller Registers
> +        * =============================================================================
> +        * Manufacturer:ISSI
> +        * Device Part Number:IS43TR16640BL-125JBLI
> +        * Clock Freq.: 400MHz
> +        * Density per CS in Gb: 1
> +        * Chip Selects used:1
> +        * Number of Banks:8
> +        * Row address:    13
> +        * Column address: 10
> +        * Data bus width16
> +        * =============================================================================
> +        */
> +
> +       {0x021b001c, 0x00008000}, /*
> +                                  * MMDC0_MDSCR, set the Configuration request bit during
> +                                  * MMDC set up
> +                                  */
> +
> +       /*
> +        * =============================================================================
> +        * Calibration setup
> +        * =============================================================================
> +        */
> +
> +       {0x021b0800, 0xA1390003}, /*
> +                                  * DDR_PHY_P0_MPZQHWCTRL, enable both one-time & periodic
> +                                  * HW ZQ calibration.
> +                                  */
> +
> +       /*
> +        * For target board, may need to run write leveling calibration to fine tune these
> +        * settings.
> +        */
> +       {0x021b080c, 0x00000000},
> +
> +       /* Read DQS Gating calibration */
> +       {0x021b083c, 0x41480148},       /* MPDGCTRL0 PHY0 */
> +
> +       /* Read calibration */
> +       {0x021b0848, 0x40403A3E},       /* MPRDDLCTL PHY0 */
> +
> +       /* Write calibration */
> +       {0x021b0850, 0x4040362E},       /* MPWRDLCTL PHY0 */
> +
> +       /*
> +        * Read data bit delay: 3 is the recommended default value, although out of reset
> +        * value is 0
> +        */
> +       {0x021b081c, 0x33333333},       /* MMDC_MPRDDQBY0DL */
> +       {0x021b0820, 0x33333333},       /* MMDC_MPRDDQBY1DL */
> +
> +       /* Write data bit delay: */
> +       {0x021b082c, 0xF3333333},       /* MMDC_MPWRDQBY0DL */
> +       {0x021b0830, 0xF3333333},       /* MMDC_MPWRDQBY1DL */
> +
> +       /* DQS&CLK Duty Cycle */
> +       {0x021b08c0, 0x00944009},       /* [MMDC_MPDCCR] MMDC Duty Cycle Control Register */
> +
> +       /* Complete calibration by forced measurement: */
> +       {0x021b08b8, 0x00000800},       /* DDR_PHY_P0_MPMUR0, frc_msr */
>
> -static struct mx6_ddr_sysinfo ddr_sysinfo = {
> -       .dsize                  = 0,
> -       .cs1_mirror             = 0,
> -       .cs_density             = 32,
> -       .ncs                    = 1,
> -       .bi_on                  = 1,
> -       .rtt_nom                = 1,
> -       .rtt_wr                 = 0,
> -       .ralat                  = 5,
> -       .walat                  = 1,
> -       .mif3_mode              = 3,
> -       .rst_to_cke             = 0x23, /* 33 cycles (JEDEC value for DDR3) - total of 500 us */
> -       .sde_to_rst             = 0x10, /* 14 cycles (JEDEC value for DDR3) - total of 200 us */
> -       .refsel                 = 1,
> -       .refr                   = 3,
> +       /*
> +        * =============================================================================
> +        * Calibration setup end
> +        * =============================================================================
> +        */
> +
> +       /* MMDC init: */
> +       {0x021b0004, 0x0002002D},       /* MMDC0_MDPDC */
> +       {0x021b0008, 0x1B333030},       /* MMDC0_MDOTC */
> +       {0x021b000c, 0x2B2F52F3},       /* MMDC0_MDCFG0 */
> +       {0x021b0010, 0xB66D0B63},       /* MMDC0_MDCFG1 */
> +       {0x021b0014, 0x01FF00DB},       /* MMDC0_MDCFG2 */
> +
> +       /*
> +        * MDMISC: RALAT kept to the high level of 5.
> +        * MDMISC: consider reducing RALAT if your 528MHz board design allow that.
> +        * Lower RALAT benefits:
> +        * a. better operation at low frequency, for LPDDR2 freq < 100MHz, change RALAT to 3
> +        * b. Small performance improvement
> +        */
> +       {0x021b0018, 0x00211740},       /* MMDC0_MDMISC */
> +       {0x021b001c, 0x00008000},       /*
> +                                        * MMDC0_MDSCR, set the Configuration request
> +                                        * bit during MMDC set up
> +                                        */
> +       {0x021b002c, 0x000026D2},       /* MMDC0_MDRWD */
> +       {0x021b0030, 0x002F1023},       /* MMDC0_MDOR */
> +       {0x021b0040, 0x00000043},       /* Chan0 CS0_END */
> +       {0x021b0000, 0x82180000},       /* MMDC0_MDCTL */
> +
> +       {0x021b0890, 0x00400000},       /* MPPDCMPR2 */
> +
> +       /* Mode register writes */
> +       {0x021b001c, 0x02808032},       /* MMDC0_MDSCR, MR2 write, CS0 */
> +       {0x021b001c, 0x00008033},       /* MMDC0_MDSCR, MR3 write, CS0 */
> +       {0x021b001c, 0x00048031},       /* MMDC0_MDSCR, MR1 write, CS0 */
> +       {0x021b001c, 0x15208030},       /* MMDC0_MDSCR, MR0write, CS0 */
> +       {0x021b001c, 0x04008040},       /*
> +                                        * MMDC0_MDSCR, ZQ calibration command sent to
> +                                        * device on CS0
> +                                        */
> +       {0x021b0020, 0x00007800},       /* MMDC0_MDREF */
> +
> +       {0x021b0818, 0x00000227},       /* DDR_PHY_P0_MPODTCTRL */
> +
> +       {0x021b0004, 0x0002552D},       /* MMDC0_MDPDC now SDCTL power down enabled */
> +
> +       {0x021b0404, 0x00011006},       /*
> +                                        * MMDC0_MAPSR ADOPT power down enabled,
> +                                        * MMDC will enter automatically to self-refresh
> +                                        * while the number of idle cycle reached.
> +                                        */
> +
> +       {0x021b001c, 0x00000000},       /*
> +                                        * MMDC0_MDSCR, clear this register
> +                                        * (especially the configuration bit as initialization
> +                                        * is complete)
> +                                        */
>  };
>
> -static struct mx6_ddr3_cfg mem_ddr = {
> -       .mem_speed              = 1333,
> -       .density                = 2,
> -       .width                  = 16,
> -       .banks                  = 8,
> -       .rowaddr                = 13,
> -       .coladdr                = 10,
> -       .pagesz                 = 2,
> -       .trcd                   = 1350,
> -       .trcmin                 = 4950,
> -       .trasmin                = 3600,
> +static struct dram_timing_info dram_timing_128mb = {
> +       .ddrc_cfg = ddr_ddrc_cfg_128mb,
> +       .ddrc_cfg_num = ARRAY_SIZE(ddr_ddrc_cfg_128mb),
>  };
>
> +static void ddr_cfg_write(const struct dram_timing_info *dram_timing_info)
> +{
> +       int i;
> +       const struct dram_cfg_param *ddrc_cfg = dram_timing_info->ddrc_cfg;
> +       const int ddrc_cfg_num = dram_timing_info->ddrc_cfg_num;
> +
> +       for (i = 0; i < ddrc_cfg_num; i++) {
> +               debug("Writing 0x%x to register 0x%x\n", ddrc_cfg->val,
> +                     ddrc_cfg->reg);
> +               writel(ddrc_cfg->val, ddrc_cfg->reg);
> +               ddrc_cfg++;
> +       }
> +}
> +
> +static void spl_dram_init(void)
> +{
> +       struct mmdc_p_regs *mmdc0 = (struct mmdc_p_regs *)MMDC_P0_BASE_ADDR;
> +
> +       clrbits_le32(&mmdc0->mdctl, 1 << 31);   /* clear SDE_0 */
> +       clrbits_le32(&mmdc0->mdctl, 1 << 30);   /* clear SDE_1 */
> +
> +       ddr_cfg_write(&dram_timing_128mb);
> +}
> +
>  static void ccgr_init(void)
>  {
>         struct mxc_ccm_reg *ccm = (struct mxc_ccm_reg *)CCM_BASE_ADDR;
> @@ -108,20 +247,17 @@ static void ccgr_init(void)
>         writel(0xFFFFFFFF, &ccm->CCGR6);
>  }
>
> -static void imx6ul_spl_dram_cfg(void)
> -{
> -       mx6ul_dram_iocfg(mem_ddr.width, &mx6_ddr_ioregs, &mx6_grp_ioregs);
> -       mx6_dram_cfg(&ddr_sysinfo, &mx6_mmcd_calib, &mem_ddr);
> -}
> -
>  void board_init_f(ulong dummy)
>  {
>         ccgr_init();
> +
> +       /* DDR initialization */
> +       spl_dram_init();
> +
>         arch_cpu_init();
>         timer_init();
>         setup_iomux_uart();
>         preloader_console_init();
> -       imx6ul_spl_dram_cfg();
>  }
>
>  void reset_cpu(void)
> --
> 2.43.0
>
> base-commit: eeb5ff1a468b2303efa9deb2483b5edbebb568c6
> branch: bsh-202505-RAM

Patch

diff --git a/arch/arm/include/asm/arch-mx6/mx6-ddr.h b/arch/arm/include/asm/arch-mx6/mx6-ddr.h
index ad9c1ac906a3..bd3ff65bcd96 100644
--- a/arch/arm/include/asm/arch-mx6/mx6-ddr.h
+++ b/arch/arm/include/asm/arch-mx6/mx6-ddr.h
@@ -457,6 +457,8 @@  struct mx6_mmdc_calibration {
 	u32 p1_mpwrdlctl;
 	/* lpddr2 zq hw calibration */
 	u32 mpzqlp2ctl;
+	/* MDC Duty Cycle Control Register */
+	u32 mpdccr;
 };
 
 /* configure iomux (pinctl/padctl) */
diff --git a/arch/arm/mach-imx/mx6/ddr.c b/arch/arm/mach-imx/mx6/ddr.c
index 5a1258e002d2..749ceee0cdbf 100644
--- a/arch/arm/mach-imx/mx6/ddr.c
+++ b/arch/arm/mach-imx/mx6/ddr.c
@@ -1444,6 +1444,9 @@  void mx6_ddr3_cfg(const struct mx6_ddr_sysinfo *sysinfo,
 	mmdc0->mpdgctrl1 = calib->p0_mpdgctrl1;
 	mmdc0->mprddlctl = calib->p0_mprddlctl;
 	mmdc0->mpwrdlctl = calib->p0_mpwrdlctl;
+	if (calib->mpdccr)
+		mmdc0->mpdccr = calib->mpdccr;
+
 	if (sysinfo->dsize > 1) {
 		MMDC1(mpwldectrl0, calib->p1_mpwldectrl0);
 		MMDC1(mpwldectrl1, calib->p1_mpwldectrl1);
diff --git a/board/bsh/imx6ulz_smm_m2/spl.c b/board/bsh/imx6ulz_smm_m2/spl.c
index 724841b57456..936e54662e98 100644
--- a/board/bsh/imx6ulz_smm_m2/spl.c
+++ b/board/bsh/imx6ulz_smm_m2/spl.c
@@ -31,70 +31,209 @@  static void setup_iomux_uart(void)
 	imx_iomux_v3_setup_multiple_pads(uart4_pads, ARRAY_SIZE(uart4_pads));
 }
 
-static struct mx6ul_iomux_grp_regs mx6_grp_ioregs = {
-	.grp_addds		= 0x00000028,
-	.grp_ddrmode_ctl	= 0x00020000,
-	.grp_b0ds		= 0x00000028,
-	.grp_ctlds		= 0x00000028,
-	.grp_b1ds		= 0x00000028,
-	.grp_ddrpke		= 0x00000000,
-	.grp_ddrmode		= 0x00020000,
-	.grp_ddr_type		= 0x000c0000,
+struct dram_cfg_param {
+	unsigned int reg;
+	unsigned int val;
 };
 
-static struct mx6ul_iomux_ddr_regs mx6_ddr_ioregs = {
-	.dram_dqm0		= 0x00000028,
-	.dram_dqm1		= 0x00000028,
-	.dram_ras		= 0x00000028,
-	.dram_cas		= 0x00000028,
-	.dram_odt0		= 0x00000028,
-	.dram_odt1		= 0x00000028,
-	.dram_sdba2		= 0x00000000,
-	.dram_sdclk_0		= 0x00000028,
-	.dram_sdqs0		= 0x00000028,
-	.dram_sdqs1		= 0x00000028,
-	.dram_reset		= 0x000c0028,
+struct dram_timing_info {
+	const struct dram_cfg_param *ddrc_cfg;
+	unsigned int ddrc_cfg_num;
 };
 
-static struct mx6_mmdc_calibration mx6_mmcd_calib = {
-	.p0_mpwldectrl0		= 0x00000000,
-	.p0_mpwldectrl1		= 0x00100010,
-	.p0_mpdgctrl0		= 0x414c014c,
-	.p0_mpdgctrl1		= 0x00000000,
-	.p0_mprddlctl		= 0x40403a42,
-	.p0_mpwrdlctl		= 0x4040342e,
-};
+static const struct dram_cfg_param ddr_ddrc_cfg_128mb[] = {
+	/* IOMUX */
+
+	/* DDR IO Type: */
+	{0x020e04b4, 0x000C0000},	/* IOMUXC_SW_PAD_CTL_GRP_DDR_TYPE */
+	{0x020e04ac, 0x00000000},	/* IOMUXC_SW_PAD_CTL_GRP_DDRPKE */
+
+	/* Clock: */
+	{0x020e027c, 0x00000028},	/* IOMUXC_SW_PAD_CTL_PAD_DRAM_SDCLK_0 */
+
+	/* Address: */
+	{0x020e0250, 0x00000028},	/* IOMUXC_SW_PAD_CTL_PAD_DRAM_CAS */
+	{0x020e024c, 0x00000028},	/* IOMUXC_SW_PAD_CTL_PAD_DRAM_RAS */
+	{0x020e0490, 0x00000028},	/* IOMUXC_SW_PAD_CTL_GRP_ADDDS */
+
+	/* Control: */
+	{0x020e0288, 0x000C0028},	/* IOMUXC_SW_PAD_CTL_PAD_DRAM_RESET */
+
+	{0x020e0270, 0x00000000},	/*
+					 * IOMUXC_SW_PAD_CTL_PAD_DRAM_SDBA2 - DSE can be configured
+					 * using Group Control Register: IOMUXC_SW_PAD_CTL_GRP_CTLDS
+					 */
+
+	{0x020e0260, 0x00000028},	/* IOMUXC_SW_PAD_CTL_PAD_DRAM_SDODT0 */
+	{0x020e0264, 0x00000028},	/* IOMUXC_SW_PAD_CTL_PAD_DRAM_SDODT1 */
+	{0x020e04a0, 0x00000028},	/* IOMUXC_SW_PAD_CTL_GRP_CTLDS */
+
+	/* Data Strobes: */
+	{0x020e0494, 0x00020000},	/* IOMUXC_SW_PAD_CTL_GRP_DDRMODE_CTL */
+	{0x020e0280, 0x00000028},	/* IOMUXC_SW_PAD_CTL_PAD_DRAM_SDQS0 */
+	{0x020e0284, 0x00000028},	/* IOMUXC_SW_PAD_CTL_PAD_DRAM_SDQS1 */
+
+	/* Data: */
+	{0x020e04b0, 0x00020000},	/* IOMUXC_SW_PAD_CTL_GRP_DDRMODE */
+	{0x020e0498, 0x00000028},	/* IOMUXC_SW_PAD_CTL_GRP_B0DS */
+	{0x020e04a4, 0x00000028},	/* IOMUXC_SW_PAD_CTL_GRP_B1DS */
+
+	{0x020e0244, 0x00000028},	/* IOMUXC_SW_PAD_CTL_PAD_DRAM_DQM0 */
+	{0x020e0248, 0x00000028},	/* IOMUXC_SW_PAD_CTL_PAD_DRAM_DQM1 */
+
+	/*
+	 * =============================================================================
+	 * DDR Controller Registers
+	 * =============================================================================
+	 * Manufacturer:ISSI
+	 * Device Part Number:IS43TR16640BL-125JBLI
+	 * Clock Freq.: 400MHz
+	 * Density per CS in Gb: 1
+	 * Chip Selects used:1
+	 * Number of Banks:8
+	 * Row address:    13
+	 * Column address: 10
+	 * Data bus width16
+	 * =============================================================================
+	 */
+
+	{0x021b001c, 0x00008000}, /*
+				   * MMDC0_MDSCR, set the Configuration request bit during
+				   * MMDC set up
+				   */
+
+	/*
+	 * =============================================================================
+	 * Calibration setup
+	 * =============================================================================
+	 */
+
+	{0x021b0800, 0xA1390003}, /*
+				   * DDR_PHY_P0_MPZQHWCTRL, enable both one-time & periodic
+				   * HW ZQ calibration.
+				   */
+
+	/*
+	 * For target board, may need to run write leveling calibration to fine tune these
+	 * settings.
+	 */
+	{0x021b080c, 0x00000000},
+
+	/* Read DQS Gating calibration */
+	{0x021b083c, 0x41480148},	/* MPDGCTRL0 PHY0 */
+
+	/* Read calibration */
+	{0x021b0848, 0x40403A3E},	/* MPRDDLCTL PHY0 */
+
+	/* Write calibration */
+	{0x021b0850, 0x4040362E},	/* MPWRDLCTL PHY0 */
+
+	/*
+	 * Read data bit delay: 3 is the recommended default value, although out of reset
+	 * value is 0
+	 */
+	{0x021b081c, 0x33333333},	/* MMDC_MPRDDQBY0DL */
+	{0x021b0820, 0x33333333},	/* MMDC_MPRDDQBY1DL */
+
+	/* Write data bit delay: */
+	{0x021b082c, 0xF3333333},	/* MMDC_MPWRDQBY0DL */
+	{0x021b0830, 0xF3333333},	/* MMDC_MPWRDQBY1DL */
+
+	/* DQS&CLK Duty Cycle */
+	{0x021b08c0, 0x00944009},	/* [MMDC_MPDCCR] MMDC Duty Cycle Control Register */
+
+	/* Complete calibration by forced measurement: */
+	{0x021b08b8, 0x00000800},	/* DDR_PHY_P0_MPMUR0, frc_msr */
 
-static struct mx6_ddr_sysinfo ddr_sysinfo = {
-	.dsize			= 0,
-	.cs1_mirror		= 0,
-	.cs_density		= 32,
-	.ncs			= 1,
-	.bi_on			= 1,
-	.rtt_nom		= 1,
-	.rtt_wr			= 0,
-	.ralat			= 5,
-	.walat			= 1,
-	.mif3_mode		= 3,
-	.rst_to_cke		= 0x23,	/* 33 cycles (JEDEC value for DDR3) - total of 500 us */
-	.sde_to_rst		= 0x10,	/* 14 cycles (JEDEC value for DDR3) - total of 200 us */
-	.refsel			= 1,
-	.refr			= 3,
+	/*
+	 * =============================================================================
+	 * Calibration setup end
+	 * =============================================================================
+	 */
+
+	/* MMDC init: */
+	{0x021b0004, 0x0002002D},	/* MMDC0_MDPDC */
+	{0x021b0008, 0x1B333030},	/* MMDC0_MDOTC */
+	{0x021b000c, 0x2B2F52F3},	/* MMDC0_MDCFG0 */
+	{0x021b0010, 0xB66D0B63},	/* MMDC0_MDCFG1 */
+	{0x021b0014, 0x01FF00DB},	/* MMDC0_MDCFG2 */
+
+	/*
+	 * MDMISC: RALAT kept to the high level of 5.
+	 * MDMISC: consider reducing RALAT if your 528MHz board design allow that.
+	 * Lower RALAT benefits:
+	 * a. better operation at low frequency, for LPDDR2 freq < 100MHz, change RALAT to 3
+	 * b. Small performance improvement
+	 */
+	{0x021b0018, 0x00211740},	/* MMDC0_MDMISC */
+	{0x021b001c, 0x00008000},	/*
+					 * MMDC0_MDSCR, set the Configuration request
+					 * bit during MMDC set up
+					 */
+	{0x021b002c, 0x000026D2},	/* MMDC0_MDRWD */
+	{0x021b0030, 0x002F1023},	/* MMDC0_MDOR */
+	{0x021b0040, 0x00000043},	/* Chan0 CS0_END */
+	{0x021b0000, 0x82180000},	/* MMDC0_MDCTL */
+
+	{0x021b0890, 0x00400000},	/* MPPDCMPR2 */
+
+	/* Mode register writes */
+	{0x021b001c, 0x02808032},	/* MMDC0_MDSCR, MR2 write, CS0 */
+	{0x021b001c, 0x00008033},	/* MMDC0_MDSCR, MR3 write, CS0 */
+	{0x021b001c, 0x00048031},	/* MMDC0_MDSCR, MR1 write, CS0 */
+	{0x021b001c, 0x15208030},	/* MMDC0_MDSCR, MR0write, CS0 */
+	{0x021b001c, 0x04008040},	/*
+					 * MMDC0_MDSCR, ZQ calibration command sent to
+					 * device on CS0
+					 */
+	{0x021b0020, 0x00007800},	/* MMDC0_MDREF */
+
+	{0x021b0818, 0x00000227},	/* DDR_PHY_P0_MPODTCTRL */
+
+	{0x021b0004, 0x0002552D},	/* MMDC0_MDPDC now SDCTL power down enabled */
+
+	{0x021b0404, 0x00011006},	/*
+					 * MMDC0_MAPSR ADOPT power down enabled,
+					 * MMDC will enter automatically to self-refresh
+					 * while the number of idle cycle reached.
+					 */
+
+	{0x021b001c, 0x00000000},	/*
+					 * MMDC0_MDSCR, clear this register
+					 * (especially the configuration bit as initialization
+					 * is complete)
+					 */
 };
 
-static struct mx6_ddr3_cfg mem_ddr = {
-	.mem_speed		= 1333,
-	.density		= 2,
-	.width			= 16,
-	.banks			= 8,
-	.rowaddr		= 13,
-	.coladdr		= 10,
-	.pagesz			= 2,
-	.trcd			= 1350,
-	.trcmin			= 4950,
-	.trasmin		= 3600,
+static struct dram_timing_info dram_timing_128mb = {
+	.ddrc_cfg = ddr_ddrc_cfg_128mb,
+	.ddrc_cfg_num = ARRAY_SIZE(ddr_ddrc_cfg_128mb),
 };
 
+static void ddr_cfg_write(const struct dram_timing_info *dram_timing_info)
+{
+	int i;
+	const struct dram_cfg_param *ddrc_cfg = dram_timing_info->ddrc_cfg;
+	const int ddrc_cfg_num = dram_timing_info->ddrc_cfg_num;
+
+	for (i = 0; i < ddrc_cfg_num; i++) {
+		debug("Writing 0x%x to register 0x%x\n", ddrc_cfg->val,
+		      ddrc_cfg->reg);
+		writel(ddrc_cfg->val, ddrc_cfg->reg);
+		ddrc_cfg++;
+	}
+}
+
+static void spl_dram_init(void)
+{
+	struct mmdc_p_regs *mmdc0 = (struct mmdc_p_regs *)MMDC_P0_BASE_ADDR;
+
+	clrbits_le32(&mmdc0->mdctl, 1 << 31);	/* clear SDE_0 */
+	clrbits_le32(&mmdc0->mdctl, 1 << 30);	/* clear SDE_1 */
+
+	ddr_cfg_write(&dram_timing_128mb);
+}
+
 static void ccgr_init(void)
 {
 	struct mxc_ccm_reg *ccm = (struct mxc_ccm_reg *)CCM_BASE_ADDR;
@@ -108,20 +247,17 @@  static void ccgr_init(void)
 	writel(0xFFFFFFFF, &ccm->CCGR6);
 }
 
-static void imx6ul_spl_dram_cfg(void)
-{
-	mx6ul_dram_iocfg(mem_ddr.width, &mx6_ddr_ioregs, &mx6_grp_ioregs);
-	mx6_dram_cfg(&ddr_sysinfo, &mx6_mmcd_calib, &mem_ddr);
-}
-
 void board_init_f(ulong dummy)
 {
 	ccgr_init();
+
+	/* DDR initialization */
+	spl_dram_init();
+
 	arch_cpu_init();
 	timer_init();
 	setup_iomux_uart();
 	preloader_console_init();
-	imx6ul_spl_dram_cfg();
 }
 
 void reset_cpu(void)