diff mbox

[U-Boot,16/24] sunxi: A64: use H3 DRAM initialization code for A64

Message ID 1479653838-3574-17-git-send-email-andre.przywara@arm.com
State Superseded
Delegated to: Jagannadha Sutradharudu Teki
Headers show

Commit Message

Andre Przywara Nov. 20, 2016, 2:57 p.m. UTC
From: Jens Kuske <jenskuske@gmail.com>

The A64 DRAM controller is very similar to the H3 one,
so the code can be reused with some small changes.
[Andre: fixed up typo, merged in fixes from Jens]

Signed-off-by: Jens Kuske <jenskuske@gmail.com>
Signed-off-by: Andre Przywara <andre.przywara@arm.com>
---
 arch/arm/include/asm/arch-sunxi/clock_sun6i.h   |   1 +
 arch/arm/include/asm/arch-sunxi/dram.h          |   2 +-
 arch/arm/include/asm/arch-sunxi/dram_sun8i_h3.h |  10 +-
 arch/arm/mach-sunxi/Makefile                    |   1 +
 arch/arm/mach-sunxi/clock_sun6i.c               |   2 +-
 arch/arm/mach-sunxi/dram_sun8i_h3.c             | 139 +++++++++++++++++++-----
 6 files changed, 123 insertions(+), 32 deletions(-)
diff mbox

Patch

diff --git a/arch/arm/include/asm/arch-sunxi/clock_sun6i.h b/arch/arm/include/asm/arch-sunxi/clock_sun6i.h
index be9fcfd..3f87672 100644
--- a/arch/arm/include/asm/arch-sunxi/clock_sun6i.h
+++ b/arch/arm/include/asm/arch-sunxi/clock_sun6i.h
@@ -322,6 +322,7 @@  struct sunxi_ccm_reg {
 #define CCM_DRAMCLK_CFG_DIV0_MASK	(0xf << 8)
 #define CCM_DRAMCLK_CFG_SRC_PLL5	(0x0 << 20)
 #define CCM_DRAMCLK_CFG_SRC_PLL6x2	(0x1 << 20)
+#define CCM_DRAMCLK_CFG_SRC_PLL11	(0x1 << 20) /* A64 only */
 #define CCM_DRAMCLK_CFG_SRC_MASK	(0x3 << 20)
 #define CCM_DRAMCLK_CFG_UPD		(0x1 << 16)
 #define CCM_DRAMCLK_CFG_RST		(0x1 << 31)
diff --git a/arch/arm/include/asm/arch-sunxi/dram.h b/arch/arm/include/asm/arch-sunxi/dram.h
index e0be744..53e6d47 100644
--- a/arch/arm/include/asm/arch-sunxi/dram.h
+++ b/arch/arm/include/asm/arch-sunxi/dram.h
@@ -24,7 +24,7 @@ 
 #include <asm/arch/dram_sun8i_a33.h>
 #elif defined(CONFIG_MACH_SUN8I_A83T)
 #include <asm/arch/dram_sun8i_a83t.h>
-#elif defined(CONFIG_MACH_SUN8I_H3)
+#elif defined(CONFIG_MACH_SUN8I_H3) || defined(CONFIG_MACH_SUN50I)
 #include <asm/arch/dram_sun8i_h3.h>
 #elif defined(CONFIG_MACH_SUN9I)
 #include <asm/arch/dram_sun9i.h>
diff --git a/arch/arm/include/asm/arch-sunxi/dram_sun8i_h3.h b/arch/arm/include/asm/arch-sunxi/dram_sun8i_h3.h
index 867fd12..b0e5d93 100644
--- a/arch/arm/include/asm/arch-sunxi/dram_sun8i_h3.h
+++ b/arch/arm/include/asm/arch-sunxi/dram_sun8i_h3.h
@@ -15,7 +15,8 @@ 
 
 struct sunxi_mctl_com_reg {
 	u32 cr;			/* 0x00 control register */
-	u8 res0[0xc];		/* 0x04 */
+	u8 res0[0x8];		/* 0x04 */
+	u32 tmr;		/* 0x0c (A64 only) */
 	u32 mcr[16][2];		/* 0x10 */
 	u32 bwcr;		/* 0x90 bandwidth control register */
 	u32 maer;		/* 0x94 master enable register */
@@ -32,7 +33,9 @@  struct sunxi_mctl_com_reg {
 	u32 swoffr;		/* 0xc4 */
 	u8 res2[0x8];		/* 0xc8 */
 	u32 cccr;		/* 0xd0 */
-	u8 res3[0x72c];		/* 0xd4 */
+	u8 res3[0x54];		/* 0xd4 */
+	u32 mdfs_bwlr[3];	/* 0x128 (A64 only) */
+	u8 res4[0x6cc];		/* 0x134 */
 	u32 protect;		/* 0x800 */
 };
 
@@ -81,7 +84,8 @@  struct sunxi_mctl_ctl_reg {
 	u32 rfshtmg;		/* 0x90 refresh timing */
 	u32 rfshctl1;		/* 0x94 */
 	u32 pwrtmg;		/* 0x98 */
-	u8 res3[0x20];		/* 0x9c */
+	u8 res3[0x1c];		/* 0x9c */
+	u32 vtfcr;		/* 0xb8 (A64 only) */
 	u32 dqsgmr;		/* 0xbc */
 	u32 dtcr;		/* 0xc0 */
 	u32 dtar[4];		/* 0xc4 */
diff --git a/arch/arm/mach-sunxi/Makefile b/arch/arm/mach-sunxi/Makefile
index e73114e..7daba11 100644
--- a/arch/arm/mach-sunxi/Makefile
+++ b/arch/arm/mach-sunxi/Makefile
@@ -50,4 +50,5 @@  obj-$(CONFIG_MACH_SUN8I_A33)	+= dram_sun8i_a33.o
 obj-$(CONFIG_MACH_SUN8I_A83T)	+= dram_sun8i_a83t.o
 obj-$(CONFIG_MACH_SUN8I_H3)	+= dram_sun8i_h3.o
 obj-$(CONFIG_MACH_SUN9I)	+= dram_sun9i.o
+obj-$(CONFIG_MACH_SUN50I)	+= dram_sun8i_h3.o
 endif
diff --git a/arch/arm/mach-sunxi/clock_sun6i.c b/arch/arm/mach-sunxi/clock_sun6i.c
index 382fa94..4570060 100644
--- a/arch/arm/mach-sunxi/clock_sun6i.c
+++ b/arch/arm/mach-sunxi/clock_sun6i.c
@@ -218,7 +218,7 @@  done:
 }
 #endif
 
-#ifdef CONFIG_MACH_SUN8I_A33
+#if defined(CONFIG_MACH_SUN8I_A33) || defined(CONFIG_MACH_SUN50I)
 void clock_set_pll11(unsigned int clk, bool sigma_delta_enable)
 {
 	struct sunxi_ccm_reg * const ccm =
diff --git a/arch/arm/mach-sunxi/dram_sun8i_h3.c b/arch/arm/mach-sunxi/dram_sun8i_h3.c
index 1647d76..2dc2071 100644
--- a/arch/arm/mach-sunxi/dram_sun8i_h3.c
+++ b/arch/arm/mach-sunxi/dram_sun8i_h3.c
@@ -32,30 +32,6 @@  static inline int ns_to_t(int nanoseconds)
 	return DIV_ROUND_UP(ctrl_freq * nanoseconds, 1000);
 }
 
-static u32 bin_to_mgray(int val)
-{
-	static const u8 lookup_table[32] = {
-		0x00, 0x01, 0x02, 0x03, 0x06, 0x07, 0x04, 0x05,
-		0x0c, 0x0d, 0x0e, 0x0f, 0x0a, 0x0b, 0x08, 0x09,
-		0x18, 0x19, 0x1a, 0x1b, 0x1e, 0x1f, 0x1c, 0x1d,
-		0x14, 0x15, 0x16, 0x17, 0x12, 0x13, 0x10, 0x11,
-	};
-
-	return lookup_table[clamp(val, 0, 31)];
-}
-
-static int mgray_to_bin(u32 val)
-{
-	static const u8 lookup_table[32] = {
-		0x00, 0x01, 0x02, 0x03, 0x06, 0x07, 0x04, 0x05,
-		0x0e, 0x0f, 0x0c, 0x0d, 0x08, 0x09, 0x0a, 0x0b,
-		0x1e, 0x1f, 0x1c, 0x1d, 0x18, 0x19, 0x1a, 0x1b,
-		0x10, 0x11, 0x12, 0x13, 0x16, 0x17, 0x14, 0x15,
-	};
-
-	return lookup_table[val & 0x1f];
-}
-
 static void mctl_phy_init(u32 val)
 {
 	struct sunxi_mctl_ctl_reg * const mctl_ctl =
@@ -91,8 +67,9 @@  static void mctl_set_master_priority(void)
 	struct sunxi_mctl_com_reg * const mctl_com =
 			(struct sunxi_mctl_com_reg *)SUNXI_DRAM_COM_BASE;
 
+#if defined(CONFIG_MACH_SUN8I_H3)
 	/* enable bandwidth limit windows and set windows size 1us */
-	writel(0x00010190, &mctl_com->bwcr);
+	writel((1 << 16) | (400 << 0), &mctl_com->bwcr);
 
 	/* set cpu high priority */
 	writel(0x00000001, &mctl_com->mapr);
@@ -121,6 +98,38 @@  static void mctl_set_master_priority(void)
 	writel(0x04001800, &mctl_com->mcr[10][1]);
 	writel(0x04000009, &mctl_com->mcr[11][0]);
 	writel(0x00400120, &mctl_com->mcr[11][1]);
+#elif defined(CONFIG_MACH_SUN50I)
+	/* enable bandwidth limit windows and set windows size 1us */
+	writel(399, &mctl_com->tmr);
+	writel((1 << 16), &mctl_com->bwcr);
+
+	writel(0x00a0000d, &mctl_com->mcr[0][0]);
+	writel(0x00500064, &mctl_com->mcr[0][1]);
+	writel(0x06000009, &mctl_com->mcr[1][0]);
+	writel(0x01000578, &mctl_com->mcr[1][1]);
+	writel(0x0200000d, &mctl_com->mcr[2][0]);
+	writel(0x00600100, &mctl_com->mcr[2][1]);
+	writel(0x01000009, &mctl_com->mcr[3][0]);
+	writel(0x00500064, &mctl_com->mcr[3][1]);
+	writel(0x07000009, &mctl_com->mcr[4][0]);
+	writel(0x01000640, &mctl_com->mcr[4][1]);
+	writel(0x01000009, &mctl_com->mcr[5][0]);
+	writel(0x00000080, &mctl_com->mcr[5][1]);
+	writel(0x01000009, &mctl_com->mcr[6][0]);
+	writel(0x00400080, &mctl_com->mcr[6][1]);
+	writel(0x0100000d, &mctl_com->mcr[7][0]);
+	writel(0x00400080, &mctl_com->mcr[7][1]);
+	writel(0x0100000d, &mctl_com->mcr[8][0]);
+	writel(0x00400080, &mctl_com->mcr[8][1]);
+	writel(0x04000009, &mctl_com->mcr[9][0]);
+	writel(0x00400100, &mctl_com->mcr[9][1]);
+	writel(0x20000209, &mctl_com->mcr[10][0]);
+	writel(0x08001800, &mctl_com->mcr[10][1]);
+	writel(0x05000009, &mctl_com->mcr[11][0]);
+	writel(0x00400090, &mctl_com->mcr[11][1]);
+
+	writel(0x81000004, &mctl_com->mdfs_bwlr[2]);
+#endif
 }
 
 static void mctl_set_timing_params(struct dram_para *para)
@@ -204,7 +213,32 @@  static void mctl_set_timing_params(struct dram_para *para)
 	writel(RFSHTMG_TREFI(trefi) | RFSHTMG_TRFC(trfc), &mctl_ctl->rfshtmg);
 }
 
-static void mctl_zq_calibration(struct dram_para *para)
+#ifdef CONFIG_MACH_SUN8I_H3
+static u32 bin_to_mgray(int val)
+{
+	static const u8 lookup_table[32] = {
+		0x00, 0x01, 0x02, 0x03, 0x06, 0x07, 0x04, 0x05,
+		0x0c, 0x0d, 0x0e, 0x0f, 0x0a, 0x0b, 0x08, 0x09,
+		0x18, 0x19, 0x1a, 0x1b, 0x1e, 0x1f, 0x1c, 0x1d,
+		0x14, 0x15, 0x16, 0x17, 0x12, 0x13, 0x10, 0x11,
+	};
+
+	return lookup_table[clamp(val, 0, 31)];
+}
+
+static int mgray_to_bin(u32 val)
+{
+	static const u8 lookup_table[32] = {
+		0x00, 0x01, 0x02, 0x03, 0x06, 0x07, 0x04, 0x05,
+		0x0e, 0x0f, 0x0c, 0x0d, 0x08, 0x09, 0x0a, 0x0b,
+		0x1e, 0x1f, 0x1c, 0x1d, 0x18, 0x19, 0x1a, 0x1b,
+		0x10, 0x11, 0x12, 0x13, 0x16, 0x17, 0x14, 0x15,
+	};
+
+	return lookup_table[val & 0x1f];
+}
+
+static void mctl_h3_zq_calibration_quirk(struct dram_para *para)
 {
 	struct sunxi_mctl_ctl_reg * const mctl_ctl =
 			(struct sunxi_mctl_ctl_reg *)SUNXI_DRAM_CTL0_BASE;
@@ -261,6 +295,7 @@  static void mctl_zq_calibration(struct dram_para *para)
 		writel((zq_val[5] << 16) | zq_val[4], &mctl_ctl->zqdr[2]);
 	}
 }
+#endif
 
 static void mctl_set_cr(struct dram_para *para)
 {
@@ -286,16 +321,27 @@  static void mctl_sys_init(struct dram_para *para)
 	clrbits_le32(&ccm->ahb_gate0, 1 << AHB_GATE_OFFSET_MCTL);
 	clrbits_le32(&ccm->ahb_reset0_cfg, 1 << AHB_RESET_OFFSET_MCTL);
 	clrbits_le32(&ccm->pll5_cfg, CCM_PLL5_CTRL_EN);
+#ifdef CONFIG_MACH_SUN50I
+	clrbits_le32(&ccm->pll11_cfg, CCM_PLL11_CTRL_EN);
+#endif
 	udelay(10);
 
 	clrbits_le32(&ccm->dram_clk_cfg, CCM_DRAMCLK_CFG_RST);
 	udelay(1000);
 
+#ifdef CONFIG_MACH_SUN50I
+	clock_set_pll11(CONFIG_DRAM_CLK * 2 * 1000000, false);
+	clrsetbits_le32(&ccm->dram_clk_cfg,
+			CCM_DRAMCLK_CFG_DIV_MASK | CCM_DRAMCLK_CFG_SRC_MASK,
+			CCM_DRAMCLK_CFG_DIV(1) | CCM_DRAMCLK_CFG_SRC_PLL11 |
+			CCM_DRAMCLK_CFG_UPD);
+#else
 	clock_set_pll5(CONFIG_DRAM_CLK * 2 * 1000000, false);
 	clrsetbits_le32(&ccm->dram_clk_cfg,
 			CCM_DRAMCLK_CFG_DIV_MASK | CCM_DRAMCLK_CFG_SRC_MASK,
 			CCM_DRAMCLK_CFG_DIV(1) | CCM_DRAMCLK_CFG_SRC_PLL5 |
 			CCM_DRAMCLK_CFG_UPD);
+#endif
 	mctl_await_completion(&ccm->dram_clk_cfg, CCM_DRAMCLK_CFG_UPD, 0);
 
 	setbits_le32(&ccm->ahb_reset0_cfg, 1 << AHB_RESET_OFFSET_MCTL);
@@ -347,12 +393,18 @@  static int mctl_channel_init(struct dram_para *para)
 	/* set DQS auto gating PD mode */
 	setbits_le32(&mctl_ctl->pgcr[2], 0x3 << 6);
 
+#if defined(CONFIG_MACH_SUN8I_H3)
 	/* dx ddr_clk & hdr_clk dynamic mode */
 	clrbits_le32(&mctl_ctl->pgcr[0], (0x3 << 14) | (0x3 << 12));
 
 	/* dphy & aphy phase select 270 degree */
 	clrsetbits_le32(&mctl_ctl->pgcr[2], (0x3 << 10) | (0x3 << 8),
 			(0x1 << 10) | (0x2 << 8));
+#elif defined(CONFIG_MACH_SUN50I)
+	/* dphy & aphy phase select ? */
+	clrsetbits_le32(&mctl_ctl->pgcr[2], (0x3 << 10) | (0x3 << 8),
+			(0x0 << 10) | (0x3 << 8));
+#endif
 
 	/* set half DQ */
 	if (para->bus_width != 32) {
@@ -367,10 +419,17 @@  static int mctl_channel_init(struct dram_para *para)
 	mctl_set_bit_delays(para);
 	udelay(50);
 
-	mctl_zq_calibration(para);
+#ifdef CONFIG_MACH_SUN8I_H3
+	mctl_h3_zq_calibration_quirk(para);
 
 	mctl_phy_init(PIR_PLLINIT | PIR_DCAL | PIR_PHYRST | PIR_DRAMRST |
 		      PIR_DRAMINIT | PIR_QSGATE);
+#else
+	clrsetbits_le32(&mctl_ctl->zqcr, 0xffffff, CONFIG_DRAM_ZQ);
+
+	mctl_phy_init(PIR_ZCAL | PIR_PLLINIT | PIR_DCAL | PIR_PHYRST |
+		      PIR_DRAMRST | PIR_DRAMINIT | PIR_QSGATE);
+#endif
 
 	/* detect ranks and bus width */
 	if (readl(&mctl_ctl->pgsr[0]) & (0xfe << 20)) {
@@ -408,7 +467,11 @@  static int mctl_channel_init(struct dram_para *para)
 	udelay(10);
 
 	/* set PGCR3, CKE polarity */
+#ifdef CONFIG_MACH_SUN50I
+	writel(0xc0aa0060, &mctl_ctl->pgcr[3]);
+#else
 	writel(0x00aa0060, &mctl_ctl->pgcr[3]);
+#endif
 
 	/* power down zq calibration module for power save */
 	setbits_le32(&mctl_ctl->zqcr, ZQCR_PWRDOWN);
@@ -452,6 +515,7 @@  unsigned long sunxi_dram_init(void)
 		.row_bits = 15,
 		.page_size = 4096,
 
+#if defined(CONFIG_MACH_SUN8I_H3)
 		.dx_read_delays =  {{ 18, 18, 18, 18, 18, 18, 18, 18, 18,  0,  0 },
 		                    { 14, 14, 14, 14, 14, 14, 14, 14, 14,  0,  0 },
 		                    { 18, 18, 18, 18, 18, 18, 18, 18, 18,  0,  0 },
@@ -464,6 +528,20 @@  unsigned long sunxi_dram_init(void)
 		                0,  0,  0,  0,  0,  0,  0,  0,
 		                0,  0,  0,  0,  0,  0,  0,  0,
 		                0,  0,  0,  0,  0,  0,  0      },
+#elif defined(CONFIG_MACH_SUN50I)
+		.dx_read_delays =  {{ 16, 16, 16, 16, 17, 16, 16, 17, 16,  1,  0 },
+		                    { 17, 17, 17, 17, 17, 17, 17, 17, 17,  1,  0 },
+		                    { 16, 17, 17, 16, 16, 16, 16, 16, 16,  0,  0 },
+		                    { 17, 17, 17, 17, 17, 17, 17, 17, 17,  1,  0 }},
+		.dx_write_delays = {{  0,  0,  0,  0,  0,  0,  0,  0,  0, 15, 15 },
+		                    {  0,  0,  0,  0,  1,  1,  1,  1,  0, 10, 10 },
+		                    {  1,  0,  1,  1,  1,  1,  1,  1,  0, 11, 11 },
+		                    {  1,  0,  0,  1,  1,  1,  1,  1,  0, 12, 12 }},
+		.ac_delays = {  5,  5, 13, 10,  2,  5,  3,  3,
+		                0,  3,  3,  3,  1,  0,  0,  0,
+		                3,  4,  0,  3,  4,  1,  4,  0,
+		                1,  1,  0,  1, 13,  5,  4      },
+#endif
 	};
 
 	mctl_sys_init(&para);
@@ -476,8 +554,15 @@  unsigned long sunxi_dram_init(void)
 		writel(0x00000201, &mctl_ctl->odtmap);
 	udelay(1);
 
+#ifdef CONFIG_MACH_SUN8I_H3
 	/* odt delay */
 	writel(0x0c000400, &mctl_ctl->odtcfg);
+#endif
+
+#ifdef CONFIG_MACH_SUN50I
+	setbits_le32(&mctl_ctl->vtfcr, (1 << 9));
+	clrbits_le32(&mctl_ctl->pgcr[2], (1 << 13));
+#endif
 
 	/* clear credit value */
 	setbits_le32(&mctl_com->cccr, 1 << 31);