All the mail mirrored from lore.kernel.org
 help / color / mirror / Atom feed
* [U-Boot] [PATCH 0/5] Add support for Vybrid VF610-based PCM052
@ 2015-06-19 12:18 Albert ARIBAUD
  2015-06-19 12:18 ` [U-Boot] [PATCH 1/5] net: fec_mxc: remove useless struct nbuf Albert ARIBAUD
  0 siblings, 1 reply; 24+ messages in thread
From: Albert ARIBAUD @ 2015-06-19 12:18 UTC (permalink / raw)
  To: u-boot

This patch series introduces the vf610-based PCM052 target after
a few fixes to the vf610 code.

As indicated in the last patch in the series, there is a bug in
the FEC whereby it wrongly reports having sent out a packet. This
bug does not seem specific to PCM052, and it also seems to appear
in the TimeSys U-Boot deliveries and also in Linux, with varying
frequencies.

NOTE: this series is not checkpatch-clean. It has:

- 51 "line over 80 characters" warnings. These lines are in a
  block for which the line lenght limit was obviously waived.
  arch/arm/include/asm/arch-vf610/iomux-vf610.h has 5 of these;
  board/phytec/pcm052/pcm052.c has the remaining 50.

- 1 "please write a paragraph that describes the config symbol
  fully" warning for arch/arm/Kconfig. There are no such descriptions
  for any target in this file.

- 1 "need consistent spacing around '|' (ctx:WxV)" error in
  board/phytec/pcm052/pcm052.c at line 98. It seems spurious to me,
  as this construct has the exact same spacing as all others in the
  file.


Albert ARIBAUD (3ADEV) (5):
  net: fec_mxc: remove useless struct nbuf
  vf610: refactor DDRMC code
  i2c: fix vf610 support
  tools: mkimage: fix imximage header size
  vf610: add support for Phytec PCM052

 arch/arm/Kconfig                              |   5 +
 arch/arm/imx-common/ddrmc-vf610.c             | 239 +++---------
 arch/arm/include/asm/arch-vf610/crm_regs.h    |   3 +
 arch/arm/include/asm/arch-vf610/ddrmc-vf610.h |  60 +--
 arch/arm/include/asm/arch-vf610/imx-regs.h    |   3 +
 arch/arm/include/asm/arch-vf610/iomux-vf610.h |  11 +-
 arch/arm/include/asm/imx-common/iomux-v3.h    |   2 +
 board/freescale/vf610twr/vf610twr.c           | 181 ++++++---
 board/phytec/pcm052/Kconfig                   |  15 +
 board/phytec/pcm052/MAINTAINERS               |   6 +
 board/phytec/pcm052/Makefile                  |   7 +
 board/phytec/pcm052/imximage.cfg              |  17 +
 board/phytec/pcm052/pcm052.c                  | 530 ++++++++++++++++++++++++++
 board/toradex/colibri_vf/colibri_vf.c         | 169 ++++++--
 configs/pcm052_defconfig                      |   6 +
 drivers/i2c/mxc_i2c.c                         |   3 +-
 drivers/net/fec_mxc.c                         |  20 +-
 include/configs/pcm052.h                      | 234 ++++++++++++
 tools/imximage.h                              |   1 +
 19 files changed, 1155 insertions(+), 357 deletions(-)
 create mode 100644 board/phytec/pcm052/Kconfig
 create mode 100644 board/phytec/pcm052/MAINTAINERS
 create mode 100644 board/phytec/pcm052/Makefile
 create mode 100644 board/phytec/pcm052/imximage.cfg
 create mode 100644 board/phytec/pcm052/pcm052.c
 create mode 100644 configs/pcm052_defconfig
 create mode 100644 include/configs/pcm052.h

-- 
2.1.0

^ permalink raw reply	[flat|nested] 24+ messages in thread

* [U-Boot] [PATCH 1/5] net: fec_mxc: remove useless struct nbuf
  2015-06-19 12:18 [U-Boot] [PATCH 0/5] Add support for Vybrid VF610-based PCM052 Albert ARIBAUD
@ 2015-06-19 12:18 ` Albert ARIBAUD
  2015-06-19 12:18   ` [U-Boot] [PATCH 2/5] vf610: refactor DDRMC code Albert ARIBAUD
                     ` (2 more replies)
  0 siblings, 3 replies; 24+ messages in thread
From: Albert ARIBAUD @ 2015-06-19 12:18 UTC (permalink / raw)
  To: u-boot

This locally defined struct is actually only used once
and as an opaque type. Remove it for clarity.

Signed-off-by: Albert ARIBAUD (3ADEV) <albert.aribaud@3adev.fr>
---

 drivers/net/fec_mxc.c | 20 +++++---------------
 1 file changed, 5 insertions(+), 15 deletions(-)

diff --git a/drivers/net/fec_mxc.c b/drivers/net/fec_mxc.c
index 9225d37..c5dcbbb 100644
--- a/drivers/net/fec_mxc.c
+++ b/drivers/net/fec_mxc.c
@@ -67,13 +67,6 @@ DECLARE_GLOBAL_DATA_PTR;
 
 #undef DEBUG
 
-struct nbuf {
-	uint8_t data[1500];	/**< actual data */
-	int length;		/**< actual length */
-	int used;		/**< buffer in use or not */
-	uint8_t head[16];	/**< MAC header(6 + 6 + 2) + 2(aligned) */
-};
-
 #ifdef CONFIG_FEC_MXC_SWAP_PACKET
 static void swap_packet(uint32_t *packet, int length)
 {
@@ -775,7 +768,6 @@ static int fec_recv(struct eth_device *dev)
 	struct fec_bd *rbd = &fec->rbd_base[fec->rbd_index];
 	unsigned long ievent;
 	int frame_length, len = 0;
-	struct nbuf *frame;
 	uint16_t bd_status;
 	uint32_t addr, size, end;
 	int i;
@@ -835,12 +827,11 @@ static int fec_recv(struct eth_device *dev)
 			/*
 			 * Get buffer address and size
 			 */
-			frame = (struct nbuf *)readl(&rbd->data_pointer);
+			addr = readl(&rbd->data_pointer);
 			frame_length = readw(&rbd->data_length) - 4;
 			/*
 			 * Invalidate data cache over the buffer
 			 */
-			addr = (uint32_t)frame;
 			end = roundup(addr + frame_length, ARCH_DMA_MINALIGN);
 			addr &= ~(ARCH_DMA_MINALIGN - 1);
 			invalidate_dcache_range(addr, end);
@@ -849,16 +840,15 @@ static int fec_recv(struct eth_device *dev)
 			 *  Fill the buffer and pass it to upper layers
 			 */
 #ifdef CONFIG_FEC_MXC_SWAP_PACKET
-			swap_packet((uint32_t *)frame->data, frame_length);
+			swap_packet((uint32_t *)addr, frame_length);
 #endif
-			memcpy(buff, frame->data, frame_length);
+			memcpy(buff, (char *)addr, frame_length);
 			net_process_received_packet(buff, frame_length);
 			len = frame_length;
 		} else {
 			if (bd_status & FEC_RBD_ERR)
-				printf("error frame: 0x%08lx 0x%08x\n",
-						(ulong)rbd->data_pointer,
-						bd_status);
+				printf("error frame: 0x%08x 0x%08x\n",
+				       addr, bd_status);
 		}
 
 		/*
-- 
2.1.0

^ permalink raw reply related	[flat|nested] 24+ messages in thread

* [U-Boot] [PATCH 2/5] vf610: refactor DDRMC code
  2015-06-19 12:18 ` [U-Boot] [PATCH 1/5] net: fec_mxc: remove useless struct nbuf Albert ARIBAUD
@ 2015-06-19 12:18   ` Albert ARIBAUD
  2015-06-19 12:18     ` [U-Boot] [PATCH 3/5] i2c: fix vf610 support Albert ARIBAUD
  2015-06-19 15:13     ` [U-Boot] [PATCH 2/5] vf610: refactor DDRMC code Stefan Agner
  2015-06-19 15:38   ` [U-Boot] [PATCH 1/5] net: fec_mxc: remove useless struct nbuf Joe Hershberger
  2015-07-10  8:03   ` Stefano Babic
  2 siblings, 2 replies; 24+ messages in thread
From: Albert ARIBAUD @ 2015-06-19 12:18 UTC (permalink / raw)
  To: u-boot

The VF610 DDRMC driver code contains settings which are
board-specific. Move these out to boards so that new boards
can define their own without having to modify the driver.

Signed-off-by: Albert ARIBAUD (3ADEV) <albert.aribaud@3adev.fr>
---

 arch/arm/imx-common/ddrmc-vf610.c             | 239 ++++++--------------------
 arch/arm/include/asm/arch-vf610/ddrmc-vf610.h |  60 +------
 board/freescale/vf610twr/vf610twr.c           | 181 +++++++++++++------
 board/toradex/colibri_vf/colibri_vf.c         | 169 +++++++++++++-----
 4 files changed, 312 insertions(+), 337 deletions(-)

diff --git a/arch/arm/imx-common/ddrmc-vf610.c b/arch/arm/imx-common/ddrmc-vf610.c
index e462631..44b9a0f 100644
--- a/arch/arm/imx-common/ddrmc-vf610.c
+++ b/arch/arm/imx-common/ddrmc-vf610.c
@@ -12,9 +12,9 @@
 #include <asm/arch/iomux-vf610.h>
 #include <asm/arch/ddrmc-vf610.h>
 
-void ddrmc_setup_iomux(void)
+void ddrmc_setup_iomux(const iomux_v3_cfg_t *pads, int pads_count)
 {
-	static const iomux_v3_cfg_t ddr_pads[] = {
+	static const iomux_v3_cfg_t default_pads[] = {
 		VF610_PAD_DDR_A15__DDR_A_15,
 		VF610_PAD_DDR_A14__DDR_A_14,
 		VF610_PAD_DDR_A13__DDR_A_13,
@@ -65,212 +65,77 @@ void ddrmc_setup_iomux(void)
 		VF610_PAD_DDR_RESETB,
 	};
 
-	imx_iomux_v3_setup_multiple_pads(ddr_pads, ARRAY_SIZE(ddr_pads));
-}
+	if ((pads == NULL) || (pads_count == 0)) {
+		pads = default_pads;
+		pads_count = ARRAY_SIZE(default_pads);
+	}
 
-void ddrmc_phy_init(void)
-{
-	struct ddrmr_regs *ddrmr = (struct ddrmr_regs *)DDR_BASE_ADDR;
+	imx_iomux_v3_setup_multiple_pads(pads, pads_count);
+}
 
-	writel(DDRMC_PHY_DQ_TIMING, &ddrmr->phy[0]);
-	writel(DDRMC_PHY_DQ_TIMING, &ddrmr->phy[16]);
-	writel(DDRMC_PHY_DQ_TIMING, &ddrmr->phy[32]);
+static struct ddrmc_reg_setting default_phy_settings[] = {
+	{ DDRMC_PHY_DQ_TIMING,  0 },
+	{ DDRMC_PHY_DQ_TIMING, 16 },
+	{ DDRMC_PHY_DQ_TIMING, 32 },
 
-	writel(DDRMC_PHY_DQS_TIMING, &ddrmr->phy[1]);
-	writel(DDRMC_PHY_DQS_TIMING, &ddrmr->phy[17]);
+	{ DDRMC_PHY_DQS_TIMING,  1 },
+	{ DDRMC_PHY_DQS_TIMING, 17 },
 
-	writel(DDRMC_PHY_CTRL, &ddrmr->phy[2]);
-	writel(DDRMC_PHY_CTRL, &ddrmr->phy[18]);
-	writel(DDRMC_PHY_CTRL, &ddrmr->phy[34]);
+	{ DDRMC_PHY_CTRL,  2 },
+	{ DDRMC_PHY_CTRL, 18 },
+	{ DDRMC_PHY_CTRL, 34 },
 
-	writel(DDRMC_PHY_MASTER_CTRL, &ddrmr->phy[3]);
-	writel(DDRMC_PHY_MASTER_CTRL, &ddrmr->phy[19]);
-	writel(DDRMC_PHY_MASTER_CTRL, &ddrmr->phy[35]);
+	{ DDRMC_PHY_MASTER_CTRL,  3 },
+	{ DDRMC_PHY_MASTER_CTRL, 19 },
+	{ DDRMC_PHY_MASTER_CTRL, 35 },
 
-	writel(DDRMC_PHY_SLAVE_CTRL, &ddrmr->phy[4]);
-	writel(DDRMC_PHY_SLAVE_CTRL, &ddrmr->phy[20]);
-	writel(DDRMC_PHY_SLAVE_CTRL, &ddrmr->phy[36]);
+	{ DDRMC_PHY_SLAVE_CTRL,  4 },
+	{ DDRMC_PHY_SLAVE_CTRL, 20 },
+	{ DDRMC_PHY_SLAVE_CTRL, 36 },
 
 	/* LPDDR2 only parameter */
-	writel(DDRMC_PHY_OFF, &ddrmr->phy[49]);
+	{ DDRMC_PHY_OFF, 49 },
 
-	writel(DDRMC_PHY50_DDR3_MODE |
-		   DDRMC_PHY50_EN_SW_HALF_CYCLE, &ddrmr->phy[50]);
+	{ DDRMC_PHY50_DDR3_MODE | DDRMC_PHY50_EN_SW_HALF_CYCLE, 50 },
 
 	/* Processor Pad ODT settings */
-	writel(DDRMC_PHY_PROC_PAD_ODT, &ddrmr->phy[52]);
-}
+	{ DDRMC_PHY_PROC_PAD_ODT, 52 },
 
-static void ddrmc_ctrl_lvl_init(struct ddrmc_lvl_info *lvl)
-{
-	struct ddrmr_regs *ddrmr = (struct ddrmr_regs *)DDR_BASE_ADDR;
-	u32 cr102 = 0, cr105 = 0, cr106 = 0, cr110 = 0;
+	/* end marker */
+	{ 0, -1 }
+};
 
-	if (lvl->wrlvl_reg_en) {
-		writel(DDRMC_CR97_WRLVL_EN, &ddrmr->cr[97]);
-		writel(DDRMC_CR98_WRLVL_DL_0(lvl->wrlvl_dl_0), &ddrmr->cr[98]);
-		writel(DDRMC_CR99_WRLVL_DL_1(lvl->wrlvl_dl_1), &ddrmr->cr[99]);
-	}
-
-	if (lvl->rdlvl_reg_en) {
-		cr102 |= DDRMC_CR102_RDLVL_REG_EN;
-		cr105 |= DDRMC_CR105_RDLVL_DL_0(lvl->rdlvl_dl_0);
-		cr110 |= DDRMC_CR110_RDLVL_DL_1(lvl->rdlvl_dl_1);
-	}
-
-	if (lvl->rdlvl_gt_reg_en) {
-		cr102 |= DDRMC_CR102_RDLVL_GT_REGEN;
-		cr106 |= DDRMC_CR106_RDLVL_GTDL_0(lvl->rdlvl_gt_dl_0);
-		cr110 |= DDRMC_CR110_RDLVL_GTDL_1(lvl->rdlvl_gt_dl_1);
-	}
-
-	writel(cr102, &ddrmr->cr[102]);
-	writel(cr105, &ddrmr->cr[105]);
-	writel(cr106, &ddrmr->cr[106]);
-	writel(cr110, &ddrmr->cr[110]);
-}
-
-void ddrmc_ctrl_init_ddr3(struct ddr3_jedec_timings const *timings,
-						  struct ddrmc_lvl_info *lvl,
-						  int col_diff, int row_diff)
+void ddrmc_ctrl_init_ddr3(struct ddrmc_reg_setting const *cr_settings,
+	struct ddrmc_reg_setting const *phy_settings)
 {
 	struct ddrmr_regs *ddrmr = (struct ddrmr_regs *)DDR_BASE_ADDR;
+	struct ddrmc_reg_setting const *cr_setting = cr_settings;
+	struct ddrmc_reg_setting const *phy_setting = phy_settings;
 
+	/* configure controller for DDR3 and start init sequence */
 	writel(DDRMC_CR00_DRAM_CLASS_DDR3, &ddrmr->cr[0]);
-	writel(DDRMC_CR02_DRAM_TINIT(timings->tinit), &ddrmr->cr[2]);
-	writel(DDRMC_CR10_TRST_PWRON(timings->trst_pwron), &ddrmr->cr[10]);
-
-	writel(DDRMC_CR11_CKE_INACTIVE(timings->cke_inactive), &ddrmr->cr[11]);
-	writel(DDRMC_CR12_WRLAT(timings->wrlat) |
-		   DDRMC_CR12_CASLAT_LIN(timings->caslat_lin), &ddrmr->cr[12]);
-	writel(DDRMC_CR13_TRC(timings->trc) | DDRMC_CR13_TRRD(timings->trrd) |
-		   DDRMC_CR13_TCCD(timings->tccd), &ddrmr->cr[13]);
-	writel(DDRMC_CR14_TFAW(timings->tfaw) | DDRMC_CR14_TRP(timings->trp) |
-		   DDRMC_CR14_TWTR(timings->twtr) |
-		   DDRMC_CR14_TRAS_MIN(timings->tras_min), &ddrmr->cr[14]);
-	writel(DDRMC_CR16_TMRD(timings->tmrd) |
-		   DDRMC_CR16_TRTP(timings->trtp), &ddrmr->cr[16]);
-	writel(DDRMC_CR17_TRAS_MAX(timings->tras_max) |
-		   DDRMC_CR17_TMOD(timings->tmod), &ddrmr->cr[17]);
-	writel(DDRMC_CR18_TCKESR(timings->tckesr) |
-		   DDRMC_CR18_TCKE(timings->tcke), &ddrmr->cr[18]);
 
-	writel(DDRMC_CR20_AP_EN, &ddrmr->cr[20]);
-	writel(DDRMC_CR21_TRCD_INT(timings->trcd_int) |
-		   DDRMC_CR21_CCMAP_EN, &ddrmr->cr[21]);
-
-	writel(DDRMC_CR22_TDAL(timings->tdal), &ddrmr->cr[22]);
-	writel(DDRMC_CR23_BSTLEN(3) |
-		   DDRMC_CR23_TDLL(timings->tdll), &ddrmr->cr[23]);
-	writel(DDRMC_CR24_TRP_AB(timings->trp_ab), &ddrmr->cr[24]);
-
-	writel(DDRMC_CR25_TREF_EN, &ddrmr->cr[25]);
-	writel(DDRMC_CR26_TREF(timings->tref) |
-		   DDRMC_CR26_TRFC(timings->trfc), &ddrmr->cr[26]);
-	writel(DDRMC_CR28_TREF_INT(0), &ddrmr->cr[28]);
-	writel(DDRMC_CR29_TPDEX(timings->tpdex), &ddrmr->cr[29]);
-
-	writel(DDRMC_CR30_TXPDLL(timings->txpdll), &ddrmr->cr[30]);
-	writel(DDRMC_CR31_TXSNR(timings->txsnr) |
-		   DDRMC_CR31_TXSR(timings->txsr), &ddrmr->cr[31]);
-	writel(DDRMC_CR33_EN_QK_SREF, &ddrmr->cr[33]);
-	writel(DDRMC_CR34_CKSRX(timings->cksrx) |
-		   DDRMC_CR34_CKSRE(timings->cksre), &ddrmr->cr[34]);
-
-	writel(DDRMC_CR38_FREQ_CHG_EN(0), &ddrmr->cr[38]);
-	writel(DDRMC_CR39_PHY_INI_COM(1024) | DDRMC_CR39_PHY_INI_STA(16) |
-		   DDRMC_CR39_FRQ_CH_DLLOFF(2), &ddrmr->cr[39]);
-
-	writel(DDRMC_CR41_PHY_INI_STRT_INI_DIS, &ddrmr->cr[41]);
-	writel(DDRMC_CR48_MR1_DA_0(70) |
-		   DDRMC_CR48_MR0_DA_0(1056), &ddrmr->cr[48]);
-
-	writel(DDRMC_CR66_ZQCL(timings->zqcl) |
-		   DDRMC_CR66_ZQINIT(timings->zqinit), &ddrmr->cr[66]);
-	writel(DDRMC_CR67_ZQCS(timings->zqcs), &ddrmr->cr[67]);
-	writel(DDRMC_CR69_ZQ_ON_SREF_EX(2), &ddrmr->cr[69]);
-
-	writel(DDRMC_CR70_REF_PER_ZQ(timings->ref_per_zq), &ddrmr->cr[70]);
-	writel(DDRMC_CR72_ZQCS_ROTATE(0), &ddrmr->cr[72]);
-
-	writel(DDRMC_CR73_APREBIT(timings->aprebit) |
-		   DDRMC_CR73_COL_DIFF(col_diff) |
-		   DDRMC_CR73_ROW_DIFF(row_diff), &ddrmr->cr[73]);
-	writel(DDRMC_CR74_BANKSPLT_EN | DDRMC_CR74_ADDR_CMP_EN |
-		   DDRMC_CR74_CMD_AGE_CNT(64) | DDRMC_CR74_AGE_CNT(64),
-		   &ddrmr->cr[74]);
-	writel(DDRMC_CR75_RW_PG_EN | DDRMC_CR75_RW_EN | DDRMC_CR75_PRI_EN |
-		   DDRMC_CR75_PLEN, &ddrmr->cr[75]);
-	writel(DDRMC_CR76_NQENT_ACTDIS(3) | DDRMC_CR76_D_RW_G_BKCN(3) |
-		   DDRMC_CR76_W2R_SPLT_EN, &ddrmr->cr[76]);
-	writel(DDRMC_CR77_CS_MAP | DDRMC_CR77_DI_RD_INTLEAVE |
-		   DDRMC_CR77_SWAP_EN, &ddrmr->cr[77]);
-	writel(DDRMC_CR78_Q_FULLNESS(7) |
-		   DDRMC_CR78_BUR_ON_FLY_BIT(12), &ddrmr->cr[78]);
-	writel(DDRMC_CR79_CTLUPD_AREF(0), &ddrmr->cr[79]);
+	/* execute CR sequence (MUST be supplied) */
+	if (cr_setting)
+		while (cr_setting->reg_num >= 0) {
+			writel(cr_setting->setting,
+			       &ddrmr->cr[cr_setting->reg_num]);
+			cr_setting++;
+		}
+
+	/* execute PHY sequence (SHOULD be supplied but can be default) */
+	if (phy_setting == NULL)
+		phy_setting = default_phy_settings;
+
+	while (phy_setting->reg_num >= 0) {
+		writel(phy_setting->setting,
+		       &ddrmr->phy[phy_setting->reg_num]);
+		phy_setting++;
+	}
 
+	/* final config: disable DDR interrupts and finish init squence */
 	writel(DDRMC_CR82_INT_MASK, &ddrmr->cr[82]);
 
-	writel(DDRMC_CR87_ODT_WR_MAPCS0, &ddrmr->cr[87]);
-	writel(DDRMC_CR88_TODTL_CMD(4), &ddrmr->cr[88]);
-	writel(DDRMC_CR89_AODT_RWSMCS(2), &ddrmr->cr[89]);
-
-	writel(DDRMC_CR91_R2W_SMCSDL(2), &ddrmr->cr[91]);
-	writel(DDRMC_CR96_WLMRD(timings->wlmrd) |
-		   DDRMC_CR96_WLDQSEN(timings->wldqsen), &ddrmr->cr[96]);
-
-	if (lvl != NULL)
-		ddrmc_ctrl_lvl_init(lvl);
-
-	writel(DDRMC_CR117_AXI0_W_PRI(0) |
-		   DDRMC_CR117_AXI0_R_PRI(0), &ddrmr->cr[117]);
-	writel(DDRMC_CR118_AXI1_W_PRI(1) |
-		   DDRMC_CR118_AXI1_R_PRI(1), &ddrmr->cr[118]);
-
-	writel(DDRMC_CR120_AXI0_PRI1_RPRI(2) |
-		   DDRMC_CR120_AXI0_PRI0_RPRI(2), &ddrmr->cr[120]);
-	writel(DDRMC_CR121_AXI0_PRI3_RPRI(2) |
-		   DDRMC_CR121_AXI0_PRI2_RPRI(2), &ddrmr->cr[121]);
-	writel(DDRMC_CR122_AXI1_PRI1_RPRI(1) | DDRMC_CR122_AXI1_PRI0_RPRI(1) |
-		   DDRMC_CR122_AXI0_PRIRLX(100), &ddrmr->cr[122]);
-	writel(DDRMC_CR123_AXI1_P_ODR_EN | DDRMC_CR123_AXI1_PRI3_RPRI(1) |
-		   DDRMC_CR123_AXI1_PRI2_RPRI(1), &ddrmr->cr[123]);
-	writel(DDRMC_CR124_AXI1_PRIRLX(100), &ddrmr->cr[124]);
-
-	writel(DDRMC_CR126_PHY_RDLAT(8), &ddrmr->cr[126]);
-	writel(DDRMC_CR132_WRLAT_ADJ(5) |
-		   DDRMC_CR132_RDLAT_ADJ(6), &ddrmr->cr[132]);
-	writel(DDRMC_CR137_PHYCTL_DL(2), &ddrmr->cr[137]);
-	writel(DDRMC_CR138_PHY_WRLV_MXDL(256) |
-		   DDRMC_CR138_PHYDRAM_CK_EN(1), &ddrmr->cr[138]);
-	writel(DDRMC_CR139_PHY_WRLV_RESPLAT(4) | DDRMC_CR139_PHY_WRLV_LOAD(7) |
-		   DDRMC_CR139_PHY_WRLV_DLL(3) |
-		   DDRMC_CR139_PHY_WRLV_EN(3), &ddrmr->cr[139]);
-	writel(DDRMC_CR140_PHY_WRLV_WW(64), &ddrmr->cr[140]);
-	writel(DDRMC_CR143_RDLV_GAT_MXDL(1536) |
-		   DDRMC_CR143_RDLV_MXDL(128), &ddrmr->cr[143]);
-	writel(DDRMC_CR144_PHY_RDLVL_RES(4) | DDRMC_CR144_PHY_RDLV_LOAD(7) |
-		   DDRMC_CR144_PHY_RDLV_DLL(3) |
-		   DDRMC_CR144_PHY_RDLV_EN(3), &ddrmr->cr[144]);
-	writel(DDRMC_CR145_PHY_RDLV_RR(64), &ddrmr->cr[145]);
-	writel(DDRMC_CR146_PHY_RDLVL_RESP(64), &ddrmr->cr[146]);
-	writel(DDRMC_CR147_RDLV_RESP_MASK(983040), &ddrmr->cr[147]);
-	writel(DDRMC_CR148_RDLV_GATE_RESP_MASK(983040), &ddrmr->cr[148]);
-	writel(DDRMC_CR151_RDLV_GAT_DQ_ZERO_CNT(1) |
-		   DDRMC_CR151_RDLVL_DQ_ZERO_CNT(1), &ddrmr->cr[151]);
-
-	writel(DDRMC_CR154_PAD_ZQ_EARLY_CMP_EN_TIMER(13) |
-		   DDRMC_CR154_PAD_ZQ_MODE(1) |
-		   DDRMC_CR154_DDR_SEL_PAD_CONTR(3) |
-		   DDRMC_CR154_PAD_ZQ_HW_FOR(1), &ddrmr->cr[154]);
-	writel(DDRMC_CR155_PAD_ODT_BYTE1(2) |
-		   DDRMC_CR155_PAD_ODT_BYTE0(2), &ddrmr->cr[155]);
-	writel(DDRMC_CR158_TWR(6), &ddrmr->cr[158]);
-	writel(DDRMC_CR161_ODT_EN(1) | DDRMC_CR161_TODTH_RD(2) |
-		   DDRMC_CR161_TODTH_WR(2), &ddrmr->cr[161]);
-
-	ddrmc_phy_init();
-
 	writel(DDRMC_CR00_DRAM_CLASS_DDR3 | DDRMC_CR00_START, &ddrmr->cr[0]);
 
 	while (!(readl(&ddrmr->cr[80]) && 0x100))
diff --git a/arch/arm/include/asm/arch-vf610/ddrmc-vf610.h b/arch/arm/include/asm/arch-vf610/ddrmc-vf610.h
index 6730cde..bc7f106 100644
--- a/arch/arm/include/asm/arch-vf610/ddrmc-vf610.h
+++ b/arch/arm/include/asm/arch-vf610/ddrmc-vf610.h
@@ -11,62 +11,14 @@
 #ifndef __ASM_ARCH_VF610_DDRMC_H
 #define __ASM_ARCH_VF610_DDRMC_H
 
-struct ddrmc_lvl_info {
-	u16 wrlvl_reg_en;
-	u16 wrlvl_dl_0;
-	u16 wrlvl_dl_1;
-	u16 rdlvl_gt_reg_en;
-	u16 rdlvl_gt_dl_0;
-	u16 rdlvl_gt_dl_1;
-	u16 rdlvl_reg_en;
-	u16 rdlvl_dl_0;
-	u16 rdlvl_dl_1;
+struct ddrmc_reg_setting {
+	u32	setting;
+	int	reg_num; /* CR or PHY ; -1 for last entry */
 };
 
-struct ddr3_jedec_timings {
-	u8 tinit;
-	u32 trst_pwron;
-	u32 cke_inactive;
-	u8 wrlat;
-	u8 caslat_lin;
-	u8 trc;
-	u8 trrd;
-	u8 tccd;
-	u8 tfaw;
-	u8 trp;
-	u8 twtr;
-	u8 tras_min;
-	u8 tmrd;
-	u8 trtp;
-	u32 tras_max;
-	u8 tmod;
-	u8 tckesr;
-	u8 tcke;
-	u8 trcd_int;
-	u8 tdal;
-	u16 tdll;
-	u8 trp_ab;
-	u16 tref;
-	u8 trfc;
-	u8 tpdex;
-	u8 txpdll;
-	u8 txsnr;
-	u16 txsr;
-	u8 cksrx;
-	u8 cksre;
-	u16 zqcl;
-	u16 zqinit;
-	u8 zqcs;
-	u8 ref_per_zq;
-	u8 aprebit;
-	u8 wlmrd;
-	u8 wldqsen;
-};
-
-void ddrmc_setup_iomux(void);
+void ddrmc_setup_iomux(const iomux_v3_cfg_t *pads, int pads_count);
 void ddrmc_phy_init(void);
-void ddrmc_ctrl_init_ddr3(struct ddr3_jedec_timings const *timings,
-						  struct ddrmc_lvl_info *lvl,
-						  int col_diff, int row_diff);
+void ddrmc_ctrl_init_ddr3(struct ddrmc_reg_setting const *cr_settings,
+	struct ddrmc_reg_setting const *phy_settings);
 
 #endif
diff --git a/board/freescale/vf610twr/vf610twr.c b/board/freescale/vf610twr/vf610twr.c
index 4160acd..aab20ad 100644
--- a/board/freescale/vf610twr/vf610twr.c
+++ b/board/freescale/vf610twr/vf610twr.c
@@ -28,63 +28,136 @@ DECLARE_GLOBAL_DATA_PTR;
 #define ENET_PAD_CTRL	(PAD_CTL_PUS_47K_UP | PAD_CTL_SPEED_HIGH | \
 			PAD_CTL_DSE_50ohm | PAD_CTL_OBE_IBE_ENABLE)
 
+static struct ddrmc_reg_setting vf610twr_cr_settings[] = {
+	{ DDRMC_CR02_DRAM_TINIT(5), 2 },
+	{ DDRMC_CR10_TRST_PWRON(80000), 10 },
+	{ DDRMC_CR11_CKE_INACTIVE(200000), 11 },
+	{ DDRMC_CR12_WRLAT(5) | DDRMC_CR12_CASLAT_LIN(12), 12 },
+	{ DDRMC_CR13_TRC(21) | DDRMC_CR13_TRRD(4) | DDRMC_CR13_TCCD(4) |
+		   DDRMC_CR13_TBST_INT_INTERVAL(0), 13 },
+	{ DDRMC_CR14_TFAW(20) | DDRMC_CR14_TRP(6) | DDRMC_CR14_TWTR(5) |
+		   DDRMC_CR14_TRAS_MIN(15), 14 },
+	{ DDRMC_CR16_TMRD(4) | DDRMC_CR16_TRTP(4), 16 },
+	{ DDRMC_CR17_TRAS_MAX(28080) | DDRMC_CR17_TMOD(12), 17 },
+	{ DDRMC_CR18_TCKESR(4) | DDRMC_CR18_TCKE(3), 18 },
+
+	{ DDRMC_CR20_AP_EN, 20 },
+	{ DDRMC_CR21_TRCD_INT(6) | DDRMC_CR21_CCMAP_EN, 21 },
+
+	{ DDRMC_CR22_TDAL(12), 22 },
+	{ DDRMC_CR23_BSTLEN(3) |
+		   DDRMC_CR23_TDLL(512), 23 },
+	{ DDRMC_CR24_TRP_AB(6), 24 },
+
+	{ DDRMC_CR25_TREF_EN, 25 },
+	{ DDRMC_CR26_TREF(3120) | DDRMC_CR26_TRFC(44), 26 },
+	{ DDRMC_CR28_TREF_INT(0), 28 },
+	{ DDRMC_CR29_TPDEX(3), 29 },
+
+	{ DDRMC_CR30_TXPDLL(10), 30 },
+	{ DDRMC_CR31_TXSNR(48) | DDRMC_CR31_TXSR(468), 31 },
+	{ DDRMC_CR33_EN_QK_SREF, 33 },
+	{ DDRMC_CR34_CKSRX(5) | DDRMC_CR34_CKSRE(5), 34 },
+
+	{ DDRMC_CR38_FREQ_CHG_EN(0), 38 },
+	{ DDRMC_CR39_PHY_INI_COM(1024) | DDRMC_CR39_PHY_INI_STA(16) |
+		   DDRMC_CR39_FRQ_CH_DLLOFF(2), 39 },
+
+	{ DDRMC_CR41_PHY_INI_STRT_INI_DIS, 41 },
+	{ DDRMC_CR48_MR1_DA_0(70) |
+		   DDRMC_CR48_MR0_DA_0(1056), 48 },
+
+	{ DDRMC_CR66_ZQCL(256) | DDRMC_CR66_ZQINIT(512), 66 },
+	{ DDRMC_CR67_ZQCS(64), 67 },
+	{ DDRMC_CR69_ZQ_ON_SREF_EX(2), 69 },
+
+	{ DDRMC_CR70_REF_PER_ZQ(64), 70 },
+	{ DDRMC_CR72_ZQCS_ROTATE(0), 72 },
+
+	{ DDRMC_CR73_APREBIT(10) | DDRMC_CR73_COL_DIFF(1) |
+		   DDRMC_CR73_ROW_DIFF(3), 73 },
+	{ DDRMC_CR74_BANKSPLT_EN | DDRMC_CR74_ADDR_CMP_EN |
+		   DDRMC_CR74_CMD_AGE_CNT(64) |
+		   DDRMC_CR74_AGE_CNT(64), 74 },
+	{ DDRMC_CR75_RW_PG_EN | DDRMC_CR75_RW_EN | DDRMC_CR75_PRI_EN |
+		   DDRMC_CR75_PLEN, 75 },
+	{ DDRMC_CR76_NQENT_ACTDIS(3) | DDRMC_CR76_D_RW_G_BKCN(3) |
+		   DDRMC_CR76_W2R_SPLT_EN, 76 },
+	{ DDRMC_CR77_CS_MAP | DDRMC_CR77_DI_RD_INTLEAVE |
+		   DDRMC_CR77_SWAP_EN, 77 },
+	{ DDRMC_CR78_Q_FULLNESS(7) | DDRMC_CR78_BUR_ON_FLY_BIT(12), 78 },
+	{ DDRMC_CR79_CTLUPD_AREF(0), 79 },
+
+	{ DDRMC_CR87_ODT_WR_MAPCS0, 87 },
+	{ DDRMC_CR88_TODTL_CMD(4), 88 },
+	{ DDRMC_CR89_AODT_RWSMCS(2), 89 },
+
+	{ DDRMC_CR91_R2W_SMCSDL(2), 91 },
+	{ DDRMC_CR96_WLMRD(40) | DDRMC_CR96_WLDQSEN(25), 96 },
+
+	/* levelling */
+	{ DDRMC_CR97_WRLVL_EN, 97 },
+	{ DDRMC_CR98_WRLVL_DL_0(0), 98 },
+	{ DDRMC_CR99_WRLVL_DL_1(0), 99 },
+	{ DDRMC_CR102_RDLVL_REG_EN | DDRMC_CR102_RDLVL_GT_REGEN, 102 },
+	{ DDRMC_CR105_RDLVL_DL_0(0), 105 },
+	{ DDRMC_CR106_RDLVL_GTDL_0(4), 106 },
+	{ DDRMC_CR110_RDLVL_DL_1(0) | DDRMC_CR110_RDLVL_GTDL_1(4), 110 },
+
+	/* AXI */
+	{ DDRMC_CR117_AXI0_W_PRI(0) | DDRMC_CR117_AXI0_R_PRI(0), 117 },
+	{ DDRMC_CR118_AXI1_W_PRI(1) | DDRMC_CR118_AXI1_R_PRI(1), 118 },
+	{ DDRMC_CR120_AXI0_PRI1_RPRI(2) |
+		   DDRMC_CR120_AXI0_PRI0_RPRI(2), 120 },
+	{ DDRMC_CR121_AXI0_PRI3_RPRI(2) |
+		   DDRMC_CR121_AXI0_PRI2_RPRI(2), 121 },
+	{ DDRMC_CR122_AXI1_PRI1_RPRI(1) | DDRMC_CR122_AXI1_PRI0_RPRI(1) |
+		   DDRMC_CR122_AXI0_PRIRLX(100), 122 },
+	{ DDRMC_CR123_AXI1_P_ODR_EN | DDRMC_CR123_AXI1_PRI3_RPRI(1) |
+		   DDRMC_CR123_AXI1_PRI2_RPRI(1), 123 },
+	{ DDRMC_CR124_AXI1_PRIRLX(100), 124 },
+	{ DDRMC_CR126_PHY_RDLAT(8), 126 },
+	{ DDRMC_CR132_WRLAT_ADJ(5) |
+		   DDRMC_CR132_RDLAT_ADJ(6), 132 },
+	{ DDRMC_CR137_PHYCTL_DL(2), 137 },
+	{ DDRMC_CR138_PHY_WRLV_MXDL(256) |
+		   DDRMC_CR138_PHYDRAM_CK_EN(1), 138 },
+	{ DDRMC_CR139_PHY_WRLV_RESPLAT(4) | DDRMC_CR139_PHY_WRLV_LOAD(7) |
+		   DDRMC_CR139_PHY_WRLV_DLL(3) |
+		   DDRMC_CR139_PHY_WRLV_EN(3), 139 },
+	{ DDRMC_CR140_PHY_WRLV_WW(64), 140 },
+	{ DDRMC_CR143_RDLV_GAT_MXDL(1536) |
+		   DDRMC_CR143_RDLV_MXDL(128), 143 },
+	{ DDRMC_CR144_PHY_RDLVL_RES(4) | DDRMC_CR144_PHY_RDLV_LOAD(7) |
+		   DDRMC_CR144_PHY_RDLV_DLL(3) |
+		   DDRMC_CR144_PHY_RDLV_EN(3), 144 },
+	{ DDRMC_CR145_PHY_RDLV_RR(64), 145 },
+	{ DDRMC_CR146_PHY_RDLVL_RESP(64), 146 },
+	{ DDRMC_CR147_RDLV_RESP_MASK(983040), 147 },
+	{ DDRMC_CR148_RDLV_GATE_RESP_MASK(983040), 148 },
+	{ DDRMC_CR151_RDLV_GAT_DQ_ZERO_CNT(1) |
+		   DDRMC_CR151_RDLVL_DQ_ZERO_CNT(1), 151 },
+
+	{ DDRMC_CR154_PAD_ZQ_EARLY_CMP_EN_TIMER(13) |
+		   DDRMC_CR154_PAD_ZQ_MODE(1) |
+		   DDRMC_CR154_DDR_SEL_PAD_CONTR(3) |
+		   DDRMC_CR154_PAD_ZQ_HW_FOR(1), 154 },
+	{ DDRMC_CR155_PAD_ODT_BYTE1(1) | DDRMC_CR155_PAD_ODT_BYTE0(1), 155 },
+	{ DDRMC_CR158_TWR(6), 158 },
+	{ DDRMC_CR161_ODT_EN(1) | DDRMC_CR161_TODTH_RD(2) |
+		   DDRMC_CR161_TODTH_WR(2), 161 },
+
+	/* end marker */
+	{ 0, -1 }
+}
+
 int dram_init(void)
 {
-	struct ddrmc_lvl_info lvl = {
-		.wrlvl_reg_en = 1,
-		.wrlvl_dl_0 = 0,
-		.wrlvl_dl_1 = 0,
-		.rdlvl_gt_reg_en = 1,
-		.rdlvl_gt_dl_0 = 4,
-		.rdlvl_gt_dl_1 = 4,
-		.rdlvl_reg_en = 1,
-		.rdlvl_dl_0 = 0,
-		.rdlvl_dl_1 = 0,
-	};
-
-	static const struct ddr3_jedec_timings timings = {
-		.tinit           = 5,
-		.trst_pwron      = 80000,
-		.cke_inactive    = 200000,
-		.wrlat           = 5,
-		.caslat_lin      = 12,
-		.trc             = 21,
-		.trrd            = 4,
-		.tccd            = 4,
-		.tfaw            = 20,
-		.trp             = 6,
-		.twtr            = 4,
-		.tras_min        = 15,
-		.tmrd            = 4,
-		.trtp            = 4,
-		.tras_max        = 28080,
-		.tmod            = 12,
-		.tckesr          = 4,
-		.tcke            = 3,
-		.trcd_int        = 6,
-		.tdal            = 12,
-		.tdll            = 512,
-		.trp_ab          = 6,
-		.tref            = 3120,
-		.trfc            = 44,
-		.tpdex           = 3,
-		.txpdll          = 10,
-		.txsnr           = 48,
-		.txsr            = 468,
-		.cksrx           = 5,
-		.cksre           = 5,
-		.zqcl            = 256,
-		.zqinit          = 512,
-		.zqcs            = 64,
-		.ref_per_zq      = 64,
-		.aprebit         = 10,
-		.wlmrd           = 40,
-		.wldqsen         = 25,
-	};
-
-	ddrmc_setup_iomux();
+	/* use driver default IOMUX settings */
+	ddrmc_setup_iomux(NULL, 0);
 
-	ddrmc_ctrl_init_ddr3(&timings, &lvl, 1, 3);
+	/* provide own CR setup but use default PHY setup */
+	ddrmc_ctrl_init_ddr3(vf610twr_cr_settings, NULL);
 	gd->ram_size = get_ram_size((void *)PHYS_SDRAM, PHYS_SDRAM_SIZE);
 
 	return 0;
diff --git a/board/toradex/colibri_vf/colibri_vf.c b/board/toradex/colibri_vf/colibri_vf.c
index 8618fd0..01b3106 100644
--- a/board/toradex/colibri_vf/colibri_vf.c
+++ b/board/toradex/colibri_vf/colibri_vf.c
@@ -39,51 +39,136 @@ static const iomux_v3_cfg_t usb_pads[] = {
 	VF610_PAD_PTD4__GPIO_83,
 };
 
+static struct ddrmc_reg_setting colibri_vf_cr_settings[] = {
+	{ DDRMC_CR02_DRAM_TINIT(5), 2 },
+	{ DDRMC_CR10_TRST_PWRON(80000), 10 },
+	{ DDRMC_CR11_CKE_INACTIVE(200000), 11 },
+	{ DDRMC_CR12_WRLAT(5) | DDRMC_CR12_CASLAT_LIN(12), 12 },
+	{ DDRMC_CR13_TRC(21) | DDRMC_CR13_TRRD(4) | DDRMC_CR13_TCCD(4) |
+		   DDRMC_CR13_TBST_INT_INTERVAL(0), 13 },
+	{ DDRMC_CR14_TFAW(20) | DDRMC_CR14_TRP(6) | DDRMC_CR14_TWTR(5) |
+		   DDRMC_CR14_TRAS_MIN(15), 14 },
+	{ DDRMC_CR16_TMRD(4) | DDRMC_CR16_TRTP(4), 16 },
+	{ DDRMC_CR17_TRAS_MAX(28080) | DDRMC_CR17_TMOD(12), 17 },
+	{ DDRMC_CR18_TCKESR(4) | DDRMC_CR18_TCKE(3), 18 },
+
+	{ DDRMC_CR20_AP_EN, 20 },
+	{ DDRMC_CR21_TRCD_INT(6) | DDRMC_CR21_CCMAP_EN, 21 },
+
+	{ DDRMC_CR22_TDAL(12), 22 },
+	{ DDRMC_CR23_BSTLEN(3) |
+		   DDRMC_CR23_TDLL(512), 23 },
+	{ DDRMC_CR24_TRP_AB(6), 24 },
+
+	{ DDRMC_CR25_TREF_EN, 25 },
+	{ DDRMC_CR26_TREF(3120) | DDRMC_CR26_TRFC(44), 26 },
+	{ DDRMC_CR28_TREF_INT(0), 28 },
+	{ DDRMC_CR29_TPDEX(3), 29 },
+
+	{ DDRMC_CR30_TXPDLL(10), 30 },
+	{ DDRMC_CR31_TXSNR(48) | DDRMC_CR31_TXSR(468), 31 },
+	{ DDRMC_CR33_EN_QK_SREF, 33 },
+	{ DDRMC_CR34_CKSRX(5) | DDRMC_CR34_CKSRE(5), 34 },
+
+	{ DDRMC_CR38_FREQ_CHG_EN(0), 38 },
+	{ DDRMC_CR39_PHY_INI_COM(1024) | DDRMC_CR39_PHY_INI_STA(16) |
+		   DDRMC_CR39_FRQ_CH_DLLOFF(2), 39 },
+
+	{ DDRMC_CR41_PHY_INI_STRT_INI_DIS, 41 },
+	{ DDRMC_CR48_MR1_DA_0(70) |
+		   DDRMC_CR48_MR0_DA_0(1056), 48 },
+
+	{ DDRMC_CR66_ZQCL(256) | DDRMC_CR66_ZQINIT(512), 66 },
+	{ DDRMC_CR67_ZQCS(64), 67 },
+	{ DDRMC_CR69_ZQ_ON_SREF_EX(2), 69 },
+
+	{ DDRMC_CR70_REF_PER_ZQ(64), 70 },
+	{ DDRMC_CR72_ZQCS_ROTATE(0), 72 },
+
+	{ DDRMC_CR73_APREBIT(10) | DDRMC_CR73_COL_DIFF(1) |
+		   DDRMC_CR73_ROW_DIFF(3), 73 },
+	{ DDRMC_CR74_BANKSPLT_EN | DDRMC_CR74_ADDR_CMP_EN |
+		   DDRMC_CR74_CMD_AGE_CNT(64) |
+		   DDRMC_CR74_AGE_CNT(64), 74 },
+	{ DDRMC_CR75_RW_PG_EN | DDRMC_CR75_RW_EN | DDRMC_CR75_PRI_EN |
+		   DDRMC_CR75_PLEN, 75 },
+	{ DDRMC_CR76_NQENT_ACTDIS(3) | DDRMC_CR76_D_RW_G_BKCN(3) |
+		   DDRMC_CR76_W2R_SPLT_EN, 76 },
+	{ DDRMC_CR77_CS_MAP | DDRMC_CR77_DI_RD_INTLEAVE |
+		   DDRMC_CR77_SWAP_EN, 77 },
+	{ DDRMC_CR78_Q_FULLNESS(7) | DDRMC_CR78_BUR_ON_FLY_BIT(12), 78 },
+	{ DDRMC_CR79_CTLUPD_AREF(0), 79 },
+
+	{ DDRMC_CR87_ODT_WR_MAPCS0, 87 },
+	{ DDRMC_CR88_TODTL_CMD(4), 88 },
+	{ DDRMC_CR89_AODT_RWSMCS(2), 89 },
+
+	{ DDRMC_CR91_R2W_SMCSDL(2), 91 },
+	{ DDRMC_CR96_WLMRD(40) | DDRMC_CR96_WLDQSEN(25), 96 },
+
+	/* levelling */
+	{ DDRMC_CR97_WRLVL_EN, 97 },
+	{ DDRMC_CR98_WRLVL_DL_0(0), 98 },
+	{ DDRMC_CR99_WRLVL_DL_1(0), 99 },
+	{ DDRMC_CR102_RDLVL_REG_EN | DDRMC_CR102_RDLVL_GT_REGEN, 102 },
+	{ DDRMC_CR105_RDLVL_DL_0(0), 105 },
+	{ DDRMC_CR106_RDLVL_GTDL_0(4), 106 },
+	{ DDRMC_CR110_RDLVL_DL_1(0) | DDRMC_CR110_RDLVL_GTDL_1(4), 110 },
+
+	/* AXI */
+	{ DDRMC_CR117_AXI0_W_PRI(0) | DDRMC_CR117_AXI0_R_PRI(0), 117 },
+	{ DDRMC_CR118_AXI1_W_PRI(1) | DDRMC_CR118_AXI1_R_PRI(1), 118 },
+	{ DDRMC_CR120_AXI0_PRI1_RPRI(2) |
+		   DDRMC_CR120_AXI0_PRI0_RPRI(2), 120 },
+	{ DDRMC_CR121_AXI0_PRI3_RPRI(2) |
+		   DDRMC_CR121_AXI0_PRI2_RPRI(2), 121 },
+	{ DDRMC_CR122_AXI1_PRI1_RPRI(1) | DDRMC_CR122_AXI1_PRI0_RPRI(1) |
+		   DDRMC_CR122_AXI0_PRIRLX(100), 122 },
+	{ DDRMC_CR123_AXI1_P_ODR_EN | DDRMC_CR123_AXI1_PRI3_RPRI(1) |
+		   DDRMC_CR123_AXI1_PRI2_RPRI(1), 123 },
+	{ DDRMC_CR124_AXI1_PRIRLX(100), 124 },
+	{ DDRMC_CR126_PHY_RDLAT(8), 126 },
+	{ DDRMC_CR132_WRLAT_ADJ(5) |
+		   DDRMC_CR132_RDLAT_ADJ(6), 132 },
+	{ DDRMC_CR137_PHYCTL_DL(2), 137 },
+	{ DDRMC_CR138_PHY_WRLV_MXDL(256) |
+		   DDRMC_CR138_PHYDRAM_CK_EN(1), 138 },
+	{ DDRMC_CR139_PHY_WRLV_RESPLAT(4) | DDRMC_CR139_PHY_WRLV_LOAD(7) |
+		   DDRMC_CR139_PHY_WRLV_DLL(3) |
+		   DDRMC_CR139_PHY_WRLV_EN(3), 139 },
+	{ DDRMC_CR140_PHY_WRLV_WW(64), 140 },
+	{ DDRMC_CR143_RDLV_GAT_MXDL(1536) |
+		   DDRMC_CR143_RDLV_MXDL(128), 143 },
+	{ DDRMC_CR144_PHY_RDLVL_RES(4) | DDRMC_CR144_PHY_RDLV_LOAD(7) |
+		   DDRMC_CR144_PHY_RDLV_DLL(3) |
+		   DDRMC_CR144_PHY_RDLV_EN(3), 144 },
+	{ DDRMC_CR145_PHY_RDLV_RR(64), 145 },
+	{ DDRMC_CR146_PHY_RDLVL_RESP(64), 146 },
+	{ DDRMC_CR147_RDLV_RESP_MASK(983040), 147 },
+	{ DDRMC_CR148_RDLV_GATE_RESP_MASK(983040), 148 },
+	{ DDRMC_CR151_RDLV_GAT_DQ_ZERO_CNT(1) |
+		   DDRMC_CR151_RDLVL_DQ_ZERO_CNT(1), 151 },
+
+	{ DDRMC_CR154_PAD_ZQ_EARLY_CMP_EN_TIMER(13) |
+		   DDRMC_CR154_PAD_ZQ_MODE(1) |
+		   DDRMC_CR154_DDR_SEL_PAD_CONTR(3) |
+		   DDRMC_CR154_PAD_ZQ_HW_FOR(1), 154 },
+	{ DDRMC_CR155_PAD_ODT_BYTE1(1) | DDRMC_CR155_PAD_ODT_BYTE0(1), 155 },
+	{ DDRMC_CR158_TWR(6), 158 },
+	{ DDRMC_CR161_ODT_EN(1) | DDRMC_CR161_TODTH_RD(2) |
+		   DDRMC_CR161_TODTH_WR(2), 161 },
+
+	/* end marker */
+	{ 0, -1 }
+}
+
 int dram_init(void)
 {
-	static const struct ddr3_jedec_timings timings = {
-		.tinit           = 5,
-		.trst_pwron      = 80000,
-		.cke_inactive    = 200000,
-		.wrlat           = 5,
-		.caslat_lin      = 12,
-		.trc             = 21,
-		.trrd            = 4,
-		.tccd            = 4,
-		.tfaw            = 20,
-		.trp             = 6,
-		.twtr            = 4,
-		.tras_min        = 15,
-		.tmrd            = 4,
-		.trtp            = 4,
-		.tras_max        = 28080,
-		.tmod            = 12,
-		.tckesr          = 4,
-		.tcke            = 3,
-		.trcd_int        = 6,
-		.tdal            = 12,
-		.tdll            = 512,
-		.trp_ab          = 6,
-		.tref            = 3120,
-		.trfc            = 64,
-		.tpdex           = 3,
-		.txpdll          = 10,
-		.txsnr           = 48,
-		.txsr            = 468,
-		.cksrx           = 5,
-		.cksre           = 5,
-		.zqcl            = 256,
-		.zqinit          = 512,
-		.zqcs            = 64,
-		.ref_per_zq      = 64,
-		.aprebit         = 10,
-		.wlmrd           = 40,
-		.wldqsen         = 25,
-	};
-
-	ddrmc_setup_iomux();
+	/* use driver default IOMUX settings */
+	ddrmc_setup_iomux(NULL, 0);
 
-	ddrmc_ctrl_init_ddr3(&timings, NULL, 1, 2);
+	/* provide own CR setup but use default PHY setup */
+	ddrmc_ctrl_init_ddr3(&colibri_vf_cr_settings, NULL, 1, 2);
 	gd->ram_size = get_ram_size((void *)PHYS_SDRAM, PHYS_SDRAM_SIZE);
 
 	return 0;
-- 
2.1.0

^ permalink raw reply related	[flat|nested] 24+ messages in thread

* [U-Boot] [PATCH 3/5] i2c: fix vf610 support
  2015-06-19 12:18   ` [U-Boot] [PATCH 2/5] vf610: refactor DDRMC code Albert ARIBAUD
@ 2015-06-19 12:18     ` Albert ARIBAUD
  2015-06-19 12:18       ` [U-Boot] [PATCH 4/5] tools: mkimage: fix imximage header size Albert ARIBAUD
  2015-07-10  8:11       ` [U-Boot] [PATCH 3/5] i2c: fix vf610 support Stefano Babic
  2015-06-19 15:13     ` [U-Boot] [PATCH 2/5] vf610: refactor DDRMC code Stefan Agner
  1 sibling, 2 replies; 24+ messages in thread
From: Albert ARIBAUD @ 2015-06-19 12:18 UTC (permalink / raw)
  To: u-boot

Add support in mxc_i2c driver, iomux_v3 and vf610 architecture for the four
I2C instances available in VF610.

Signed-off-by: Albert ARIBAUD (3ADEV) <albert.aribaud@3adev.fr>
---

 arch/arm/include/asm/arch-vf610/crm_regs.h    |  3 +++
 arch/arm/include/asm/arch-vf610/imx-regs.h    |  3 +++
 arch/arm/include/asm/arch-vf610/iomux-vf610.h | 11 +++++++----
 arch/arm/include/asm/imx-common/iomux-v3.h    |  2 ++
 drivers/i2c/mxc_i2c.c                         |  3 ++-
 5 files changed, 17 insertions(+), 5 deletions(-)

diff --git a/arch/arm/include/asm/arch-vf610/crm_regs.h b/arch/arm/include/asm/arch-vf610/crm_regs.h
index fdb45e9..a46e396 100644
--- a/arch/arm/include/asm/arch-vf610/crm_regs.h
+++ b/arch/arm/include/asm/arch-vf610/crm_regs.h
@@ -207,6 +207,7 @@ struct anadig_reg {
 #define CCM_CCGR4_CCM_CTRL_MASK			(0x3 << 22)
 #define CCM_CCGR4_GPC_CTRL_MASK			(0x3 << 24)
 #define CCM_CCGR4_I2C0_CTRL_MASK		(0x3 << 12)
+#define CCM_CCGR4_I2C1_CTRL_MASK		(0x3 << 14)
 #define CCM_CCGR6_OCOTP_CTRL_MASK		(0x3 << 10)
 #define CCM_CCGR6_DSPI2_CTRL_MASK		(0x3 << 24)
 #define CCM_CCGR6_DSPI3_CTRL_MASK		(0x3 << 26)
@@ -216,6 +217,8 @@ struct anadig_reg {
 #define CCM_CCGR9_FEC0_CTRL_MASK		0x3
 #define CCM_CCGR9_FEC1_CTRL_MASK		(0x3 << 2)
 #define CCM_CCGR10_NFC_CTRL_MASK		0x3
+#define CCM_CCGR10_I2C2_CTRL_MASK		(0x3 << 12)
+#define CCM_CCGR10_I2C3_CTRL_MASK		(0x3 << 14)
 
 #define ANADIG_PLL7_CTRL_BYPASS         (1 << 16)
 #define ANADIG_PLL7_CTRL_ENABLE         (1 << 13)
diff --git a/arch/arm/include/asm/arch-vf610/imx-regs.h b/arch/arm/include/asm/arch-vf610/imx-regs.h
index 7df3b1e..4366985 100644
--- a/arch/arm/include/asm/arch-vf610/imx-regs.h
+++ b/arch/arm/include/asm/arch-vf610/imx-regs.h
@@ -75,6 +75,9 @@
 #define ESAI_FIFO_BASE_ADDR	(AIPS0_BASE_ADDR + 0x00063000)
 #define WDOG_BASE_ADDR		(AIPS0_BASE_ADDR + 0x00065000)
 #define I2C1_BASE_ADDR		(AIPS0_BASE_ADDR + 0x00066000)
+#define I2C2_BASE_ADDR		(AIPS0_BASE_ADDR + 0x00067000)
+#define I2C3_BASE_ADDR		(AIPS0_BASE_ADDR + 0x000E6000)
+#define I2C4_BASE_ADDR		(AIPS0_BASE_ADDR + 0x000E7000)
 #define WKUP_BASE_ADDR		(AIPS0_BASE_ADDR + 0x0006A000)
 #define CCM_BASE_ADDR		(AIPS0_BASE_ADDR + 0x0006B000)
 #define GPC_BASE_ADDR		(AIPS0_BASE_ADDR + 0x0006C000)
diff --git a/arch/arm/include/asm/arch-vf610/iomux-vf610.h b/arch/arm/include/asm/arch-vf610/iomux-vf610.h
index 019307b..0e2bd53 100644
--- a/arch/arm/include/asm/arch-vf610/iomux-vf610.h
+++ b/arch/arm/include/asm/arch-vf610/iomux-vf610.h
@@ -20,7 +20,8 @@
 #define VF610_DDR_PAD_CTRL_1	(PAD_CTL_DSE_25ohm | \
 				PAD_CTL_INPUT_DIFFERENTIAL)
 #define VF610_I2C_PAD_CTRL	(PAD_CTL_PUS_47K_UP | PAD_CTL_DSE_50ohm | \
-				PAD_CTL_SPEED_HIGH | PAD_CTL_OBE_IBE_ENABLE)
+				PAD_CTL_SPEED_HIGH | PAD_CTL_ODE | \
+				PAD_CTL_OBE_IBE_ENABLE)
 #define VF610_NFC_IO_PAD_CTRL	(PAD_CTL_SPEED_MED | PAD_CTL_SRE | \
 				PAD_CTL_DSE_50ohm | PAD_CTL_PUS_47K_UP | \
 				PAD_CTL_OBE_IBE_ENABLE)
@@ -110,6 +111,8 @@ enum {
 	VF610_PAD_PTA29__ESDHC1_DAT3		= IOMUX_PAD(0x004c, 0x004c, 5, __NA_, 0, VF610_SDHC_PAD_CTRL),
 	VF610_PAD_PTB14__I2C0_SCL		= IOMUX_PAD(0x0090, 0x0090, 2, 0x033c, 1, VF610_I2C_PAD_CTRL),
 	VF610_PAD_PTB15__I2C0_SDA		= IOMUX_PAD(0x0094, 0x0094, 2, 0x0340, 1, VF610_I2C_PAD_CTRL),
+	VF610_PAD_PTA22__I2C2_SCL		= IOMUX_PAD(0x0030, 0x0030, 6, 0x034c, 0, VF610_I2C_PAD_CTRL),
+	VF610_PAD_PTA23__I2C2_SDA		= IOMUX_PAD(0x0034, 0x0034, 6, 0x0350, 0, VF610_I2C_PAD_CTRL),
 	VF610_PAD_PTD31__NF_IO15		= IOMUX_PAD(0x00fc, 0x00fc, 2, __NA_, 0, VF610_NFC_IO_PAD_CTRL),
 	VF610_PAD_PTD31__GPIO_63		= IOMUX_PAD(0x00fc, 0x00fc, 0, __NA_, 0, VF610_GPIO_PAD_CTRL),
 	VF610_PAD_PTD30__NF_IO14		= IOMUX_PAD(0x0100, 0x0100, 2, __NA_, 0, VF610_NFC_IO_PAD_CTRL),
@@ -146,10 +149,10 @@ enum {
 	VF610_PAD_PTD12__GPIO_91		= IOMUX_PAD(0x016c, 0x016c, 0, __NA_, 0, VF610_GPIO_PAD_CTRL),
 	VF610_PAD_PTD13__GPIO_92		= IOMUX_PAD(0x0170, 0x0170, 0, __NA_, 0, VF610_GPIO_PAD_CTRL),
 	VF610_PAD_PTD22__NF_IO6			= IOMUX_PAD(0x0120, 0x0120, 2, __NA_, 0, VF610_NFC_IO_PAD_CTRL),
-	VF610_PAD_PTD21__NF_IO5			= IOMUX_PAD(0x0124, 0x0124, 2, __NA_, 0, VF610_NFC_IO_PAD_CTRL), 
-	VF610_PAD_PTD20__NF_IO4			= IOMUX_PAD(0x0128, 0x0128, 2, __NA_, 0, VF610_NFC_IO_PAD_CTRL), 
+	VF610_PAD_PTD21__NF_IO5			= IOMUX_PAD(0x0124, 0x0124, 2, __NA_, 0, VF610_NFC_IO_PAD_CTRL),
+	VF610_PAD_PTD20__NF_IO4			= IOMUX_PAD(0x0128, 0x0128, 2, __NA_, 0, VF610_NFC_IO_PAD_CTRL),
 	VF610_PAD_PTD19__NF_IO3			= IOMUX_PAD(0x012c, 0x012c, 2, __NA_, 0, VF610_NFC_IO_PAD_CTRL),
-	VF610_PAD_PTD18__NF_IO2			= IOMUX_PAD(0x0130, 0x0130, 2, __NA_, 0, VF610_NFC_IO_PAD_CTRL), 
+	VF610_PAD_PTD18__NF_IO2			= IOMUX_PAD(0x0130, 0x0130, 2, __NA_, 0, VF610_NFC_IO_PAD_CTRL),
 	VF610_PAD_PTD17__NF_IO1			= IOMUX_PAD(0x0134, 0x0134, 2, __NA_, 0, VF610_NFC_IO_PAD_CTRL),
 	VF610_PAD_PTD16__NF_IO0			= IOMUX_PAD(0x0138, 0x0138, 2, __NA_, 0, VF610_NFC_IO_PAD_CTRL),
 	VF610_PAD_PTB24__NF_WE_B		= IOMUX_PAD(0x0178, 0x0178, 5, __NA_, 0, VF610_NFC_CN_PAD_CTRL),
diff --git a/arch/arm/include/asm/imx-common/iomux-v3.h b/arch/arm/include/asm/imx-common/iomux-v3.h
index 2581019..5cde90f 100644
--- a/arch/arm/include/asm/imx-common/iomux-v3.h
+++ b/arch/arm/include/asm/imx-common/iomux-v3.h
@@ -127,6 +127,8 @@ typedef u64 iomux_v3_cfg_t;
 
 #define PAD_CTL_SRE		(1 << 11)
 
+#define PAD_CTL_ODE		(1 << 10)
+
 #define PAD_CTL_DSE_150ohm	(1 << 6)
 #define PAD_CTL_DSE_50ohm	(3 << 6)
 #define PAD_CTL_DSE_25ohm	(6 << 6)
diff --git a/drivers/i2c/mxc_i2c.c b/drivers/i2c/mxc_i2c.c
index b3c50aa..f1056e2 100644
--- a/drivers/i2c/mxc_i2c.c
+++ b/drivers/i2c/mxc_i2c.c
@@ -523,7 +523,8 @@ static int bus_i2c_write(struct mxc_i2c_bus *i2c_bus, u8 chip, u32 addr,
 #endif
 
 static struct mxc_i2c_bus mxc_i2c_buses[] = {
-#if defined(CONFIG_LS102XA) || defined(CONFIG_FSL_LSCH3)
+#if defined(CONFIG_LS102XA) || defined(CONFIG_FSL_LSCH3) || \
+		defined(CONFIG_VF610)
 	{ 0, I2C1_BASE_ADDR, I2C_QUIRK_FLAG },
 	{ 1, I2C2_BASE_ADDR, I2C_QUIRK_FLAG },
 	{ 2, I2C3_BASE_ADDR, I2C_QUIRK_FLAG },
-- 
2.1.0

^ permalink raw reply related	[flat|nested] 24+ messages in thread

* [U-Boot] [PATCH 4/5] tools: mkimage: fix imximage header size
  2015-06-19 12:18     ` [U-Boot] [PATCH 3/5] i2c: fix vf610 support Albert ARIBAUD
@ 2015-06-19 12:18       ` Albert ARIBAUD
  2015-06-19 12:18         ` [U-Boot] [PATCH 5/5] vf610: add support for Phytec PCM052 Albert ARIBAUD
  2015-07-10  8:14         ` [U-Boot] [PATCH 4/5] tools: mkimage: fix imximage header size Stefano Babic
  2015-07-10  8:11       ` [U-Boot] [PATCH 3/5] i2c: fix vf610 support Stefano Babic
  1 sibling, 2 replies; 24+ messages in thread
From: Albert ARIBAUD @ 2015-06-19 12:18 UTC (permalink / raw)
  To: u-boot

imximage header size is 4-byte, not 8-byte aligned.
This produces .imx images that a Vybrid cannot boot
on.

Fix by adding a "padding" field in header.

Signed-off-by: Albert ARIBAUD (3ADEV) <albert.aribaud@3adev.fr>
---

 tools/imximage.h | 1 +
 1 file changed, 1 insertion(+)

diff --git a/tools/imximage.h b/tools/imximage.h
index 36fe095..a913329 100644
--- a/tools/imximage.h
+++ b/tools/imximage.h
@@ -129,6 +129,7 @@ typedef struct {
 	ivt_header_t header;
 	write_dcd_command_t write_dcd_command;
 	dcd_addr_data_t addr_data[MAX_HW_CFG_SIZE_V2];
+	uint32_t padding[1]; /* end up on an 8-byte boundary */
 } dcd_v2_t;
 
 typedef struct {
-- 
2.1.0

^ permalink raw reply related	[flat|nested] 24+ messages in thread

* [U-Boot] [PATCH 5/5] vf610: add support for Phytec PCM052
  2015-06-19 12:18       ` [U-Boot] [PATCH 4/5] tools: mkimage: fix imximage header size Albert ARIBAUD
@ 2015-06-19 12:18         ` Albert ARIBAUD
  2015-07-10  8:14         ` [U-Boot] [PATCH 4/5] tools: mkimage: fix imximage header size Stefano Babic
  1 sibling, 0 replies; 24+ messages in thread
From: Albert ARIBAUD @ 2015-06-19 12:18 UTC (permalink / raw)
  To: u-boot

Devices supported are:
- NFC (NAND FLASH)
- MMC
- QSPI (SPI NOR FLASH)
- I2C (only bus 2)
- I2C RTC
- I2C EEPROM
- FEC

NOTES:

1. The NAND partitioning is different from the TimeSys U-Boot
deliveries' for the following reasons:

- mainline U-Boot is bigger than TimeSys', even though it now
  builds for Thumb state, which forces the bootloader area size
  to increase by 128KB;

- The redundant environment definition in the TimeSys deliveries
  is erroneous, as both environments are in the same Flash sector.
  Here each environment gest its own sector, which increases the
  size needed for the environments by 128KB;

- The kernel area was consequently reduced by 256KB, and the
  rootfs area left unchanged (depending on the actual kernel
  size, the kernel and rootfs area sizes may need to change
  again in the future).

2. The FEC presents a bug whereby it will indicate a packet as
   sent but will not actually have sent it. Caches are not the
   cause. Erratum e6358 is not the cause, and implementing this
   erratum's workaround does not fix the bug. The FEC's observable
   state is strictly the same (and correct) whether the packet was
   actually sent or not, i.e., there is no way to detect a bug
   occurrence, apart from the higher layer failure (e.g. TFTP
   timeout). At this point I suspect this to be a silicon bug.

Patch-series: 1
Signed-off-by: Albert ARIBAUD (3ADEV) <albert.aribaud@3adev.fr>
---

 arch/arm/Kconfig                 |   5 +
 board/phytec/pcm052/Kconfig      |  15 ++
 board/phytec/pcm052/MAINTAINERS  |   6 +
 board/phytec/pcm052/Makefile     |   7 +
 board/phytec/pcm052/imximage.cfg |  17 ++
 board/phytec/pcm052/pcm052.c     | 530 +++++++++++++++++++++++++++++++++++++++
 configs/pcm052_defconfig         |   6 +
 include/configs/pcm052.h         | 234 +++++++++++++++++
 8 files changed, 820 insertions(+)
 create mode 100644 board/phytec/pcm052/Kconfig
 create mode 100644 board/phytec/pcm052/MAINTAINERS
 create mode 100644 board/phytec/pcm052/Makefile
 create mode 100644 board/phytec/pcm052/imximage.cfg
 create mode 100644 board/phytec/pcm052/pcm052.c
 create mode 100644 configs/pcm052_defconfig
 create mode 100644 include/configs/pcm052.h

diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index ac86518..27a5a04 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -661,6 +661,10 @@ config TARGET_COLIBRI_VF
 	bool "Support Colibri VF50/61"
 	select CPU_V7
 
+config TARGET_PCM052
+	bool "Support pcm-052"
+	select CPU_V7
+
 config ARCH_ZYNQ
 	bool "Xilinx Zynq Platform"
 	select CPU_V7
@@ -936,6 +940,7 @@ source "board/palmld/Kconfig"
 source "board/palmtc/Kconfig"
 source "board/palmtreo680/Kconfig"
 source "board/phytec/pcm051/Kconfig"
+source "board/phytec/pcm052/Kconfig"
 source "board/ppcag/bg0900/Kconfig"
 source "board/pxa255_idp/Kconfig"
 source "board/samsung/smdk2410/Kconfig"
diff --git a/board/phytec/pcm052/Kconfig b/board/phytec/pcm052/Kconfig
new file mode 100644
index 0000000..d67a69a
--- /dev/null
+++ b/board/phytec/pcm052/Kconfig
@@ -0,0 +1,15 @@
+if TARGET_PCM052
+
+config SYS_BOARD
+	default "pcm052"
+
+config SYS_VENDOR
+	default "phytec"
+
+config SYS_SOC
+	default "vf610"
+
+config SYS_CONFIG_NAME
+	default "pcm052"
+
+endif
diff --git a/board/phytec/pcm052/MAINTAINERS b/board/phytec/pcm052/MAINTAINERS
new file mode 100644
index 0000000..a877436
--- /dev/null
+++ b/board/phytec/pcm052/MAINTAINERS
@@ -0,0 +1,6 @@
+PCM052 BOARD
+M:	Albert ARIBAUD (3ADEV) <albert.aribaud@3adev.fr>
+S:	Maintained
+F:	board/phytec/pcm052/
+F:	include/configs/pcm052.h
+F:	configs/pcm052_defconfig
diff --git a/board/phytec/pcm052/Makefile b/board/phytec/pcm052/Makefile
new file mode 100644
index 0000000..144f4e7
--- /dev/null
+++ b/board/phytec/pcm052/Makefile
@@ -0,0 +1,7 @@
+#
+# Copyright 2013 Freescale Semiconductor, Inc.
+#
+# SPDX-License-Identifier:	GPL-2.0+
+#
+
+obj-y	:= pcm052.o
diff --git a/board/phytec/pcm052/imximage.cfg b/board/phytec/pcm052/imximage.cfg
new file mode 100644
index 0000000..f5a9747
--- /dev/null
+++ b/board/phytec/pcm052/imximage.cfg
@@ -0,0 +1,17 @@
+/*
+ * Copyright 2015 3ADEV <http://www.3adev.com>
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ *
+ * Refer docs/README.imxmage for more details about how-to configure
+ * and create imximage boot image
+ *
+ * The syntax is taken as close as possible with the kwbimage
+ */
+#include <asm/imx-common/imximage.cfg>
+
+/* image version */
+IMAGE_VERSION	2
+
+/* Boot Offset 0x400, valid for both SD and NAND boot */
+BOOT_OFFSET	FLASH_OFFSET_STANDARD
diff --git a/board/phytec/pcm052/pcm052.c b/board/phytec/pcm052/pcm052.c
new file mode 100644
index 0000000..0607f1c
--- /dev/null
+++ b/board/phytec/pcm052/pcm052.c
@@ -0,0 +1,530 @@
+/*
+ * Copyright 2013 Freescale Semiconductor, Inc.
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#include <common.h>
+#include <asm/io.h>
+#include <asm/arch/imx-regs.h>
+#include <asm/arch/iomux-vf610.h>
+#include <asm/arch/ddrmc-vf610.h>
+#include <asm/arch/crm_regs.h>
+#include <asm/arch/clock.h>
+#include <mmc.h>
+#include <fsl_esdhc.h>
+#include <miiphy.h>
+#include <netdev.h>
+#include <i2c.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+/*
+ * Default DDR pad settings in arch/arm/include/asm/arch-vf610/iomux-vf610.h
+ * do not match our settings. Let us (re)define our own settings here.
+ */
+
+#define PCM052_VF610_DDR_PAD_CTRL	PAD_CTL_DSE_20ohm
+#define PCM052_VF610_DDR_PAD_CTRL_1	(PAD_CTL_DSE_20ohm | \
+					PAD_CTL_INPUT_DIFFERENTIAL)
+#define PCM052_VF610_DDR_RESET_PAD_CTL	(PAD_CTL_DSE_150ohm | \
+					PAD_CTL_PUS_100K_UP | \
+					PAD_CTL_INPUT_DIFFERENTIAL)
+
+enum {
+	PCM052_VF610_PAD_DDR_RESETB			= IOMUX_PAD(0x021c, __NA_, 0, __NA_, 0, PCM052_VF610_DDR_RESET_PAD_CTL),
+	PCM052_VF610_PAD_DDR_A15__DDR_A_15		= IOMUX_PAD(0x0220, __NA_, 0, __NA_, 0, PCM052_VF610_DDR_PAD_CTRL),
+	PCM052_VF610_PAD_DDR_A14__DDR_A_14		= IOMUX_PAD(0x0224, __NA_, 0, __NA_, 0, PCM052_VF610_DDR_PAD_CTRL),
+	PCM052_VF610_PAD_DDR_A13__DDR_A_13		= IOMUX_PAD(0x0228, __NA_, 0, __NA_, 0, PCM052_VF610_DDR_PAD_CTRL),
+	PCM052_VF610_PAD_DDR_A12__DDR_A_12		= IOMUX_PAD(0x022c, __NA_, 0, __NA_, 0, PCM052_VF610_DDR_PAD_CTRL),
+	PCM052_VF610_PAD_DDR_A11__DDR_A_11		= IOMUX_PAD(0x0230, __NA_, 0, __NA_, 0, PCM052_VF610_DDR_PAD_CTRL),
+	PCM052_VF610_PAD_DDR_A10__DDR_A_10		= IOMUX_PAD(0x0234, __NA_, 0, __NA_, 0, PCM052_VF610_DDR_PAD_CTRL),
+	PCM052_VF610_PAD_DDR_A9__DDR_A_9		= IOMUX_PAD(0x0238, __NA_, 0, __NA_, 0, PCM052_VF610_DDR_PAD_CTRL),
+	PCM052_VF610_PAD_DDR_A8__DDR_A_8		= IOMUX_PAD(0x023c, __NA_, 0, __NA_, 0, PCM052_VF610_DDR_PAD_CTRL),
+	PCM052_VF610_PAD_DDR_A7__DDR_A_7		= IOMUX_PAD(0x0240, __NA_, 0, __NA_, 0, PCM052_VF610_DDR_PAD_CTRL),
+	PCM052_VF610_PAD_DDR_A6__DDR_A_6		= IOMUX_PAD(0x0244, __NA_, 0, __NA_, 0, PCM052_VF610_DDR_PAD_CTRL),
+	PCM052_VF610_PAD_DDR_A5__DDR_A_5		= IOMUX_PAD(0x0248, __NA_, 0, __NA_, 0, PCM052_VF610_DDR_PAD_CTRL),
+	PCM052_VF610_PAD_DDR_A4__DDR_A_4		= IOMUX_PAD(0x024c, __NA_, 0, __NA_, 0, PCM052_VF610_DDR_PAD_CTRL),
+	PCM052_VF610_PAD_DDR_A3__DDR_A_3		= IOMUX_PAD(0x0250, __NA_, 0, __NA_, 0, PCM052_VF610_DDR_PAD_CTRL),
+	PCM052_VF610_PAD_DDR_A2__DDR_A_2		= IOMUX_PAD(0x0254, __NA_, 0, __NA_, 0, PCM052_VF610_DDR_PAD_CTRL),
+	PCM052_VF610_PAD_DDR_A1__DDR_A_1		= IOMUX_PAD(0x0258, __NA_, 0, __NA_, 0, PCM052_VF610_DDR_PAD_CTRL),
+	PCM052_VF610_PAD_DDR_A0__DDR_A_0		= IOMUX_PAD(0x025c, __NA_, 0, __NA_, 0, PCM052_VF610_DDR_PAD_CTRL),
+	PCM052_VF610_PAD_DDR_BA2__DDR_BA_2		= IOMUX_PAD(0x0260, __NA_, 0, __NA_, 0, PCM052_VF610_DDR_PAD_CTRL),
+	PCM052_VF610_PAD_DDR_BA1__DDR_BA_1		= IOMUX_PAD(0x0264, __NA_, 0, __NA_, 0, PCM052_VF610_DDR_PAD_CTRL),
+	PCM052_VF610_PAD_DDR_BA0__DDR_BA_0		= IOMUX_PAD(0x0268, __NA_, 0, __NA_, 0, PCM052_VF610_DDR_PAD_CTRL),
+	PCM052_VF610_PAD_DDR_CAS__DDR_CAS_B		= IOMUX_PAD(0x026c, __NA_, 0, __NA_, 0, PCM052_VF610_DDR_PAD_CTRL),
+	PCM052_VF610_PAD_DDR_CKE__DDR_CKE_0		= IOMUX_PAD(0x0270, __NA_, 0, __NA_, 0, PCM052_VF610_DDR_PAD_CTRL),
+	PCM052_VF610_PAD_DDR_CLK__DDR_CLK_0		= IOMUX_PAD(0x0274, __NA_, 0, __NA_, 0, PCM052_VF610_DDR_PAD_CTRL_1),
+	PCM052_VF610_PAD_DDR_CS__DDR_CS_B_0		= IOMUX_PAD(0x0278, __NA_, 0, __NA_, 0, PCM052_VF610_DDR_PAD_CTRL),
+	PCM052_VF610_PAD_DDR_D15__DDR_D_15		= IOMUX_PAD(0x027c, __NA_, 0, __NA_, 0, PCM052_VF610_DDR_PAD_CTRL),
+	PCM052_VF610_PAD_DDR_D14__DDR_D_14		= IOMUX_PAD(0x0280, __NA_, 0, __NA_, 0, PCM052_VF610_DDR_PAD_CTRL),
+	PCM052_VF610_PAD_DDR_D13__DDR_D_13		= IOMUX_PAD(0x0284, __NA_, 0, __NA_, 0, PCM052_VF610_DDR_PAD_CTRL),
+	PCM052_VF610_PAD_DDR_D12__DDR_D_12		= IOMUX_PAD(0x0288, __NA_, 0, __NA_, 0, PCM052_VF610_DDR_PAD_CTRL),
+	PCM052_VF610_PAD_DDR_D11__DDR_D_11		= IOMUX_PAD(0x028c, __NA_, 0, __NA_, 0, PCM052_VF610_DDR_PAD_CTRL),
+	PCM052_VF610_PAD_DDR_D10__DDR_D_10		= IOMUX_PAD(0x0290, __NA_, 0, __NA_, 0, PCM052_VF610_DDR_PAD_CTRL),
+	PCM052_VF610_PAD_DDR_D9__DDR_D_9		= IOMUX_PAD(0x0294, __NA_, 0, __NA_, 0, PCM052_VF610_DDR_PAD_CTRL),
+	PCM052_VF610_PAD_DDR_D8__DDR_D_8		= IOMUX_PAD(0x0298, __NA_, 0, __NA_, 0, PCM052_VF610_DDR_PAD_CTRL),
+	PCM052_VF610_PAD_DDR_D7__DDR_D_7		= IOMUX_PAD(0x029c, __NA_, 0, __NA_, 0, PCM052_VF610_DDR_PAD_CTRL),
+	PCM052_VF610_PAD_DDR_D6__DDR_D_6		= IOMUX_PAD(0x02a0, __NA_, 0, __NA_, 0, PCM052_VF610_DDR_PAD_CTRL),
+	PCM052_VF610_PAD_DDR_D5__DDR_D_5		= IOMUX_PAD(0x02a4, __NA_, 0, __NA_, 0, PCM052_VF610_DDR_PAD_CTRL),
+	PCM052_VF610_PAD_DDR_D4__DDR_D_4		= IOMUX_PAD(0x02a8, __NA_, 0, __NA_, 0, PCM052_VF610_DDR_PAD_CTRL),
+	PCM052_VF610_PAD_DDR_D3__DDR_D_3		= IOMUX_PAD(0x02ac, __NA_, 0, __NA_, 0, PCM052_VF610_DDR_PAD_CTRL),
+	PCM052_VF610_PAD_DDR_D2__DDR_D_2		= IOMUX_PAD(0x02b0, __NA_, 0, __NA_, 0, PCM052_VF610_DDR_PAD_CTRL),
+	PCM052_VF610_PAD_DDR_D1__DDR_D_1		= IOMUX_PAD(0x02b4, __NA_, 0, __NA_, 0, PCM052_VF610_DDR_PAD_CTRL),
+	PCM052_VF610_PAD_DDR_D0__DDR_D_0		= IOMUX_PAD(0x02b8, __NA_, 0, __NA_, 0, PCM052_VF610_DDR_PAD_CTRL),
+	PCM052_VF610_PAD_DDR_DQM1__DDR_DQM_1		= IOMUX_PAD(0x02bc, __NA_, 0, __NA_, 0, PCM052_VF610_DDR_PAD_CTRL),
+	PCM052_VF610_PAD_DDR_DQM0__DDR_DQM_0		= IOMUX_PAD(0x02c0, __NA_, 0, __NA_, 0, PCM052_VF610_DDR_PAD_CTRL),
+	PCM052_VF610_PAD_DDR_DQS1__DDR_DQS_1		= IOMUX_PAD(0x02c4, __NA_, 0, __NA_, 0, PCM052_VF610_DDR_PAD_CTRL_1),
+	PCM052_VF610_PAD_DDR_DQS0__DDR_DQS_0		= IOMUX_PAD(0x02c8, __NA_, 0, __NA_, 0, PCM052_VF610_DDR_PAD_CTRL_1),
+	PCM052_VF610_PAD_DDR_RAS__DDR_RAS_B		= IOMUX_PAD(0x02cc, __NA_, 0, __NA_, 0, PCM052_VF610_DDR_PAD_CTRL),
+	PCM052_VF610_PAD_DDR_WE__DDR_WE_B		= IOMUX_PAD(0x02d0, __NA_, 0, __NA_, 0, PCM052_VF610_DDR_PAD_CTRL),
+	PCM052_VF610_PAD_DDR_ODT1__DDR_ODT_0		= IOMUX_PAD(0x02d4, __NA_, 0, __NA_, 0, PCM052_VF610_DDR_PAD_CTRL),
+	PCM052_VF610_PAD_DDR_ODT0__DDR_ODT_1		= IOMUX_PAD(0x02d8, __NA_, 0, __NA_, 0, PCM052_VF610_DDR_PAD_CTRL),
+	PCM052_VF610_PAD_DDR_DDRBYTE1__DDR_DDRBYTE1	= IOMUX_PAD(0x02dc, __NA_, 0, __NA_, 0, PCM052_VF610_DDR_PAD_CTRL),
+	PCM052_VF610_PAD_DDR_DDRBYTE0__DDR_DDRBYTE0	= IOMUX_PAD(0x02e0, __NA_, 0, __NA_, 0, PCM052_VF610_DDR_PAD_CTRL),
+};
+
+static struct ddrmc_reg_setting pcm052_cr_settings[] = {
+	{ DDRMC_CR00_DRAM_CLASS_DDR3, 0 },
+	{ DDRMC_CR02_DRAM_TINIT(5), 2 },
+	{ DDRMC_CR10_TRST_PWRON(80000), 10 },
+
+	{ DDRMC_CR11_CKE_INACTIVE(200000), 11 },
+	{ DDRMC_CR12_WRLAT(5) | DDRMC_CR12_CASLAT_LIN(12), 12 },
+	{ DDRMC_CR13_TRC(6) | DDRMC_CR13_TRRD(4) | DDRMC_CR13_TCCD(4) |
+		   DDRMC_CR13_TBST_INT_INTERVAL(4), 13 },
+	{ DDRMC_CR14_TFAW(18) | DDRMC_CR14_TRP(6) | DDRMC_CR14_TWTR(4) |
+		   DDRMC_CR14_TRAS_MIN(15), 14 },
+	{ DDRMC_CR16_TMRD(4) |DDRMC_CR16_TRTP(4), 16 },
+	{ DDRMC_CR17_TRAS_MAX(14040) | DDRMC_CR17_TMOD(12), 17 },
+	{ DDRMC_CR18_TCKESR(4) | DDRMC_CR18_TCKE(3), 18 },
+
+	{ DDRMC_CR20_AP_EN, 20 },
+	{ DDRMC_CR21_TRCD_INT(6) | DDRMC_CR21_CCMAP_EN |
+		   DDRMC_CR21_TRAS_LOCKOUT, 21 },
+
+	{ DDRMC_CR22_TDAL(10), 22 },
+	{ DDRMC_CR23_BSTLEN(3) | DDRMC_CR23_TDLL(512), 23 },
+	{ DDRMC_CR24_TRP_AB(6), 24 },
+
+	{ DDRMC_CR25_TREF_EN, 25 },
+	{ DDRMC_CR26_TREF(1542) | DDRMC_CR26_TRFC(64), 26 },
+	{ DDRMC_CR28_TREF_INT(5), 28 },
+	{ DDRMC_CR29_TPDEX(3), 29 },
+
+	{ DDRMC_CR30_TXPDLL(10), 30 },
+	{ DDRMC_CR31_TXSNR(68) | DDRMC_CR31_TXSR(506), 31 },
+	{ DDRMC_CR33_EN_QK_SREF, 33 },
+	{ DDRMC_CR34_CKSRX(5) | DDRMC_CR34_CKSRE(5), 34 },
+
+	{ DDRMC_CR38_FREQ_CHG_EN(1), 38 },
+	{ DDRMC_CR39_PHY_INI_COM(1024) | DDRMC_CR39_PHY_INI_STA(16) |
+		   DDRMC_CR39_FRQ_CH_DLLOFF(2), 39 },
+
+	{ DDRMC_CR41_PHY_INI_STRT_INI_DIS, 41 },
+	{ DDRMC_CR48_MR1_DA_0(70) | DDRMC_CR48_MR0_DA_0(1056), 48 },
+
+	{ DDRMC_CR66_ZQCL(256) | DDRMC_CR66_ZQINIT(512), 66 },
+	{ DDRMC_CR67_ZQCS(64), 67 },
+	{ DDRMC_CR69_ZQ_ON_SREF_EX(2), 69 },
+
+	{ DDRMC_CR70_REF_PER_ZQ(64), 70 },
+	{ DDRMC_CR72_ZQCS_ROTATE(1), 72 },
+
+	{ DDRMC_CR73_APREBIT(10) | DDRMC_CR73_COL_DIFF(1) |
+		   DDRMC_CR73_ROW_DIFF(2), 73 },
+	{ DDRMC_CR74_BANKSPLT_EN | DDRMC_CR74_ADDR_CMP_EN |
+		   DDRMC_CR74_CMD_AGE_CNT(255) | DDRMC_CR74_AGE_CNT(255),
+		   74 },
+	{ DDRMC_CR75_RW_PG_EN | DDRMC_CR75_RW_EN | DDRMC_CR75_PRI_EN |
+		   DDRMC_CR75_PLEN, 75 },
+	{ DDRMC_CR76_NQENT_ACTDIS(3) | DDRMC_CR76_D_RW_G_BKCN(3) |
+		   DDRMC_CR76_W2R_SPLT_EN, 76 },
+	{ DDRMC_CR77_CS_MAP | DDRMC_CR77_DI_RD_INTLEAVE |
+		   DDRMC_CR77_SWAP_EN, 77 },
+	{ DDRMC_CR78_Q_FULLNESS(0) |
+		   DDRMC_CR78_BUR_ON_FLY_BIT(12), 78 },
+	{ DDRMC_CR79_CTLUPD_AREF(0), 79 },
+
+	{ DDRMC_CR87_ODT_WR_MAPCS0 | DDRMC_CR87_ODT_RD_MAPCS0, 87 },
+	{ DDRMC_CR88_TODTL_CMD(4), 88 },
+	{ DDRMC_CR89_AODT_RWSMCS(2), 89 },
+
+	{ DDRMC_CR91_R2W_SMCSDL(2), 91 },
+	{ DDRMC_CR96_WLMRD(40) | DDRMC_CR96_WLDQSEN(25), 96 },
+
+	{ 0x00002000, 105 },
+	{ 0x00000020, 110 },
+
+	{ DDRMC_CR117_AXI0_W_PRI(1) | DDRMC_CR117_AXI0_R_PRI(1), 117 },
+	{ DDRMC_CR118_AXI1_W_PRI(1) | DDRMC_CR118_AXI1_R_PRI(1), 118 },
+	{ DDRMC_CR120_AXI0_PRI1_RPRI(2) |
+		   DDRMC_CR120_AXI0_PRI0_RPRI(2), 120 },
+	{ DDRMC_CR121_AXI0_PRI3_RPRI(2) |
+		   DDRMC_CR121_AXI0_PRI2_RPRI(2), 121 },
+	{ DDRMC_CR122_AXI1_PRI1_RPRI(1) | DDRMC_CR122_AXI1_PRI0_RPRI(1) |
+		   DDRMC_CR122_AXI0_PRIRLX(100), 122 },
+	{ DDRMC_CR123_AXI1_P_ODR_EN | DDRMC_CR123_AXI1_PRI3_RPRI(1) |
+		   DDRMC_CR123_AXI1_PRI2_RPRI(1), 123 },
+	{ DDRMC_CR124_AXI1_PRIRLX(100), 124 },
+	{ DDRMC_CR126_PHY_RDLAT(11), 126 },
+	{ DDRMC_CR132_WRLAT_ADJ(5) | DDRMC_CR132_RDLAT_ADJ(6), 132 },
+	{ DDRMC_CR137_PHYCTL_DL(2), 137 },
+	{ DDRMC_CR139_PHY_WRLV_RESPLAT(4) | DDRMC_CR139_PHY_WRLV_LOAD(7) |
+		   DDRMC_CR139_PHY_WRLV_DLL(3) |
+		   DDRMC_CR139_PHY_WRLV_EN(3), 139 },
+	{ DDRMC_CR154_PAD_ZQ_EARLY_CMP_EN_TIMER(13) |
+		   DDRMC_CR154_PAD_ZQ_MODE(1) |
+		   DDRMC_CR154_DDR_SEL_PAD_CONTR(3) |
+		   DDRMC_CR154_PAD_ZQ_HW_FOR(0), 154 },
+	{ DDRMC_CR155_PAD_ODT_BYTE1(5) | DDRMC_CR155_PAD_ODT_BYTE0(5), 155 },
+	{ DDRMC_CR158_TWR(6), 158 },
+	{ DDRMC_CR161_ODT_EN(0) | DDRMC_CR161_TODTH_RD(0) |
+		   DDRMC_CR161_TODTH_WR(6), 161 },
+	/* end marker */
+	{ 0, -1 }
+};
+
+/* PHY settings -- some of them differ from default in imx-regs.h */
+
+#define PCM052_DDRMC_PHY_DQ_TIMING			0x00002213
+#define PCM052_DDRMC_PHY_CTRL				0x00290000
+#define PCM052_DDRMC_PHY_SLAVE_CTRL			0x00002c00
+#define PCM052_DDRMC_PHY_PROC_PAD_ODT			0x00010020
+
+static struct ddrmc_reg_setting pcm052_phy_settings[] = {
+	{ PCM052_DDRMC_PHY_DQ_TIMING,  0 },
+	{ PCM052_DDRMC_PHY_DQ_TIMING, 16 },
+	{ PCM052_DDRMC_PHY_DQ_TIMING, 32 },
+	{ PCM052_DDRMC_PHY_DQ_TIMING, 48 },
+	{ DDRMC_PHY_DQS_TIMING,  1 },
+	{ DDRMC_PHY_DQS_TIMING, 17 },
+	{ DDRMC_PHY_DQS_TIMING, 33 },
+	{ DDRMC_PHY_DQS_TIMING, 49 },
+	{ PCM052_DDRMC_PHY_CTRL,  2 },
+	{ PCM052_DDRMC_PHY_CTRL, 18 },
+	{ PCM052_DDRMC_PHY_CTRL, 34 },
+	{ DDRMC_PHY_MASTER_CTRL,  3 },
+	{ DDRMC_PHY_MASTER_CTRL, 19 },
+	{ DDRMC_PHY_MASTER_CTRL, 35 },
+	{ PCM052_DDRMC_PHY_SLAVE_CTRL,  4 },
+	{ PCM052_DDRMC_PHY_SLAVE_CTRL, 20 },
+	{ PCM052_DDRMC_PHY_SLAVE_CTRL, 36 },
+	{ DDRMC_PHY50_DDR3_MODE | DDRMC_PHY50_EN_SW_HALF_CYCLE, 50 },
+	{ PCM052_DDRMC_PHY_PROC_PAD_ODT, 52 },
+
+	/* end marker */
+	{ 0, -1 }
+};
+
+int dram_init(void)
+{
+	static const iomux_v3_cfg_t pcm052_pads[] = {
+		PCM052_VF610_PAD_DDR_A15__DDR_A_15,
+		PCM052_VF610_PAD_DDR_A14__DDR_A_14,
+		PCM052_VF610_PAD_DDR_A13__DDR_A_13,
+		PCM052_VF610_PAD_DDR_A12__DDR_A_12,
+		PCM052_VF610_PAD_DDR_A11__DDR_A_11,
+		PCM052_VF610_PAD_DDR_A10__DDR_A_10,
+		PCM052_VF610_PAD_DDR_A9__DDR_A_9,
+		PCM052_VF610_PAD_DDR_A8__DDR_A_8,
+		PCM052_VF610_PAD_DDR_A7__DDR_A_7,
+		PCM052_VF610_PAD_DDR_A6__DDR_A_6,
+		PCM052_VF610_PAD_DDR_A5__DDR_A_5,
+		PCM052_VF610_PAD_DDR_A4__DDR_A_4,
+		PCM052_VF610_PAD_DDR_A3__DDR_A_3,
+		PCM052_VF610_PAD_DDR_A2__DDR_A_2,
+		PCM052_VF610_PAD_DDR_A1__DDR_A_1,
+		PCM052_VF610_PAD_DDR_A0__DDR_A_0,
+		PCM052_VF610_PAD_DDR_BA2__DDR_BA_2,
+		PCM052_VF610_PAD_DDR_BA1__DDR_BA_1,
+		PCM052_VF610_PAD_DDR_BA0__DDR_BA_0,
+		PCM052_VF610_PAD_DDR_CAS__DDR_CAS_B,
+		PCM052_VF610_PAD_DDR_CKE__DDR_CKE_0,
+		PCM052_VF610_PAD_DDR_CLK__DDR_CLK_0,
+		PCM052_VF610_PAD_DDR_CS__DDR_CS_B_0,
+		PCM052_VF610_PAD_DDR_D15__DDR_D_15,
+		PCM052_VF610_PAD_DDR_D14__DDR_D_14,
+		PCM052_VF610_PAD_DDR_D13__DDR_D_13,
+		PCM052_VF610_PAD_DDR_D12__DDR_D_12,
+		PCM052_VF610_PAD_DDR_D11__DDR_D_11,
+		PCM052_VF610_PAD_DDR_D10__DDR_D_10,
+		PCM052_VF610_PAD_DDR_D9__DDR_D_9,
+		PCM052_VF610_PAD_DDR_D8__DDR_D_8,
+		PCM052_VF610_PAD_DDR_D7__DDR_D_7,
+		PCM052_VF610_PAD_DDR_D6__DDR_D_6,
+		PCM052_VF610_PAD_DDR_D5__DDR_D_5,
+		PCM052_VF610_PAD_DDR_D4__DDR_D_4,
+		PCM052_VF610_PAD_DDR_D3__DDR_D_3,
+		PCM052_VF610_PAD_DDR_D2__DDR_D_2,
+		PCM052_VF610_PAD_DDR_D1__DDR_D_1,
+		PCM052_VF610_PAD_DDR_D0__DDR_D_0,
+		PCM052_VF610_PAD_DDR_DQM1__DDR_DQM_1,
+		PCM052_VF610_PAD_DDR_DQM0__DDR_DQM_0,
+		PCM052_VF610_PAD_DDR_DQS1__DDR_DQS_1,
+		PCM052_VF610_PAD_DDR_DQS0__DDR_DQS_0,
+		PCM052_VF610_PAD_DDR_RAS__DDR_RAS_B,
+		PCM052_VF610_PAD_DDR_WE__DDR_WE_B,
+		PCM052_VF610_PAD_DDR_ODT1__DDR_ODT_0,
+		PCM052_VF610_PAD_DDR_ODT0__DDR_ODT_1,
+		PCM052_VF610_PAD_DDR_DDRBYTE1__DDR_DDRBYTE1,
+		PCM052_VF610_PAD_DDR_DDRBYTE0__DDR_DDRBYTE0,
+		PCM052_VF610_PAD_DDR_RESETB,
+	};
+
+	imx_iomux_v3_setup_multiple_pads(pcm052_pads, ARRAY_SIZE(pcm052_pads));
+
+	ddrmc_ctrl_init_ddr3(pcm052_cr_settings, pcm052_phy_settings);
+
+	gd->ram_size = get_ram_size((void *)PHYS_SDRAM, PHYS_SDRAM_SIZE);
+
+	return 0;
+}
+
+static void setup_iomux_uart(void)
+{
+	static const iomux_v3_cfg_t uart1_pads[] = {
+		NEW_PAD_CTRL(VF610_PAD_PTB4__UART1_TX, VF610_UART_PAD_CTRL),
+		NEW_PAD_CTRL(VF610_PAD_PTB5__UART1_RX, VF610_UART_PAD_CTRL),
+	};
+
+	imx_iomux_v3_setup_multiple_pads(uart1_pads, ARRAY_SIZE(uart1_pads));
+}
+
+#define ENET_PAD_CTRL	(PAD_CTL_PUS_47K_UP | PAD_CTL_SPEED_HIGH | \
+			PAD_CTL_DSE_50ohm | PAD_CTL_OBE_IBE_ENABLE)
+
+static void setup_iomux_enet(void)
+{
+	static const iomux_v3_cfg_t enet0_pads[] = {
+		NEW_PAD_CTRL(VF610_PAD_PTA6__RMII0_CLKIN, ENET_PAD_CTRL),
+		NEW_PAD_CTRL(VF610_PAD_PTC1__RMII0_MDIO, ENET_PAD_CTRL),
+		NEW_PAD_CTRL(VF610_PAD_PTC0__RMII0_MDC, ENET_PAD_CTRL),
+		NEW_PAD_CTRL(VF610_PAD_PTC2__RMII0_CRS_DV, ENET_PAD_CTRL),
+		NEW_PAD_CTRL(VF610_PAD_PTC3__RMII0_RD1, ENET_PAD_CTRL),
+		NEW_PAD_CTRL(VF610_PAD_PTC4__RMII0_RD0, ENET_PAD_CTRL),
+		NEW_PAD_CTRL(VF610_PAD_PTC5__RMII0_RXER, ENET_PAD_CTRL),
+		NEW_PAD_CTRL(VF610_PAD_PTC6__RMII0_TD1, ENET_PAD_CTRL),
+		NEW_PAD_CTRL(VF610_PAD_PTC7__RMII0_TD0, ENET_PAD_CTRL),
+		NEW_PAD_CTRL(VF610_PAD_PTC8__RMII0_TXEN, ENET_PAD_CTRL),
+	};
+
+	imx_iomux_v3_setup_multiple_pads(enet0_pads, ARRAY_SIZE(enet0_pads));
+}
+
+/*
+ * I2C2 is the only I2C used, on pads PTA22/PTA23.
+ */
+
+static void setup_iomux_i2c(void)
+{
+	static const iomux_v3_cfg_t i2c_pads[] = {
+		VF610_PAD_PTA22__I2C2_SCL,
+		VF610_PAD_PTA23__I2C2_SDA,
+	};
+
+	imx_iomux_v3_setup_multiple_pads(i2c_pads, ARRAY_SIZE(i2c_pads));
+}
+
+#ifdef CONFIG_NAND_VF610_NFC
+static void setup_iomux_nfc(void)
+{
+	static const iomux_v3_cfg_t nfc_pads[] = {
+		VF610_PAD_PTD31__NF_IO15,
+		VF610_PAD_PTD30__NF_IO14,
+		VF610_PAD_PTD29__NF_IO13,
+		VF610_PAD_PTD28__NF_IO12,
+		VF610_PAD_PTD27__NF_IO11,
+		VF610_PAD_PTD26__NF_IO10,
+		VF610_PAD_PTD25__NF_IO9,
+		VF610_PAD_PTD24__NF_IO8,
+		VF610_PAD_PTD23__NF_IO7,
+		VF610_PAD_PTD22__NF_IO6,
+		VF610_PAD_PTD21__NF_IO5,
+		VF610_PAD_PTD20__NF_IO4,
+		VF610_PAD_PTD19__NF_IO3,
+		VF610_PAD_PTD18__NF_IO2,
+		VF610_PAD_PTD17__NF_IO1,
+		VF610_PAD_PTD16__NF_IO0,
+		VF610_PAD_PTB24__NF_WE_B,
+		VF610_PAD_PTB25__NF_CE0_B,
+		VF610_PAD_PTB27__NF_RE_B,
+		VF610_PAD_PTC26__NF_RB_B,
+		VF610_PAD_PTC27__NF_ALE,
+		VF610_PAD_PTC28__NF_CLE
+	};
+
+	imx_iomux_v3_setup_multiple_pads(nfc_pads, ARRAY_SIZE(nfc_pads));
+}
+#endif
+
+static void setup_iomux_qspi(void)
+{
+	static const iomux_v3_cfg_t qspi0_pads[] = {
+		VF610_PAD_PTD0__QSPI0_A_QSCK,
+		VF610_PAD_PTD1__QSPI0_A_CS0,
+		VF610_PAD_PTD2__QSPI0_A_DATA3,
+		VF610_PAD_PTD3__QSPI0_A_DATA2,
+		VF610_PAD_PTD4__QSPI0_A_DATA1,
+		VF610_PAD_PTD5__QSPI0_A_DATA0,
+		VF610_PAD_PTD7__QSPI0_B_QSCK,
+		VF610_PAD_PTD8__QSPI0_B_CS0,
+		VF610_PAD_PTD9__QSPI0_B_DATA3,
+		VF610_PAD_PTD10__QSPI0_B_DATA2,
+		VF610_PAD_PTD11__QSPI0_B_DATA1,
+		VF610_PAD_PTD12__QSPI0_B_DATA0,
+	};
+
+	imx_iomux_v3_setup_multiple_pads(qspi0_pads, ARRAY_SIZE(qspi0_pads));
+}
+
+#define ESDHC_PAD_CTRL	(PAD_CTL_PUS_100K_UP | PAD_CTL_SPEED_HIGH | \
+			PAD_CTL_DSE_20ohm | PAD_CTL_OBE_IBE_ENABLE)
+
+struct fsl_esdhc_cfg esdhc_cfg[1] = {
+	{ESDHC1_BASE_ADDR},
+};
+
+int board_mmc_getcd(struct mmc *mmc)
+{
+	/* eSDHC1 is always present */
+	return 1;
+}
+
+int board_mmc_init(bd_t *bis)
+{
+	static const iomux_v3_cfg_t esdhc1_pads[] = {
+		NEW_PAD_CTRL(VF610_PAD_PTA24__ESDHC1_CLK, ESDHC_PAD_CTRL),
+		NEW_PAD_CTRL(VF610_PAD_PTA25__ESDHC1_CMD, ESDHC_PAD_CTRL),
+		NEW_PAD_CTRL(VF610_PAD_PTA26__ESDHC1_DAT0, ESDHC_PAD_CTRL),
+		NEW_PAD_CTRL(VF610_PAD_PTA27__ESDHC1_DAT1, ESDHC_PAD_CTRL),
+		NEW_PAD_CTRL(VF610_PAD_PTA28__ESDHC1_DAT2, ESDHC_PAD_CTRL),
+		NEW_PAD_CTRL(VF610_PAD_PTA29__ESDHC1_DAT3, ESDHC_PAD_CTRL),
+	};
+
+	esdhc_cfg[0].sdhc_clk = mxc_get_clock(MXC_ESDHC_CLK);
+
+	imx_iomux_v3_setup_multiple_pads(
+		esdhc1_pads, ARRAY_SIZE(esdhc1_pads));
+
+	return fsl_esdhc_initialize(bis, &esdhc_cfg[0]);
+}
+
+static void clock_init(void)
+{
+	struct ccm_reg *ccm = (struct ccm_reg *)CCM_BASE_ADDR;
+	struct anadig_reg *anadig = (struct anadig_reg *)ANADIG_BASE_ADDR;
+
+	clrsetbits_le32(&ccm->ccgr0, CCM_REG_CTRL_MASK,
+			CCM_CCGR0_UART1_CTRL_MASK);
+	clrsetbits_le32(&ccm->ccgr1, CCM_REG_CTRL_MASK,
+			CCM_CCGR1_PIT_CTRL_MASK | CCM_CCGR1_WDOGA5_CTRL_MASK);
+	clrsetbits_le32(&ccm->ccgr2, CCM_REG_CTRL_MASK,
+			CCM_CCGR2_IOMUXC_CTRL_MASK | CCM_CCGR2_PORTA_CTRL_MASK |
+			CCM_CCGR2_PORTB_CTRL_MASK | CCM_CCGR2_PORTC_CTRL_MASK |
+			CCM_CCGR2_PORTD_CTRL_MASK | CCM_CCGR2_PORTE_CTRL_MASK |
+			CCM_CCGR2_QSPI0_CTRL_MASK);
+	clrsetbits_le32(&ccm->ccgr3, CCM_REG_CTRL_MASK,
+			CCM_CCGR3_ANADIG_CTRL_MASK | CCM_CCGR3_SCSC_CTRL_MASK);
+	clrsetbits_le32(&ccm->ccgr4, CCM_REG_CTRL_MASK,
+			CCM_CCGR4_WKUP_CTRL_MASK | CCM_CCGR4_CCM_CTRL_MASK |
+			CCM_CCGR4_GPC_CTRL_MASK);
+	clrsetbits_le32(&ccm->ccgr6, CCM_REG_CTRL_MASK,
+			CCM_CCGR6_OCOTP_CTRL_MASK | CCM_CCGR6_DDRMC_CTRL_MASK);
+	clrsetbits_le32(&ccm->ccgr7, CCM_REG_CTRL_MASK,
+			CCM_CCGR7_SDHC1_CTRL_MASK);
+	clrsetbits_le32(&ccm->ccgr9, CCM_REG_CTRL_MASK,
+			CCM_CCGR9_FEC0_CTRL_MASK | CCM_CCGR9_FEC1_CTRL_MASK);
+	clrsetbits_le32(&ccm->ccgr10, CCM_REG_CTRL_MASK,
+			CCM_CCGR10_NFC_CTRL_MASK | CCM_CCGR10_I2C2_CTRL_MASK);
+
+	clrsetbits_le32(&anadig->pll2_ctrl, ANADIG_PLL2_CTRL_POWERDOWN,
+			ANADIG_PLL2_CTRL_ENABLE | ANADIG_PLL2_CTRL_DIV_SELECT);
+	clrsetbits_le32(&anadig->pll1_ctrl, ANADIG_PLL1_CTRL_POWERDOWN,
+			ANADIG_PLL1_CTRL_ENABLE | ANADIG_PLL1_CTRL_DIV_SELECT);
+
+	clrsetbits_le32(&ccm->ccr, CCM_CCR_OSCNT_MASK,
+			CCM_CCR_FIRC_EN | CCM_CCR_OSCNT(5));
+	clrsetbits_le32(&ccm->ccsr, CCM_REG_CTRL_MASK,
+			CCM_CCSR_PLL1_PFD_CLK_SEL(3) | CCM_CCSR_PLL2_PFD4_EN |
+			CCM_CCSR_PLL2_PFD3_EN | CCM_CCSR_PLL2_PFD2_EN |
+			CCM_CCSR_PLL2_PFD1_EN | CCM_CCSR_PLL1_PFD4_EN |
+			CCM_CCSR_PLL1_PFD3_EN | CCM_CCSR_PLL1_PFD2_EN |
+			CCM_CCSR_PLL1_PFD1_EN | CCM_CCSR_DDRC_CLK_SEL(1) |
+			CCM_CCSR_FAST_CLK_SEL(1) | CCM_CCSR_SYS_CLK_SEL(4));
+	clrsetbits_le32(&ccm->cacrr, CCM_REG_CTRL_MASK,
+			CCM_CACRR_IPG_CLK_DIV(1) | CCM_CACRR_BUS_CLK_DIV(2) |
+			CCM_CACRR_ARM_CLK_DIV(0));
+	clrsetbits_le32(&ccm->cscmr1, CCM_REG_CTRL_MASK,
+			CCM_CSCMR1_ESDHC1_CLK_SEL(3) |
+			CCM_CSCMR1_QSPI0_CLK_SEL(3) |
+			CCM_CSCMR1_NFC_CLK_SEL(0));
+	clrsetbits_le32(&ccm->cscdr1, CCM_REG_CTRL_MASK,
+			CCM_CSCDR1_RMII_CLK_EN);
+	clrsetbits_le32(&ccm->cscdr2, CCM_REG_CTRL_MASK,
+			CCM_CSCDR2_ESDHC1_EN | CCM_CSCDR2_ESDHC1_CLK_DIV(0) |
+			CCM_CSCDR2_NFC_EN);
+	clrsetbits_le32(&ccm->cscdr3, CCM_REG_CTRL_MASK,
+			CCM_CSCDR3_QSPI0_EN | CCM_CSCDR3_QSPI0_DIV(1) |
+			CCM_CSCDR3_QSPI0_X2_DIV(1) |
+			CCM_CSCDR3_QSPI0_X4_DIV(3) |
+			CCM_CSCDR3_NFC_PRE_DIV(5));
+	clrsetbits_le32(&ccm->cscmr2, CCM_REG_CTRL_MASK,
+			CCM_CSCMR2_RMII_CLK_SEL(0));
+}
+
+static void mscm_init(void)
+{
+	struct mscm_ir *mscmir = (struct mscm_ir *)MSCM_IR_BASE_ADDR;
+	int i;
+
+	for (i = 0; i < MSCM_IRSPRC_NUM; i++)
+		writew(MSCM_IRSPRC_CP0_EN, &mscmir->irsprc[i]);
+}
+
+int board_phy_config(struct phy_device *phydev)
+{
+	if (phydev->drv->config)
+		phydev->drv->config(phydev);
+
+	return 0;
+}
+
+int board_early_init_f(void)
+{
+	clock_init();
+	mscm_init();
+	setup_iomux_uart();
+	setup_iomux_enet();
+	setup_iomux_i2c();
+	setup_iomux_qspi();
+	setup_iomux_nfc();
+
+	return 0;
+}
+
+int board_init(void)
+{
+	struct scsc_reg *scsc = (struct scsc_reg *)SCSC_BASE_ADDR;
+
+	/* address of boot parameters */
+	gd->bd->bi_boot_params = PHYS_SDRAM + 0x100;
+
+	/*
+	 * Enable external 32K Oscillator
+	 *
+	 * The internal clock experiences significant drift
+	 * so we must use the external oscillator in order
+	 * to maintain correct time in the hwclock
+	 */
+	setbits_le32(&scsc->sosc_ctr, SCSC_SOSC_CTR_SOSC_EN);
+
+	return 0;
+}
+
+int checkboard(void)
+{
+	puts("Board: PCM-052\n");
+
+	return 0;
+}
diff --git a/configs/pcm052_defconfig b/configs/pcm052_defconfig
new file mode 100644
index 0000000..e8dc402
--- /dev/null
+++ b/configs/pcm052_defconfig
@@ -0,0 +1,6 @@
+CONFIG_ARM=y
+CONFIG_TARGET_PCM052=y
+CONFIG_SYS_EXTRA_OPTIONS="IMX_CONFIG=board/phytec/pcm052/imximage.cfg,ENV_IS_IN_NAND"
+CONFIG_NAND_VF610_NFC=y
+CONFIG_SYS_NAND_BUSWIDTH_16BIT=y
+CONFIG_SYS_NAND_VF610_NFC_45_ECC_BYTES=y
diff --git a/include/configs/pcm052.h b/include/configs/pcm052.h
new file mode 100644
index 0000000..4cfce05
--- /dev/null
+++ b/include/configs/pcm052.h
@@ -0,0 +1,234 @@
+/*
+ * Copyright 2013 Freescale Semiconductor, Inc.
+ *
+ * Configuration settings for the phytec PCM-052 SoM.
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#ifndef __CONFIG_H
+#define __CONFIG_H
+
+#include <asm/arch/imx-regs.h>
+#include <config_cmd_default.h>
+
+#define CONFIG_VF610
+
+#define CONFIG_SYS_GENERIC_BOARD
+#define CONFIG_DISPLAY_CPUINFO
+#define CONFIG_DISPLAY_BOARDINFO
+#define CONFIG_SYS_THUMB_BUILD
+
+#define CONFIG_SKIP_LOWLEVEL_INIT
+
+/* Enable passing of ATAGs */
+#define CONFIG_CMDLINE_TAG
+
+/* Size of malloc() pool */
+#define CONFIG_SYS_MALLOC_LEN		(CONFIG_ENV_SIZE + 2 * 1024 * 1024)
+
+#define CONFIG_BOARD_EARLY_INIT_F
+
+#define CONFIG_FSL_LPUART
+#define LPUART_BASE			UART1_BASE
+
+/* Allow to overwrite serial and ethaddr */
+#define CONFIG_ENV_OVERWRITE
+#define CONFIG_SYS_UART_PORT		(1)
+#define CONFIG_BAUDRATE			115200
+
+#undef CONFIG_CMD_IMLS
+
+/* NAND support */
+#define CONFIG_CMD_NAND
+#define CONFIG_CMD_NAND_TRIMFFS
+#define CONFIG_SYS_NAND_ONFI_DETECTION
+
+#ifdef CONFIG_CMD_NAND
+#define CONFIG_USE_ARCH_MEMCPY
+#define CONFIG_SYS_MAX_NAND_DEVICE	1
+#define CONFIG_SYS_NAND_BASE		NFC_BASE_ADDR
+
+#define CONFIG_JFFS2_NAND
+
+/* UBI */
+#define CONFIG_CMD_UBI
+#define CONFIG_CMD_UBIFS
+#define CONFIG_RBTREE
+#define CONFIG_LZO
+
+/* Dynamic MTD partition support */
+#define CONFIG_CMD_MTDPARTS
+#define CONFIG_MTD_PARTITIONS
+#define CONFIG_MTD_DEVICE
+#define MTDIDS_DEFAULT			"nand0=NAND,nor0=qspi0-a,nor1=qspi0-b"
+#define MTDPARTS_DEFAULT		"mtdparts=NAND:256k(spare)"\
+					",384k(bootloader)"\
+					",128k(env1)"\
+					",128k(env2)"\
+					",3840k(kernel)"\
+					",-(rootfs)"\
+					",qspi0-a:-(jffs2),qspio0-b:-(jffs2)"
+#endif
+
+#define CONFIG_MMC
+#define CONFIG_FSL_ESDHC
+#define CONFIG_SYS_FSL_ESDHC_ADDR	0
+#define CONFIG_SYS_FSL_ESDHC_NUM	1
+
+/*#define CONFIG_ESDHC_DETECT_USE_EXTERN_IRQ1*/
+#define CONFIG_SYS_FSL_ERRATUM_ESDHC135
+#define CONFIG_SYS_FSL_ERRATUM_ESDHC111
+#define CONFIG_SYS_FSL_ERRATUM_ESDHC_A001
+
+#define CONFIG_CMD_MMC
+#define CONFIG_GENERIC_MMC
+#define CONFIG_CMD_FAT
+#define CONFIG_DOS_PARTITION
+
+#define CONFIG_CMD_PING
+#define CONFIG_CMD_DHCP
+#define CONFIG_CMD_MII
+#define CONFIG_CMD_NET
+#define CONFIG_FEC_MXC
+#define CONFIG_MII
+#define IMX_FEC_BASE			ENET_BASE_ADDR
+#define CONFIG_FEC_XCV_TYPE		RMII
+#define CONFIG_FEC_MXC_PHYADDR          0
+#define CONFIG_PHYLIB
+#define CONFIG_PHY_MICREL
+
+/* QSPI Configs*/
+#define CONFIG_FSL_QSPI
+
+#ifdef CONFIG_FSL_QSPI
+#define CONFIG_CMD_SF
+#define CONFIG_SPI_FLASH
+#define CONFIG_SPI_FLASH_STMICRO
+#define FSL_QSPI_FLASH_SIZE		(1 << 24)
+#define FSL_QSPI_FLASH_NUM		2
+#define CONFIG_SYS_FSL_QSPI_LE
+#endif
+
+/* I2C Configs */
+#define CONFIG_CMD_I2C
+#define CONFIG_SYS_I2C
+#define CONFIG_SYS_I2C_MXC_I2C3
+#define CONFIG_SYS_I2C_MXC
+#define CONFIG_SYS_SPD_BUS_NUM		0
+
+/* RTC (actually an RV-4162 but M41T62-compatible) */
+#define CONFIG_CMD_DATE
+#define CONFIG_RTC_M41T62
+#define CONFIG_SYS_I2C_RTC_ADDR 0x68
+#define CONFIG_SYS_RTC_BUS_NUM 2
+
+/* EEPROM (24FC256) */
+#define CONFIG_CMD_EEPROM
+#define CONFIG_SYS_I2C_EEPROM_ADDR 0x50
+#define CONFIG_SYS_I2C_EEPROM_ADDR_LEN 2
+#define CONFIG_SYS_I2C_EEPROM_BUS 2
+
+#define CONFIG_BOOTDELAY		3
+
+#define CONFIG_LOADADDR			0x82000000
+
+/* We boot from the gfxRAM area of the OCRAM. */
+#define CONFIG_SYS_TEXT_BASE		0x3f408000
+#define CONFIG_BOARD_SIZE_LIMIT		524288
+
+#define CONFIG_BOOTCOMMAND              "run bootcmd_sd"
+#define CONFIG_EXTRA_ENV_SETTINGS                                       \
+	"bootfile=uImage\0"                             \
+	"bootargs_base=setenv bootargs rw mem=256M "                    \
+		"console=ttymxc1,115200n8\0"            \
+	"bootargs_sd=setenv bootargs ${bootargs} "                      \
+		"root=/dev/mmcblk0p2 rootwait\0"        \
+	"bootargs_net=setenv bootargs ${bootargs} root=/dev/nfs ip=dhcp " \
+		"nfsroot=${serverip}:${nfs_root},v3,tcp\0"              \
+	"bootargs_nand=setenv bootargs ${bootargs} "                    \
+		"root=/dev/mtdblock2 rootfstype=jffs2\0"                \
+	"bootargs_mtd=setenv bootargs ${bootargs} ${mtdparts}\0"        \
+	"bootcmd_sd=run bootargs_base bootargs_sd bootargs_mtd; mmc rescan; " \
+		"fatload mmc 0:1 ${loadaddr} ${bootfile}; bootm ${loadaddr}\0" \
+	"bootcmd_net=run bootargs_base bootargs_net bootargs_mtd; "     \
+		"tftpboot ${loadaddr} ${tftploc}${bootfile}; bootm\0"   \
+	"bootcmd_nand='run bootargs_base bootargs_nand bootargs_mtd; "  \
+		"nand read ${loadaddr} 0x000E0000 0x3C0000; "           \
+		"bootm ${loadaddr}\0"                                   \
+	"tftploc=/path/to/tftp/directory/\0"                            \
+	"nfs_root=/path/to/nfs/root\0"                                  \
+	"mtdparts=" MTDPARTS_DEFAULT "\0"                               \
+	"update_kernel_from_sd=mw.b $(loadaddr) 0xff 0x3C0000; "        \
+		"mmc rescan; fatload mmc 0:2 ${loadaddr} ${bootfile}; " \
+		"nand erase 0xE0000 0x3C0000; "                         \
+		"nand write.i ${loadaddr} 0xE0000 0x3C0000\0"           \
+	"update_rootfs_from_tftp=mw.b ${loadaddr} 0xff 0x8F20000; "     \
+		"tftp ${loadaddr} ${tftp}${filesys}; "                  \
+		"nand erase 0x4A0000 0x8F20000; "                       \
+		"nand write.i ${loadaddr} 0x4A0000 0x8F20000\0"         \
+	"filesys=rootfs.jffs2\0"
+
+/* miscellaneous commands */
+#define CONFIG_CMD_ELF
+
+/* Miscellaneous configurable options */
+#define CONFIG_SYS_LONGHELP		/* undef to save memory */
+#define CONFIG_SYS_HUSH_PARSER		/* use "hush" command parser */
+#define CONFIG_SYS_PROMPT_HUSH_PS2	"> "
+#define CONFIG_AUTO_COMPLETE
+#define CONFIG_CMDLINE_EDITING
+#define CONFIG_SYS_CBSIZE		256	/* Console I/O Buffer Size */
+#define CONFIG_SYS_PBSIZE		\
+			(CONFIG_SYS_CBSIZE + sizeof(CONFIG_SYS_PROMPT) + 16)
+#define CONFIG_SYS_MAXARGS		16	/* max number of command args */
+#define CONFIG_SYS_BARGSIZE		CONFIG_SYS_CBSIZE
+
+#define CONFIG_CMD_MEMTEST
+#define CONFIG_SYS_MEMTEST_START	0x80010000
+#define CONFIG_SYS_MEMTEST_END		0x87C00000
+
+#define CONFIG_SYS_LOAD_ADDR		CONFIG_LOADADDR
+
+/*
+ * Stack sizes
+ * The stack sizes are set up in start.S using the settings below
+ */
+#define CONFIG_STACKSIZE		(128 * 1024)	/* regular stack */
+
+/* Physical memory map */
+#define CONFIG_NR_DRAM_BANKS		1
+#define PHYS_SDRAM			(0x80000000)
+#define PHYS_SDRAM_SIZE			(256 * 1024 * 1024)
+
+#define CONFIG_SYS_SDRAM_BASE		PHYS_SDRAM
+#define CONFIG_SYS_INIT_RAM_ADDR	IRAM_BASE_ADDR
+#define CONFIG_SYS_INIT_RAM_SIZE	IRAM_SIZE
+
+#define CONFIG_SYS_INIT_SP_OFFSET \
+	(CONFIG_SYS_INIT_RAM_SIZE - GENERATED_GBL_DATA_SIZE)
+#define CONFIG_SYS_INIT_SP_ADDR \
+	(CONFIG_SYS_INIT_RAM_ADDR + CONFIG_SYS_INIT_SP_OFFSET)
+
+/* FLASH and environment organization */
+#define CONFIG_SYS_NO_FLASH
+
+#ifdef CONFIG_ENV_IS_IN_MMC
+#define CONFIG_ENV_SIZE			(8 * 1024)
+
+#define CONFIG_ENV_OFFSET		(12 * 64 * 1024)
+#define CONFIG_SYS_MMC_ENV_DEV		0
+#endif
+
+#ifdef CONFIG_ENV_IS_IN_NAND
+#define CONFIG_ENV_SECT_SIZE		(128 * 1024)
+#define CONFIG_ENV_SIZE			(8 * 1024)
+#define CONFIG_ENV_OFFSET		0x80000
+#define CONFIG_ENV_SIZE_REDUND		(8 * 1024)
+#define CONFIG_ENV_OFFSET_REDUND	0xA0000
+#endif
+
+#define CONFIG_OF_LIBFDT
+#define CONFIG_CMD_BOOTZ
+
+#endif
-- 
2.1.0

^ permalink raw reply related	[flat|nested] 24+ messages in thread

* [U-Boot] [PATCH 2/5] vf610: refactor DDRMC code
  2015-06-19 12:18   ` [U-Boot] [PATCH 2/5] vf610: refactor DDRMC code Albert ARIBAUD
  2015-06-19 12:18     ` [U-Boot] [PATCH 3/5] i2c: fix vf610 support Albert ARIBAUD
@ 2015-06-19 15:13     ` Stefan Agner
  2015-06-19 16:50       ` Albert ARIBAUD
  2015-06-19 17:33       ` Albert ARIBAUD
  1 sibling, 2 replies; 24+ messages in thread
From: Stefan Agner @ 2015-06-19 15:13 UTC (permalink / raw)
  To: u-boot

Hi Albert,

On 19.06.2015 14:18, Albert ARIBAUD (3ADEV) wrote:
> The VF610 DDRMC driver code contains settings which are
> board-specific. Move these out to boards so that new boards
> can define their own without having to modify the driver.
>
> Signed-off-by: Albert ARIBAUD (3ADEV) <albert.aribaud@3adev.fr>
> ---
>
>  arch/arm/imx-common/ddrmc-vf610.c             | 239 ++++++--------------------
>  arch/arm/include/asm/arch-vf610/ddrmc-vf610.h |  60 +------
>  board/freescale/vf610twr/vf610twr.c           | 181 +++++++++++++------
>  board/toradex/colibri_vf/colibri_vf.c         | 169 +++++++++++++-----
>  4 files changed, 312 insertions(+), 337 deletions(-)


So this goes basically back to setting all DDR registers directly from
boards? What we tried to do here is to factor out the memory chip
specific data (JEDEC). The idea behind this is it would make it simpler
to add new RAM timings if a new RAM vendor is used on a different board
revision...  With your changes it will be unnecessarily hard to add just
a new RAM timing for a new board revision...

--
Stefan


>
> diff --git a/arch/arm/imx-common/ddrmc-vf610.c b/arch/arm/imx-common/ddrmc-vf610.c
> index e462631..44b9a0f 100644
> --- a/arch/arm/imx-common/ddrmc-vf610.c
> +++ b/arch/arm/imx-common/ddrmc-vf610.c
> @@ -12,9 +12,9 @@
>  #include <asm/arch/iomux-vf610.h>
>  #include <asm/arch/ddrmc-vf610.h>
>  
> -void ddrmc_setup_iomux(void)
> +void ddrmc_setup_iomux(const iomux_v3_cfg_t *pads, int pads_count)
>  {
> -	static const iomux_v3_cfg_t ddr_pads[] = {
> +	static const iomux_v3_cfg_t default_pads[] = {
>  		VF610_PAD_DDR_A15__DDR_A_15,
>  		VF610_PAD_DDR_A14__DDR_A_14,
>  		VF610_PAD_DDR_A13__DDR_A_13,
> @@ -65,212 +65,77 @@ void ddrmc_setup_iomux(void)
>  		VF610_PAD_DDR_RESETB,
>  	};
>  
> -	imx_iomux_v3_setup_multiple_pads(ddr_pads, ARRAY_SIZE(ddr_pads));
> -}
> +	if ((pads == NULL) || (pads_count == 0)) {
> +		pads = default_pads;
> +		pads_count = ARRAY_SIZE(default_pads);
> +	}
>  
> -void ddrmc_phy_init(void)
> -{
> -	struct ddrmr_regs *ddrmr = (struct ddrmr_regs *)DDR_BASE_ADDR;
> +	imx_iomux_v3_setup_multiple_pads(pads, pads_count);
> +}
>  
> -	writel(DDRMC_PHY_DQ_TIMING, &ddrmr->phy[0]);
> -	writel(DDRMC_PHY_DQ_TIMING, &ddrmr->phy[16]);
> -	writel(DDRMC_PHY_DQ_TIMING, &ddrmr->phy[32]);
> +static struct ddrmc_reg_setting default_phy_settings[] = {
> +	{ DDRMC_PHY_DQ_TIMING,  0 },
> +	{ DDRMC_PHY_DQ_TIMING, 16 },
> +	{ DDRMC_PHY_DQ_TIMING, 32 },
>  
> -	writel(DDRMC_PHY_DQS_TIMING, &ddrmr->phy[1]);
> -	writel(DDRMC_PHY_DQS_TIMING, &ddrmr->phy[17]);
> +	{ DDRMC_PHY_DQS_TIMING,  1 },
> +	{ DDRMC_PHY_DQS_TIMING, 17 },
>  
> -	writel(DDRMC_PHY_CTRL, &ddrmr->phy[2]);
> -	writel(DDRMC_PHY_CTRL, &ddrmr->phy[18]);
> -	writel(DDRMC_PHY_CTRL, &ddrmr->phy[34]);
> +	{ DDRMC_PHY_CTRL,  2 },
> +	{ DDRMC_PHY_CTRL, 18 },
> +	{ DDRMC_PHY_CTRL, 34 },
>  
> -	writel(DDRMC_PHY_MASTER_CTRL, &ddrmr->phy[3]);
> -	writel(DDRMC_PHY_MASTER_CTRL, &ddrmr->phy[19]);
> -	writel(DDRMC_PHY_MASTER_CTRL, &ddrmr->phy[35]);
> +	{ DDRMC_PHY_MASTER_CTRL,  3 },
> +	{ DDRMC_PHY_MASTER_CTRL, 19 },
> +	{ DDRMC_PHY_MASTER_CTRL, 35 },
>  
> -	writel(DDRMC_PHY_SLAVE_CTRL, &ddrmr->phy[4]);
> -	writel(DDRMC_PHY_SLAVE_CTRL, &ddrmr->phy[20]);
> -	writel(DDRMC_PHY_SLAVE_CTRL, &ddrmr->phy[36]);
> +	{ DDRMC_PHY_SLAVE_CTRL,  4 },
> +	{ DDRMC_PHY_SLAVE_CTRL, 20 },
> +	{ DDRMC_PHY_SLAVE_CTRL, 36 },
>  
>  	/* LPDDR2 only parameter */
> -	writel(DDRMC_PHY_OFF, &ddrmr->phy[49]);
> +	{ DDRMC_PHY_OFF, 49 },
>  
> -	writel(DDRMC_PHY50_DDR3_MODE |
> -		   DDRMC_PHY50_EN_SW_HALF_CYCLE, &ddrmr->phy[50]);
> +	{ DDRMC_PHY50_DDR3_MODE | DDRMC_PHY50_EN_SW_HALF_CYCLE, 50 },
>  
>  	/* Processor Pad ODT settings */
> -	writel(DDRMC_PHY_PROC_PAD_ODT, &ddrmr->phy[52]);
> -}
> +	{ DDRMC_PHY_PROC_PAD_ODT, 52 },
>  
> -static void ddrmc_ctrl_lvl_init(struct ddrmc_lvl_info *lvl)
> -{
> -	struct ddrmr_regs *ddrmr = (struct ddrmr_regs *)DDR_BASE_ADDR;
> -	u32 cr102 = 0, cr105 = 0, cr106 = 0, cr110 = 0;
> +	/* end marker */
> +	{ 0, -1 }
> +};
>  
> -	if (lvl->wrlvl_reg_en) {
> -		writel(DDRMC_CR97_WRLVL_EN, &ddrmr->cr[97]);
> -		writel(DDRMC_CR98_WRLVL_DL_0(lvl->wrlvl_dl_0), &ddrmr->cr[98]);
> -		writel(DDRMC_CR99_WRLVL_DL_1(lvl->wrlvl_dl_1), &ddrmr->cr[99]);
> -	}
> -
> -	if (lvl->rdlvl_reg_en) {
> -		cr102 |= DDRMC_CR102_RDLVL_REG_EN;
> -		cr105 |= DDRMC_CR105_RDLVL_DL_0(lvl->rdlvl_dl_0);
> -		cr110 |= DDRMC_CR110_RDLVL_DL_1(lvl->rdlvl_dl_1);
> -	}
> -
> -	if (lvl->rdlvl_gt_reg_en) {
> -		cr102 |= DDRMC_CR102_RDLVL_GT_REGEN;
> -		cr106 |= DDRMC_CR106_RDLVL_GTDL_0(lvl->rdlvl_gt_dl_0);
> -		cr110 |= DDRMC_CR110_RDLVL_GTDL_1(lvl->rdlvl_gt_dl_1);
> -	}
> -
> -	writel(cr102, &ddrmr->cr[102]);
> -	writel(cr105, &ddrmr->cr[105]);
> -	writel(cr106, &ddrmr->cr[106]);
> -	writel(cr110, &ddrmr->cr[110]);
> -}
> -
> -void ddrmc_ctrl_init_ddr3(struct ddr3_jedec_timings const *timings,
> -						  struct ddrmc_lvl_info *lvl,
> -						  int col_diff, int row_diff)
> +void ddrmc_ctrl_init_ddr3(struct ddrmc_reg_setting const *cr_settings,
> +	struct ddrmc_reg_setting const *phy_settings)
>  {
>  	struct ddrmr_regs *ddrmr = (struct ddrmr_regs *)DDR_BASE_ADDR;
> +	struct ddrmc_reg_setting const *cr_setting = cr_settings;
> +	struct ddrmc_reg_setting const *phy_setting = phy_settings;
>  
> +	/* configure controller for DDR3 and start init sequence */
>  	writel(DDRMC_CR00_DRAM_CLASS_DDR3, &ddrmr->cr[0]);
> -	writel(DDRMC_CR02_DRAM_TINIT(timings->tinit), &ddrmr->cr[2]);
> -	writel(DDRMC_CR10_TRST_PWRON(timings->trst_pwron), &ddrmr->cr[10]);
> -
> -	writel(DDRMC_CR11_CKE_INACTIVE(timings->cke_inactive), &ddrmr->cr[11]);
> -	writel(DDRMC_CR12_WRLAT(timings->wrlat) |
> -		   DDRMC_CR12_CASLAT_LIN(timings->caslat_lin), &ddrmr->cr[12]);
> -	writel(DDRMC_CR13_TRC(timings->trc) | DDRMC_CR13_TRRD(timings->trrd) |
> -		   DDRMC_CR13_TCCD(timings->tccd), &ddrmr->cr[13]);
> -	writel(DDRMC_CR14_TFAW(timings->tfaw) | DDRMC_CR14_TRP(timings->trp) |
> -		   DDRMC_CR14_TWTR(timings->twtr) |
> -		   DDRMC_CR14_TRAS_MIN(timings->tras_min), &ddrmr->cr[14]);
> -	writel(DDRMC_CR16_TMRD(timings->tmrd) |
> -		   DDRMC_CR16_TRTP(timings->trtp), &ddrmr->cr[16]);
> -	writel(DDRMC_CR17_TRAS_MAX(timings->tras_max) |
> -		   DDRMC_CR17_TMOD(timings->tmod), &ddrmr->cr[17]);
> -	writel(DDRMC_CR18_TCKESR(timings->tckesr) |
> -		   DDRMC_CR18_TCKE(timings->tcke), &ddrmr->cr[18]);
>  
> -	writel(DDRMC_CR20_AP_EN, &ddrmr->cr[20]);
> -	writel(DDRMC_CR21_TRCD_INT(timings->trcd_int) |
> -		   DDRMC_CR21_CCMAP_EN, &ddrmr->cr[21]);
> -
> -	writel(DDRMC_CR22_TDAL(timings->tdal), &ddrmr->cr[22]);
> -	writel(DDRMC_CR23_BSTLEN(3) |
> -		   DDRMC_CR23_TDLL(timings->tdll), &ddrmr->cr[23]);
> -	writel(DDRMC_CR24_TRP_AB(timings->trp_ab), &ddrmr->cr[24]);
> -
> -	writel(DDRMC_CR25_TREF_EN, &ddrmr->cr[25]);
> -	writel(DDRMC_CR26_TREF(timings->tref) |
> -		   DDRMC_CR26_TRFC(timings->trfc), &ddrmr->cr[26]);
> -	writel(DDRMC_CR28_TREF_INT(0), &ddrmr->cr[28]);
> -	writel(DDRMC_CR29_TPDEX(timings->tpdex), &ddrmr->cr[29]);
> -
> -	writel(DDRMC_CR30_TXPDLL(timings->txpdll), &ddrmr->cr[30]);
> -	writel(DDRMC_CR31_TXSNR(timings->txsnr) |
> -		   DDRMC_CR31_TXSR(timings->txsr), &ddrmr->cr[31]);
> -	writel(DDRMC_CR33_EN_QK_SREF, &ddrmr->cr[33]);
> -	writel(DDRMC_CR34_CKSRX(timings->cksrx) |
> -		   DDRMC_CR34_CKSRE(timings->cksre), &ddrmr->cr[34]);
> -
> -	writel(DDRMC_CR38_FREQ_CHG_EN(0), &ddrmr->cr[38]);
> -	writel(DDRMC_CR39_PHY_INI_COM(1024) | DDRMC_CR39_PHY_INI_STA(16) |
> -		   DDRMC_CR39_FRQ_CH_DLLOFF(2), &ddrmr->cr[39]);
> -
> -	writel(DDRMC_CR41_PHY_INI_STRT_INI_DIS, &ddrmr->cr[41]);
> -	writel(DDRMC_CR48_MR1_DA_0(70) |
> -		   DDRMC_CR48_MR0_DA_0(1056), &ddrmr->cr[48]);
> -
> -	writel(DDRMC_CR66_ZQCL(timings->zqcl) |
> -		   DDRMC_CR66_ZQINIT(timings->zqinit), &ddrmr->cr[66]);
> -	writel(DDRMC_CR67_ZQCS(timings->zqcs), &ddrmr->cr[67]);
> -	writel(DDRMC_CR69_ZQ_ON_SREF_EX(2), &ddrmr->cr[69]);
> -
> -	writel(DDRMC_CR70_REF_PER_ZQ(timings->ref_per_zq), &ddrmr->cr[70]);
> -	writel(DDRMC_CR72_ZQCS_ROTATE(0), &ddrmr->cr[72]);
> -
> -	writel(DDRMC_CR73_APREBIT(timings->aprebit) |
> -		   DDRMC_CR73_COL_DIFF(col_diff) |
> -		   DDRMC_CR73_ROW_DIFF(row_diff), &ddrmr->cr[73]);
> -	writel(DDRMC_CR74_BANKSPLT_EN | DDRMC_CR74_ADDR_CMP_EN |
> -		   DDRMC_CR74_CMD_AGE_CNT(64) | DDRMC_CR74_AGE_CNT(64),
> -		   &ddrmr->cr[74]);
> -	writel(DDRMC_CR75_RW_PG_EN | DDRMC_CR75_RW_EN | DDRMC_CR75_PRI_EN |
> -		   DDRMC_CR75_PLEN, &ddrmr->cr[75]);
> -	writel(DDRMC_CR76_NQENT_ACTDIS(3) | DDRMC_CR76_D_RW_G_BKCN(3) |
> -		   DDRMC_CR76_W2R_SPLT_EN, &ddrmr->cr[76]);
> -	writel(DDRMC_CR77_CS_MAP | DDRMC_CR77_DI_RD_INTLEAVE |
> -		   DDRMC_CR77_SWAP_EN, &ddrmr->cr[77]);
> -	writel(DDRMC_CR78_Q_FULLNESS(7) |
> -		   DDRMC_CR78_BUR_ON_FLY_BIT(12), &ddrmr->cr[78]);
> -	writel(DDRMC_CR79_CTLUPD_AREF(0), &ddrmr->cr[79]);
> +	/* execute CR sequence (MUST be supplied) */
> +	if (cr_setting)
> +		while (cr_setting->reg_num >= 0) {
> +			writel(cr_setting->setting,
> +			       &ddrmr->cr[cr_setting->reg_num]);
> +			cr_setting++;
> +		}
> +
> +	/* execute PHY sequence (SHOULD be supplied but can be default) */
> +	if (phy_setting == NULL)
> +		phy_setting = default_phy_settings;
> +
> +	while (phy_setting->reg_num >= 0) {
> +		writel(phy_setting->setting,
> +		       &ddrmr->phy[phy_setting->reg_num]);
> +		phy_setting++;
> +	}
>  
> +	/* final config: disable DDR interrupts and finish init squence */
>  	writel(DDRMC_CR82_INT_MASK, &ddrmr->cr[82]);
>  
> -	writel(DDRMC_CR87_ODT_WR_MAPCS0, &ddrmr->cr[87]);
> -	writel(DDRMC_CR88_TODTL_CMD(4), &ddrmr->cr[88]);
> -	writel(DDRMC_CR89_AODT_RWSMCS(2), &ddrmr->cr[89]);
> -
> -	writel(DDRMC_CR91_R2W_SMCSDL(2), &ddrmr->cr[91]);
> -	writel(DDRMC_CR96_WLMRD(timings->wlmrd) |
> -		   DDRMC_CR96_WLDQSEN(timings->wldqsen), &ddrmr->cr[96]);
> -
> -	if (lvl != NULL)
> -		ddrmc_ctrl_lvl_init(lvl);
> -
> -	writel(DDRMC_CR117_AXI0_W_PRI(0) |
> -		   DDRMC_CR117_AXI0_R_PRI(0), &ddrmr->cr[117]);
> -	writel(DDRMC_CR118_AXI1_W_PRI(1) |
> -		   DDRMC_CR118_AXI1_R_PRI(1), &ddrmr->cr[118]);
> -
> -	writel(DDRMC_CR120_AXI0_PRI1_RPRI(2) |
> -		   DDRMC_CR120_AXI0_PRI0_RPRI(2), &ddrmr->cr[120]);
> -	writel(DDRMC_CR121_AXI0_PRI3_RPRI(2) |
> -		   DDRMC_CR121_AXI0_PRI2_RPRI(2), &ddrmr->cr[121]);
> -	writel(DDRMC_CR122_AXI1_PRI1_RPRI(1) | DDRMC_CR122_AXI1_PRI0_RPRI(1) |
> -		   DDRMC_CR122_AXI0_PRIRLX(100), &ddrmr->cr[122]);
> -	writel(DDRMC_CR123_AXI1_P_ODR_EN | DDRMC_CR123_AXI1_PRI3_RPRI(1) |
> -		   DDRMC_CR123_AXI1_PRI2_RPRI(1), &ddrmr->cr[123]);
> -	writel(DDRMC_CR124_AXI1_PRIRLX(100), &ddrmr->cr[124]);
> -
> -	writel(DDRMC_CR126_PHY_RDLAT(8), &ddrmr->cr[126]);
> -	writel(DDRMC_CR132_WRLAT_ADJ(5) |
> -		   DDRMC_CR132_RDLAT_ADJ(6), &ddrmr->cr[132]);
> -	writel(DDRMC_CR137_PHYCTL_DL(2), &ddrmr->cr[137]);
> -	writel(DDRMC_CR138_PHY_WRLV_MXDL(256) |
> -		   DDRMC_CR138_PHYDRAM_CK_EN(1), &ddrmr->cr[138]);
> -	writel(DDRMC_CR139_PHY_WRLV_RESPLAT(4) | DDRMC_CR139_PHY_WRLV_LOAD(7) |
> -		   DDRMC_CR139_PHY_WRLV_DLL(3) |
> -		   DDRMC_CR139_PHY_WRLV_EN(3), &ddrmr->cr[139]);
> -	writel(DDRMC_CR140_PHY_WRLV_WW(64), &ddrmr->cr[140]);
> -	writel(DDRMC_CR143_RDLV_GAT_MXDL(1536) |
> -		   DDRMC_CR143_RDLV_MXDL(128), &ddrmr->cr[143]);
> -	writel(DDRMC_CR144_PHY_RDLVL_RES(4) | DDRMC_CR144_PHY_RDLV_LOAD(7) |
> -		   DDRMC_CR144_PHY_RDLV_DLL(3) |
> -		   DDRMC_CR144_PHY_RDLV_EN(3), &ddrmr->cr[144]);
> -	writel(DDRMC_CR145_PHY_RDLV_RR(64), &ddrmr->cr[145]);
> -	writel(DDRMC_CR146_PHY_RDLVL_RESP(64), &ddrmr->cr[146]);
> -	writel(DDRMC_CR147_RDLV_RESP_MASK(983040), &ddrmr->cr[147]);
> -	writel(DDRMC_CR148_RDLV_GATE_RESP_MASK(983040), &ddrmr->cr[148]);
> -	writel(DDRMC_CR151_RDLV_GAT_DQ_ZERO_CNT(1) |
> -		   DDRMC_CR151_RDLVL_DQ_ZERO_CNT(1), &ddrmr->cr[151]);
> -
> -	writel(DDRMC_CR154_PAD_ZQ_EARLY_CMP_EN_TIMER(13) |
> -		   DDRMC_CR154_PAD_ZQ_MODE(1) |
> -		   DDRMC_CR154_DDR_SEL_PAD_CONTR(3) |
> -		   DDRMC_CR154_PAD_ZQ_HW_FOR(1), &ddrmr->cr[154]);
> -	writel(DDRMC_CR155_PAD_ODT_BYTE1(2) |
> -		   DDRMC_CR155_PAD_ODT_BYTE0(2), &ddrmr->cr[155]);
> -	writel(DDRMC_CR158_TWR(6), &ddrmr->cr[158]);
> -	writel(DDRMC_CR161_ODT_EN(1) | DDRMC_CR161_TODTH_RD(2) |
> -		   DDRMC_CR161_TODTH_WR(2), &ddrmr->cr[161]);
> -
> -	ddrmc_phy_init();
> -
>  	writel(DDRMC_CR00_DRAM_CLASS_DDR3 | DDRMC_CR00_START, &ddrmr->cr[0]);
>  
>  	while (!(readl(&ddrmr->cr[80]) && 0x100))
> diff --git a/arch/arm/include/asm/arch-vf610/ddrmc-vf610.h b/arch/arm/include/asm/arch-vf610/ddrmc-vf610.h
> index 6730cde..bc7f106 100644
> --- a/arch/arm/include/asm/arch-vf610/ddrmc-vf610.h
> +++ b/arch/arm/include/asm/arch-vf610/ddrmc-vf610.h
> @@ -11,62 +11,14 @@
>  #ifndef __ASM_ARCH_VF610_DDRMC_H
>  #define __ASM_ARCH_VF610_DDRMC_H
>  
> -struct ddrmc_lvl_info {
> -	u16 wrlvl_reg_en;
> -	u16 wrlvl_dl_0;
> -	u16 wrlvl_dl_1;
> -	u16 rdlvl_gt_reg_en;
> -	u16 rdlvl_gt_dl_0;
> -	u16 rdlvl_gt_dl_1;
> -	u16 rdlvl_reg_en;
> -	u16 rdlvl_dl_0;
> -	u16 rdlvl_dl_1;
> +struct ddrmc_reg_setting {
> +	u32	setting;
> +	int	reg_num; /* CR or PHY ; -1 for last entry */
>  };
>  
> -struct ddr3_jedec_timings {
> -	u8 tinit;
> -	u32 trst_pwron;
> -	u32 cke_inactive;
> -	u8 wrlat;
> -	u8 caslat_lin;
> -	u8 trc;
> -	u8 trrd;
> -	u8 tccd;
> -	u8 tfaw;
> -	u8 trp;
> -	u8 twtr;
> -	u8 tras_min;
> -	u8 tmrd;
> -	u8 trtp;
> -	u32 tras_max;
> -	u8 tmod;
> -	u8 tckesr;
> -	u8 tcke;
> -	u8 trcd_int;
> -	u8 tdal;
> -	u16 tdll;
> -	u8 trp_ab;
> -	u16 tref;
> -	u8 trfc;
> -	u8 tpdex;
> -	u8 txpdll;
> -	u8 txsnr;
> -	u16 txsr;
> -	u8 cksrx;
> -	u8 cksre;
> -	u16 zqcl;
> -	u16 zqinit;
> -	u8 zqcs;
> -	u8 ref_per_zq;
> -	u8 aprebit;
> -	u8 wlmrd;
> -	u8 wldqsen;
> -};
> -
> -void ddrmc_setup_iomux(void);
> +void ddrmc_setup_iomux(const iomux_v3_cfg_t *pads, int pads_count);
>  void ddrmc_phy_init(void);
> -void ddrmc_ctrl_init_ddr3(struct ddr3_jedec_timings const *timings,
> -						  struct ddrmc_lvl_info *lvl,
> -						  int col_diff, int row_diff);
> +void ddrmc_ctrl_init_ddr3(struct ddrmc_reg_setting const *cr_settings,
> +	struct ddrmc_reg_setting const *phy_settings);
>  
>  #endif
> diff --git a/board/freescale/vf610twr/vf610twr.c b/board/freescale/vf610twr/vf610twr.c
> index 4160acd..aab20ad 100644
> --- a/board/freescale/vf610twr/vf610twr.c
> +++ b/board/freescale/vf610twr/vf610twr.c
> @@ -28,63 +28,136 @@ DECLARE_GLOBAL_DATA_PTR;
>  #define ENET_PAD_CTRL	(PAD_CTL_PUS_47K_UP | PAD_CTL_SPEED_HIGH | \
>  			PAD_CTL_DSE_50ohm | PAD_CTL_OBE_IBE_ENABLE)
>  
> +static struct ddrmc_reg_setting vf610twr_cr_settings[] = {
> +	{ DDRMC_CR02_DRAM_TINIT(5), 2 },
> +	{ DDRMC_CR10_TRST_PWRON(80000), 10 },
> +	{ DDRMC_CR11_CKE_INACTIVE(200000), 11 },
> +	{ DDRMC_CR12_WRLAT(5) | DDRMC_CR12_CASLAT_LIN(12), 12 },
> +	{ DDRMC_CR13_TRC(21) | DDRMC_CR13_TRRD(4) | DDRMC_CR13_TCCD(4) |
> +		   DDRMC_CR13_TBST_INT_INTERVAL(0), 13 },
> +	{ DDRMC_CR14_TFAW(20) | DDRMC_CR14_TRP(6) | DDRMC_CR14_TWTR(5) |
> +		   DDRMC_CR14_TRAS_MIN(15), 14 },
> +	{ DDRMC_CR16_TMRD(4) | DDRMC_CR16_TRTP(4), 16 },
> +	{ DDRMC_CR17_TRAS_MAX(28080) | DDRMC_CR17_TMOD(12), 17 },
> +	{ DDRMC_CR18_TCKESR(4) | DDRMC_CR18_TCKE(3), 18 },
> +
> +	{ DDRMC_CR20_AP_EN, 20 },
> +	{ DDRMC_CR21_TRCD_INT(6) | DDRMC_CR21_CCMAP_EN, 21 },
> +
> +	{ DDRMC_CR22_TDAL(12), 22 },
> +	{ DDRMC_CR23_BSTLEN(3) |
> +		   DDRMC_CR23_TDLL(512), 23 },
> +	{ DDRMC_CR24_TRP_AB(6), 24 },
> +
> +	{ DDRMC_CR25_TREF_EN, 25 },
> +	{ DDRMC_CR26_TREF(3120) | DDRMC_CR26_TRFC(44), 26 },
> +	{ DDRMC_CR28_TREF_INT(0), 28 },
> +	{ DDRMC_CR29_TPDEX(3), 29 },
> +
> +	{ DDRMC_CR30_TXPDLL(10), 30 },
> +	{ DDRMC_CR31_TXSNR(48) | DDRMC_CR31_TXSR(468), 31 },
> +	{ DDRMC_CR33_EN_QK_SREF, 33 },
> +	{ DDRMC_CR34_CKSRX(5) | DDRMC_CR34_CKSRE(5), 34 },
> +
> +	{ DDRMC_CR38_FREQ_CHG_EN(0), 38 },
> +	{ DDRMC_CR39_PHY_INI_COM(1024) | DDRMC_CR39_PHY_INI_STA(16) |
> +		   DDRMC_CR39_FRQ_CH_DLLOFF(2), 39 },
> +
> +	{ DDRMC_CR41_PHY_INI_STRT_INI_DIS, 41 },
> +	{ DDRMC_CR48_MR1_DA_0(70) |
> +		   DDRMC_CR48_MR0_DA_0(1056), 48 },
> +
> +	{ DDRMC_CR66_ZQCL(256) | DDRMC_CR66_ZQINIT(512), 66 },
> +	{ DDRMC_CR67_ZQCS(64), 67 },
> +	{ DDRMC_CR69_ZQ_ON_SREF_EX(2), 69 },
> +
> +	{ DDRMC_CR70_REF_PER_ZQ(64), 70 },
> +	{ DDRMC_CR72_ZQCS_ROTATE(0), 72 },
> +
> +	{ DDRMC_CR73_APREBIT(10) | DDRMC_CR73_COL_DIFF(1) |
> +		   DDRMC_CR73_ROW_DIFF(3), 73 },
> +	{ DDRMC_CR74_BANKSPLT_EN | DDRMC_CR74_ADDR_CMP_EN |
> +		   DDRMC_CR74_CMD_AGE_CNT(64) |
> +		   DDRMC_CR74_AGE_CNT(64), 74 },
> +	{ DDRMC_CR75_RW_PG_EN | DDRMC_CR75_RW_EN | DDRMC_CR75_PRI_EN |
> +		   DDRMC_CR75_PLEN, 75 },
> +	{ DDRMC_CR76_NQENT_ACTDIS(3) | DDRMC_CR76_D_RW_G_BKCN(3) |
> +		   DDRMC_CR76_W2R_SPLT_EN, 76 },
> +	{ DDRMC_CR77_CS_MAP | DDRMC_CR77_DI_RD_INTLEAVE |
> +		   DDRMC_CR77_SWAP_EN, 77 },
> +	{ DDRMC_CR78_Q_FULLNESS(7) | DDRMC_CR78_BUR_ON_FLY_BIT(12), 78 },
> +	{ DDRMC_CR79_CTLUPD_AREF(0), 79 },
> +
> +	{ DDRMC_CR87_ODT_WR_MAPCS0, 87 },
> +	{ DDRMC_CR88_TODTL_CMD(4), 88 },
> +	{ DDRMC_CR89_AODT_RWSMCS(2), 89 },
> +
> +	{ DDRMC_CR91_R2W_SMCSDL(2), 91 },
> +	{ DDRMC_CR96_WLMRD(40) | DDRMC_CR96_WLDQSEN(25), 96 },
> +
> +	/* levelling */
> +	{ DDRMC_CR97_WRLVL_EN, 97 },
> +	{ DDRMC_CR98_WRLVL_DL_0(0), 98 },
> +	{ DDRMC_CR99_WRLVL_DL_1(0), 99 },
> +	{ DDRMC_CR102_RDLVL_REG_EN | DDRMC_CR102_RDLVL_GT_REGEN, 102 },
> +	{ DDRMC_CR105_RDLVL_DL_0(0), 105 },
> +	{ DDRMC_CR106_RDLVL_GTDL_0(4), 106 },
> +	{ DDRMC_CR110_RDLVL_DL_1(0) | DDRMC_CR110_RDLVL_GTDL_1(4), 110 },
> +
> +	/* AXI */
> +	{ DDRMC_CR117_AXI0_W_PRI(0) | DDRMC_CR117_AXI0_R_PRI(0), 117 },
> +	{ DDRMC_CR118_AXI1_W_PRI(1) | DDRMC_CR118_AXI1_R_PRI(1), 118 },
> +	{ DDRMC_CR120_AXI0_PRI1_RPRI(2) |
> +		   DDRMC_CR120_AXI0_PRI0_RPRI(2), 120 },
> +	{ DDRMC_CR121_AXI0_PRI3_RPRI(2) |
> +		   DDRMC_CR121_AXI0_PRI2_RPRI(2), 121 },
> +	{ DDRMC_CR122_AXI1_PRI1_RPRI(1) | DDRMC_CR122_AXI1_PRI0_RPRI(1) |
> +		   DDRMC_CR122_AXI0_PRIRLX(100), 122 },
> +	{ DDRMC_CR123_AXI1_P_ODR_EN | DDRMC_CR123_AXI1_PRI3_RPRI(1) |
> +		   DDRMC_CR123_AXI1_PRI2_RPRI(1), 123 },
> +	{ DDRMC_CR124_AXI1_PRIRLX(100), 124 },
> +	{ DDRMC_CR126_PHY_RDLAT(8), 126 },
> +	{ DDRMC_CR132_WRLAT_ADJ(5) |
> +		   DDRMC_CR132_RDLAT_ADJ(6), 132 },
> +	{ DDRMC_CR137_PHYCTL_DL(2), 137 },
> +	{ DDRMC_CR138_PHY_WRLV_MXDL(256) |
> +		   DDRMC_CR138_PHYDRAM_CK_EN(1), 138 },
> +	{ DDRMC_CR139_PHY_WRLV_RESPLAT(4) | DDRMC_CR139_PHY_WRLV_LOAD(7) |
> +		   DDRMC_CR139_PHY_WRLV_DLL(3) |
> +		   DDRMC_CR139_PHY_WRLV_EN(3), 139 },
> +	{ DDRMC_CR140_PHY_WRLV_WW(64), 140 },
> +	{ DDRMC_CR143_RDLV_GAT_MXDL(1536) |
> +		   DDRMC_CR143_RDLV_MXDL(128), 143 },
> +	{ DDRMC_CR144_PHY_RDLVL_RES(4) | DDRMC_CR144_PHY_RDLV_LOAD(7) |
> +		   DDRMC_CR144_PHY_RDLV_DLL(3) |
> +		   DDRMC_CR144_PHY_RDLV_EN(3), 144 },
> +	{ DDRMC_CR145_PHY_RDLV_RR(64), 145 },
> +	{ DDRMC_CR146_PHY_RDLVL_RESP(64), 146 },
> +	{ DDRMC_CR147_RDLV_RESP_MASK(983040), 147 },
> +	{ DDRMC_CR148_RDLV_GATE_RESP_MASK(983040), 148 },
> +	{ DDRMC_CR151_RDLV_GAT_DQ_ZERO_CNT(1) |
> +		   DDRMC_CR151_RDLVL_DQ_ZERO_CNT(1), 151 },
> +
> +	{ DDRMC_CR154_PAD_ZQ_EARLY_CMP_EN_TIMER(13) |
> +		   DDRMC_CR154_PAD_ZQ_MODE(1) |
> +		   DDRMC_CR154_DDR_SEL_PAD_CONTR(3) |
> +		   DDRMC_CR154_PAD_ZQ_HW_FOR(1), 154 },
> +	{ DDRMC_CR155_PAD_ODT_BYTE1(1) | DDRMC_CR155_PAD_ODT_BYTE0(1), 155 },
> +	{ DDRMC_CR158_TWR(6), 158 },
> +	{ DDRMC_CR161_ODT_EN(1) | DDRMC_CR161_TODTH_RD(2) |
> +		   DDRMC_CR161_TODTH_WR(2), 161 },
> +
> +	/* end marker */
> +	{ 0, -1 }
> +}
> +
>  int dram_init(void)
>  {
> -	struct ddrmc_lvl_info lvl = {
> -		.wrlvl_reg_en = 1,
> -		.wrlvl_dl_0 = 0,
> -		.wrlvl_dl_1 = 0,
> -		.rdlvl_gt_reg_en = 1,
> -		.rdlvl_gt_dl_0 = 4,
> -		.rdlvl_gt_dl_1 = 4,
> -		.rdlvl_reg_en = 1,
> -		.rdlvl_dl_0 = 0,
> -		.rdlvl_dl_1 = 0,
> -	};
> -
> -	static const struct ddr3_jedec_timings timings = {
> -		.tinit           = 5,
> -		.trst_pwron      = 80000,
> -		.cke_inactive    = 200000,
> -		.wrlat           = 5,
> -		.caslat_lin      = 12,
> -		.trc             = 21,
> -		.trrd            = 4,
> -		.tccd            = 4,
> -		.tfaw            = 20,
> -		.trp             = 6,
> -		.twtr            = 4,
> -		.tras_min        = 15,
> -		.tmrd            = 4,
> -		.trtp            = 4,
> -		.tras_max        = 28080,
> -		.tmod            = 12,
> -		.tckesr          = 4,
> -		.tcke            = 3,
> -		.trcd_int        = 6,
> -		.tdal            = 12,
> -		.tdll            = 512,
> -		.trp_ab          = 6,
> -		.tref            = 3120,
> -		.trfc            = 44,
> -		.tpdex           = 3,
> -		.txpdll          = 10,
> -		.txsnr           = 48,
> -		.txsr            = 468,
> -		.cksrx           = 5,
> -		.cksre           = 5,
> -		.zqcl            = 256,
> -		.zqinit          = 512,
> -		.zqcs            = 64,
> -		.ref_per_zq      = 64,
> -		.aprebit         = 10,
> -		.wlmrd           = 40,
> -		.wldqsen         = 25,
> -	};
> -
> -	ddrmc_setup_iomux();
> +	/* use driver default IOMUX settings */
> +	ddrmc_setup_iomux(NULL, 0);
>  
> -	ddrmc_ctrl_init_ddr3(&timings, &lvl, 1, 3);
> +	/* provide own CR setup but use default PHY setup */
> +	ddrmc_ctrl_init_ddr3(vf610twr_cr_settings, NULL);
>  	gd->ram_size = get_ram_size((void *)PHYS_SDRAM, PHYS_SDRAM_SIZE);
>  
>  	return 0;
> diff --git a/board/toradex/colibri_vf/colibri_vf.c b/board/toradex/colibri_vf/colibri_vf.c
> index 8618fd0..01b3106 100644
> --- a/board/toradex/colibri_vf/colibri_vf.c
> +++ b/board/toradex/colibri_vf/colibri_vf.c
> @@ -39,51 +39,136 @@ static const iomux_v3_cfg_t usb_pads[] = {
>  	VF610_PAD_PTD4__GPIO_83,
>  };
>  
> +static struct ddrmc_reg_setting colibri_vf_cr_settings[] = {
> +	{ DDRMC_CR02_DRAM_TINIT(5), 2 },
> +	{ DDRMC_CR10_TRST_PWRON(80000), 10 },
> +	{ DDRMC_CR11_CKE_INACTIVE(200000), 11 },
> +	{ DDRMC_CR12_WRLAT(5) | DDRMC_CR12_CASLAT_LIN(12), 12 },
> +	{ DDRMC_CR13_TRC(21) | DDRMC_CR13_TRRD(4) | DDRMC_CR13_TCCD(4) |
> +		   DDRMC_CR13_TBST_INT_INTERVAL(0), 13 },
> +	{ DDRMC_CR14_TFAW(20) | DDRMC_CR14_TRP(6) | DDRMC_CR14_TWTR(5) |
> +		   DDRMC_CR14_TRAS_MIN(15), 14 },
> +	{ DDRMC_CR16_TMRD(4) | DDRMC_CR16_TRTP(4), 16 },
> +	{ DDRMC_CR17_TRAS_MAX(28080) | DDRMC_CR17_TMOD(12), 17 },
> +	{ DDRMC_CR18_TCKESR(4) | DDRMC_CR18_TCKE(3), 18 },
> +
> +	{ DDRMC_CR20_AP_EN, 20 },
> +	{ DDRMC_CR21_TRCD_INT(6) | DDRMC_CR21_CCMAP_EN, 21 },
> +
> +	{ DDRMC_CR22_TDAL(12), 22 },
> +	{ DDRMC_CR23_BSTLEN(3) |
> +		   DDRMC_CR23_TDLL(512), 23 },
> +	{ DDRMC_CR24_TRP_AB(6), 24 },
> +
> +	{ DDRMC_CR25_TREF_EN, 25 },
> +	{ DDRMC_CR26_TREF(3120) | DDRMC_CR26_TRFC(44), 26 },
> +	{ DDRMC_CR28_TREF_INT(0), 28 },
> +	{ DDRMC_CR29_TPDEX(3), 29 },
> +
> +	{ DDRMC_CR30_TXPDLL(10), 30 },
> +	{ DDRMC_CR31_TXSNR(48) | DDRMC_CR31_TXSR(468), 31 },
> +	{ DDRMC_CR33_EN_QK_SREF, 33 },
> +	{ DDRMC_CR34_CKSRX(5) | DDRMC_CR34_CKSRE(5), 34 },
> +
> +	{ DDRMC_CR38_FREQ_CHG_EN(0), 38 },
> +	{ DDRMC_CR39_PHY_INI_COM(1024) | DDRMC_CR39_PHY_INI_STA(16) |
> +		   DDRMC_CR39_FRQ_CH_DLLOFF(2), 39 },
> +
> +	{ DDRMC_CR41_PHY_INI_STRT_INI_DIS, 41 },
> +	{ DDRMC_CR48_MR1_DA_0(70) |
> +		   DDRMC_CR48_MR0_DA_0(1056), 48 },
> +
> +	{ DDRMC_CR66_ZQCL(256) | DDRMC_CR66_ZQINIT(512), 66 },
> +	{ DDRMC_CR67_ZQCS(64), 67 },
> +	{ DDRMC_CR69_ZQ_ON_SREF_EX(2), 69 },
> +
> +	{ DDRMC_CR70_REF_PER_ZQ(64), 70 },
> +	{ DDRMC_CR72_ZQCS_ROTATE(0), 72 },
> +
> +	{ DDRMC_CR73_APREBIT(10) | DDRMC_CR73_COL_DIFF(1) |
> +		   DDRMC_CR73_ROW_DIFF(3), 73 },
> +	{ DDRMC_CR74_BANKSPLT_EN | DDRMC_CR74_ADDR_CMP_EN |
> +		   DDRMC_CR74_CMD_AGE_CNT(64) |
> +		   DDRMC_CR74_AGE_CNT(64), 74 },
> +	{ DDRMC_CR75_RW_PG_EN | DDRMC_CR75_RW_EN | DDRMC_CR75_PRI_EN |
> +		   DDRMC_CR75_PLEN, 75 },
> +	{ DDRMC_CR76_NQENT_ACTDIS(3) | DDRMC_CR76_D_RW_G_BKCN(3) |
> +		   DDRMC_CR76_W2R_SPLT_EN, 76 },
> +	{ DDRMC_CR77_CS_MAP | DDRMC_CR77_DI_RD_INTLEAVE |
> +		   DDRMC_CR77_SWAP_EN, 77 },
> +	{ DDRMC_CR78_Q_FULLNESS(7) | DDRMC_CR78_BUR_ON_FLY_BIT(12), 78 },
> +	{ DDRMC_CR79_CTLUPD_AREF(0), 79 },
> +
> +	{ DDRMC_CR87_ODT_WR_MAPCS0, 87 },
> +	{ DDRMC_CR88_TODTL_CMD(4), 88 },
> +	{ DDRMC_CR89_AODT_RWSMCS(2), 89 },
> +
> +	{ DDRMC_CR91_R2W_SMCSDL(2), 91 },
> +	{ DDRMC_CR96_WLMRD(40) | DDRMC_CR96_WLDQSEN(25), 96 },
> +
> +	/* levelling */
> +	{ DDRMC_CR97_WRLVL_EN, 97 },
> +	{ DDRMC_CR98_WRLVL_DL_0(0), 98 },
> +	{ DDRMC_CR99_WRLVL_DL_1(0), 99 },
> +	{ DDRMC_CR102_RDLVL_REG_EN | DDRMC_CR102_RDLVL_GT_REGEN, 102 },
> +	{ DDRMC_CR105_RDLVL_DL_0(0), 105 },
> +	{ DDRMC_CR106_RDLVL_GTDL_0(4), 106 },
> +	{ DDRMC_CR110_RDLVL_DL_1(0) | DDRMC_CR110_RDLVL_GTDL_1(4), 110 },
> +
> +	/* AXI */
> +	{ DDRMC_CR117_AXI0_W_PRI(0) | DDRMC_CR117_AXI0_R_PRI(0), 117 },
> +	{ DDRMC_CR118_AXI1_W_PRI(1) | DDRMC_CR118_AXI1_R_PRI(1), 118 },
> +	{ DDRMC_CR120_AXI0_PRI1_RPRI(2) |
> +		   DDRMC_CR120_AXI0_PRI0_RPRI(2), 120 },
> +	{ DDRMC_CR121_AXI0_PRI3_RPRI(2) |
> +		   DDRMC_CR121_AXI0_PRI2_RPRI(2), 121 },
> +	{ DDRMC_CR122_AXI1_PRI1_RPRI(1) | DDRMC_CR122_AXI1_PRI0_RPRI(1) |
> +		   DDRMC_CR122_AXI0_PRIRLX(100), 122 },
> +	{ DDRMC_CR123_AXI1_P_ODR_EN | DDRMC_CR123_AXI1_PRI3_RPRI(1) |
> +		   DDRMC_CR123_AXI1_PRI2_RPRI(1), 123 },
> +	{ DDRMC_CR124_AXI1_PRIRLX(100), 124 },
> +	{ DDRMC_CR126_PHY_RDLAT(8), 126 },
> +	{ DDRMC_CR132_WRLAT_ADJ(5) |
> +		   DDRMC_CR132_RDLAT_ADJ(6), 132 },
> +	{ DDRMC_CR137_PHYCTL_DL(2), 137 },
> +	{ DDRMC_CR138_PHY_WRLV_MXDL(256) |
> +		   DDRMC_CR138_PHYDRAM_CK_EN(1), 138 },
> +	{ DDRMC_CR139_PHY_WRLV_RESPLAT(4) | DDRMC_CR139_PHY_WRLV_LOAD(7) |
> +		   DDRMC_CR139_PHY_WRLV_DLL(3) |
> +		   DDRMC_CR139_PHY_WRLV_EN(3), 139 },
> +	{ DDRMC_CR140_PHY_WRLV_WW(64), 140 },
> +	{ DDRMC_CR143_RDLV_GAT_MXDL(1536) |
> +		   DDRMC_CR143_RDLV_MXDL(128), 143 },
> +	{ DDRMC_CR144_PHY_RDLVL_RES(4) | DDRMC_CR144_PHY_RDLV_LOAD(7) |
> +		   DDRMC_CR144_PHY_RDLV_DLL(3) |
> +		   DDRMC_CR144_PHY_RDLV_EN(3), 144 },
> +	{ DDRMC_CR145_PHY_RDLV_RR(64), 145 },
> +	{ DDRMC_CR146_PHY_RDLVL_RESP(64), 146 },
> +	{ DDRMC_CR147_RDLV_RESP_MASK(983040), 147 },
> +	{ DDRMC_CR148_RDLV_GATE_RESP_MASK(983040), 148 },
> +	{ DDRMC_CR151_RDLV_GAT_DQ_ZERO_CNT(1) |
> +		   DDRMC_CR151_RDLVL_DQ_ZERO_CNT(1), 151 },
> +
> +	{ DDRMC_CR154_PAD_ZQ_EARLY_CMP_EN_TIMER(13) |
> +		   DDRMC_CR154_PAD_ZQ_MODE(1) |
> +		   DDRMC_CR154_DDR_SEL_PAD_CONTR(3) |
> +		   DDRMC_CR154_PAD_ZQ_HW_FOR(1), 154 },
> +	{ DDRMC_CR155_PAD_ODT_BYTE1(1) | DDRMC_CR155_PAD_ODT_BYTE0(1), 155 },
> +	{ DDRMC_CR158_TWR(6), 158 },
> +	{ DDRMC_CR161_ODT_EN(1) | DDRMC_CR161_TODTH_RD(2) |
> +		   DDRMC_CR161_TODTH_WR(2), 161 },
> +
> +	/* end marker */
> +	{ 0, -1 }
> +}
> +
>  int dram_init(void)
>  {
> -	static const struct ddr3_jedec_timings timings = {
> -		.tinit           = 5,
> -		.trst_pwron      = 80000,
> -		.cke_inactive    = 200000,
> -		.wrlat           = 5,
> -		.caslat_lin      = 12,
> -		.trc             = 21,
> -		.trrd            = 4,
> -		.tccd            = 4,
> -		.tfaw            = 20,
> -		.trp             = 6,
> -		.twtr            = 4,
> -		.tras_min        = 15,
> -		.tmrd            = 4,
> -		.trtp            = 4,
> -		.tras_max        = 28080,
> -		.tmod            = 12,
> -		.tckesr          = 4,
> -		.tcke            = 3,
> -		.trcd_int        = 6,
> -		.tdal            = 12,
> -		.tdll            = 512,
> -		.trp_ab          = 6,
> -		.tref            = 3120,
> -		.trfc            = 64,
> -		.tpdex           = 3,
> -		.txpdll          = 10,
> -		.txsnr           = 48,
> -		.txsr            = 468,
> -		.cksrx           = 5,
> -		.cksre           = 5,
> -		.zqcl            = 256,
> -		.zqinit          = 512,
> -		.zqcs            = 64,
> -		.ref_per_zq      = 64,
> -		.aprebit         = 10,
> -		.wlmrd           = 40,
> -		.wldqsen         = 25,
> -	};
> -
> -	ddrmc_setup_iomux();
> +	/* use driver default IOMUX settings */
> +	ddrmc_setup_iomux(NULL, 0);
>  
> -	ddrmc_ctrl_init_ddr3(&timings, NULL, 1, 2);
> +	/* provide own CR setup but use default PHY setup */
> +	ddrmc_ctrl_init_ddr3(&colibri_vf_cr_settings, NULL, 1, 2);
>  	gd->ram_size = get_ram_size((void *)PHYS_SDRAM, PHYS_SDRAM_SIZE);
>  
>  	return 0;

^ permalink raw reply	[flat|nested] 24+ messages in thread

* [U-Boot] [PATCH 1/5] net: fec_mxc: remove useless struct nbuf
  2015-06-19 12:18 ` [U-Boot] [PATCH 1/5] net: fec_mxc: remove useless struct nbuf Albert ARIBAUD
  2015-06-19 12:18   ` [U-Boot] [PATCH 2/5] vf610: refactor DDRMC code Albert ARIBAUD
@ 2015-06-19 15:38   ` Joe Hershberger
  2015-07-10  8:03   ` Stefano Babic
  2 siblings, 0 replies; 24+ messages in thread
From: Joe Hershberger @ 2015-06-19 15:38 UTC (permalink / raw)
  To: u-boot

Hi Albert,

On Fri, Jun 19, 2015 at 7:18 AM, Albert ARIBAUD (3ADEV)
<albert.aribaud@3adev.fr> wrote:
> This locally defined struct is actually only used once
> and as an opaque type. Remove it for clarity.
>
> Signed-off-by: Albert ARIBAUD (3ADEV) <albert.aribaud@3adev.fr>
> ---
Acked-by: Joe Hershberger <joe.hershberger@ni.com>

^ permalink raw reply	[flat|nested] 24+ messages in thread

* [U-Boot] [PATCH 2/5] vf610: refactor DDRMC code
  2015-06-19 15:13     ` [U-Boot] [PATCH 2/5] vf610: refactor DDRMC code Stefan Agner
@ 2015-06-19 16:50       ` Albert ARIBAUD
  2015-06-19 17:33       ` Albert ARIBAUD
  1 sibling, 0 replies; 24+ messages in thread
From: Albert ARIBAUD @ 2015-06-19 16:50 UTC (permalink / raw)
  To: u-boot

Bonjour Stefan,

Le Fri, 19 Jun 2015 17:13:12 +0200, Stefan Agner
<stefan.agner@toradex.com> a ?crit :

> Hi Albert,
> 
> On 19.06.2015 14:18, Albert ARIBAUD (3ADEV) wrote:
> > The VF610 DDRMC driver code contains settings which are
> > board-specific. Move these out to boards so that new boards
> > can define their own without having to modify the driver.
> >
> > Signed-off-by: Albert ARIBAUD (3ADEV) <albert.aribaud@3adev.fr>
> > ---
> >
> >  arch/arm/imx-common/ddrmc-vf610.c             | 239 ++++++--------------------
> >  arch/arm/include/asm/arch-vf610/ddrmc-vf610.h |  60 +------
> >  board/freescale/vf610twr/vf610twr.c           | 181 +++++++++++++------
> >  board/toradex/colibri_vf/colibri_vf.c         | 169 +++++++++++++-----
> >  4 files changed, 312 insertions(+), 337 deletions(-)
> 
> So this goes basically back to setting all DDR registers directly from
> boards? What we tried to do here is to factor out the memory chip
> specific data (JEDEC). The idea behind this is it would make it simpler
> to add new RAM timings if a new RAM vendor is used on a different board
> revision...  With your changes it will be unnecessarily hard to add just
> a new RAM timing for a new board revision...

I could probably factor back out the JEDEC settings, but there are
still differences in the lists of registers to write between the
existing vf610twr/colibri_vf and the new pcm052, especially the PHY
regs but elsewhere too, and there are some writes in the driver that
the PCM052 does not have.

As I wanted to leave the existing boards strictly unaffected, and as I
did not want to start sprinkling '#if defined(some-board)' over the
driver code, I went for a fully board-controlled design so that no
board could possibly be affected by any future change to the driver.

How about a mix? I could keep the JEDEC and lvl pointers in the DDR
controller init call arguments and append "per-boards" CR and PHY
arrays. The driver would do the JEDEC writes (thus keeping JEDEC DDR3
additions simple), the LVL writes if not NULL, then the "per-board" CR
writes if not NULL, then the current common PHY writes, then the
"per-board" PHY writes if not null.

This would keep common parts (JEDEC and minimal settings) in the driver
while allowing board their own specific settings -- even overriding the
driver settings, since the per-board writes would come last before
CR000 is rewritten.

Would that be ok ?

> --
> Stefan

Cordialement,
Albert ARIBAUD
3ADEV

^ permalink raw reply	[flat|nested] 24+ messages in thread

* [U-Boot] [PATCH 2/5] vf610: refactor DDRMC code
  2015-06-19 15:13     ` [U-Boot] [PATCH 2/5] vf610: refactor DDRMC code Stefan Agner
  2015-06-19 16:50       ` Albert ARIBAUD
@ 2015-06-19 17:33       ` Albert ARIBAUD
  2015-07-10  8:09         ` Stefano Babic
  1 sibling, 1 reply; 24+ messages in thread
From: Albert ARIBAUD @ 2015-06-19 17:33 UTC (permalink / raw)
  To: u-boot

Bonjour Stefan,

Le Fri, 19 Jun 2015 17:13:12 +0200, Stefan Agner
<stefan.agner@toradex.com> a ?crit :

> Hi Albert,
> 
> On 19.06.2015 14:18, Albert ARIBAUD (3ADEV) wrote:
> > The VF610 DDRMC driver code contains settings which are
> > board-specific. Move these out to boards so that new boards
> > can define their own without having to modify the driver.
> >
> > Signed-off-by: Albert ARIBAUD (3ADEV) <albert.aribaud@3adev.fr>
> > ---
> >
> >  arch/arm/imx-common/ddrmc-vf610.c             | 239 ++++++--------------------
> >  arch/arm/include/asm/arch-vf610/ddrmc-vf610.h |  60 +------
> >  board/freescale/vf610twr/vf610twr.c           | 181 +++++++++++++------
> >  board/toradex/colibri_vf/colibri_vf.c         | 169 +++++++++++++-----
> >  4 files changed, 312 insertions(+), 337 deletions(-)
> 
> So this goes basically back to setting all DDR registers directly from
> boards? What we tried to do here is to factor out the memory chip
> specific data (JEDEC). The idea behind this is it would make it simpler
> to add new RAM timings if a new RAM vendor is used on a different board
> revision...  With your changes it will be unnecessarily hard to add just
> a new RAM timing for a new board revision...

I could probably factor back out the JEDEC settings, but there are
still differences in the lists of registers to write between the
existing vf610twr/colibri_vf and the new pcm052, especially the PHY
regs but elsewhere too, and there are some writes in the driver that
the PCM052 does not have.

As I wanted to leave the existing boards strictly unaffected, and as I
did not want to start sprinkling '#if defined(some-board)' over the
driver code, I went for a fully board-controlled design so that no
board could possibly be affected by any future change to the driver.

How about a mix? I could keep the JEDEC and lvl pointers in the DDR
controller init call arguments and append "per-boards" CR and PHY
arrays. The driver would do the JEDEC writes (thus keeping JEDEC DDR3
additions simple), the LVL writes if not NULL, then the "per-board" CR
writes if not NULL, then the current common PHY writes, then the
"per-board" PHY writes if not null.

This would keep common parts (JEDEC and minimal settings) in the driver
while allowing board their own specific settings -- even overriding the
driver settings, since the per-board writes would come last before
CR000 is rewritten.

Would that be ok ?

> --
> Stefan

Cordialement,
Albert ARIBAUD
3ADEV

^ permalink raw reply	[flat|nested] 24+ messages in thread

* [U-Boot] [PATCH 1/5] net: fec_mxc: remove useless struct nbuf
  2015-06-19 12:18 ` [U-Boot] [PATCH 1/5] net: fec_mxc: remove useless struct nbuf Albert ARIBAUD
  2015-06-19 12:18   ` [U-Boot] [PATCH 2/5] vf610: refactor DDRMC code Albert ARIBAUD
  2015-06-19 15:38   ` [U-Boot] [PATCH 1/5] net: fec_mxc: remove useless struct nbuf Joe Hershberger
@ 2015-07-10  8:03   ` Stefano Babic
  2 siblings, 0 replies; 24+ messages in thread
From: Stefano Babic @ 2015-07-10  8:03 UTC (permalink / raw)
  To: u-boot

On 19/06/2015 14:18, Albert ARIBAUD (3ADEV) wrote:
> This locally defined struct is actually only used once
> and as an opaque type. Remove it for clarity.
> 
> Signed-off-by: Albert ARIBAUD (3ADEV) <albert.aribaud@3adev.fr>
> ---
> 
>  drivers/net/fec_mxc.c | 20 +++++---------------
>  1 file changed, 5 insertions(+), 15 deletions(-)
> 
> diff --git a/drivers/net/fec_mxc.c b/drivers/net/fec_mxc.c
> index 9225d37..c5dcbbb 100644
> --- a/drivers/net/fec_mxc.c
> +++ b/drivers/net/fec_mxc.c
> @@ -67,13 +67,6 @@ DECLARE_GLOBAL_DATA_PTR;
>  
>  #undef DEBUG
>  
> -struct nbuf {
> -	uint8_t data[1500];	/**< actual data */
> -	int length;		/**< actual length */
> -	int used;		/**< buffer in use or not */
> -	uint8_t head[16];	/**< MAC header(6 + 6 + 2) + 2(aligned) */
> -};
> -
>  #ifdef CONFIG_FEC_MXC_SWAP_PACKET
>  static void swap_packet(uint32_t *packet, int length)
>  {
> @@ -775,7 +768,6 @@ static int fec_recv(struct eth_device *dev)
>  	struct fec_bd *rbd = &fec->rbd_base[fec->rbd_index];
>  	unsigned long ievent;
>  	int frame_length, len = 0;
> -	struct nbuf *frame;
>  	uint16_t bd_status;
>  	uint32_t addr, size, end;
>  	int i;
> @@ -835,12 +827,11 @@ static int fec_recv(struct eth_device *dev)
>  			/*
>  			 * Get buffer address and size
>  			 */
> -			frame = (struct nbuf *)readl(&rbd->data_pointer);
> +			addr = readl(&rbd->data_pointer);
>  			frame_length = readw(&rbd->data_length) - 4;
>  			/*
>  			 * Invalidate data cache over the buffer
>  			 */
> -			addr = (uint32_t)frame;
>  			end = roundup(addr + frame_length, ARCH_DMA_MINALIGN);
>  			addr &= ~(ARCH_DMA_MINALIGN - 1);
>  			invalidate_dcache_range(addr, end);
> @@ -849,16 +840,15 @@ static int fec_recv(struct eth_device *dev)
>  			 *  Fill the buffer and pass it to upper layers
>  			 */
>  #ifdef CONFIG_FEC_MXC_SWAP_PACKET
> -			swap_packet((uint32_t *)frame->data, frame_length);
> +			swap_packet((uint32_t *)addr, frame_length);
>  #endif
> -			memcpy(buff, frame->data, frame_length);
> +			memcpy(buff, (char *)addr, frame_length);
>  			net_process_received_packet(buff, frame_length);
>  			len = frame_length;
>  		} else {
>  			if (bd_status & FEC_RBD_ERR)
> -				printf("error frame: 0x%08lx 0x%08x\n",
> -						(ulong)rbd->data_pointer,
> -						bd_status);
> +				printf("error frame: 0x%08x 0x%08x\n",
> +				       addr, bd_status);
>  		}
>  
>  		/*
> 

Applied to u-boot-imx, thanks !

Best regards,
Stefano Babic

-- 
=====================================================================
DENX Software Engineering GmbH,      Managing Director: Wolfgang Denk
HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany
Phone: +49-8142-66989-53 Fax: +49-8142-66989-80 Email: sbabic at denx.de
=====================================================================

^ permalink raw reply	[flat|nested] 24+ messages in thread

* [U-Boot] [PATCH 2/5] vf610: refactor DDRMC code
  2015-06-19 17:33       ` Albert ARIBAUD
@ 2015-07-10  8:09         ` Stefano Babic
  2015-07-13 19:01           ` Stefan Agner
  0 siblings, 1 reply; 24+ messages in thread
From: Stefano Babic @ 2015-07-10  8:09 UTC (permalink / raw)
  To: u-boot

Hi Albert, Stefan,

On 19/06/2015 19:33, Albert ARIBAUD wrote:

> 
> I could probably factor back out the JEDEC settings, but there are
> still differences in the lists of registers to write between the
> existing vf610twr/colibri_vf and the new pcm052, especially the PHY
> regs but elsewhere too, and there are some writes in the driver that
> the PCM052 does not have.
> 
> As I wanted to leave the existing boards strictly unaffected, and as I
> did not want to start sprinkling '#if defined(some-board)' over the
> driver code, I went for a fully board-controlled design so that no
> board could possibly be affected by any future change to the driver.
> 
> How about a mix? I could keep the JEDEC and lvl pointers in the DDR
> controller init call arguments and append "per-boards" CR and PHY
> arrays. The driver would do the JEDEC writes (thus keeping JEDEC DDR3
> additions simple), the LVL writes if not NULL, then the "per-board" CR
> writes if not NULL, then the current common PHY writes, then the
> "per-board" PHY writes if not null.

This matches IMHO what we have already tried to do with most of
Frescale's i.MXes, putting general code and setting in the arch/cpu/ (or
in the imx_common for MX5 and MX6), but letting the board code to write
the board specific part.

Some mix seems to me a goog compromise between flexibility and common code.
> 
> This would keep common parts (JEDEC and minimal settings) in the driver
> while allowing board their own specific settings -- even overriding the
> driver settings, since the per-board writes would come last before
> CR000 is rewritten.
> 
> Would that be ok ?
> 
>> --
Best regards,
Stefano Babic


-- 
=====================================================================
DENX Software Engineering GmbH,      Managing Director: Wolfgang Denk
HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany
Phone: +49-8142-66989-53 Fax: +49-8142-66989-80 Email: sbabic at denx.de
=====================================================================

^ permalink raw reply	[flat|nested] 24+ messages in thread

* [U-Boot] [PATCH 3/5] i2c: fix vf610 support
  2015-06-19 12:18     ` [U-Boot] [PATCH 3/5] i2c: fix vf610 support Albert ARIBAUD
  2015-06-19 12:18       ` [U-Boot] [PATCH 4/5] tools: mkimage: fix imximage header size Albert ARIBAUD
@ 2015-07-10  8:11       ` Stefano Babic
  1 sibling, 0 replies; 24+ messages in thread
From: Stefano Babic @ 2015-07-10  8:11 UTC (permalink / raw)
  To: u-boot

Hi Albert,

On 19/06/2015 14:18, Albert ARIBAUD (3ADEV) wrote:
> Add support in mxc_i2c driver, iomux_v3 and vf610 architecture for the four
> I2C instances available in VF610.
> 
> Signed-off-by: Albert ARIBAUD (3ADEV) <albert.aribaud@3adev.fr>
> ---
> 
>  arch/arm/include/asm/arch-vf610/crm_regs.h    |  3 +++
>  arch/arm/include/asm/arch-vf610/imx-regs.h    |  3 +++
>  arch/arm/include/asm/arch-vf610/iomux-vf610.h | 11 +++++++----
>  arch/arm/include/asm/imx-common/iomux-v3.h    |  2 ++
>  drivers/i2c/mxc_i2c.c                         |  3 ++-
>  5 files changed, 17 insertions(+), 5 deletions(-)
> 
> diff --git a/arch/arm/include/asm/arch-vf610/crm_regs.h b/arch/arm/include/asm/arch-vf610/crm_regs.h
> index fdb45e9..a46e396 100644
> --- a/arch/arm/include/asm/arch-vf610/crm_regs.h
> +++ b/arch/arm/include/asm/arch-vf610/crm_regs.h
> @@ -207,6 +207,7 @@ struct anadig_reg {
>  #define CCM_CCGR4_CCM_CTRL_MASK			(0x3 << 22)
>  #define CCM_CCGR4_GPC_CTRL_MASK			(0x3 << 24)
>  #define CCM_CCGR4_I2C0_CTRL_MASK		(0x3 << 12)
> +#define CCM_CCGR4_I2C1_CTRL_MASK		(0x3 << 14)
>  #define CCM_CCGR6_OCOTP_CTRL_MASK		(0x3 << 10)
>  #define CCM_CCGR6_DSPI2_CTRL_MASK		(0x3 << 24)
>  #define CCM_CCGR6_DSPI3_CTRL_MASK		(0x3 << 26)
> @@ -216,6 +217,8 @@ struct anadig_reg {
>  #define CCM_CCGR9_FEC0_CTRL_MASK		0x3
>  #define CCM_CCGR9_FEC1_CTRL_MASK		(0x3 << 2)
>  #define CCM_CCGR10_NFC_CTRL_MASK		0x3
> +#define CCM_CCGR10_I2C2_CTRL_MASK		(0x3 << 12)
> +#define CCM_CCGR10_I2C3_CTRL_MASK		(0x3 << 14)
>  
>  #define ANADIG_PLL7_CTRL_BYPASS         (1 << 16)
>  #define ANADIG_PLL7_CTRL_ENABLE         (1 << 13)
> diff --git a/arch/arm/include/asm/arch-vf610/imx-regs.h b/arch/arm/include/asm/arch-vf610/imx-regs.h
> index 7df3b1e..4366985 100644
> --- a/arch/arm/include/asm/arch-vf610/imx-regs.h
> +++ b/arch/arm/include/asm/arch-vf610/imx-regs.h
> @@ -75,6 +75,9 @@
>  #define ESAI_FIFO_BASE_ADDR	(AIPS0_BASE_ADDR + 0x00063000)
>  #define WDOG_BASE_ADDR		(AIPS0_BASE_ADDR + 0x00065000)
>  #define I2C1_BASE_ADDR		(AIPS0_BASE_ADDR + 0x00066000)
> +#define I2C2_BASE_ADDR		(AIPS0_BASE_ADDR + 0x00067000)
> +#define I2C3_BASE_ADDR		(AIPS0_BASE_ADDR + 0x000E6000)
> +#define I2C4_BASE_ADDR		(AIPS0_BASE_ADDR + 0x000E7000)
>  #define WKUP_BASE_ADDR		(AIPS0_BASE_ADDR + 0x0006A000)
>  #define CCM_BASE_ADDR		(AIPS0_BASE_ADDR + 0x0006B000)
>  #define GPC_BASE_ADDR		(AIPS0_BASE_ADDR + 0x0006C000)
> diff --git a/arch/arm/include/asm/arch-vf610/iomux-vf610.h b/arch/arm/include/asm/arch-vf610/iomux-vf610.h
> index 019307b..0e2bd53 100644
> --- a/arch/arm/include/asm/arch-vf610/iomux-vf610.h
> +++ b/arch/arm/include/asm/arch-vf610/iomux-vf610.h
> @@ -20,7 +20,8 @@
>  #define VF610_DDR_PAD_CTRL_1	(PAD_CTL_DSE_25ohm | \
>  				PAD_CTL_INPUT_DIFFERENTIAL)
>  #define VF610_I2C_PAD_CTRL	(PAD_CTL_PUS_47K_UP | PAD_CTL_DSE_50ohm | \
> -				PAD_CTL_SPEED_HIGH | PAD_CTL_OBE_IBE_ENABLE)
> +				PAD_CTL_SPEED_HIGH | PAD_CTL_ODE | \
> +				PAD_CTL_OBE_IBE_ENABLE)
>  #define VF610_NFC_IO_PAD_CTRL	(PAD_CTL_SPEED_MED | PAD_CTL_SRE | \
>  				PAD_CTL_DSE_50ohm | PAD_CTL_PUS_47K_UP | \
>  				PAD_CTL_OBE_IBE_ENABLE)
> @@ -110,6 +111,8 @@ enum {
>  	VF610_PAD_PTA29__ESDHC1_DAT3		= IOMUX_PAD(0x004c, 0x004c, 5, __NA_, 0, VF610_SDHC_PAD_CTRL),
>  	VF610_PAD_PTB14__I2C0_SCL		= IOMUX_PAD(0x0090, 0x0090, 2, 0x033c, 1, VF610_I2C_PAD_CTRL),
>  	VF610_PAD_PTB15__I2C0_SDA		= IOMUX_PAD(0x0094, 0x0094, 2, 0x0340, 1, VF610_I2C_PAD_CTRL),
> +	VF610_PAD_PTA22__I2C2_SCL		= IOMUX_PAD(0x0030, 0x0030, 6, 0x034c, 0, VF610_I2C_PAD_CTRL),
> +	VF610_PAD_PTA23__I2C2_SDA		= IOMUX_PAD(0x0034, 0x0034, 6, 0x0350, 0, VF610_I2C_PAD_CTRL),
>  	VF610_PAD_PTD31__NF_IO15		= IOMUX_PAD(0x00fc, 0x00fc, 2, __NA_, 0, VF610_NFC_IO_PAD_CTRL),
>  	VF610_PAD_PTD31__GPIO_63		= IOMUX_PAD(0x00fc, 0x00fc, 0, __NA_, 0, VF610_GPIO_PAD_CTRL),
>  	VF610_PAD_PTD30__NF_IO14		= IOMUX_PAD(0x0100, 0x0100, 2, __NA_, 0, VF610_NFC_IO_PAD_CTRL),
> @@ -146,10 +149,10 @@ enum {
>  	VF610_PAD_PTD12__GPIO_91		= IOMUX_PAD(0x016c, 0x016c, 0, __NA_, 0, VF610_GPIO_PAD_CTRL),
>  	VF610_PAD_PTD13__GPIO_92		= IOMUX_PAD(0x0170, 0x0170, 0, __NA_, 0, VF610_GPIO_PAD_CTRL),
>  	VF610_PAD_PTD22__NF_IO6			= IOMUX_PAD(0x0120, 0x0120, 2, __NA_, 0, VF610_NFC_IO_PAD_CTRL),
> -	VF610_PAD_PTD21__NF_IO5			= IOMUX_PAD(0x0124, 0x0124, 2, __NA_, 0, VF610_NFC_IO_PAD_CTRL), 
> -	VF610_PAD_PTD20__NF_IO4			= IOMUX_PAD(0x0128, 0x0128, 2, __NA_, 0, VF610_NFC_IO_PAD_CTRL), 
> +	VF610_PAD_PTD21__NF_IO5			= IOMUX_PAD(0x0124, 0x0124, 2, __NA_, 0, VF610_NFC_IO_PAD_CTRL),
> +	VF610_PAD_PTD20__NF_IO4			= IOMUX_PAD(0x0128, 0x0128, 2, __NA_, 0, VF610_NFC_IO_PAD_CTRL),
>  	VF610_PAD_PTD19__NF_IO3			= IOMUX_PAD(0x012c, 0x012c, 2, __NA_, 0, VF610_NFC_IO_PAD_CTRL),
> -	VF610_PAD_PTD18__NF_IO2			= IOMUX_PAD(0x0130, 0x0130, 2, __NA_, 0, VF610_NFC_IO_PAD_CTRL), 
> +	VF610_PAD_PTD18__NF_IO2			= IOMUX_PAD(0x0130, 0x0130, 2, __NA_, 0, VF610_NFC_IO_PAD_CTRL),
>  	VF610_PAD_PTD17__NF_IO1			= IOMUX_PAD(0x0134, 0x0134, 2, __NA_, 0, VF610_NFC_IO_PAD_CTRL),
>  	VF610_PAD_PTD16__NF_IO0			= IOMUX_PAD(0x0138, 0x0138, 2, __NA_, 0, VF610_NFC_IO_PAD_CTRL),
>  	VF610_PAD_PTB24__NF_WE_B		= IOMUX_PAD(0x0178, 0x0178, 5, __NA_, 0, VF610_NFC_CN_PAD_CTRL),
> diff --git a/arch/arm/include/asm/imx-common/iomux-v3.h b/arch/arm/include/asm/imx-common/iomux-v3.h
> index 2581019..5cde90f 100644
> --- a/arch/arm/include/asm/imx-common/iomux-v3.h
> +++ b/arch/arm/include/asm/imx-common/iomux-v3.h
> @@ -127,6 +127,8 @@ typedef u64 iomux_v3_cfg_t;
>  
>  #define PAD_CTL_SRE		(1 << 11)
>  
> +#define PAD_CTL_ODE		(1 << 10)
> +
>  #define PAD_CTL_DSE_150ohm	(1 << 6)
>  #define PAD_CTL_DSE_50ohm	(3 << 6)
>  #define PAD_CTL_DSE_25ohm	(6 << 6)
> diff --git a/drivers/i2c/mxc_i2c.c b/drivers/i2c/mxc_i2c.c
> index b3c50aa..f1056e2 100644
> --- a/drivers/i2c/mxc_i2c.c
> +++ b/drivers/i2c/mxc_i2c.c
> @@ -523,7 +523,8 @@ static int bus_i2c_write(struct mxc_i2c_bus *i2c_bus, u8 chip, u32 addr,
>  #endif
>  
>  static struct mxc_i2c_bus mxc_i2c_buses[] = {
> -#if defined(CONFIG_LS102XA) || defined(CONFIG_FSL_LSCH3)
> +#if defined(CONFIG_LS102XA) || defined(CONFIG_FSL_LSCH3) || \
> +		defined(CONFIG_VF610)
>  	{ 0, I2C1_BASE_ADDR, I2C_QUIRK_FLAG },
>  	{ 1, I2C2_BASE_ADDR, I2C_QUIRK_FLAG },
>  	{ 2, I2C3_BASE_ADDR, I2C_QUIRK_FLAG },
> 

This is independent from the rest of patchset - I can merge it.

Applied to u-boot-imx, thanks !

Best regards,
Stefano Babic


-- 
=====================================================================
DENX Software Engineering GmbH,      Managing Director: Wolfgang Denk
HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany
Phone: +49-8142-66989-53 Fax: +49-8142-66989-80 Email: sbabic at denx.de
=====================================================================

^ permalink raw reply	[flat|nested] 24+ messages in thread

* [U-Boot] [PATCH 4/5] tools: mkimage: fix imximage header size
  2015-06-19 12:18       ` [U-Boot] [PATCH 4/5] tools: mkimage: fix imximage header size Albert ARIBAUD
  2015-06-19 12:18         ` [U-Boot] [PATCH 5/5] vf610: add support for Phytec PCM052 Albert ARIBAUD
@ 2015-07-10  8:14         ` Stefano Babic
  2015-07-14 10:29           ` Stefan Agner
  1 sibling, 1 reply; 24+ messages in thread
From: Stefano Babic @ 2015-07-10  8:14 UTC (permalink / raw)
  To: u-boot

On 19/06/2015 14:18, Albert ARIBAUD (3ADEV) wrote:
> imximage header size is 4-byte, not 8-byte aligned.
> This produces .imx images that a Vybrid cannot boot
> on.
> 
> Fix by adding a "padding" field in header.
> 
> Signed-off-by: Albert ARIBAUD (3ADEV) <albert.aribaud@3adev.fr>
> ---
> 
>  tools/imximage.h | 1 +
>  1 file changed, 1 insertion(+)
> 
> diff --git a/tools/imximage.h b/tools/imximage.h
> index 36fe095..a913329 100644
> --- a/tools/imximage.h
> +++ b/tools/imximage.h
> @@ -129,6 +129,7 @@ typedef struct {
>  	ivt_header_t header;
>  	write_dcd_command_t write_dcd_command;
>  	dcd_addr_data_t addr_data[MAX_HW_CFG_SIZE_V2];
> +	uint32_t padding[1]; /* end up on an 8-byte boundary */
>  } dcd_v2_t;
>  
>  typedef struct {
> 

Applied to u-boot-imx, thanks !

Best regards,
Stefano Babic


-- 
=====================================================================
DENX Software Engineering GmbH,      Managing Director: Wolfgang Denk
HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany
Phone: +49-8142-66989-53 Fax: +49-8142-66989-80 Email: sbabic at denx.de
=====================================================================

^ permalink raw reply	[flat|nested] 24+ messages in thread

* [U-Boot] [PATCH 2/5] vf610: refactor DDRMC code
  2015-07-10  8:09         ` Stefano Babic
@ 2015-07-13 19:01           ` Stefan Agner
  2015-07-14  7:16             ` [U-Boot] (rather [LONG], sorry) " Albert ARIBAUD
  0 siblings, 1 reply; 24+ messages in thread
From: Stefan Agner @ 2015-07-13 19:01 UTC (permalink / raw)
  To: u-boot

Hi Albert, Hi Stefano,

On 10.07.2015 10:09, Stefano Babic wrote:
> Hi Albert, Stefan,
>
> On 19/06/2015 19:33, Albert ARIBAUD wrote:
>
>> I could probably factor back out the JEDEC settings, but there are
>> still differences in the lists of registers to write between the
>> existing vf610twr/colibri_vf and the new pcm052, especially the PHY
>> regs but elsewhere too, and there are some writes in the driver that
>> the PCM052 does not have.
>>
>> As I wanted to leave the existing boards strictly unaffected, and as I
>> did not want to start sprinkling '#if defined(some-board)' over the
>> driver code, I went for a fully board-controlled design so that no
>> board could possibly be affected by any future change to the driver.
>>
>> How about a mix? I could keep the JEDEC and lvl pointers in the DDR
>> controller init call arguments and append "per-boards" CR and PHY
>> arrays. The driver would do the JEDEC writes (thus keeping JEDEC DDR3
>> additions simple), the LVL writes if not NULL, then the "per-board" CR
>> writes if not NULL, then the current common PHY writes, then the
>> "per-board" PHY writes if not null.
> This matches IMHO what we have already tried to do with most of
> Frescale's i.MXes, putting general code and setting in the arch/cpu/ (or
> in the imx_common for MX5 and MX6), but letting the board code to write
> the board specific part.
>
> Some mix seems to me a goog compromise between flexibility and common code.

As far as I understood Alberts proposition it would mean that we write
some registers directly from board code right? I'm not sure if this
works out for all registers, since some might have JEDEC and Board
specific fields in one register...?

Looking throug some CR registers lead me to belive that most settings
are exact the same or already covered by the JEDEC struct... The few
remaning ones could be part of a renamed ddrmc_lvl_info struct (e.g.
ddrmc_cr_info).

The same for the PHY settings (ddrmc_phy_info). This would lead to a
common place where all registers gets written, while having the
flexibility to use board specific data... No back and forth between the
board file and the common code.

I did not an exact survey how much of the registers are actually
different, but I feel that the difference is not that big that moving
the whole initialization to the board files is worth the effort...

--
Stefan


>> This would keep common parts (JEDEC and minimal settings) in the driver
>> while allowing board their own specific settings -- even overriding the
>> driver settings, since the per-board writes would come last before
>> CR000 is rewritten.
>>
>> Would that be ok ?
>>
>>> --
> Best regards,
> Stefano Babic
>
>

^ permalink raw reply	[flat|nested] 24+ messages in thread

* [U-Boot] (rather [LONG], sorry) Re: [PATCH 2/5] vf610: refactor DDRMC code
  2015-07-13 19:01           ` Stefan Agner
@ 2015-07-14  7:16             ` Albert ARIBAUD
  0 siblings, 0 replies; 24+ messages in thread
From: Albert ARIBAUD @ 2015-07-14  7:16 UTC (permalink / raw)
  To: u-boot

Hi Stefan,

Le Mon, 13 Jul 2015 21:01:56 +0200, Stefan Agner
<stefan.agner@toradex.com> a ?crit :

> Hi Albert, Hi Stefano,
> 
> On 10.07.2015 10:09, Stefano Babic wrote:
> > Hi Albert, Stefan,
> >
> > On 19/06/2015 19:33, Albert ARIBAUD wrote:
> >
> >> I could probably factor back out the JEDEC settings, but there are
> >> still differences in the lists of registers to write between the
> >> existing vf610twr/colibri_vf and the new pcm052, especially the PHY
> >> regs but elsewhere too, and there are some writes in the driver that
> >> the PCM052 does not have.
> >>
> >> As I wanted to leave the existing boards strictly unaffected, and as I
> >> did not want to start sprinkling '#if defined(some-board)' over the
> >> driver code, I went for a fully board-controlled design so that no
> >> board could possibly be affected by any future change to the driver.
> >>
> >> How about a mix? I could keep the JEDEC and lvl pointers in the DDR
> >> controller init call arguments and append "per-boards" CR and PHY
> >> arrays. The driver would do the JEDEC writes (thus keeping JEDEC DDR3
> >> additions simple), the LVL writes if not NULL, then the "per-board" CR
> >> writes if not NULL, then the current common PHY writes, then the
> >> "per-board" PHY writes if not null.
> > This matches IMHO what we have already tried to do with most of
> > Frescale's i.MXes, putting general code and setting in the arch/cpu/ (or
> > in the imx_common for MX5 and MX6), but letting the board code to write
> > the board specific part.
> >
> > Some mix seems to me a goog compromise between flexibility and common code.
> 
> As far as I understood Alberts proposition it would mean that we write
> some registers directly from board code right? I'm not sure if this
> works out for all registers, since some might have JEDEC and Board
> specific fields in one register...?

Well, it would not be /from/ board code as boards would actually pass
descriptions and the writing would occur in the driver within the
general write sequence, but I see your point about some register values
possibly needing to be constructed from both the jedec struct) /and/
some other source -- see below.

Also, we can hardly avoid that each board will require regiser writes
which will be somewhat unique to it. The question is not whether we can
avoid that, it is how we should specify that and where we should put
that.

> Looking throug some CR registers lead me to belive that most settings
> are exact the same or already covered by the JEDEC struct... The few
> remaning ones could be part of a renamed ddrmc_lvl_info struct (e.g.
> ddrmc_cr_info).

I do understand the benefit of passing JEDEC parameters rather that
register values, because this allows "working in the problem domain",
i.e. using JEDEC values straight from datasheets, and having thdriver
to the "heavy lifting", i.e. converting this set of JEDEC values into
a consistent set of interrelated register values.

I might understand it for PHY settings when you might know that
several PHY registers need values consistent with one another (more
below).

Generally, though, I don't think there is added values in turning
register values into a struct rather than an (offset, value) pair list
which is IMO more versatile.

Take the lvl struct for example: it embodies a 'leveling' abstraction
which does not exist in the IP per se, and does not exist outside the
IP as JEDEC parameters do; it' artificial. And while it does provide
some consistency, it does not even hide all hardware implementation
details, so you still need to go see the IP's register definition if
you want to fill that struct (as opposed to only having to read the
DDR3 datasheet to fill the JEDEC structure). And if you need to go read
the register structure, working with (offset, value) pairs makes a
simpler driver.

Last point: the driver is supposed to work with various incarnations of
the IP, not all of which may have the same set of known, and unknown,
registers. I stumbled uplon this problem with the current driver code:
it writes some (non-JEDEC) CR registers which my board does not write
as far as I can tell, and it does not do some writes my board does.

I could have gone through the driver's 'extra' writes and tested
whether they could be done on my board without any ill effect. I could
also hve gone through my board's extra writes and seen whether they
could be removed without any any ill effect. In fact, I *had* to do
some of each, because some of the driver's writes (in the lvl struct
notably, but elsewhere too) caused issues.

The problem was, I could not test what effect my changes would have on
the other boards that use the driver -- it's not even a question of
time: I just don't have these other boards which happen to use the
driver that I'm modifying (and I expect that's a pretty common case).

Or I could make my changes so that existing boards using the driver
kept writing the registers as they do in the current code and that my
board write the registers as it needs to, and keep only the common part
in the driver.

This way, I could ensure that existing code would retain the exact
behavior it currently expects from the IP it runs on while in the same
time getting the exact behavior I expected on my board.

> The same for the PHY settings (ddrmc_phy_info). This would lead to a
> common place where all registers gets written, while having the
> flexibility to use board specific data... No back and forth between the
> board file and the common code.

Here too, there is a problem: current code does not write all the
registers my code wants written. If I added writes to the driver
unconditionally, I would risk breaking existing boards by adding writes
to them that they never intended to do. If I added it conditionally, I
would add artificial complexity to the driver, basically injecting
board-specifics in it. That's why I initially went the "driver provides
the tools, board provides the values" route.

Now I do understand that one might want to avoid duplication, which is
why I would agree with keeping the existing sequence in the driver and
only defining board-specific sequences in the board code. 

> I did not an exact survey how much of the registers are actually
> different, but I feel that the difference is not that big that moving
> the whole initialization to the board files is worth the effort...

OTOH, if the difference is not that big, then keeping it in the board
is not that painful either. :)

Seriously, though: There's zero reason we should have board dependency
compiled into drivers, since we can always write the driver API so that
board-specifics are passed by argument to driver functions, and having
a board-agnostic driver is a Good Thing (tm).

Now, what part is board-specific and how it is passed, that's quite an
open point.

I personally think that the way we should abstract things, and whether
we should abstract them at all, depends on the benefit from an overall
SW architecture standpoint.

For instance, I have come to think the JEDEC abstraction is good,
because it can be be reused by other (future /or/ existing) drivers, and
ecause the JEDEC definition for a given DDR3 chip can be hared across
all boards that use it (and then, all can benefit from 'bugfixes', if
any, in the chip's JEDEC definition).

The only thing I'm not 100% sure is, as you mention it, whether the
IP's JEDEC-related are *purely* JEDEC or whether they also depend in
part on the board's HW design (track lengths, buffers, whatever). But
even if they do, then we can always pass the existing, pure, JEDEC
info in the JEDEC struct, /plus/ HW related info in another argument,
and have the driver do the mix. The separation would allow us to keep 
sharing the pure JEDEC info in all boards that use the same DDR3 chip.

OTOH, structs like the lvl struct, with the driver interpreting them
into register writes, seems not to benefit the SW architecture: you
can't generalize that to other drivers. You can't share lvl struct
values across boards. The lvl struct's only benefit is to ensure
that a small group of writes will be consistent, something that the
developer will quite probably have checked from the spec anyway; it is
prone to introducing restrictions that will inevitably be hit one day,
and then we will have to maintain the struct *and* the writing code,
and run a risk of affecting existing boards each time we do it.

The (offset, value) sequence is indeed very low-level and does indeed
make the board hardware-dependent, but the board already *is*, anyway --
anyone looking at the board's DDR3 init certainly should have read the
DDR3 controller (and chip) HW specs -- and the maintenance cost in the
is low: the driver won't need any once it knows how to run the sequence
properly, existing boards which use it will only need maintenance in
case of bugs, and new boards will only need to get their new sequence
right without fear of affecting existing code.

> --
> Stefan
> 
> 
> >> This would keep common parts (JEDEC and minimal settings) in the driver
> >> while allowing board their own specific settings -- even overriding the
> >> driver settings, since the per-board writes would come last before
> >> CR000 is rewritten.
> >>
> >> Would that be ok ?
> >>
> >>> --
> > Best regards,
> > Stefano Babic
> >
> >
> 



Cordialement,
Albert ARIBAUD
3ADEV

^ permalink raw reply	[flat|nested] 24+ messages in thread

* [U-Boot] [PATCH 4/5] tools: mkimage: fix imximage header size
  2015-07-10  8:14         ` [U-Boot] [PATCH 4/5] tools: mkimage: fix imximage header size Stefano Babic
@ 2015-07-14 10:29           ` Stefan Agner
  2015-07-15  7:19             ` Stefano Babic
  2015-07-15  7:37             ` Albert ARIBAUD
  0 siblings, 2 replies; 24+ messages in thread
From: Stefan Agner @ 2015-07-14 10:29 UTC (permalink / raw)
  To: u-boot

Hi Stefano,

On 2015-07-10 10:14, Stefano Babic wrote:
> On 19/06/2015 14:18, Albert ARIBAUD (3ADEV) wrote:
>> imximage header size is 4-byte, not 8-byte aligned.
>> This produces .imx images that a Vybrid cannot boot
>> on.
>>
>> Fix by adding a "padding" field in header.
>>
>> Signed-off-by: Albert ARIBAUD (3ADEV) <albert.aribaud@3adev.fr>
>> ---
>>
>>  tools/imximage.h | 1 +
>>  1 file changed, 1 insertion(+)
>>
>> diff --git a/tools/imximage.h b/tools/imximage.h
>> index 36fe095..a913329 100644
>> --- a/tools/imximage.h
>> +++ b/tools/imximage.h
>> @@ -129,6 +129,7 @@ typedef struct {
>>  	ivt_header_t header;
>>  	write_dcd_command_t write_dcd_command;
>>  	dcd_addr_data_t addr_data[MAX_HW_CFG_SIZE_V2];
>> +	uint32_t padding[1]; /* end up on an 8-byte boundary */
>>  } dcd_v2_t;
>>
>>  typedef struct {
>>
> 
> Applied to u-boot-imx, thanks !

Sorry, just stumbled over this message now.

We discussed exactly this issue already more than a year ago, see:
http://lists.denx.de/pipermail/u-boot/2014-April/177580.html

Back then you asked whether I asked Freescale about it. Earlier this
year I tried to get hold of that issue and asked Freescale on Community,
see:
https://community.freescale.com/thread/355161

However, no official confirmation or explanation so far.

I think my patch back then solves the issue nicer. The struct dcd_v2_t
is not the reason the whole header is not aligned by 8-byte, it is a
problem of the boot_data_t header which is 12 bytes long. So inserting
the padding just after struct boot_data_t (or inside of struct
boot_data_t) seems to be more appropriate.

--
Stefan

^ permalink raw reply	[flat|nested] 24+ messages in thread

* [U-Boot] [PATCH 4/5] tools: mkimage: fix imximage header size
  2015-07-14 10:29           ` Stefan Agner
@ 2015-07-15  7:19             ` Stefano Babic
  2015-07-15  7:54               ` Albert ARIBAUD
  2015-07-15  7:37             ` Albert ARIBAUD
  1 sibling, 1 reply; 24+ messages in thread
From: Stefano Babic @ 2015-07-15  7:19 UTC (permalink / raw)
  To: u-boot


Hi Stefan,

On 14/07/2015 12:29, Stefan Agner wrote:
>>
>> Applied to u-boot-imx, thanks !
> 
> Sorry, just stumbled over this message now.
> 
> We discussed exactly this issue already more than a year ago, see:
> http://lists.denx.de/pipermail/u-boot/2014-April/177580.html

I admit that I have forgotten it....thanks to revive it !

> 
> Back then you asked whether I asked Freescale about it. Earlier this
> year I tried to get hold of that issue and asked Freescale on Community,
> see:
> https://community.freescale.com/thread/355161
> 
> However, no official confirmation or explanation so far.
> 
> I think my patch back then solves the issue nicer. The struct dcd_v2_t
> is not the reason the whole header is not aligned by 8-byte, it is a
> problem of the boot_data_t header which is 12 bytes long. So inserting
> the padding just after struct boot_data_t (or inside of struct
> boot_data_t) seems to be more appropriate.

I see. Albert, can you test on your board if Stefan's patch solves your
issue, too ? I could then revert this one and apply Stefan's.

It remains doubious how the ROMs on Freescale are interpretating the
header, but we can only test it.

Best regards,
Stefano


-- 
=====================================================================
DENX Software Engineering GmbH,      Managing Director: Wolfgang Denk
HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany
Phone: +49-8142-66989-53 Fax: +49-8142-66989-80 Email: sbabic at denx.de
=====================================================================

^ permalink raw reply	[flat|nested] 24+ messages in thread

* [U-Boot] [PATCH 4/5] tools: mkimage: fix imximage header size
  2015-07-14 10:29           ` Stefan Agner
  2015-07-15  7:19             ` Stefano Babic
@ 2015-07-15  7:37             ` Albert ARIBAUD
  1 sibling, 0 replies; 24+ messages in thread
From: Albert ARIBAUD @ 2015-07-15  7:37 UTC (permalink / raw)
  To: u-boot

Hello Stefan,

On Tue, 14 Jul 2015 12:29:52 +0200, Stefan Agner <stefan@agner.ch>
wrote:
> Hi Stefano,
> 
> On 2015-07-10 10:14, Stefano Babic wrote:
> > On 19/06/2015 14:18, Albert ARIBAUD (3ADEV) wrote:
> >> imximage header size is 4-byte, not 8-byte aligned.
> >> This produces .imx images that a Vybrid cannot boot
> >> on.
> >>
> >> Fix by adding a "padding" field in header.
> >>
> >> Signed-off-by: Albert ARIBAUD (3ADEV) <albert.aribaud@3adev.fr>
> >> ---
> >>
> >>  tools/imximage.h | 1 +
> >>  1 file changed, 1 insertion(+)
> >>
> >> diff --git a/tools/imximage.h b/tools/imximage.h
> >> index 36fe095..a913329 100644
> >> --- a/tools/imximage.h
> >> +++ b/tools/imximage.h
> >> @@ -129,6 +129,7 @@ typedef struct {
> >>  	ivt_header_t header;
> >>  	write_dcd_command_t write_dcd_command;
> >>  	dcd_addr_data_t addr_data[MAX_HW_CFG_SIZE_V2];
> >> +	uint32_t padding[1]; /* end up on an 8-byte boundary */
> >>  } dcd_v2_t;
> >>
> >>  typedef struct {
> >>
> > 
> > Applied to u-boot-imx, thanks !
> 
> Sorry, just stumbled over this message now.
> 
> We discussed exactly this issue already more than a year ago, see:
> http://lists.denx.de/pipermail/u-boot/2014-April/177580.html
> 
> Back then you asked whether I asked Freescale about it. Earlier this
> year I tried to get hold of that issue and asked Freescale on Community,
> see:
> https://community.freescale.com/thread/355161
> 
> However, no official confirmation or explanation so far.
> 
> I think my patch back then solves the issue nicer. The struct dcd_v2_t
> is not the reason the whole header is not aligned by 8-byte, it is a
> problem of the boot_data_t header which is 12 bytes long. So inserting
> the padding just after struct boot_data_t (or inside of struct
> boot_data_t) seems to be more appropriate.

After reading the U-Boot and Freescale discussions, IIUC you have come
to the conclusion that the missing 4 bytes were in boot_data_t because
it was the only structure in the header which was not 8-bytes-aligned.

However, the available documentation does not specify this constraint,
and from a more experimental vewpoint, my patch adds 4 bytes at the end
of the overall header, thus leaving boot data at 12 bytes (therefore
leaving the dcd_table not 8-byte-aligned) and yet Vybrid can boot.

To me, this proves that the size alignment problem is not with
boot_data_t but with the overall header.

Aside:

My own hypothesis on the reason for the non-written 8-byte-alignment
requirement is that the ROM code initially loads the NAND sector
containing the header at some fixed address then calls some function to
copy the header just below the image destination address, and that
function is 'optimized' to use 8-byte chunks (probably because it
only had two free regs for ldm/stm) and thus assumes an 8 bytes header
size, and nobody cared to document (or possibly even realized the
existence of) that assumption.

> --
> Stefan

Amicalement,
-- 
Albert.

^ permalink raw reply	[flat|nested] 24+ messages in thread

* [U-Boot] [PATCH 4/5] tools: mkimage: fix imximage header size
  2015-07-15  7:19             ` Stefano Babic
@ 2015-07-15  7:54               ` Albert ARIBAUD
  2015-07-15 10:41                 ` Stefan Agner
  0 siblings, 1 reply; 24+ messages in thread
From: Albert ARIBAUD @ 2015-07-15  7:54 UTC (permalink / raw)
  To: u-boot

Hello Stefano,

On Wed, 15 Jul 2015 09:19:55 +0200, Stefano Babic <sbabic@denx.de>
wrote:

> > I think my patch back then solves the issue nicer. The struct dcd_v2_t
> > is not the reason the whole header is not aligned by 8-byte, it is a
> > problem of the boot_data_t header which is 12 bytes long. So inserting
> > the padding just after struct boot_data_t (or inside of struct
> > boot_data_t) seems to be more appropriate.
> 
> I see. Albert, can you test on your board if Stefan's patch solves your
> issue, too ? I could then revert this one and apply Stefan's.

I can test it, but I'm sure that boot data does not need size alignment
since in my case there is no such alignment and Vybrid boots. To me
this means aligning boot_data_t size would introduce a constraint that
is not really there.

If Stefan would test my patch as well, I reckon he would find it to
work as well as his.

So we have two patches which fix Vybrid booting:

- one which aligns the boot_data_t /size/ but keeps its /offset/
  unaligned;

- one which aligns the the boot_data_t /offset/ but keeps its /size/
  unaligned.

Seems to me that the conclusion is that the actual alignment of
boot_data_t does not matter and that only the alignment of the
whole imx_header_v2_t size (and, consequently, offset) matters.

How about just adding an attribute((align(8))) to imx_header_v2_t?

> It remains doubious how the ROMs on Freescale are interpretating the
> header, but we can only test it.

See my other answer. We could prove it by disassembling the ROM code.
Any volunteer? :)

> Best regards,
> Stefano

Amicalement,
-- 
Albert.

^ permalink raw reply	[flat|nested] 24+ messages in thread

* [U-Boot] [PATCH 4/5] tools: mkimage: fix imximage header size
  2015-07-15  7:54               ` Albert ARIBAUD
@ 2015-07-15 10:41                 ` Stefan Agner
  2015-07-15 11:44                   ` Albert ARIBAUD
  0 siblings, 1 reply; 24+ messages in thread
From: Stefan Agner @ 2015-07-15 10:41 UTC (permalink / raw)
  To: u-boot

Hi Albert,

On 2015-07-15 09:54, Albert ARIBAUD wrote:
> Hello Stefano,
> 
> On Wed, 15 Jul 2015 09:19:55 +0200, Stefano Babic <sbabic@denx.de>
> wrote:
> 
>> > I think my patch back then solves the issue nicer. The struct dcd_v2_t
>> > is not the reason the whole header is not aligned by 8-byte, it is a
>> > problem of the boot_data_t header which is 12 bytes long. So inserting
>> > the padding just after struct boot_data_t (or inside of struct
>> > boot_data_t) seems to be more appropriate.
>>
>> I see. Albert, can you test on your board if Stefan's patch solves your
>> issue, too ? I could then revert this one and apply Stefan's.
> 
> I can test it, but I'm sure that boot data does not need size alignment
> since in my case there is no such alignment and Vybrid boots. To me
> this means aligning boot_data_t size would introduce a constraint that
> is not really there.

I quote here from both emails, since its about the same topic.

> After reading the U-Boot and Freescale discussions, IIUC you have come
> to the conclusion that the missing 4 bytes were in boot_data_t because
> it was the only structure in the header which was not 8-bytes-aligned.
> 
> However, the available documentation does not specify this constraint,
> and from a more experimental vewpoint, my patch adds 4 bytes at the end
> of the overall header, thus leaving boot data at 12 bytes (therefore
> leaving the dcd_table not 8-byte-aligned) and yet Vybrid can boot.

Yes, I agree on that. Also the boot data seems not to have the 8-byte
alignment requirement (see the graphics I posted on the Freescale
community article).

> To me, this proves that the size alignment problem is not with
> boot_data_t but with the overall header.

I agree. Still, boot_data_t is the "offender", hence I would prefer that
solution over your solution.

> If Stefan would test my patch as well, I reckon he would find it to
> work as well as his.
> 
> So we have two patches which fix Vybrid booting:
> 
> - one which aligns the boot_data_t /size/ but keeps its /offset/
>   unaligned;
> 
> - one which aligns the the boot_data_t /offset/ but keeps its /size/
>   unaligned.

I don't get this classification. The complete header struct shows that
dcd_v2_t is _after_ boot_data_t.

typedef struct {
	flash_header_v2_t fhdr;
	boot_data_t boot_data;
	dcd_v2_t dcd_table;
} imx_header_v2_t;

Your patch changes the size of dcd_v2_t, hence compensating the
"unaligned" size of boot_data_t.

As far as I see we have these two patches which fix Vybrid booting:

- one which changes the boot_data_t /size/ which keeps the offset
  of dcd_v2_t and the image aligned.

- one which changes the dcd_v2_t /size/ which compensates the unaligned
  size of boot_data_t and keeps the image aligned.
 
> Seems to me that the conclusion is that the actual alignment of
> boot_data_t does not matter and that only the alignment of the
> whole imx_header_v2_t size (and, consequently, offset) matters.
> 
> How about just adding an attribute((align(8))) to imx_header_v2_t?

Hm this sounds tempting, but it does not seem to work here. I think
because it only aligns the beginning of imx_header_v2_t in to 8-byte,
however it does not align the size of the whole struct to 8 bytes, I
guess? Hence the header size is still "unaligned".

> 
>> It remains doubious how the ROMs on Freescale are interpretating the
>> header, but we can only test it.
> 
> See my other answer. We could prove it by disassembling the ROM code.
> Any volunteer? :)

Hehe, not me :-)

--
Stefan

^ permalink raw reply	[flat|nested] 24+ messages in thread

* [U-Boot] [PATCH 4/5] tools: mkimage: fix imximage header size
  2015-07-15 10:41                 ` Stefan Agner
@ 2015-07-15 11:44                   ` Albert ARIBAUD
  2015-07-15 12:36                     ` Stefan Agner
  0 siblings, 1 reply; 24+ messages in thread
From: Albert ARIBAUD @ 2015-07-15 11:44 UTC (permalink / raw)
  To: u-boot

Hello Stefan (and sorry for the duplicate),

On Wed, 15 Jul 2015 12:41:59 +0200, Stefan Agner <stefan@agner.ch>
wrote:
> Hi Albert,
> 
> On 2015-07-15 09:54, Albert ARIBAUD wrote:
> > Hello Stefano,
> > 
> > On Wed, 15 Jul 2015 09:19:55 +0200, Stefano Babic <sbabic@denx.de>
> > wrote:
> > 
> >> > I think my patch back then solves the issue nicer. The struct dcd_v2_t
> >> > is not the reason the whole header is not aligned by 8-byte, it is a
> >> > problem of the boot_data_t header which is 12 bytes long. So inserting
> >> > the padding just after struct boot_data_t (or inside of struct
> >> > boot_data_t) seems to be more appropriate.
> >>
> >> I see. Albert, can you test on your board if Stefan's patch solves your
> >> issue, too ? I could then revert this one and apply Stefan's.
> > 
> > I can test it, but I'm sure that boot data does not need size alignment
> > since in my case there is no such alignment and Vybrid boots. To me
> > this means aligning boot_data_t size would introduce a constraint that
> > is not really there.
> 
> I quote here from both emails, since its about the same topic.
> 
> > After reading the U-Boot and Freescale discussions, IIUC you have come
> > to the conclusion that the missing 4 bytes were in boot_data_t because
> > it was the only structure in the header which was not 8-bytes-aligned.
> > 
> > However, the available documentation does not specify this constraint,
> > and from a more experimental vewpoint, my patch adds 4 bytes at the end
> > of the overall header, thus leaving boot data at 12 bytes (therefore
> > leaving the dcd_table not 8-byte-aligned) and yet Vybrid can boot.
> 
> Yes, I agree on that. Also the boot data seems not to have the 8-byte
> alignment requirement (see the graphics I posted on the Freescale
> community article).
> 
> > To me, this proves that the size alignment problem is not with
> > boot_data_t but with the overall header.
> 
> I agree. Still, boot_data_t is the "offender", hence I would prefer that
> solution over your solution.
> 
> > If Stefan would test my patch as well, I reckon he would find it to
> > work as well as his.
> > 
> > So we have two patches which fix Vybrid booting:
> > 
> > - one which aligns the boot_data_t /size/ but keeps its /offset/
> >   unaligned;
> > 
> > - one which aligns the the boot_data_t /offset/ but keeps its /size/
> >   unaligned.
> 
> I don't get this classification. The complete header struct shows that
> dcd_v2_t is _after_ boot_data_t.
> 
> typedef struct {
> 	flash_header_v2_t fhdr;
> 	boot_data_t boot_data;
> 	dcd_v2_t dcd_table;
> } imx_header_v2_t;
> 
> Your patch changes the size of dcd_v2_t, hence compensating the
> "unaligned" size of boot_data_t.

Compensating the unaligned size of the overall header for sure, since
I'm adding a last field in the last structure. But precisely since I'm
adding 4 bytes at the very end of the construct, we cannot tell whether
I fixed the 'size' of the flash header, boot data or DCD.

What we can tell, though, is that Vybrid will boot as long as we
increase the size of the overall header to an 8-byte boundary, and also
that it will boot regardless to whether these 4 bytes are added between
boot data and DCD or after DCD.

(note, btw, that in the Vybrid RM, the IVT itself, and the DCD, contain
their own size explicitly in their tag-length-version headers, but the
boot data does not contain its own size, nor is it contained elsewhere.
What we call 'the size of the boot data' is 'the difference between the
boot data and dcd addresses', but that's a definition for convenience.)

> As far as I see we have these two patches which fix Vybrid booting:
> 
> - one which changes the boot_data_t /size/ which keeps the offset
>   of dcd_v2_t and the image aligned.
> 
> - one which changes the dcd_v2_t /size/ which compensates the unaligned
>   size of boot_data_t and keeps the image aligned.
>  
> > Seems to me that the conclusion is that the actual alignment of
> > boot_data_t does not matter and that only the alignment of the
> > whole imx_header_v2_t size (and, consequently, offset) matters.
> > 
> > How about just adding an attribute((align(8))) to imx_header_v2_t?
> 
> Hm this sounds tempting, but it does not seem to work here. I think
> because it only aligns the beginning of imx_header_v2_t in to 8-byte,
> however it does not align the size of the whole struct to 8 bytes, I
> guess? Hence the header size is still "unaligned".

Correct -- my fault, this aligns the address, not size, and there is
no attribute that will control size alignment.

So we really need to add manual padding.

And if we want to not introduce any artificial constaints, I suggest we
define the padding as a separate field in the overall structure, i.e.:

typedef struct {
        flash_header_v2_t fhdr;
        boot_data_t boot_data;
        dcd_v2_t dcd_table;
	uint32_t padding; /* make size an 8-byte multiple */
} imx_header_v2_t;

I think this is the 'least inexact' solution: it does not enforce any
address or size alignment constraint that is not defined in the RM, and
it does show that the constraint is not on the boot data or DCD but on
the header as a whole.

Functionally, it is identical to what I did, so I'm pretty sure it
works. :)

> >> It remains doubious how the ROMs on Freescale are interpretating the
> >> header, but we can only test it.
> > 
> > See my other answer. We could prove it by disassembling the ROM code.
> > Any volunteer? :)
> 
> Hehe, not me :-)

:)

> --
> Stefan

Amicalement,
-- 
Albert.

^ permalink raw reply	[flat|nested] 24+ messages in thread

* [U-Boot] [PATCH 4/5] tools: mkimage: fix imximage header size
  2015-07-15 11:44                   ` Albert ARIBAUD
@ 2015-07-15 12:36                     ` Stefan Agner
  2015-07-15 12:54                       ` Albert ARIBAUD
  0 siblings, 1 reply; 24+ messages in thread
From: Stefan Agner @ 2015-07-15 12:36 UTC (permalink / raw)
  To: u-boot

On 2015-07-15 13:44, Albert ARIBAUD wrote:
> Hello Stefan (and sorry for the duplicate),
> 
> On Wed, 15 Jul 2015 12:41:59 +0200, Stefan Agner <stefan@agner.ch>
> wrote:
>> Hi Albert,
>>
>> On 2015-07-15 09:54, Albert ARIBAUD wrote:
>> > Hello Stefano,
>> >
>> > On Wed, 15 Jul 2015 09:19:55 +0200, Stefano Babic <sbabic@denx.de>
>> > wrote:
>> >
>> >> > I think my patch back then solves the issue nicer. The struct dcd_v2_t
>> >> > is not the reason the whole header is not aligned by 8-byte, it is a
>> >> > problem of the boot_data_t header which is 12 bytes long. So inserting
>> >> > the padding just after struct boot_data_t (or inside of struct
>> >> > boot_data_t) seems to be more appropriate.
>> >>
>> >> I see. Albert, can you test on your board if Stefan's patch solves your
>> >> issue, too ? I could then revert this one and apply Stefan's.
>> >
>> > I can test it, but I'm sure that boot data does not need size alignment
>> > since in my case there is no such alignment and Vybrid boots. To me
>> > this means aligning boot_data_t size would introduce a constraint that
>> > is not really there.
>>
>> I quote here from both emails, since its about the same topic.
>>
>> > After reading the U-Boot and Freescale discussions, IIUC you have come
>> > to the conclusion that the missing 4 bytes were in boot_data_t because
>> > it was the only structure in the header which was not 8-bytes-aligned.
>> >
>> > However, the available documentation does not specify this constraint,
>> > and from a more experimental vewpoint, my patch adds 4 bytes at the end
>> > of the overall header, thus leaving boot data at 12 bytes (therefore
>> > leaving the dcd_table not 8-byte-aligned) and yet Vybrid can boot.
>>
>> Yes, I agree on that. Also the boot data seems not to have the 8-byte
>> alignment requirement (see the graphics I posted on the Freescale
>> community article).
>>
>> > To me, this proves that the size alignment problem is not with
>> > boot_data_t but with the overall header.
>>
>> I agree. Still, boot_data_t is the "offender", hence I would prefer that
>> solution over your solution.
>>
>> > If Stefan would test my patch as well, I reckon he would find it to
>> > work as well as his.
>> >
>> > So we have two patches which fix Vybrid booting:
>> >
>> > - one which aligns the boot_data_t /size/ but keeps its /offset/
>> >   unaligned;
>> >
>> > - one which aligns the the boot_data_t /offset/ but keeps its /size/
>> >   unaligned.
>>
>> I don't get this classification. The complete header struct shows that
>> dcd_v2_t is _after_ boot_data_t.
>>
>> typedef struct {
>> 	flash_header_v2_t fhdr;
>> 	boot_data_t boot_data;
>> 	dcd_v2_t dcd_table;
>> } imx_header_v2_t;
>>
>> Your patch changes the size of dcd_v2_t, hence compensating the
>> "unaligned" size of boot_data_t.
> 
> Compensating the unaligned size of the overall header for sure, since
> I'm adding a last field in the last structure. But precisely since I'm
> adding 4 bytes at the very end of the construct, we cannot tell whether
> I fixed the 'size' of the flash header, boot data or DCD.
> 
> What we can tell, though, is that Vybrid will boot as long as we
> increase the size of the overall header to an 8-byte boundary, and also
> that it will boot regardless to whether these 4 bytes are added between
> boot data and DCD or after DCD.
> 
> (note, btw, that in the Vybrid RM, the IVT itself, and the DCD, contain
> their own size explicitly in their tag-length-version headers, but the
> boot data does not contain its own size, nor is it contained elsewhere.
> What we call 'the size of the boot data' is 'the difference between the
> boot data and dcd addresses', but that's a definition for convenience.)

Good point, agreed.

>> As far as I see we have these two patches which fix Vybrid booting:
>>
>> - one which changes the boot_data_t /size/ which keeps the offset
>>   of dcd_v2_t and the image aligned.
>>
>> - one which changes the dcd_v2_t /size/ which compensates the unaligned
>>   size of boot_data_t and keeps the image aligned.
>>
>> > Seems to me that the conclusion is that the actual alignment of
>> > boot_data_t does not matter and that only the alignment of the
>> > whole imx_header_v2_t size (and, consequently, offset) matters.
>> >
>> > How about just adding an attribute((align(8))) to imx_header_v2_t?
>>
>> Hm this sounds tempting, but it does not seem to work here. I think
>> because it only aligns the beginning of imx_header_v2_t in to 8-byte,
>> however it does not align the size of the whole struct to 8 bytes, I
>> guess? Hence the header size is still "unaligned".
> 
> Correct -- my fault, this aligns the address, not size, and there is
> no attribute that will control size alignment.

Actually I just discovered that "aligned" also changes the size (make
sure using the correct syntax "__attribute__((aligned(8)))").

However, imximage.c seems to do some calculations using sizeof(struct
imx_header) and sizeof(imx_header_v2_t) which lead to this error
message:
./tools/mkimage: header error

Adding __attribute__((aligned(8))) to struct imx_header seems not to
alleviate the problem... Any idea?

> 
> So we really need to add manual padding.
> 
> And if we want to not introduce any artificial constaints, I suggest we
> define the padding as a separate field in the overall structure, i.e.:
> 
> typedef struct {
>         flash_header_v2_t fhdr;
>         boot_data_t boot_data;
>         dcd_v2_t dcd_table;
> 	uint32_t padding; /* make size an 8-byte multiple */
> } imx_header_v2_t;

That change would also sound good to me.

> 
> I think this is the 'least inexact' solution: it does not enforce any
> address or size alignment constraint that is not defined in the RM, and
> it does show that the constraint is not on the boot data or DCD but on
> the header as a whole.
> 
> Functionally, it is identical to what I did, so I'm pretty sure it
> works. :)

Agreed.

--
Stefan

^ permalink raw reply	[flat|nested] 24+ messages in thread

* [U-Boot] [PATCH 4/5] tools: mkimage: fix imximage header size
  2015-07-15 12:36                     ` Stefan Agner
@ 2015-07-15 12:54                       ` Albert ARIBAUD
  0 siblings, 0 replies; 24+ messages in thread
From: Albert ARIBAUD @ 2015-07-15 12:54 UTC (permalink / raw)
  To: u-boot

Hello Stefan,

On Wed, 15 Jul 2015 14:36:16 +0200, Stefan Agner <stefan@agner.ch>
wrote:

> >> As far as I see we have these two patches which fix Vybrid booting:
> >>
> >> - one which changes the boot_data_t /size/ which keeps the offset
> >>   of dcd_v2_t and the image aligned.
> >>
> >> - one which changes the dcd_v2_t /size/ which compensates the unaligned
> >>   size of boot_data_t and keeps the image aligned.
> >>
> >> > Seems to me that the conclusion is that the actual alignment of
> >> > boot_data_t does not matter and that only the alignment of the
> >> > whole imx_header_v2_t size (and, consequently, offset) matters.
> >> >
> >> > How about just adding an attribute((align(8))) to imx_header_v2_t?
> >>
> >> Hm this sounds tempting, but it does not seem to work here. I think
> >> because it only aligns the beginning of imx_header_v2_t in to 8-byte,
> >> however it does not align the size of the whole struct to 8 bytes, I
> >> guess? Hence the header size is still "unaligned".
> > 
> > Correct -- my fault, this aligns the address, not size, and there is
> > no attribute that will control size alignment.
> 
> Actually I just discovered that "aligned" also changes the size (make
> sure using the correct syntax "__attribute__((aligned(8)))").

Does it? Then I too was under the same misconception that it did not.

> However, imximage.c seems to do some calculations using sizeof(struct
> imx_header) and sizeof(imx_header_v2_t) which lead to this error
> message:
> ./tools/mkimage: header error
> 
> Adding __attribute__((aligned(8))) to struct imx_header seems not to
> alleviate the problem... Any idea?
>
> > So we really need to add manual padding.
> > 
> > And if we want to not introduce any artificial constaints, I suggest we
> > define the padding as a separate field in the overall structure, i.e.:
> > 
> > typedef struct {
> >         flash_header_v2_t fhdr;
> >         boot_data_t boot_data;
> >         dcd_v2_t dcd_table;
> > 	uint32_t padding; /* make size an 8-byte multiple */
> > } imx_header_v2_t;
> 
> That change would also sound good to me.
> 
> > 
> > I think this is the 'least inexact' solution: it does not enforce any
> > address or size alignment constraint that is not defined in the RM, and
> > it does show that the constraint is not on the boot data or DCD but on
> > the header as a whole.
> > 
> > Functionally, it is identical to what I did, so I'm pretty sure it
> > works. :)
> 
> Agreed.

Ok, so let me look into the __attribute__((aligned(8))) issue. If that
can be solved, I would give it my preference; if it cannot, then I will
settle for manually padding the end of imx_header_v2_t.

> --
> Stefan

Amicalement,
-- 
Albert.

^ permalink raw reply	[flat|nested] 24+ messages in thread

end of thread, other threads:[~2015-07-15 12:54 UTC | newest]

Thread overview: 24+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2015-06-19 12:18 [U-Boot] [PATCH 0/5] Add support for Vybrid VF610-based PCM052 Albert ARIBAUD
2015-06-19 12:18 ` [U-Boot] [PATCH 1/5] net: fec_mxc: remove useless struct nbuf Albert ARIBAUD
2015-06-19 12:18   ` [U-Boot] [PATCH 2/5] vf610: refactor DDRMC code Albert ARIBAUD
2015-06-19 12:18     ` [U-Boot] [PATCH 3/5] i2c: fix vf610 support Albert ARIBAUD
2015-06-19 12:18       ` [U-Boot] [PATCH 4/5] tools: mkimage: fix imximage header size Albert ARIBAUD
2015-06-19 12:18         ` [U-Boot] [PATCH 5/5] vf610: add support for Phytec PCM052 Albert ARIBAUD
2015-07-10  8:14         ` [U-Boot] [PATCH 4/5] tools: mkimage: fix imximage header size Stefano Babic
2015-07-14 10:29           ` Stefan Agner
2015-07-15  7:19             ` Stefano Babic
2015-07-15  7:54               ` Albert ARIBAUD
2015-07-15 10:41                 ` Stefan Agner
2015-07-15 11:44                   ` Albert ARIBAUD
2015-07-15 12:36                     ` Stefan Agner
2015-07-15 12:54                       ` Albert ARIBAUD
2015-07-15  7:37             ` Albert ARIBAUD
2015-07-10  8:11       ` [U-Boot] [PATCH 3/5] i2c: fix vf610 support Stefano Babic
2015-06-19 15:13     ` [U-Boot] [PATCH 2/5] vf610: refactor DDRMC code Stefan Agner
2015-06-19 16:50       ` Albert ARIBAUD
2015-06-19 17:33       ` Albert ARIBAUD
2015-07-10  8:09         ` Stefano Babic
2015-07-13 19:01           ` Stefan Agner
2015-07-14  7:16             ` [U-Boot] (rather [LONG], sorry) " Albert ARIBAUD
2015-06-19 15:38   ` [U-Boot] [PATCH 1/5] net: fec_mxc: remove useless struct nbuf Joe Hershberger
2015-07-10  8:03   ` Stefano Babic

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.