[PATCH 3/5] sunxi: H616: dram: split struct dram_para

Andre Przywara andre.przywara at arm.com
Wed Jun 7 02:07:43 CEST 2023


Currently there is one DRAM parameter struct for the Allwinner H616 DRAM
"driver". It contains many fields that are compile time constants
(set by Kconfig variables), though there are also some fields that are
probed and changed over the runtime of the DRAM initialisation.

Because of this mixture, the compiler cannot properly optimise the code
for size, as it does not consider constant propagation in its full
potential.

Help the compiler out by splitting that structure into two: one that only
contains values known at compile time, and another one where the values
will actually change. The former can then be declared "const", which will
let the compiler fold its values directly into the code using it.

We also add "const" tags for some new "struct dram_config" pointers, to
further increase code optimisation.
To help the compiler optimise the code further, the definition of the
now "const struct dram_para" has to happen at a file-global level, so
move that part out of sunxi_dram_init().

That results in quite some code savings (almost 2KB), and helps to keep
the code small with the LPDDR3 support added later.

Signed-off-by: Andre Przywara <andre.przywara at arm.com>
---
 .../include/asm/arch-sunxi/dram_sun50i_h616.h |  10 +-
 arch/arm/mach-sunxi/dram_sun50i_h616.c        | 182 +++++++++---------
 2 files changed, 101 insertions(+), 91 deletions(-)

diff --git a/arch/arm/include/asm/arch-sunxi/dram_sun50i_h616.h b/arch/arm/include/asm/arch-sunxi/dram_sun50i_h616.h
index 34d19f71438..11774deded0 100644
--- a/arch/arm/include/asm/arch-sunxi/dram_sun50i_h616.h
+++ b/arch/arm/include/asm/arch-sunxi/dram_sun50i_h616.h
@@ -148,10 +148,6 @@ check_member(sunxi_mctl_ctl_reg, unk_0x4240, 0x4240);
 struct dram_para {
 	u32 clk;
 	enum sunxi_dram_type type;
-	u8 cols;
-	u8 rows;
-	u8 ranks;
-	u8 bus_full_width;
 	u32 dx_odt;
 	u32 dx_dri;
 	u32 ca_dri;
@@ -163,6 +159,12 @@ struct dram_para {
 	u32 tpr12;
 };
 
+struct dram_config {
+	u8 cols;
+	u8 rows;
+	u8 ranks;
+	u8 bus_full_width;
+};
 
 static inline int ns_to_t(int nanoseconds)
 {
diff --git a/arch/arm/mach-sunxi/dram_sun50i_h616.c b/arch/arm/mach-sunxi/dram_sun50i_h616.c
index e0ee764cec7..4e988cebf59 100644
--- a/arch/arm/mach-sunxi/dram_sun50i_h616.c
+++ b/arch/arm/mach-sunxi/dram_sun50i_h616.c
@@ -141,15 +141,15 @@ static void mctl_sys_init(u32 clk_rate)
 	writel(0x8000, &mctl_ctl->clken);
 }
 
-static void mctl_set_addrmap(const struct dram_para *para)
+static void mctl_set_addrmap(const struct dram_config *config)
 {
 	struct sunxi_mctl_ctl_reg * const mctl_ctl =
 			(struct sunxi_mctl_ctl_reg *)SUNXI_DRAM_CTL0_BASE;
-	u8 cols = para->cols;
-	u8 rows = para->rows;
-	u8 ranks = para->ranks;
+	u8 cols = config->cols;
+	u8 rows = config->rows;
+	u8 ranks = config->ranks;
 
-	if (!para->bus_full_width)
+	if (!config->bus_full_width)
 		cols -= 1;
 
 	/* Ranks */
@@ -281,7 +281,7 @@ static void mctl_phy_configure_odt(const struct dram_para *para)
 	dmb();
 }
 
-static bool mctl_phy_write_leveling(const struct dram_para *para)
+static bool mctl_phy_write_leveling(const struct dram_config *config)
 {
 	bool result = true;
 	u32 val;
@@ -292,7 +292,7 @@ static bool mctl_phy_write_leveling(const struct dram_para *para)
 
 	setbits_le32(SUNXI_DRAM_PHY0_BASE + 8, 4);
 
-	if (para->bus_full_width)
+	if (config->bus_full_width)
 		val = 0xf;
 	else
 		val = 3;
@@ -316,12 +316,12 @@ static bool mctl_phy_write_leveling(const struct dram_para *para)
 
 	clrbits_le32(SUNXI_DRAM_PHY0_BASE + 8, 0xc0);
 
-	if (para->ranks == 2) {
+	if (config->ranks == 2) {
 		clrsetbits_le32(SUNXI_DRAM_PHY0_BASE + 8, 0xc0, 0x40);
 
 		setbits_le32(SUNXI_DRAM_PHY0_BASE + 8, 4);
 
-		if (para->bus_full_width)
+		if (config->bus_full_width)
 			val = 0xf;
 		else
 			val = 3;
@@ -336,7 +336,7 @@ static bool mctl_phy_write_leveling(const struct dram_para *para)
 	return result;
 }
 
-static bool mctl_phy_read_calibration(const struct dram_para *para)
+static bool mctl_phy_read_calibration(const struct dram_config *config)
 {
 	bool result = true;
 	u32 val, tmp;
@@ -345,7 +345,7 @@ static bool mctl_phy_read_calibration(const struct dram_para *para)
 
 	setbits_le32(SUNXI_DRAM_PHY0_BASE + 8, 1);
 
-	if (para->bus_full_width)
+	if (config->bus_full_width)
 		val = 0xf;
 	else
 		val = 3;
@@ -361,7 +361,7 @@ static bool mctl_phy_read_calibration(const struct dram_para *para)
 
 	clrbits_le32(SUNXI_DRAM_PHY0_BASE + 8, 0x30);
 
-	if (para->ranks == 2) {
+	if (config->ranks == 2) {
 		clrsetbits_le32(SUNXI_DRAM_PHY0_BASE + 8, 0x30, 0x10);
 
 		setbits_le32(SUNXI_DRAM_PHY0_BASE + 8, 1);
@@ -395,7 +395,7 @@ static bool mctl_phy_read_calibration(const struct dram_para *para)
 	return result;
 }
 
-static bool mctl_phy_read_training(const struct dram_para *para)
+static bool mctl_phy_read_training(const struct dram_config *config)
 {
 	u32 val1, val2, *ptr1, *ptr2;
 	bool result = true;
@@ -414,7 +414,7 @@ static bool mctl_phy_read_training(const struct dram_para *para)
 	if (readl(SUNXI_DRAM_PHY0_BASE + 0x840) & 3)
 		result = false;
 
-	if (para->bus_full_width) {
+	if (config->bus_full_width) {
 		mctl_await_completion((u32 *)(SUNXI_DRAM_PHY0_BASE + 0xa40), 0xc, 0xc);
 		if (readl(SUNXI_DRAM_PHY0_BASE + 0xa40) & 3)
 			result = false;
@@ -437,7 +437,7 @@ static bool mctl_phy_read_training(const struct dram_para *para)
 			result = false;
 	}
 
-	if (para->bus_full_width) {
+	if (config->bus_full_width) {
 		ptr1 = (u32 *)(SUNXI_DRAM_PHY0_BASE + 0xa98);
 		ptr2 = (u32 *)(SUNXI_DRAM_PHY0_BASE + 0xa50);
 		for (i = 0; i < 9; i++) {
@@ -459,7 +459,7 @@ static bool mctl_phy_read_training(const struct dram_para *para)
 
 	clrbits_le32(SUNXI_DRAM_PHY0_BASE + 0x190, 3);
 
-	if (para->ranks == 2) {
+	if (config->ranks == 2) {
 		/* maybe last parameter should be 1? */
 		clrsetbits_le32(SUNXI_DRAM_PHY0_BASE + 0x198, 3, 2);
 
@@ -470,7 +470,7 @@ static bool mctl_phy_read_training(const struct dram_para *para)
 		if (readl(SUNXI_DRAM_PHY0_BASE + 0x840) & 3)
 			result = false;
 
-		if (para->bus_full_width) {
+		if (config->bus_full_width) {
 			mctl_await_completion((u32 *)(SUNXI_DRAM_PHY0_BASE + 0xa40), 0xc, 0xc);
 			if (readl(SUNXI_DRAM_PHY0_BASE + 0xa40) & 3)
 				result = false;
@@ -484,7 +484,7 @@ static bool mctl_phy_read_training(const struct dram_para *para)
 	return result;
 }
 
-static bool mctl_phy_write_training(const struct dram_para *para)
+static bool mctl_phy_write_training(const struct dram_config *config)
 {
 	u32 val1, val2, *ptr1, *ptr2;
 	bool result = true;
@@ -504,7 +504,7 @@ static bool mctl_phy_write_training(const struct dram_para *para)
 	if (readl(SUNXI_DRAM_PHY0_BASE + 0x8e0) & 0xc)
 		result = false;
 
-	if (para->bus_full_width) {
+	if (config->bus_full_width) {
 		mctl_await_completion((u32 *)(SUNXI_DRAM_PHY0_BASE + 0xae0), 3, 3);
 		if (readl(SUNXI_DRAM_PHY0_BASE + 0xae0) & 0xc)
 			result = false;
@@ -527,7 +527,7 @@ static bool mctl_phy_write_training(const struct dram_para *para)
 			result = false;
 	}
 
-	if (para->bus_full_width) {
+	if (config->bus_full_width) {
 		ptr1 = (u32 *)(SUNXI_DRAM_PHY0_BASE + 0xb38);
 		ptr2 = (u32 *)(SUNXI_DRAM_PHY0_BASE + 0xaf0);
 		for (i = 0; i < 9; i++) {
@@ -548,7 +548,7 @@ static bool mctl_phy_write_training(const struct dram_para *para)
 
 	clrbits_le32(SUNXI_DRAM_PHY0_BASE + 0x190, 0x60);
 
-	if (para->ranks == 2) {
+	if (config->ranks == 2) {
 		clrsetbits_le32(SUNXI_DRAM_PHY0_BASE + 0x198, 0xc, 4);
 
 		setbits_le32(SUNXI_DRAM_PHY0_BASE + 0x190, 0x10);
@@ -558,7 +558,7 @@ static bool mctl_phy_write_training(const struct dram_para *para)
 		if (readl(SUNXI_DRAM_PHY0_BASE + 0x8e0) & 0xc)
 			result = false;
 
-		if (para->bus_full_width) {
+		if (config->bus_full_width) {
 			mctl_await_completion((u32 *)(SUNXI_DRAM_PHY0_BASE + 0xae0), 3, 3);
 			if (readl(SUNXI_DRAM_PHY0_BASE + 0xae0) & 0xc)
 				result = false;
@@ -773,7 +773,8 @@ static void mctl_phy_bit_delay_compensation(const struct dram_para *para)
 	}
 }
 
-static void mctl_phy_ca_bit_delay_compensation(const struct dram_para *para)
+static void mctl_phy_ca_bit_delay_compensation(const struct dram_para *para,
+					       const struct dram_config *config)
 {
 	u32 val, *ptr;
 	int i;
@@ -797,7 +798,7 @@ static void mctl_phy_ca_bit_delay_compensation(const struct dram_para *para)
 	val = (para->tpr10 >> 7) & 0x1e;
 	if (para->tpr2 & 1) {
 		writel(val, SUNXI_DRAM_PHY0_BASE + 0x794);
-		if (para->ranks == 2) {
+		if (config->ranks == 2) {
 			val = (para->tpr10 >> 11) & 0x1e;
 			writel(val, SUNXI_DRAM_PHY0_BASE + 0x7e4);
 		}
@@ -809,7 +810,7 @@ static void mctl_phy_ca_bit_delay_compensation(const struct dram_para *para)
 		}
 	} else {
 		writel(val, SUNXI_DRAM_PHY0_BASE + 0x7d4);
-		if (para->ranks == 2) {
+		if (config->ranks == 2) {
 			val = (para->tpr10 >> 11) & 0x1e;
 			writel(val, SUNXI_DRAM_PHY0_BASE + 0x79c);
 		}
@@ -822,7 +823,8 @@ static void mctl_phy_ca_bit_delay_compensation(const struct dram_para *para)
 	}
 }
 
-static bool mctl_phy_init(const struct dram_para *para)
+static bool mctl_phy_init(const struct dram_para *para,
+			  const struct dram_config *config)
 {
 	struct sunxi_mctl_com_reg * const mctl_com =
 			(struct sunxi_mctl_com_reg *)SUNXI_DRAM_COM_BASE;
@@ -831,7 +833,7 @@ static bool mctl_phy_init(const struct dram_para *para)
 	u32 val, val2, *ptr, mr0, mr2;
 	int i;
 
-	if (para->bus_full_width)
+	if (config->bus_full_width)
 		val = 0xf;
 	else
 		val = 3;
@@ -865,7 +867,7 @@ static bool mctl_phy_init(const struct dram_para *para)
 		writel(phy_init[i], &ptr[i]);
 
 	if (para->tpr10 & TPR10_CA_BIT_DELAY)
-		mctl_phy_ca_bit_delay_compensation(para);
+		mctl_phy_ca_bit_delay_compensation(para, config);
 
 	writel(0x80, SUNXI_DRAM_PHY0_BASE + 0x3dc);
 	writel(0x80, SUNXI_DRAM_PHY0_BASE + 0x45c);
@@ -946,7 +948,7 @@ static bool mctl_phy_init(const struct dram_para *para)
 
 	if (para->tpr10 & TPR10_WRITE_LEVELING) {
 		for (i = 0; i < 5; i++)
-			if (mctl_phy_write_leveling(para))
+			if (mctl_phy_write_leveling(config))
 				break;
 		if (i == 5) {
 			debug("write leveling failed!\n");
@@ -956,7 +958,7 @@ static bool mctl_phy_init(const struct dram_para *para)
 
 	if (para->tpr10 & TPR10_READ_CALIBRATION) {
 		for (i = 0; i < 5; i++)
-			if (mctl_phy_read_calibration(para))
+			if (mctl_phy_read_calibration(config))
 				break;
 		if (i == 5) {
 			debug("read calibration failed!\n");
@@ -966,7 +968,7 @@ static bool mctl_phy_init(const struct dram_para *para)
 
 	if (para->tpr10 & TPR10_READ_TRAINING) {
 		for (i = 0; i < 5; i++)
-			if (mctl_phy_read_training(para))
+			if (mctl_phy_read_training(config))
 				break;
 		if (i == 5) {
 			debug("read training failed!\n");
@@ -976,7 +978,7 @@ static bool mctl_phy_init(const struct dram_para *para)
 
 	if (para->tpr10 & TPR10_WRITE_TRAINING) {
 		for (i = 0; i < 5; i++)
-			if (mctl_phy_write_training(para))
+			if (mctl_phy_write_training(config))
 				break;
 		if (i == 5) {
 			debug("write training failed!\n");
@@ -991,7 +993,8 @@ static bool mctl_phy_init(const struct dram_para *para)
 	return true;
 }
 
-static bool mctl_ctrl_init(const struct dram_para *para)
+static bool mctl_ctrl_init(const struct dram_para *para,
+			   const struct dram_config *config)
 {
 	struct sunxi_mctl_com_reg * const mctl_com =
 			(struct sunxi_mctl_com_reg *)SUNXI_DRAM_COM_BASE;
@@ -1010,15 +1013,15 @@ static bool mctl_ctrl_init(const struct dram_para *para)
 
 	setbits_le32(&mctl_com->unk_0x008, 0xff00);
 
-	reg_val = MSTR_BURST_LENGTH(8) | MSTR_ACTIVE_RANKS(para->ranks);
+	reg_val = MSTR_BURST_LENGTH(8) | MSTR_ACTIVE_RANKS(config->ranks);
 	reg_val |= MSTR_DEVICETYPE_DDR3 | MSTR_2TMODE;
-	if (para->bus_full_width)
+	if (config->bus_full_width)
 		reg_val |= MSTR_BUSWIDTH_FULL;
 	else
 		reg_val |= MSTR_BUSWIDTH_HALF;
 	writel(BIT(31) | BIT(30) | reg_val, &mctl_ctl->mstr);
 
-	if (para->ranks == 2)
+	if (config->ranks == 2)
 		writel(0x0303, &mctl_ctl->odtmap);
 	else
 		writel(0x0201, &mctl_ctl->odtmap);
@@ -1030,7 +1033,7 @@ static bool mctl_ctrl_init(const struct dram_para *para)
 
 	writel(BIT(31), &mctl_com->cr);
 
-	mctl_set_addrmap(para);
+	mctl_set_addrmap(config);
 
 	mctl_set_timing_params(para);
 
@@ -1056,7 +1059,7 @@ static bool mctl_ctrl_init(const struct dram_para *para)
 	/* this write seems to enable PHY MMIO region */
 	setbits_le32(&mctl_com->unk_0x500, BIT(24));
 
-	if (!mctl_phy_init(para))
+	if (!mctl_phy_init(para, config))
 		return false;
 
 	writel(0, &mctl_ctl->swctl);
@@ -1073,18 +1076,20 @@ static bool mctl_ctrl_init(const struct dram_para *para)
 	return true;
 }
 
-static bool mctl_core_init(const struct dram_para *para)
+static bool mctl_core_init(const struct dram_para *para,
+			   const struct dram_config *config)
 {
 	mctl_sys_init(para->clk);
 
-	return mctl_ctrl_init(para);
+	return mctl_ctrl_init(para, config);
 }
 
-static void mctl_auto_detect_rank_width(struct dram_para *para)
+static void mctl_auto_detect_rank_width(const struct dram_para *para,
+					struct dram_config *config)
 {
 	/* this is minimum size that it's supported */
-	para->cols = 8;
-	para->rows = 13;
+	config->cols = 8;
+	config->rows = 13;
 
 	/*
 	 * Strategy here is to test most demanding combination first and least
@@ -1095,94 +1100,97 @@ static void mctl_auto_detect_rank_width(struct dram_para *para)
 	 */
 
 	debug("testing 32-bit width, rank = 2\n");
-	para->bus_full_width = 1;
-	para->ranks = 2;
-	if (mctl_core_init(para))
+	config->bus_full_width = 1;
+	config->ranks = 2;
+	if (mctl_core_init(para, config))
 		return;
 
 	debug("testing 32-bit width, rank = 1\n");
-	para->bus_full_width = 1;
-	para->ranks = 1;
-	if (mctl_core_init(para))
+	config->bus_full_width = 1;
+	config->ranks = 1;
+	if (mctl_core_init(para, config))
 		return;
 
 	debug("testing 16-bit width, rank = 2\n");
-	para->bus_full_width = 0;
-	para->ranks = 2;
-	if (mctl_core_init(para))
+	config->bus_full_width = 0;
+	config->ranks = 2;
+	if (mctl_core_init(para, config))
 		return;
 
 	debug("testing 16-bit width, rank = 1\n");
-	para->bus_full_width = 0;
-	para->ranks = 1;
-	if (mctl_core_init(para))
+	config->bus_full_width = 0;
+	config->ranks = 1;
+	if (mctl_core_init(para, config))
 		return;
 
 	panic("This DRAM setup is currently not supported.\n");
 }
 
-static void mctl_auto_detect_dram_size(struct dram_para *para)
+static void mctl_auto_detect_dram_size(const struct dram_para *para,
+				       struct dram_config *config)
 {
 	/* detect row address bits */
-	para->cols = 8;
-	para->rows = 18;
-	mctl_core_init(para);
+	config->cols = 8;
+	config->rows = 18;
+	mctl_core_init(para, config);
 
-	for (para->rows = 13; para->rows < 18; para->rows++) {
+	for (config->rows = 13; config->rows < 18; config->rows++) {
 		/* 8 banks, 8 bit per byte and 16/32 bit width */
-		if (mctl_mem_matches((1 << (para->rows + para->cols +
-					    4 + para->bus_full_width))))
+		if (mctl_mem_matches((1 << (config->rows + config->cols +
+					    4 + config->bus_full_width))))
 			break;
 	}
 
 	/* detect column address bits */
-	para->cols = 11;
-	mctl_core_init(para);
+	config->cols = 11;
+	mctl_core_init(para, config);
 
-	for (para->cols = 8; para->cols < 11; para->cols++) {
+	for (config->cols = 8; config->cols < 11; config->cols++) {
 		/* 8 bits per byte and 16/32 bit width */
-		if (mctl_mem_matches(1 << (para->cols + 1 +
-					   para->bus_full_width)))
+		if (mctl_mem_matches(1 << (config->cols + 1 +
+					   config->bus_full_width)))
 			break;
 	}
 }
 
-static unsigned long mctl_calc_size(const struct dram_para *para)
+static unsigned long mctl_calc_size(const struct dram_config *config)
 {
-	u8 width = para->bus_full_width ? 4 : 2;
+	u8 width = config->bus_full_width ? 4 : 2;
 
 	/* 8 banks */
-	return (1ULL << (para->cols + para->rows + 3)) * width * para->ranks;
+	return (1ULL << (config->cols + config->rows + 3)) * width * config->ranks;
 }
 
+static const struct dram_para para = {
+	.clk = CONFIG_DRAM_CLK,
+	.type = SUNXI_DRAM_TYPE_DDR3,
+	.dx_odt = CONFIG_DRAM_SUN50I_H616_DX_ODT,
+	.dx_dri = CONFIG_DRAM_SUN50I_H616_DX_DRI,
+	.ca_dri = CONFIG_DRAM_SUN50I_H616_CA_DRI,
+	.odt_en = CONFIG_DRAM_SUN50I_H616_ODT_EN,
+	.tpr0 = CONFIG_DRAM_SUN50I_H616_TPR0,
+	.tpr2 = CONFIG_DRAM_SUN50I_H616_TPR2,
+	.tpr10 = CONFIG_DRAM_SUN50I_H616_TPR10,
+	.tpr11 = CONFIG_DRAM_SUN50I_H616_TPR11,
+	.tpr12 = CONFIG_DRAM_SUN50I_H616_TPR12,
+};
+
 unsigned long sunxi_dram_init(void)
 {
 	struct sunxi_prcm_reg *const prcm =
 		(struct sunxi_prcm_reg *)SUNXI_PRCM_BASE;
-	struct dram_para para = {
-		.clk = CONFIG_DRAM_CLK,
-		.type = SUNXI_DRAM_TYPE_DDR3,
-		.dx_odt = CONFIG_DRAM_SUN50I_H616_DX_ODT,
-		.dx_dri = CONFIG_DRAM_SUN50I_H616_DX_DRI,
-		.ca_dri = CONFIG_DRAM_SUN50I_H616_CA_DRI,
-		.odt_en = CONFIG_DRAM_SUN50I_H616_ODT_EN,
-		.tpr0 = CONFIG_DRAM_SUN50I_H616_TPR0,
-		.tpr2 = CONFIG_DRAM_SUN50I_H616_TPR2,
-		.tpr10 = CONFIG_DRAM_SUN50I_H616_TPR10,
-		.tpr11 = CONFIG_DRAM_SUN50I_H616_TPR11,
-		.tpr12 = CONFIG_DRAM_SUN50I_H616_TPR12,
-	};
+	struct dram_config config;
 	unsigned long size;
 
 	setbits_le32(&prcm->res_cal_ctrl, BIT(8));
 	clrbits_le32(&prcm->ohms240, 0x3f);
 
-	mctl_auto_detect_rank_width(&para);
-	mctl_auto_detect_dram_size(&para);
+	mctl_auto_detect_rank_width(&para, &config);
+	mctl_auto_detect_dram_size(&para, &config);
 
-	mctl_core_init(&para);
+	mctl_core_init(&para, &config);
 
-	size = mctl_calc_size(&para);
+	size = mctl_calc_size(&config);
 
 	mctl_set_master_priority();
 
-- 
2.35.8



More information about the U-Boot mailing list