[PATCH v2] memory: atmel-ebi: Disable SMC clock on probe failure

From: Krzysztof Kozlowski

Date: Sun Nov 01 2026 - 14:09:16 EST


Unprepare and drop the SMC clock reference, if probe fails to avoid
resource leakage e.g. during probe deferral.

There is no remove() callback, presumably on purpose so only error paths
are handled.

Cc: <stable@xxxxxxxxxxxxxxx>
Fixes: 87108dc78eb8 ("memory: atmel-ebi: Enable the SMC clock if specified")
Reported-by: Wentao Liang <vulab@xxxxxxxxxxx>
Closes: https://lore.kernel.org/all/20260917101623.2146392-1-vulab@xxxxxxxxxxx/
Reported-by: Sashiko <sashiko-bot@xxxxxxxxxx>
Closes: https://sashiko.dev/#/bug/linux-8e236c81-01b2-4274-a213-11c3f31acfc2
Signed-off-by: Krzysztof Kozlowski <krzysztof.kozlowski@xxxxxxxxxxxxxxxx>

---

I independently developed the patch and then checked the queue with
pending work of iscas. That one has issues and other complains from me,
so only credits for the report.

Changes in v2:
1. Handle of_platform_populate() error.
---
drivers/memory/atmel-ebi.c | 27 ++++++++++++++++++++-------
1 file changed, 20 insertions(+), 7 deletions(-)

diff --git a/drivers/memory/atmel-ebi.c b/drivers/memory/atmel-ebi.c
index 1e8e8aba2542..7dc2f7add1b1 100644
--- a/drivers/memory/atmel-ebi.c
+++ b/drivers/memory/atmel-ebi.c
@@ -562,7 +562,7 @@ static int atmel_ebi_probe(struct platform_device *pdev)
}
ret = clk_prepare_enable(ebi->smc.clk);
if (ret)
- return ret;
+ goto err_put_clk;

/*
* The sama5d3 does not provide an EBICSA register and thus does need
@@ -572,14 +572,16 @@ static int atmel_ebi_probe(struct platform_device *pdev)
ebi->regmap =
syscon_regmap_lookup_by_phandle(np,
ebi->caps->regmap_name);
- if (IS_ERR(ebi->regmap))
- return PTR_ERR(ebi->regmap);
+ if (IS_ERR(ebi->regmap)) {
+ ret = PTR_ERR(ebi->regmap);
+ goto err_disable_clk;
+ }
}

ret = of_property_read_u32(np, "#address-cells", &val);
if (ret) {
dev_err(dev, "missing #address-cells property\n");
- return ret;
+ goto err_disable_clk;
}

reg_cells = val;
@@ -587,7 +589,7 @@ static int atmel_ebi_probe(struct platform_device *pdev)
ret = of_property_read_u32(np, "#size-cells", &val);
if (ret) {
dev_err(dev, "missing #address-cells property\n");
- return ret;
+ goto err_disable_clk;
}

reg_cells += val;
@@ -603,11 +605,22 @@ static int atmel_ebi_probe(struct platform_device *pdev)

ret = atmel_ebi_dev_disable(ebi, child);
if (ret)
- return ret;
+ goto err_disable_clk;
}
}

- return of_platform_populate(np, NULL, NULL, dev);
+ ret = of_platform_populate(np, NULL, NULL, dev);
+ if (ret)
+ goto err_disable_clk;
+
+ return 0;
+
+err_disable_clk:
+ clk_disable_unprepare(ebi->smc.clk);
+err_put_clk:
+ clk_put(ebi->smc.clk);
+
+ return ret;
}

static __maybe_unused int atmel_ebi_resume(struct device *dev)
--
2.53.0