[PATCH 07/10] mtd: rawnand: Help supporting controllers that are not able to split operations

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



While performing any NAND operation is as simple as following the
cores order and send "command", "address" and "data" cycles as
provided in a list of instructions, certain controllers are "too
clever" and are not able to split the sending of these cycles.

Try to find out at boot time if the controller will be problematic and
flag it. Additional changes will make use of this flag to workaround
the capricious controllers by proposing "packed" operations as an
alternative.

Signed-off-by: Miquel Raynal <miquel.raynal@xxxxxxxxxxx>
---
 drivers/mtd/nand/raw/internals.h |  5 ++++
 drivers/mtd/nand/raw/nand_base.c | 44 ++++++++++++++++++++++++++++++++
 include/linux/mtd/rawnand.h      |  8 ++++++
 3 files changed, 57 insertions(+)

diff --git a/drivers/mtd/nand/raw/internals.h b/drivers/mtd/nand/raw/internals.h
index 9d0caadf940e..38898b8639ee 100644
--- a/drivers/mtd/nand/raw/internals.h
+++ b/drivers/mtd/nand/raw/internals.h
@@ -130,6 +130,11 @@ static inline bool nand_has_setup_data_iface(struct nand_chip *chip)
 	return true;
 }
 
+static inline bool nand_pack_ops(struct nand_chip *chip)
+{
+	return (chip->options & NAND_PACK_OPS);
+}
+
 /* BBT functions */
 int nand_markbad_bbt(struct nand_chip *chip, loff_t offs);
 int nand_isreserved_bbt(struct nand_chip *chip, loff_t offs);
diff --git a/drivers/mtd/nand/raw/nand_base.c b/drivers/mtd/nand/raw/nand_base.c
index 15a9189b2307..6e4eabb9dc11 100644
--- a/drivers/mtd/nand/raw/nand_base.c
+++ b/drivers/mtd/nand/raw/nand_base.c
@@ -5031,6 +5031,44 @@ static int nand_dt_init(struct nand_chip *chip)
 	return 0;
 }
 
+/**
+ * nand_controller_needs_packed_op - Check the controller habilities to perform
+ *                                   a set of split operations that the core is
+ *                                   very likely to try. If one of them do not
+ *                                   pass, then try to pack operations together.
+ * @chip: The NAND chip
+ *
+ * Returns @true if packing is needed, false otherwise.
+ */
+static bool nand_controller_needs_packed_op(struct nand_chip *chip)
+{
+	u8 tmp[8];
+	struct nand_op_instr data_in_instrs[] = {
+		NAND_OP_DATA_IN(8, tmp, 0),
+	};
+	struct nand_op_instr data_out_instrs[] = {
+		NAND_OP_DATA_OUT(8, tmp, 0),
+	};
+	struct nand_operation ops[] = {
+		NAND_OPERATION(0, data_in_instrs),
+		NAND_OPERATION(0, data_out_instrs),
+	};
+	int ret, i;
+
+	if (!nand_has_exec_op(chip))
+		return false;
+
+	for (i = 0; i < ARRAY_SIZE(ops); i++) {
+		ret = chip->controller->ops->exec_op(chip, &ops[i], true);
+		if (ret) {
+			pr_debug("Using ->exec_op() packed operations only\n");
+			return true;
+		}
+	}
+
+	return false;
+}
+
 /**
  * nand_scan_ident - Scan for the NAND device
  * @chip: NAND chip object
@@ -5052,6 +5090,7 @@ static int nand_scan_ident(struct nand_chip *chip, unsigned int maxchips,
 	struct nand_memory_organization *memorg;
 	int nand_maf_id, nand_dev_id;
 	unsigned int i;
+	bool pack_ops;
 	int ret;
 
 	memorg = nanddev_get_memorg(&chip->base);
@@ -5080,6 +5119,11 @@ static int nand_scan_ident(struct nand_chip *chip, unsigned int maxchips,
 
 	memorg->ntargets = maxchips;
 
+	/* Verify the controller's abilities */
+	pack_ops = nand_controller_needs_packed_op(chip);
+	if (pack_ops)
+		chip->options |= NAND_PACK_OPS;
+
 	/* Read the flash type */
 	ret = nand_detect(chip, table);
 	if (ret) {
diff --git a/include/linux/mtd/rawnand.h b/include/linux/mtd/rawnand.h
index 21753b83d536..4ecc6be434e0 100644
--- a/include/linux/mtd/rawnand.h
+++ b/include/linux/mtd/rawnand.h
@@ -170,6 +170,14 @@ enum nand_ecc_algo {
 /* Non chip related options */
 /* This option skips the bbt scan during initialization. */
 #define NAND_SKIP_BBTSCAN	BIT(16)
+
+/*
+ * Controller does not support "naked" operations, the core should try to pack
+ * the NAND commands as much as possible thanks to the constant use of a bounce
+ * buffer. This flag must be set by the core only.
+ */
+#define NAND_PACK_OPS		BIT(17)
+
 /* Chip may not exist, so silence any errors in scan */
 #define NAND_SCAN_SILENT_NODEV	BIT(18)
 
-- 
2.20.1


______________________________________________________
Linux MTD discussion mailing list
http://lists.infradead.org/mailman/listinfo/linux-mtd/



[Index of Archives]     [LARTC]     [Bugtraq]     [Yosemite Forum]     [Photo]

  Powered by Linux