diff options
Diffstat (limited to 'drivers/mtd/nand/oxnas_nand.c')
-rw-r--r-- | drivers/mtd/nand/oxnas_nand.c | 38 |
1 files changed, 26 insertions, 12 deletions
diff --git a/drivers/mtd/nand/oxnas_nand.c b/drivers/mtd/nand/oxnas_nand.c index d649d5944826..08b6ae364f2b 100644 --- a/drivers/mtd/nand/oxnas_nand.c +++ b/drivers/mtd/nand/oxnas_nand.c @@ -36,6 +36,7 @@ struct oxnas_nand_ctrl { void __iomem *io_base; struct clk *clk; struct nand_chip *chips[OXNAS_NAND_MAX_CHIPS]; + unsigned int nchips; }; static uint8_t oxnas_nand_read_byte(struct mtd_info *mtd) @@ -86,9 +87,9 @@ static int oxnas_nand_probe(struct platform_device *pdev) struct nand_chip *chip; struct mtd_info *mtd; struct resource *res; - int nchips = 0; int count = 0; int err = 0; + int i; /* Allocate memory for the device structure (and zero it) */ oxnas = devm_kzalloc(&pdev->dev, sizeof(*oxnas), @@ -123,7 +124,7 @@ static int oxnas_nand_probe(struct platform_device *pdev) GFP_KERNEL); if (!chip) { err = -ENOMEM; - goto err_clk_unprepare; + goto err_release_child; } chip->controller = &oxnas->base; @@ -144,20 +145,18 @@ static int oxnas_nand_probe(struct platform_device *pdev) /* Scan to find existence of the device */ err = nand_scan(mtd, 1); if (err) - goto err_clk_unprepare; + goto err_release_child; err = mtd_device_register(mtd, NULL, 0); - if (err) { - nand_release(mtd); - goto err_clk_unprepare; - } + if (err) + goto err_cleanup_nand; - oxnas->chips[nchips] = chip; - ++nchips; + oxnas->chips[oxnas->nchips] = chip; + ++oxnas->nchips; } /* Exit if no chips found */ - if (!nchips) { + if (!oxnas->nchips) { err = -ENODEV; goto err_clk_unprepare; } @@ -166,6 +165,17 @@ static int oxnas_nand_probe(struct platform_device *pdev) return 0; +err_cleanup_nand: + nand_cleanup(chip); +err_release_child: + of_node_put(nand_np); + + for (i = 0; i < oxnas->nchips; i++) { + chip = oxnas->chips[i]; + WARN_ON(mtd_device_unregister(nand_to_mtd(chip))); + nand_cleanup(chip); + } + err_clk_unprepare: clk_disable_unprepare(oxnas->clk); return err; @@ -174,9 +184,13 @@ err_clk_unprepare: static int oxnas_nand_remove(struct platform_device *pdev) { struct oxnas_nand_ctrl *oxnas = platform_get_drvdata(pdev); + struct nand_chip *chip; + int i; - if (oxnas->chips[0]) - nand_release(nand_to_mtd(oxnas->chips[0])); + for (i = 0; i < oxnas->nchips; i++) { + chip = oxnas->chips[i]; + nand_release(chip); + } clk_disable_unprepare(oxnas->clk); |