summaryrefslogtreecommitdiff
path: root/arch/arm/mach-uniphier/dram
diff options
context:
space:
mode:
Diffstat (limited to 'arch/arm/mach-uniphier/dram')
-rw-r--r--arch/arm/mach-uniphier/dram/Makefile4
-rw-r--r--arch/arm/mach-uniphier/dram/ddrphy-ph1-ld4.c80
-rw-r--r--arch/arm/mach-uniphier/dram/ddrphy-ph1-pro4.c67
-rw-r--r--arch/arm/mach-uniphier/dram/ddrphy-ph1-sld8.c78
-rw-r--r--arch/arm/mach-uniphier/dram/ddrphy-regs.h5
-rw-r--r--arch/arm/mach-uniphier/dram/umc-ph1-ld4.c225
-rw-r--r--arch/arm/mach-uniphier/dram/umc-ph1-pro4.c182
-rw-r--r--arch/arm/mach-uniphier/dram/umc-ph1-sld8.c218
-rw-r--r--arch/arm/mach-uniphier/dram/umc-proxstream2.c217
-rw-r--r--arch/arm/mach-uniphier/dram/umc-regs.h48
10 files changed, 501 insertions, 623 deletions
diff --git a/arch/arm/mach-uniphier/dram/Makefile b/arch/arm/mach-uniphier/dram/Makefile
index a0a6003..3d1553c 100644
--- a/arch/arm/mach-uniphier/dram/Makefile
+++ b/arch/arm/mach-uniphier/dram/Makefile
@@ -7,9 +7,9 @@ ifdef CONFIG_SPL_BUILD
obj-$(CONFIG_ARCH_UNIPHIER_PH1_LD4) += umc-ph1-ld4.o \
ddrphy-training.o ddrphy-ph1-ld4.o
obj-$(CONFIG_ARCH_UNIPHIER_PH1_PRO4) += umc-ph1-pro4.o \
- ddrphy-training.o ddrphy-ph1-pro4.o
+ ddrphy-training.o ddrphy-ph1-ld4.o
obj-$(CONFIG_ARCH_UNIPHIER_PH1_SLD8) += umc-ph1-sld8.o \
- ddrphy-training.o ddrphy-ph1-sld8.o
+ ddrphy-training.o ddrphy-ph1-ld4.o
obj-$(CONFIG_ARCH_UNIPHIER_PROXSTREAM2) += umc-proxstream2.o
obj-$(CONFIG_ARCH_UNIPHIER_PH1_LD6B) += umc-proxstream2.o
diff --git a/arch/arm/mach-uniphier/dram/ddrphy-ph1-ld4.c b/arch/arm/mach-uniphier/dram/ddrphy-ph1-ld4.c
index d2bc5a1..eb9bf24 100644
--- a/arch/arm/mach-uniphier/dram/ddrphy-ph1-ld4.c
+++ b/arch/arm/mach-uniphier/dram/ddrphy-ph1-ld4.c
@@ -4,31 +4,52 @@
* SPDX-License-Identifier: GPL-2.0+
*/
+#include <common.h>
+#include <linux/err.h>
#include <linux/types.h>
#include <linux/io.h>
#include "ddrphy-regs.h"
-int ph1_ld4_ddrphy_init(struct ddrphy __iomem *phy, int freq, int size)
+enum dram_freq {
+ DRAM_FREQ_1333M,
+ DRAM_FREQ_1600M,
+ DRAM_FREQ_NR,
+};
+
+static u32 ddrphy_ptr0[DRAM_FREQ_NR] = {0x0a806844, 0x0c807d04};
+static u32 ddrphy_ptr1[DRAM_FREQ_NR] = {0x208e0124, 0x2710015E};
+static u32 ddrphy_ptr3[DRAM_FREQ_NR] = {0x0f051616, 0x12061A80};
+static u32 ddrphy_ptr4[DRAM_FREQ_NR] = {0x06ae08d6, 0x08027100};
+static u32 ddrphy_dtpr0[DRAM_FREQ_NR] = {0x85589955, 0x999cbb66};
+static u32 ddrphy_dtpr1[DRAM_FREQ_NR] = {0x1a8363c0, 0x1a878400};
+static u32 ddrphy_dtpr2[DRAM_FREQ_NR] = {0x5002c200, 0xa00214f8};
+static u32 ddrphy_mr0[DRAM_FREQ_NR] = {0x00000b51, 0x00000d71};
+static u32 ddrphy_mr2[DRAM_FREQ_NR] = {0x00000290, 0x00000298};
+
+int ph1_ld4_ddrphy_init(struct ddrphy __iomem *phy, int freq, bool ddr3plus)
{
+ enum dram_freq freq_e;
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]);
+ switch (freq) {
+ case 1333:
+ freq_e = DRAM_FREQ_1333M;
+ break;
+ case 1600:
+ freq_e = DRAM_FREQ_1600M;
+ break;
+ default:
+ printf("unsupported DRAM frequency %d MHz\n", freq);
+ return -EINVAL;
}
+
+ writel(0x0300c473, &phy->pgcr[1]);
+ writel(ddrphy_ptr0[freq_e], &phy->ptr[0]);
+ writel(ddrphy_ptr1[freq_e], &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(ddrphy_ptr3[freq_e], &phy->ptr[3]);
+ writel(ddrphy_ptr4[freq_e], &phy->ptr[4]);
writel(0xF004001A, &phy->dsgcr);
/* change the value of the on-die pull-up/pull-down registors */
@@ -38,30 +59,13 @@ int ph1_ld4_ddrphy_init(struct ddrphy __iomem *phy, int freq, int size)
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(ddrphy_dtpr0[freq_e], &phy->dtpr[0]);
+ writel(ddrphy_dtpr1[freq_e], &phy->dtpr[1]);
+ writel(ddrphy_dtpr2[freq_e], &phy->dtpr[2]);
+ writel(ddrphy_mr0[freq_e], &phy->mr0);
writel(0x00000006, &phy->mr1);
- if (freq == 1333)
- writel(0x00000290, &phy->mr2);
- else
- writel(0x00000298, &phy->mr2);
-
- writel(0x00000800, &phy->mr3);
+ writel(ddrphy_mr2[freq_e], &phy->mr2);
+ writel(ddr3plus ? 0x00000800 : 0x00000000, &phy->mr3);
while (!(readl(&phy->pgsr[0]) & PGSR0_IDONE))
;
diff --git a/arch/arm/mach-uniphier/dram/ddrphy-ph1-pro4.c b/arch/arm/mach-uniphier/dram/ddrphy-ph1-pro4.c
deleted file mode 100644
index 9fb34f7..0000000
--- a/arch/arm/mach-uniphier/dram/ddrphy-ph1-pro4.c
+++ /dev/null
@@ -1,67 +0,0 @@
-/*
- * Copyright (C) 2014-2015 Masahiro Yamada <yamada.masahiro@socionext.com>
- *
- * SPDX-License-Identifier: GPL-2.0+
- */
-
-#include <linux/types.h>
-#include <linux/io.h>
-
-#include "ddrphy-regs.h"
-
-int ph1_pro4_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]);
- writel(0x1a8363c0, &phy->dtpr[1]);
- writel(0x5002c200, &phy->dtpr[2]);
- writel(0x00000b51, &phy->mr0);
- } else {
- writel(0x999cbb66, &phy->dtpr[0]);
- 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]);
-
- return 0;
-}
diff --git a/arch/arm/mach-uniphier/dram/ddrphy-ph1-sld8.c b/arch/arm/mach-uniphier/dram/ddrphy-ph1-sld8.c
deleted file mode 100644
index 6510690..0000000
--- a/arch/arm/mach-uniphier/dram/ddrphy-ph1-sld8.c
+++ /dev/null
@@ -1,78 +0,0 @@
-/*
- * Copyright (C) 2014-2015 Masahiro Yamada <yamada.masahiro@socionext.com>
- *
- * SPDX-License-Identifier: GPL-2.0+
- */
-
-#include <config.h>
-#include <linux/types.h>
-#include <linux/io.h>
-
-#include "ddrphy-regs.h"
-
-int ph1_sld8_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]);
-
- return 0;
-}
diff --git a/arch/arm/mach-uniphier/dram/ddrphy-regs.h b/arch/arm/mach-uniphier/dram/ddrphy-regs.h
index 03aedc2..87f6d0d 100644
--- a/arch/arm/mach-uniphier/dram/ddrphy-regs.h
+++ b/arch/arm/mach-uniphier/dram/ddrphy-regs.h
@@ -11,6 +11,7 @@
#include <linux/bitops.h>
#include <linux/compiler.h>
+#include <linux/types.h>
#ifndef __ASSEMBLY__
@@ -169,9 +170,7 @@ struct ddrphy {
#define DDRPHY_BASE(ch, phy) (0x5bc01000 + 0x200000 * (ch) + 0x1000 * (phy))
#ifndef __ASSEMBLY__
-int ph1_ld4_ddrphy_init(struct ddrphy __iomem *phy, int freq, int size);
-int ph1_pro4_ddrphy_init(struct ddrphy __iomem *phy, int freq, int size);
-int ph1_sld8_ddrphy_init(struct ddrphy __iomem *phy, int freq, int size);
+int ph1_ld4_ddrphy_init(struct ddrphy __iomem *phy, int freq, bool ddr3plus);
void ddrphy_prepare_training(struct ddrphy __iomem *phy, int rank);
int ddrphy_training(struct ddrphy __iomem *phy);
#endif
diff --git a/arch/arm/mach-uniphier/dram/umc-ph1-ld4.c b/arch/arm/mach-uniphier/dram/umc-ph1-ld4.c
index ffd7aa9..72447cc 100644
--- a/arch/arm/mach-uniphier/dram/umc-ph1-ld4.c
+++ b/arch/arm/mach-uniphier/dram/umc-ph1-ld4.c
@@ -8,11 +8,40 @@
#include <linux/err.h>
#include <linux/io.h>
#include <linux/sizes.h>
+#include <asm/processor.h>
#include "../init.h"
#include "ddrphy-regs.h"
#include "umc-regs.h"
+#define DRAM_CH_NR 2
+
+enum dram_freq {
+ DRAM_FREQ_1333M,
+ DRAM_FREQ_1600M,
+ DRAM_FREQ_NR,
+};
+
+enum dram_size {
+ DRAM_SZ_128M,
+ DRAM_SZ_256M,
+ DRAM_SZ_NR,
+};
+
+static u32 umc_cmdctla_plus[DRAM_FREQ_NR] = {0x45990b11, 0x36bb0f17};
+static u32 umc_cmdctlb_plus[DRAM_FREQ_NR] = {0x16958924, 0x18c6aa24};
+static u32 umc_spcctla[DRAM_FREQ_NR][DRAM_SZ_NR] = {
+ {0x00240512, 0x00350512},
+ {0x002b0617, 0x003f0617},
+};
+static u32 umc_spcctlb[DRAM_FREQ_NR] = {0x00ff0006, 0x00ff0008};
+static u32 umc_rdatactl[DRAM_FREQ_NR] = {0x000a00ac, 0x000c00ae};
+
+static int umc_get_rank(int ch)
+{
+ return ch; /* ch0: rank0, ch1: rank1 for this SoC */
+}
+
static void umc_start_ssif(void __iomem *ssif_base)
{
writel(0x00000000, ssif_base + 0x0000b004);
@@ -47,130 +76,116 @@ static void umc_start_ssif(void __iomem *ssif_base)
writel(0x00000001, ssif_base + UMC_DMDRST);
}
-static void umc_dramcont_init(void __iomem *dramcont, void __iomem *ca_base,
- int size, int freq)
+static int umc_dramcont_init(void __iomem *dc_base, void __iomem *ca_base,
+ int freq, unsigned long size, bool ddr3plus)
{
- if (freq == 1333) {
- writel(0x45990b11, dramcont + UMC_CMDCTLA);
- writel(0x16958924, dramcont + UMC_CMDCTLB);
- writel(0x5101046A, dramcont + UMC_INITCTLA);
-
- if (size == 1)
- writel(0x27028B0A, dramcont + UMC_INITCTLB);
- else if (size == 2)
- writel(0x38028B0A, dramcont + UMC_INITCTLB);
-
- writel(0x000FF0FF, dramcont + UMC_INITCTLC);
- writel(0x00000b51, dramcont + UMC_DRMMR0);
- } else if (freq == 1600) {
- writel(0x36BB0F17, dramcont + UMC_CMDCTLA);
- writel(0x18C6AA24, dramcont + UMC_CMDCTLB);
- writel(0x5101387F, dramcont + UMC_INITCTLA);
-
- if (size == 1)
- writel(0x2F030D3F, dramcont + UMC_INITCTLB);
- else if (size == 2)
- writel(0x43030D3F, dramcont + UMC_INITCTLB);
-
- writel(0x00FF00FF, dramcont + UMC_INITCTLC);
- writel(0x00000d71, dramcont + UMC_DRMMR0);
- }
-
- writel(0x00000006, dramcont + UMC_DRMMR1);
-
- if (freq == 1333)
- writel(0x00000290, dramcont + UMC_DRMMR2);
- else if (freq == 1600)
- writel(0x00000298, dramcont + UMC_DRMMR2);
-
- writel(0x00000800, dramcont + UMC_DRMMR3);
+ enum dram_freq freq_e;
+ enum dram_size size_e;
- if (freq == 1333) {
- if (size == 1)
- writel(0x00240512, dramcont + UMC_SPCCTLA);
- else if (size == 2)
- writel(0x00350512, dramcont + UMC_SPCCTLA);
+ if (!ddr3plus) {
+ pr_err("DDR3 standard is not supported\n");
+ return -EINVAL;
+ }
- writel(0x00ff0006, dramcont + UMC_SPCCTLB);
- writel(0x000a00ac, dramcont + UMC_RDATACTL_D0);
- } else if (freq == 1600) {
- if (size == 1)
- writel(0x002B0617, dramcont + UMC_SPCCTLA);
- else if (size == 2)
- writel(0x003F0617, dramcont + UMC_SPCCTLA);
+ switch (freq) {
+ case 1333:
+ freq_e = DRAM_FREQ_1333M;
+ break;
+ case 1600:
+ freq_e = DRAM_FREQ_1600M;
+ break;
+ default:
+ pr_err("unsupported DRAM frequency %d MHz\n", freq);
+ return -EINVAL;
+ }
- writel(0x00ff0008, dramcont + UMC_SPCCTLB);
- writel(0x000c00ae, dramcont + UMC_RDATACTL_D0);
+ switch (size) {
+ case 0:
+ return 0;
+ case SZ_128M:
+ size_e = DRAM_SZ_128M;
+ break;
+ case SZ_256M:
+ size_e = DRAM_SZ_256M;
+ break;
+ default:
+ pr_err("unsupported DRAM size 0x%08lx\n", size);
+ return -EINVAL;
}
- writel(0x04060806, dramcont + UMC_WDATACTL_D0);
- writel(0x04a02000, dramcont + UMC_DATASET);
+ writel(umc_cmdctla_plus[freq_e], dc_base + UMC_CMDCTLA);
+ writel(umc_cmdctlb_plus[freq_e], dc_base + UMC_CMDCTLB);
+ writel(umc_spcctla[freq_e][size_e], dc_base + UMC_SPCCTLA);
+ writel(umc_spcctlb[freq_e], dc_base + UMC_SPCCTLB);
+ writel(umc_rdatactl[freq_e], dc_base + UMC_RDATACTL_D0);
+ writel(0x04060806, dc_base + UMC_WDATACTL_D0);
+ writel(0x04a02000, dc_base + UMC_DATASET);
writel(0x00000000, ca_base + 0x2300);
- writel(0x00400020, dramcont + UMC_DCCGCTL);
- writel(0x00000003, dramcont + 0x7000);
- writel(0x0000000f, dramcont + 0x8000);
- writel(0x000000c3, dramcont + 0x8004);
- writel(0x00000071, dramcont + 0x8008);
- writel(0x0000003b, dramcont + UMC_DICGCTLA);
- writel(0x020a0808, dramcont + UMC_DICGCTLB);
- writel(0x00000004, dramcont + UMC_FLOWCTLG);
+ writel(0x00400020, dc_base + UMC_DCCGCTL);
+ writel(0x00000003, dc_base + 0x7000);
+ writel(0x0000000f, dc_base + 0x8000);
+ writel(0x000000c3, dc_base + 0x8004);
+ writel(0x00000071, dc_base + 0x8008);
+ writel(0x0000003b, dc_base + UMC_DICGCTLA);
+ writel(0x020a0808, dc_base + UMC_DICGCTLB);
+ writel(0x00000004, dc_base + UMC_FLOWCTLG);
writel(0x80000201, ca_base + 0xc20);
- writel(0x0801e01e, dramcont + UMC_FLOWCTLA);
- writel(0x00200000, dramcont + UMC_FLOWCTLB);
- writel(0x00004444, dramcont + UMC_FLOWCTLC);
- writel(0x200a0a00, dramcont + UMC_SPCSETB);
- writel(0x00000000, dramcont + UMC_SPCSETD);
- writel(0x00000520, dramcont + UMC_DFICUPDCTLA);
+ writel(0x0801e01e, dc_base + UMC_FLOWCTLA);
+ writel(0x00200000, dc_base + UMC_FLOWCTLB);
+ writel(0x00004444, dc_base + UMC_FLOWCTLC);
+ writel(0x200a0a00, dc_base + UMC_SPCSETB);
+ writel(0x00000000, dc_base + UMC_SPCSETD);
+ writel(0x00000520, dc_base + UMC_DFICUPDCTLA);
+
+ return 0;
}
-static int umc_init_sub(int freq, int size_ch0, int size_ch1)
+static int umc_ch_init(void __iomem *dc_base, void __iomem *ca_base,
+ int freq, unsigned long size, bool ddr3plus, int ch)
{
- void __iomem *ssif_base = (void __iomem *)UMC_SSIF_BASE;
- void __iomem *ca_base0 = (void __iomem *)UMC_CA_BASE(0);
- 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);
- umc_dram_init_poll(dramcont0);
- umc_dram_init_poll(dramcont1);
-
- writel(0x00000101, dramcont0 + UMC_DIOCTLA);
-
- ph1_ld4_ddrphy_init(phy0_0, freq, size_ch0);
+ void __iomem *phy_base = dc_base + 0x00001000;
+ int ret;
- ddrphy_prepare_training(phy0_0, 0);
- ddrphy_training(phy0_0);
+ writel(UMC_INITSET_INIT1EN, dc_base + UMC_INITSET);
+ while (readl(dc_base + UMC_INITSET) & UMC_INITSTAT_INIT1ST)
+ cpu_relax();
- writel(0x00000101, dramcont1 + UMC_DIOCTLA);
+ writel(0x00000101, dc_base + UMC_DIOCTLA);
- ph1_ld4_ddrphy_init(phy1_0, freq, size_ch1);
+ ret = ph1_ld4_ddrphy_init(phy_base, freq, ddr3plus);
+ if (ret)
+ return ret;
- 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);
-
- umc_start_ssif(ssif_base);
+ ddrphy_prepare_training(phy_base, umc_get_rank(ch));
+ ret = ddrphy_training(phy_base);
+ if (ret)
+ return ret;
- return 0;
+ return umc_dramcont_init(dc_base, ca_base, freq, size, ddr3plus);
}
int ph1_ld4_umc_init(const struct uniphier_board_data *bd)
{
- if ((bd->dram_ch0_size == SZ_128M || bd->dram_ch0_size == SZ_256M) &&
- (bd->dram_ch1_size == SZ_128M || bd->dram_ch1_size == SZ_256M) &&
- (bd->dram_freq == 1333 || bd->dram_freq == 1600) &&
- bd->dram_ch0_width == 16 && bd->dram_ch1_width == 16) {
- return umc_init_sub(bd->dram_freq,
- bd->dram_ch0_size / SZ_128M,
- bd->dram_ch1_size / SZ_128M);
- } else {
- pr_err("Unsupported DDR configuration\n");
- return -EINVAL;
+ void __iomem *umc_base = (void __iomem *)0x5b800000;
+ void __iomem *ca_base = umc_base + 0x00001000;
+ void __iomem *dc_base = umc_base + 0x00400000;
+ void __iomem *ssif_base = umc_base;
+ int ch, ret;
+
+ for (ch = 0; ch < DRAM_CH_NR; ch++) {
+ ret = umc_ch_init(dc_base, ca_base, bd->dram_freq,
+ bd->dram_ch[ch].size,
+ bd->dram_ddr3plus, ch);
+ if (ret) {
+ pr_err("failed to initialize UMC ch%d\n", ch);
+ return ret;
+ }
+
+ ca_base += 0x00001000;
+ dc_base += 0x00200000;
}
+
+ umc_start_ssif(ssif_base);
+
+ return 0;
}
diff --git a/arch/arm/mach-uniphier/dram/umc-ph1-pro4.c b/arch/arm/mach-uniphier/dram/umc-ph1-pro4.c
index 261f7cf..23fb7b9 100644
--- a/arch/arm/mach-uniphier/dram/umc-ph1-pro4.c
+++ b/arch/arm/mach-uniphier/dram/umc-ph1-pro4.c
@@ -8,11 +8,14 @@
#include <linux/err.h>
#include <linux/io.h>
#include <linux/sizes.h>
+#include <asm/processor.h>
#include "../init.h"
#include "ddrphy-regs.h"
#include "umc-regs.h"
+#define DRAM_CH_NR 2
+
enum dram_size {
DRAM_SZ_128M,
DRAM_SZ_256M,
@@ -20,14 +23,13 @@ enum dram_size {
DRAM_SZ_NR,
};
-static u32 umc_initctlb[DRAM_SZ_NR] = {0x43030d3f, 0x43030d3f, 0x7b030d3f};
static u32 umc_spcctla[DRAM_SZ_NR] = {0x002b0617, 0x003f0617, 0x00770617};
static void umc_start_ssif(void __iomem *ssif_base)
{
- writel(0x00000001, ssif_base + 0x0000b004);
+ writel(0x00000000, ssif_base + 0x0000b004);
writel(0xffffffff, ssif_base + 0x0000c004);
- writel(0x07ffffff, ssif_base + 0x0000c008);
+ writel(0x000fffcf, ssif_base + 0x0000c008);
writel(0x00000001, ssif_base + 0x0000b000);
writel(0x00000001, ssif_base + 0x0000c000);
@@ -66,121 +68,117 @@ static void umc_start_ssif(void __iomem *ssif_base)
writel(0x00000001, ssif_base + UMC_DMDRST);
}
-static int umc_dramcont_init(void __iomem *dramcont, void __iomem *ca_base,
- int size, int width)
+static int umc_dramcont_init(void __iomem *dc_base, void __iomem *ca_base,
+ int freq, unsigned long size, bool ddr3plus)
{
- enum dram_size dram_size;
+ enum dram_size size_e;
+
+ if (freq != 1600) {
+ pr_err("Unsupported DDR frequency %d MHz\n", freq);
+ return -EINVAL;
+ }
+
+ if (ddr3plus) {
+ pr_err("DDR3+ is not supported\n");
+ return -EINVAL;
+ }
- switch (size / (width / 16)) {
+ switch (size) {
case SZ_128M:
- dram_size = DRAM_SZ_128M;
+ size_e = DRAM_SZ_128M;
break;
case SZ_256M:
- dram_size = DRAM_SZ_256M;
+ size_e = DRAM_SZ_256M;
break;
case SZ_512M:
- dram_size = DRAM_SZ_512M;
+ size_e = DRAM_SZ_512M;
break;
default:
- printf("unsupported DRAM size\n");
+ pr_err("unsupported DRAM size 0x%08lx (per 16bit)\n", size);
return -EINVAL;
}
- writel(0x66bb0f17, dramcont + UMC_CMDCTLA);
- writel(0x18c6aa44, dramcont + UMC_CMDCTLB);
- writel(0x5101387f, dramcont + UMC_INITCTLA);
- writel(umc_initctlb[dram_size], dramcont + UMC_INITCTLB);
- writel(0x00ff00ff, dramcont + UMC_INITCTLC);
- writel(0x00000d71, dramcont + UMC_DRMMR0);
- writel(0x00000006, dramcont + UMC_DRMMR1);
- writel(0x00000298, dramcont + UMC_DRMMR2);
- writel(0x00000000, dramcont + UMC_DRMMR3);
- writel(umc_spcctla[dram_size], dramcont + UMC_SPCCTLA);
- writel(0x00ff0008, dramcont + UMC_SPCCTLB);
- writel(0x000c00ae, dramcont + UMC_RDATACTL_D0);
- writel(0x000c00ae, dramcont + UMC_RDATACTL_D1);
- writel(0x04060802, dramcont + UMC_WDATACTL_D0);
- writel(0x04060802, dramcont + UMC_WDATACTL_D1);
- writel(0x04a02000, dramcont + UMC_DATASET);
+ writel(0x66bb0f17, dc_base + UMC_CMDCTLA);
+ writel(0x18c6aa44, dc_base + UMC_CMDCTLB);
+ writel(umc_spcctla[size_e], dc_base + UMC_SPCCTLA);
+ writel(0x00ff0008, dc_base + UMC_SPCCTLB);
+ writel(0x000c00ae, dc_base + UMC_RDATACTL_D0);
+ writel(0x000c00ae, dc_base + UMC_RDATACTL_D1);
+ writel(0x04060802, dc_base + UMC_WDATACTL_D0);
+ writel(0x04060802, dc_base + UMC_WDATACTL_D1);
+ writel(0x04a02000, dc_base + UMC_DATASET);
writel(0x00000000, ca_base + 0x2300);
- writel(0x00400020, dramcont + UMC_DCCGCTL);
- writel(0x0000000f, dramcont + 0x7000);
- writel(0x0000000f, dramcont + 0x8000);
- writel(0x000000c3, dramcont + 0x8004);
- writel(0x00000071, dramcont + 0x8008);
- writel(0x00000004, dramcont + UMC_FLOWCTLG);
- writel(0x00000000, dramcont + 0x0060);
+ writel(0x00400020, dc_base + UMC_DCCGCTL);
+ writel(0x0000000f, dc_base + 0x7000);
+ writel(0x0000000f, dc_base + 0x8000);
+ writel(0x000000c3, dc_base + 0x8004);
+ writel(0x00000071, dc_base + 0x8008);
+ writel(0x00000004, dc_base + UMC_FLOWCTLG);
+ writel(0x00000000, dc_base + 0x0060);
writel(0x80000201, ca_base + 0xc20);
- writel(0x0801e01e, dramcont + UMC_FLOWCTLA);
- writel(0x00200000, dramcont + UMC_FLOWCTLB);
- writel(0x00004444, dramcont + UMC_FLOWCTLC);
- writel(0x200a0a00, dramcont + UMC_SPCSETB);
- writel(0x00010000, dramcont + UMC_SPCSETD);
- writel(0x80000020, dramcont + UMC_DFICUPDCTLA);
+ writel(0x0801e01e, dc_base + UMC_FLOWCTLA);
+ writel(0x00200000, dc_base + UMC_FLOWCTLB);
+ writel(0x00004444, dc_base + UMC_FLOWCTLC);
+ writel(0x200a0a00, dc_base + UMC_SPCSETB);
+ writel(0x00010000, dc_base + UMC_SPCSETD);
+ writel(0x80000020, dc_base + UMC_DFICUPDCTLA);
return 0;
}
-int ph1_pro4_umc_init(const struct uniphier_board_data *bd)
+static int umc_ch_init(void __iomem *dc_base, void __iomem *ca_base,
+ int freq, unsigned long size, unsigned int width,
+ bool ddr3plus)
{
- void __iomem *ssif_base = (void __iomem *)UMC_SSIF_BASE;
- void __iomem *ca_base0 = (void __iomem *)UMC_CA_BASE(0);
- 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);
- int ret;
-
- if (bd->dram_freq != 1600) {
- pr_err("Unsupported DDR configuration\n");
- return -EINVAL;
- }
-
- umc_dram_init_start(dramcont0);
- umc_dram_init_start(dramcont1);
- umc_dram_init_poll(dramcont0);
- umc_dram_init_poll(dramcont1);
-
- writel(0x00000101, dramcont0 + UMC_DIOCTLA);
+ void __iomem *phy_base = dc_base + 0x00001000;
+ int nr_phy = width / 16;
+ int phy, ret;
- ph1_pro4_ddrphy_init(phy0_0, bd->dram_freq, bd->dram_ch0_size);
+ writel(UMC_INITSET_INIT1EN, dc_base + UMC_INITSET);
+ while (readl(dc_base + UMC_INITSET) & UMC_INITSTAT_INIT1ST)
+ cpu_relax();
- ddrphy_prepare_training(phy0_0, 0);
- ddrphy_training(phy0_0);
+ for (phy = 0; phy < nr_phy; phy++) {
+ writel(0x00000100 | ((1 << (phy + 1)) - 1),
+ dc_base + UMC_DIOCTLA);
- writel(0x00000103, dramcont0 + UMC_DIOCTLA);
+ ret = ph1_ld4_ddrphy_init(phy_base, freq, ddr3plus);
+ if (ret)
+ return ret;
- ph1_pro4_ddrphy_init(phy0_1, bd->dram_freq, bd->dram_ch0_size);
+ ddrphy_prepare_training(phy_base, phy);
+ ret = ddrphy_training(phy_base);
+ if (ret)
+ return ret;
- ddrphy_prepare_training(phy0_1, 1);
- ddrphy_training(phy0_1);
-
- writel(0x00000101, dramcont1 + UMC_DIOCTLA);
-
- ph1_pro4_ddrphy_init(phy1_0, bd->dram_freq, bd->dram_ch1_size);
-
- ddrphy_prepare_training(phy1_0, 0);
- ddrphy_training(phy1_0);
-
- writel(0x00000103, dramcont1 + UMC_DIOCTLA);
-
- ph1_pro4_ddrphy_init(phy1_1, bd->dram_freq, bd->dram_ch1_size);
-
- ddrphy_prepare_training(phy1_1, 1);
- ddrphy_training(phy1_1);
+ phy_base += 0x00001000;
+ }
- ret = umc_dramcont_init(dramcont0, ca_base0, bd->dram_ch0_size,
- bd->dram_ch0_width);
- if (ret)
- return ret;
+ return umc_dramcont_init(dc_base, ca_base, freq, size / (width / 16),
+ ddr3plus);
+}
- ret = umc_dramcont_init(dramcont1, ca_base1, bd->dram_ch1_size,
- bd->dram_ch1_width);
- if (ret)
- return ret;
+int ph1_pro4_umc_init(const struct uniphier_board_data *bd)
+{
+ void __iomem *umc_base = (void __iomem *)0x5b800000;
+ void __iomem *ca_base = umc_base + 0x00001000;
+ void __iomem *dc_base = umc_base + 0x00400000;
+ void __iomem *ssif_base = umc_base;
+ int ch, ret;
+
+ for (ch = 0; ch < DRAM_CH_NR; ch++) {
+ ret = umc_ch_init(dc_base, ca_base, bd->dram_freq,
+ bd->dram_ch[ch].size,
+ bd->dram_ch[ch].width,
+ bd->dram_ddr3plus);
+ if (ret) {
+ pr_err("failed to initialize UMC ch%d\n", ch);
+ return ret;
+ }
+
+ ca_base += 0x00001000;
+ dc_base += 0x00200000;
+ }
umc_start_ssif(ssif_base);
diff --git a/arch/arm/mach-uniphier/dram/umc-ph1-sld8.c b/arch/arm/mach-uniphier/dram/umc-ph1-sld8.c
index 09f9ccf..6cacd25 100644
--- a/arch/arm/mach-uniphier/dram/umc-ph1-sld8.c
+++ b/arch/arm/mach-uniphier/dram/umc-ph1-sld8.c
@@ -8,11 +8,43 @@
#include <linux/err.h>
#include <linux/io.h>
#include <linux/sizes.h>
+#include <asm/processor.h>
#include "../init.h"
#include "ddrphy-regs.h"
#include "umc-regs.h"
+#define DRAM_CH_NR 2
+
+enum dram_freq {
+ DRAM_FREQ_1333M,
+ DRAM_FREQ_1600M,
+ DRAM_FREQ_NR,
+};
+
+enum dram_size {
+ DRAM_SZ_128M,
+ DRAM_SZ_256M,
+ DRAM_SZ_512M,
+ DRAM_SZ_NR,
+};
+
+static u32 umc_cmdctla[DRAM_FREQ_NR] = {0x55990b11, 0x66bb0f17};
+static u32 umc_cmdctla_plus[DRAM_FREQ_NR] = {0x45990b11, 0x46bb0f17};
+static u32 umc_cmdctlb[DRAM_FREQ_NR] = {0x16958944, 0x18c6ab44};
+static u32 umc_cmdctlb_plus[DRAM_FREQ_NR] = {0x16958924, 0x18c6ab24};
+static u32 umc_spcctla[DRAM_FREQ_NR][DRAM_SZ_NR] = {
+ {0x00240512, 0x00350512, 0x00000000}, /* no data for 1333MHz,128MB */
+ {0x002b0617, 0x003f0617, 0x00670617},
+};
+static u32 umc_spcctlb[DRAM_FREQ_NR] = {0x00ff0006, 0x00ff0008};
+static u32 umc_rdatactl[DRAM_FREQ_NR] = {0x000a00ac, 0x000c00ac};
+
+static int umc_get_rank(int ch)
+{
+ return ch; /* ch0: rank0, ch1: rank1 for this SoC */
+}
+
static void umc_start_ssif(void __iomem *ssif_base)
{
writel(0x00000000, ssif_base + 0x0000b004);
@@ -47,110 +79,116 @@ static void umc_start_ssif(void __iomem *ssif_base)
writel(0x00000001, ssif_base + UMC_DMDRST);
}
-static void umc_dramcont_init(void __iomem *dramcont, void __iomem *ca_base,
- int size, int freq)
+static int umc_dramcont_init(void __iomem *dc_base, void __iomem *ca_base,
+ int freq, unsigned long size, bool ddr3plus)
{
-#ifdef CONFIG_DDR_STANDARD
- writel(0x55990b11, dramcont + UMC_CMDCTLA);
- writel(0x16958944, dramcont + UMC_CMDCTLB);
-#else
- writel(0x45990b11, dramcont + UMC_CMDCTLA);
- writel(0x16958924, dramcont + UMC_CMDCTLB);
-#endif
-
- writel(0x5101046A, dramcont + UMC_INITCTLA);
-
- if (size == 1)
- writel(0x27028B0A, dramcont + UMC_INITCTLB);
- else if (size == 2)
- writel(0x38028B0A, dramcont + UMC_INITCTLB);
-
- writel(0x00FF00FF, dramcont + UMC_INITCTLC);
- writel(0x00000b51, dramcont + UMC_DRMMR0);
- writel(0x00000006, dramcont + UMC_DRMMR1);
- writel(0x00000290, dramcont + UMC_DRMMR2);
-
-#ifdef CONFIG_DDR_STANDARD
- writel(0x00000000, dramcont + UMC_DRMMR3);
-#else
- writel(0x00000800, dramcont + UMC_DRMMR3);
-#endif
-
- if (size == 1)
- writel(0x00240512, dramcont + UMC_SPCCTLA);
- else if (size == 2)
- writel(0x00350512, dramcont + UMC_SPCCTLA);
-
- writel(0x00ff0006, dramcont + UMC_SPCCTLB);
- writel(0x000a00ac, dramcont + UMC_RDATACTL_D0);
- writel(0x04060806, dramcont + UMC_WDATACTL_D0);
- writel(0x04a02000, dramcont + UMC_DATASET);
+ enum dram_freq freq_e;
+ enum dram_size size_e;
+
+ switch (freq) {
+ case 1333:
+ freq_e = DRAM_FREQ_1333M;
+ break;
+ case 1600:
+ freq_e = DRAM_FREQ_1600M;
+ break;
+ default:
+ pr_err("unsupported DRAM frequency %d MHz\n", freq);
+ return -EINVAL;
+ }
+
+ switch (size) {
+ case 0:
+ return 0;
+ case SZ_128M:
+ size_e = DRAM_SZ_128M;
+ break;
+ case SZ_256M:
+ size_e = DRAM_SZ_256M;
+ break;
+ case SZ_512M:
+ size_e = DRAM_SZ_512M;
+ break;
+ default:
+ pr_err("unsupported DRAM size 0x%08lx\n", size);
+ return -EINVAL;
+ }
+
+ writel((ddr3plus ? umc_cmdctla_plus : umc_cmdctla)[freq_e],
+ dc_base + UMC_CMDCTLA);
+ writel((ddr3plus ? umc_cmdctlb_plus : umc_cmdctlb)[freq_e],
+ dc_base + UMC_CMDCTLB);
+ writel(umc_spcctla[freq_e][size_e], dc_base + UMC_SPCCTLA);
+ writel(umc_spcctlb[freq_e], dc_base + UMC_SPCCTLB);
+ writel(umc_rdatactl[freq_e], dc_base + UMC_RDATACTL_D0);
+ writel(0x04060806, dc_base + UMC_WDATACTL_D0);
+ writel(0x04a02000, dc_base + UMC_DATASET);
writel(0x00000000, ca_base + 0x2300);
- writel(0x00400020, dramcont + UMC_DCCGCTL);
- writel(0x00000003, dramcont + 0x7000);
- writel(0x0000004f, dramcont + 0x8000);
- writel(0x000000c3, dramcont + 0x8004);
- writel(0x00000077, dramcont + 0x8008);
- writel(0x0000003b, dramcont + UMC_DICGCTLA);
- writel(0x020a0808, dramcont + UMC_DICGCTLB);
- writel(0x00000004, dramcont + UMC_FLOWCTLG);
+ writel(0x00400020, dc_base + UMC_DCCGCTL);
+ writel(0x00000003, dc_base + 0x7000);
+ writel(0x0000004f, dc_base + 0x8000);
+ writel(0x000000c3, dc_base + 0x8004);
+ writel(0x00000077, dc_base + 0x8008);
+ writel(0x0000003b, dc_base + UMC_DICGCTLA);
+ writel(0x020a0808, dc_base + UMC_DICGCTLB);
+ writel(0x00000004, dc_base + UMC_FLOWCTLG);
writel(0x80000201, ca_base + 0xc20);
- writel(0x0801e01e, dramcont + UMC_FLOWCTLA);
- writel(0x00200000, dramcont + UMC_FLOWCTLB);
- writel(0x00004444, dramcont + UMC_FLOWCTLC);
- writel(0x200a0a00, dramcont + UMC_SPCSETB);
- writel(0x00000000, dramcont + UMC_SPCSETD);
- writel(0x00000520, dramcont + UMC_DFICUPDCTLA);
+ writel(0x0801e01e, dc_base + UMC_FLOWCTLA);
+ writel(0x00200000, dc_base + UMC_FLOWCTLB);
+ writel(0x00004444, dc_base + UMC_FLOWCTLC);
+ writel(0x200a0a00, dc_base + UMC_SPCSETB);
+ writel(0x00000000, dc_base + UMC_SPCSETD);
+ writel(0x00000520, dc_base + UMC_DFICUPDCTLA);
+
+ return 0;
}
-static int umc_init_sub(int freq, int size_ch0, int size_ch1)
+static int umc_ch_init(void __iomem *dc_base, void __iomem *ca_base,
+ int freq, unsigned long size, bool ddr3plus, int ch)
{
- void __iomem *ssif_base = (void __iomem *)UMC_SSIF_BASE;
- void __iomem *ca_base0 = (void __iomem *)UMC_CA_BASE(0);
- 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);
- umc_dram_init_poll(dramcont0);
- umc_dram_init_poll(dramcont1);
+ void __iomem *phy_base = dc_base + 0x00001000;
+ int ret;
- writel(0x00000101, dramcont0 + UMC_DIOCTLA);
+ writel(UMC_INITSET_INIT1EN, dc_base + UMC_INITSET);
+ while (readl(dc_base + UMC_INITSET) & UMC_INITSTAT_INIT1ST)
+ cpu_relax();
- ph1_sld8_ddrphy_init(phy0_0, freq, size_ch0);
+ writel(0x00000101, dc_base + UMC_DIOCTLA);
- ddrphy_prepare_training(phy0_0, 0);
- ddrphy_training(phy0_0);
+ ret = ph1_ld4_ddrphy_init(phy_base, freq, ddr3plus);
+ if (ret)
+ return ret;
- writel(0x00000101, dramcont1 + UMC_DIOCTLA);
+ ddrphy_prepare_training(phy_base, umc_get_rank(ch));
+ ret = ddrphy_training(phy_base);
+ if (ret)
+ return ret;
- ph1_sld8_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);
-
- umc_start_ssif(ssif_base);
-
- return 0;
+ return umc_dramcont_init(dc_base, ca_base, freq, size, ddr3plus);
}
int ph1_sld8_umc_init(const struct uniphier_board_data *bd)
{
- if ((bd->dram_ch0_size == SZ_128M || bd->dram_ch0_size == SZ_256M) &&
- (bd->dram_ch1_size == SZ_128M || bd->dram_ch1_size == SZ_256M) &&
- bd->dram_freq == 1333 &&
- bd->dram_ch0_width == 16 && bd->dram_ch1_width == 16) {
- return umc_init_sub(bd->dram_freq,
- bd->dram_ch0_size / SZ_128M,
- bd->dram_ch1_size / SZ_128M);
- } else {
- pr_err("Unsupported DDR configuration\n");
- return -EINVAL;
+ void __iomem *umc_base = (void __iomem *)0x5b800000;
+ void __iomem *ca_base = umc_base + 0x00001000;
+ void __iomem *dc_base = umc_base + 0x00400000;
+ void __iomem *ssif_base = umc_base;
+ int ch, ret;
+
+ for (ch = 0; ch < DRAM_CH_NR; ch++) {
+ ret = umc_ch_init(dc_base, ca_base, bd->dram_freq,
+ bd->dram_ch[ch].size,
+ bd->dram_ddr3plus, ch);
+ if (ret) {
+ pr_err("failed to initialize UMC ch%d\n", ch);
+ return ret;
+ }
+
+ ca_base += 0x00001000;
+ dc_base += 0x00200000;
}
+
+ umc_start_ssif(ssif_base);
+
+ return 0;
}
diff --git a/arch/arm/mach-uniphier/dram/umc-proxstream2.c b/arch/arm/mach-uniphier/dram/umc-proxstream2.c
index 6e7fa88..50c0238 100644
--- a/arch/arm/mach-uniphier/dram/umc-proxstream2.c
+++ b/arch/arm/mach-uniphier/dram/umc-proxstream2.c
@@ -18,46 +18,45 @@
#include "ddrmphy-regs.h"
#include "umc-regs.h"
-#define CH_NR 3
+#define DRAM_CH_NR 3
enum dram_freq {
- FREQ_1866M,
- FREQ_2133M,
- FREQ_NR,
+ DRAM_FREQ_1866M,
+ DRAM_FREQ_2133M,
+ DRAM_FREQ_NR,
};
enum dram_size {
- SIZE_0,
- SIZE_512M,
- SIZE_1G,
- SIZE_NR,
+ DRAM_SZ_256M,
+ DRAM_SZ_512M,
+ DRAM_SZ_NR,
};
-static u32 ddrphy_pgcr2[FREQ_NR] = {0x00FC7E5D, 0x00FC90AB};
-static u32 ddrphy_ptr0[FREQ_NR] = {0x0EA09205, 0x10C0A6C6};
-static u32 ddrphy_ptr1[FREQ_NR] = {0x0DAC041B, 0x0FA104B1};
-static u32 ddrphy_ptr3[FREQ_NR] = {0x15171e45, 0x18182357};
-static u32 ddrphy_ptr4[FREQ_NR] = {0x0e9ad8e9, 0x10b34157};
-static u32 ddrphy_dtpr0[FREQ_NR] = {0x35a00d88, 0x39e40e88};
-static u32 ddrphy_dtpr1[FREQ_NR] = {0x2288cc2c, 0x228a04d0};
-static u32 ddrphy_dtpr2[FREQ_NR] = {0x50005e00, 0x50006a00};
-static u32 ddrphy_dtpr3[FREQ_NR] = {0x0010cb49, 0x0010ec89};
-static u32 ddrphy_mr0[FREQ_NR] = {0x00000115, 0x00000125};
-static u32 ddrphy_mr2[FREQ_NR] = {0x000002a0, 0x000002a8};
+static u32 ddrphy_pgcr2[DRAM_FREQ_NR] = {0x00FC7E5D, 0x00FC90AB};
+static u32 ddrphy_ptr0[DRAM_FREQ_NR] = {0x0EA09205, 0x10C0A6C6};
+static u32 ddrphy_ptr1[DRAM_FREQ_NR] = {0x0DAC041B, 0x0FA104B1};
+static u32 ddrphy_ptr3[DRAM_FREQ_NR] = {0x15171e45, 0x18182357};
+static u32 ddrphy_ptr4[DRAM_FREQ_NR] = {0x0e9ad8e9, 0x10b34157};
+static u32 ddrphy_dtpr0[DRAM_FREQ_NR] = {0x35a00d88, 0x39e40e88};
+static u32 ddrphy_dtpr1[DRAM_FREQ_NR] = {0x2288cc2c, 0x228a04d0};
+static u32 ddrphy_dtpr2[DRAM_FREQ_NR] = {0x50005e00, 0x50006a00};
+static u32 ddrphy_dtpr3[DRAM_FREQ_NR] = {0x0010cb49, 0x0010ec89};
+static u32 ddrphy_mr0[DRAM_FREQ_NR] = {0x00000115, 0x00000125};
+static u32 ddrphy_mr2[DRAM_FREQ_NR] = {0x000002a0, 0x000002a8};
/* dependent on package and board design */
-static u32 ddrphy_acbdlr0[CH_NR] = {0x0000000c, 0x0000000c, 0x00000009};
+static u32 ddrphy_acbdlr0[DRAM_CH_NR] = {0x0000000c, 0x0000000c, 0x00000009};
-static u32 umc_cmdctla[FREQ_NR] = {0x66DD131D, 0x77EE1722};
+static u32 umc_cmdctla[DRAM_FREQ_NR] = {0x66DD131D, 0x77EE1722};
/*
* The ch2 is a different generation UMC core.
* The register spec is different, unfortunately.
*/
-static u32 umc_cmdctlb_ch01[FREQ_NR] = {0x13E87C44, 0x18F88C44};
-static u32 umc_cmdctlb_ch2[FREQ_NR] = {0x19E8DC44, 0x1EF8EC44};
-static u32 umc_spcctla[FREQ_NR][SIZE_NR] = {
- {0x00000000, 0x004A071D, 0x0078071D},
- {0x00000000, 0x0055081E, 0x0089081E},
+static u32 umc_cmdctlb_ch01[DRAM_FREQ_NR] = {0x13E87C44, 0x18F88C44};
+static u32 umc_cmdctlb_ch2[DRAM_FREQ_NR] = {0x19E8DC44, 0x1EF8EC44};
+static u32 umc_spcctla[DRAM_FREQ_NR][DRAM_SZ_NR] = {
+ {0x004A071D, 0x0078071D},
+ {0x0055081E, 0x0089081E},
};
static u32 umc_spcctlb[] = {0x00FF000A, 0x00FF000B};
@@ -344,7 +343,7 @@ static int __ddrphy_training(void __iomem *phy_base,
do {
if (--timeout < 0) {
- printf("%s: error: timeout during DDR training\n",
+ pr_err("%s: error: timeout during DDR training\n",
__func__);
return -ETIMEDOUT;
}
@@ -354,7 +353,7 @@ static int __ddrphy_training(void __iomem *phy_base,
for (s = seq; s->description; s++) {
if (pgsr0 & s->err_flag) {
- printf("%s: error: %s failed\n", __func__,
+ pr_err("%s: error: %s failed\n", __func__,
s->description);
return -EIO;
}
@@ -405,12 +404,12 @@ static int ddrphy_training(void __iomem *phy_base)
}
/* UMC */
-static void umc_set_system_latency(void __iomem *umc_dc_base, int phy_latency)
+static void umc_set_system_latency(void __iomem *dc_base, int phy_latency)
{
u32 val;
int latency;
- val = readl(umc_dc_base + UMC_RDATACTL_D0);
+ val = readl(dc_base + UMC_RDATACTL_D0);
latency = (val & UMC_RDATACTL_RADLTY_MASK) >> UMC_RDATACTL_RADLTY_SHIFT;
latency += (val & UMC_RDATACTL_RAD2LTY_MASK) >>
UMC_RDATACTL_RAD2LTY_SHIFT;
@@ -428,18 +427,18 @@ static void umc_set_system_latency(void __iomem *umc_dc_base, int phy_latency)
val |= latency << UMC_RDATACTL_RADLTY_SHIFT;
}
- writel(val, umc_dc_base + UMC_RDATACTL_D0);
- writel(val, umc_dc_base + UMC_RDATACTL_D1);
+ writel(val, dc_base + UMC_RDATACTL_D0);
+ writel(val, dc_base + UMC_RDATACTL_D1);
- readl(umc_dc_base + UMC_RDATACTL_D1); /* relax */
+ readl(dc_base + UMC_RDATACTL_D1); /* relax */
}
/* enable/disable auto refresh */
-void umc_refresh_ctrl(void __iomem *umc_dc_base, int enable)
+void umc_refresh_ctrl(void __iomem *dc_base, int enable)
{
u32 tmp;
- tmp = readl(umc_dc_base + UMC_SPCSETB);
+ tmp = readl(dc_base + UMC_SPCSETB);
tmp &= ~UMC_SPCSETB_AREFMD_MASK;
if (enable)
@@ -447,7 +446,7 @@ void umc_refresh_ctrl(void __iomem *umc_dc_base, int enable)
else
tmp |= UMC_SPCSETB_AREFMD_REG;
- writel(tmp, umc_dc_base + UMC_SPCSETB);
+ writel(tmp, dc_base + UMC_SPCSETB);
udelay(1);
}
@@ -459,20 +458,35 @@ static void umc_ud_init(void __iomem *umc_base, int ch)
writel(0x00000033, umc_base + UMC_PAIR1DOFF_D0);
}
-static void umc_dc_init(void __iomem *umc_dc_base, enum dram_freq freq,
- enum dram_size size, int ch, int width)
+static int umc_dc_init(void __iomem *dc_base, enum dram_freq freq,
+ unsigned long size, int width, int ch)
{
+ enum dram_size size_e;
int latency;
u32 val;
- writel(umc_cmdctla[freq], umc_dc_base + UMC_CMDCTLA);
+ switch (size) {
+ case 0:
+ return 0;
+ case SZ_256M:
+ size_e = DRAM_SZ_256M;
+ break;
+ case SZ_512M:
+ size_e = DRAM_SZ_512M;
+ break;
+ default:
+ pr_err("unsupported DRAM size 0x%08lx (per 16bit) for ch%d\n",
+ size, ch);
+ return -EINVAL;
+ }
+
+ writel(umc_cmdctla[freq], dc_base + UMC_CMDCTLA);
writel(ch == 2 ? umc_cmdctlb_ch2[freq] : umc_cmdctlb_ch01[freq],
- umc_dc_base + UMC_CMDCTLB);
+ dc_base + UMC_CMDCTLB);
- writel(umc_spcctla[freq][size / (width / 16)],
- umc_dc_base + UMC_SPCCTLA);
- writel(umc_spcctlb[freq], umc_dc_base + UMC_SPCCTLB);
+ writel(umc_spcctla[freq][size_e], dc_base + UMC_SPCCTLA);
+ writel(umc_spcctlb[freq], dc_base + UMC_SPCCTLB);
val = 0x000e000e;
latency = 12;
@@ -487,54 +501,56 @@ static void umc_dc_init(void __iomem *umc_dc_base, enum dram_freq freq,
val |= latency << UMC_RDATACTL_RADLTY_SHIFT;
}
- writel(val, umc_dc_base + UMC_RDATACTL_D0);
+ writel(val, dc_base + UMC_RDATACTL_D0);
if (width >= 32)
- writel(val, umc_dc_base + UMC_RDATACTL_D1);
+ writel(val, dc_base + UMC_RDATACTL_D1);
- writel(0x04060A02, umc_dc_base + UMC_WDATACTL_D0);
+ writel(0x04060A02, dc_base + UMC_WDATACTL_D0);
if (width >= 32)
- writel(0x04060A02, umc_dc_base + UMC_WDATACTL_D1);
- writel(0x04000000, umc_dc_base + UMC_DATASET);
- writel(0x00400020, umc_dc_base + UMC_DCCGCTL);
- writel(0x00000084, umc_dc_base + UMC_FLOWCTLG);
- writel(0x00000000, umc_dc_base + UMC_ACSSETA);
+ writel(0x04060A02, dc_base + UMC_WDATACTL_D1);
+ writel(0x04000000, dc_base + UMC_DATASET);
+ writel(0x00400020, dc_base + UMC_DCCGCTL);
+ writel(0x00000084, dc_base + UMC_FLOWCTLG);
+ writel(0x00000000, dc_base + UMC_ACSSETA);
writel(ch == 2 ? umc_flowctla_ch2[freq] : umc_flowctla_ch01[freq],
- umc_dc_base + UMC_FLOWCTLA);
+ dc_base + UMC_FLOWCTLA);
- writel(0x00004400, umc_dc_base + UMC_FLOWCTLC);
- writel(0x200A0A00, umc_dc_base + UMC_SPCSETB);
- writel(0x00000520, umc_dc_base + UMC_DFICUPDCTLA);
- writel(0x0000000D, umc_dc_base + UMC_RESPCTL);
+ writel(0x00004400, dc_base + UMC_FLOWCTLC);
+ writel(0x200A0A00, dc_base + UMC_SPCSETB);
+ writel(0x00000520, dc_base + UMC_DFICUPDCTLA);
+ writel(0x0000000D, dc_base + UMC_RESPCTL);
if (ch != 2) {
- writel(0x00202000, umc_dc_base + UMC_FLOWCTLB);
- writel(0xFDBFFFFF, umc_dc_base + UMC_FLOWCTLOB0);
- writel(0xFFFFFFFF, umc_dc_base + UMC_FLOWCTLOB1);
- writel(0x00080700, umc_dc_base + UMC_BSICMAPSET);
+ writel(0x00202000, dc_base + UMC_FLOWCTLB);
+ writel(0xFDBFFFFF, dc_base + UMC_FLOWCTLOB0);
+ writel(0xFFFFFFFF, dc_base + UMC_FLOWCTLOB1);
+ writel(0x00080700, dc_base + UMC_BSICMAPSET);
} else {
- writel(0x00200000, umc_dc_base + UMC_FLOWCTLB);
- writel(0x00000000, umc_dc_base + UMC_BSICMAPSET);
+ writel(0x00200000, dc_base + UMC_FLOWCTLB);
+ writel(0x00000000, dc_base + UMC_BSICMAPSET);
}
- writel(0x00000000, umc_dc_base + UMC_ERRMASKA);
- writel(0x00000000, umc_dc_base + UMC_ERRMASKB);
+ writel(0x00000000, dc_base + UMC_ERRMASKA);
+ writel(0x00000000, dc_base + UMC_ERRMASKB);
+
+ return 0;
}
-static int umc_init(void __iomem *umc_base, enum dram_freq freq, int ch,
- enum dram_size size, int width)
+static int umc_ch_init(void __iomem *umc_ch_base, enum dram_freq freq,
+ unsigned long size, unsigned int width, int ch)
{
- void __iomem *umc_dc_base = umc_base + 0x00011000;
- void __iomem *phy_base = umc_base + 0x00030000;
+ void __iomem *dc_base = umc_ch_base + 0x00011000;
+ void __iomem *phy_base = umc_ch_base + 0x00030000;
int ret;
- writel(0x00000002, umc_dc_base + UMC_INITSET);
- while (readl(umc_dc_base + UMC_INITSTAT) & BIT(2))
+ writel(0x00000002, dc_base + UMC_INITSET);
+ while (readl(dc_base + UMC_INITSTAT) & BIT(2))
cpu_relax();
/* deassert PHY reset signals */
writel(UMC_DIOCTLA_CTL_NRST | UMC_DIOCTLA_CFG_NRST,
- umc_dc_base + UMC_DIOCTLA);
+ dc_base + UMC_DIOCTLA);
ddrphy_init(phy_base, freq, width, ch);
@@ -546,28 +562,28 @@ static int umc_init(void __iomem *umc_base, enum dram_freq freq, int ch,
if (ret)
return ret;
- umc_dc_init(umc_dc_base, freq, size, ch, width);
+ ret = umc_dc_init(dc_base, freq, size, width, ch);
+ if (ret)
+ return ret;
- umc_ud_init(umc_base, ch);
+ umc_ud_init(umc_ch_base, ch);
- if (size) {
- ret = ddrphy_training(phy_base);
- if (ret)
- return ret;
- }
+ ret = ddrphy_training(phy_base);
+ if (ret)
+ return ret;
udelay(1);
/* match the system latency between UMC and PHY */
- umc_set_system_latency(umc_dc_base,
+ umc_set_system_latency(dc_base,
ddrphy_get_system_latency(phy_base, width));
udelay(1);
/* stop auto refresh before clearing FIFO in PHY */
- umc_refresh_ctrl(umc_dc_base, 0);
+ umc_refresh_ctrl(dc_base, 0);
ddrphy_fifo_reset(phy_base);
- umc_refresh_ctrl(umc_dc_base, 1);
+ umc_refresh_ctrl(dc_base, 1);
udelay(10);
@@ -585,43 +601,34 @@ static void um_init(void __iomem *um_base)
int proxstream2_umc_init(const struct uniphier_board_data *bd)
{
void __iomem *um_base = (void __iomem *)0x5b600000;
- void __iomem *umc_ch0_base = (void __iomem *)0x5b800000;
- void __iomem *umc_ch1_base = (void __iomem *)0x5ba00000;
- void __iomem *umc_ch2_base = (void __iomem *)0x5bc00000;
+ void __iomem *umc_ch_base = (void __iomem *)0x5b800000;
enum dram_freq freq;
- int ret;
+ int ch, ret;
switch (bd->dram_freq) {
case 1866:
- freq = FREQ_1866M;
+ freq = DRAM_FREQ_1866M;
break;
case 2133:
- freq = FREQ_2133M;
+ freq = DRAM_FREQ_2133M;
break;
default:
- printf("unsupported DRAM frequency %d MHz\n", bd->dram_freq);
+ pr_err("unsupported DRAM frequency %d MHz\n", bd->dram_freq);
return -EINVAL;
}
- ret = umc_init(umc_ch0_base, freq, 0, bd->dram_ch0_size / SZ_256M,
- bd->dram_ch0_width);
- if (ret) {
- printf("failed to initialize UMC ch0\n");
- return ret;
- }
+ for (ch = 0; ch < bd->dram_nr_ch; ch++) {
+ unsigned long size = bd->dram_ch[ch].size;
+ unsigned int width = bd->dram_ch[ch].width;
- ret = umc_init(umc_ch1_base, freq, 1, bd->dram_ch1_size / SZ_256M,
- bd->dram_ch1_width);
- if (ret) {
- printf("failed to initialize UMC ch1\n");
- return ret;
- }
+ ret = umc_ch_init(umc_ch_base, freq, size / (width / 16),
+ width, ch);
+ if (ret) {
+ pr_err("failed to initialize UMC ch%d\n", ch);
+ return ret;
+ }
- ret = umc_init(umc_ch2_base, freq, 2, bd->dram_ch2_size / SZ_256M,
- bd->dram_ch2_width);
- if (ret) {
- printf("failed to initialize UMC ch2\n");
- return ret;
+ umc_ch_base += 0x00200000;
}
um_init(um_base);
diff --git a/arch/arm/mach-uniphier/dram/umc-regs.h b/arch/arm/mach-uniphier/dram/umc-regs.h
index a6957a4..cc2dd27 100644
--- a/arch/arm/mach-uniphier/dram/umc-regs.h
+++ b/arch/arm/mach-uniphier/dram/umc-regs.h
@@ -9,10 +9,7 @@
#ifndef ARCH_UMC_REGS_H
#define ARCH_UMC_REGS_H
-#define UMC_BASE 0x5b800000
-
-/* SSIF registers */
-#define UMC_SSIF_BASE UMC_BASE
+#include <linux/bitops.h>
#define UMC_CPURST 0x00000700
#define UMC_IDSRST 0x0000070C
@@ -48,23 +45,14 @@
#define UMC_CLKEN_SSIF_RC 0x0000C080
#define UMC_CLKEN_SSIF_DST 0x0000C084
-/* CA registers */
-#define UMC_CA_BASE(ch) (UMC_BASE + 0x00001000 + 0x00001000 * (ch))
-
-/* DRAM controller registers */
-#define UMC_DRAMCONT_BASE(ch) (UMC_BASE + 0x00400000 + 0x00200000 * (ch))
-
#define UMC_CMDCTLA 0x00000000
#define UMC_CMDCTLB 0x00000004
-#define UMC_INITCTLA 0x00000008
-#define UMC_INITCTLB 0x0000000C
-#define UMC_INITCTLC 0x00000010
#define UMC_INITSET 0x00000014
+#define UMC_INITSET_INIT1EN BIT(1) /* init without power-on wait */
+#define UMC_INITSET_INIT0EN BIT(0) /* init with power-on wait */
#define UMC_INITSTAT 0x00000018
-#define UMC_DRMMR0 0x0000001C
-#define UMC_DRMMR1 0x00000020
-#define UMC_DRMMR2 0x00000024
-#define UMC_DRMMR3 0x00000028
+#define UMC_INITSTAT_INIT1ST BIT(1) /* init without power-on wait */
+#define UMC_INITSTAT_INIT0ST BIT(0) /* init with power-on wait */
#define UMC_SPCCTLA 0x00000030
#define UMC_SPCCTLB 0x00000034
#define UMC_SPCSETA 0x00000038
@@ -116,30 +104,4 @@
#define UMC_BITPERPIXELMODE_D0 0x010
#define UMC_PAIR1DOFF_D0 0x054
-#ifndef __ASSEMBLY__
-
-#include <linux/types.h>
-
-static inline void umc_polling(u32 address, u32 expval, u32 mask)
-{
- u32 nmask = ~mask;
- u32 data;
- do {
- data = readl(address) & nmask;
- } while (data != expval);
-}
-
-static inline void umc_dram_init_start(void __iomem *dramcont)
-{
- writel(0x00000002, dramcont + UMC_INITSET);
-}
-
-static inline void umc_dram_init_poll(void __iomem *dramcont)
-{
- while ((readl(dramcont + UMC_INITSTAT) & 0x00000002))
- ;
-}
-
-#endif
-
#endif