[U-Boot] [PATCH 06/14] sunxi: dram: Configurable MBUS clock speed (use PLL5 or PLL6)

Siarhei Siamashka siarhei.siamashka at gmail.com
Fri Jul 18 18:22:57 CEST 2014


The sun5i hardware (Allwinner A13) introduced configurable MBUS clock speed.
Allwinner A13 uses only 16-bit data bus width to connect the external DRAM,
which is halved compared to the 32-bit data bus of sun4i (Allwinner A10), so
it does not make much sense to clock a wider internal bus at a very high speed.
The Allwinner A13 manual specifies 300 MHz MBUS clock speed limit and 533 MHz
DRAM clock speed limit. Newer sun7i hardware (Allwinner A20) has a full width
32-bit external memory interface again, but still keeps the MBUS clock speed
configurable. Clocking MBUS too low inhibits memory performance and one has
to find the optimal MBUS/DRAM clock speed ratio, which may depend on many
factors.

This patch introduces a new 'mbus_clock' parameter for the 'dram_para' struct
and uses it as a desired MBUS clock speed target. If 'mbus_clock' is not set,
300 MHz is used by default to match the older hardcoded settings.

Attempting to set the MBUS clock speed has no effect on sun4i, but does no
harm either.

Signed-off-by: Siarhei Siamashka <siarhei.siamashka at gmail.com>
---
 arch/arm/cpu/armv7/sunxi/dram.c        | 41 +++++++++++++++++++++++++++++-----
 arch/arm/include/asm/arch-sunxi/dram.h |  1 +
 2 files changed, 36 insertions(+), 6 deletions(-)

diff --git a/arch/arm/cpu/armv7/sunxi/dram.c b/arch/arm/cpu/armv7/sunxi/dram.c
index afeb2df..d41fb1e 100644
--- a/arch/arm/cpu/armv7/sunxi/dram.c
+++ b/arch/arm/cpu/armv7/sunxi/dram.c
@@ -178,11 +178,19 @@ static void mctl_configure_hostport(void)
 		writel(hpcr_value[i], &dram->hpcr[i]);
 }
 
-static void mctl_setup_dram_clock(u32 clk)
+static void mctl_setup_dram_clock(u32 clk, u32 mbus_clk)
 {
 	u32 reg_val;
 	struct sunxi_ccm_reg *ccm = (struct sunxi_ccm_reg *)SUNXI_CCM_BASE;
 
+	/* PLL5P and PLL6 are the potential clock sources for MBUS */
+	u32 pll6x_div, pll5p_div;
+	u32 pll6x_clk = clock_get_pll6() / 1000000;
+	u32 pll5p_clk = clk / 24 * 24;
+#ifdef CONFIG_SUN7I
+	pll6x_clk *= 2; /* sun7i uses PLL6*2, sun5i uses just PLL6 */
+#endif
+
 	/* setup DRAM PLL */
 	reg_val = readl(&ccm->pll5_cfg);
 	reg_val &= ~CCM_PLL5_CTRL_M_MASK;		/* set M to 0 (x1) */
@@ -191,30 +199,35 @@ static void mctl_setup_dram_clock(u32 clk)
 	reg_val &= ~CCM_PLL5_CTRL_P_MASK;		/* set P to 0 (x1) */
 	if (clk >= 540 && clk < 552) {
 		/* dram = 540MHz, pll5p = 540MHz */
+		pll5p_clk = 540;
 		reg_val |= CCM_PLL5_CTRL_M(CCM_PLL5_CTRL_M_X(2));
 		reg_val |= CCM_PLL5_CTRL_K(CCM_PLL5_CTRL_K_X(3));
 		reg_val |= CCM_PLL5_CTRL_N(CCM_PLL5_CTRL_N_X(15));
 		reg_val |= CCM_PLL5_CTRL_P(1);
 	} else if (clk >= 512 && clk < 528) {
 		/* dram = 512MHz, pll5p = 384MHz */
+		pll5p_clk = 384;
 		reg_val |= CCM_PLL5_CTRL_M(CCM_PLL5_CTRL_M_X(3));
 		reg_val |= CCM_PLL5_CTRL_K(CCM_PLL5_CTRL_K_X(4));
 		reg_val |= CCM_PLL5_CTRL_N(CCM_PLL5_CTRL_N_X(16));
 		reg_val |= CCM_PLL5_CTRL_P(2);
 	} else if (clk >= 496 && clk < 504) {
 		/* dram = 496MHz, pll5p = 372MHz */
+		pll5p_clk = 372;
 		reg_val |= CCM_PLL5_CTRL_M(CCM_PLL5_CTRL_M_X(3));
 		reg_val |= CCM_PLL5_CTRL_K(CCM_PLL5_CTRL_K_X(2));
 		reg_val |= CCM_PLL5_CTRL_N(CCM_PLL5_CTRL_N_X(31));
 		reg_val |= CCM_PLL5_CTRL_P(2);
 	} else if (clk >= 468 && clk < 480) {
 		/* dram = 468MHz, pll5p = 468MHz */
+		pll5p_clk = 468;
 		reg_val |= CCM_PLL5_CTRL_M(CCM_PLL5_CTRL_M_X(2));
 		reg_val |= CCM_PLL5_CTRL_K(CCM_PLL5_CTRL_K_X(3));
 		reg_val |= CCM_PLL5_CTRL_N(CCM_PLL5_CTRL_N_X(13));
 		reg_val |= CCM_PLL5_CTRL_P(1);
 	} else if (clk >= 396 && clk < 408) {
 		/* dram = 396MHz, pll5p = 396MHz */
+		pll5p_clk = 396;
 		reg_val |= CCM_PLL5_CTRL_M(CCM_PLL5_CTRL_M_X(2));
 		reg_val |= CCM_PLL5_CTRL_K(CCM_PLL5_CTRL_K_X(3));
 		reg_val |= CCM_PLL5_CTRL_N(CCM_PLL5_CTRL_N_X(11));
@@ -242,10 +255,26 @@ static void mctl_setup_dram_clock(u32 clk)
 #endif
 
 	/* setup MBUS clock */
-	reg_val = CCM_MBUS_CTRL_GATE |
-		  CCM_MBUS_CTRL_CLK_SRC(CCM_MBUS_CTRL_CLK_SRC_PLL6) |
-		  CCM_MBUS_CTRL_N(CCM_MBUS_CTRL_N_X(2)) |
-		  CCM_MBUS_CTRL_M(CCM_MBUS_CTRL_M_X(2));
+	if (!mbus_clk)
+		mbus_clk = 300;
+	pll6x_div = (pll6x_clk + mbus_clk - 1) / mbus_clk;
+	pll5p_div = (pll5p_clk + mbus_clk - 1) / mbus_clk;
+
+	if (pll6x_div <= 16 && pll6x_clk / pll6x_div > pll5p_clk / pll5p_div) {
+		/* use PLL6 as the MBUS clock source */
+		reg_val = CCM_MBUS_CTRL_GATE |
+			  CCM_MBUS_CTRL_CLK_SRC(CCM_MBUS_CTRL_CLK_SRC_PLL6) |
+			  CCM_MBUS_CTRL_N(CCM_MBUS_CTRL_N_X(1)) |
+			  CCM_MBUS_CTRL_M(CCM_MBUS_CTRL_M_X(pll6x_div));
+	} else if (pll5p_div <= 16) {
+		/* use PLL5P as the MBUS clock source */
+		reg_val = CCM_MBUS_CTRL_GATE |
+			  CCM_MBUS_CTRL_CLK_SRC(CCM_MBUS_CTRL_CLK_SRC_PLL5) |
+			  CCM_MBUS_CTRL_N(CCM_MBUS_CTRL_N_X(1)) |
+			  CCM_MBUS_CTRL_M(CCM_MBUS_CTRL_M_X(pll5p_div));
+	} else {
+		panic("Bad mbus_clk\n");
+	}
 	writel(reg_val, &ccm->mbus_clk_cfg);
 
 	/*
@@ -423,7 +452,7 @@ unsigned long dramc_init(struct dram_para *para)
 		return 0;
 
 	/* setup DRAM relative clock */
-	mctl_setup_dram_clock(para->clock);
+	mctl_setup_dram_clock(para->clock, para->mbus_clock);
 
 	/* Disable any pad power save control */
 	mctl_disable_power_save();
diff --git a/arch/arm/include/asm/arch-sunxi/dram.h b/arch/arm/include/asm/arch-sunxi/dram.h
index 4433eeb..3c29256 100644
--- a/arch/arm/include/asm/arch-sunxi/dram.h
+++ b/arch/arm/include/asm/arch-sunxi/dram.h
@@ -69,6 +69,7 @@ struct sunxi_dram_reg {
 
 struct dram_para {
 	u32 clock;
+	u32 mbus_clock;
 	u32 type;
 	u32 rank_num;
 	u32 density;
-- 
1.8.3.2



More information about the U-Boot mailing list