[PATCH u-boot v2019.04-aspeed-openbmc v2] ram/aspeed: Re-init ECC if requested but not enabled

Joel Stanley joel at jms.id.au
Wed Sep 21 17:46:29 AEST 2022


If a machine has a new u-boot installed that enables ECC, but it has not
had a power cycle since being updated, the DDR will not re-initalise and
ECC will stay disabled.

Similarly for the reverse case, where ECC was enabled but a new u-boot
disables it.

Detect if ECC has been requested by the firmware and check against the
hardware state. If it does not match, and the DDR has already been
initialised, proceed as if the DDR has not been set up.

Signed-off-by: Joel Stanley <joel at jms.id.au>
---
v2:
 Add ast2500 too
 Fix logic for if (required) test
---
 drivers/ram/aspeed/sdram_ast2500.c | 23 ++++++++++++++++++++++-
 drivers/ram/aspeed/sdram_ast2600.c | 27 +++++++++++++++++++++++++--
 2 files changed, 47 insertions(+), 3 deletions(-)

diff --git a/drivers/ram/aspeed/sdram_ast2500.c b/drivers/ram/aspeed/sdram_ast2500.c
index c8eee32da698..f89dd78487e9 100644
--- a/drivers/ram/aspeed/sdram_ast2500.c
+++ b/drivers/ram/aspeed/sdram_ast2500.c
@@ -409,6 +409,27 @@ static void ast2500_sdrammc_lock(struct dram_info *info)
 		;
 }
 
+static bool ast2500_sdrammc_init_required(struct udevice *dev)
+{
+	struct dram_info *priv = dev_get_priv(dev);
+	struct ast2500_sdrammc_regs *regs = priv->regs;
+	bool ecc_requested;
+	bool ecc_enabled;
+	bool dram_ready;
+
+	ecc_requested = dev_read_bool(dev, "aspeed,ecc-enabled");
+	ecc_enabled = readl(&regs->config) & SDRAM_CONF_ECC_EN;
+	dram_ready  = readl(&priv->scu->vga_handshake[0]) & BIT(6);
+
+	if (!dram_ready)
+		return true;
+
+	if (ecc_requested != ecc_enabled)
+		return true;
+
+	return false;
+}
+
 static int ast2500_sdrammc_probe(struct udevice *dev)
 {
 	struct dram_info *priv = (struct dram_info *)dev_get_priv(dev);
@@ -437,7 +458,7 @@ static int ast2500_sdrammc_probe(struct udevice *dev)
 		return PTR_ERR(priv->scu);
 	}
 
-	if (readl(&priv->scu->vga_handshake[0]) & (0x1 << 6)) {
+	if (!ast2500_sdrammc_init_required(dev)) {
 		ast2500_sdrammc_update_size(priv);
 
 		if (!(readl(&priv->regs->config) & SDRAM_CONF_CACHE_EN)) {
diff --git a/drivers/ram/aspeed/sdram_ast2600.c b/drivers/ram/aspeed/sdram_ast2600.c
index 5f7b160faddf..66b5dd1fe6a9 100644
--- a/drivers/ram/aspeed/sdram_ast2600.c
+++ b/drivers/ram/aspeed/sdram_ast2600.c
@@ -891,6 +891,30 @@ static void ast2600_sdrammc_ecc_enable(struct dram_info *info, u32 conf_size_mb)
 	writel(0, &regs->intr_ctrl);
 }
 
+static bool ast2600_sdrammc_init_required(struct udevice *dev)
+{
+	struct dram_info *priv = dev_get_priv(dev);
+	struct ast2600_sdrammc_regs *regs = priv->regs;
+	bool ecc_requested;
+	bool ecc_enabled;
+	bool dram_ready;
+
+	ecc_requested = dev_read_bool(dev, "aspeed,ecc-enabled");
+	ecc_enabled = readl(&regs->config) & SDRAM_CONF_ECC_SETUP;
+	dram_ready  = readl(priv->scu + AST_SCU_HANDSHAKE) & SCU_SDRAM_INIT_READY_MASK;
+
+	debug("ECC: requested %d enabled %d dram ready %d\n",
+			ecc_requested, ecc_enabled, dram_ready);
+
+	if (!dram_ready)
+		return true;
+
+	if (ecc_requested != ecc_enabled)
+		return true;
+
+	return false;
+}
+
 static int ast2600_sdrammc_probe(struct udevice *dev)
 {
 	struct dram_info *priv = (struct dram_info *)dev_get_priv(dev);
@@ -913,8 +937,7 @@ static int ast2600_sdrammc_probe(struct udevice *dev)
 		return PTR_ERR(priv->scu);
 	}
 
-	reg = readl(priv->scu + AST_SCU_HANDSHAKE);
-	if (reg & SCU_SDRAM_INIT_READY_MASK) {
+	if (!ast2600_sdrammc_init_required(dev)) {
 		printf("already initialized, ");
 		setbits_le32(priv->scu + AST_SCU_HANDSHAKE, SCU_HANDSHAKE_MASK);
 		ast2600_sdrammc_update_size(priv);
-- 
2.35.1



More information about the openbmc mailing list