spi: nxp-fspi: use devm instead of remove for driver detach
authorHan Xu <han.xu@nxp.com>
Mon, 28 Apr 2025 10:06:47 +0000 (18:06 +0800)
committerMark Brown <broonie@kernel.org>
Tue, 6 May 2025 14:17:31 +0000 (23:17 +0900)
fspi driver use devm APIs to manage clk/irq/resources and register the spi
controller, but the legacy remove function will be called first during
device detach and trigger kernel panic. Drop the remove function and use
devm_add_action_or_reset() for driver cleanup to ensure the release
sequence.

Signed-off-by: Han Xu <han.xu@nxp.com>
Signed-off-by: Haibo Chen <haibo.chen@nxp.com>
Link: https://patch.msgid.link/20250428-flexspipatch-v3-5-61d5e8f591bc@nxp.com
Signed-off-by: Mark Brown <broonie@kernel.org>
drivers/spi/spi-nxp-fspi.c

index 0ea04e7..e63c77e 100644 (file)
@@ -1168,6 +1168,24 @@ static const struct spi_controller_mem_caps nxp_fspi_mem_caps = {
        .per_op_freq = true,
 };
 
+static void nxp_fspi_cleanup(void *data)
+{
+       struct nxp_fspi *f = data;
+
+       /* enable clock first since there is register access */
+       pm_runtime_get_sync(f->dev);
+
+       /* disable the hardware */
+       fspi_writel(f, FSPI_MCR0_MDIS, f->iobase + FSPI_MCR0);
+
+       pm_runtime_disable(f->dev);
+       pm_runtime_put_noidle(f->dev);
+       nxp_fspi_clk_disable_unprep(f);
+
+       if (f->ahb_addr)
+               iounmap(f->ahb_addr);
+}
+
 static int nxp_fspi_probe(struct platform_device *pdev)
 {
        struct spi_controller *ctlr;
@@ -1263,25 +1281,11 @@ static int nxp_fspi_probe(struct platform_device *pdev)
        ctlr->mem_caps = &nxp_fspi_mem_caps;
        ctlr->dev.of_node = np;
 
-       return devm_spi_register_controller(&pdev->dev, ctlr);
-}
-
-static void nxp_fspi_remove(struct platform_device *pdev)
-{
-       struct nxp_fspi *f = platform_get_drvdata(pdev);
-
-       /* enable clock first since there is reigster access */
-       pm_runtime_get_sync(f->dev);
-
-       /* disable the hardware */
-       fspi_writel(f, FSPI_MCR0_MDIS, f->iobase + FSPI_MCR0);
-
-       pm_runtime_disable(f->dev);
-       pm_runtime_put_noidle(f->dev);
-       nxp_fspi_clk_disable_unprep(f);
+       ret = devm_add_action_or_reset(dev, nxp_fspi_cleanup, f);
+       if (ret)
+               return dev_err_probe(dev, ret, "Failed to register nxp_fspi_cleanup\n");
 
-       if (f->ahb_addr)
-               iounmap(f->ahb_addr);
+       return devm_spi_register_controller(&pdev->dev, ctlr);
 }
 
 static int nxp_fspi_runtime_suspend(struct device *dev)
@@ -1361,7 +1365,6 @@ static struct platform_driver nxp_fspi_driver = {
                .pm = pm_ptr(&nxp_fspi_pm_ops),
        },
        .probe          = nxp_fspi_probe,
-       .remove         = nxp_fspi_remove,
 };
 module_platform_driver(nxp_fspi_driver);