summaryrefslogtreecommitdiff
path: root/arch/arm/cpu/armv7
diff options
context:
space:
mode:
authorMasahiro Yamada <yamada.m@jp.panasonic.com>2014-12-19 20:20:52 +0900
committerMasahiro Yamada <yamada.m@jp.panasonic.com>2014-12-30 17:45:25 +0900
commitb614e16cc07113dc890ecc83649b89da1bced464 (patch)
treecb5c47751c4dfb9bd886846c0ee20f7faea3c4da /arch/arm/cpu/armv7
parent125738e819a3b9d15210794b3dcef9f4d9bcf866 (diff)
downloadu-boot-imx-b614e16cc07113dc890ecc83649b89da1bced464.zip
u-boot-imx-b614e16cc07113dc890ecc83649b89da1bced464.tar.gz
u-boot-imx-b614e16cc07113dc890ecc83649b89da1bced464.tar.bz2
ARM: UniPhier: add DDR PHY training code
This training code provides run-time adjustment of DDR PHY parameters for stable DDR operation. Signed-off-by: Masahiro Yamada <yamada.m@jp.panasonic.com>
Diffstat (limited to 'arch/arm/cpu/armv7')
-rw-r--r--arch/arm/cpu/armv7/uniphier/Makefile1
-rw-r--r--arch/arm/cpu/armv7/uniphier/ddrphy_training.c144
-rw-r--r--arch/arm/cpu/armv7/uniphier/ph1-ld4/Makefile2
-rw-r--r--arch/arm/cpu/armv7/uniphier/ph1-ld4/ddrphy_init.c70
-rw-r--r--arch/arm/cpu/armv7/uniphier/ph1-ld4/umc_init.c13
-rw-r--r--arch/arm/cpu/armv7/uniphier/ph1-pro4/Makefile2
-rw-r--r--arch/arm/cpu/armv7/uniphier/ph1-pro4/ddrphy_init.c70
-rw-r--r--arch/arm/cpu/armv7/uniphier/ph1-pro4/umc_init.c25
-rw-r--r--arch/arm/cpu/armv7/uniphier/ph1-sld8/Makefile2
-rw-r--r--arch/arm/cpu/armv7/uniphier/ph1-sld8/ddrphy_init.c75
-rw-r--r--arch/arm/cpu/armv7/uniphier/ph1-sld8/umc_init.c13
11 files changed, 414 insertions, 3 deletions
diff --git a/arch/arm/cpu/armv7/uniphier/Makefile b/arch/arm/cpu/armv7/uniphier/Makefile
index 4a7b8a9..1d84696 100644
--- a/arch/arm/cpu/armv7/uniphier/Makefile
+++ b/arch/arm/cpu/armv7/uniphier/Makefile
@@ -10,6 +10,7 @@ obj-y += reset.o
obj-y += cache_uniphier.o
obj-$(CONFIG_BOARD_POSTCLK_INIT) += board_postclk_init.o
obj-y += dram_init.o
+obj-$(CONFIG_DRAM_INIT) += ddrphy_training.o
obj-$(CONFIG_DISPLAY_CPUINFO) += cpu_info.o
obj-$(CONFIG_BOARD_EARLY_INIT_R) += board_early_init_r.o
obj-$(CONFIG_BOARD_LATE_INIT) += board_late_init.o
diff --git a/arch/arm/cpu/armv7/uniphier/ddrphy_training.c b/arch/arm/cpu/armv7/uniphier/ddrphy_training.c
new file mode 100644
index 0000000..cc8b8ad
--- /dev/null
+++ b/arch/arm/cpu/armv7/uniphier/ddrphy_training.c
@@ -0,0 +1,144 @@
+/*
+ * Copyright (C) 2011-2014 Panasonic Corporation
+ * Author: Masahiro Yamada <yamada.m@jp.panasonic.com>
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+#include <common.h>
+#include <asm/io.h>
+#include <asm/arch/ddrphy-regs.h>
+
+void ddrphy_prepare_training(struct ddrphy __iomem *phy, int rank)
+{
+ int dx;
+ u32 __iomem tmp, *p;
+
+ for (dx = 0; dx < NR_DATX8_PER_DDRPHY; dx++) {
+ p = &phy->dx[dx].gcr;
+
+ tmp = readl(p);
+ /* Specify the rank that should be write leveled */
+ tmp &= ~DXGCR_WLRKEN_MASK;
+ tmp |= (1 << (DXGCR_WLRKEN_SHIFT + rank)) & DXGCR_WLRKEN_MASK;
+ writel(tmp, p);
+ }
+
+ p = &phy->dtcr;
+
+ tmp = readl(p);
+ /* Specify the rank used during data bit deskew and eye centering */
+ tmp &= ~DTCR_DTRANK_MASK;
+ tmp |= (rank << DTCR_DTRANK_SHIFT) & DTCR_DTRANK_MASK;
+ /* Use Multi-Purpose Register for DQS gate training */
+ tmp |= DTCR_DTMPR;
+ /* Specify the rank enabled for data-training */
+ tmp &= ~DTCR_RNKEN_MASK;
+ tmp |= (1 << (DTCR_RNKEN_SHIFT + rank)) & DTCR_RNKEN_MASK;
+ writel(tmp, p);
+}
+
+struct ddrphy_init_sequence {
+ char *description;
+ u32 init_flag;
+ u32 done_flag;
+ u32 err_flag;
+};
+
+static struct ddrphy_init_sequence init_sequence[] = {
+ {
+ "DRAM Initialization",
+ PIR_DRAMRST | PIR_DRAMINIT,
+ PGSR0_DIDONE,
+ PGSR0_DIERR
+ },
+ {
+ "Write Leveling",
+ PIR_WL,
+ PGSR0_WLDONE,
+ PGSR0_WLERR
+ },
+ {
+ "Read DQS Gate Training",
+ PIR_QSGATE,
+ PGSR0_QSGDONE,
+ PGSR0_QSGERR
+ },
+ {
+ "Write Leveling Adjustment",
+ PIR_WLADJ,
+ PGSR0_WLADONE,
+ PGSR0_WLAERR
+ },
+ {
+ "Read Bit Deskew",
+ PIR_RDDSKW,
+ PGSR0_RDDONE,
+ PGSR0_RDERR
+ },
+ {
+ "Write Bit Deskew",
+ PIR_WRDSKW,
+ PGSR0_WDDONE,
+ PGSR0_WDERR
+ },
+ {
+ "Read Eye Training",
+ PIR_RDEYE,
+ PGSR0_REDONE,
+ PGSR0_REERR
+ },
+ {
+ "Write Eye Training",
+ PIR_WREYE,
+ PGSR0_WEDONE,
+ PGSR0_WEERR
+ }
+};
+
+int ddrphy_training(struct ddrphy __iomem *phy)
+{
+ int i;
+ u32 pgsr0;
+ u32 init_flag = PIR_INIT;
+ u32 done_flag = PGSR0_IDONE;
+ int timeout = 50000; /* 50 msec is long enough */
+#ifdef DISPLAY_ELAPSED_TIME
+ ulong start = get_timer(0);
+#endif
+
+ for (i = 0; i < ARRAY_SIZE(init_sequence); i++) {
+ init_flag |= init_sequence[i].init_flag;
+ done_flag |= init_sequence[i].done_flag;
+ }
+
+ writel(init_flag, &phy->pir);
+
+ do {
+ if (--timeout < 0) {
+#ifndef CONFIG_SPL_BUILD
+ printf("%s: error: timeout during DDR training\n",
+ __func__);
+#endif
+ return -1;
+ }
+ udelay(1);
+ pgsr0 = readl(&phy->pgsr[0]);
+ } while ((pgsr0 & done_flag) != done_flag);
+
+ for (i = 0; i < ARRAY_SIZE(init_sequence); i++) {
+ if (pgsr0 & init_sequence[i].err_flag) {
+#ifndef CONFIG_SPL_BUILD
+ printf("%s: error: %s failed\n", __func__,
+ init_sequence[i].description);
+#endif
+ return -1;
+ }
+ }
+
+#ifdef DISPLAY_ELAPSED_TIME
+ printf("%s: info: elapsed time %ld msec\n", get_timer(start));
+#endif
+
+ return 0;
+}
diff --git a/arch/arm/cpu/armv7/uniphier/ph1-ld4/Makefile b/arch/arm/cpu/armv7/uniphier/ph1-ld4/Makefile
index 5d682d3..8794629 100644
--- a/arch/arm/cpu/armv7/uniphier/ph1-ld4/Makefile
+++ b/arch/arm/cpu/armv7/uniphier/ph1-ld4/Makefile
@@ -8,4 +8,4 @@ obj-y += boot-mode.o
obj-$(CONFIG_SOC_INIT) += bcu_init.o sbc_init.o sg_init.o pll_init.o \
clkrst_init.o
obj-$(CONFIG_BOARD_POSTCLK_INIT) += pinctrl.o
-obj-$(CONFIG_DRAM_INIT) += pll_spectrum.o umc_init.o
+obj-$(CONFIG_DRAM_INIT) += pll_spectrum.o umc_init.o ddrphy_init.o
diff --git a/arch/arm/cpu/armv7/uniphier/ph1-ld4/ddrphy_init.c b/arch/arm/cpu/armv7/uniphier/ph1-ld4/ddrphy_init.c
new file mode 100644
index 0000000..60fc5ad
--- /dev/null
+++ b/arch/arm/cpu/armv7/uniphier/ph1-ld4/ddrphy_init.c
@@ -0,0 +1,70 @@
+/*
+ * Copyright (C) 2014 Panasonic Corporation
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+#include <linux/types.h>
+#include <asm/io.h>
+#include <asm/arch/ddrphy-regs.h>
+
+void ddrphy_init(struct ddrphy __iomem *phy, int freq, int size)
+{
+ u32 tmp;
+
+ writel(0x0300c473, &phy->pgcr[1]);
+ if (freq == 1333) {
+ writel(0x0a806844, &phy->ptr[0]);
+ writel(0x208e0124, &phy->ptr[1]);
+ } else {
+ writel(0x0c807d04, &phy->ptr[0]);
+ writel(0x2710015E, &phy->ptr[1]);
+ }
+ writel(0x00083DEF, &phy->ptr[2]);
+ if (freq == 1333) {
+ writel(0x0f051616, &phy->ptr[3]);
+ writel(0x06ae08d6, &phy->ptr[4]);
+ } else {
+ writel(0x12061A80, &phy->ptr[3]);
+ writel(0x08027100, &phy->ptr[4]);
+ }
+ writel(0xF004001A, &phy->dsgcr);
+
+ /* change the value of the on-die pull-up/pull-down registors */
+ tmp = readl(&phy->dxccr);
+ tmp &= ~0x0ee0;
+ tmp |= DXCCR_DQSNRES_688_OHM | DXCCR_DQSRES_688_OHM;
+ writel(tmp, &phy->dxccr);
+
+ writel(0x0000040B, &phy->dcr);
+ if (freq == 1333) {
+ writel(0x85589955, &phy->dtpr[0]);
+ if (size == 1)
+ writel(0x1a8253c0, &phy->dtpr[1]);
+ else
+ writel(0x1a8363c0, &phy->dtpr[1]);
+ writel(0x5002c200, &phy->dtpr[2]);
+ writel(0x00000b51, &phy->mr0);
+ } else {
+ writel(0x999cbb66, &phy->dtpr[0]);
+ if (size == 1)
+ writel(0x1a82dbc0, &phy->dtpr[1]);
+ else
+ writel(0x1a878400, &phy->dtpr[1]);
+ writel(0xa00214f8, &phy->dtpr[2]);
+ writel(0x00000d71, &phy->mr0);
+ }
+ writel(0x00000006, &phy->mr1);
+ if (freq == 1333)
+ writel(0x00000290, &phy->mr2);
+ else
+ writel(0x00000298, &phy->mr2);
+
+ writel(0x00000800, &phy->mr3);
+
+ while (!(readl(&phy->pgsr[0]) & PGSR0_IDONE))
+ ;
+
+ writel(0x0300C473, &phy->pgcr[1]);
+ writel(0x0000005D, &phy->zq[0].cr[1]);
+}
diff --git a/arch/arm/cpu/armv7/uniphier/ph1-ld4/umc_init.c b/arch/arm/cpu/armv7/uniphier/ph1-ld4/umc_init.c
index ebcbaab..8788916 100644
--- a/arch/arm/cpu/armv7/uniphier/ph1-ld4/umc_init.c
+++ b/arch/arm/cpu/armv7/uniphier/ph1-ld4/umc_init.c
@@ -7,6 +7,7 @@
#include <common.h>
#include <asm/io.h>
#include <asm/arch/umc-regs.h>
+#include <asm/arch/ddrphy-regs.h>
static inline void umc_start_ssif(void __iomem *ssif_base)
{
@@ -125,6 +126,8 @@ static inline int umc_init_sub(int freq, int size_ch0, int size_ch1)
void __iomem *ca_base1 = (void __iomem *)UMC_CA_BASE(1);
void __iomem *dramcont0 = (void __iomem *)UMC_DRAMCONT_BASE(0);
void __iomem *dramcont1 = (void __iomem *)UMC_DRAMCONT_BASE(1);
+ void __iomem *phy0_0 = (void __iomem *)DDRPHY_BASE(0, 0);
+ void __iomem *phy1_0 = (void __iomem *)DDRPHY_BASE(1, 0);
umc_dram_init_start(dramcont0);
umc_dram_init_start(dramcont1);
@@ -133,8 +136,18 @@ static inline int umc_init_sub(int freq, int size_ch0, int size_ch1)
writel(0x00000101, dramcont0 + UMC_DIOCTLA);
+ ddrphy_init(phy0_0, freq, size_ch0);
+
+ ddrphy_prepare_training(phy0_0, 0);
+ ddrphy_training(phy0_0);
+
writel(0x00000101, dramcont1 + UMC_DIOCTLA);
+ ddrphy_init(phy1_0, freq, size_ch1);
+
+ ddrphy_prepare_training(phy1_0, 1);
+ ddrphy_training(phy1_0);
+
umc_dramcont_init(dramcont0, ca_base0, size_ch0, freq);
umc_dramcont_init(dramcont1, ca_base1, size_ch1, freq);
diff --git a/arch/arm/cpu/armv7/uniphier/ph1-pro4/Makefile b/arch/arm/cpu/armv7/uniphier/ph1-pro4/Makefile
index fd1c432..cee7878 100644
--- a/arch/arm/cpu/armv7/uniphier/ph1-pro4/Makefile
+++ b/arch/arm/cpu/armv7/uniphier/ph1-pro4/Makefile
@@ -7,4 +7,4 @@ obj-$(if $(CONFIG_OF_CONTROL),,y) += platdevice.o
obj-y += boot-mode.o
obj-$(CONFIG_SOC_INIT) += sbc_init.o sg_init.o pll_init.o clkrst_init.o
obj-$(CONFIG_BOARD_POSTCLK_INIT) += pinctrl.o
-obj-$(CONFIG_DRAM_INIT) += pll_spectrum.o umc_init.o
+obj-$(CONFIG_DRAM_INIT) += pll_spectrum.o umc_init.o ddrphy_init.o
diff --git a/arch/arm/cpu/armv7/uniphier/ph1-pro4/ddrphy_init.c b/arch/arm/cpu/armv7/uniphier/ph1-pro4/ddrphy_init.c
new file mode 100644
index 0000000..c5d1f60
--- /dev/null
+++ b/arch/arm/cpu/armv7/uniphier/ph1-pro4/ddrphy_init.c
@@ -0,0 +1,70 @@
+/*
+ * Copyright (C) 2014 Panasonic Corporation
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+#include <linux/types.h>
+#include <asm/io.h>
+#include <asm/arch/ddrphy-regs.h>
+
+void ddrphy_init(struct ddrphy __iomem *phy, int freq, int size)
+{
+ u32 tmp;
+
+ writel(0x0300c473, &phy->pgcr[1]);
+ if (freq == 1333) {
+ writel(0x0a806844, &phy->ptr[0]);
+ writel(0x208e0124, &phy->ptr[1]);
+ } else {
+ writel(0x0c807d04, &phy->ptr[0]);
+ writel(0x2710015E, &phy->ptr[1]);
+ }
+ writel(0x00083DEF, &phy->ptr[2]);
+ if (freq == 1333) {
+ writel(0x0f051616, &phy->ptr[3]);
+ writel(0x06ae08d6, &phy->ptr[4]);
+ } else {
+ writel(0x12061A80, &phy->ptr[3]);
+ writel(0x08027100, &phy->ptr[4]);
+ }
+ writel(0xF004001A, &phy->dsgcr);
+
+ /* change the value of the on-die pull-up/pull-down registors */
+ tmp = readl(&phy->dxccr);
+ tmp &= ~0x0ee0;
+ tmp |= DXCCR_DQSNRES_688_OHM | DXCCR_DQSRES_688_OHM;
+ writel(tmp, &phy->dxccr);
+
+ writel(0x0000040B, &phy->dcr);
+ if (freq == 1333) {
+ writel(0x85589955, &phy->dtpr[0]);
+ if (size == 1)
+ writel(0x1a8363c0, &phy->dtpr[1]);
+ else
+ writel(0x1a8363c0, &phy->dtpr[1]);
+ writel(0x5002c200, &phy->dtpr[2]);
+ writel(0x00000b51, &phy->mr0);
+ } else {
+ writel(0x999cbb66, &phy->dtpr[0]);
+ if (size == 1)
+ writel(0x1a878400, &phy->dtpr[1]);
+ else
+ writel(0x1a878400, &phy->dtpr[1]);
+ writel(0xa00214f8, &phy->dtpr[2]);
+ writel(0x00000d71, &phy->mr0);
+ }
+ writel(0x00000006, &phy->mr1);
+ if (freq == 1333)
+ writel(0x00000290, &phy->mr2);
+ else
+ writel(0x00000298, &phy->mr2);
+
+ writel(0x00000000, &phy->mr3);
+
+ while (!(readl(&phy->pgsr[0]) & PGSR0_IDONE))
+ ;
+
+ writel(0x0300C473, &phy->pgcr[1]);
+ writel(0x0000005D, &phy->zq[0].cr[1]);
+}
diff --git a/arch/arm/cpu/armv7/uniphier/ph1-pro4/umc_init.c b/arch/arm/cpu/armv7/uniphier/ph1-pro4/umc_init.c
index 328b2f4..1973ab0 100644
--- a/arch/arm/cpu/armv7/uniphier/ph1-pro4/umc_init.c
+++ b/arch/arm/cpu/armv7/uniphier/ph1-pro4/umc_init.c
@@ -7,6 +7,7 @@
#include <common.h>
#include <asm/io.h>
#include <asm/arch/umc-regs.h>
+#include <asm/arch/ddrphy-regs.h>
static inline void umc_start_ssif(void __iomem *ssif_base)
{
@@ -94,6 +95,10 @@ static inline int umc_init_sub(int freq, int size_ch0, int size_ch1)
void __iomem *ca_base1 = (void __iomem *)UMC_CA_BASE(1);
void __iomem *dramcont0 = (void __iomem *)UMC_DRAMCONT_BASE(0);
void __iomem *dramcont1 = (void __iomem *)UMC_DRAMCONT_BASE(1);
+ void __iomem *phy0_0 = (void __iomem *)DDRPHY_BASE(0, 0);
+ void __iomem *phy0_1 = (void __iomem *)DDRPHY_BASE(0, 1);
+ void __iomem *phy1_0 = (void __iomem *)DDRPHY_BASE(1, 0);
+ void __iomem *phy1_1 = (void __iomem *)DDRPHY_BASE(1, 1);
umc_dram_init_start(dramcont0);
umc_dram_init_start(dramcont1);
@@ -102,12 +107,32 @@ static inline int umc_init_sub(int freq, int size_ch0, int size_ch1)
writel(0x00000101, dramcont0 + UMC_DIOCTLA);
+ ddrphy_init(phy0_0, freq, size_ch0);
+
+ ddrphy_prepare_training(phy0_0, 0);
+ ddrphy_training(phy0_0);
+
writel(0x00000103, dramcont0 + UMC_DIOCTLA);
+ ddrphy_init(phy0_1, freq, size_ch0);
+
+ ddrphy_prepare_training(phy0_1, 1);
+ ddrphy_training(phy0_1);
+
writel(0x00000101, dramcont1 + UMC_DIOCTLA);
+ ddrphy_init(phy1_0, freq, size_ch1);
+
+ ddrphy_prepare_training(phy1_0, 0);
+ ddrphy_training(phy1_0);
+
writel(0x00000103, dramcont1 + UMC_DIOCTLA);
+ ddrphy_init(phy1_1, freq, size_ch1);
+
+ ddrphy_prepare_training(phy1_1, 1);
+ ddrphy_training(phy1_1);
+
umc_dramcont_init(dramcont0, ca_base0, size_ch0, freq);
umc_dramcont_init(dramcont1, ca_base1, size_ch1, freq);
diff --git a/arch/arm/cpu/armv7/uniphier/ph1-sld8/Makefile b/arch/arm/cpu/armv7/uniphier/ph1-sld8/Makefile
index 5d682d3..8794629 100644
--- a/arch/arm/cpu/armv7/uniphier/ph1-sld8/Makefile
+++ b/arch/arm/cpu/armv7/uniphier/ph1-sld8/Makefile
@@ -8,4 +8,4 @@ obj-y += boot-mode.o
obj-$(CONFIG_SOC_INIT) += bcu_init.o sbc_init.o sg_init.o pll_init.o \
clkrst_init.o
obj-$(CONFIG_BOARD_POSTCLK_INIT) += pinctrl.o
-obj-$(CONFIG_DRAM_INIT) += pll_spectrum.o umc_init.o
+obj-$(CONFIG_DRAM_INIT) += pll_spectrum.o umc_init.o ddrphy_init.o
diff --git a/arch/arm/cpu/armv7/uniphier/ph1-sld8/ddrphy_init.c b/arch/arm/cpu/armv7/uniphier/ph1-sld8/ddrphy_init.c
new file mode 100644
index 0000000..a5eafef
--- /dev/null
+++ b/arch/arm/cpu/armv7/uniphier/ph1-sld8/ddrphy_init.c
@@ -0,0 +1,75 @@
+/*
+ * Copyright (C) 2014 Panasonic Corporation
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+#include <config.h>
+#include <linux/types.h>
+#include <asm/io.h>
+#include <asm/arch/ddrphy-regs.h>
+
+void ddrphy_init(struct ddrphy __iomem *phy, int freq, int size)
+{
+ u32 tmp;
+
+ writel(0x0300c473, &phy->pgcr[1]);
+ if (freq == 1333) {
+ writel(0x0a806844, &phy->ptr[0]);
+ writel(0x208e0124, &phy->ptr[1]);
+ } else {
+ writel(0x0c807d04, &phy->ptr[0]);
+ writel(0x2710015E, &phy->ptr[1]);
+ }
+ writel(0x00083DEF, &phy->ptr[2]);
+ if (freq == 1333) {
+ writel(0x0f051616, &phy->ptr[3]);
+ writel(0x06ae08d6, &phy->ptr[4]);
+ } else {
+ writel(0x12061A80, &phy->ptr[3]);
+ writel(0x08027100, &phy->ptr[4]);
+ }
+ writel(0xF004001A, &phy->dsgcr);
+
+ /* change the value of the on-die pull-up/pull-down registors */
+ tmp = readl(&phy->dxccr);
+ tmp &= ~0x0ee0;
+ tmp |= DXCCR_DQSNRES_688_OHM | DXCCR_DQSRES_688_OHM;
+ writel(tmp, &phy->dxccr);
+
+ writel(0x0000040B, &phy->dcr);
+ if (freq == 1333) {
+ writel(0x85589955, &phy->dtpr[0]);
+ if (size == 1)
+ writel(0x1a8363c0, &phy->dtpr[1]);
+ else
+ writel(0x1a8363c0, &phy->dtpr[1]);
+ writel(0x5002c200, &phy->dtpr[2]);
+ writel(0x00000b51, &phy->mr0);
+ } else {
+ writel(0x999cbb66, &phy->dtpr[0]);
+ if (size == 1)
+ writel(0x1a878400, &phy->dtpr[1]);
+ else
+ writel(0x1a878400, &phy->dtpr[1]);
+ writel(0xa00214f8, &phy->dtpr[2]);
+ writel(0x00000d71, &phy->mr0);
+ }
+ writel(0x00000006, &phy->mr1);
+ if (freq == 1333)
+ writel(0x00000290, &phy->mr2);
+ else
+ writel(0x00000298, &phy->mr2);
+
+#ifdef CONFIG_DDR_STANDARD
+ writel(0x00000000, &phy->mr3);
+#else
+ writel(0x00000800, &phy->mr3);
+#endif
+
+ while (!(readl(&phy->pgsr[0]) & PGSR0_IDONE))
+ ;
+
+ writel(0x0300C473, &phy->pgcr[1]);
+ writel(0x0000005D, &phy->zq[0].cr[1]);
+}
diff --git a/arch/arm/cpu/armv7/uniphier/ph1-sld8/umc_init.c b/arch/arm/cpu/armv7/uniphier/ph1-sld8/umc_init.c
index a44f999..2e0f9ae 100644
--- a/arch/arm/cpu/armv7/uniphier/ph1-sld8/umc_init.c
+++ b/arch/arm/cpu/armv7/uniphier/ph1-sld8/umc_init.c
@@ -7,6 +7,7 @@
#include <common.h>
#include <asm/io.h>
#include <asm/arch/umc-regs.h>
+#include <asm/arch/ddrphy-regs.h>
static inline void umc_start_ssif(void __iomem *ssif_base)
{
@@ -105,6 +106,8 @@ static inline int umc_init_sub(int freq, int size_ch0, int size_ch1)
void __iomem *ca_base1 = (void __iomem *)UMC_CA_BASE(1);
void __iomem *dramcont0 = (void __iomem *)UMC_DRAMCONT_BASE(0);
void __iomem *dramcont1 = (void __iomem *)UMC_DRAMCONT_BASE(1);
+ void __iomem *phy0_0 = (void __iomem *)DDRPHY_BASE(0, 0);
+ void __iomem *phy1_0 = (void __iomem *)DDRPHY_BASE(1, 0);
umc_dram_init_start(dramcont0);
umc_dram_init_start(dramcont1);
@@ -113,8 +116,18 @@ static inline int umc_init_sub(int freq, int size_ch0, int size_ch1)
writel(0x00000101, dramcont0 + UMC_DIOCTLA);
+ ddrphy_init(phy0_0, freq, size_ch0);
+
+ ddrphy_prepare_training(phy0_0, 0);
+ ddrphy_training(phy0_0);
+
writel(0x00000101, dramcont1 + UMC_DIOCTLA);
+ ddrphy_init(phy1_0, freq, size_ch1);
+
+ ddrphy_prepare_training(phy1_0, 1);
+ ddrphy_training(phy1_0);
+
umc_dramcont_init(dramcont0, ca_base0, size_ch0, freq);
umc_dramcont_init(dramcont1, ca_base1, size_ch1, freq);