This patch adds DRAM initialisation support for the Allwinner A20 (sun7i)
processor. This code will not been compiled until the build is hooked up in a
later patch. It has been split out to keep the patches manageable.
Signed-off-by: Alexandru Gagniuc
Signed-off-by: Emilio López
Signed-off-by: Hans de Goede
Signed-off-by: Henrik Nordstrom
Signed-off-by: Jens Kuske
Signed-off-by: Luke Leighton
Signed-off-by: Oliver Schinagl
Signed-off-by: Siarhei Siamashka
Signed-off-by: Stefan Roese
Signed-off-by: Ian Campbell
Reviewed-by: Marek Vasut
Cc: Tom Cubie
---
v5: Based on 3f5ff92b1503 "sunxi: add comments to pll1_para array."
- No changes required
v4: Based on d9fe0a1e061e "sunxi: mksunxiboot: remove unnecessary casts."
- removed unbounded loops
- support more dram clock speeds.
v3: Based on c89867dca2e9 "sunxi: clocks: clock_get_pll5
prototype and coding style".
v2: Based on u-boot-sunxi.git#sunxi d9aa5dd3d15c "sunxi: mmc:
checkpatch whitespace fixes" with v2014.04-rc2 merged in:
- remove redundant braces in mctl_ddr3_reset
- remove incorrect call to mctl_ddr3_reset.
- add CONFIG_SUN7I to simplify future SUN?I support.
- add a comment about the magic numbers from the a/w code dumps
- fix a bunch of checkpatch.pl issues
v1: Based on u-boot-sunxi.git#sunxi commit d854c4de2f57 "arm: Handle .gnu.hash
section in ldscripts" vs v2014.01.
---
arch/arm/cpu/armv7/sunxi/Makefile | 1 +
arch/arm/cpu/armv7/sunxi/dram.c| 593 +
arch/arm/include/asm/arch-sunxi/dram.h | 179 ++
3 files changed, 773 insertions(+)
create mode 100644 arch/arm/cpu/armv7/sunxi/dram.c
create mode 100644 arch/arm/include/asm/arch-sunxi/dram.h
diff --git a/arch/arm/cpu/armv7/sunxi/Makefile
b/arch/arm/cpu/armv7/sunxi/Makefile
index 529e7ec..d81d26c 100644
--- a/arch/arm/cpu/armv7/sunxi/Makefile
+++ b/arch/arm/cpu/armv7/sunxi/Makefile
@@ -11,3 +11,4 @@ obj-y += timer.o
obj-y += clock.o
obj-y += pinmux.o
obj-$(CONFIG_SUN7I)+= clock_sun4i.o
+obj-$(CONFIG_SUN7I)+= dram.o
diff --git a/arch/arm/cpu/armv7/sunxi/dram.c b/arch/arm/cpu/armv7/sunxi/dram.c
new file mode 100644
index 000..b43c4b4
--- /dev/null
+++ b/arch/arm/cpu/armv7/sunxi/dram.c
@@ -0,0 +1,593 @@
+/*
+ * sunxi DRAM controller initialization
+ * (C) Copyright 2012 Henrik Nordstrom
+ * (C) Copyright 2013 Luke Kenneth Casson Leighton
+ *
+ * Based on sun4i Linux kernel sources mach-sunxi/pm/standby/dram*.c
+ * and earlier U-Boot Allwiner A10 SPL work
+ *
+ * (C) Copyright 2007-2012
+ * Allwinner Technology Co., Ltd.
+ * Berg Xing
+ * Tom Cubie
+ *
+ * SPDX-License-Identifier:GPL-2.0+
+ */
+
+/*
+ * Unfortunately the only documentation we have on the sun7i DRAM
+ * controller is Allwinner boot0 + boot1 code, and that code uses
+ * magic numbers & shifts with no explanations. Hence this code is
+ * rather undocumented and full of magic.
+ */
+
+#include
+#include
+#include
+#include
+#include
+#include
+
+#define CPU_CFG_CHIP_VER(n) ((n) << 6)
+#define CPU_CFG_CHIP_VER_MASK CPU_CFG_CHIP_VER(0x3)
+#define CPU_CFG_CHIP_REV_A 0x0
+#define CPU_CFG_CHIP_REV_C1 0x1
+#define CPU_CFG_CHIP_REV_C2 0x2
+#define CPU_CFG_CHIP_REV_B 0x3
+
+/*
+ * Wait up to 1s for mask to be clear in given reg.
+ */
+static void await_completion(u32 *reg, u32 mask)
+{
+ unsigned long tmo = timer_get_us() + 100;
+
+ while (readl(reg) & mask) {
+ if (timer_get_us() > tmo)
+ panic("Timeout initialising DRAM\n");
+ }
+}
+
+static void mctl_ddr3_reset(void)
+{
+ struct sunxi_dram_reg *dram =
+ (struct sunxi_dram_reg *)SUNXI_DRAMC_BASE;
+
+ clrbits_le32(&dram->mcr, DRAM_MCR_RESET);
+ udelay(2);
+ setbits_le32(&dram->mcr, DRAM_MCR_RESET);
+}
+
+static void mctl_set_drive(void)
+{
+ struct sunxi_dram_reg *dram = (struct sunxi_dram_reg *)SUNXI_DRAMC_BASE;
+
+ clrsetbits_le32(&dram->mcr, DRAM_MCR_MODE_NORM(0x3) | (0x3 << 28),
+ DRAM_MCR_MODE_EN(0x3) |
+ 0xffc);
+}
+
+static void mctl_itm_disable(void)
+{
+ struct sunxi_dram_reg *dram = (struct sunxi_dram_reg *)SUNXI_DRAMC_BASE;
+
+ clrsetbits_le32(&dram->ccr, DRAM_CCR_INIT, DRAM_CCR_ITM_OFF);
+}
+
+static void mctl_itm_enable(void)
+{
+ struct sunxi_dram_reg *dram = (struct sunxi_dram_reg *)SUNXI_DRAMC_BASE;
+
+ clrbits_le32(&dram->ccr, DRAM_CCR_ITM_OFF);
+}
+
+static void mctl_enable_dll0(u32 phase)
+{
+ struct sunxi_dram_reg *dram = (struct sunxi_dram_reg *)SUNXI_DRAMC_BASE;
+
+ clrsetbits_le32(&dram->dllcr[0], 0x3f << 6,
+ ((phase >> 16) & 0x3f) << 6);
+ clrsetbits_le32(&dram->dllcr[0], DRAM_DLLCR_NRESET, DRAM_DLLCR_DISABLE);
+ udelay(2);
+
+ clrbits_le32(&dram->dllcr[0], DRAM_DLLCR_NRESET | DRAM_DLLCR_DISABLE);
+ udelay(22);
+
+ clrsetbits_le32(&dram->dllcr[0], DRAM_DLLCR_DISABLE, DRAM_DLLCR_NRESET);
+ udelay(