[PATCH 47/58] mtd: rawnand: lpc32xx_mlc: retain chip state across removal
From: James Hilliard
Date: Sat Nov 07 2026 - 15:22:03 EST
Drain chip operations before releasing interrupts, DMA and controller
resources. Retain the embedded NAND chip and controller until the final
MTD reference releases their metadata.
Signed-off-by: James Hilliard <james.hilliard1@xxxxxxxxx>
---
drivers/mtd/nand/raw/lpc32xx_mlc.c | 26 ++++++++++++++++++++++----
1 file changed, 22 insertions(+), 4 deletions(-)
diff --git a/drivers/mtd/nand/raw/lpc32xx_mlc.c b/drivers/mtd/nand/raw/lpc32xx_mlc.c
index 8436015edcb4..93ee8cfc0345 100644
--- a/drivers/mtd/nand/raw/lpc32xx_mlc.c
+++ b/drivers/mtd/nand/raw/lpc32xx_mlc.c
@@ -675,6 +675,12 @@ static const struct nand_controller_ops lpc32xx_nand_controller_ops = {
.attach_chip = lpc32xx_nand_attach_chip,
};
+static void lpc32xx_nand_release(struct nand_controller *controller)
+{
+ kfree(container_of(controller, struct lpc32xx_nand_host,
+ nand_chip.legacy.dummy_controller));
+}
+
/*
* Probe for NAND controller
*/
@@ -687,9 +693,14 @@ static int lpc32xx_nand_probe(struct platform_device *pdev)
int res;
/* Allocate memory for the device structure (and zero it) */
- host = devm_kzalloc(&pdev->dev, sizeof(*host), GFP_KERNEL);
+ host = kzalloc_obj(*host);
if (!host)
return -ENOMEM;
+ nand_chip = &host->nand_chip;
+ nand_chip->controller = &nand_chip->legacy.dummy_controller;
+ res = devm_nand_controller_init(&pdev->dev, nand_chip->controller, lpc32xx_nand_release);
+ if (res)
+ return res;
host->pdev = pdev;
@@ -794,10 +805,16 @@ static int lpc32xx_nand_probe(struct platform_device *pdev)
mtd->name = DRV_NAME;
- res = mtd_device_register(mtd, host->ncfg->parts,
- host->ncfg->num_parts);
+ res = nand_set_release(nand_chip, NULL);
if (res)
goto cleanup_nand;
+ res = mtd_device_register(mtd, host->ncfg->parts,
+ host->ncfg->num_parts);
+ if (res) {
+ nand_disconnect(nand_chip);
+ mtd_put_master(mtd);
+ goto free_irq;
+ }
return 0;
@@ -830,7 +847,7 @@ static void lpc32xx_nand_remove(struct platform_device *pdev)
ret = mtd_device_unregister(nand_to_mtd(chip));
WARN_ON(ret);
- nand_cleanup(chip);
+ nand_disconnect(chip);
free_irq(host->irq, host);
if (use_dma)
@@ -841,6 +858,7 @@ static void lpc32xx_nand_remove(struct platform_device *pdev)
lpc32xx_wp_enable(host);
gpiod_put(host->wp_gpio);
+ mtd_put_master(nand_to_mtd(chip));
}
static int lpc32xx_nand_resume(struct platform_device *pdev)
--
2.53.0