summaryrefslogtreecommitdiffstats
path: root/drivers/mtd/nand
diff options
context:
space:
mode:
authorMiquel Raynal <miquel.raynal@bootlin.com>2018-07-19 01:05:46 +0200
committerMiquel Raynal <miquel.raynal@bootlin.com>2018-07-31 09:45:53 +0200
commit05b54c7bac906c443fd0b23ab8954e0560b33e5c (patch)
treeabd06f557b559470ade1502b49fc515ebd645c67 /drivers/mtd/nand
parent7da45139d264f3b7ead04e00ebb29b189cf9826e (diff)
downloadlinux-05b54c7bac906c443fd0b23ab8954e0560b33e5c.tar.bz2
mtd: rawnand: add hooks that may be called during nand_scan()
In order to remove the limitation that forbids dynamic allocation in nand_scan_ident(), we must create a path that will be the same for all controller drivers. The idea is to use nand_scan() instead of the widely used nand_scan_ident()/nand_scan_tail() couple. In order to achieve this, controller drivers will need to adjust some parameters between these two functions depending on the NAND chip wired on them. This takes the form of two new hooks (->{attach,detach}_chip()) that are placed in a new nand_controller_ops structure, which is then attached to the nand_controller object at driver initialization time. ->attach_chip() is called between nand_scan_ident() and nand_scan_tail(), and ->detach_chip() is called in the error path of nand_scan() and in nand_cleanup(). Note that some NAND controller drivers don't have a dedicated nand_controller object and instead rely on the default/dummy one embedded in nand_chip. If you're in this case and still want to initialize the controller ops, you'll have to manipulate chip->dummy_controller directly. Last but not least, it's worth mentioning that we plan to move some of the controller related hooks placed in nand_chip into nand_controller_ops to make the separation between NAND chip and NAND controller methods clearer. Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com> Acked-by: Boris Brezillon <boris.brezillon@bootlin.com>
Diffstat (limited to 'drivers/mtd/nand')
-rw-r--r--drivers/mtd/nand/raw/nand_base.c32
1 files changed, 30 insertions, 2 deletions
diff --git a/drivers/mtd/nand/raw/nand_base.c b/drivers/mtd/nand/raw/nand_base.c
index dcdf0f373100..dea41fa25be1 100644
--- a/drivers/mtd/nand/raw/nand_base.c
+++ b/drivers/mtd/nand/raw/nand_base.c
@@ -6718,6 +6718,20 @@ err_free_buf:
}
EXPORT_SYMBOL(nand_scan_tail);
+static int nand_attach(struct nand_chip *chip)
+{
+ if (chip->controller->ops && chip->controller->ops->attach_chip)
+ return chip->controller->ops->attach_chip(chip);
+
+ return 0;
+}
+
+static void nand_detach(struct nand_chip *chip)
+{
+ if (chip->controller->ops && chip->controller->ops->detach_chip)
+ chip->controller->ops->detach_chip(chip);
+}
+
/**
* nand_scan_with_ids - [NAND Interface] Scan for the NAND device
* @mtd: MTD device structure
@@ -6731,11 +6745,21 @@ EXPORT_SYMBOL(nand_scan_tail);
int nand_scan_with_ids(struct mtd_info *mtd, int maxchips,
struct nand_flash_dev *ids)
{
+ struct nand_chip *chip = mtd_to_nand(mtd);
int ret;
ret = nand_scan_ident(mtd, maxchips, ids);
- if (!ret)
- ret = nand_scan_tail(mtd);
+ if (ret)
+ return ret;
+
+ ret = nand_attach(chip);
+ if (ret)
+ return ret;
+
+ ret = nand_scan_tail(mtd);
+ if (ret)
+ nand_detach(chip);
+
return ret;
}
EXPORT_SYMBOL(nand_scan_with_ids);
@@ -6763,7 +6787,11 @@ void nand_cleanup(struct nand_chip *chip)
/* Free manufacturer priv data. */
nand_manufacturer_cleanup(chip);
+
+ /* Free controller specific allocations after chip identification */
+ nand_detach(chip);
}
+
EXPORT_SYMBOL_GPL(nand_cleanup);
/**