diff mbox

[U-Boot,07/12] MX6: add structs for mmdc and ddr iomux registers

Message ID 1398716258-8420-8-git-send-email-tharvey@gateworks.com
State Changes Requested
Delegated to: Stefano Babic
Headers show

Commit Message

Tim Harvey April 28, 2014, 8:17 p.m. UTC
Add memory-mapped structures for MMDC iomux and configuration. Note that while
the MMDC configuration registers are common between the IMX6DQ
(IMX6DUAL/IMX6QUAD) and IMX6SDL (IMX6SOLO/IMX6DUALLITE) types the iomux
registers differ. This requires two sets of structures.

Add structures to describe DDR3 device information, system information
(memory layout, etc), and MMDC calibration regitsers that can be used to
configure the MMDC dynamically.

We define these structures for SPL builds instead of including mx6q-ddr.h and
mx6dl-ddr.h which use the same namespace and are only useful for imximage cfg
files.

Signed-off-by: Tim Harvey <tharvey@gateworks.com>
---
v2:
- split out from original mmdc configuration patch
- only define for SPL build
- do not include mx6q-ddr.h and mx6dl-ddr.h for SPL build - these use the
  same namespace and are only useful for imximage cfg files
---
 arch/arm/include/asm/arch-mx6/mx6-ddr.h | 231 ++++++++++++++++++++++++++++++++
 1 file changed, 231 insertions(+)

Comments

Eric Nelson April 29, 2014, 2:20 p.m. UTC | #1
Hi Tim,

On 04/28/2014 01:17 PM, Tim Harvey wrote:
> Add memory-mapped structures for MMDC iomux and configuration. Note that while
> the MMDC configuration registers are common between the IMX6DQ
> (IMX6DUAL/IMX6QUAD) and IMX6SDL (IMX6SOLO/IMX6DUALLITE) types the iomux
> registers differ. This requires two sets of structures.
>
> Add structures to describe DDR3 device information, system information
> (memory layout, etc), and MMDC calibration regitsers that can be used to
> configure the MMDC dynamically.
>
> We define these structures for SPL builds instead of including mx6q-ddr.h and
> mx6dl-ddr.h which use the same namespace and are only useful for imximage cfg
> files.
>
> Signed-off-by: Tim Harvey <tharvey@gateworks.com>
> ---
> v2:
> - split out from original mmdc configuration patch
> - only define for SPL build
> - do not include mx6q-ddr.h and mx6dl-ddr.h for SPL build - these use the
>    same namespace and are only useful for imximage cfg files
> ---
>   arch/arm/include/asm/arch-mx6/mx6-ddr.h | 231 ++++++++++++++++++++++++++++++++
>   1 file changed, 231 insertions(+)
>
> diff --git a/arch/arm/include/asm/arch-mx6/mx6-ddr.h b/arch/arm/include/asm/arch-mx6/mx6-ddr.h
> index 43d377a..d544d2e 100644
> --- a/arch/arm/include/asm/arch-mx6/mx6-ddr.h
> +++ b/arch/arm/include/asm/arch-mx6/mx6-ddr.h
> @@ -6,6 +6,7 @@
>   #ifndef __ASM_ARCH_MX6_DDR_H__
>   #define __ASM_ARCH_MX6_DDR_H__
>
> +#ifndef CONFIG_SPL_BUILD
>   #ifdef CONFIG_MX6Q
>   #include "mx6q-ddr.h"
>   #else
> @@ -15,6 +16,236 @@
>   #error "Please select cpu"
>   #endif	/* CONFIG_MX6DL or CONFIG_MX6S */
>   #endif	/* CONFIG_MX6Q */
> +#else
> +

This part of the patch matches the commit message for patch 7.

> +/* MMDC P0/P1 Registers */
> +struct mmdc_p_regs {
> +	u32 mdctl;
> +	u32 mdpdc;
> +	u32 mdotc;
> +	u32 mdcfg0;
> +	u32 mdcfg1;
> +	u32 mdcfg2;
> +	u32 mdmisc;
> +	u32 mdscr;
>
 > ...
 >

The following bits should probably be moved into patch 8 though:

> +
> +/* Device Information: Varies per DDR3 part number and speed grade */
> +struct mx6_ddr3_cfg {
> +	u16 mem_speed;	/* ie 1600 for DDR3-1600 (800,1066,1333,1600) */
> +	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) */
> +	u8 pagesz;	/* page size (K) (1-2) */
> +	u16 trcd;	/* tRCD=tRP=CL (ns*100) */
> +	u16 trcmin;	/* tRC min (ns*100) */
> +	u16 trasmin;	/* tRAS min (ns*100) */
> +	u8 SRT;		/* self-refresh temperature: 0=normal, 1=extended */
> +};
> +
> +/* 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) */
> +	u8 cs_density;	/* density per chip select (Gb) */
> +	u8 ncs;		/* number chip selects used (1|2) */
> +	char cs1_mirror;/* enable address mirror (0|1) */
> +	char bi_on;	/* Bank interleaving enable */
> +	u8 rtt_nom;	/* Rtt_Nom (DDR3_RTT_*) */
> +	u8 rtt_wr;	/* Rtt_Wr (DDR3_RTT_*) */
> +	u8 ralat;	/* Read Additional Latency (0-7) */
> +	u8 walat;	/* Write Additional Latency (0-3) */
> +	u8 mif3_mode;	/* Command prediction working mode */
> +	u8 rst_to_cke;	/* Time from SDE enable to CKE rise */
> +	u8 sde_to_rst;	/* Time from SDE enable until DDR reset# is high */
> +};
> +
> +/*
> + * Board specific calibration:
> + *   This includes write leveling calibration values as well as DQS gating
> + *   and read/write delays. These values are board/layout/device specific.
> + *   Freescale recommends using the i.MX6 DDR Stress Test Tool V1.0.2
> + *   (DOC-96412) to determine these values over a range of boards and
> + *   temperatures.
> + */
> +struct mx6_mmdc_calibration {
> +	/* write leveling calibration */
> +	u32 p0_mpwldectrl0;
> +	u32 p0_mpwldectrl1;
> +	u32 p1_mpwldectrl0;
> +	u32 p1_mpwldectrl1;
> +	/* read DQS gating */
> +	u32 p0_mpdgctrl0;
> +	u32 p0_mpdgctrl1;
> +	u32 p1_mpdgctrl0;
> +	u32 p1_mpdgctrl1;
> +	/* read delay */
> +	u32 p0_mprddlctl;
> +	u32 p1_mprddlctl;
> +	/* write delay */
> +	u32 p0_mpwrdlctl;
> +	u32 p1_mpwrdlctl;
> +};

Nicely done!

This partitioning of chip-level, design-level, and calibration data
makes perfect sense.

> +
> +/* configure iomux (pinctl/padctl) */
> +void mx6dq_dram_iocfg(unsigned width,
> +		      const struct mx6dq_iomux_ddr_regs *,
> +		      const struct mx6dq_iomux_grp_regs *);
> +void mx6sdl_dram_iocfg(unsigned width,
> +		       const struct mx6sdl_iomux_ddr_regs *,
> +		       const struct mx6sdl_iomux_grp_regs *);
> +
> +/* configure mx6 mmdc registers */
> +void mx6_dram_cfg(const struct mx6_ddr_sysinfo *,
> +		  const struct mx6_mmdc_calibration *,
> +		  const struct mx6_ddr3_cfg *);
> +
> +#endif /* CONFIG_SPL_BUILD */
>
>   #define MX6_MMDC_P0_MDCTL	0x021b0000
>   #define MX6_MMDC_P0_MDPDC	0x021b0004
>

Regards,


Eric
Stefano Babic May 5, 2014, 10:34 a.m. UTC | #2
Hi Tim,

On 28/04/2014 22:17, Tim Harvey wrote:
> Add memory-mapped structures for MMDC iomux and configuration. Note that while
> the MMDC configuration registers are common between the IMX6DQ
> (IMX6DUAL/IMX6QUAD) and IMX6SDL (IMX6SOLO/IMX6DUALLITE) types the iomux
> registers differ. This requires two sets of structures.
> 
> Add structures to describe DDR3 device information, system information
> (memory layout, etc), and MMDC calibration regitsers that can be used to
> configure the MMDC dynamically.
> 
> We define these structures for SPL builds instead of including mx6q-ddr.h and
> mx6dl-ddr.h which use the same namespace and are only useful for imximage cfg
> files.
> 
> Signed-off-by: Tim Harvey <tharvey@gateworks.com>
> ---
> v2:
> - split out from original mmdc configuration patch
> - only define for SPL build
> - do not include mx6q-ddr.h and mx6dl-ddr.h for SPL build - these use the
>   same namespace and are only useful for imximage cfg files
> ---
>  arch/arm/include/asm/arch-mx6/mx6-ddr.h | 231 ++++++++++++++++++++++++++++++++
>  1 file changed, 231 insertions(+)
> 
> diff --git a/arch/arm/include/asm/arch-mx6/mx6-ddr.h b/arch/arm/include/asm/arch-mx6/mx6-ddr.h
> index 43d377a..d544d2e 100644
> --- a/arch/arm/include/asm/arch-mx6/mx6-ddr.h
> +++ b/arch/arm/include/asm/arch-mx6/mx6-ddr.h
> @@ -6,6 +6,7 @@
>  #ifndef __ASM_ARCH_MX6_DDR_H__
>  #define __ASM_ARCH_MX6_DDR_H__
>  
> +#ifndef CONFIG_SPL_BUILD
>  #ifdef CONFIG_MX6Q
>  #include "mx6q-ddr.h"
>  #else
> @@ -15,6 +16,236 @@
>  #error "Please select cpu"
>  #endif	/* CONFIG_MX6DL or CONFIG_MX6S */
>  #endif	/* CONFIG_MX6Q */
> +#else
> +
> +/* MMDC P0/P1 Registers */
> +struct mmdc_p_regs {
> +	u32 mdctl;
> +	u32 mdpdc;
> +	u32 mdotc;
> +	u32 mdcfg0;
> +	u32 mdcfg1;
> +	u32 mdcfg2;
> +	u32 mdmisc;
> +	u32 mdscr;
> +	u32 mdref;
> +	u32 res1[2];
> +	u32 mdrwd;
> +	u32 mdor;
> +	u32 res2[3];
> +	u32 mdasp;
> +	u32 res3[240];
> +	u32 mapsr;
> +	u32 res4[254];
> +	u32 mpzqhwctrl;
> +	u32 res5[2];
> +	u32 mpwldectrl0;
> +	u32 mpwldectrl1;
> +	u32 res6;
> +	u32 mpodtctrl;
> +	u32 mprddqby0dl;
> +	u32 mprddqby1dl;
> +	u32 mprddqby2dl;
> +	u32 mprddqby3dl;
> +	u32 res7[4];
> +	u32 mpdgctrl0;
> +	u32 mpdgctrl1;
> +	u32 res8;
> +	u32 mprddlctl;
> +	u32 res9;
> +	u32 mpwrdlctl;
> +	u32 res10[25];
> +	u32 mpmur0;
> +};
> +
> +/*
> + * MMDC iomux registers (pinctl/padctl) - (different for IMX6DQ vs IMX6SDL)
> + */
> +#define MX6DQ_IOM_DDR_BASE      0x020e0500

It is only a question - having the value here let us know where the
registers are located. Anyway, registers' offsets are stored in the
imx-regs.h file of the SOC. Which is the reason to set them here ?

> +struct mx6dq_iomux_ddr_regs {
> +	u32 res1[3];
> +	u32 dram_sdqs5;
> +	u32 dram_dqm5;
> +	u32 dram_dqm4;
> +	u32 dram_sdqs4;
> +	u32 dram_sdqs3;
> +	u32 dram_dqm3;
> +	u32 dram_sdqs2;
> +	u32 dram_dqm2;
> +	u32 res2[16];
> +	u32 dram_cas;
> +	u32 res3[2];
> +	u32 dram_ras;
> +	u32 dram_reset;
> +	u32 res4[2];
> +	u32 dram_sdclk_0;
> +	u32 dram_sdba2;
> +	u32 dram_sdcke0;
> +	u32 dram_sdclk_1;
> +	u32 dram_sdcke1;
> +	u32 dram_sdodt0;
> +	u32 dram_sdodt1;
> +	u32 res5;
> +	u32 dram_sdqs0;
> +	u32 dram_dqm0;
> +	u32 dram_sdqs1;
> +	u32 dram_dqm1;
> +	u32 dram_sdqs6;
> +	u32 dram_dqm6;
> +	u32 dram_sdqs7;
> +	u32 dram_dqm7;
> +};
> +
> +#define MX6DQ_IOM_GRP_BASE      0x020e0700
> +struct mx6dq_iomux_grp_regs {
> +	u32 res1[18];
> +	u32 grp_b7ds;
> +	u32 grp_addds;
> +	u32 grp_ddrmode_ctl;
> +	u32 res2;
> +	u32 grp_ddrpke;
> +	u32 res3[6];
> +	u32 grp_ddrmode;
> +	u32 res4[3];
> +	u32 grp_b0ds;
> +	u32 grp_b1ds;
> +	u32 grp_ctlds;
> +	u32 res5;
> +	u32 grp_b2ds;
> +	u32 grp_ddr_type;
> +	u32 grp_b3ds;
> +	u32 grp_b4ds;
> +	u32 grp_b5ds;
> +	u32 grp_b6ds;
> +};
> +
> +#define MX6SDL_IOM_DDR_BASE     0x020e0400
> +struct mx6sdl_iomux_ddr_regs {
> +	u32 res1[25];
> +	u32 dram_cas;
> +	u32 res2[2];
> +	u32 dram_dqm0;
> +	u32 dram_dqm1;
> +	u32 dram_dqm2;
> +	u32 dram_dqm3;
> +	u32 dram_dqm4;
> +	u32 dram_dqm5;
> +	u32 dram_dqm6;
> +	u32 dram_dqm7;
> +	u32 dram_ras;
> +	u32 dram_reset;
> +	u32 res3[2];
> +	u32 dram_sdba2;
> +	u32 dram_sdcke0;
> +	u32 dram_sdcke1;
> +	u32 dram_sdclk_0;
> +	u32 dram_sdclk_1;
> +	u32 dram_sdodt0;
> +	u32 dram_sdodt1;
> +	u32 dram_sdqs0;
> +	u32 dram_sdqs1;
> +	u32 dram_sdqs2;
> +	u32 dram_sdqs3;
> +	u32 dram_sdqs4;
> +	u32 dram_sdqs5;
> +	u32 dram_sdqs6;
> +	u32 dram_sdqs7;
> +};
> +
> +#define MX6SDL_IOM_GRP_BASE     0x020e0700
> +struct mx6sdl_iomux_grp_regs {
> +	u32 res1[18];
> +	u32 grp_b7ds;
> +	u32 grp_addds;
> +	u32 grp_ddrmode_ctl;
> +	u32 grp_ddrpke;
> +	u32 res2[2];
> +	u32 grp_ddrmode;
> +	u32 grp_b0ds;
> +	u32 res3;
> +	u32 grp_ctlds;
> +	u32 grp_b1ds;
> +	u32 grp_ddr_type;
> +	u32 grp_b2ds;
> +	u32 grp_b3ds;
> +	u32 grp_b4ds;
> +	u32 grp_b5ds;
> +	u32 res4;
> +	u32 grp_b6ds;
> +};
> +
> +/* Device Information: Varies per DDR3 part number and speed grade */
> +struct mx6_ddr3_cfg {
> +	u16 mem_speed;	/* ie 1600 for DDR3-1600 (800,1066,1333,1600) */
> +	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) */
> +	u8 pagesz;	/* page size (K) (1-2) */
> +	u16 trcd;	/* tRCD=tRP=CL (ns*100) */
> +	u16 trcmin;	/* tRC min (ns*100) */
> +	u16 trasmin;	/* tRAS min (ns*100) */
> +	u8 SRT;		/* self-refresh temperature: 0=normal, 1=extended */
> +};
> +
> +/* 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) */
> +	u8 cs_density;	/* density per chip select (Gb) */
> +	u8 ncs;		/* number chip selects used (1|2) */
> +	char cs1_mirror;/* enable address mirror (0|1) */
> +	char bi_on;	/* Bank interleaving enable */
> +	u8 rtt_nom;	/* Rtt_Nom (DDR3_RTT_*) */
> +	u8 rtt_wr;	/* Rtt_Wr (DDR3_RTT_*) */
> +	u8 ralat;	/* Read Additional Latency (0-7) */
> +	u8 walat;	/* Write Additional Latency (0-3) */
> +	u8 mif3_mode;	/* Command prediction working mode */
> +	u8 rst_to_cke;	/* Time from SDE enable to CKE rise */
> +	u8 sde_to_rst;	/* Time from SDE enable until DDR reset# is high */
> +};
> +
> +/*
> + * Board specific calibration:
> + *   This includes write leveling calibration values as well as DQS gating
> + *   and read/write delays. These values are board/layout/device specific.
> + *   Freescale recommends using the i.MX6 DDR Stress Test Tool V1.0.2
> + *   (DOC-96412) to determine these values over a range of boards and
> + *   temperatures.
> + */
> +struct mx6_mmdc_calibration {
> +	/* write leveling calibration */
> +	u32 p0_mpwldectrl0;
> +	u32 p0_mpwldectrl1;
> +	u32 p1_mpwldectrl0;
> +	u32 p1_mpwldectrl1;
> +	/* read DQS gating */
> +	u32 p0_mpdgctrl0;
> +	u32 p0_mpdgctrl1;
> +	u32 p1_mpdgctrl0;
> +	u32 p1_mpdgctrl1;
> +	/* read delay */
> +	u32 p0_mprddlctl;
> +	u32 p1_mprddlctl;
> +	/* write delay */
> +	u32 p0_mpwrdlctl;
> +	u32 p1_mpwrdlctl;
> +};
> +

I agree on theses structures. It is then simpler for a board maintainer
to understand what is required to add SPL support for the own board.

> +/* configure iomux (pinctl/padctl) */
> +void mx6dq_dram_iocfg(unsigned width,
> +		      const struct mx6dq_iomux_ddr_regs *,
> +		      const struct mx6dq_iomux_grp_regs *);
> +void mx6sdl_dram_iocfg(unsigned width,
> +		       const struct mx6sdl_iomux_ddr_regs *,
> +		       const struct mx6sdl_iomux_grp_regs *);
> +
> +/* configure mx6 mmdc registers */
> +void mx6_dram_cfg(const struct mx6_ddr_sysinfo *,
> +		  const struct mx6_mmdc_calibration *,
> +		  const struct mx6_ddr3_cfg *);
> +
> +#endif /* CONFIG_SPL_BUILD */
>  
>  #define MX6_MMDC_P0_MDCTL	0x021b0000
>  #define MX6_MMDC_P0_MDPDC	0x021b0004
> 

Best regards,
Stefano Babic
Tim Harvey May 5, 2014, 3:52 p.m. UTC | #3
On Mon, May 5, 2014 at 3:34 AM, Stefano Babic <sbabic@denx.de> wrote:
> Hi Tim,
>
> On 28/04/2014 22:17, Tim Harvey wrote:
>> Add memory-mapped structures for MMDC iomux and configuration. Note that while
>> the MMDC configuration registers are common between the IMX6DQ
>> (IMX6DUAL/IMX6QUAD) and IMX6SDL (IMX6SOLO/IMX6DUALLITE) types the iomux
>> registers differ. This requires two sets of structures.
>>
>> Add structures to describe DDR3 device information, system information
>> (memory layout, etc), and MMDC calibration regitsers that can be used to
>> configure the MMDC dynamically.
>>
>> We define these structures for SPL builds instead of including mx6q-ddr.h and
>> mx6dl-ddr.h which use the same namespace and are only useful for imximage cfg
>> files.
>>
>> Signed-off-by: Tim Harvey <tharvey@gateworks.com>
>> ---
>> v2:
>> - split out from original mmdc configuration patch
>> - only define for SPL build
>> - do not include mx6q-ddr.h and mx6dl-ddr.h for SPL build - these use the
>>   same namespace and are only useful for imximage cfg files
>> ---
>>  arch/arm/include/asm/arch-mx6/mx6-ddr.h | 231 ++++++++++++++++++++++++++++++++
>>  1 file changed, 231 insertions(+)
>>
>> diff --git a/arch/arm/include/asm/arch-mx6/mx6-ddr.h b/arch/arm/include/asm/arch-mx6/mx6-ddr.h
>> index 43d377a..d544d2e 100644
>> --- a/arch/arm/include/asm/arch-mx6/mx6-ddr.h
>> +++ b/arch/arm/include/asm/arch-mx6/mx6-ddr.h
>> @@ -6,6 +6,7 @@
>>  #ifndef __ASM_ARCH_MX6_DDR_H__
>>  #define __ASM_ARCH_MX6_DDR_H__
>>
>> +#ifndef CONFIG_SPL_BUILD
>>  #ifdef CONFIG_MX6Q
>>  #include "mx6q-ddr.h"
>>  #else
>> @@ -15,6 +16,236 @@
>>  #error "Please select cpu"
>>  #endif       /* CONFIG_MX6DL or CONFIG_MX6S */
>>  #endif       /* CONFIG_MX6Q */
>> +#else
>> +
>> +/* MMDC P0/P1 Registers */
>> +struct mmdc_p_regs {
>> +     u32 mdctl;
>> +     u32 mdpdc;
>> +     u32 mdotc;
>> +     u32 mdcfg0;
>> +     u32 mdcfg1;
>> +     u32 mdcfg2;
>> +     u32 mdmisc;
>> +     u32 mdscr;
>> +     u32 mdref;
>> +     u32 res1[2];
>> +     u32 mdrwd;
>> +     u32 mdor;
>> +     u32 res2[3];
>> +     u32 mdasp;
>> +     u32 res3[240];
>> +     u32 mapsr;
>> +     u32 res4[254];
>> +     u32 mpzqhwctrl;
>> +     u32 res5[2];
>> +     u32 mpwldectrl0;
>> +     u32 mpwldectrl1;
>> +     u32 res6;
>> +     u32 mpodtctrl;
>> +     u32 mprddqby0dl;
>> +     u32 mprddqby1dl;
>> +     u32 mprddqby2dl;
>> +     u32 mprddqby3dl;
>> +     u32 res7[4];
>> +     u32 mpdgctrl0;
>> +     u32 mpdgctrl1;
>> +     u32 res8;
>> +     u32 mprddlctl;
>> +     u32 res9;
>> +     u32 mpwrdlctl;
>> +     u32 res10[25];
>> +     u32 mpmur0;
>> +};
>> +
>> +/*
>> + * MMDC iomux registers (pinctl/padctl) - (different for IMX6DQ vs IMX6SDL)
>> + */
>> +#define MX6DQ_IOM_DDR_BASE      0x020e0500
>
> It is only a question - having the value here let us know where the
> registers are located. Anyway, registers' offsets are stored in the
> imx-regs.h file of the SOC. Which is the reason to set them here ?

I felt they belonged with the ddr structures themselves. I can move
them but then will someone claim that the ddr structures should also
be moved?

Tim
diff mbox

Patch

diff --git a/arch/arm/include/asm/arch-mx6/mx6-ddr.h b/arch/arm/include/asm/arch-mx6/mx6-ddr.h
index 43d377a..d544d2e 100644
--- a/arch/arm/include/asm/arch-mx6/mx6-ddr.h
+++ b/arch/arm/include/asm/arch-mx6/mx6-ddr.h
@@ -6,6 +6,7 @@ 
 #ifndef __ASM_ARCH_MX6_DDR_H__
 #define __ASM_ARCH_MX6_DDR_H__
 
+#ifndef CONFIG_SPL_BUILD
 #ifdef CONFIG_MX6Q
 #include "mx6q-ddr.h"
 #else
@@ -15,6 +16,236 @@ 
 #error "Please select cpu"
 #endif	/* CONFIG_MX6DL or CONFIG_MX6S */
 #endif	/* CONFIG_MX6Q */
+#else
+
+/* MMDC P0/P1 Registers */
+struct mmdc_p_regs {
+	u32 mdctl;
+	u32 mdpdc;
+	u32 mdotc;
+	u32 mdcfg0;
+	u32 mdcfg1;
+	u32 mdcfg2;
+	u32 mdmisc;
+	u32 mdscr;
+	u32 mdref;
+	u32 res1[2];
+	u32 mdrwd;
+	u32 mdor;
+	u32 res2[3];
+	u32 mdasp;
+	u32 res3[240];
+	u32 mapsr;
+	u32 res4[254];
+	u32 mpzqhwctrl;
+	u32 res5[2];
+	u32 mpwldectrl0;
+	u32 mpwldectrl1;
+	u32 res6;
+	u32 mpodtctrl;
+	u32 mprddqby0dl;
+	u32 mprddqby1dl;
+	u32 mprddqby2dl;
+	u32 mprddqby3dl;
+	u32 res7[4];
+	u32 mpdgctrl0;
+	u32 mpdgctrl1;
+	u32 res8;
+	u32 mprddlctl;
+	u32 res9;
+	u32 mpwrdlctl;
+	u32 res10[25];
+	u32 mpmur0;
+};
+
+/*
+ * MMDC iomux registers (pinctl/padctl) - (different for IMX6DQ vs IMX6SDL)
+ */
+#define MX6DQ_IOM_DDR_BASE      0x020e0500
+struct mx6dq_iomux_ddr_regs {
+	u32 res1[3];
+	u32 dram_sdqs5;
+	u32 dram_dqm5;
+	u32 dram_dqm4;
+	u32 dram_sdqs4;
+	u32 dram_sdqs3;
+	u32 dram_dqm3;
+	u32 dram_sdqs2;
+	u32 dram_dqm2;
+	u32 res2[16];
+	u32 dram_cas;
+	u32 res3[2];
+	u32 dram_ras;
+	u32 dram_reset;
+	u32 res4[2];
+	u32 dram_sdclk_0;
+	u32 dram_sdba2;
+	u32 dram_sdcke0;
+	u32 dram_sdclk_1;
+	u32 dram_sdcke1;
+	u32 dram_sdodt0;
+	u32 dram_sdodt1;
+	u32 res5;
+	u32 dram_sdqs0;
+	u32 dram_dqm0;
+	u32 dram_sdqs1;
+	u32 dram_dqm1;
+	u32 dram_sdqs6;
+	u32 dram_dqm6;
+	u32 dram_sdqs7;
+	u32 dram_dqm7;
+};
+
+#define MX6DQ_IOM_GRP_BASE      0x020e0700
+struct mx6dq_iomux_grp_regs {
+	u32 res1[18];
+	u32 grp_b7ds;
+	u32 grp_addds;
+	u32 grp_ddrmode_ctl;
+	u32 res2;
+	u32 grp_ddrpke;
+	u32 res3[6];
+	u32 grp_ddrmode;
+	u32 res4[3];
+	u32 grp_b0ds;
+	u32 grp_b1ds;
+	u32 grp_ctlds;
+	u32 res5;
+	u32 grp_b2ds;
+	u32 grp_ddr_type;
+	u32 grp_b3ds;
+	u32 grp_b4ds;
+	u32 grp_b5ds;
+	u32 grp_b6ds;
+};
+
+#define MX6SDL_IOM_DDR_BASE     0x020e0400
+struct mx6sdl_iomux_ddr_regs {
+	u32 res1[25];
+	u32 dram_cas;
+	u32 res2[2];
+	u32 dram_dqm0;
+	u32 dram_dqm1;
+	u32 dram_dqm2;
+	u32 dram_dqm3;
+	u32 dram_dqm4;
+	u32 dram_dqm5;
+	u32 dram_dqm6;
+	u32 dram_dqm7;
+	u32 dram_ras;
+	u32 dram_reset;
+	u32 res3[2];
+	u32 dram_sdba2;
+	u32 dram_sdcke0;
+	u32 dram_sdcke1;
+	u32 dram_sdclk_0;
+	u32 dram_sdclk_1;
+	u32 dram_sdodt0;
+	u32 dram_sdodt1;
+	u32 dram_sdqs0;
+	u32 dram_sdqs1;
+	u32 dram_sdqs2;
+	u32 dram_sdqs3;
+	u32 dram_sdqs4;
+	u32 dram_sdqs5;
+	u32 dram_sdqs6;
+	u32 dram_sdqs7;
+};
+
+#define MX6SDL_IOM_GRP_BASE     0x020e0700
+struct mx6sdl_iomux_grp_regs {
+	u32 res1[18];
+	u32 grp_b7ds;
+	u32 grp_addds;
+	u32 grp_ddrmode_ctl;
+	u32 grp_ddrpke;
+	u32 res2[2];
+	u32 grp_ddrmode;
+	u32 grp_b0ds;
+	u32 res3;
+	u32 grp_ctlds;
+	u32 grp_b1ds;
+	u32 grp_ddr_type;
+	u32 grp_b2ds;
+	u32 grp_b3ds;
+	u32 grp_b4ds;
+	u32 grp_b5ds;
+	u32 res4;
+	u32 grp_b6ds;
+};
+
+/* Device Information: Varies per DDR3 part number and speed grade */
+struct mx6_ddr3_cfg {
+	u16 mem_speed;	/* ie 1600 for DDR3-1600 (800,1066,1333,1600) */
+	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) */
+	u8 pagesz;	/* page size (K) (1-2) */
+	u16 trcd;	/* tRCD=tRP=CL (ns*100) */
+	u16 trcmin;	/* tRC min (ns*100) */
+	u16 trasmin;	/* tRAS min (ns*100) */
+	u8 SRT;		/* self-refresh temperature: 0=normal, 1=extended */
+};
+
+/* 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) */
+	u8 cs_density;	/* density per chip select (Gb) */
+	u8 ncs;		/* number chip selects used (1|2) */
+	char cs1_mirror;/* enable address mirror (0|1) */
+	char bi_on;	/* Bank interleaving enable */
+	u8 rtt_nom;	/* Rtt_Nom (DDR3_RTT_*) */
+	u8 rtt_wr;	/* Rtt_Wr (DDR3_RTT_*) */
+	u8 ralat;	/* Read Additional Latency (0-7) */
+	u8 walat;	/* Write Additional Latency (0-3) */
+	u8 mif3_mode;	/* Command prediction working mode */
+	u8 rst_to_cke;	/* Time from SDE enable to CKE rise */
+	u8 sde_to_rst;	/* Time from SDE enable until DDR reset# is high */
+};
+
+/*
+ * Board specific calibration:
+ *   This includes write leveling calibration values as well as DQS gating
+ *   and read/write delays. These values are board/layout/device specific.
+ *   Freescale recommends using the i.MX6 DDR Stress Test Tool V1.0.2
+ *   (DOC-96412) to determine these values over a range of boards and
+ *   temperatures.
+ */
+struct mx6_mmdc_calibration {
+	/* write leveling calibration */
+	u32 p0_mpwldectrl0;
+	u32 p0_mpwldectrl1;
+	u32 p1_mpwldectrl0;
+	u32 p1_mpwldectrl1;
+	/* read DQS gating */
+	u32 p0_mpdgctrl0;
+	u32 p0_mpdgctrl1;
+	u32 p1_mpdgctrl0;
+	u32 p1_mpdgctrl1;
+	/* read delay */
+	u32 p0_mprddlctl;
+	u32 p1_mprddlctl;
+	/* write delay */
+	u32 p0_mpwrdlctl;
+	u32 p1_mpwrdlctl;
+};
+
+/* configure iomux (pinctl/padctl) */
+void mx6dq_dram_iocfg(unsigned width,
+		      const struct mx6dq_iomux_ddr_regs *,
+		      const struct mx6dq_iomux_grp_regs *);
+void mx6sdl_dram_iocfg(unsigned width,
+		       const struct mx6sdl_iomux_ddr_regs *,
+		       const struct mx6sdl_iomux_grp_regs *);
+
+/* configure mx6 mmdc registers */
+void mx6_dram_cfg(const struct mx6_ddr_sysinfo *,
+		  const struct mx6_mmdc_calibration *,
+		  const struct mx6_ddr3_cfg *);
+
+#endif /* CONFIG_SPL_BUILD */
 
 #define MX6_MMDC_P0_MDCTL	0x021b0000
 #define MX6_MMDC_P0_MDPDC	0x021b0004