aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/mtd/nand/oxnas_nand.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/mtd/nand/oxnas_nand.c')
-rw-r--r--drivers/mtd/nand/oxnas_nand.c38
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);