Linux-mtd Archive on lore.kernel.org
 help / color / Atom feed
* [PATCH v2 00/19] mtd: rawnand: cafe: Convert to exec_op() (and more)
@ 2020-05-05 10:13 Boris Brezillon
  2020-05-05 10:13 ` [PATCH v2 01/19] mtd: rawnand: Propage CS selection to sub operations Boris Brezillon
                   ` (19 more replies)
  0 siblings, 20 replies; 46+ messages in thread
From: Boris Brezillon @ 2020-05-05 10:13 UTC (permalink / raw)
  To: Miquel Raynal, linux-mtd, Lubomir Rintel
  Cc: Richard Weinberger, Boris Brezillon, Vignesh Raghavendra, Tudor Ambarus

Hello,

A bit of context to explain the motivation behind those conversions
I've been sending for the last couple of weeks. The raw NAND subsystem
carries a lot of history which makes any rework not only painful, but
also subject to regressions which we only detect when someone dares to
update its kernel on one of those ancient HW. While carrying drivers
for old HW is not a problem per se, carrying ancient and unmaintained
drivers that are not converted to new APIs is a maintenance burden,
hence this massive conversion attempt I'm conducting here.

So here is a series converting the CAFE NAND controller driver to
exec_op(), plus a bunch of minor improvements done along the way.
I hope I'll find someone to test those changes, but if there's no one
still owning OLPC HW or no interest in keeping it supported in recent
kernel versions, we should definitely consider removing the driver
instead.

No major changes in this v2, apart from fixes for things reported by
Lubomir and Miquel. See the changelog on each patch for more details.

Regards,

Boris

Boris Brezillon (19):
  mtd: rawnand: Propage CS selection to sub operations
  mtd: rawnand: cafe: Get rid of an inaccurate kernel doc header
  mtd: rawnand: cafe: Rename cafe_nand_write_page_lowlevel()
  mtd: rawnand: cafe: Use a correct ECC mode and pass the ECC alg
  mtd: rawnand: cafe: Include linux/io.h instead of asm/io.h
  mtd: rawnand: cafe: Demistify register fields
  mtd: rawnand: cafe: Factor out the controller initialization logic
  mtd: rawnand: cafe: Get rid of the debug module param
  mtd: rawnand: cafe: Use devm_kzalloc and devm_request_irq()
  mtd: rawnand: cafe: Get rid of a useless label
  mtd: rawnand: cafe: Explicitly inherit from nand_controller
  mtd: rawnand: cafe: Don't leave ECC enabled in the write path
  mtd: rawnand: cafe: Don't split things when reading/writing a page
  mtd: rawnand: cafe: Add exec_op() support
  mtd: rawnand: cafe: Get rid of the legacy interface implementation
  mtd: rawnand: cafe: Adjust the cafe_{read,write}_buf() prototypes
  mtd: rawnand: cafe: s/uint{8,16,32}_t/u{8,16,32}/
  mtd: rawnand: cafe: Drop the cafe_{readl,writel}() wrappers
  mtd: rawnand: cafe: Get rid of the last printk()

 drivers/mtd/nand/raw/cafe_nand.c | 798 ++++++++++++++++---------------
 drivers/mtd/nand/raw/nand_base.c |   3 +-
 include/linux/mtd/rawnand.h      |   2 +
 3 files changed, 410 insertions(+), 393 deletions(-)

-- 
2.25.3


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

^ permalink raw reply	[flat|nested] 46+ messages in thread

* [PATCH v2 01/19] mtd: rawnand: Propage CS selection to sub operations
  2020-05-05 10:13 [PATCH v2 00/19] mtd: rawnand: cafe: Convert to exec_op() (and more) Boris Brezillon
@ 2020-05-05 10:13 ` Boris Brezillon
  2020-05-24 19:17   ` Miquel Raynal
  2020-05-05 10:13 ` [PATCH v2 02/19] mtd: rawnand: cafe: Get rid of an inaccurate kernel doc header Boris Brezillon
                   ` (18 subsequent siblings)
  19 siblings, 1 reply; 46+ messages in thread
From: Boris Brezillon @ 2020-05-05 10:13 UTC (permalink / raw)
  To: Miquel Raynal, linux-mtd, Lubomir Rintel
  Cc: Richard Weinberger, Boris Brezillon, Vignesh Raghavendra, Tudor Ambarus

Some controller using the instruction parse infrastructure might need
to know which CS a specific sub-operation is targeting. Let's propagate
this information.

Signed-off-by: Boris Brezillon <boris.brezillon@collabora.com>
Reviewed-by: Miquel Raynal <miquel.raynal@bootlin.com>
---
Changes in v2:
* Add R-b
---
 drivers/mtd/nand/raw/nand_base.c | 3 ++-
 include/linux/mtd/rawnand.h      | 2 ++
 2 files changed, 4 insertions(+), 1 deletion(-)

diff --git a/drivers/mtd/nand/raw/nand_base.c b/drivers/mtd/nand/raw/nand_base.c
index 3a0e85ebcbe3..1cb5cf7a049a 100644
--- a/drivers/mtd/nand/raw/nand_base.c
+++ b/drivers/mtd/nand/raw/nand_base.c
@@ -2119,7 +2119,7 @@ static void nand_op_parser_trace(const struct nand_op_parser_ctx *ctx)
 	char *prefix = "      ";
 	unsigned int i;
 
-	pr_debug("executing subop:\n");
+	pr_debug("executing subop (CS%d):\n", ctx->subop.cs);
 
 	for (i = 0; i < ctx->ninstrs; i++) {
 		instr = &ctx->instrs[i];
@@ -2183,6 +2183,7 @@ int nand_op_parser_exec_op(struct nand_chip *chip,
 			   const struct nand_operation *op, bool check_only)
 {
 	struct nand_op_parser_ctx ctx = {
+		.subop.cs = op->cs,
 		.subop.instrs = op->instrs,
 		.instrs = op->instrs,
 		.ninstrs = op->ninstrs,
diff --git a/include/linux/mtd/rawnand.h b/include/linux/mtd/rawnand.h
index e26a87b0fbd9..c92de1fa4eaf 100644
--- a/include/linux/mtd/rawnand.h
+++ b/include/linux/mtd/rawnand.h
@@ -702,6 +702,7 @@ struct nand_op_instr {
 
 /**
  * struct nand_subop - a sub operation
+ * @cs: the CS line to select for this NAND sub-operation
  * @instrs: array of instructions
  * @ninstrs: length of the @instrs array
  * @first_instr_start_off: offset to start from for the first instruction
@@ -718,6 +719,7 @@ struct nand_op_instr {
  * controller driver.
  */
 struct nand_subop {
+	unsigned int cs;
 	const struct nand_op_instr *instrs;
 	unsigned int ninstrs;
 	unsigned int first_instr_start_off;
-- 
2.25.3


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

^ permalink raw reply	[flat|nested] 46+ messages in thread

* [PATCH v2 02/19] mtd: rawnand: cafe: Get rid of an inaccurate kernel doc header
  2020-05-05 10:13 [PATCH v2 00/19] mtd: rawnand: cafe: Convert to exec_op() (and more) Boris Brezillon
  2020-05-05 10:13 ` [PATCH v2 01/19] mtd: rawnand: Propage CS selection to sub operations Boris Brezillon
@ 2020-05-05 10:13 ` Boris Brezillon
  2020-05-05 10:13 ` [PATCH v2 03/19] mtd: rawnand: cafe: Rename cafe_nand_write_page_lowlevel() Boris Brezillon
                   ` (17 subsequent siblings)
  19 siblings, 0 replies; 46+ messages in thread
From: Boris Brezillon @ 2020-05-05 10:13 UTC (permalink / raw)
  To: Miquel Raynal, linux-mtd, Lubomir Rintel
  Cc: Richard Weinberger, Boris Brezillon, Vignesh Raghavendra, Tudor Ambarus

Driver files are not parsed for doc generation, and the
cafe_nand_read_page() kernel-doc header was wrong, so let's get rid of
it.

Signed-off-by: Boris Brezillon <boris.brezillon@collabora.com>
Reviewed-by: Miquel Raynal <miquel.raynal@bootlin.com>
---
Changes in v2:
* Add R-b
---
 drivers/mtd/nand/raw/cafe_nand.c | 9 ++-------
 1 file changed, 2 insertions(+), 7 deletions(-)

diff --git a/drivers/mtd/nand/raw/cafe_nand.c b/drivers/mtd/nand/raw/cafe_nand.c
index 2a0df13df5f3..1296380a4996 100644
--- a/drivers/mtd/nand/raw/cafe_nand.c
+++ b/drivers/mtd/nand/raw/cafe_nand.c
@@ -357,13 +357,8 @@ static int cafe_nand_read_oob(struct nand_chip *chip, int page)
 
 	return nand_read_oob_op(chip, page, 0, chip->oob_poi, mtd->oobsize);
 }
-/**
- * cafe_nand_read_page_syndrome - [REPLACEABLE] hardware ecc syndrome based page read
- * @mtd:	mtd info structure
- * @chip:	nand chip info structure
- * @buf:	buffer to store read data
- * @oob_required:	caller expects OOB data read to chip->oob_poi
- *
+
+/*
  * The hw generator calculates the error syndrome automatically. Therefore
  * we need a special oob layout and handling.
  */
-- 
2.25.3


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

^ permalink raw reply	[flat|nested] 46+ messages in thread

* [PATCH v2 03/19] mtd: rawnand: cafe: Rename cafe_nand_write_page_lowlevel()
  2020-05-05 10:13 [PATCH v2 00/19] mtd: rawnand: cafe: Convert to exec_op() (and more) Boris Brezillon
  2020-05-05 10:13 ` [PATCH v2 01/19] mtd: rawnand: Propage CS selection to sub operations Boris Brezillon
  2020-05-05 10:13 ` [PATCH v2 02/19] mtd: rawnand: cafe: Get rid of an inaccurate kernel doc header Boris Brezillon
@ 2020-05-05 10:13 ` Boris Brezillon
  2020-05-05 10:13 ` [PATCH v2 04/19] mtd: rawnand: cafe: Use a correct ECC mode and pass the ECC alg Boris Brezillon
                   ` (16 subsequent siblings)
  19 siblings, 0 replies; 46+ messages in thread
From: Boris Brezillon @ 2020-05-05 10:13 UTC (permalink / raw)
  To: Miquel Raynal, linux-mtd, Lubomir Rintel
  Cc: Richard Weinberger, Boris Brezillon, Vignesh Raghavendra, Tudor Ambarus

Let's rename that one cafe_nand_write_page() to be consistent with other
function names.

Signed-off-by: Boris Brezillon <boris.brezillon@collabora.com>
Reviewed-by: Miquel Raynal <miquel.raynal@bootlin.com>
Tested-by: Lubomir Rintel <lkundrak@v3.sk>
---
Changes in v2:
* Add R-b/T-b
---
 drivers/mtd/nand/raw/cafe_nand.c | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/drivers/mtd/nand/raw/cafe_nand.c b/drivers/mtd/nand/raw/cafe_nand.c
index 1296380a4996..03964e092243 100644
--- a/drivers/mtd/nand/raw/cafe_nand.c
+++ b/drivers/mtd/nand/raw/cafe_nand.c
@@ -525,9 +525,9 @@ static struct nand_bbt_descr cafe_bbt_mirror_descr_512 = {
 };
 
 
-static int cafe_nand_write_page_lowlevel(struct nand_chip *chip,
-					 const uint8_t *buf, int oob_required,
-					 int page)
+static int cafe_nand_write_page(struct nand_chip *chip,
+				const uint8_t *buf, int oob_required,
+				int page)
 {
 	struct mtd_info *mtd = nand_to_mtd(chip);
 	struct cafe_priv *cafe = nand_get_controller_data(chip);
@@ -628,7 +628,7 @@ static int cafe_nand_attach_chip(struct nand_chip *chip)
 	cafe->nand.ecc.size = mtd->writesize;
 	cafe->nand.ecc.bytes = 14;
 	cafe->nand.ecc.strength = 4;
-	cafe->nand.ecc.write_page = cafe_nand_write_page_lowlevel;
+	cafe->nand.ecc.write_page = cafe_nand_write_page;
 	cafe->nand.ecc.write_oob = cafe_nand_write_oob;
 	cafe->nand.ecc.read_page = cafe_nand_read_page;
 	cafe->nand.ecc.read_oob = cafe_nand_read_oob;
-- 
2.25.3


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

^ permalink raw reply	[flat|nested] 46+ messages in thread

* [PATCH v2 04/19] mtd: rawnand: cafe: Use a correct ECC mode and pass the ECC alg
  2020-05-05 10:13 [PATCH v2 00/19] mtd: rawnand: cafe: Convert to exec_op() (and more) Boris Brezillon
                   ` (2 preceding siblings ...)
  2020-05-05 10:13 ` [PATCH v2 03/19] mtd: rawnand: cafe: Rename cafe_nand_write_page_lowlevel() Boris Brezillon
@ 2020-05-05 10:13 ` Boris Brezillon
  2020-05-05 10:13 ` [PATCH v2 05/19] mtd: rawnand: cafe: Include linux/io.h instead of asm/io.h Boris Brezillon
                   ` (15 subsequent siblings)
  19 siblings, 0 replies; 46+ messages in thread
From: Boris Brezillon @ 2020-05-05 10:13 UTC (permalink / raw)
  To: Miquel Raynal, linux-mtd, Lubomir Rintel
  Cc: Richard Weinberger, Boris Brezillon, Vignesh Raghavendra, Tudor Ambarus

The NAND_ECC_HW_SYNDROME name is a bit misleading. It's actually used
for drivers that interleave data and ECC bytes inside a page, which is
not the case here. Let's fix that and pass the ECC algorithm used by the
ECC engine.

Signed-off-by: Boris Brezillon <boris.brezillon@collabora.com>
Reviewed-by: Miquel Raynal <miquel.raynal@bootlin.com>
Tested-by: Lubomir Rintel <lkundrak@v3.sk>
---
Changes in v2:
* Add R-b/T-b
---
 drivers/mtd/nand/raw/cafe_nand.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/drivers/mtd/nand/raw/cafe_nand.c b/drivers/mtd/nand/raw/cafe_nand.c
index 03964e092243..47aacfab8ecb 100644
--- a/drivers/mtd/nand/raw/cafe_nand.c
+++ b/drivers/mtd/nand/raw/cafe_nand.c
@@ -624,7 +624,8 @@ static int cafe_nand_attach_chip(struct nand_chip *chip)
 		goto out_free_dma;
 	}
 
-	cafe->nand.ecc.mode = NAND_ECC_HW_SYNDROME;
+	cafe->nand.ecc.mode = NAND_ECC_HW;
+	cafe->nand.ecc.algo = NAND_ECC_RS;
 	cafe->nand.ecc.size = mtd->writesize;
 	cafe->nand.ecc.bytes = 14;
 	cafe->nand.ecc.strength = 4;
-- 
2.25.3


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

^ permalink raw reply	[flat|nested] 46+ messages in thread

* [PATCH v2 05/19] mtd: rawnand: cafe: Include linux/io.h instead of asm/io.h
  2020-05-05 10:13 [PATCH v2 00/19] mtd: rawnand: cafe: Convert to exec_op() (and more) Boris Brezillon
                   ` (3 preceding siblings ...)
  2020-05-05 10:13 ` [PATCH v2 04/19] mtd: rawnand: cafe: Use a correct ECC mode and pass the ECC alg Boris Brezillon
@ 2020-05-05 10:13 ` Boris Brezillon
  2020-05-05 10:13 ` [PATCH v2 06/19] mtd: rawnand: cafe: Demistify register fields Boris Brezillon
                   ` (14 subsequent siblings)
  19 siblings, 0 replies; 46+ messages in thread
From: Boris Brezillon @ 2020-05-05 10:13 UTC (permalink / raw)
  To: Miquel Raynal, linux-mtd, Lubomir Rintel
  Cc: Richard Weinberger, Boris Brezillon, Vignesh Raghavendra, Tudor Ambarus

Drivers should not include asm headers directly.

Signed-off-by: Boris Brezillon <boris.brezillon@collabora.com>
Reviewed-by: Miquel Raynal <miquel.raynal@bootlin.com>
Tested-by: Lubomir Rintel <lkundrak@v3.sk>
---
Changes in v2:
* Add R-b/T-b
---
 drivers/mtd/nand/raw/cafe_nand.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/mtd/nand/raw/cafe_nand.c b/drivers/mtd/nand/raw/cafe_nand.c
index 47aacfab8ecb..156a308b530b 100644
--- a/drivers/mtd/nand/raw/cafe_nand.c
+++ b/drivers/mtd/nand/raw/cafe_nand.c
@@ -23,7 +23,7 @@
 #include <linux/dma-mapping.h>
 #include <linux/slab.h>
 #include <linux/module.h>
-#include <asm/io.h>
+#include <linux/io.h>
 
 #define CAFE_NAND_CTRL1		0x00
 #define CAFE_NAND_CTRL2		0x04
-- 
2.25.3


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

^ permalink raw reply	[flat|nested] 46+ messages in thread

* [PATCH v2 06/19] mtd: rawnand: cafe: Demistify register fields
  2020-05-05 10:13 [PATCH v2 00/19] mtd: rawnand: cafe: Convert to exec_op() (and more) Boris Brezillon
                   ` (4 preceding siblings ...)
  2020-05-05 10:13 ` [PATCH v2 05/19] mtd: rawnand: cafe: Include linux/io.h instead of asm/io.h Boris Brezillon
@ 2020-05-05 10:13 ` Boris Brezillon
       [not found]   ` <20200506204638.GB207924@furthur.local>
  2020-05-05 10:13 ` [PATCH v2 07/19] mtd: rawnand: cafe: Factor out the controller initialization logic Boris Brezillon
                   ` (13 subsequent siblings)
  19 siblings, 1 reply; 46+ messages in thread
From: Boris Brezillon @ 2020-05-05 10:13 UTC (permalink / raw)
  To: Miquel Raynal, linux-mtd, Lubomir Rintel
  Cc: Richard Weinberger, Boris Brezillon, Vignesh Raghavendra, Tudor Ambarus

The driver has a bunch of magic values. Let's define proper register
fields based on the spec [1] and use them.

[1]http://wiki.laptop.org/images/5/5c/88ALP01_Datasheet_July_2007.pdf

Signed-off-by: Boris Brezillon <boris.brezillon@collabora.com>
Reviewed-by: Lubomir Rintel <lkundrak@v3.sk>
Tested-by: Lubomir Rintel <lkundrak@v3.sk>
---
Changes in v2:
* Add R-b/T-b
* Get rid of unrelated select_chip() change
* Fix CE selection logic
* s/CAFE_NAND_CTRL2_CMD2/CAFE_NAND_CTRL2_HAS_CMD2/ (Reported by Lubomir)
---
 drivers/mtd/nand/raw/cafe_nand.c | 349 ++++++++++++++++++++++++-------
 1 file changed, 268 insertions(+), 81 deletions(-)

diff --git a/drivers/mtd/nand/raw/cafe_nand.c b/drivers/mtd/nand/raw/cafe_nand.c
index 156a308b530b..7fb5b21aeb00 100644
--- a/drivers/mtd/nand/raw/cafe_nand.c
+++ b/drivers/mtd/nand/raw/cafe_nand.c
@@ -9,6 +9,7 @@
  * Copyright © 2006 David Woodhouse <dwmw2@infradead.org>
  */
 
+#include <linux/bitfield.h>
 #define DEBUG
 
 #include <linux/device.h>
@@ -25,37 +26,127 @@
 #include <linux/module.h>
 #include <linux/io.h>
 
-#define CAFE_NAND_CTRL1		0x00
-#define CAFE_NAND_CTRL2		0x04
-#define CAFE_NAND_CTRL3		0x08
-#define CAFE_NAND_STATUS	0x0c
-#define CAFE_NAND_IRQ		0x10
-#define CAFE_NAND_IRQ_MASK	0x14
-#define CAFE_NAND_DATA_LEN	0x18
-#define CAFE_NAND_ADDR1		0x1c
-#define CAFE_NAND_ADDR2		0x20
-#define CAFE_NAND_TIMING1	0x24
-#define CAFE_NAND_TIMING2	0x28
-#define CAFE_NAND_TIMING3	0x2c
-#define CAFE_NAND_NONMEM	0x30
-#define CAFE_NAND_ECC_RESULT	0x3C
-#define CAFE_NAND_DMA_CTRL	0x40
-#define CAFE_NAND_DMA_ADDR0	0x44
-#define CAFE_NAND_DMA_ADDR1	0x48
-#define CAFE_NAND_ECC_SYN01	0x50
-#define CAFE_NAND_ECC_SYN23	0x54
-#define CAFE_NAND_ECC_SYN45	0x58
-#define CAFE_NAND_ECC_SYN67	0x5c
-#define CAFE_NAND_READ_DATA	0x1000
-#define CAFE_NAND_WRITE_DATA	0x2000
+#define CAFE_NAND_CTRL1				0x00
+#define CAFE_NAND_CTRL1_HAS_CMD			BIT(31)
+#define CAFE_NAND_CTRL1_HAS_ADDR		BIT(30)
+#define CAFE_NAND_CTRL1_NUM_ADDR_CYC		GENMASK(29, 27)
+#define CAFE_NAND_CTRL1_HAS_DATA_IN		BIT(26)
+#define CAFE_NAND_CTRL1_HAS_DATA_OUT		BIT(25)
+#define CAFE_NAND_CTRL1_NUM_NONMEM_READ_HIGH	GENMASK(24, 22)
+#define CAFE_NAND_CTRL1_WAIT_BSY_AFTER_SEQ	BIT(21)
+#define CAFE_NAND_CTRL1_NUM_NONMEM_READ_LOW	BIT(20)
+#define CAFE_NAND_CTRL1_CE			BIT(19)
+#define CAFE_NAND_CTRL1_CMD			GENMASK(7, 0)
 
-#define CAFE_GLOBAL_CTRL	0x3004
-#define CAFE_GLOBAL_IRQ		0x3008
-#define CAFE_GLOBAL_IRQ_MASK	0x300c
-#define CAFE_NAND_RESET		0x3034
+#define CAFE_NAND_CTRL2				0x04
+#define CAFE_NAND_CTRL2_AUTO_WRITE_ECC		BIT(30)
+#define CAFE_NAND_CTRL2_PAGE_SIZE		GENMASK(29, 28)
+#define CAFE_NAND_CTRL2_ECC_ALG_RS		BIT(27)
+#define CAFE_NAND_CTRL2_HAS_CMD2		BIT(8)
+#define CAFE_NAND_CTRL2_CMD2			GENMASK(7, 0)
 
-/* Missing from the datasheet: bit 19 of CTRL1 sets CE0 vs. CE1 */
-#define CTRL1_CHIPSELECT	(1<<19)
+#define CAFE_NAND_CTRL3				0x08
+#define CAFE_NAND_CTRL3_READ_BUSY_RESET		BIT(31)
+#define CAFE_NAND_CTRL3_WP			BIT(30)
+
+#define CAFE_NAND_STATUS			0x0c
+#define CAFE_NAND_STATUS_CONTROLLER_BUSY	BIT(31)
+#define CAFE_NAND_STATUS_FLASH_BUSY		BIT(30)
+
+#define CAFE_NAND_IRQ				0x10
+#define CAFE_NAND_IRQ_MASK			0x14
+#define CAFE_NAND_IRQ_CMD_DONE			BIT(31)
+#define CAFE_NAND_IRQ_FLASH_RDY			BIT(30)
+#define CAFE_NAND_IRQ_DMA_DONE			BIT(28)
+#define CAFE_NAND_IRQ_BOOT_DONE			BIT(27)
+
+#define CAFE_NAND_DATA_LEN			0x18
+#define CAFE_NAND_ADDR1				0x1c
+#define CAFE_NAND_ADDR2				0x20
+
+#define CAFE_NAND_TIMING1			0x24
+#define CAFE_NAND_TIMING1_TCLS			GENMASK(31, 28)
+#define CAFE_NAND_TIMING1_TCLH			GENMASK(27, 24)
+#define CAFE_NAND_TIMING1_TALS			GENMASK(23, 20)
+#define CAFE_NAND_TIMING1_TALH			GENMASK(19, 16)
+#define CAFE_NAND_TIMING1_TWB			GENMASK(15, 8)
+#define CAFE_NAND_TIMING1_TRB			GENMASK(7, 0)
+
+#define CAFE_NAND_TIMING2			0x28
+#define CAFE_NAND_TIMING2_TRR			GENMASK(31, 28)
+#define CAFE_NAND_TIMING2_TREA			GENMASK(27, 24)
+#define CAFE_NAND_TIMING2_TDH			GENMASK(23, 20)
+#define CAFE_NAND_TIMING2_TDS			GENMASK(19, 16)
+#define CAFE_NAND_TIMING2_TRH			GENMASK(15, 12)
+#define CAFE_NAND_TIMING2_TRP			GENMASK(11, 8)
+#define CAFE_NAND_TIMING2_TWH			GENMASK(7, 4)
+#define CAFE_NAND_TIMING2_TWP			GENMASK(3, 0)
+
+#define CAFE_NAND_TIMING3			0x2c
+#define CAFE_NAND_TIMING3_TAR			GENMASK(31, 28)
+#define CAFE_NAND_TIMING3_TCLR			GENMASK(27, 24)
+
+#define CAFE_NAND_NONMEM_READ_DATA		0x30
+#define CAFE_NAND_ECC_READ_CODE			0x38
+
+#define CAFE_NAND_ECC_RESULT			0x3C
+#define CAFE_NAND_ECC_RESULT_RS_ERRORS		BIT(18)
+#define CAFE_NAND_ECC_RESULT_STATUS		GENMASK(17, 16)
+#define CAFE_NAND_ECC_RESULT_NO_ERROR		(0 << 16)
+#define CAFE_NAND_ECC_RESULT_CORRECTABLE_ERRS	(1 << 16)
+#define CAFE_NAND_ECC_RESULT_UNCORRECTABLE_ERRS	(2 << 16)
+#define CAFE_NAND_ECC_RESULT_FAIL_BIT_LOC	GENMASK(13, 0)
+
+#define CAFE_NAND_DMA_CTRL			0x40
+#define CAFE_NAND_DMA_CTRL_ENABLE		BIT(31)
+#define CAFE_NAND_DMA_CTRL_RESERVED		BIT(30)
+#define CAFE_NAND_DMA_CTRL_DATA_IN		BIT(29)
+#define CAFE_NAND_DMA_CTRL_DATA_LEN		GENMASK(11, 0)
+
+#define CAFE_NAND_DMA_ADDR0			0x44
+#define CAFE_NAND_DMA_ADDR1			0x48
+#define CAFE_NAND_ECC_SYN_REG(x)		(((x) / 2) + 0x50)
+#define CAFE_NAND_ECC_SYN_FIELD(x)		(((x) % 2) ? GENMASK(31, 16) : GENMASK(15, 0))
+
+#define CAFE_NAND_CTRL4				0x60
+#define CAFE_NAND_CTRL4_NO_READ_DELAY		BIT(8)
+
+#define CAFE_NAND_DRIVE_STRENGTH		0x64
+#define CAFE_NAND_DRIVE_STRENGTH_VAL		GENMASK(4, 0)
+
+#define CAFE_NAND_READ_DATA			0x1000
+#define CAFE_NAND_WRITE_DATA			0x2000
+
+#define CAFE_GLOBAL_CTRL			0x3004
+#define CAFE_GLOBAL_CCIC_CLK_ENABLE		BIT(14)
+#define CAFE_GLOBAL_SDH_CLK_ENABLE		BIT(13)
+#define CAFE_GLOBAL_NAND_CLK_ENABLE		BIT(12)
+#define CAFE_GLOBAL_CLKRUN_ENABLE_SET		BIT(11)
+#define CAFE_GLOBAL_CLKRUN_ENABLE_CLEAR		BIT(10)
+#define CAFE_GLOBAL_SW_IRQ_SET			BIT(7)
+#define CAFE_GLOBAL_SW_IRQ_CLEAR		BIT(6)
+#define CAFE_GLOBAL_STOP_MASTER_DONE		BIT(5)
+#define CAFE_GLOBAL_STOP_MASTER			BIT(4)
+#define CAFE_GLOBAL_MASTER_RESET_CLEAR		BIT(3)
+#define CAFE_GLOBAL_MASTER_RESET_SET		BIT(2)
+#define CAFE_GLOBAL_SW_RESET_CLEAR		BIT(1)
+#define CAFE_GLOBAL_SW_RESET_SET		BIT(0)
+
+#define CAFE_GLOBAL_IRQ				0x3008
+#define CAFE_GLOBAL_IRQ_MASK			0x300c
+#define CAFE_GLOBAL_IRQ_PCI_ERROR		BIT(31)
+#define CAFE_GLOBAL_IRQ_VPD_TWSI		BIT(26)
+#define CAFE_GLOBAL_IRQ_CCIC			BIT(2)
+#define CAFE_GLOBAL_IRQ_SDH			BIT(1)
+#define CAFE_GLOBAL_IRQ_NAND			BIT(0)
+
+#define CAFE_GLOBAL_RESET			0x3034
+#define CAFE_GLOBAL_RESET_CCIC			BIT(2)
+#define CAFE_GLOBAL_RESET_SDH			BIT(1)
+#define CAFE_GLOBAL_RESET_NAND			BIT(0)
+
+#define CAFE_FIELD_PREP(reg, field, val)	FIELD_PREP(CAFE_##reg##_##field, val)
+#define CAFE_FIELD_GET(reg, field, val)		FIELD_GET(CAFE_##reg##_##field, val)
 
 struct cafe_priv {
 	struct nand_chip nand;
@@ -104,7 +195,8 @@ static const char *part_probes[] = { "cmdlinepart", "RedBoot", NULL };
 static int cafe_device_ready(struct nand_chip *chip)
 {
 	struct cafe_priv *cafe = nand_get_controller_data(chip);
-	int result = !!(cafe_readl(cafe, NAND_STATUS) & 0x40000000);
+	int result = !!(cafe_readl(cafe, NAND_STATUS) &
+			CAFE_NAND_STATUS_FLASH_BUSY);
 	uint32_t irqs = cafe_readl(cafe, NAND_IRQ);
 
 	cafe_writel(cafe, irqs, NAND_IRQ);
@@ -164,16 +256,20 @@ static void cafe_nand_cmdfunc(struct nand_chip *chip, unsigned command,
 	struct cafe_priv *cafe = nand_get_controller_data(chip);
 	int adrbytes = 0;
 	uint32_t ctl1;
-	uint32_t doneint = 0x80000000;
+	uint32_t doneint = CAFE_NAND_IRQ_CMD_DONE;
 
 	cafe_dev_dbg(&cafe->pdev->dev, "cmdfunc %02x, 0x%x, 0x%x\n",
 		command, column, page_addr);
 
 	if (command == NAND_CMD_ERASE2 || command == NAND_CMD_PAGEPROG) {
 		/* Second half of a command we already calculated */
-		cafe_writel(cafe, cafe->ctl2 | 0x100 | command, NAND_CTRL2);
+		cafe_writel(cafe,
+			    cafe->ctl2 |
+			    CAFE_NAND_CTRL2_HAS_CMD2 |
+			    CAFE_FIELD_PREP(NAND_CTRL2, CMD2, command),
+			    NAND_CTRL2);
 		ctl1 = cafe->ctl1;
-		cafe->ctl2 &= ~(1<<30);
+		cafe->ctl2 &= ~CAFE_NAND_CTRL2_AUTO_WRITE_ECC;
 		cafe_dev_dbg(&cafe->pdev->dev, "Continue command, ctl1 %08x, #data %d\n",
 			  cafe->ctl1, cafe->nr_data);
 		goto do_command;
@@ -209,26 +305,29 @@ static void cafe_nand_cmdfunc(struct nand_chip *chip, unsigned command,
 	cafe->data_pos = cafe->datalen = 0;
 
 	/* Set command valid bit, mask in the chip select bit  */
-	ctl1 = 0x80000000 | command | (cafe->ctl1 & CTRL1_CHIPSELECT);
+	ctl1 = CAFE_NAND_CTRL1_HAS_CMD |
+	       CAFE_FIELD_PREP(NAND_CTRL1, CMD, command) |
+	       (cafe->ctl1 & CAFE_NAND_CTRL1_CE);
 
 	/* Set RD or WR bits as appropriate */
 	if (command == NAND_CMD_READID || command == NAND_CMD_STATUS) {
-		ctl1 |= (1<<26); /* rd */
+		ctl1 |= CAFE_NAND_CTRL1_HAS_DATA_IN;
 		/* Always 5 bytes, for now */
 		cafe->datalen = 4;
 		/* And one address cycle -- even for STATUS, since the controller doesn't work without */
 		adrbytes = 1;
 	} else if (command == NAND_CMD_READ0 || command == NAND_CMD_READ1 ||
 		   command == NAND_CMD_READOOB || command == NAND_CMD_RNDOUT) {
-		ctl1 |= 1<<26; /* rd */
+		ctl1 |= CAFE_NAND_CTRL1_HAS_DATA_IN;
 		/* For now, assume just read to end of page */
 		cafe->datalen = mtd->writesize + mtd->oobsize - column;
 	} else if (command == NAND_CMD_SEQIN)
-		ctl1 |= 1<<25; /* wr */
+		ctl1 |= CAFE_NAND_CTRL1_HAS_DATA_OUT;
 
 	/* Set number of address bytes */
 	if (adrbytes)
-		ctl1 |= ((adrbytes-1)|8) << 27;
+		ctl1 |= CAFE_NAND_CTRL1_HAS_ADDR |
+			CAFE_FIELD_PREP(NAND_CTRL1, NUM_ADDR_CYC, adrbytes - 1);
 
 	if (command == NAND_CMD_SEQIN || command == NAND_CMD_ERASE1) {
 		/* Ignore the first command of a pair; the hardware
@@ -240,9 +339,15 @@ static void cafe_nand_cmdfunc(struct nand_chip *chip, unsigned command,
 	}
 	/* RNDOUT and READ0 commands need a following byte */
 	if (command == NAND_CMD_RNDOUT)
-		cafe_writel(cafe, cafe->ctl2 | 0x100 | NAND_CMD_RNDOUTSTART, NAND_CTRL2);
+		cafe_writel(cafe,
+			    cafe->ctl2 | CAFE_NAND_CTRL2_HAS_CMD2 |
+			    CAFE_FIELD_PREP(NAND_CTRL2, CMD2, NAND_CMD_RNDOUTSTART),
+			    NAND_CTRL2);
 	else if (command == NAND_CMD_READ0 && mtd->writesize > 512)
-		cafe_writel(cafe, cafe->ctl2 | 0x100 | NAND_CMD_READSTART, NAND_CTRL2);
+		cafe_writel(cafe,
+			    cafe->ctl2 | CAFE_NAND_CTRL2_HAS_CMD2 |
+			    CAFE_FIELD_PREP(NAND_CTRL2, CMD2, NAND_CMD_READSTART),
+			    NAND_CTRL2);
 
  do_command:
 	cafe_dev_dbg(&cafe->pdev->dev, "dlen %x, ctl1 %x, ctl2 %x\n",
@@ -250,16 +355,23 @@ static void cafe_nand_cmdfunc(struct nand_chip *chip, unsigned command,
 
 	/* NB: The datasheet lies -- we really should be subtracting 1 here */
 	cafe_writel(cafe, cafe->datalen, NAND_DATA_LEN);
-	cafe_writel(cafe, 0x90000000, NAND_IRQ);
-	if (cafe->usedma && (ctl1 & (3<<25))) {
-		uint32_t dmactl = 0xc0000000 + cafe->datalen;
+	cafe_writel(cafe, CAFE_NAND_IRQ_CMD_DONE | CAFE_NAND_IRQ_DMA_DONE,
+		    NAND_IRQ);
+	if (cafe->usedma &&
+	    (ctl1 & (CAFE_NAND_CTRL1_HAS_DATA_IN |
+		     CAFE_NAND_CTRL1_HAS_DATA_OUT))) {
+		uint32_t dmactl = CAFE_NAND_DMA_CTRL_ENABLE |
+				  CAFE_NAND_DMA_CTRL_RESERVED;
+
+		dmactl |= CAFE_FIELD_PREP(NAND_DMA_CTRL, DATA_LEN,
+					  cafe->datalen);
 		/* If WR or RD bits set, set up DMA */
-		if (ctl1 & (1<<26)) {
+		if (ctl1 & CAFE_NAND_CTRL1_HAS_DATA_IN) {
 			/* It's a read */
-			dmactl |= (1<<29);
+			dmactl |= CAFE_NAND_DMA_CTRL_DATA_IN;
 			/* ... so it's done when the DMA is done, not just
 			   the command. */
-			doneint = 0x10000000;
+			doneint = CAFE_NAND_IRQ_DMA_DONE;
 		}
 		cafe_writel(cafe, dmactl, NAND_DMA_CTRL);
 	}
@@ -295,7 +407,7 @@ static void cafe_nand_cmdfunc(struct nand_chip *chip, unsigned command,
 			     command, 500000-c, irqs, cafe_readl(cafe, NAND_IRQ));
 	}
 
-	WARN_ON(cafe->ctl2 & (1<<30));
+	WARN_ON(cafe->ctl2 & CAFE_NAND_CTRL2_AUTO_WRITE_ECC);
 
 	switch (command) {
 
@@ -322,10 +434,8 @@ static void cafe_select_chip(struct nand_chip *chip, int chipnr)
 
 	/* Mask the appropriate bit into the stored value of ctl1
 	   which will be used by cafe_nand_cmdfunc() */
-	if (chipnr)
-		cafe->ctl1 |= CTRL1_CHIPSELECT;
-	else
-		cafe->ctl1 &= ~CTRL1_CHIPSELECT;
+	cafe->ctl1 &= ~CAFE_NAND_CTRL1_CE;
+	cafe->ctl1 |= CAFE_FIELD_PREP(NAND_CTRL1, CE, chipnr);
 }
 
 static irqreturn_t cafe_nand_interrupt(int irq, void *id)
@@ -334,7 +444,9 @@ static irqreturn_t cafe_nand_interrupt(int irq, void *id)
 	struct nand_chip *chip = mtd_to_nand(mtd);
 	struct cafe_priv *cafe = nand_get_controller_data(chip);
 	uint32_t irqs = cafe_readl(cafe, NAND_IRQ);
-	cafe_writel(cafe, irqs & ~0x90000000, NAND_IRQ);
+	cafe_writel(cafe,
+		    irqs & ~(CAFE_NAND_IRQ_CMD_DONE | CAFE_NAND_IRQ_DMA_DONE),
+		    NAND_IRQ);
 	if (!irqs)
 		return IRQ_NONE;
 
@@ -368,25 +480,31 @@ static int cafe_nand_read_page(struct nand_chip *chip, uint8_t *buf,
 	struct mtd_info *mtd = nand_to_mtd(chip);
 	struct cafe_priv *cafe = nand_get_controller_data(chip);
 	unsigned int max_bitflips = 0;
+	u32 ecc_result, status;
 
 	cafe_dev_dbg(&cafe->pdev->dev, "ECC result %08x SYN1,2 %08x\n",
 		     cafe_readl(cafe, NAND_ECC_RESULT),
-		     cafe_readl(cafe, NAND_ECC_SYN01));
+		     cafe_readl(cafe, NAND_ECC_SYN_REG(0)));
 
 	nand_read_page_op(chip, page, 0, buf, mtd->writesize);
 	chip->legacy.read_buf(chip, chip->oob_poi, mtd->oobsize);
 
-	if (checkecc && cafe_readl(cafe, NAND_ECC_RESULT) & (1<<18)) {
+	ecc_result = cafe_readl(cafe, NAND_ECC_RESULT);
+	status = CAFE_FIELD_GET(NAND_ECC_RESULT, STATUS, ecc_result);
+	if (checkecc && status == CAFE_NAND_ECC_RESULT_CORRECTABLE_ERRS) {
 		unsigned short syn[8], pat[4];
 		int pos[4];
 		u8 *oob = chip->oob_poi;
 		int i, n;
 
 		for (i=0; i<8; i+=2) {
-			uint32_t tmp = cafe_readl(cafe, NAND_ECC_SYN01 + (i*2));
+			uint32_t tmp = cafe_readl(cafe, NAND_ECC_SYN_REG(i));
+			uint16_t idx;
 
-			syn[i] = cafe->rs->codec->index_of[tmp & 0xfff];
-			syn[i+1] = cafe->rs->codec->index_of[(tmp >> 16) & 0xfff];
+			idx = FIELD_GET(CAFE_NAND_ECC_SYN_FIELD(i), tmp);
+			syn[i] = cafe->rs->codec->index_of[idx];
+			idx = FIELD_GET(CAFE_NAND_ECC_SYN_FIELD(i + 1), tmp);
+			syn[i+1] = cafe->rs->codec->index_of[idx];
 		}
 
 		n = decode_rs16(cafe->rs, NULL, NULL, 1367, syn, 0, pos, 0,
@@ -536,7 +654,7 @@ static int cafe_nand_write_page(struct nand_chip *chip,
 	chip->legacy.write_buf(chip, chip->oob_poi, mtd->oobsize);
 
 	/* Set up ECC autogeneration */
-	cafe->ctl2 |= (1<<30);
+	cafe->ctl2 |= CAFE_NAND_CTRL2_AUTO_WRITE_ECC;
 
 	return nand_prog_page_end_op(chip);
 }
@@ -604,9 +722,9 @@ static int cafe_nand_attach_chip(struct nand_chip *chip)
 	/* Restore the DMA flag */
 	cafe->usedma = usedma;
 
-	cafe->ctl2 = BIT(27); /* Reed-Solomon ECC */
-	if (mtd->writesize == 2048)
-		cafe->ctl2 |= BIT(29); /* 2KiB page size */
+	cafe->ctl2 = CAFE_NAND_CTRL2_ECC_ALG_RS |
+		     CAFE_FIELD_PREP(NAND_CTRL2, PAGE_SIZE,
+				     mtd->writesize / 512);
 
 	/* Set up ECC according to the type of chip we found */
 	mtd_set_ooblayout(mtd, &cafe_ooblayout_ops);
@@ -734,8 +852,8 @@ static int cafe_nand_probe(struct pci_dev *pdev,
 	}
 
 	/* Start off by resetting the NAND controller completely */
-	cafe_writel(cafe, 1, NAND_RESET);
-	cafe_writel(cafe, 0, NAND_RESET);
+	cafe_writel(cafe, CAFE_GLOBAL_RESET_NAND, GLOBAL_RESET);
+	cafe_writel(cafe, 0, GLOBAL_RESET);
 
 	cafe_writel(cafe, timing[0], NAND_TIMING1);
 	cafe_writel(cafe, timing[1], NAND_TIMING2);
@@ -751,17 +869,49 @@ static int cafe_nand_probe(struct pci_dev *pdev,
 
 	/* Disable master reset, enable NAND clock */
 	ctrl = cafe_readl(cafe, GLOBAL_CTRL);
-	ctrl &= 0xffffeff0;
-	ctrl |= 0x00007000;
-	cafe_writel(cafe, ctrl | 0x05, GLOBAL_CTRL);
-	cafe_writel(cafe, ctrl | 0x0a, GLOBAL_CTRL);
+	ctrl &= ~(CAFE_GLOBAL_SW_RESET_SET |
+		  CAFE_GLOBAL_SW_RESET_CLEAR |
+		  CAFE_GLOBAL_MASTER_RESET_SET |
+		  CAFE_GLOBAL_MASTER_RESET_CLEAR |
+		  CAFE_GLOBAL_NAND_CLK_ENABLE);
+	ctrl |= CAFE_GLOBAL_NAND_CLK_ENABLE |
+		CAFE_GLOBAL_SDH_CLK_ENABLE |
+		CAFE_GLOBAL_CCIC_CLK_ENABLE;
+	cafe_writel(cafe,
+		    ctrl |
+		    CAFE_GLOBAL_MASTER_RESET_SET |
+		    CAFE_GLOBAL_SW_RESET_SET,
+		    GLOBAL_CTRL);
+	cafe_writel(cafe,
+		    ctrl |
+		    CAFE_GLOBAL_MASTER_RESET_CLEAR |
+		    CAFE_GLOBAL_SW_RESET_CLEAR,
+		    GLOBAL_CTRL);
+
 	cafe_writel(cafe, 0, NAND_DMA_CTRL);
 
-	cafe_writel(cafe, 0x7006, GLOBAL_CTRL);
-	cafe_writel(cafe, 0x700a, GLOBAL_CTRL);
+	cafe_writel(cafe,
+		    CAFE_GLOBAL_NAND_CLK_ENABLE |
+		    CAFE_GLOBAL_SDH_CLK_ENABLE |
+		    CAFE_GLOBAL_CCIC_CLK_ENABLE |
+		    CAFE_GLOBAL_MASTER_RESET_SET |
+		    CAFE_GLOBAL_SW_RESET_CLEAR,
+		    GLOBAL_CTRL);
+	cafe_writel(cafe,
+		    CAFE_GLOBAL_NAND_CLK_ENABLE |
+		    CAFE_GLOBAL_SDH_CLK_ENABLE |
+		    CAFE_GLOBAL_CCIC_CLK_ENABLE |
+		    CAFE_GLOBAL_MASTER_RESET_CLEAR |
+		    CAFE_GLOBAL_SW_RESET_CLEAR,
+		    GLOBAL_CTRL);
 
 	/* Enable NAND IRQ in global IRQ mask register */
-	cafe_writel(cafe, 0x80000007, GLOBAL_IRQ_MASK);
+	cafe_writel(cafe,
+		    CAFE_GLOBAL_IRQ_PCI_ERROR |
+		    CAFE_GLOBAL_IRQ_CCIC |
+		    CAFE_GLOBAL_IRQ_SDH |
+		    CAFE_GLOBAL_IRQ_NAND,
+		    GLOBAL_IRQ_MASK);
 	cafe_dev_dbg(&cafe->pdev->dev, "Control %x, IRQ mask %x\n",
 		cafe_readl(cafe, GLOBAL_CTRL),
 		cafe_readl(cafe, GLOBAL_IRQ_MASK));
@@ -788,7 +938,9 @@ static int cafe_nand_probe(struct pci_dev *pdev,
 	nand_cleanup(&cafe->nand);
  out_irq:
 	/* Disable NAND IRQ in global IRQ mask register */
-	cafe_writel(cafe, ~1 & cafe_readl(cafe, GLOBAL_IRQ_MASK), GLOBAL_IRQ_MASK);
+	cafe_writel(cafe,
+		    cafe_readl(cafe, GLOBAL_IRQ_MASK) & ~CAFE_GLOBAL_IRQ_NAND,
+		    GLOBAL_IRQ_MASK);
 	free_irq(pdev->irq, mtd);
  out_ior:
 	pci_iounmap(pdev, cafe->mmio);
@@ -805,7 +957,9 @@ static void cafe_nand_remove(struct pci_dev *pdev)
 	struct cafe_priv *cafe = nand_get_controller_data(chip);
 
 	/* Disable NAND IRQ in global IRQ mask register */
-	cafe_writel(cafe, ~1 & cafe_readl(cafe, GLOBAL_IRQ_MASK), GLOBAL_IRQ_MASK);
+	cafe_writel(cafe,
+		    cafe_readl(cafe, GLOBAL_IRQ_MASK) & ~CAFE_GLOBAL_IRQ_NAND,
+		    GLOBAL_IRQ_MASK);
 	free_irq(pdev->irq, mtd);
 	nand_release(chip);
 	free_rs(cafe->rs);
@@ -830,8 +984,8 @@ static int cafe_nand_resume(struct pci_dev *pdev)
 	struct cafe_priv *cafe = nand_get_controller_data(chip);
 
        /* Start off by resetting the NAND controller completely */
-	cafe_writel(cafe, 1, NAND_RESET);
-	cafe_writel(cafe, 0, NAND_RESET);
+	cafe_writel(cafe, CAFE_GLOBAL_RESET_NAND, GLOBAL_RESET);
+	cafe_writel(cafe, 0, GLOBAL_RESET);
 	cafe_writel(cafe, 0xffffffff, NAND_IRQ_MASK);
 
 	/* Restore timing configuration */
@@ -841,13 +995,41 @@ static int cafe_nand_resume(struct pci_dev *pdev)
 
         /* Disable master reset, enable NAND clock */
 	ctrl = cafe_readl(cafe, GLOBAL_CTRL);
-	ctrl &= 0xffffeff0;
-	ctrl |= 0x00007000;
-	cafe_writel(cafe, ctrl | 0x05, GLOBAL_CTRL);
-	cafe_writel(cafe, ctrl | 0x0a, GLOBAL_CTRL);
+	ctrl &= ~(CAFE_GLOBAL_SW_RESET_SET |
+		  CAFE_GLOBAL_SW_RESET_CLEAR |
+		  CAFE_GLOBAL_MASTER_RESET_SET |
+		  CAFE_GLOBAL_MASTER_RESET_CLEAR |
+		  CAFE_GLOBAL_NAND_CLK_ENABLE);
+	ctrl |= CAFE_GLOBAL_NAND_CLK_ENABLE |
+		CAFE_GLOBAL_SDH_CLK_ENABLE |
+		CAFE_GLOBAL_CCIC_CLK_ENABLE;
+	cafe_writel(cafe,
+		    ctrl |
+		    CAFE_GLOBAL_MASTER_RESET_SET |
+		    CAFE_GLOBAL_SW_RESET_SET,
+		    GLOBAL_CTRL);
+	cafe_writel(cafe,
+		    ctrl |
+		    CAFE_GLOBAL_MASTER_RESET_CLEAR |
+		    CAFE_GLOBAL_SW_RESET_CLEAR,
+		    GLOBAL_CTRL);
+
 	cafe_writel(cafe, 0, NAND_DMA_CTRL);
-	cafe_writel(cafe, 0x7006, GLOBAL_CTRL);
-	cafe_writel(cafe, 0x700a, GLOBAL_CTRL);
+
+	cafe_writel(cafe,
+		    CAFE_GLOBAL_NAND_CLK_ENABLE |
+		    CAFE_GLOBAL_SDH_CLK_ENABLE |
+		    CAFE_GLOBAL_CCIC_CLK_ENABLE |
+		    CAFE_GLOBAL_MASTER_RESET_SET |
+		    CAFE_GLOBAL_SW_RESET_CLEAR,
+		    GLOBAL_CTRL);
+	cafe_writel(cafe,
+		    CAFE_GLOBAL_NAND_CLK_ENABLE |
+		    CAFE_GLOBAL_SDH_CLK_ENABLE |
+		    CAFE_GLOBAL_CCIC_CLK_ENABLE |
+		    CAFE_GLOBAL_MASTER_RESET_CLEAR |
+		    CAFE_GLOBAL_SW_RESET_CLEAR,
+		    GLOBAL_CTRL);
 
 	/* Set up DMA address */
 	cafe_writel(cafe, cafe->dmaaddr & 0xffffffff, NAND_DMA_ADDR0);
@@ -858,7 +1040,12 @@ static int cafe_nand_resume(struct pci_dev *pdev)
 		cafe_writel(cafe, 0, NAND_DMA_ADDR1);
 
 	/* Enable NAND IRQ in global IRQ mask register */
-	cafe_writel(cafe, 0x80000007, GLOBAL_IRQ_MASK);
+	cafe_writel(cafe,
+		    CAFE_GLOBAL_IRQ_PCI_ERROR |
+		    CAFE_GLOBAL_IRQ_CCIC |
+		    CAFE_GLOBAL_IRQ_SDH |
+		    CAFE_GLOBAL_IRQ_NAND,
+		    GLOBAL_IRQ_MASK);
 	return 0;
 }
 
-- 
2.25.3


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

^ permalink raw reply	[flat|nested] 46+ messages in thread

* [PATCH v2 07/19] mtd: rawnand: cafe: Factor out the controller initialization logic
  2020-05-05 10:13 [PATCH v2 00/19] mtd: rawnand: cafe: Convert to exec_op() (and more) Boris Brezillon
                   ` (5 preceding siblings ...)
  2020-05-05 10:13 ` [PATCH v2 06/19] mtd: rawnand: cafe: Demistify register fields Boris Brezillon
@ 2020-05-05 10:13 ` Boris Brezillon
  2020-05-10 21:49   ` Miquel Raynal
  2020-05-05 10:13 ` [PATCH v2 08/19] mtd: rawnand: cafe: Get rid of the debug module param Boris Brezillon
                   ` (12 subsequent siblings)
  19 siblings, 1 reply; 46+ messages in thread
From: Boris Brezillon @ 2020-05-05 10:13 UTC (permalink / raw)
  To: Miquel Raynal, linux-mtd, Lubomir Rintel
  Cc: Richard Weinberger, Boris Brezillon, Vignesh Raghavendra, Tudor Ambarus

The same code is present in the probe and resume path. Let's create
an init helper to factor that out.

Signed-off-by: Boris Brezillon <boris.brezillon@collabora.com>
Tested-by: Lubomir Rintel <lkundrak@v3.sk>
---
Changes in v2:
* Add R-b/T-b
* Add a blank line before return statement
---
 drivers/mtd/nand/raw/cafe_nand.c | 188 +++++++++++--------------------
 1 file changed, 67 insertions(+), 121 deletions(-)

diff --git a/drivers/mtd/nand/raw/cafe_nand.c b/drivers/mtd/nand/raw/cafe_nand.c
index 7fb5b21aeb00..542165db9a67 100644
--- a/drivers/mtd/nand/raw/cafe_nand.c
+++ b/drivers/mtd/nand/raw/cafe_nand.c
@@ -772,12 +772,76 @@ static const struct nand_controller_ops cafe_nand_controller_ops = {
 	.detach_chip = cafe_nand_detach_chip,
 };
 
+static void cafe_nand_init(struct cafe_priv *cafe)
+{
+	u32 ctrl;
+
+	/* Start off by resetting the NAND controller completely */
+	cafe_writel(cafe, CAFE_GLOBAL_RESET_NAND, GLOBAL_RESET);
+	cafe_writel(cafe, 0, GLOBAL_RESET);
+	cafe_writel(cafe, 0xffffffff, NAND_IRQ_MASK);
+
+	/* Restore timing configuration */
+	cafe_writel(cafe, timing[0], NAND_TIMING1);
+	cafe_writel(cafe, timing[1], NAND_TIMING2);
+	cafe_writel(cafe, timing[2], NAND_TIMING3);
+
+	/* Disable master reset, enable NAND clock */
+	ctrl = cafe_readl(cafe, GLOBAL_CTRL);
+	ctrl &= ~(CAFE_GLOBAL_SW_RESET_SET |
+		  CAFE_GLOBAL_SW_RESET_CLEAR |
+		  CAFE_GLOBAL_MASTER_RESET_SET |
+		  CAFE_GLOBAL_MASTER_RESET_CLEAR |
+		  CAFE_GLOBAL_NAND_CLK_ENABLE);
+	ctrl |= CAFE_GLOBAL_NAND_CLK_ENABLE |
+		CAFE_GLOBAL_SDH_CLK_ENABLE |
+		CAFE_GLOBAL_CCIC_CLK_ENABLE;
+	cafe_writel(cafe,
+		    ctrl |
+		    CAFE_GLOBAL_MASTER_RESET_SET |
+		    CAFE_GLOBAL_SW_RESET_SET,
+		    GLOBAL_CTRL);
+	cafe_writel(cafe,
+		    ctrl |
+		    CAFE_GLOBAL_MASTER_RESET_CLEAR |
+		    CAFE_GLOBAL_SW_RESET_CLEAR,
+		    GLOBAL_CTRL);
+
+	cafe_writel(cafe, 0, NAND_DMA_CTRL);
+
+	cafe_writel(cafe,
+		    CAFE_GLOBAL_NAND_CLK_ENABLE |
+		    CAFE_GLOBAL_SDH_CLK_ENABLE |
+		    CAFE_GLOBAL_CCIC_CLK_ENABLE |
+		    CAFE_GLOBAL_MASTER_RESET_SET |
+		    CAFE_GLOBAL_SW_RESET_CLEAR,
+		    GLOBAL_CTRL);
+	cafe_writel(cafe,
+		    CAFE_GLOBAL_NAND_CLK_ENABLE |
+		    CAFE_GLOBAL_SDH_CLK_ENABLE |
+		    CAFE_GLOBAL_CCIC_CLK_ENABLE |
+		    CAFE_GLOBAL_MASTER_RESET_CLEAR |
+		    CAFE_GLOBAL_SW_RESET_CLEAR,
+		    GLOBAL_CTRL);
+
+	/* Set up DMA address */
+	cafe_writel(cafe, lower_32_bits(cafe->dmaaddr), NAND_DMA_ADDR0);
+	cafe_writel(cafe, upper_32_bits(cafe->dmaaddr), NAND_DMA_ADDR1);
+
+	/* Enable NAND IRQ in global IRQ mask register */
+	cafe_writel(cafe,
+		    CAFE_GLOBAL_IRQ_PCI_ERROR |
+		    CAFE_GLOBAL_IRQ_CCIC |
+		    CAFE_GLOBAL_IRQ_SDH |
+		    CAFE_GLOBAL_IRQ_NAND,
+		    GLOBAL_IRQ_MASK);
+}
+
 static int cafe_nand_probe(struct pci_dev *pdev,
 				     const struct pci_device_id *ent)
 {
 	struct mtd_info *mtd;
 	struct cafe_priv *cafe;
-	uint32_t ctrl;
 	int err = 0;
 
 	/* Very old versions shared the same PCI ident for all three
@@ -851,15 +915,8 @@ static int cafe_nand_probe(struct pci_dev *pdev,
 		}
 	}
 
-	/* Start off by resetting the NAND controller completely */
-	cafe_writel(cafe, CAFE_GLOBAL_RESET_NAND, GLOBAL_RESET);
-	cafe_writel(cafe, 0, GLOBAL_RESET);
+	cafe_nand_init(cafe);
 
-	cafe_writel(cafe, timing[0], NAND_TIMING1);
-	cafe_writel(cafe, timing[1], NAND_TIMING2);
-	cafe_writel(cafe, timing[2], NAND_TIMING3);
-
-	cafe_writel(cafe, 0xffffffff, NAND_IRQ_MASK);
 	err = request_irq(pdev->irq, &cafe_nand_interrupt, IRQF_SHARED,
 			  "CAFE NAND", mtd);
 	if (err) {
@@ -867,55 +924,6 @@ static int cafe_nand_probe(struct pci_dev *pdev,
 		goto out_ior;
 	}
 
-	/* Disable master reset, enable NAND clock */
-	ctrl = cafe_readl(cafe, GLOBAL_CTRL);
-	ctrl &= ~(CAFE_GLOBAL_SW_RESET_SET |
-		  CAFE_GLOBAL_SW_RESET_CLEAR |
-		  CAFE_GLOBAL_MASTER_RESET_SET |
-		  CAFE_GLOBAL_MASTER_RESET_CLEAR |
-		  CAFE_GLOBAL_NAND_CLK_ENABLE);
-	ctrl |= CAFE_GLOBAL_NAND_CLK_ENABLE |
-		CAFE_GLOBAL_SDH_CLK_ENABLE |
-		CAFE_GLOBAL_CCIC_CLK_ENABLE;
-	cafe_writel(cafe,
-		    ctrl |
-		    CAFE_GLOBAL_MASTER_RESET_SET |
-		    CAFE_GLOBAL_SW_RESET_SET,
-		    GLOBAL_CTRL);
-	cafe_writel(cafe,
-		    ctrl |
-		    CAFE_GLOBAL_MASTER_RESET_CLEAR |
-		    CAFE_GLOBAL_SW_RESET_CLEAR,
-		    GLOBAL_CTRL);
-
-	cafe_writel(cafe, 0, NAND_DMA_CTRL);
-
-	cafe_writel(cafe,
-		    CAFE_GLOBAL_NAND_CLK_ENABLE |
-		    CAFE_GLOBAL_SDH_CLK_ENABLE |
-		    CAFE_GLOBAL_CCIC_CLK_ENABLE |
-		    CAFE_GLOBAL_MASTER_RESET_SET |
-		    CAFE_GLOBAL_SW_RESET_CLEAR,
-		    GLOBAL_CTRL);
-	cafe_writel(cafe,
-		    CAFE_GLOBAL_NAND_CLK_ENABLE |
-		    CAFE_GLOBAL_SDH_CLK_ENABLE |
-		    CAFE_GLOBAL_CCIC_CLK_ENABLE |
-		    CAFE_GLOBAL_MASTER_RESET_CLEAR |
-		    CAFE_GLOBAL_SW_RESET_CLEAR,
-		    GLOBAL_CTRL);
-
-	/* Enable NAND IRQ in global IRQ mask register */
-	cafe_writel(cafe,
-		    CAFE_GLOBAL_IRQ_PCI_ERROR |
-		    CAFE_GLOBAL_IRQ_CCIC |
-		    CAFE_GLOBAL_IRQ_SDH |
-		    CAFE_GLOBAL_IRQ_NAND,
-		    GLOBAL_IRQ_MASK);
-	cafe_dev_dbg(&cafe->pdev->dev, "Control %x, IRQ mask %x\n",
-		cafe_readl(cafe, GLOBAL_CTRL),
-		cafe_readl(cafe, GLOBAL_IRQ_MASK));
-
 	/* Do not use the DMA during the NAND identification */
 	cafe->usedma = 0;
 
@@ -978,74 +986,12 @@ MODULE_DEVICE_TABLE(pci, cafe_nand_tbl);
 
 static int cafe_nand_resume(struct pci_dev *pdev)
 {
-	uint32_t ctrl;
 	struct mtd_info *mtd = pci_get_drvdata(pdev);
 	struct nand_chip *chip = mtd_to_nand(mtd);
 	struct cafe_priv *cafe = nand_get_controller_data(chip);
 
-       /* Start off by resetting the NAND controller completely */
-	cafe_writel(cafe, CAFE_GLOBAL_RESET_NAND, GLOBAL_RESET);
-	cafe_writel(cafe, 0, GLOBAL_RESET);
-	cafe_writel(cafe, 0xffffffff, NAND_IRQ_MASK);
+	cafe_nand_init(cafe);
 
-	/* Restore timing configuration */
-	cafe_writel(cafe, timing[0], NAND_TIMING1);
-	cafe_writel(cafe, timing[1], NAND_TIMING2);
-	cafe_writel(cafe, timing[2], NAND_TIMING3);
-
-        /* Disable master reset, enable NAND clock */
-	ctrl = cafe_readl(cafe, GLOBAL_CTRL);
-	ctrl &= ~(CAFE_GLOBAL_SW_RESET_SET |
-		  CAFE_GLOBAL_SW_RESET_CLEAR |
-		  CAFE_GLOBAL_MASTER_RESET_SET |
-		  CAFE_GLOBAL_MASTER_RESET_CLEAR |
-		  CAFE_GLOBAL_NAND_CLK_ENABLE);
-	ctrl |= CAFE_GLOBAL_NAND_CLK_ENABLE |
-		CAFE_GLOBAL_SDH_CLK_ENABLE |
-		CAFE_GLOBAL_CCIC_CLK_ENABLE;
-	cafe_writel(cafe,
-		    ctrl |
-		    CAFE_GLOBAL_MASTER_RESET_SET |
-		    CAFE_GLOBAL_SW_RESET_SET,
-		    GLOBAL_CTRL);
-	cafe_writel(cafe,
-		    ctrl |
-		    CAFE_GLOBAL_MASTER_RESET_CLEAR |
-		    CAFE_GLOBAL_SW_RESET_CLEAR,
-		    GLOBAL_CTRL);
-
-	cafe_writel(cafe, 0, NAND_DMA_CTRL);
-
-	cafe_writel(cafe,
-		    CAFE_GLOBAL_NAND_CLK_ENABLE |
-		    CAFE_GLOBAL_SDH_CLK_ENABLE |
-		    CAFE_GLOBAL_CCIC_CLK_ENABLE |
-		    CAFE_GLOBAL_MASTER_RESET_SET |
-		    CAFE_GLOBAL_SW_RESET_CLEAR,
-		    GLOBAL_CTRL);
-	cafe_writel(cafe,
-		    CAFE_GLOBAL_NAND_CLK_ENABLE |
-		    CAFE_GLOBAL_SDH_CLK_ENABLE |
-		    CAFE_GLOBAL_CCIC_CLK_ENABLE |
-		    CAFE_GLOBAL_MASTER_RESET_CLEAR |
-		    CAFE_GLOBAL_SW_RESET_CLEAR,
-		    GLOBAL_CTRL);
-
-	/* Set up DMA address */
-	cafe_writel(cafe, cafe->dmaaddr & 0xffffffff, NAND_DMA_ADDR0);
-	if (sizeof(cafe->dmaaddr) > 4)
-	/* Shift in two parts to shut the compiler up */
-		cafe_writel(cafe, (cafe->dmaaddr >> 16) >> 16, NAND_DMA_ADDR1);
-	else
-		cafe_writel(cafe, 0, NAND_DMA_ADDR1);
-
-	/* Enable NAND IRQ in global IRQ mask register */
-	cafe_writel(cafe,
-		    CAFE_GLOBAL_IRQ_PCI_ERROR |
-		    CAFE_GLOBAL_IRQ_CCIC |
-		    CAFE_GLOBAL_IRQ_SDH |
-		    CAFE_GLOBAL_IRQ_NAND,
-		    GLOBAL_IRQ_MASK);
 	return 0;
 }
 
-- 
2.25.3


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

^ permalink raw reply	[flat|nested] 46+ messages in thread

* [PATCH v2 08/19] mtd: rawnand: cafe: Get rid of the debug module param
  2020-05-05 10:13 [PATCH v2 00/19] mtd: rawnand: cafe: Convert to exec_op() (and more) Boris Brezillon
                   ` (6 preceding siblings ...)
  2020-05-05 10:13 ` [PATCH v2 07/19] mtd: rawnand: cafe: Factor out the controller initialization logic Boris Brezillon
@ 2020-05-05 10:13 ` Boris Brezillon
  2020-05-05 10:13 ` [PATCH v2 09/19] mtd: rawnand: cafe: Use devm_kzalloc and devm_request_irq() Boris Brezillon
                   ` (11 subsequent siblings)
  19 siblings, 0 replies; 46+ messages in thread
From: Boris Brezillon @ 2020-05-05 10:13 UTC (permalink / raw)
  To: Miquel Raynal, linux-mtd, Lubomir Rintel
  Cc: Richard Weinberger, Boris Brezillon, Vignesh Raghavendra, Tudor Ambarus

Dynamic prink already offers conditional debug traces enablement, let's
not define a new way to do the same thing.

Signed-off-by: Boris Brezillon <boris.brezillon@collabora.com>
Reviewed-by: Miquel Raynal <miquel.raynal@bootlin.com>
---
Changes in v2:
* Add R-b
---
 drivers/mtd/nand/raw/cafe_nand.c | 59 ++++++++++++++------------------
 1 file changed, 25 insertions(+), 34 deletions(-)

diff --git a/drivers/mtd/nand/raw/cafe_nand.c b/drivers/mtd/nand/raw/cafe_nand.c
index 542165db9a67..fedf434a563f 100644
--- a/drivers/mtd/nand/raw/cafe_nand.c
+++ b/drivers/mtd/nand/raw/cafe_nand.c
@@ -10,10 +10,7 @@
  */
 
 #include <linux/bitfield.h>
-#define DEBUG
-
 #include <linux/device.h>
-#undef DEBUG
 #include <linux/mtd/mtd.h>
 #include <linux/mtd/rawnand.h>
 #include <linux/mtd/partitions.h>
@@ -170,9 +167,6 @@ module_param(usedma, int, 0644);
 static int skipbbt = 0;
 module_param(skipbbt, int, 0644);
 
-static int debug = 0;
-module_param(debug, int, 0644);
-
 static int regdebug = 0;
 module_param(regdebug, int, 0644);
 
@@ -185,9 +179,6 @@ module_param_array(timing, int, &numtimings, 0644);
 
 static const char *part_probes[] = { "cmdlinepart", "RedBoot", NULL };
 
-/* Hrm. Why isn't this already conditional on something in the struct device? */
-#define cafe_dev_dbg(dev, args...) do { if (debug) dev_dbg(dev, ##args); } while(0)
-
 /* Make it easier to switch to PIO if we need to */
 #define cafe_readl(cafe, addr)			readl((cafe)->mmio + CAFE_##addr)
 #define cafe_writel(cafe, datum, addr)		writel(datum, (cafe)->mmio + CAFE_##addr)
@@ -201,7 +192,7 @@ static int cafe_device_ready(struct nand_chip *chip)
 
 	cafe_writel(cafe, irqs, NAND_IRQ);
 
-	cafe_dev_dbg(&cafe->pdev->dev, "NAND device is%s ready, IRQ %x (%x) (%x,%x)\n",
+	dev_dbg(&cafe->pdev->dev, "NAND device is%s ready, IRQ %x (%x) (%x,%x)\n",
 		result?"":" not", irqs, cafe_readl(cafe, NAND_IRQ),
 		cafe_readl(cafe, GLOBAL_IRQ), cafe_readl(cafe, GLOBAL_IRQ_MASK));
 
@@ -220,7 +211,7 @@ static void cafe_write_buf(struct nand_chip *chip, const uint8_t *buf, int len)
 
 	cafe->datalen += len;
 
-	cafe_dev_dbg(&cafe->pdev->dev, "Copy 0x%x bytes to write buffer. datalen 0x%x\n",
+	dev_dbg(&cafe->pdev->dev, "Copy 0x%x bytes to write buffer. datalen 0x%x\n",
 		len, cafe->datalen);
 }
 
@@ -233,8 +224,8 @@ static void cafe_read_buf(struct nand_chip *chip, uint8_t *buf, int len)
 	else
 		memcpy_fromio(buf, cafe->mmio + CAFE_NAND_READ_DATA + cafe->datalen, len);
 
-	cafe_dev_dbg(&cafe->pdev->dev, "Copy 0x%x bytes from position 0x%x in read buffer.\n",
-		  len, cafe->datalen);
+	dev_dbg(&cafe->pdev->dev, "Copy 0x%x bytes from position 0x%x in read buffer.\n",
+		len, cafe->datalen);
 	cafe->datalen += len;
 }
 
@@ -244,7 +235,7 @@ static uint8_t cafe_read_byte(struct nand_chip *chip)
 	uint8_t d;
 
 	cafe_read_buf(chip, &d, 1);
-	cafe_dev_dbg(&cafe->pdev->dev, "Read %02x\n", d);
+	dev_dbg(&cafe->pdev->dev, "Read %02x\n", d);
 
 	return d;
 }
@@ -258,7 +249,7 @@ static void cafe_nand_cmdfunc(struct nand_chip *chip, unsigned command,
 	uint32_t ctl1;
 	uint32_t doneint = CAFE_NAND_IRQ_CMD_DONE;
 
-	cafe_dev_dbg(&cafe->pdev->dev, "cmdfunc %02x, 0x%x, 0x%x\n",
+	dev_dbg(&cafe->pdev->dev, "cmdfunc %02x, 0x%x, 0x%x\n",
 		command, column, page_addr);
 
 	if (command == NAND_CMD_ERASE2 || command == NAND_CMD_PAGEPROG) {
@@ -270,8 +261,8 @@ static void cafe_nand_cmdfunc(struct nand_chip *chip, unsigned command,
 			    NAND_CTRL2);
 		ctl1 = cafe->ctl1;
 		cafe->ctl2 &= ~CAFE_NAND_CTRL2_AUTO_WRITE_ECC;
-		cafe_dev_dbg(&cafe->pdev->dev, "Continue command, ctl1 %08x, #data %d\n",
-			  cafe->ctl1, cafe->nr_data);
+		dev_dbg(&cafe->pdev->dev, "Continue command, ctl1 %08x, #data %d\n",
+			cafe->ctl1, cafe->nr_data);
 		goto do_command;
 	}
 	/* Reset ECC engine */
@@ -333,8 +324,8 @@ static void cafe_nand_cmdfunc(struct nand_chip *chip, unsigned command,
 		/* Ignore the first command of a pair; the hardware
 		   deals with them both at once, later */
 		cafe->ctl1 = ctl1;
-		cafe_dev_dbg(&cafe->pdev->dev, "Setup for delayed command, ctl1 %08x, dlen %x\n",
-			  cafe->ctl1, cafe->datalen);
+		dev_dbg(&cafe->pdev->dev, "Setup for delayed command, ctl1 %08x, dlen %x\n",
+			cafe->ctl1, cafe->datalen);
 		return;
 	}
 	/* RNDOUT and READ0 commands need a following byte */
@@ -350,7 +341,7 @@ static void cafe_nand_cmdfunc(struct nand_chip *chip, unsigned command,
 			    NAND_CTRL2);
 
  do_command:
-	cafe_dev_dbg(&cafe->pdev->dev, "dlen %x, ctl1 %x, ctl2 %x\n",
+	dev_dbg(&cafe->pdev->dev, "dlen %x, ctl1 %x, ctl2 %x\n",
 		cafe->datalen, ctl1, cafe_readl(cafe, NAND_CTRL2));
 
 	/* NB: The datasheet lies -- we really should be subtracting 1 here */
@@ -399,12 +390,12 @@ static void cafe_nand_cmdfunc(struct nand_chip *chip, unsigned command,
 				break;
 			udelay(1);
 			if (!(c % 100000))
-				cafe_dev_dbg(&cafe->pdev->dev, "Wait for ready, IRQ %x\n", irqs);
+				dev_dbg(&cafe->pdev->dev, "Wait for ready, IRQ %x\n", irqs);
 			cpu_relax();
 		}
 		cafe_writel(cafe, doneint, NAND_IRQ);
-		cafe_dev_dbg(&cafe->pdev->dev, "Command %x completed after %d usec, irqs %x (%x)\n",
-			     command, 500000-c, irqs, cafe_readl(cafe, NAND_IRQ));
+		dev_dbg(&cafe->pdev->dev, "Command %x completed after %d usec, irqs %x (%x)\n",
+			command, 500000-c, irqs, cafe_readl(cafe, NAND_IRQ));
 	}
 
 	WARN_ON(cafe->ctl2 & CAFE_NAND_CTRL2_AUTO_WRITE_ECC);
@@ -430,7 +421,7 @@ static void cafe_select_chip(struct nand_chip *chip, int chipnr)
 {
 	struct cafe_priv *cafe = nand_get_controller_data(chip);
 
-	cafe_dev_dbg(&cafe->pdev->dev, "select_chip %d\n", chipnr);
+	dev_dbg(&cafe->pdev->dev, "select_chip %d\n", chipnr);
 
 	/* Mask the appropriate bit into the stored value of ctl1
 	   which will be used by cafe_nand_cmdfunc() */
@@ -450,7 +441,7 @@ static irqreturn_t cafe_nand_interrupt(int irq, void *id)
 	if (!irqs)
 		return IRQ_NONE;
 
-	cafe_dev_dbg(&cafe->pdev->dev, "irq, bits %x (%x)\n", irqs, cafe_readl(cafe, NAND_IRQ));
+	dev_dbg(&cafe->pdev->dev, "irq, bits %x (%x)\n", irqs, cafe_readl(cafe, NAND_IRQ));
 	return IRQ_HANDLED;
 }
 
@@ -482,9 +473,9 @@ static int cafe_nand_read_page(struct nand_chip *chip, uint8_t *buf,
 	unsigned int max_bitflips = 0;
 	u32 ecc_result, status;
 
-	cafe_dev_dbg(&cafe->pdev->dev, "ECC result %08x SYN1,2 %08x\n",
-		     cafe_readl(cafe, NAND_ECC_RESULT),
-		     cafe_readl(cafe, NAND_ECC_SYN_REG(0)));
+	dev_dbg(&cafe->pdev->dev, "ECC result %08x SYN1,2 %08x\n",
+		cafe_readl(cafe, NAND_ECC_RESULT),
+		cafe_readl(cafe, NAND_ECC_SYN_REG(0)));
 
 	nand_read_page_op(chip, page, 0, buf, mtd->writesize);
 	chip->legacy.read_buf(chip, chip->oob_poi, mtd->oobsize);
@@ -716,8 +707,8 @@ static int cafe_nand_attach_chip(struct nand_chip *chip)
 	cafe_writel(cafe, lower_32_bits(cafe->dmaaddr), NAND_DMA_ADDR0);
 	cafe_writel(cafe, upper_32_bits(cafe->dmaaddr), NAND_DMA_ADDR1);
 
-	cafe_dev_dbg(&cafe->pdev->dev, "Set DMA address to %x (virt %p)\n",
-		     cafe_readl(cafe, NAND_DMA_ADDR0), cafe->dmabuf);
+	dev_dbg(&cafe->pdev->dev, "Set DMA address to %x (virt %p)\n",
+		cafe_readl(cafe, NAND_DMA_ADDR0), cafe->dmabuf);
 
 	/* Restore the DMA flag */
 	cafe->usedma = usedma;
@@ -899,16 +890,16 @@ static int cafe_nand_probe(struct pci_dev *pdev,
 	}
 
 	if (numtimings == 3) {
-		cafe_dev_dbg(&cafe->pdev->dev, "Using provided timings (%08x %08x %08x)\n",
-			     timing[0], timing[1], timing[2]);
+		dev_dbg(&cafe->pdev->dev, "Using provided timings (%08x %08x %08x)\n",
+			timing[0], timing[1], timing[2]);
 	} else {
 		timing[0] = cafe_readl(cafe, NAND_TIMING1);
 		timing[1] = cafe_readl(cafe, NAND_TIMING2);
 		timing[2] = cafe_readl(cafe, NAND_TIMING3);
 
 		if (timing[0] | timing[1] | timing[2]) {
-			cafe_dev_dbg(&cafe->pdev->dev, "Timing registers already set (%08x %08x %08x)\n",
-				     timing[0], timing[1], timing[2]);
+			dev_dbg(&cafe->pdev->dev, "Timing registers already set (%08x %08x %08x)\n",
+				timing[0], timing[1], timing[2]);
 		} else {
 			dev_warn(&cafe->pdev->dev, "Timing registers unset; using most conservative defaults\n");
 			timing[0] = timing[1] = timing[2] = 0xffffffff;
-- 
2.25.3


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

^ permalink raw reply	[flat|nested] 46+ messages in thread

* [PATCH v2 09/19] mtd: rawnand: cafe: Use devm_kzalloc and devm_request_irq()
  2020-05-05 10:13 [PATCH v2 00/19] mtd: rawnand: cafe: Convert to exec_op() (and more) Boris Brezillon
                   ` (7 preceding siblings ...)
  2020-05-05 10:13 ` [PATCH v2 08/19] mtd: rawnand: cafe: Get rid of the debug module param Boris Brezillon
@ 2020-05-05 10:13 ` Boris Brezillon
  2020-05-05 10:13 ` [PATCH v2 10/19] mtd: rawnand: cafe: Get rid of a useless label Boris Brezillon
                   ` (10 subsequent siblings)
  19 siblings, 0 replies; 46+ messages in thread
From: Boris Brezillon @ 2020-05-05 10:13 UTC (permalink / raw)
  To: Miquel Raynal, linux-mtd, Lubomir Rintel
  Cc: Richard Weinberger, Boris Brezillon, Vignesh Raghavendra, Tudor Ambarus

This simplifies the error/remove path.

Signed-off-by: Boris Brezillon <boris.brezillon@collabora.com>
Reviewed-by: Miquel Raynal <miquel.raynal@bootlin.com>
Tested-by: Lubomir Rintel <lkundrak@v3.sk>
---
Changes in v2:
* Add R-b/T-b
---
 drivers/mtd/nand/raw/cafe_nand.c | 14 ++++----------
 1 file changed, 4 insertions(+), 10 deletions(-)

diff --git a/drivers/mtd/nand/raw/cafe_nand.c b/drivers/mtd/nand/raw/cafe_nand.c
index fedf434a563f..93e8e124df45 100644
--- a/drivers/mtd/nand/raw/cafe_nand.c
+++ b/drivers/mtd/nand/raw/cafe_nand.c
@@ -846,7 +846,7 @@ static int cafe_nand_probe(struct pci_dev *pdev,
 
 	pci_set_master(pdev);
 
-	cafe = kzalloc(sizeof(*cafe), GFP_KERNEL);
+	cafe = devm_kzalloc(&pdev->dev, sizeof(*cafe), GFP_KERNEL);
 	if (!cafe)
 		return  -ENOMEM;
 
@@ -858,8 +858,7 @@ static int cafe_nand_probe(struct pci_dev *pdev,
 	cafe->mmio = pci_iomap(pdev, 0, 0);
 	if (!cafe->mmio) {
 		dev_warn(&pdev->dev, "failed to iomap\n");
-		err = -ENOMEM;
-		goto out_free_mtd;
+		return -ENOMEM;
 	}
 
 	cafe->rs = init_rs_non_canonical(12, &cafe_mul, 0, 1, 8);
@@ -908,8 +907,8 @@ static int cafe_nand_probe(struct pci_dev *pdev,
 
 	cafe_nand_init(cafe);
 
-	err = request_irq(pdev->irq, &cafe_nand_interrupt, IRQF_SHARED,
-			  "CAFE NAND", mtd);
+	err = devm_request_irq(&pdev->dev, pdev->irq, cafe_nand_interrupt,
+			       IRQF_SHARED, "CAFE NAND", mtd);
 	if (err) {
 		dev_warn(&pdev->dev, "Could not register IRQ %d\n", pdev->irq);
 		goto out_ior;
@@ -940,11 +939,8 @@ static int cafe_nand_probe(struct pci_dev *pdev,
 	cafe_writel(cafe,
 		    cafe_readl(cafe, GLOBAL_IRQ_MASK) & ~CAFE_GLOBAL_IRQ_NAND,
 		    GLOBAL_IRQ_MASK);
-	free_irq(pdev->irq, mtd);
  out_ior:
 	pci_iounmap(pdev, cafe->mmio);
- out_free_mtd:
-	kfree(cafe);
  out:
 	return err;
 }
@@ -959,12 +955,10 @@ static void cafe_nand_remove(struct pci_dev *pdev)
 	cafe_writel(cafe,
 		    cafe_readl(cafe, GLOBAL_IRQ_MASK) & ~CAFE_GLOBAL_IRQ_NAND,
 		    GLOBAL_IRQ_MASK);
-	free_irq(pdev->irq, mtd);
 	nand_release(chip);
 	free_rs(cafe->rs);
 	pci_iounmap(pdev, cafe->mmio);
 	dma_free_coherent(&cafe->pdev->dev, 2112, cafe->dmabuf, cafe->dmaaddr);
-	kfree(cafe);
 }
 
 static const struct pci_device_id cafe_nand_tbl[] = {
-- 
2.25.3


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

^ permalink raw reply	[flat|nested] 46+ messages in thread

* [PATCH v2 10/19] mtd: rawnand: cafe: Get rid of a useless label
  2020-05-05 10:13 [PATCH v2 00/19] mtd: rawnand: cafe: Convert to exec_op() (and more) Boris Brezillon
                   ` (8 preceding siblings ...)
  2020-05-05 10:13 ` [PATCH v2 09/19] mtd: rawnand: cafe: Use devm_kzalloc and devm_request_irq() Boris Brezillon
@ 2020-05-05 10:13 ` Boris Brezillon
  2020-05-05 10:13 ` [PATCH v2 11/19] mtd: rawnand: cafe: Explicitly inherit from nand_controller Boris Brezillon
                   ` (9 subsequent siblings)
  19 siblings, 0 replies; 46+ messages in thread
From: Boris Brezillon @ 2020-05-05 10:13 UTC (permalink / raw)
  To: Miquel Raynal, linux-mtd, Lubomir Rintel
  Cc: Richard Weinberger, Boris Brezillon, Vignesh Raghavendra, Tudor Ambarus

We can return 0 directly instead of branching to the out label.

Signed-off-by: Boris Brezillon <boris.brezillon@collabora.com>
Reviewed-by: Miquel Raynal <miquel.raynal@bootlin.com>
Tested-by: Lubomir Rintel <lkundrak@v3.sk>
---
Changes in v2:
* Add R-b/T-b
---
 drivers/mtd/nand/raw/cafe_nand.c | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

diff --git a/drivers/mtd/nand/raw/cafe_nand.c b/drivers/mtd/nand/raw/cafe_nand.c
index 93e8e124df45..84b8d50c7f08 100644
--- a/drivers/mtd/nand/raw/cafe_nand.c
+++ b/drivers/mtd/nand/raw/cafe_nand.c
@@ -930,7 +930,7 @@ static int cafe_nand_probe(struct pci_dev *pdev,
 	if (err)
 		goto out_cleanup_nand;
 
-	goto out;
+	return 0;
 
  out_cleanup_nand:
 	nand_cleanup(&cafe->nand);
@@ -941,7 +941,6 @@ static int cafe_nand_probe(struct pci_dev *pdev,
 		    GLOBAL_IRQ_MASK);
  out_ior:
 	pci_iounmap(pdev, cafe->mmio);
- out:
 	return err;
 }
 
-- 
2.25.3


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

^ permalink raw reply	[flat|nested] 46+ messages in thread

* [PATCH v2 11/19] mtd: rawnand: cafe: Explicitly inherit from nand_controller
  2020-05-05 10:13 [PATCH v2 00/19] mtd: rawnand: cafe: Convert to exec_op() (and more) Boris Brezillon
                   ` (9 preceding siblings ...)
  2020-05-05 10:13 ` [PATCH v2 10/19] mtd: rawnand: cafe: Get rid of a useless label Boris Brezillon
@ 2020-05-05 10:13 ` Boris Brezillon
  2020-05-05 10:13 ` [PATCH v2 12/19] mtd: rawnand: cafe: Don't leave ECC enabled in the write path Boris Brezillon
                   ` (8 subsequent siblings)
  19 siblings, 0 replies; 46+ messages in thread
From: Boris Brezillon @ 2020-05-05 10:13 UTC (permalink / raw)
  To: Miquel Raynal, linux-mtd, Lubomir Rintel
  Cc: Richard Weinberger, Boris Brezillon, Vignesh Raghavendra, Tudor Ambarus

Explicitly inherit from nand_controller instead of using the dummy
controller object.

Signed-off-by: Boris Brezillon <boris.brezillon@collabora.com>
Reviewed-by: Miquel Raynal <miquel.raynal@bootlin.com>
Tested-by: Lubomir Rintel <lkundrak@v3.sk>
---
Changes in v2:
* Add R-b/T-b
---
 drivers/mtd/nand/raw/cafe_nand.c | 5 ++++-
 1 file changed, 4 insertions(+), 1 deletion(-)

diff --git a/drivers/mtd/nand/raw/cafe_nand.c b/drivers/mtd/nand/raw/cafe_nand.c
index 84b8d50c7f08..e41ea95b3088 100644
--- a/drivers/mtd/nand/raw/cafe_nand.c
+++ b/drivers/mtd/nand/raw/cafe_nand.c
@@ -146,6 +146,7 @@
 #define CAFE_FIELD_GET(reg, field, val)		FIELD_GET(CAFE_##reg##_##field, val)
 
 struct cafe_priv {
+	struct nand_controller base;
 	struct nand_chip nand;
 	struct pci_dev *pdev;
 	void __iomem *mmio;
@@ -918,7 +919,9 @@ static int cafe_nand_probe(struct pci_dev *pdev,
 	cafe->usedma = 0;
 
 	/* Scan to find existence of the device */
-	cafe->nand.legacy.dummy_controller.ops = &cafe_nand_controller_ops;
+	nand_controller_init(&cafe->base);
+	cafe->base.ops = &cafe_nand_controller_ops;
+	cafe->nand.controller = &cafe->base;
 	err = nand_scan(&cafe->nand, 2);
 	if (err)
 		goto out_irq;
-- 
2.25.3


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

^ permalink raw reply	[flat|nested] 46+ messages in thread

* [PATCH v2 12/19] mtd: rawnand: cafe: Don't leave ECC enabled in the write path
  2020-05-05 10:13 [PATCH v2 00/19] mtd: rawnand: cafe: Convert to exec_op() (and more) Boris Brezillon
                   ` (10 preceding siblings ...)
  2020-05-05 10:13 ` [PATCH v2 11/19] mtd: rawnand: cafe: Explicitly inherit from nand_controller Boris Brezillon
@ 2020-05-05 10:13 ` Boris Brezillon
  2020-05-05 10:13 ` [PATCH v2 13/19] mtd: rawnand: cafe: Don't split things when reading/writing a page Boris Brezillon
                   ` (7 subsequent siblings)
  19 siblings, 0 replies; 46+ messages in thread
From: Boris Brezillon @ 2020-05-05 10:13 UTC (permalink / raw)
  To: Miquel Raynal, linux-mtd, Lubomir Rintel
  Cc: Richard Weinberger, Boris Brezillon, Vignesh Raghavendra, Tudor Ambarus

cafe_nand_write_pagel() sets the ECC auto-generation flag but
never clears it, thus forcing cafe_nand_cmdfunc() to clear it
in certain circumstances. Let's just clear this flag in
where it's been set instead.

Signed-off-by: Boris Brezillon <boris.brezillon@collabora.com>
Reviewed-by: Miquel Raynal <miquel.raynal@bootlin.com>
Tested-by: Lubomir Rintel <lkundrak@v3.sk>
---
Changes in v2:
* Add R-b/T-b
* Fix commit message
* Add blank line before return statement
---
 drivers/mtd/nand/raw/cafe_nand.c | 12 ++++++++++--
 1 file changed, 10 insertions(+), 2 deletions(-)

diff --git a/drivers/mtd/nand/raw/cafe_nand.c b/drivers/mtd/nand/raw/cafe_nand.c
index e41ea95b3088..f7e537836d55 100644
--- a/drivers/mtd/nand/raw/cafe_nand.c
+++ b/drivers/mtd/nand/raw/cafe_nand.c
@@ -261,7 +261,6 @@ static void cafe_nand_cmdfunc(struct nand_chip *chip, unsigned command,
 			    CAFE_FIELD_PREP(NAND_CTRL2, CMD2, command),
 			    NAND_CTRL2);
 		ctl1 = cafe->ctl1;
-		cafe->ctl2 &= ~CAFE_NAND_CTRL2_AUTO_WRITE_ECC;
 		dev_dbg(&cafe->pdev->dev, "Continue command, ctl1 %08x, #data %d\n",
 			cafe->ctl1, cafe->nr_data);
 		goto do_command;
@@ -641,6 +640,7 @@ static int cafe_nand_write_page(struct nand_chip *chip,
 {
 	struct mtd_info *mtd = nand_to_mtd(chip);
 	struct cafe_priv *cafe = nand_get_controller_data(chip);
+	int ret;
 
 	nand_prog_page_begin_op(chip, page, 0, buf, mtd->writesize);
 	chip->legacy.write_buf(chip, chip->oob_poi, mtd->oobsize);
@@ -648,7 +648,15 @@ static int cafe_nand_write_page(struct nand_chip *chip,
 	/* Set up ECC autogeneration */
 	cafe->ctl2 |= CAFE_NAND_CTRL2_AUTO_WRITE_ECC;
 
-	return nand_prog_page_end_op(chip);
+	ret = nand_prog_page_end_op(chip);
+
+	/*
+	 * And clear it before returning so that following write operations
+	 * that do not involve ECC don't generate ECC bytes.
+	 */
+	cafe->ctl2 &= ~CAFE_NAND_CTRL2_AUTO_WRITE_ECC;
+
+	return ret;
 }
 
 /* F_2[X]/(X**6+X+1)  */
-- 
2.25.3


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

^ permalink raw reply	[flat|nested] 46+ messages in thread

* [PATCH v2 13/19] mtd: rawnand: cafe: Don't split things when reading/writing a page
  2020-05-05 10:13 [PATCH v2 00/19] mtd: rawnand: cafe: Convert to exec_op() (and more) Boris Brezillon
                   ` (11 preceding siblings ...)
  2020-05-05 10:13 ` [PATCH v2 12/19] mtd: rawnand: cafe: Don't leave ECC enabled in the write path Boris Brezillon
@ 2020-05-05 10:13 ` Boris Brezillon
  2020-05-10 21:49   ` Miquel Raynal
  2020-05-05 10:13 ` [PATCH v2 14/19] mtd: rawnand: cafe: Add exec_op() support Boris Brezillon
                   ` (6 subsequent siblings)
  19 siblings, 1 reply; 46+ messages in thread
From: Boris Brezillon @ 2020-05-05 10:13 UTC (permalink / raw)
  To: Miquel Raynal, linux-mtd, Lubomir Rintel
  Cc: Richard Weinberger, Boris Brezillon, Vignesh Raghavendra, Tudor Ambarus

Calling nand_read_page_op(pagesize)/nand_prog_page_begin_op(pagesize)
and expecting to get a pagesize+oobsize read from/written to the
read/write buffer is fragile and only works because of hacks done
in cmdfunc(). Let's read/write the page in one go, using the page
cache buffer as a bounce buffer instead of relying on guesses done
in cafe_nand_cmdfunc().

Signed-off-by: Boris Brezillon <boris.brezillon@collabora.com>
Tested-by: Lubomir Rintel <lkundrak@v3.sk>
---
Changes in v2:
* Add T-b
* None
---
 drivers/mtd/nand/raw/cafe_nand.c | 16 +++++++++++-----
 1 file changed, 11 insertions(+), 5 deletions(-)

diff --git a/drivers/mtd/nand/raw/cafe_nand.c b/drivers/mtd/nand/raw/cafe_nand.c
index f7e537836d55..36685bee9d83 100644
--- a/drivers/mtd/nand/raw/cafe_nand.c
+++ b/drivers/mtd/nand/raw/cafe_nand.c
@@ -470,6 +470,7 @@ static int cafe_nand_read_page(struct nand_chip *chip, uint8_t *buf,
 {
 	struct mtd_info *mtd = nand_to_mtd(chip);
 	struct cafe_priv *cafe = nand_get_controller_data(chip);
+	void *pagebuf = nand_get_data_buf(chip);
 	unsigned int max_bitflips = 0;
 	u32 ecc_result, status;
 
@@ -477,8 +478,11 @@ static int cafe_nand_read_page(struct nand_chip *chip, uint8_t *buf,
 		cafe_readl(cafe, NAND_ECC_RESULT),
 		cafe_readl(cafe, NAND_ECC_SYN_REG(0)));
 
-	nand_read_page_op(chip, page, 0, buf, mtd->writesize);
-	chip->legacy.read_buf(chip, chip->oob_poi, mtd->oobsize);
+	nand_read_page_op(chip, page, 0, pagebuf,
+			  mtd->writesize + mtd->oobsize);
+
+	if (buf != pagebuf)
+		memcpy(buf, pagebuf, mtd->writesize);
 
 	ecc_result = cafe_readl(cafe, NAND_ECC_RESULT);
 	status = CAFE_FIELD_GET(NAND_ECC_RESULT, STATUS, ecc_result);
@@ -640,15 +644,17 @@ static int cafe_nand_write_page(struct nand_chip *chip,
 {
 	struct mtd_info *mtd = nand_to_mtd(chip);
 	struct cafe_priv *cafe = nand_get_controller_data(chip);
+	void *pagebuf = nand_get_data_buf(chip);
 	int ret;
 
-	nand_prog_page_begin_op(chip, page, 0, buf, mtd->writesize);
-	chip->legacy.write_buf(chip, chip->oob_poi, mtd->oobsize);
+	if (pagebuf != buf)
+		memcpy(pagebuf, buf, mtd->writesize);
 
 	/* Set up ECC autogeneration */
 	cafe->ctl2 |= CAFE_NAND_CTRL2_AUTO_WRITE_ECC;
 
-	ret = nand_prog_page_end_op(chip);
+	ret = nand_prog_page_op(chip, page, 0, pagebuf,
+				mtd->writesize + mtd->oobsize);
 
 	/*
 	 * And clear it before returning so that following write operations
-- 
2.25.3


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

^ permalink raw reply	[flat|nested] 46+ messages in thread

* [PATCH v2 14/19] mtd: rawnand: cafe: Add exec_op() support
  2020-05-05 10:13 [PATCH v2 00/19] mtd: rawnand: cafe: Convert to exec_op() (and more) Boris Brezillon
                   ` (12 preceding siblings ...)
  2020-05-05 10:13 ` [PATCH v2 13/19] mtd: rawnand: cafe: Don't split things when reading/writing a page Boris Brezillon
@ 2020-05-05 10:13 ` Boris Brezillon
  2020-05-05 10:13 ` [PATCH v2 15/19] mtd: rawnand: cafe: Get rid of the legacy interface implementation Boris Brezillon
                   ` (5 subsequent siblings)
  19 siblings, 0 replies; 46+ messages in thread
From: Boris Brezillon @ 2020-05-05 10:13 UTC (permalink / raw)
  To: Miquel Raynal, linux-mtd, Lubomir Rintel
  Cc: Richard Weinberger, Boris Brezillon, Vignesh Raghavendra, Tudor Ambarus

Implementing exec_op() will help us get rid of the legacy interface and
should make drivers much cleaner too.

Signed-off-by: Boris Brezillon <boris.brezillon@collabora.com>
Reviewed-by: Lubomir Rintel <lkundrak@v3.sk>
Tested-by: Lubomir Rintel <lkundrak@v3.sk>
---
Changes in v2:
* Add R-b/T-b
* Drop WARN_ON()s
* Use nand_subop_get_xxx() where appropriate
* Write ADDR2 unconditionally
* Do not wait on CMD_DONE when the last instruction is a DATA
  instruction and DMA is used
* s/CAFE_NAND_DMA_CTRL_DATA_IN/CAFE_NAND_CTRL1_HAS_DATA_IN/
---
 drivers/mtd/nand/raw/cafe_nand.c | 140 ++++++++++++++++++++++++++++++-
 1 file changed, 139 insertions(+), 1 deletion(-)

diff --git a/drivers/mtd/nand/raw/cafe_nand.c b/drivers/mtd/nand/raw/cafe_nand.c
index 36685bee9d83..2f35faf13805 100644
--- a/drivers/mtd/nand/raw/cafe_nand.c
+++ b/drivers/mtd/nand/raw/cafe_nand.c
@@ -21,7 +21,7 @@
 #include <linux/dma-mapping.h>
 #include <linux/slab.h>
 #include <linux/module.h>
-#include <linux/io.h>
+#include <linux/iopoll.h>
 
 #define CAFE_NAND_CTRL1				0x00
 #define CAFE_NAND_CTRL1_HAS_CMD			BIT(31)
@@ -773,9 +773,147 @@ static void cafe_nand_detach_chip(struct nand_chip *chip)
 	dma_free_coherent(&cafe->pdev->dev, 2112, cafe->dmabuf, cafe->dmaaddr);
 }
 
+static int cafe_nand_exec_subop(struct nand_chip *chip,
+				const struct nand_subop *subop)
+{
+	struct cafe_priv *cafe = nand_get_controller_data(chip);
+	u32 ctrl1 = 0, ctrl2 = cafe->ctl2, addr1 = 0, addr2 = 0;
+	u32 status, wait = CAFE_NAND_IRQ_CMD_DONE;
+	int ret, data_instr = -1;
+	bool waitrdy = false;
+	unsigned int i, j;
+
+	cafe->datalen = 0;
+	ctrl1 |= CAFE_FIELD_PREP(NAND_CTRL1, CE, subop->cs);
+
+	for (i = 0; i < subop->ninstrs; i++) {
+		const struct nand_op_instr *instr = &subop->instrs[i];
+
+		switch (instr->type) {
+		case NAND_OP_CMD_INSTR:
+			if (!(ctrl1 & CAFE_NAND_CTRL1_HAS_CMD))
+				ctrl1 |= CAFE_NAND_CTRL1_HAS_CMD |
+					 CAFE_FIELD_PREP(NAND_CTRL1, CMD,
+							 instr->ctx.cmd.opcode);
+			else
+				ctrl2 |= CAFE_NAND_CTRL2_HAS_CMD2 |
+					 CAFE_FIELD_PREP(NAND_CTRL2, CMD2,
+							 instr->ctx.cmd.opcode);
+			break;
+
+		case NAND_OP_ADDR_INSTR:
+			for (j = nand_subop_get_addr_start_off(subop, i);
+			     j < nand_subop_get_num_addr_cyc(subop, i); j++) {
+				u32 addr = instr->ctx.addr.addrs[j];
+
+				if (j < 2)
+					addr1 |= addr << (8 * j);
+				else
+					addr2 |= addr << (8 * (j - 2));
+			}
+
+			ctrl1 |= CAFE_NAND_CTRL1_HAS_ADDR |
+				 CAFE_FIELD_PREP(NAND_CTRL1, NUM_ADDR_CYC,
+						 instr->ctx.addr.naddrs - 1);
+			cafe_writel(cafe, addr1, NAND_ADDR1);
+			cafe_writel(cafe, addr2, NAND_ADDR2);
+			break;
+
+		case NAND_OP_DATA_IN_INSTR:
+			data_instr = i;
+			ctrl1 |= CAFE_NAND_CTRL1_HAS_DATA_IN;
+			break;
+
+		case NAND_OP_DATA_OUT_INSTR:
+			data_instr = i;
+			ctrl1 |= CAFE_NAND_CTRL1_HAS_DATA_OUT;
+			cafe_write_buf(chip,
+				       instr->ctx.data.buf.out +
+				       nand_subop_get_data_start_off(subop, i),
+				       nand_subop_get_data_len(subop, i));
+			break;
+
+		case NAND_OP_WAITRDY_INSTR:
+			wait |= CAFE_NAND_IRQ_FLASH_RDY;
+			waitrdy = true;
+			break;
+		}
+	}
+
+	if (data_instr >= 0)
+		cafe_writel(cafe, nand_subop_get_data_len(subop, data_instr),
+			    NAND_DATA_LEN);
+
+	if (cafe->usedma && data_instr >= 0) {
+		u32 dmactrl = CAFE_NAND_DMA_CTRL_ENABLE |
+			      CAFE_NAND_DMA_CTRL_RESERVED;
+
+		dmactrl |= CAFE_FIELD_PREP(NAND_DMA_CTRL, DATA_LEN,
+					   nand_subop_get_data_len(subop,
+								   data_instr));
+		if (ctrl1 & CAFE_NAND_CTRL1_HAS_DATA_IN)
+			dmactrl |= CAFE_NAND_DMA_CTRL_DATA_IN;
+
+		cafe_writel(cafe, dmactrl, NAND_DMA_CTRL);
+
+		/*
+		 * If the last instruction is a data transfer and we're using
+		 * DMA, we should wait on DMA_DONE only, otherwise, keep
+		 * waiting on CMD_DONE.
+		 */
+		if (data_instr == subop->ninstrs - 1) {
+			wait &= ~CAFE_NAND_IRQ_CMD_DONE;
+			wait |= CAFE_NAND_IRQ_DMA_DONE;
+		}
+	}
+
+	/* Clear the pending interrupts before starting the operation. */
+	cafe_writel(cafe, wait, NAND_IRQ);
+
+	cafe_writel(cafe, ctrl2, NAND_CTRL2);
+	cafe_writel(cafe, ctrl1, NAND_CTRL1);
+
+	ret = readl_poll_timeout(cafe->mmio + CAFE_NAND_IRQ, status,
+				 (status & wait) == wait, 1, USEC_PER_SEC);
+	if (ret)
+		return ret;
+
+	if (ctrl1 & CAFE_NAND_CTRL1_HAS_DATA_IN)
+		cafe_read_buf(chip,
+			      subop->instrs[data_instr].ctx.data.buf.in +
+			      nand_subop_get_data_start_off(subop, data_instr),
+			      nand_subop_get_data_len(subop, data_instr));
+
+	return 0;
+}
+
+static const struct nand_op_parser cafe_nand_op_parser = NAND_OP_PARSER(
+	NAND_OP_PARSER_PATTERN(cafe_nand_exec_subop,
+			       NAND_OP_PARSER_PAT_CMD_ELEM(true),
+			       NAND_OP_PARSER_PAT_ADDR_ELEM(true, 5),
+			       NAND_OP_PARSER_PAT_CMD_ELEM(true),
+			       NAND_OP_PARSER_PAT_WAITRDY_ELEM(true),
+			       NAND_OP_PARSER_PAT_DATA_IN_ELEM(true, 2112)),
+	NAND_OP_PARSER_PATTERN(cafe_nand_exec_subop,
+			       NAND_OP_PARSER_PAT_CMD_ELEM(true),
+			       NAND_OP_PARSER_PAT_ADDR_ELEM(true, 5),
+			       NAND_OP_PARSER_PAT_CMD_ELEM(true),
+			       NAND_OP_PARSER_PAT_DATA_IN_ELEM(true, 2112),
+			       NAND_OP_PARSER_PAT_WAITRDY_ELEM(true))
+);
+
+static int cafe_nand_exec_op(struct nand_chip *chip,
+			     const struct nand_operation *op,
+			     bool check_only)
+{
+	return nand_op_parser_exec_op(chip, &cafe_nand_op_parser, op,
+				      check_only);
+}
+
 static const struct nand_controller_ops cafe_nand_controller_ops = {
 	.attach_chip = cafe_nand_attach_chip,
 	.detach_chip = cafe_nand_detach_chip,
+	.exec_op = cafe_nand_exec_op,
 };
 
 static void cafe_nand_init(struct cafe_priv *cafe)
-- 
2.25.3


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

^ permalink raw reply	[flat|nested] 46+ messages in thread

* [PATCH v2 15/19] mtd: rawnand: cafe: Get rid of the legacy interface implementation
  2020-05-05 10:13 [PATCH v2 00/19] mtd: rawnand: cafe: Convert to exec_op() (and more) Boris Brezillon
                   ` (13 preceding siblings ...)
  2020-05-05 10:13 ` [PATCH v2 14/19] mtd: rawnand: cafe: Add exec_op() support Boris Brezillon
@ 2020-05-05 10:13 ` Boris Brezillon
  2020-05-05 10:13 ` [PATCH v2 16/19] mtd: rawnand: cafe: Adjust the cafe_{read, write}_buf() prototypes Boris Brezillon
                   ` (4 subsequent siblings)
  19 siblings, 0 replies; 46+ messages in thread
From: Boris Brezillon @ 2020-05-05 10:13 UTC (permalink / raw)
  To: Miquel Raynal, linux-mtd, Lubomir Rintel
  Cc: Richard Weinberger, Boris Brezillon, Vignesh Raghavendra, Tudor Ambarus

Now that exec_op() is implemented, we can safely get rid of all
legacy hooks implementations.

Signed-off-by: Boris Brezillon <boris.brezillon@collabora.com>
Reviewed-by: Miquel Raynal <miquel.raynal@bootlin.com>
Tested-by: Lubomir Rintel <lkundrak@v3.sk>
---
Changes in v2:
* Add R-b/T-b
---
 drivers/mtd/nand/raw/cafe_nand.c | 250 +------------------------------
 1 file changed, 6 insertions(+), 244 deletions(-)

diff --git a/drivers/mtd/nand/raw/cafe_nand.c b/drivers/mtd/nand/raw/cafe_nand.c
index 2f35faf13805..bcdd58e93666 100644
--- a/drivers/mtd/nand/raw/cafe_nand.c
+++ b/drivers/mtd/nand/raw/cafe_nand.c
@@ -151,12 +151,7 @@ struct cafe_priv {
 	struct pci_dev *pdev;
 	void __iomem *mmio;
 	struct rs_control *rs;
-	uint32_t ctl1;
 	uint32_t ctl2;
-	int datalen;
-	int nr_data;
-	int data_pos;
-	int page_addr;
 	bool usedma;
 	dma_addr_t dmaaddr;
 	unsigned char *dmabuf;
@@ -184,36 +179,16 @@ static const char *part_probes[] = { "cmdlinepart", "RedBoot", NULL };
 #define cafe_readl(cafe, addr)			readl((cafe)->mmio + CAFE_##addr)
 #define cafe_writel(cafe, datum, addr)		writel(datum, (cafe)->mmio + CAFE_##addr)
 
-static int cafe_device_ready(struct nand_chip *chip)
-{
-	struct cafe_priv *cafe = nand_get_controller_data(chip);
-	int result = !!(cafe_readl(cafe, NAND_STATUS) &
-			CAFE_NAND_STATUS_FLASH_BUSY);
-	uint32_t irqs = cafe_readl(cafe, NAND_IRQ);
-
-	cafe_writel(cafe, irqs, NAND_IRQ);
-
-	dev_dbg(&cafe->pdev->dev, "NAND device is%s ready, IRQ %x (%x) (%x,%x)\n",
-		result?"":" not", irqs, cafe_readl(cafe, NAND_IRQ),
-		cafe_readl(cafe, GLOBAL_IRQ), cafe_readl(cafe, GLOBAL_IRQ_MASK));
-
-	return result;
-}
-
-
 static void cafe_write_buf(struct nand_chip *chip, const uint8_t *buf, int len)
 {
 	struct cafe_priv *cafe = nand_get_controller_data(chip);
 
 	if (cafe->usedma)
-		memcpy(cafe->dmabuf + cafe->datalen, buf, len);
+		memcpy(cafe->dmabuf, buf, len);
 	else
-		memcpy_toio(cafe->mmio + CAFE_NAND_WRITE_DATA + cafe->datalen, buf, len);
+		memcpy_toio(cafe->mmio + CAFE_NAND_WRITE_DATA, buf, len);
 
-	cafe->datalen += len;
-
-	dev_dbg(&cafe->pdev->dev, "Copy 0x%x bytes to write buffer. datalen 0x%x\n",
-		len, cafe->datalen);
+	dev_dbg(&cafe->pdev->dev, "Copy 0x%x bytes to write buffer.\n",	len);
 }
 
 static void cafe_read_buf(struct nand_chip *chip, uint8_t *buf, int len)
@@ -221,212 +196,11 @@ static void cafe_read_buf(struct nand_chip *chip, uint8_t *buf, int len)
 	struct cafe_priv *cafe = nand_get_controller_data(chip);
 
 	if (cafe->usedma)
-		memcpy(buf, cafe->dmabuf + cafe->datalen, len);
+		memcpy(buf, cafe->dmabuf, len);
 	else
-		memcpy_fromio(buf, cafe->mmio + CAFE_NAND_READ_DATA + cafe->datalen, len);
+		memcpy_fromio(buf, cafe->mmio + CAFE_NAND_READ_DATA, len);
 
-	dev_dbg(&cafe->pdev->dev, "Copy 0x%x bytes from position 0x%x in read buffer.\n",
-		len, cafe->datalen);
-	cafe->datalen += len;
-}
-
-static uint8_t cafe_read_byte(struct nand_chip *chip)
-{
-	struct cafe_priv *cafe = nand_get_controller_data(chip);
-	uint8_t d;
-
-	cafe_read_buf(chip, &d, 1);
-	dev_dbg(&cafe->pdev->dev, "Read %02x\n", d);
-
-	return d;
-}
-
-static void cafe_nand_cmdfunc(struct nand_chip *chip, unsigned command,
-			      int column, int page_addr)
-{
-	struct mtd_info *mtd = nand_to_mtd(chip);
-	struct cafe_priv *cafe = nand_get_controller_data(chip);
-	int adrbytes = 0;
-	uint32_t ctl1;
-	uint32_t doneint = CAFE_NAND_IRQ_CMD_DONE;
-
-	dev_dbg(&cafe->pdev->dev, "cmdfunc %02x, 0x%x, 0x%x\n",
-		command, column, page_addr);
-
-	if (command == NAND_CMD_ERASE2 || command == NAND_CMD_PAGEPROG) {
-		/* Second half of a command we already calculated */
-		cafe_writel(cafe,
-			    cafe->ctl2 |
-			    CAFE_NAND_CTRL2_HAS_CMD2 |
-			    CAFE_FIELD_PREP(NAND_CTRL2, CMD2, command),
-			    NAND_CTRL2);
-		ctl1 = cafe->ctl1;
-		dev_dbg(&cafe->pdev->dev, "Continue command, ctl1 %08x, #data %d\n",
-			cafe->ctl1, cafe->nr_data);
-		goto do_command;
-	}
-	/* Reset ECC engine */
-	cafe_writel(cafe, 0, NAND_CTRL2);
-
-	/* Emulate NAND_CMD_READOOB on large-page chips */
-	if (mtd->writesize > 512 &&
-	    command == NAND_CMD_READOOB) {
-		column += mtd->writesize;
-		command = NAND_CMD_READ0;
-	}
-
-	/* FIXME: Do we need to send read command before sending data
-	   for small-page chips, to position the buffer correctly? */
-
-	if (column != -1) {
-		cafe_writel(cafe, column, NAND_ADDR1);
-		adrbytes = 2;
-		if (page_addr != -1)
-			goto write_adr2;
-	} else if (page_addr != -1) {
-		cafe_writel(cafe, page_addr & 0xffff, NAND_ADDR1);
-		page_addr >>= 16;
-	write_adr2:
-		cafe_writel(cafe, page_addr, NAND_ADDR2);
-		adrbytes += 2;
-		if (mtd->size > mtd->writesize << 16)
-			adrbytes++;
-	}
-
-	cafe->data_pos = cafe->datalen = 0;
-
-	/* Set command valid bit, mask in the chip select bit  */
-	ctl1 = CAFE_NAND_CTRL1_HAS_CMD |
-	       CAFE_FIELD_PREP(NAND_CTRL1, CMD, command) |
-	       (cafe->ctl1 & CAFE_NAND_CTRL1_CE);
-
-	/* Set RD or WR bits as appropriate */
-	if (command == NAND_CMD_READID || command == NAND_CMD_STATUS) {
-		ctl1 |= CAFE_NAND_CTRL1_HAS_DATA_IN;
-		/* Always 5 bytes, for now */
-		cafe->datalen = 4;
-		/* And one address cycle -- even for STATUS, since the controller doesn't work without */
-		adrbytes = 1;
-	} else if (command == NAND_CMD_READ0 || command == NAND_CMD_READ1 ||
-		   command == NAND_CMD_READOOB || command == NAND_CMD_RNDOUT) {
-		ctl1 |= CAFE_NAND_CTRL1_HAS_DATA_IN;
-		/* For now, assume just read to end of page */
-		cafe->datalen = mtd->writesize + mtd->oobsize - column;
-	} else if (command == NAND_CMD_SEQIN)
-		ctl1 |= CAFE_NAND_CTRL1_HAS_DATA_OUT;
-
-	/* Set number of address bytes */
-	if (adrbytes)
-		ctl1 |= CAFE_NAND_CTRL1_HAS_ADDR |
-			CAFE_FIELD_PREP(NAND_CTRL1, NUM_ADDR_CYC, adrbytes - 1);
-
-	if (command == NAND_CMD_SEQIN || command == NAND_CMD_ERASE1) {
-		/* Ignore the first command of a pair; the hardware
-		   deals with them both at once, later */
-		cafe->ctl1 = ctl1;
-		dev_dbg(&cafe->pdev->dev, "Setup for delayed command, ctl1 %08x, dlen %x\n",
-			cafe->ctl1, cafe->datalen);
-		return;
-	}
-	/* RNDOUT and READ0 commands need a following byte */
-	if (command == NAND_CMD_RNDOUT)
-		cafe_writel(cafe,
-			    cafe->ctl2 | CAFE_NAND_CTRL2_HAS_CMD2 |
-			    CAFE_FIELD_PREP(NAND_CTRL2, CMD2, NAND_CMD_RNDOUTSTART),
-			    NAND_CTRL2);
-	else if (command == NAND_CMD_READ0 && mtd->writesize > 512)
-		cafe_writel(cafe,
-			    cafe->ctl2 | CAFE_NAND_CTRL2_HAS_CMD2 |
-			    CAFE_FIELD_PREP(NAND_CTRL2, CMD2, NAND_CMD_READSTART),
-			    NAND_CTRL2);
-
- do_command:
-	dev_dbg(&cafe->pdev->dev, "dlen %x, ctl1 %x, ctl2 %x\n",
-		cafe->datalen, ctl1, cafe_readl(cafe, NAND_CTRL2));
-
-	/* NB: The datasheet lies -- we really should be subtracting 1 here */
-	cafe_writel(cafe, cafe->datalen, NAND_DATA_LEN);
-	cafe_writel(cafe, CAFE_NAND_IRQ_CMD_DONE | CAFE_NAND_IRQ_DMA_DONE,
-		    NAND_IRQ);
-	if (cafe->usedma &&
-	    (ctl1 & (CAFE_NAND_CTRL1_HAS_DATA_IN |
-		     CAFE_NAND_CTRL1_HAS_DATA_OUT))) {
-		uint32_t dmactl = CAFE_NAND_DMA_CTRL_ENABLE |
-				  CAFE_NAND_DMA_CTRL_RESERVED;
-
-		dmactl |= CAFE_FIELD_PREP(NAND_DMA_CTRL, DATA_LEN,
-					  cafe->datalen);
-		/* If WR or RD bits set, set up DMA */
-		if (ctl1 & CAFE_NAND_CTRL1_HAS_DATA_IN) {
-			/* It's a read */
-			dmactl |= CAFE_NAND_DMA_CTRL_DATA_IN;
-			/* ... so it's done when the DMA is done, not just
-			   the command. */
-			doneint = CAFE_NAND_IRQ_DMA_DONE;
-		}
-		cafe_writel(cafe, dmactl, NAND_DMA_CTRL);
-	}
-	cafe->datalen = 0;
-
-	if (unlikely(regdebug)) {
-		int i;
-		printk("About to write command %08x to register 0\n", ctl1);
-		for (i=4; i< 0x5c; i+=4)
-			printk("Register %x: %08x\n", i, readl(cafe->mmio + i));
-	}
-
-	cafe_writel(cafe, ctl1, NAND_CTRL1);
-	/* Apply this short delay always to ensure that we do wait tWB in
-	 * any case on any machine. */
-	ndelay(100);
-
-	if (1) {
-		int c;
-		uint32_t irqs;
-
-		for (c = 500000; c != 0; c--) {
-			irqs = cafe_readl(cafe, NAND_IRQ);
-			if (irqs & doneint)
-				break;
-			udelay(1);
-			if (!(c % 100000))
-				dev_dbg(&cafe->pdev->dev, "Wait for ready, IRQ %x\n", irqs);
-			cpu_relax();
-		}
-		cafe_writel(cafe, doneint, NAND_IRQ);
-		dev_dbg(&cafe->pdev->dev, "Command %x completed after %d usec, irqs %x (%x)\n",
-			command, 500000-c, irqs, cafe_readl(cafe, NAND_IRQ));
-	}
-
-	WARN_ON(cafe->ctl2 & CAFE_NAND_CTRL2_AUTO_WRITE_ECC);
-
-	switch (command) {
-
-	case NAND_CMD_CACHEDPROG:
-	case NAND_CMD_PAGEPROG:
-	case NAND_CMD_ERASE1:
-	case NAND_CMD_ERASE2:
-	case NAND_CMD_SEQIN:
-	case NAND_CMD_RNDIN:
-	case NAND_CMD_STATUS:
-	case NAND_CMD_RNDOUT:
-		cafe_writel(cafe, cafe->ctl2, NAND_CTRL2);
-		return;
-	}
-	nand_wait_ready(chip);
-	cafe_writel(cafe, cafe->ctl2, NAND_CTRL2);
-}
-
-static void cafe_select_chip(struct nand_chip *chip, int chipnr)
-{
-	struct cafe_priv *cafe = nand_get_controller_data(chip);
-
-	dev_dbg(&cafe->pdev->dev, "select_chip %d\n", chipnr);
-
-	/* Mask the appropriate bit into the stored value of ctl1
-	   which will be used by cafe_nand_cmdfunc() */
-	cafe->ctl1 &= ~CAFE_NAND_CTRL1_CE;
-	cafe->ctl1 |= CAFE_FIELD_PREP(NAND_CTRL1, CE, chipnr);
+	dev_dbg(&cafe->pdev->dev, "Copy 0x%x bytes from read buffer.\n", len);
 }
 
 static irqreturn_t cafe_nand_interrupt(int irq, void *id)
@@ -783,7 +557,6 @@ static int cafe_nand_exec_subop(struct nand_chip *chip,
 	bool waitrdy = false;
 	unsigned int i, j;
 
-	cafe->datalen = 0;
 	ctrl1 |= CAFE_FIELD_PREP(NAND_CTRL1, CE, subop->cs);
 
 	for (i = 0; i < subop->ninstrs; i++) {
@@ -1020,17 +793,6 @@ static int cafe_nand_probe(struct pci_dev *pdev,
 		goto out_ior;
 	}
 
-	cafe->nand.legacy.cmdfunc = cafe_nand_cmdfunc;
-	cafe->nand.legacy.dev_ready = cafe_device_ready;
-	cafe->nand.legacy.read_byte = cafe_read_byte;
-	cafe->nand.legacy.read_buf = cafe_read_buf;
-	cafe->nand.legacy.write_buf = cafe_write_buf;
-	cafe->nand.legacy.select_chip = cafe_select_chip;
-	cafe->nand.legacy.set_features = nand_get_set_features_notsupp;
-	cafe->nand.legacy.get_features = nand_get_set_features_notsupp;
-
-	cafe->nand.legacy.chip_delay = 0;
-
 	/* Enable the following for a flash based bad block table */
 	cafe->nand.bbt_options = NAND_BBT_USE_FLASH;
 
-- 
2.25.3


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

^ permalink raw reply	[flat|nested] 46+ messages in thread

* [PATCH v2 16/19] mtd: rawnand: cafe: Adjust the cafe_{read, write}_buf() prototypes
  2020-05-05 10:13 [PATCH v2 00/19] mtd: rawnand: cafe: Convert to exec_op() (and more) Boris Brezillon
                   ` (14 preceding siblings ...)
  2020-05-05 10:13 ` [PATCH v2 15/19] mtd: rawnand: cafe: Get rid of the legacy interface implementation Boris Brezillon
@ 2020-05-05 10:13 ` Boris Brezillon
  2020-05-05 10:13 ` [PATCH v2 17/19] mtd: rawnand: cafe: s/uint{8,16,32}_t/u{8,16,32}/ Boris Brezillon
                   ` (3 subsequent siblings)
  19 siblings, 0 replies; 46+ messages in thread
From: Boris Brezillon @ 2020-05-05 10:13 UTC (permalink / raw)
  To: Miquel Raynal, linux-mtd, Lubomir Rintel
  Cc: Richard Weinberger, Boris Brezillon, Vignesh Raghavendra, Tudor Ambarus

Replace the uint8_t pointer by a void pointer and make the length
unsigned so it matches what's passed through the NAND instructions.

Signed-off-by: Boris Brezillon <boris.brezillon@collabora.com>
Reviewed-by: Miquel Raynal <miquel.raynal@bootlin.com>
Tested-by: Lubomir Rintel <lkundrak@v3.sk>
---
Changes in v2:
* s/nand/NAND/
* Add R-b/T-b
---
 drivers/mtd/nand/raw/cafe_nand.c | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)

diff --git a/drivers/mtd/nand/raw/cafe_nand.c b/drivers/mtd/nand/raw/cafe_nand.c
index bcdd58e93666..74c64af700d5 100644
--- a/drivers/mtd/nand/raw/cafe_nand.c
+++ b/drivers/mtd/nand/raw/cafe_nand.c
@@ -179,7 +179,8 @@ static const char *part_probes[] = { "cmdlinepart", "RedBoot", NULL };
 #define cafe_readl(cafe, addr)			readl((cafe)->mmio + CAFE_##addr)
 #define cafe_writel(cafe, datum, addr)		writel(datum, (cafe)->mmio + CAFE_##addr)
 
-static void cafe_write_buf(struct nand_chip *chip, const uint8_t *buf, int len)
+static void cafe_write_buf(struct nand_chip *chip, const void *buf,
+			   unsigned int len)
 {
 	struct cafe_priv *cafe = nand_get_controller_data(chip);
 
@@ -191,7 +192,7 @@ static void cafe_write_buf(struct nand_chip *chip, const uint8_t *buf, int len)
 	dev_dbg(&cafe->pdev->dev, "Copy 0x%x bytes to write buffer.\n",	len);
 }
 
-static void cafe_read_buf(struct nand_chip *chip, uint8_t *buf, int len)
+static void cafe_read_buf(struct nand_chip *chip, void *buf, unsigned int len)
 {
 	struct cafe_priv *cafe = nand_get_controller_data(chip);
 
-- 
2.25.3


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

^ permalink raw reply	[flat|nested] 46+ messages in thread

* [PATCH v2 17/19] mtd: rawnand: cafe: s/uint{8,16,32}_t/u{8,16,32}/
  2020-05-05 10:13 [PATCH v2 00/19] mtd: rawnand: cafe: Convert to exec_op() (and more) Boris Brezillon
                   ` (15 preceding siblings ...)
  2020-05-05 10:13 ` [PATCH v2 16/19] mtd: rawnand: cafe: Adjust the cafe_{read, write}_buf() prototypes Boris Brezillon
@ 2020-05-05 10:13 ` Boris Brezillon
  2020-05-05 10:13 ` [PATCH v2 18/19] mtd: rawnand: cafe: Drop the cafe_{readl, writel}() wrappers Boris Brezillon
                   ` (2 subsequent siblings)
  19 siblings, 0 replies; 46+ messages in thread
From: Boris Brezillon @ 2020-05-05 10:13 UTC (permalink / raw)
  To: Miquel Raynal, linux-mtd, Lubomir Rintel
  Cc: Richard Weinberger, Boris Brezillon, Vignesh Raghavendra, Tudor Ambarus

Replace uint{8,16,32}_t by u{8,16,32} to make checkpatch happy.

Signed-off-by: Boris Brezillon <boris.brezillon@collabora.com>
Reviewed-by: Miquel Raynal <miquel.raynal@bootlin.com>
Tested-by: Lubomir Rintel <lkundrak@v3.sk>
---
Changes in v2:
* Add R-b/T-b
---
 drivers/mtd/nand/raw/cafe_nand.c | 20 ++++++++++----------
 1 file changed, 10 insertions(+), 10 deletions(-)

diff --git a/drivers/mtd/nand/raw/cafe_nand.c b/drivers/mtd/nand/raw/cafe_nand.c
index 74c64af700d5..022c7a3e4073 100644
--- a/drivers/mtd/nand/raw/cafe_nand.c
+++ b/drivers/mtd/nand/raw/cafe_nand.c
@@ -151,7 +151,7 @@ struct cafe_priv {
 	struct pci_dev *pdev;
 	void __iomem *mmio;
 	struct rs_control *rs;
-	uint32_t ctl2;
+	u32 ctl2;
 	bool usedma;
 	dma_addr_t dmaaddr;
 	unsigned char *dmabuf;
@@ -209,7 +209,7 @@ static irqreturn_t cafe_nand_interrupt(int irq, void *id)
 	struct mtd_info *mtd = id;
 	struct nand_chip *chip = mtd_to_nand(mtd);
 	struct cafe_priv *cafe = nand_get_controller_data(chip);
-	uint32_t irqs = cafe_readl(cafe, NAND_IRQ);
+	u32 irqs = cafe_readl(cafe, NAND_IRQ);
 	cafe_writel(cafe,
 		    irqs & ~(CAFE_NAND_IRQ_CMD_DONE | CAFE_NAND_IRQ_DMA_DONE),
 		    NAND_IRQ);
@@ -240,7 +240,7 @@ static int cafe_nand_read_oob(struct nand_chip *chip, int page)
  * The hw generator calculates the error syndrome automatically. Therefore
  * we need a special oob layout and handling.
  */
-static int cafe_nand_read_page(struct nand_chip *chip, uint8_t *buf,
+static int cafe_nand_read_page(struct nand_chip *chip, u8 *buf,
 			       int oob_required, int page)
 {
 	struct mtd_info *mtd = nand_to_mtd(chip);
@@ -268,8 +268,8 @@ static int cafe_nand_read_page(struct nand_chip *chip, uint8_t *buf,
 		int i, n;
 
 		for (i=0; i<8; i+=2) {
-			uint32_t tmp = cafe_readl(cafe, NAND_ECC_SYN_REG(i));
-			uint16_t idx;
+			u32 tmp = cafe_readl(cafe, NAND_ECC_SYN_REG(i));
+			u16 idx;
 
 			idx = FIELD_GET(CAFE_NAND_ECC_SYN_FIELD(i), tmp);
 			syn[i] = cafe->rs->codec->index_of[idx];
@@ -365,11 +365,11 @@ static const struct mtd_ooblayout_ops cafe_ooblayout_ops = {
 
 /* Ick. The BBT code really ought to be able to work this bit out
    for itself from the above, at least for the 2KiB case */
-static uint8_t cafe_bbt_pattern_2048[] = { 'B', 'b', 't', '0' };
-static uint8_t cafe_mirror_pattern_2048[] = { '1', 't', 'b', 'B' };
+static u8 cafe_bbt_pattern_2048[] = { 'B', 'b', 't', '0' };
+static u8 cafe_mirror_pattern_2048[] = { '1', 't', 'b', 'B' };
 
-static uint8_t cafe_bbt_pattern_512[] = { 0xBB };
-static uint8_t cafe_mirror_pattern_512[] = { 0xBC };
+static u8 cafe_bbt_pattern_512[] = { 0xBB };
+static u8 cafe_mirror_pattern_512[] = { 0xBC };
 
 
 static struct nand_bbt_descr cafe_bbt_main_descr_2048 = {
@@ -414,7 +414,7 @@ static struct nand_bbt_descr cafe_bbt_mirror_descr_512 = {
 
 
 static int cafe_nand_write_page(struct nand_chip *chip,
-				const uint8_t *buf, int oob_required,
+				const u8 *buf, int oob_required,
 				int page)
 {
 	struct mtd_info *mtd = nand_to_mtd(chip);
-- 
2.25.3


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

^ permalink raw reply	[flat|nested] 46+ messages in thread

* [PATCH v2 18/19] mtd: rawnand: cafe: Drop the cafe_{readl, writel}() wrappers
  2020-05-05 10:13 [PATCH v2 00/19] mtd: rawnand: cafe: Convert to exec_op() (and more) Boris Brezillon
                   ` (16 preceding siblings ...)
  2020-05-05 10:13 ` [PATCH v2 17/19] mtd: rawnand: cafe: s/uint{8,16,32}_t/u{8,16,32}/ Boris Brezillon
@ 2020-05-05 10:13 ` Boris Brezillon
  2020-05-10 21:45   ` [PATCH v2 18/19] mtd: rawnand: cafe: Drop the cafe_{readl,writel}() wrappers Miquel Raynal
  2020-05-05 10:13 ` [PATCH v2 19/19] mtd: rawnand: cafe: Get rid of the last printk() Boris Brezillon
       [not found] ` <20200505144639.GB1997@furthur.local>
  19 siblings, 1 reply; 46+ messages in thread
From: Boris Brezillon @ 2020-05-05 10:13 UTC (permalink / raw)
  To: Miquel Raynal, linux-mtd, Lubomir Rintel
  Cc: Richard Weinberger, Boris Brezillon, Vignesh Raghavendra, Tudor Ambarus

Given how long this driver has been there we can safely assume that
nobody cares about PIO support. Getting rid of these macros allows for
easy register name greping.

Signed-off-by: Boris Brezillon <boris.brezillon@collabora.com>
Suggested-by: Lubomir Rintel <lkundrak@v3.sk>
---
Changes in v2:
* New patch
---
 drivers/mtd/nand/raw/cafe_nand.c | 134 +++++++++++++------------------
 1 file changed, 58 insertions(+), 76 deletions(-)

diff --git a/drivers/mtd/nand/raw/cafe_nand.c b/drivers/mtd/nand/raw/cafe_nand.c
index 022c7a3e4073..2f20032b4df7 100644
--- a/drivers/mtd/nand/raw/cafe_nand.c
+++ b/drivers/mtd/nand/raw/cafe_nand.c
@@ -175,10 +175,6 @@ module_param_array(timing, int, &numtimings, 0644);
 
 static const char *part_probes[] = { "cmdlinepart", "RedBoot", NULL };
 
-/* Make it easier to switch to PIO if we need to */
-#define cafe_readl(cafe, addr)			readl((cafe)->mmio + CAFE_##addr)
-#define cafe_writel(cafe, datum, addr)		writel(datum, (cafe)->mmio + CAFE_##addr)
-
 static void cafe_write_buf(struct nand_chip *chip, const void *buf,
 			   unsigned int len)
 {
@@ -209,14 +205,14 @@ static irqreturn_t cafe_nand_interrupt(int irq, void *id)
 	struct mtd_info *mtd = id;
 	struct nand_chip *chip = mtd_to_nand(mtd);
 	struct cafe_priv *cafe = nand_get_controller_data(chip);
-	u32 irqs = cafe_readl(cafe, NAND_IRQ);
-	cafe_writel(cafe,
-		    irqs & ~(CAFE_NAND_IRQ_CMD_DONE | CAFE_NAND_IRQ_DMA_DONE),
-		    NAND_IRQ);
+	u32 irqs = readl(cafe->mmio + CAFE_NAND_IRQ);
+	writel(irqs & ~(CAFE_NAND_IRQ_CMD_DONE | CAFE_NAND_IRQ_DMA_DONE),
+	       cafe->mmio + CAFE_NAND_IRQ);
 	if (!irqs)
 		return IRQ_NONE;
 
-	dev_dbg(&cafe->pdev->dev, "irq, bits %x (%x)\n", irqs, cafe_readl(cafe, NAND_IRQ));
+	dev_dbg(&cafe->pdev->dev, "irq, bits %x (%x)\n", irqs,
+		readl(cafe->mmio + CAFE_NAND_IRQ));
 	return IRQ_HANDLED;
 }
 
@@ -250,8 +246,8 @@ static int cafe_nand_read_page(struct nand_chip *chip, u8 *buf,
 	u32 ecc_result, status;
 
 	dev_dbg(&cafe->pdev->dev, "ECC result %08x SYN1,2 %08x\n",
-		cafe_readl(cafe, NAND_ECC_RESULT),
-		cafe_readl(cafe, NAND_ECC_SYN_REG(0)));
+		readl(cafe->mmio + CAFE_NAND_ECC_RESULT),
+		readl(cafe->mmio + CAFE_NAND_ECC_SYN_REG(0)));
 
 	nand_read_page_op(chip, page, 0, pagebuf,
 			  mtd->writesize + mtd->oobsize);
@@ -259,7 +255,7 @@ static int cafe_nand_read_page(struct nand_chip *chip, u8 *buf,
 	if (buf != pagebuf)
 		memcpy(buf, pagebuf, mtd->writesize);
 
-	ecc_result = cafe_readl(cafe, NAND_ECC_RESULT);
+	ecc_result = readl(cafe->mmio + CAFE_NAND_ECC_RESULT);
 	status = CAFE_FIELD_GET(NAND_ECC_RESULT, STATUS, ecc_result);
 	if (checkecc && status == CAFE_NAND_ECC_RESULT_CORRECTABLE_ERRS) {
 		unsigned short syn[8], pat[4];
@@ -268,7 +264,7 @@ static int cafe_nand_read_page(struct nand_chip *chip, u8 *buf,
 		int i, n;
 
 		for (i=0; i<8; i+=2) {
-			u32 tmp = cafe_readl(cafe, NAND_ECC_SYN_REG(i));
+			u32 tmp = readl(cafe->mmio + CAFE_NAND_ECC_SYN_REG(i));
 			u16 idx;
 
 			idx = FIELD_GET(CAFE_NAND_ECC_SYN_FIELD(i), tmp);
@@ -315,10 +311,12 @@ static int cafe_nand_read_page(struct nand_chip *chip, u8 *buf,
 		}
 
 		if (n < 0) {
-			dev_dbg(&cafe->pdev->dev, "Failed to correct ECC at %08x\n",
-				cafe_readl(cafe, NAND_ADDR2) * 2048);
+			dev_dbg(&cafe->pdev->dev,
+				"Failed to correct ECC at %08x\n",
+				readl(cafe->mmio + CAFE_NAND_ADDR2) * 2048);
 			for (i = 0; i < 0x5c; i += 4)
-				printk("Register %x: %08x\n", i, readl(cafe->mmio + i));
+				printk("Register %x: %08x\n", i,
+				       readl(cafe->mmio + i));
 			mtd->ecc_stats.failed++;
 		} else {
 			dev_dbg(&cafe->pdev->dev, "Corrected %d symbol errors\n", n);
@@ -494,11 +492,11 @@ static int cafe_nand_attach_chip(struct nand_chip *chip)
 		return -ENOMEM;
 
 	/* Set up DMA address */
-	cafe_writel(cafe, lower_32_bits(cafe->dmaaddr), NAND_DMA_ADDR0);
-	cafe_writel(cafe, upper_32_bits(cafe->dmaaddr), NAND_DMA_ADDR1);
+	writel(lower_32_bits(cafe->dmaaddr), cafe->mmio + CAFE_NAND_DMA_ADDR0);
+	writel(upper_32_bits(cafe->dmaaddr), cafe->mmio + CAFE_NAND_DMA_ADDR1);
 
 	dev_dbg(&cafe->pdev->dev, "Set DMA address to %x (virt %p)\n",
-		cafe_readl(cafe, NAND_DMA_ADDR0), cafe->dmabuf);
+		readl(cafe->mmio + CAFE_NAND_DMA_ADDR0), cafe->dmabuf);
 
 	/* Restore the DMA flag */
 	cafe->usedma = usedma;
@@ -589,8 +587,8 @@ static int cafe_nand_exec_subop(struct nand_chip *chip,
 			ctrl1 |= CAFE_NAND_CTRL1_HAS_ADDR |
 				 CAFE_FIELD_PREP(NAND_CTRL1, NUM_ADDR_CYC,
 						 instr->ctx.addr.naddrs - 1);
-			cafe_writel(cafe, addr1, NAND_ADDR1);
-			cafe_writel(cafe, addr2, NAND_ADDR2);
+			writel(addr1, cafe->mmio + CAFE_NAND_ADDR1);
+			writel(addr2, cafe->mmio + CAFE_NAND_ADDR2);
 			break;
 
 		case NAND_OP_DATA_IN_INSTR:
@@ -615,8 +613,8 @@ static int cafe_nand_exec_subop(struct nand_chip *chip,
 	}
 
 	if (data_instr >= 0)
-		cafe_writel(cafe, nand_subop_get_data_len(subop, data_instr),
-			    NAND_DATA_LEN);
+		writel(nand_subop_get_data_len(subop, data_instr),
+		       cafe->mmio + CAFE_NAND_DATA_LEN);
 
 	if (cafe->usedma && data_instr >= 0) {
 		u32 dmactrl = CAFE_NAND_DMA_CTRL_ENABLE |
@@ -628,7 +626,7 @@ static int cafe_nand_exec_subop(struct nand_chip *chip,
 		if (ctrl1 & CAFE_NAND_CTRL1_HAS_DATA_IN)
 			dmactrl |= CAFE_NAND_DMA_CTRL_DATA_IN;
 
-		cafe_writel(cafe, dmactrl, NAND_DMA_CTRL);
+		writel(dmactrl, cafe->mmio + CAFE_NAND_DMA_CTRL);
 
 		/*
 		 * If the last instruction is a data transfer and we're using
@@ -642,10 +640,10 @@ static int cafe_nand_exec_subop(struct nand_chip *chip,
 	}
 
 	/* Clear the pending interrupts before starting the operation. */
-	cafe_writel(cafe, wait, NAND_IRQ);
+	writel(wait, cafe->mmio + CAFE_NAND_IRQ);
 
-	cafe_writel(cafe, ctrl2, NAND_CTRL2);
-	cafe_writel(cafe, ctrl1, NAND_CTRL1);
+	writel(ctrl2, cafe->mmio + CAFE_NAND_CTRL2);
+	writel(ctrl1, cafe->mmio + CAFE_NAND_CTRL1);
 
 	ret = readl_poll_timeout(cafe->mmio + CAFE_NAND_IRQ, status,
 				 (status & wait) == wait, 1, USEC_PER_SEC);
@@ -695,17 +693,17 @@ static void cafe_nand_init(struct cafe_priv *cafe)
 	u32 ctrl;
 
 	/* Start off by resetting the NAND controller completely */
-	cafe_writel(cafe, CAFE_GLOBAL_RESET_NAND, GLOBAL_RESET);
-	cafe_writel(cafe, 0, GLOBAL_RESET);
-	cafe_writel(cafe, 0xffffffff, NAND_IRQ_MASK);
+	writel(CAFE_GLOBAL_RESET_NAND, cafe->mmio + CAFE_GLOBAL_RESET);
+	writel(0, cafe->mmio + CAFE_GLOBAL_RESET);
+	writel(0xffffffff, cafe->mmio + CAFE_NAND_IRQ_MASK);
 
 	/* Restore timing configuration */
-	cafe_writel(cafe, timing[0], NAND_TIMING1);
-	cafe_writel(cafe, timing[1], NAND_TIMING2);
-	cafe_writel(cafe, timing[2], NAND_TIMING3);
+	writel(timing[0], cafe->mmio + CAFE_NAND_TIMING1);
+	writel(timing[1], cafe->mmio + CAFE_NAND_TIMING2);
+	writel(timing[2], cafe->mmio + CAFE_NAND_TIMING3);
 
 	/* Disable master reset, enable NAND clock */
-	ctrl = cafe_readl(cafe, GLOBAL_CTRL);
+	ctrl = readl(cafe->mmio + CAFE_GLOBAL_CTRL);
 	ctrl &= ~(CAFE_GLOBAL_SW_RESET_SET |
 		  CAFE_GLOBAL_SW_RESET_CLEAR |
 		  CAFE_GLOBAL_MASTER_RESET_SET |
@@ -714,45 +712,31 @@ static void cafe_nand_init(struct cafe_priv *cafe)
 	ctrl |= CAFE_GLOBAL_NAND_CLK_ENABLE |
 		CAFE_GLOBAL_SDH_CLK_ENABLE |
 		CAFE_GLOBAL_CCIC_CLK_ENABLE;
-	cafe_writel(cafe,
-		    ctrl |
-		    CAFE_GLOBAL_MASTER_RESET_SET |
-		    CAFE_GLOBAL_SW_RESET_SET,
-		    GLOBAL_CTRL);
-	cafe_writel(cafe,
-		    ctrl |
-		    CAFE_GLOBAL_MASTER_RESET_CLEAR |
-		    CAFE_GLOBAL_SW_RESET_CLEAR,
-		    GLOBAL_CTRL);
+	writel(ctrl | CAFE_GLOBAL_MASTER_RESET_SET | CAFE_GLOBAL_SW_RESET_SET,
+	       cafe->mmio + CAFE_GLOBAL_CTRL);
+	writel(ctrl | CAFE_GLOBAL_MASTER_RESET_CLEAR |
+	       CAFE_GLOBAL_SW_RESET_CLEAR,
+	       cafe->mmio + CAFE_GLOBAL_CTRL);
 
-	cafe_writel(cafe, 0, NAND_DMA_CTRL);
+	writel(0, cafe->mmio + CAFE_NAND_DMA_CTRL);
 
-	cafe_writel(cafe,
-		    CAFE_GLOBAL_NAND_CLK_ENABLE |
-		    CAFE_GLOBAL_SDH_CLK_ENABLE |
-		    CAFE_GLOBAL_CCIC_CLK_ENABLE |
-		    CAFE_GLOBAL_MASTER_RESET_SET |
-		    CAFE_GLOBAL_SW_RESET_CLEAR,
-		    GLOBAL_CTRL);
-	cafe_writel(cafe,
-		    CAFE_GLOBAL_NAND_CLK_ENABLE |
-		    CAFE_GLOBAL_SDH_CLK_ENABLE |
-		    CAFE_GLOBAL_CCIC_CLK_ENABLE |
-		    CAFE_GLOBAL_MASTER_RESET_CLEAR |
-		    CAFE_GLOBAL_SW_RESET_CLEAR,
-		    GLOBAL_CTRL);
+	writel(CAFE_GLOBAL_NAND_CLK_ENABLE | CAFE_GLOBAL_SDH_CLK_ENABLE |
+	       CAFE_GLOBAL_CCIC_CLK_ENABLE | CAFE_GLOBAL_MASTER_RESET_SET |
+	       CAFE_GLOBAL_SW_RESET_CLEAR,
+	       cafe->mmio + CAFE_GLOBAL_CTRL);
+	writel(CAFE_GLOBAL_NAND_CLK_ENABLE | CAFE_GLOBAL_SDH_CLK_ENABLE |
+	       CAFE_GLOBAL_CCIC_CLK_ENABLE | CAFE_GLOBAL_MASTER_RESET_CLEAR |
+	       CAFE_GLOBAL_SW_RESET_CLEAR,
+	       cafe->mmio + CAFE_GLOBAL_CTRL);
 
 	/* Set up DMA address */
-	cafe_writel(cafe, lower_32_bits(cafe->dmaaddr), NAND_DMA_ADDR0);
-	cafe_writel(cafe, upper_32_bits(cafe->dmaaddr), NAND_DMA_ADDR1);
+	writel(lower_32_bits(cafe->dmaaddr), cafe->mmio + CAFE_NAND_DMA_ADDR0);
+	writel(upper_32_bits(cafe->dmaaddr), cafe->mmio + CAFE_NAND_DMA_ADDR1);
 
 	/* Enable NAND IRQ in global IRQ mask register */
-	cafe_writel(cafe,
-		    CAFE_GLOBAL_IRQ_PCI_ERROR |
-		    CAFE_GLOBAL_IRQ_CCIC |
-		    CAFE_GLOBAL_IRQ_SDH |
-		    CAFE_GLOBAL_IRQ_NAND,
-		    GLOBAL_IRQ_MASK);
+	writel(CAFE_GLOBAL_IRQ_PCI_ERROR | CAFE_GLOBAL_IRQ_CCIC |
+	       CAFE_GLOBAL_IRQ_SDH | CAFE_GLOBAL_IRQ_NAND,
+	       cafe->mmio + CAFE_GLOBAL_IRQ_MASK);
 }
 
 static int cafe_nand_probe(struct pci_dev *pdev,
@@ -808,9 +792,9 @@ static int cafe_nand_probe(struct pci_dev *pdev,
 		dev_dbg(&cafe->pdev->dev, "Using provided timings (%08x %08x %08x)\n",
 			timing[0], timing[1], timing[2]);
 	} else {
-		timing[0] = cafe_readl(cafe, NAND_TIMING1);
-		timing[1] = cafe_readl(cafe, NAND_TIMING2);
-		timing[2] = cafe_readl(cafe, NAND_TIMING3);
+		timing[0] = readl(cafe->mmio + CAFE_NAND_TIMING1);
+		timing[1] = readl(cafe->mmio + CAFE_NAND_TIMING2);
+		timing[2] = readl(cafe->mmio + CAFE_NAND_TIMING3);
 
 		if (timing[0] | timing[1] | timing[2]) {
 			dev_dbg(&cafe->pdev->dev, "Timing registers already set (%08x %08x %08x)\n",
@@ -854,9 +838,8 @@ static int cafe_nand_probe(struct pci_dev *pdev,
 	nand_cleanup(&cafe->nand);
  out_irq:
 	/* Disable NAND IRQ in global IRQ mask register */
-	cafe_writel(cafe,
-		    cafe_readl(cafe, GLOBAL_IRQ_MASK) & ~CAFE_GLOBAL_IRQ_NAND,
-		    GLOBAL_IRQ_MASK);
+	writel(readl(cafe->mmio + CAFE_GLOBAL_IRQ_MASK) & ~CAFE_GLOBAL_IRQ_NAND,
+	       cafe->mmio + CAFE_GLOBAL_IRQ_MASK);
  out_ior:
 	pci_iounmap(pdev, cafe->mmio);
 	return err;
@@ -869,9 +852,8 @@ static void cafe_nand_remove(struct pci_dev *pdev)
 	struct cafe_priv *cafe = nand_get_controller_data(chip);
 
 	/* Disable NAND IRQ in global IRQ mask register */
-	cafe_writel(cafe,
-		    cafe_readl(cafe, GLOBAL_IRQ_MASK) & ~CAFE_GLOBAL_IRQ_NAND,
-		    GLOBAL_IRQ_MASK);
+	writel(readl(cafe->mmio + CAFE_GLOBAL_IRQ_MASK) & ~CAFE_GLOBAL_IRQ_NAND,
+	       cafe->mmio + CAFE_GLOBAL_IRQ_MASK);
 	nand_release(chip);
 	free_rs(cafe->rs);
 	pci_iounmap(pdev, cafe->mmio);
-- 
2.25.3


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

^ permalink raw reply	[flat|nested] 46+ messages in thread

* [PATCH v2 19/19] mtd: rawnand: cafe: Get rid of the last printk()
  2020-05-05 10:13 [PATCH v2 00/19] mtd: rawnand: cafe: Convert to exec_op() (and more) Boris Brezillon
                   ` (17 preceding siblings ...)
  2020-05-05 10:13 ` [PATCH v2 18/19] mtd: rawnand: cafe: Drop the cafe_{readl, writel}() wrappers Boris Brezillon
@ 2020-05-05 10:13 ` Boris Brezillon
  2020-05-10 21:43   ` Miquel Raynal
       [not found] ` <20200505144639.GB1997@furthur.local>
  19 siblings, 1 reply; 46+ messages in thread
From: Boris Brezillon @ 2020-05-05 10:13 UTC (permalink / raw)
  To: Miquel Raynal, linux-mtd, Lubomir Rintel
  Cc: Richard Weinberger, Boris Brezillon, Vignesh Raghavendra, Tudor Ambarus

Replace the last printk() by a dev_dbg().

Signed-off-by: Boris Brezillon <boris.brezillon@collabora.com>
---
 drivers/mtd/nand/raw/cafe_nand.c | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)

diff --git a/drivers/mtd/nand/raw/cafe_nand.c b/drivers/mtd/nand/raw/cafe_nand.c
index 2f20032b4df7..9df02ad951d8 100644
--- a/drivers/mtd/nand/raw/cafe_nand.c
+++ b/drivers/mtd/nand/raw/cafe_nand.c
@@ -315,8 +315,9 @@ static int cafe_nand_read_page(struct nand_chip *chip, u8 *buf,
 				"Failed to correct ECC at %08x\n",
 				readl(cafe->mmio + CAFE_NAND_ADDR2) * 2048);
 			for (i = 0; i < 0x5c; i += 4)
-				printk("Register %x: %08x\n", i,
-				       readl(cafe->mmio + i));
+				dev_dbg(&cafe->pdev->dev,
+					"Register %x: %08x\n", i,
+					readl(cafe->mmio + i));
 			mtd->ecc_stats.failed++;
 		} else {
 			dev_dbg(&cafe->pdev->dev, "Corrected %d symbol errors\n", n);
-- 
2.25.3


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

^ permalink raw reply	[flat|nested] 46+ messages in thread

* Re: [PATCH v2 00/19] mtd: rawnand: cafe: Convert to exec_op() (and more)
       [not found]   ` <20200505220152.GA157445@furthur.local>
@ 2020-05-06  6:32     ` Boris Brezillon
       [not found]       ` <20200506155359.GA183666@furthur.local>
  0 siblings, 1 reply; 46+ messages in thread
From: Boris Brezillon @ 2020-05-06  6:32 UTC (permalink / raw)
  To: Lubomir Rintel
  Cc: Richard Weinberger, Tudor Ambarus, linux-mtd,
	Vignesh Raghavendra, Miquel Raynal

On Wed, 6 May 2020 00:01:52 +0200
Lubomir Rintel <lkundrak@v3.sk> wrote:

> On Tue, May 05, 2020 at 04:46:41PM +0200, Lubomir Rintel wrote:
> > On Tue, May 05, 2020 at 12:13:34PM +0200, Boris Brezillon wrote:  
> > > Hello,
> > > 
> > > A bit of context to explain the motivation behind those conversions
> > > I've been sending for the last couple of weeks. The raw NAND subsystem
> > > carries a lot of history which makes any rework not only painful, but
> > > also subject to regressions which we only detect when someone dares to
> > > update its kernel on one of those ancient HW. While carrying drivers
> > > for old HW is not a problem per se, carrying ancient and unmaintained
> > > drivers that are not converted to new APIs is a maintenance burden,
> > > hence this massive conversion attempt I'm conducting here.
> > > 
> > > So here is a series converting the CAFE NAND controller driver to
> > > exec_op(), plus a bunch of minor improvements done along the way.
> > > I hope I'll find someone to test those changes, but if there's no one
> > > still owning OLPC HW or no interest in keeping it supported in recent
> > > kernel versions, we should definitely consider removing the driver
> > > instead.
> > > 
> > > No major changes in this v2, apart from fixes for things reported by
> > > Lubomir and Miquel. See the changelog on each patch for more details.
> > > 
> > > Regards,
> > > 
> > > Boris
> > > 
> > > Boris Brezillon (19):
> > >   mtd: rawnand: Propage CS selection to sub operations
> > >   mtd: rawnand: cafe: Get rid of an inaccurate kernel doc header
> > >   mtd: rawnand: cafe: Rename cafe_nand_write_page_lowlevel()
> > >   mtd: rawnand: cafe: Use a correct ECC mode and pass the ECC alg
> > >   mtd: rawnand: cafe: Include linux/io.h instead of asm/io.h
> > >   mtd: rawnand: cafe: Demistify register fields
> > >   mtd: rawnand: cafe: Factor out the controller initialization logic
> > >   mtd: rawnand: cafe: Get rid of the debug module param
> > >   mtd: rawnand: cafe: Use devm_kzalloc and devm_request_irq()
> > >   mtd: rawnand: cafe: Get rid of a useless label
> > >   mtd: rawnand: cafe: Explicitly inherit from nand_controller
> > >   mtd: rawnand: cafe: Don't leave ECC enabled in the write path
> > >   mtd: rawnand: cafe: Don't split things when reading/writing a page
> > >   mtd: rawnand: cafe: Add exec_op() support
> > >   mtd: rawnand: cafe: Get rid of the legacy interface implementation
> > >   mtd: rawnand: cafe: Adjust the cafe_{read,write}_buf() prototypes
> > >   mtd: rawnand: cafe: s/uint{8,16,32}_t/u{8,16,32}/
> > >   mtd: rawnand: cafe: Drop the cafe_{readl,writel}() wrappers
> > >   mtd: rawnand: cafe: Get rid of the last printk()
> > > 
> > >  drivers/mtd/nand/raw/cafe_nand.c | 798 ++++++++++++++++---------------
> > >  drivers/mtd/nand/raw/nand_base.c |   3 +-
> > >  include/linux/mtd/rawnand.h      |   2 +
> > >  3 files changed, 410 insertions(+), 393 deletions(-)  
> > 
> > Just confirming that this set works a treat on an OLPC XO-1 laptop,
> > applied on top of v5.7-rc4.  
> 
> Perhaps I spoke too soon. Before I've tested by dumping a couple of pages
> and checksumming them and it indeed worked fine every time.
> 
> Now I've actually tried to mount a JFFS2 filesystem. On v5.7-rc4 it worked:
> 
>   bash-5.0# mount -t jffs2 mtd0 /mnt
>   jffs2: jffs2_scan_dirent_node(): Name CRC failed on node at 0x30212fc8: Read 0x583ccb57, calculated 0x06d03796
>   jffs2: notice: (96) jffs2_build_xattr_subsystem: complete building xattr subsystem, 0 of xdatum (0 unchecked, 0 orphan) and 0 of xref (0 dead, 0 orphan) f.
>   bash-5.0# ls /mnt
>   boot        dev         lost+found  security    versions
>   boot-alt    home        proc        sys
>   bash-5.0#
> 
> Whereas with the patches applied it does not:
> 
>   bash-5.0# mount -t jffs2 mtd0 /mnt
>   jffs2: cannot read OOB for EB at 00260000, requested 8 bytes, read 0 bytes, error -110
>   mount: /mnt: can't read superblock on mtd0.
>   bash-5.0# mount -t jffs2 mtd0 /mnt
>   jffs2: cannot read OOB for EB at 001c0000, requested 8 bytes, read 0 bytes, error -110
>   mount: /mnt: can't read superblock on mtd0.
>   bash-5.0# mount -t jffs2 mtd0 /mnt
>   jffs2: warning: (102) jffs2_sum_scan_sumnode: Summary node crc error, skipping summary information.
>   jffs2: jffs2_scan_eraseblock(): Magic bitmask 0x1985 not found at 0x00122a28: 0x15ee instead
>   jffs2: jffs2_scan_eraseblock(): Magic bitmask 0x1985 not found at 0x00122a2c: 0x4176 instead
>   jffs2: jffs2_scan_eraseblock(): Magic bitmask 0x1985 not found at 0x00122a30: 0x105d instead
>   jffs2: jffs2_scan_eraseblock(): Magic bitmask 0x1985 not found at 0x00122a34: 0x13f1 instead
>   jffs2: jffs2_scan_eraseblock(): Magic bitmask 0x1985 not found at 0x00122a38: 0x7df1 instead
>   jffs2: jffs2_scan_eraseblock(): Magic bitmask 0x1985 not found at 0x00122a3c: 0xca39 instead
>   jffs2: jffs2_scan_eraseblock(): Magic bitmask 0x1985 not found at 0x00122a40: 0xe70e instead
>   jffs2: jffs2_scan_eraseblock(): Magic bitmask 0x1985 not found at 0x00122a44: 0x1004 instead
>   jffs2: jffs2_scan_eraseblock(): Magic bitmask 0x1985 not found at 0x00122a48: 0x2902 instead
>   jffs2: jffs2_scan_eraseblock(): Magic bitmask 0x1985 not found at 0x00122a4c: 0x0030 instead
>   jffs2: Further such events for this erase block will not be printed
>   jffs2: jffs2_scan_dirent_node(): Name CRC failed on node at 0x001287cc: Read 0x7fea120a, calculated 0x9ceec452
>   jffs2: jffs2_scan_dirent_node(): Name CRC failed on node at 0x00128fcc: Read 0x7fea120a, calculated 0xb77b2a34
>   jffs2: warning: (102) jffs2_sum_scan_sumnode: Summary node crc error, skipping summary information.
>   jffs2: jffs2_scan_eraseblock(): Magic bitmask 0x1985 not found at 0x007232b0: 0xdd29 instead
>   jffs2: jffs2_scan_eraseblock(): Magic bitmask 0x1985 not found at 0x007232b4: 0xf37e instead
>   jffs2: jffs2_scan_eraseblock(): Magic bitmask 0x1985 not found at 0x007232b8: 0x251b instead
>   jffs2: jffs2_scan_eraseblock(): Magic bitmask 0x1985 not found at 0x007232bc: 0xe805 instead
>   jffs2: jffs2_scan_eraseblock(): Magic bitmask 0x1985 not found at 0x007232c0: 0xd3bf instead
>   jffs2: jffs2_scan_eraseblock(): Magic bitmask 0x1985 not found at 0x007232c4: 0x2927 instead
>   jffs2: jffs2_scan_eraseblock(): Magic bitmask 0x1985 not found at 0x007232c8: 0xd79d instead
>   jffs2: jffs2_scan_eraseblock(): Magic bitmask 0x1985 not found at 0x007232cc: 0xd548 instead
>   jffs2: jffs2_scan_eraseblock(): Magic bitmask 0x1985 not found at 0x007232d0: 0x46e3 instead
>   jffs2: jffs2_scan_eraseblock(): Magic bitmask 0x1985 not found at 0x007232d4: 0x7716 instead
>   jffs2: Further such events for this erase block will not be printed
>   jffs2: cannot read OOB for EB at 009e0000, requested 8 bytes, read 0 bytes, error -110
>   mount: /mnt: can't read superblock on mtd0.
>   bash-5.0# 
> 
> Note that the failed reads are for different addresses every time. The
> CRC errors are there presumably because we don't handle
> nand_read_page_op() errors in cafe_nand_read_page().
> 
> I have no idea what's going on. With the debug trace on it looks like
> CAFE_NAND_IRQ_FLASH_RDY is sometimes not flipped on for no apparent
> reason:
> 
>   ...
>   instr[0] = CMD(00)
>   instr[1] = ADDR(00 00 bd 09 00)
>   instr[2] = CMD(30)
>   instr[3] = WAITRDY
>   instr[4] = DATA_IN(len=2112)
>   5: ret=0 status=d0000000 wait=50000000
>   instr[0] = CMD(00)
>   instr[1] = ADDR(00 00 be 09 00)
>   instr[2] = CMD(30)
>   instr[3] = WAITRDY
>   instr[4] = DATA_IN(len=2112)
>   5: ret=0 status=d0000000 wait=50000000
>   instr[0] = CMD(00)
>   instr[1] = ADDR(00 08 c0 09 00)
>   instr[2] = CMD(30)
>   instr[3] = WAITRDY
>   instr[4] = DATA_IN(len=64)
>   5: ret=0 status=d0000000 wait=50000000
>   instr[0] = CMD(00)
>   instr[1] = ADDR(00 00 ff 09 00)
>   instr[2] = CMD(30)
>   instr[3] = WAITRDY
>   instr[4] = DATA_IN(len=2112)
>   5: ret=0 status=d0000000 wait=50000000
>   instr[0] = CMD(00)
>   instr[1] = ADDR(00 00 fd 09 00)
>   instr[2] = CMD(30)
>   instr[3] = WAITRDY
>   instr[4] = DATA_IN(len=2112)
>   5: ret=0 status=d0000000 wait=50000000
>   instr[0] = CMD(00)
>   instr[1] = ADDR(00 00 fe 09 00)
>   instr[2] = CMD(30)
>   instr[3] = WAITRDY
>   instr[4] = DATA_IN(len=2112)
>   5: ret=0 status=d0000000 wait=50000000
>   instr[0] = CMD(00)
>   instr[1] = ADDR(00 08 00 0a 00)
>   instr[2] = CMD(30)
>   instr[3] = WAITRDY
>   instr[4] = DATA_IN(len=64)
>   5: ret=-110 status=90000000 wait=50000000
>   jffs2: cannot read OOB for EB at 00500000, requested 8 bytes, read 0 bytes, error -110
> 
> Indeed, commenting out the CAFE_NAND_IRQ_FLASH_RDY makes things work

Looks like that happens when you read less than 2k. Can you print the
CAFE_NAND_STATUS register in your trace? I suspect
CAFE_NAND_STATUS_FLASH_BUSY will be cleared, so maybe it's the way to
go if we want to make sure the check Ready/Busy pin status.

> (on a somewhat unrelated note, the waitrdy doesn't seem to be used at
> all):

Yep, I initially thought I would need to poll the NAND_STATUS register
and added a boolean to keep track that before realizing there was a bit
in the IRQ_STATUS reg.

> 
>        case NAND_OP_WAITRDY_INSTR:
> 	       // wait |= CAFE_NAND_IRQ_FLASH_RDY;
> 	       waitrdy = true;
> 	       break;
>        }
> 
> 
>   bash-5.0# time mount -t jffs2 mtd0 /mnt
>   jffs2: jffs2_scan_dirent_node(): Name CRC failed on node at 0x30212fc8: Read 0x583ccb57, calculated 0x06d03796
>   jffs2: notice: (96) jffs2_build_xattr_subsystem: complete building xattr subsystem, 0 of xdatum (0 unchecked, 0 orphan) and 0 of xref (0 dead, 0 orphan) f.
>   
>   real    5m5.512s
>   user    0m0.000s
>   sys     0m17.523s
>   bash-5.0#
> 
> The mount time seems to be significantly higher than with mainline,
> where it looks more like this:

Can you add a trace in the IRQ handler (before the "if (!irqs)" check).
I interpreted the 'masked' state as 'irq disabled', but maybe that's
the opposite, and we're being flood by uncleared 'FLASH_RDY'
interrupts. In any case, given we're polling the IRQ_STATUS
register, I don't think we need to enable interrupts (unless the
status is only updated when the interrupt is enabled).

Using readl_poll_timeout_atomic() instead of readl_poll_timeout() might
also help.

> 
>   bash-5.0# time mount -t jffs2 mtd0 /mnt
>   jffs2: jffs2_scan_dirent_node(): Name CRC failed on node at 0x30212fc8: Read 0x583ccb57, calculated 0x06d03796
>   jffs2: notice: (96) jffs2_build_xattr_subsystem: complete building xattr subsystem, 0 of xdatum (0 unchecked, 0 orphan) and 0 of xref (0 dead, 0 orphan) f.
>   
>   real    0m7.282s
>   user    0m0.000s
>   sys     0m7.118s
>   bash-5.0# 
> 
> I have not looked into why that might be; perhaps you have an idea?
> 
> Lubo


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

^ permalink raw reply	[flat|nested] 46+ messages in thread

* Re: [PATCH v2 00/19] mtd: rawnand: cafe: Convert to exec_op() (and more)
       [not found]       ` <20200506155359.GA183666@furthur.local>
@ 2020-05-06 16:11         ` Boris Brezillon
       [not found]           ` <20200506203635.GA207924@furthur.local>
  0 siblings, 1 reply; 46+ messages in thread
From: Boris Brezillon @ 2020-05-06 16:11 UTC (permalink / raw)
  To: Lubomir Rintel
  Cc: Richard Weinberger, Tudor Ambarus, linux-mtd,
	Vignesh Raghavendra, Miquel Raynal

On Wed, 6 May 2020 17:53:59 +0200
Lubomir Rintel <lkundrak@v3.sk> wrote:

> On Wed, May 06, 2020 at 08:32:09AM +0200, Boris Brezillon wrote:
> > On Wed, 6 May 2020 00:01:52 +0200
> > Lubomir Rintel <lkundrak@v3.sk> wrote:
> >   
> > > On Tue, May 05, 2020 at 04:46:41PM +0200, Lubomir Rintel wrote:  
> > > > On Tue, May 05, 2020 at 12:13:34PM +0200, Boris Brezillon wrote:    
> > > > > Hello,
> > > > > 
> > > > > A bit of context to explain the motivation behind those conversions
> > > > > I've been sending for the last couple of weeks. The raw NAND subsystem
> > > > > carries a lot of history which makes any rework not only painful, but
> > > > > also subject to regressions which we only detect when someone dares to
> > > > > update its kernel on one of those ancient HW. While carrying drivers
> > > > > for old HW is not a problem per se, carrying ancient and unmaintained
> > > > > drivers that are not converted to new APIs is a maintenance burden,
> > > > > hence this massive conversion attempt I'm conducting here.
> > > > > 
> > > > > So here is a series converting the CAFE NAND controller driver to
> > > > > exec_op(), plus a bunch of minor improvements done along the way.
> > > > > I hope I'll find someone to test those changes, but if there's no one
> > > > > still owning OLPC HW or no interest in keeping it supported in recent
> > > > > kernel versions, we should definitely consider removing the driver
> > > > > instead.
> > > > > 
> > > > > No major changes in this v2, apart from fixes for things reported by
> > > > > Lubomir and Miquel. See the changelog on each patch for more details.
> > > > > 
> > > > > Regards,
> > > > > 
> > > > > Boris
> > > > > 
> > > > > Boris Brezillon (19):
> > > > >   mtd: rawnand: Propage CS selection to sub operations
> > > > >   mtd: rawnand: cafe: Get rid of an inaccurate kernel doc header
> > > > >   mtd: rawnand: cafe: Rename cafe_nand_write_page_lowlevel()
> > > > >   mtd: rawnand: cafe: Use a correct ECC mode and pass the ECC alg
> > > > >   mtd: rawnand: cafe: Include linux/io.h instead of asm/io.h
> > > > >   mtd: rawnand: cafe: Demistify register fields
> > > > >   mtd: rawnand: cafe: Factor out the controller initialization logic
> > > > >   mtd: rawnand: cafe: Get rid of the debug module param
> > > > >   mtd: rawnand: cafe: Use devm_kzalloc and devm_request_irq()
> > > > >   mtd: rawnand: cafe: Get rid of a useless label
> > > > >   mtd: rawnand: cafe: Explicitly inherit from nand_controller
> > > > >   mtd: rawnand: cafe: Don't leave ECC enabled in the write path
> > > > >   mtd: rawnand: cafe: Don't split things when reading/writing a page
> > > > >   mtd: rawnand: cafe: Add exec_op() support
> > > > >   mtd: rawnand: cafe: Get rid of the legacy interface implementation
> > > > >   mtd: rawnand: cafe: Adjust the cafe_{read,write}_buf() prototypes
> > > > >   mtd: rawnand: cafe: s/uint{8,16,32}_t/u{8,16,32}/
> > > > >   mtd: rawnand: cafe: Drop the cafe_{readl,writel}() wrappers
> > > > >   mtd: rawnand: cafe: Get rid of the last printk()
> > > > > 
> > > > >  drivers/mtd/nand/raw/cafe_nand.c | 798 ++++++++++++++++---------------
> > > > >  drivers/mtd/nand/raw/nand_base.c |   3 +-
> > > > >  include/linux/mtd/rawnand.h      |   2 +
> > > > >  3 files changed, 410 insertions(+), 393 deletions(-)    
> > > > 
> > > > Just confirming that this set works a treat on an OLPC XO-1 laptop,
> > > > applied on top of v5.7-rc4.    
> > > 
> > > Perhaps I spoke too soon. Before I've tested by dumping a couple of pages
> > > and checksumming them and it indeed worked fine every time.
> > > 
> > > Now I've actually tried to mount a JFFS2 filesystem. On v5.7-rc4 it worked:
> > > 
> > >   bash-5.0# mount -t jffs2 mtd0 /mnt
> > >   jffs2: jffs2_scan_dirent_node(): Name CRC failed on node at 0x30212fc8: Read 0x583ccb57, calculated 0x06d03796
> > >   jffs2: notice: (96) jffs2_build_xattr_subsystem: complete building xattr subsystem, 0 of xdatum (0 unchecked, 0 orphan) and 0 of xref (0 dead, 0 orphan) f.
> > >   bash-5.0# ls /mnt
> > >   boot        dev         lost+found  security    versions
> > >   boot-alt    home        proc        sys
> > >   bash-5.0#
> > > 
> > > Whereas with the patches applied it does not:
> > > 
> > >   bash-5.0# mount -t jffs2 mtd0 /mnt
> > >   jffs2: cannot read OOB for EB at 00260000, requested 8 bytes, read 0 bytes, error -110
> > >   mount: /mnt: can't read superblock on mtd0.
> > >   bash-5.0# mount -t jffs2 mtd0 /mnt
> > >   jffs2: cannot read OOB for EB at 001c0000, requested 8 bytes, read 0 bytes, error -110
> > >   mount: /mnt: can't read superblock on mtd0.
> > >   bash-5.0# mount -t jffs2 mtd0 /mnt
> > >   jffs2: warning: (102) jffs2_sum_scan_sumnode: Summary node crc error, skipping summary information.
> > >   jffs2: jffs2_scan_eraseblock(): Magic bitmask 0x1985 not found at 0x00122a28: 0x15ee instead
> > >   jffs2: jffs2_scan_eraseblock(): Magic bitmask 0x1985 not found at 0x00122a2c: 0x4176 instead
> > >   jffs2: jffs2_scan_eraseblock(): Magic bitmask 0x1985 not found at 0x00122a30: 0x105d instead
> > >   jffs2: jffs2_scan_eraseblock(): Magic bitmask 0x1985 not found at 0x00122a34: 0x13f1 instead
> > >   jffs2: jffs2_scan_eraseblock(): Magic bitmask 0x1985 not found at 0x00122a38: 0x7df1 instead
> > >   jffs2: jffs2_scan_eraseblock(): Magic bitmask 0x1985 not found at 0x00122a3c: 0xca39 instead
> > >   jffs2: jffs2_scan_eraseblock(): Magic bitmask 0x1985 not found at 0x00122a40: 0xe70e instead
> > >   jffs2: jffs2_scan_eraseblock(): Magic bitmask 0x1985 not found at 0x00122a44: 0x1004 instead
> > >   jffs2: jffs2_scan_eraseblock(): Magic bitmask 0x1985 not found at 0x00122a48: 0x2902 instead
> > >   jffs2: jffs2_scan_eraseblock(): Magic bitmask 0x1985 not found at 0x00122a4c: 0x0030 instead
> > >   jffs2: Further such events for this erase block will not be printed
> > >   jffs2: jffs2_scan_dirent_node(): Name CRC failed on node at 0x001287cc: Read 0x7fea120a, calculated 0x9ceec452
> > >   jffs2: jffs2_scan_dirent_node(): Name CRC failed on node at 0x00128fcc: Read 0x7fea120a, calculated 0xb77b2a34
> > >   jffs2: warning: (102) jffs2_sum_scan_sumnode: Summary node crc error, skipping summary information.
> > >   jffs2: jffs2_scan_eraseblock(): Magic bitmask 0x1985 not found at 0x007232b0: 0xdd29 instead
> > >   jffs2: jffs2_scan_eraseblock(): Magic bitmask 0x1985 not found at 0x007232b4: 0xf37e instead
> > >   jffs2: jffs2_scan_eraseblock(): Magic bitmask 0x1985 not found at 0x007232b8: 0x251b instead
> > >   jffs2: jffs2_scan_eraseblock(): Magic bitmask 0x1985 not found at 0x007232bc: 0xe805 instead
> > >   jffs2: jffs2_scan_eraseblock(): Magic bitmask 0x1985 not found at 0x007232c0: 0xd3bf instead
> > >   jffs2: jffs2_scan_eraseblock(): Magic bitmask 0x1985 not found at 0x007232c4: 0x2927 instead
> > >   jffs2: jffs2_scan_eraseblock(): Magic bitmask 0x1985 not found at 0x007232c8: 0xd79d instead
> > >   jffs2: jffs2_scan_eraseblock(): Magic bitmask 0x1985 not found at 0x007232cc: 0xd548 instead
> > >   jffs2: jffs2_scan_eraseblock(): Magic bitmask 0x1985 not found at 0x007232d0: 0x46e3 instead
> > >   jffs2: jffs2_scan_eraseblock(): Magic bitmask 0x1985 not found at 0x007232d4: 0x7716 instead
> > >   jffs2: Further such events for this erase block will not be printed
> > >   jffs2: cannot read OOB for EB at 009e0000, requested 8 bytes, read 0 bytes, error -110
> > >   mount: /mnt: can't read superblock on mtd0.
> > >   bash-5.0# 
> > > 
> > > Note that the failed reads are for different addresses every time. The
> > > CRC errors are there presumably because we don't handle
> > > nand_read_page_op() errors in cafe_nand_read_page().
> > > 
> > > I have no idea what's going on. With the debug trace on it looks like
> > > CAFE_NAND_IRQ_FLASH_RDY is sometimes not flipped on for no apparent
> > > reason:
> > > 
> > >   ...
> > >   instr[0] = CMD(00)
> > >   instr[1] = ADDR(00 00 bd 09 00)
> > >   instr[2] = CMD(30)
> > >   instr[3] = WAITRDY
> > >   instr[4] = DATA_IN(len=2112)
> > >   5: ret=0 status=d0000000 wait=50000000
> > >   instr[0] = CMD(00)
> > >   instr[1] = ADDR(00 00 be 09 00)
> > >   instr[2] = CMD(30)
> > >   instr[3] = WAITRDY
> > >   instr[4] = DATA_IN(len=2112)
> > >   5: ret=0 status=d0000000 wait=50000000
> > >   instr[0] = CMD(00)
> > >   instr[1] = ADDR(00 08 c0 09 00)
> > >   instr[2] = CMD(30)
> > >   instr[3] = WAITRDY
> > >   instr[4] = DATA_IN(len=64)
> > >   5: ret=0 status=d0000000 wait=50000000
> > >   instr[0] = CMD(00)
> > >   instr[1] = ADDR(00 00 ff 09 00)
> > >   instr[2] = CMD(30)
> > >   instr[3] = WAITRDY
> > >   instr[4] = DATA_IN(len=2112)
> > >   5: ret=0 status=d0000000 wait=50000000
> > >   instr[0] = CMD(00)
> > >   instr[1] = ADDR(00 00 fd 09 00)
> > >   instr[2] = CMD(30)
> > >   instr[3] = WAITRDY
> > >   instr[4] = DATA_IN(len=2112)
> > >   5: ret=0 status=d0000000 wait=50000000
> > >   instr[0] = CMD(00)
> > >   instr[1] = ADDR(00 00 fe 09 00)
> > >   instr[2] = CMD(30)
> > >   instr[3] = WAITRDY
> > >   instr[4] = DATA_IN(len=2112)
> > >   5: ret=0 status=d0000000 wait=50000000
> > >   instr[0] = CMD(00)
> > >   instr[1] = ADDR(00 08 00 0a 00)
> > >   instr[2] = CMD(30)
> > >   instr[3] = WAITRDY
> > >   instr[4] = DATA_IN(len=64)
> > >   5: ret=-110 status=90000000 wait=50000000
> > >   jffs2: cannot read OOB for EB at 00500000, requested 8 bytes, read 0 bytes, error -110
> > > 
> > > Indeed, commenting out the CAFE_NAND_IRQ_FLASH_RDY makes things work  
> > 
> > Looks like that happens when you read less than 2k.  
> 
> Not really, there's a successful len=64 insn above. In fact, you've
> provided a clue about what is going on below: the interrupt handler is
> racing with readl_poll_timeout() and sometimes wins, acknowledging the
> CAFE_NAND_IRQ_FLASH_RDY before readl_poll_timeout() can see it.
> 
> This fixes it:
> 
> -       writel(irqs & ~(CAFE_NAND_IRQ_CMD_DONE | CAFE_NAND_IRQ_DMA_DONE),
> +       writel(irqs & ~(CAFE_NAND_IRQ_CMD_DONE | CAFE_NAND_IRQ_DMA_DONE | CAFE_NAND_IRQ_FLASH_RDY),

We really should mask IRQs (AKA disable IRQs in my naming convention
:-)) here, unless we want to switch to interrupt-based waits (which
would be a good thing when we have DMA or WAIT_RDY involved). Having an
interrupt handler in the current implementation doesn't make any sense
(that's assuming the IRQ_STATUS bits are updated even if the interrupts
are disabled, which am not sure is a valid assumption in this case).

> 
> > Can you print the
> > CAFE_NAND_STATUS register in your trace? I suspect
> > CAFE_NAND_STATUS_FLASH_BUSY will be cleared, so maybe it's the way to
> > go if we want to make sure the check Ready/Busy pin status.
> >   
> > > (on a somewhat unrelated note, the waitrdy doesn't seem to be used at
> > > all):  
> > 
> > Yep, I initially thought I would need to poll the NAND_STATUS register
> > and added a boolean to keep track that before realizing there was a bit
> > in the IRQ_STATUS reg.
> >   
> > > 
> > >        case NAND_OP_WAITRDY_INSTR:
> > > 	       // wait |= CAFE_NAND_IRQ_FLASH_RDY;
> > > 	       waitrdy = true;
> > > 	       break;
> > >        }
> > > 
> > > 
> > >   bash-5.0# time mount -t jffs2 mtd0 /mnt
> > >   jffs2: jffs2_scan_dirent_node(): Name CRC failed on node at 0x30212fc8: Read 0x583ccb57, calculated 0x06d03796
> > >   jffs2: notice: (96) jffs2_build_xattr_subsystem: complete building xattr subsystem, 0 of xdatum (0 unchecked, 0 orphan) and 0 of xref (0 dead, 0 orphan) f.
> > >   
> > >   real    5m5.512s
> > >   user    0m0.000s
> > >   sys     0m17.523s
> > >   bash-5.0#
> > > 
> > > The mount time seems to be significantly higher than with mainline,
> > > where it looks more like this:  
> > 
> > Can you add a trace in the IRQ handler (before the "if (!irqs)" check).
> > I interpreted the 'masked' state as 'irq disabled', but maybe that's
> > the opposite, and we're being flood by uncleared 'FLASH_RDY'
> > interrupts. In any case, given we're polling the IRQ_STATUS
> > register, I don't think we need to enable interrupts (unless the
> > status is only updated when the interrupt is enabled).
> > 
> > Using readl_poll_timeout_atomic() instead of readl_poll_timeout() might
> > also help.  
> 
> We've been actually acidentally clearing FLASH_RDY (see above), so I
> don't think that's the case. I'm not seeing an interrupt storm either:

I think it's worth trying to use the atomic version of
readl_poll_timeout(), even if we don't have an interrupt storm here.

> 
>   bash-5.0# grep CAFE /proc/interrupts
>    11:       1469    XT-PIC      CAFE NAND, cafe-ccic, mmc0
>   bash-5.0# time mount -t jffs2 mtd0 /mnt
>   jffs2: jffs2_scan_dirent_node(): Name CRC failed on node at 0x30212fc8: Read 0x583ccb57, calculated 0x06d03796
>   jffs2: notice: (121) jffs2_build_xattr_subsystem: complete building xattr subsystem, 0 of xdatum (0 unchecked, 0 orphan) and 0 of xref (0 dead, 0 orphan) .
>   real    5m5.382s
>   user    0m0.000s
>   sys     0m17.594s
>   bash-5.0# grep CAFE /proc/interrupts
>    11:       1902    XT-PIC      CAFE NAND, cafe-ccic, mmc0
>   bash-5.0#
> 
> I'll try to look more into it, but I suspect the kid is going to wake up
> any time soon, so I won't be able to look into that today.

Hehe, no problem.

> Ideas welcome.

Apart from those I have already mentioned, nope.

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

^ permalink raw reply	[flat|nested] 46+ messages in thread

* Re: [PATCH v2 06/19] mtd: rawnand: cafe: Demistify register fields
       [not found]   ` <20200506204638.GB207924@furthur.local>
@ 2020-05-06 20:53     ` Boris Brezillon
  0 siblings, 0 replies; 46+ messages in thread
From: Boris Brezillon @ 2020-05-06 20:53 UTC (permalink / raw)
  To: Lubomir Rintel
  Cc: Richard Weinberger, Tudor Ambarus, linux-mtd,
	Vignesh Raghavendra, Miquel Raynal

On Wed, 6 May 2020 22:46:38 +0200
Lubomir Rintel <lkundrak@v3.sk> wrote:

> On Tue, May 05, 2020 at 12:13:40PM +0200, Boris Brezillon wrote:
> > The driver has a bunch of magic values. Let's define proper register
> > fields based on the spec [1] and use them.
> > 
> > [1]http://wiki.laptop.org/images/5/5c/88ALP01_Datasheet_July_2007.pdf
> > 
> > Signed-off-by: Boris Brezillon <boris.brezillon@collabora.com>
> > Reviewed-by: Lubomir Rintel <lkundrak@v3.sk>
> > Tested-by: Lubomir Rintel <lkundrak@v3.sk>
> > ---
> > Changes in v2:
> > * Add R-b/T-b
> > * Get rid of unrelated select_chip() change
> > * Fix CE selection logic
> > * s/CAFE_NAND_CTRL2_CMD2/CAFE_NAND_CTRL2_HAS_CMD2/ (Reported by Lubomir)
> > ---
> >  drivers/mtd/nand/raw/cafe_nand.c | 349 ++++++++++++++++++++++++-------
> >  1 file changed, 268 insertions(+), 81 deletions(-)
> > 
> > diff --git a/drivers/mtd/nand/raw/cafe_nand.c b/drivers/mtd/nand/raw/cafe_nand.c
> > index 156a308b530b..7fb5b21aeb00 100644
> > --- a/drivers/mtd/nand/raw/cafe_nand.c
> > +++ b/drivers/mtd/nand/raw/cafe_nand.c  
> ...
> > @@ -604,9 +722,9 @@ static int cafe_nand_attach_chip(struct nand_chip *chip)
> >  	/* Restore the DMA flag */
> >  	cafe->usedma = usedma;
> >  
> > -	cafe->ctl2 = BIT(27); /* Reed-Solomon ECC */
> > -	if (mtd->writesize == 2048)
> > -		cafe->ctl2 |= BIT(29); /* 2KiB page size */
> > +	cafe->ctl2 = CAFE_NAND_CTRL2_ECC_ALG_RS |
> > +		     CAFE_FIELD_PREP(NAND_CTRL2, PAGE_SIZE,
> > +				     mtd->writesize / 512);
> >  
> >  	/* Set up ECC according to the type of chip we found */
> >  	mtd_set_ooblayout(mtd, &cafe_ooblayout_ops);  
> 
> One more thing here. With page size of 2048 B, the old code would set bits
> 29,28 to 2 (10 binary), whereas 2048/512 tries to set 4 (00 binary, MSB
> overflows).
> 
> For 512 B pages, it the page size bits would previously remain zero,
> while with the patch they'd be set to one.
> 
> The old behavior was more like this:
> 
> -       cafe->ctl2 = CAFE_NAND_CTRL2_ECC_ALG_RS |
> -                    CAFE_FIELD_PREP(NAND_CTRL2, PAGE_SIZE,
> -                                    mtd->writesize / 512);

Oops, it was supposed to be 'mtd->writesize / 1024' here. I'll fix that.

> +       cafe->ctl2 = CAFE_NAND_CTRL2_ECC_ALG_RS;
> +       if (mtd->writesize == 2048)
> +               cafe->ctl2 |= CAFE_FIELD_PREP(NAND_CTRL2, PAGE_SIZE, 2);
> 
> That said, I have no idea what difference it makes. I'm still able to
> mount a JFFS2 filesystem from the flash (mine has 2K pages) without any
> trouble.
> 
> Lubo


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

^ permalink raw reply	[flat|nested] 46+ messages in thread

* Re: [PATCH v2 00/19] mtd: rawnand: cafe: Convert to exec_op() (and more)
       [not found]           ` <20200506203635.GA207924@furthur.local>
@ 2020-05-06 20:58             ` Boris Brezillon
  2020-05-06 21:35             ` Boris Brezillon
  1 sibling, 0 replies; 46+ messages in thread
From: Boris Brezillon @ 2020-05-06 20:58 UTC (permalink / raw)
  To: Lubomir Rintel
  Cc: Richard Weinberger, Tudor Ambarus, linux-mtd,
	Vignesh Raghavendra, Miquel Raynal

On Wed, 6 May 2020 22:36:35 +0200
Lubomir Rintel <lkundrak@v3.sk> wrote:

> On Wed, May 06, 2020 at 06:11:53PM +0200, Boris Brezillon wrote:
> > On Wed, 6 May 2020 17:53:59 +0200
> > Lubomir Rintel <lkundrak@v3.sk> wrote:
> >   
> > > On Wed, May 06, 2020 at 08:32:09AM +0200, Boris Brezillon wrote:  
> > > > On Wed, 6 May 2020 00:01:52 +0200
> > > > Lubomir Rintel <lkundrak@v3.sk> wrote:
> > > >     
> > > > > On Tue, May 05, 2020 at 04:46:41PM +0200, Lubomir Rintel wrote:    
> > > > > > On Tue, May 05, 2020 at 12:13:34PM +0200, Boris Brezillon wrote:      
> > > > > > > Hello,
> > > > > > > 
> > > > > > > A bit of context to explain the motivation behind those conversions
> > > > > > > I've been sending for the last couple of weeks. The raw NAND subsystem
> > > > > > > carries a lot of history which makes any rework not only painful, but
> > > > > > > also subject to regressions which we only detect when someone dares to
> > > > > > > update its kernel on one of those ancient HW. While carrying drivers
> > > > > > > for old HW is not a problem per se, carrying ancient and unmaintained
> > > > > > > drivers that are not converted to new APIs is a maintenance burden,
> > > > > > > hence this massive conversion attempt I'm conducting here.
> > > > > > > 
> > > > > > > So here is a series converting the CAFE NAND controller driver to
> > > > > > > exec_op(), plus a bunch of minor improvements done along the way.
> > > > > > > I hope I'll find someone to test those changes, but if there's no one
> > > > > > > still owning OLPC HW or no interest in keeping it supported in recent
> > > > > > > kernel versions, we should definitely consider removing the driver
> > > > > > > instead.
> > > > > > > 
> > > > > > > No major changes in this v2, apart from fixes for things reported by
> > > > > > > Lubomir and Miquel. See the changelog on each patch for more details.
> > > > > > > 
> > > > > > > Regards,
> > > > > > > 
> > > > > > > Boris
> > > > > > > 
> > > > > > > Boris Brezillon (19):
> > > > > > >   mtd: rawnand: Propage CS selection to sub operations
> > > > > > >   mtd: rawnand: cafe: Get rid of an inaccurate kernel doc header
> > > > > > >   mtd: rawnand: cafe: Rename cafe_nand_write_page_lowlevel()
> > > > > > >   mtd: rawnand: cafe: Use a correct ECC mode and pass the ECC alg
> > > > > > >   mtd: rawnand: cafe: Include linux/io.h instead of asm/io.h
> > > > > > >   mtd: rawnand: cafe: Demistify register fields
> > > > > > >   mtd: rawnand: cafe: Factor out the controller initialization logic
> > > > > > >   mtd: rawnand: cafe: Get rid of the debug module param
> > > > > > >   mtd: rawnand: cafe: Use devm_kzalloc and devm_request_irq()
> > > > > > >   mtd: rawnand: cafe: Get rid of a useless label
> > > > > > >   mtd: rawnand: cafe: Explicitly inherit from nand_controller
> > > > > > >   mtd: rawnand: cafe: Don't leave ECC enabled in the write path
> > > > > > >   mtd: rawnand: cafe: Don't split things when reading/writing a page
> > > > > > >   mtd: rawnand: cafe: Add exec_op() support
> > > > > > >   mtd: rawnand: cafe: Get rid of the legacy interface implementation
> > > > > > >   mtd: rawnand: cafe: Adjust the cafe_{read,write}_buf() prototypes
> > > > > > >   mtd: rawnand: cafe: s/uint{8,16,32}_t/u{8,16,32}/
> > > > > > >   mtd: rawnand: cafe: Drop the cafe_{readl,writel}() wrappers
> > > > > > >   mtd: rawnand: cafe: Get rid of the last printk()
> > > > > > > 
> > > > > > >  drivers/mtd/nand/raw/cafe_nand.c | 798 ++++++++++++++++---------------
> > > > > > >  drivers/mtd/nand/raw/nand_base.c |   3 +-
> > > > > > >  include/linux/mtd/rawnand.h      |   2 +
> > > > > > >  3 files changed, 410 insertions(+), 393 deletions(-)      
> > > > > > 
> > > > > > Just confirming that this set works a treat on an OLPC XO-1 laptop,
> > > > > > applied on top of v5.7-rc4.      
> > > > > 
> > > > > Perhaps I spoke too soon. Before I've tested by dumping a couple of pages
> > > > > and checksumming them and it indeed worked fine every time.
> > > > > 
> > > > > Now I've actually tried to mount a JFFS2 filesystem. On v5.7-rc4 it worked:
> > > > > 
> > > > >   bash-5.0# mount -t jffs2 mtd0 /mnt
> > > > >   jffs2: jffs2_scan_dirent_node(): Name CRC failed on node at 0x30212fc8: Read 0x583ccb57, calculated 0x06d03796
> > > > >   jffs2: notice: (96) jffs2_build_xattr_subsystem: complete building xattr subsystem, 0 of xdatum (0 unchecked, 0 orphan) and 0 of xref (0 dead, 0 orphan) f.
> > > > >   bash-5.0# ls /mnt
> > > > >   boot        dev         lost+found  security    versions
> > > > >   boot-alt    home        proc        sys
> > > > >   bash-5.0#
> > > > > 
> > > > > Whereas with the patches applied it does not:
> > > > > 
> > > > >   bash-5.0# mount -t jffs2 mtd0 /mnt
> > > > >   jffs2: cannot read OOB for EB at 00260000, requested 8 bytes, read 0 bytes, error -110
> > > > >   mount: /mnt: can't read superblock on mtd0.
> > > > >   bash-5.0# mount -t jffs2 mtd0 /mnt
> > > > >   jffs2: cannot read OOB for EB at 001c0000, requested 8 bytes, read 0 bytes, error -110
> > > > >   mount: /mnt: can't read superblock on mtd0.
> > > > >   bash-5.0# mount -t jffs2 mtd0 /mnt
> > > > >   jffs2: warning: (102) jffs2_sum_scan_sumnode: Summary node crc error, skipping summary information.
> > > > >   jffs2: jffs2_scan_eraseblock(): Magic bitmask 0x1985 not found at 0x00122a28: 0x15ee instead
> > > > >   jffs2: jffs2_scan_eraseblock(): Magic bitmask 0x1985 not found at 0x00122a2c: 0x4176 instead
> > > > >   jffs2: jffs2_scan_eraseblock(): Magic bitmask 0x1985 not found at 0x00122a30: 0x105d instead
> > > > >   jffs2: jffs2_scan_eraseblock(): Magic bitmask 0x1985 not found at 0x00122a34: 0x13f1 instead
> > > > >   jffs2: jffs2_scan_eraseblock(): Magic bitmask 0x1985 not found at 0x00122a38: 0x7df1 instead
> > > > >   jffs2: jffs2_scan_eraseblock(): Magic bitmask 0x1985 not found at 0x00122a3c: 0xca39 instead
> > > > >   jffs2: jffs2_scan_eraseblock(): Magic bitmask 0x1985 not found at 0x00122a40: 0xe70e instead
> > > > >   jffs2: jffs2_scan_eraseblock(): Magic bitmask 0x1985 not found at 0x00122a44: 0x1004 instead
> > > > >   jffs2: jffs2_scan_eraseblock(): Magic bitmask 0x1985 not found at 0x00122a48: 0x2902 instead
> > > > >   jffs2: jffs2_scan_eraseblock(): Magic bitmask 0x1985 not found at 0x00122a4c: 0x0030 instead
> > > > >   jffs2: Further such events for this erase block will not be printed
> > > > >   jffs2: jffs2_scan_dirent_node(): Name CRC failed on node at 0x001287cc: Read 0x7fea120a, calculated 0x9ceec452
> > > > >   jffs2: jffs2_scan_dirent_node(): Name CRC failed on node at 0x00128fcc: Read 0x7fea120a, calculated 0xb77b2a34
> > > > >   jffs2: warning: (102) jffs2_sum_scan_sumnode: Summary node crc error, skipping summary information.
> > > > >   jffs2: jffs2_scan_eraseblock(): Magic bitmask 0x1985 not found at 0x007232b0: 0xdd29 instead
> > > > >   jffs2: jffs2_scan_eraseblock(): Magic bitmask 0x1985 not found at 0x007232b4: 0xf37e instead
> > > > >   jffs2: jffs2_scan_eraseblock(): Magic bitmask 0x1985 not found at 0x007232b8: 0x251b instead
> > > > >   jffs2: jffs2_scan_eraseblock(): Magic bitmask 0x1985 not found at 0x007232bc: 0xe805 instead
> > > > >   jffs2: jffs2_scan_eraseblock(): Magic bitmask 0x1985 not found at 0x007232c0: 0xd3bf instead
> > > > >   jffs2: jffs2_scan_eraseblock(): Magic bitmask 0x1985 not found at 0x007232c4: 0x2927 instead
> > > > >   jffs2: jffs2_scan_eraseblock(): Magic bitmask 0x1985 not found at 0x007232c8: 0xd79d instead
> > > > >   jffs2: jffs2_scan_eraseblock(): Magic bitmask 0x1985 not found at 0x007232cc: 0xd548 instead
> > > > >   jffs2: jffs2_scan_eraseblock(): Magic bitmask 0x1985 not found at 0x007232d0: 0x46e3 instead
> > > > >   jffs2: jffs2_scan_eraseblock(): Magic bitmask 0x1985 not found at 0x007232d4: 0x7716 instead
> > > > >   jffs2: Further such events for this erase block will not be printed
> > > > >   jffs2: cannot read OOB for EB at 009e0000, requested 8 bytes, read 0 bytes, error -110
> > > > >   mount: /mnt: can't read superblock on mtd0.
> > > > >   bash-5.0# 
> > > > > 
> > > > > Note that the failed reads are for different addresses every time. The
> > > > > CRC errors are there presumably because we don't handle
> > > > > nand_read_page_op() errors in cafe_nand_read_page().
> > > > > 
> > > > > I have no idea what's going on. With the debug trace on it looks like
> > > > > CAFE_NAND_IRQ_FLASH_RDY is sometimes not flipped on for no apparent
> > > > > reason:
> > > > > 
> > > > >   ...
> > > > >   instr[0] = CMD(00)
> > > > >   instr[1] = ADDR(00 00 bd 09 00)
> > > > >   instr[2] = CMD(30)
> > > > >   instr[3] = WAITRDY
> > > > >   instr[4] = DATA_IN(len=2112)
> > > > >   5: ret=0 status=d0000000 wait=50000000
> > > > >   instr[0] = CMD(00)
> > > > >   instr[1] = ADDR(00 00 be 09 00)
> > > > >   instr[2] = CMD(30)
> > > > >   instr[3] = WAITRDY
> > > > >   instr[4] = DATA_IN(len=2112)
> > > > >   5: ret=0 status=d0000000 wait=50000000
> > > > >   instr[0] = CMD(00)
> > > > >   instr[1] = ADDR(00 08 c0 09 00)
> > > > >   instr[2] = CMD(30)
> > > > >   instr[3] = WAITRDY
> > > > >   instr[4] = DATA_IN(len=64)
> > > > >   5: ret=0 status=d0000000 wait=50000000
> > > > >   instr[0] = CMD(00)
> > > > >   instr[1] = ADDR(00 00 ff 09 00)
> > > > >   instr[2] = CMD(30)
> > > > >   instr[3] = WAITRDY
> > > > >   instr[4] = DATA_IN(len=2112)
> > > > >   5: ret=0 status=d0000000 wait=50000000
> > > > >   instr[0] = CMD(00)
> > > > >   instr[1] = ADDR(00 00 fd 09 00)
> > > > >   instr[2] = CMD(30)
> > > > >   instr[3] = WAITRDY
> > > > >   instr[4] = DATA_IN(len=2112)
> > > > >   5: ret=0 status=d0000000 wait=50000000
> > > > >   instr[0] = CMD(00)
> > > > >   instr[1] = ADDR(00 00 fe 09 00)
> > > > >   instr[2] = CMD(30)
> > > > >   instr[3] = WAITRDY
> > > > >   instr[4] = DATA_IN(len=2112)
> > > > >   5: ret=0 status=d0000000 wait=50000000
> > > > >   instr[0] = CMD(00)
> > > > >   instr[1] = ADDR(00 08 00 0a 00)
> > > > >   instr[2] = CMD(30)
> > > > >   instr[3] = WAITRDY
> > > > >   instr[4] = DATA_IN(len=64)
> > > > >   5: ret=-110 status=90000000 wait=50000000
> > > > >   jffs2: cannot read OOB for EB at 00500000, requested 8 bytes, read 0 bytes, error -110
> > > > > 
> > > > > Indeed, commenting out the CAFE_NAND_IRQ_FLASH_RDY makes things work    
> > > > 
> > > > Looks like that happens when you read less than 2k.    
> > > 
> > > Not really, there's a successful len=64 insn above. In fact, you've
> > > provided a clue about what is going on below: the interrupt handler is
> > > racing with readl_poll_timeout() and sometimes wins, acknowledging the
> > > CAFE_NAND_IRQ_FLASH_RDY before readl_poll_timeout() can see it.
> > > 
> > > This fixes it:
> > > 
> > > -       writel(irqs & ~(CAFE_NAND_IRQ_CMD_DONE | CAFE_NAND_IRQ_DMA_DONE),
> > > +       writel(irqs & ~(CAFE_NAND_IRQ_CMD_DONE | CAFE_NAND_IRQ_DMA_DONE | CAFE_NAND_IRQ_FLASH_RDY),  
> > 
> > We really should mask IRQs (AKA disable IRQs in my naming convention
> > :-)) here, unless we want to switch to interrupt-based waits (which
> > would be a good thing when we have DMA or WAIT_RDY involved). Having an
> > interrupt handler in the current implementation doesn't make any sense
> > (that's assuming the IRQ_STATUS bits are updated even if the interrupts
> > are disabled, which am not sure is a valid assumption in this case).  
> 
> I have no idea why the interrupt handler is there. Perhaps some
> interrupts can't be masked and need an ack or something.

According to the code, nope.

> 
> > > > Can you print the
> > > > CAFE_NAND_STATUS register in your trace? I suspect
> > > > CAFE_NAND_STATUS_FLASH_BUSY will be cleared, so maybe it's the way to
> > > > go if we want to make sure the check Ready/Busy pin status.
> > > >     
> > > > > (on a somewhat unrelated note, the waitrdy doesn't seem to be used at
> > > > > all):    
> > > > 
> > > > Yep, I initially thought I would need to poll the NAND_STATUS register
> > > > and added a boolean to keep track that before realizing there was a bit
> > > > in the IRQ_STATUS reg.
> > > >     
> > > > > 
> > > > >        case NAND_OP_WAITRDY_INSTR:
> > > > > 	       // wait |= CAFE_NAND_IRQ_FLASH_RDY;
> > > > > 	       waitrdy = true;
> > > > > 	       break;
> > > > >        }
> > > > > 
> > > > > 
> > > > >   bash-5.0# time mount -t jffs2 mtd0 /mnt
> > > > >   jffs2: jffs2_scan_dirent_node(): Name CRC failed on node at 0x30212fc8: Read 0x583ccb57, calculated 0x06d03796
> > > > >   jffs2: notice: (96) jffs2_build_xattr_subsystem: complete building xattr subsystem, 0 of xdatum (0 unchecked, 0 orphan) and 0 of xref (0 dead, 0 orphan) f.
> > > > >   
> > > > >   real    5m5.512s
> > > > >   user    0m0.000s
> > > > >   sys     0m17.523s
> > > > >   bash-5.0#
> > > > > 
> > > > > The mount time seems to be significantly higher than with mainline,
> > > > > where it looks more like this:    
> > > > 
> > > > Can you add a trace in the IRQ handler (before the "if (!irqs)" check).
> > > > I interpreted the 'masked' state as 'irq disabled', but maybe that's
> > > > the opposite, and we're being flood by uncleared 'FLASH_RDY'
> > > > interrupts. In any case, given we're polling the IRQ_STATUS
> > > > register, I don't think we need to enable interrupts (unless the
> > > > status is only updated when the interrupt is enabled).
> > > > 
> > > > Using readl_poll_timeout_atomic() instead of readl_poll_timeout() might
> > > > also help.    
> > > 
> > > We've been actually acidentally clearing FLASH_RDY (see above), so I
> > > don't think that's the case. I'm not seeing an interrupt storm either:  
> > 
> > I think it's worth trying to use the atomic version of
> > readl_poll_timeout(), even if we don't have an interrupt storm here.  
> 
> That indeed seems to work. With
> s/readl_poll_timeout/readl_poll_timeout_atomic/ the mount time seems the
> same as with the legacy code path:

Okay. I'll try to add support for interrupt-based waits and use it when
waiting for DMA_DONE/WAIT_RDY. Anything else should keep using
polling-based waits.

> 
>   bash-5.0# time mount -t jffs2 mtd0 /mnt
>   jffs2: jffs2_scan_dirent_node(): Name CRC failed on node at 0x30212fc8: Read 0x583ccb57, calculated 0x06d03796
>   jffs2: notice: (96) jffs2_build_xattr_subsystem: complete building xattr subsystem, 0 of xdatum (0 unchecked, 0 orphan) and 0 of xref (0 dead, 0 orphan) f.
>   
>   real    0m7.474s
>   user    0m0.000s
>   sys     0m7.306s
>   bash-5.0#


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

^ permalink raw reply	[flat|nested] 46+ messages in thread

* Re: [PATCH v2 00/19] mtd: rawnand: cafe: Convert to exec_op() (and more)
       [not found]           ` <20200506203635.GA207924@furthur.local>
  2020-05-06 20:58             ` Boris Brezillon
@ 2020-05-06 21:35             ` Boris Brezillon
       [not found]               ` <20200507134708.GA303404@furthur.local>
  1 sibling, 1 reply; 46+ messages in thread
From: Boris Brezillon @ 2020-05-06 21:35 UTC (permalink / raw)
  To: Lubomir Rintel
  Cc: Richard Weinberger, Tudor Ambarus, linux-mtd,
	Vignesh Raghavendra, Miquel Raynal

On Wed, 6 May 2020 22:36:35 +0200
Lubomir Rintel <lkundrak@v3.sk> wrote:

> > We really should mask IRQs (AKA disable IRQs in my naming convention
> > :-)) here, unless we want to switch to interrupt-based waits (which
> > would be a good thing when we have DMA or WAIT_RDY involved). Having an
> > interrupt handler in the current implementation doesn't make any sense
> > (that's assuming the IRQ_STATUS bits are updated even if the interrupts
> > are disabled, which am not sure is a valid assumption in this case).  
> 
> I have no idea why the interrupt handler is there. Perhaps some
> interrupts can't be masked and need an ack or something.

Can you try to set NAND_IRQ_MASK to 0x0 and see if that still works.
Can you also check the number of NAND interrupts when set to 0x0? It's
hard to tell exactly what caused the interrupt handler to be called
since this is a shared interrupt.

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

^ permalink raw reply	[flat|nested] 46+ messages in thread

* Re: [PATCH v2 00/19] mtd: rawnand: cafe: Convert to exec_op() (and more)
       [not found]               ` <20200507134708.GA303404@furthur.local>
@ 2020-05-07 14:11                 ` Boris Brezillon
  2020-05-07 20:12                 ` Boris Brezillon
  1 sibling, 0 replies; 46+ messages in thread
From: Boris Brezillon @ 2020-05-07 14:11 UTC (permalink / raw)
  To: Lubomir Rintel
  Cc: Richard Weinberger, Tudor Ambarus, linux-mtd,
	Vignesh Raghavendra, Miquel Raynal

On Thu, 7 May 2020 15:47:08 +0200
Lubomir Rintel <lkundrak@v3.sk> wrote:

> On Wed, May 06, 2020 at 11:35:52PM +0200, Boris Brezillon wrote:
> > On Wed, 6 May 2020 22:36:35 +0200
> > Lubomir Rintel <lkundrak@v3.sk> wrote:
> >   
> > > > We really should mask IRQs (AKA disable IRQs in my naming convention
> > > > :-)) here, unless we want to switch to interrupt-based waits (which
> > > > would be a good thing when we have DMA or WAIT_RDY involved). Having an
> > > > interrupt handler in the current implementation doesn't make any sense
> > > > (that's assuming the IRQ_STATUS bits are updated even if the interrupts
> > > > are disabled, which am not sure is a valid assumption in this case).    
> > > 
> > > I have no idea why the interrupt handler is there. Perhaps some
> > > interrupts can't be masked and need an ack or something.  
> > 
> > Can you try to set NAND_IRQ_MASK to 0x0 and see if that still works.
> > Can you also check the number of NAND interrupts when set to 0x0? It's
> > hard to tell exactly what caused the interrupt handler to be called
> > since this is a shared interrupt.  
> 
> When it's set to 0, I get an interrupt with CAFE_NAND_IRQ=0x40000000
> (CAFE_NAND_IRQ_FLASH_RDY) right off the bat. That doesn't happen with
> a mask of 0xffffffff.
> 
> When changing the handler to always ack CAFE_NAND_IRQ_FLASH_RDY I've
> also seen CAFE_NAND_IRQ=0x80000000 (CAFE_NAND_IRQ_CMD_DONE) suggesting
> that other interrupts aren't masked either.
> 
> It seems to be that ones indeed mask interrupts but just can't be
> masked (CAFE_NAND_IRQ_CMD_DONE or CAFE_NAND_IRQ_DMA_DONE), perhaps
> due to hardware bugs.

I suspect the interrupts you receive when all NAND irqs are masked come
from the CCIC (Camera Sensor) or SDIO controller which are part of
88ALP01. This should actually be modeled as an interrupt controller
dispatching interrupts to sub-devices so we don't have those spurious
interrupts reaching the NAND IRQ handler, but that implies a lot of
changes which I'm not ready to do :-). So I'll just do as you suggest
and avoid clearing the FLASH_RDY IRQ in the handler.

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

^ permalink raw reply	[flat|nested] 46+ messages in thread

* Re: [PATCH v2 00/19] mtd: rawnand: cafe: Convert to exec_op() (and more)
       [not found]               ` <20200507134708.GA303404@furthur.local>
  2020-05-07 14:11                 ` Boris Brezillon
@ 2020-05-07 20:12                 ` Boris Brezillon
       [not found]                   ` <20200509193440.GA524772@furthur.local>
  1 sibling, 1 reply; 46+ messages in thread
From: Boris Brezillon @ 2020-05-07 20:12 UTC (permalink / raw)
  To: Lubomir Rintel
  Cc: Richard Weinberger, Tudor Ambarus, linux-mtd,
	Vignesh Raghavendra, Miquel Raynal

On Thu, 7 May 2020 15:47:08 +0200
Lubomir Rintel <lkundrak@v3.sk> wrote:

> On Wed, May 06, 2020 at 11:35:52PM +0200, Boris Brezillon wrote:
> > On Wed, 6 May 2020 22:36:35 +0200
> > Lubomir Rintel <lkundrak@v3.sk> wrote:
> >   
> > > > We really should mask IRQs (AKA disable IRQs in my naming convention
> > > > :-)) here, unless we want to switch to interrupt-based waits (which
> > > > would be a good thing when we have DMA or WAIT_RDY involved). Having an
> > > > interrupt handler in the current implementation doesn't make any sense
> > > > (that's assuming the IRQ_STATUS bits are updated even if the interrupts
> > > > are disabled, which am not sure is a valid assumption in this case).    
> > > 
> > > I have no idea why the interrupt handler is there. Perhaps some
> > > interrupts can't be masked and need an ack or something.  
> > 
> > Can you try to set NAND_IRQ_MASK to 0x0 and see if that still works.
> > Can you also check the number of NAND interrupts when set to 0x0? It's
> > hard to tell exactly what caused the interrupt handler to be called
> > since this is a shared interrupt.  
> 
> When it's set to 0, I get an interrupt with CAFE_NAND_IRQ=0x40000000
> (CAFE_NAND_IRQ_FLASH_RDY) right off the bat. That doesn't happen with
> a mask of 0xffffffff.
> 
> When changing the handler to always ack CAFE_NAND_IRQ_FLASH_RDY I've
> also seen CAFE_NAND_IRQ=0x80000000 (CAFE_NAND_IRQ_CMD_DONE) suggesting
> that other interrupts aren't masked either.
> 
> It seems to be that ones indeed mask interrupts but just can't be
> masked (CAFE_NAND_IRQ_CMD_DONE or CAFE_NAND_IRQ_DMA_DONE), perhaps
> due to hardware bugs.
> 

I pushed a new version with some interrupt-related changes [1].

[1]https://github.com/bbrezillon/linux/commits/nand/cafe-nand-exec-op-debug


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

^ permalink raw reply	[flat|nested] 46+ messages in thread

* Re: [PATCH v2 00/19] mtd: rawnand: cafe: Convert to exec_op() (and more)
       [not found]                   ` <20200509193440.GA524772@furthur.local>
@ 2020-05-09 20:01                     ` Boris Brezillon
       [not found]                       ` <20200509202855.GB524772@furthur.local>
  0 siblings, 1 reply; 46+ messages in thread
From: Boris Brezillon @ 2020-05-09 20:01 UTC (permalink / raw)
  To: Lubomir Rintel
  Cc: Richard Weinberger, Tudor Ambarus, linux-mtd,
	Vignesh Raghavendra, Miquel Raynal

On Sat, 9 May 2020 21:34:40 +0200
Lubomir Rintel <lkundrak@v3.sk> wrote:

> On Thu, May 07, 2020 at 10:12:57PM +0200, Boris Brezillon wrote:
> > On Thu, 7 May 2020 15:47:08 +0200
> > Lubomir Rintel <lkundrak@v3.sk> wrote:
> >   
> > > On Wed, May 06, 2020 at 11:35:52PM +0200, Boris Brezillon wrote:  
> > > > On Wed, 6 May 2020 22:36:35 +0200
> > > > Lubomir Rintel <lkundrak@v3.sk> wrote:
> > > >     
> > > > > > We really should mask IRQs (AKA disable IRQs in my naming convention
> > > > > > :-)) here, unless we want to switch to interrupt-based waits (which
> > > > > > would be a good thing when we have DMA or WAIT_RDY involved). Having an
> > > > > > interrupt handler in the current implementation doesn't make any sense
> > > > > > (that's assuming the IRQ_STATUS bits are updated even if the interrupts
> > > > > > are disabled, which am not sure is a valid assumption in this case).      
> > > > > 
> > > > > I have no idea why the interrupt handler is there. Perhaps some
> > > > > interrupts can't be masked and need an ack or something.    
> > > > 
> > > > Can you try to set NAND_IRQ_MASK to 0x0 and see if that still works.
> > > > Can you also check the number of NAND interrupts when set to 0x0? It's
> > > > hard to tell exactly what caused the interrupt handler to be called
> > > > since this is a shared interrupt.    
> > > 
> > > When it's set to 0, I get an interrupt with CAFE_NAND_IRQ=0x40000000
> > > (CAFE_NAND_IRQ_FLASH_RDY) right off the bat. That doesn't happen with
> > > a mask of 0xffffffff.
> > > 
> > > When changing the handler to always ack CAFE_NAND_IRQ_FLASH_RDY I've
> > > also seen CAFE_NAND_IRQ=0x80000000 (CAFE_NAND_IRQ_CMD_DONE) suggesting
> > > that other interrupts aren't masked either.
> > > 
> > > It seems to be that ones indeed mask interrupts but just can't be
> > > masked (CAFE_NAND_IRQ_CMD_DONE or CAFE_NAND_IRQ_DMA_DONE), perhaps
> > > due to hardware bugs.
> > >   
> > 
> > I pushed a new version with some interrupt-related changes [1].
> > 
> > [1]https://github.com/bbrezillon/linux/commits/nand/cafe-nand-exec-op-debug  
> 
> Works with one fix:
> 
> diff --git a/drivers/mtd/nand/raw/cafe_nand.c b/drivers/mtd/nand/raw/cafe_nand.c
> index 591d79730961..e37737b7b089 100644
> --- a/drivers/mtd/nand/raw/cafe_nand.c
> +++ b/drivers/mtd/nand/raw/cafe_nand.c
> @@ -801,6 +801,7 @@ static int cafe_nand_probe(struct pci_dev *pdev,
>         if (!cafe)
>                 return  -ENOMEM;
>  
> +       init_completion(&cafe->complete);

Oops, indeed.

>         mtd = nand_to_mtd(&cafe->nand);
>         mtd->dev.parent = &pdev->dev;
>         nand_set_controller_data(&cafe->nand, cafe);
> 
> However, the mount JFFS2 mount takes about twice as long as it did with
> the polling version:

Yes, that's not surprising. At the same time, using atomic-polling for
something that's expected to take hundreds of microseconds is not that
great. That means your CPU is not doing anything useful while you wait
for the read/write/erase operation to finish.

> 
>   bash-5.0# time mount -t jffs2 mtd0 /mnt
>   jffs2: jffs2_scan_dirent_node(): Name CRC failed on node at 0x30212fc8: Read 0x583ccb57, calculated 0x06d03796
>   jffs2: notice: (96) jffs2_build_xattr_subsystem: complete building xattr subsystem, 0 of xdatum (0 unchecked, 0 orphan) and 0 of xref (0 dead, 0 orphan) f.
>   
>   real    0m15.374s

Given the time it takes to mount the FS, I'd recommend considering
switching to UBI/UBIFS, but maybe that's not an option here.

>   user    0m0.000s
>   sys     0m9.727s
> 
> Lubo


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

^ permalink raw reply	[flat|nested] 46+ messages in thread

* Re: [PATCH v2 00/19] mtd: rawnand: cafe: Convert to exec_op() (and more)
       [not found]                       ` <20200509202855.GB524772@furthur.local>
@ 2020-05-10  6:31                         ` Boris Brezillon
  2020-05-10  6:45                           ` Boris Brezillon
  0 siblings, 1 reply; 46+ messages in thread
From: Boris Brezillon @ 2020-05-10  6:31 UTC (permalink / raw)
  To: Lubomir Rintel
  Cc: Richard Weinberger, Tudor Ambarus, linux-mtd,
	Vignesh Raghavendra, Miquel Raynal

On Sat, 9 May 2020 22:28:55 +0200
Lubomir Rintel <lkundrak@v3.sk> wrote:

> On Sat, May 09, 2020 at 10:01:02PM +0200, Boris Brezillon wrote:
> > On Sat, 9 May 2020 21:34:40 +0200
> > Lubomir Rintel <lkundrak@v3.sk> wrote:
> >   
> > > On Thu, May 07, 2020 at 10:12:57PM +0200, Boris Brezillon wrote:  
> > > > On Thu, 7 May 2020 15:47:08 +0200
> > > > Lubomir Rintel <lkundrak@v3.sk> wrote:
> > > >     
> > > > > On Wed, May 06, 2020 at 11:35:52PM +0200, Boris Brezillon wrote:    
> > > > > > On Wed, 6 May 2020 22:36:35 +0200
> > > > > > Lubomir Rintel <lkundrak@v3.sk> wrote:
> > > > > >       
> > > > > > > > We really should mask IRQs (AKA disable IRQs in my naming convention
> > > > > > > > :-)) here, unless we want to switch to interrupt-based waits (which
> > > > > > > > would be a good thing when we have DMA or WAIT_RDY involved). Having an
> > > > > > > > interrupt handler in the current implementation doesn't make any sense
> > > > > > > > (that's assuming the IRQ_STATUS bits are updated even if the interrupts
> > > > > > > > are disabled, which am not sure is a valid assumption in this case).        
> > > > > > > 
> > > > > > > I have no idea why the interrupt handler is there. Perhaps some
> > > > > > > interrupts can't be masked and need an ack or something.      
> > > > > > 
> > > > > > Can you try to set NAND_IRQ_MASK to 0x0 and see if that still works.
> > > > > > Can you also check the number of NAND interrupts when set to 0x0? It's
> > > > > > hard to tell exactly what caused the interrupt handler to be called
> > > > > > since this is a shared interrupt.      
> > > > > 
> > > > > When it's set to 0, I get an interrupt with CAFE_NAND_IRQ=0x40000000
> > > > > (CAFE_NAND_IRQ_FLASH_RDY) right off the bat. That doesn't happen with
> > > > > a mask of 0xffffffff.
> > > > > 
> > > > > When changing the handler to always ack CAFE_NAND_IRQ_FLASH_RDY I've
> > > > > also seen CAFE_NAND_IRQ=0x80000000 (CAFE_NAND_IRQ_CMD_DONE) suggesting
> > > > > that other interrupts aren't masked either.
> > > > > 
> > > > > It seems to be that ones indeed mask interrupts but just can't be
> > > > > masked (CAFE_NAND_IRQ_CMD_DONE or CAFE_NAND_IRQ_DMA_DONE), perhaps
> > > > > due to hardware bugs.
> > > > >     
> > > > 
> > > > I pushed a new version with some interrupt-related changes [1].
> > > > 
> > > > [1]https://github.com/bbrezillon/linux/commits/nand/cafe-nand-exec-op-debug    
> > > 
> > > Works with one fix:
> > > 
> > > diff --git a/drivers/mtd/nand/raw/cafe_nand.c b/drivers/mtd/nand/raw/cafe_nand.c
> > > index 591d79730961..e37737b7b089 100644
> > > --- a/drivers/mtd/nand/raw/cafe_nand.c
> > > +++ b/drivers/mtd/nand/raw/cafe_nand.c
> > > @@ -801,6 +801,7 @@ static int cafe_nand_probe(struct pci_dev *pdev,
> > >         if (!cafe)
> > >                 return  -ENOMEM;
> > >  
> > > +       init_completion(&cafe->complete);  
> > 
> > Oops, indeed.
> >   
> > >         mtd = nand_to_mtd(&cafe->nand);
> > >         mtd->dev.parent = &pdev->dev;
> > >         nand_set_controller_data(&cafe->nand, cafe);
> > > 
> > > However, the mount JFFS2 mount takes about twice as long as it did with
> > > the polling version:  
> > 
> > Yes, that's not surprising. At the same time, using atomic-polling for
> > something that's expected to take hundreds of microseconds is not that
> > great. That means your CPU is not doing anything useful while you wait
> > for the read/write/erase operation to finish.  
> 
> Yes. But this really is too much of a slowdown:
> 
>   bash-5.0# time dd count=65536 bs=2k if=/dev/mtd0 of=/dev/null
>   65536+0 records in
>   65536+0 records out
>   
>   real    0m20.191s
>   user    0m0.346s
>   sys     0m10.366s
> 
> vs (previously):
>   
>   bash-5.0# time dd count=65536 bs=2k if=/dev/mtd0 of=/dev/null
>   65536+0 records in
>   65536+0 records out
>   
>   real    0m7.629s
>   user    0m0.010s
>   sys     0m7.500s
>   bash-5.0#

Almost a factor 3. I was definitely not expecting interrupt-based waits
to have such a huge impact on the perfs.

> 
> Note that your CPU can't be doing anything useful before the program and
> its data is loaded from the storage :)

Well, that's only true at mount time (and if you delay the mount after
the boot, your CPU might already have other things to do), but any
erase/write operations are likely to monopolize your CPU for no good
reason.

> 
> I suppose that if someone really prefers to avoid hogging the CPU at
> this cost, then it makes sense to add a knob (a module parameter or
> something) that would enable the interrupt-driven operation, but
> keep polling as a default.

Let's not add more module params than we already have, it just
confuses users and deciding how to wait on HW events doesn't sounds
like something they should be able to choose anyway (just like passing
the timing params, this should be calculated by the driver). Oh well,
I'll drop the patch adding interrupt-based waits. Having the driver
converted to exec_op() is more than enough :-).

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

^ permalink raw reply	[flat|nested] 46+ messages in thread

* Re: [PATCH v2 00/19] mtd: rawnand: cafe: Convert to exec_op() (and more)
  2020-05-10  6:31                         ` Boris Brezillon
@ 2020-05-10  6:45                           ` Boris Brezillon
       [not found]                             ` <20200510072108.GA587379@furthur.local>
  0 siblings, 1 reply; 46+ messages in thread
From: Boris Brezillon @ 2020-05-10  6:45 UTC (permalink / raw)
  To: Lubomir Rintel
  Cc: Richard Weinberger, Tudor Ambarus, linux-mtd,
	Vignesh Raghavendra, Miquel Raynal

On Sun, 10 May 2020 08:31:05 +0200
Boris Brezillon <boris.brezillon@collabora.com> wrote:

> On Sat, 9 May 2020 22:28:55 +0200
> Lubomir Rintel <lkundrak@v3.sk> wrote:
> 
> > On Sat, May 09, 2020 at 10:01:02PM +0200, Boris Brezillon wrote:  
> > > On Sat, 9 May 2020 21:34:40 +0200
> > > Lubomir Rintel <lkundrak@v3.sk> wrote:
> > >     
> > > > On Thu, May 07, 2020 at 10:12:57PM +0200, Boris Brezillon wrote:    
> > > > > On Thu, 7 May 2020 15:47:08 +0200
> > > > > Lubomir Rintel <lkundrak@v3.sk> wrote:
> > > > >       
> > > > > > On Wed, May 06, 2020 at 11:35:52PM +0200, Boris Brezillon wrote:      
> > > > > > > On Wed, 6 May 2020 22:36:35 +0200
> > > > > > > Lubomir Rintel <lkundrak@v3.sk> wrote:
> > > > > > >         
> > > > > > > > > We really should mask IRQs (AKA disable IRQs in my naming convention
> > > > > > > > > :-)) here, unless we want to switch to interrupt-based waits (which
> > > > > > > > > would be a good thing when we have DMA or WAIT_RDY involved). Having an
> > > > > > > > > interrupt handler in the current implementation doesn't make any sense
> > > > > > > > > (that's assuming the IRQ_STATUS bits are updated even if the interrupts
> > > > > > > > > are disabled, which am not sure is a valid assumption in this case).          
> > > > > > > > 
> > > > > > > > I have no idea why the interrupt handler is there. Perhaps some
> > > > > > > > interrupts can't be masked and need an ack or something.        
> > > > > > > 
> > > > > > > Can you try to set NAND_IRQ_MASK to 0x0 and see if that still works.
> > > > > > > Can you also check the number of NAND interrupts when set to 0x0? It's
> > > > > > > hard to tell exactly what caused the interrupt handler to be called
> > > > > > > since this is a shared interrupt.        
> > > > > > 
> > > > > > When it's set to 0, I get an interrupt with CAFE_NAND_IRQ=0x40000000
> > > > > > (CAFE_NAND_IRQ_FLASH_RDY) right off the bat. That doesn't happen with
> > > > > > a mask of 0xffffffff.
> > > > > > 
> > > > > > When changing the handler to always ack CAFE_NAND_IRQ_FLASH_RDY I've
> > > > > > also seen CAFE_NAND_IRQ=0x80000000 (CAFE_NAND_IRQ_CMD_DONE) suggesting
> > > > > > that other interrupts aren't masked either.
> > > > > > 
> > > > > > It seems to be that ones indeed mask interrupts but just can't be
> > > > > > masked (CAFE_NAND_IRQ_CMD_DONE or CAFE_NAND_IRQ_DMA_DONE), perhaps
> > > > > > due to hardware bugs.
> > > > > >       
> > > > > 
> > > > > I pushed a new version with some interrupt-related changes [1].
> > > > > 
> > > > > [1]https://github.com/bbrezillon/linux/commits/nand/cafe-nand-exec-op-debug      
> > > > 
> > > > Works with one fix:
> > > > 
> > > > diff --git a/drivers/mtd/nand/raw/cafe_nand.c b/drivers/mtd/nand/raw/cafe_nand.c
> > > > index 591d79730961..e37737b7b089 100644
> > > > --- a/drivers/mtd/nand/raw/cafe_nand.c
> > > > +++ b/drivers/mtd/nand/raw/cafe_nand.c
> > > > @@ -801,6 +801,7 @@ static int cafe_nand_probe(struct pci_dev *pdev,
> > > >         if (!cafe)
> > > >                 return  -ENOMEM;
> > > >  
> > > > +       init_completion(&cafe->complete);    
> > > 
> > > Oops, indeed.
> > >     
> > > >         mtd = nand_to_mtd(&cafe->nand);
> > > >         mtd->dev.parent = &pdev->dev;
> > > >         nand_set_controller_data(&cafe->nand, cafe);
> > > > 
> > > > However, the mount JFFS2 mount takes about twice as long as it did with
> > > > the polling version:    
> > > 
> > > Yes, that's not surprising. At the same time, using atomic-polling for
> > > something that's expected to take hundreds of microseconds is not that
> > > great. That means your CPU is not doing anything useful while you wait
> > > for the read/write/erase operation to finish.    
> > 
> > Yes. But this really is too much of a slowdown:
> > 
> >   bash-5.0# time dd count=65536 bs=2k if=/dev/mtd0 of=/dev/null
> >   65536+0 records in
> >   65536+0 records out
> >   
> >   real    0m20.191s
> >   user    0m0.346s
> >   sys     0m10.366s
> > 
> > vs (previously):
> >   
> >   bash-5.0# time dd count=65536 bs=2k if=/dev/mtd0 of=/dev/null
> >   65536+0 records in
> >   65536+0 records out
> >   
> >   real    0m7.629s
> >   user    0m0.010s
> >   sys     0m7.500s
> >   bash-5.0#  
> 
> Almost a factor 3. I was definitely not expecting interrupt-based waits
> to have such a huge impact on the perfs.
> 
> > 
> > Note that your CPU can't be doing anything useful before the program and
> > its data is loaded from the storage :)  
> 
> Well, that's only true at mount time (and if you delay the mount after
> the boot, your CPU might already have other things to do), but any
> erase/write operations are likely to monopolize your CPU for no good
> reason.
> 
> > 
> > I suppose that if someone really prefers to avoid hogging the CPU at
> > this cost, then it makes sense to add a knob (a module parameter or
> > something) that would enable the interrupt-driven operation, but
> > keep polling as a default.  
> 
> Let's not add more module params than we already have, it just
> confuses users and deciding how to wait on HW events doesn't sounds
> like something they should be able to choose anyway (just like passing
> the timing params, this should be calculated by the driver). Oh well,
> I'll drop the patch adding interrupt-based waits. Having the driver
> converted to exec_op() is more than enough :-).

Just pushed a new version. If it works for you I'll send a v3.

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

^ permalink raw reply	[flat|nested] 46+ messages in thread

* Re: [PATCH v2 00/19] mtd: rawnand: cafe: Convert to exec_op() (and more)
       [not found]                             ` <20200510072108.GA587379@furthur.local>
@ 2020-05-10  7:35                               ` Boris Brezillon
  2020-05-11  8:23                                 ` Boris Brezillon
  0 siblings, 1 reply; 46+ messages in thread
From: Boris Brezillon @ 2020-05-10  7:35 UTC (permalink / raw)
  To: Lubomir Rintel
  Cc: Richard Weinberger, Tudor Ambarus, linux-mtd,
	Vignesh Raghavendra, Miquel Raynal

On Sun, 10 May 2020 09:21:08 +0200
Lubomir Rintel <lkundrak@v3.sk> wrote:

> On Sun, May 10, 2020 at 08:45:41AM +0200, Boris Brezillon wrote:
> > On Sun, 10 May 2020 08:31:05 +0200
> > Boris Brezillon <boris.brezillon@collabora.com> wrote:
> >   
> > > On Sat, 9 May 2020 22:28:55 +0200
> > > Lubomir Rintel <lkundrak@v3.sk> wrote:
> > >   
> > > > On Sat, May 09, 2020 at 10:01:02PM +0200, Boris Brezillon wrote:    
> > > > > On Sat, 9 May 2020 21:34:40 +0200
> > > > > Lubomir Rintel <lkundrak@v3.sk> wrote:
> > > > >       
> > > > > > On Thu, May 07, 2020 at 10:12:57PM +0200, Boris Brezillon wrote:      
> > > > > > > On Thu, 7 May 2020 15:47:08 +0200
> > > > > > > Lubomir Rintel <lkundrak@v3.sk> wrote:
> > > > > > >         
> > > > > > > > On Wed, May 06, 2020 at 11:35:52PM +0200, Boris Brezillon wrote:        
> > > > > > > > > On Wed, 6 May 2020 22:36:35 +0200
> > > > > > > > > Lubomir Rintel <lkundrak@v3.sk> wrote:
> > > > > > > > >           
> > > > > > > > > > > We really should mask IRQs (AKA disable IRQs in my naming convention
> > > > > > > > > > > :-)) here, unless we want to switch to interrupt-based waits (which
> > > > > > > > > > > would be a good thing when we have DMA or WAIT_RDY involved). Having an
> > > > > > > > > > > interrupt handler in the current implementation doesn't make any sense
> > > > > > > > > > > (that's assuming the IRQ_STATUS bits are updated even if the interrupts
> > > > > > > > > > > are disabled, which am not sure is a valid assumption in this case).            
> > > > > > > > > > 
> > > > > > > > > > I have no idea why the interrupt handler is there. Perhaps some
> > > > > > > > > > interrupts can't be masked and need an ack or something.          
> > > > > > > > > 
> > > > > > > > > Can you try to set NAND_IRQ_MASK to 0x0 and see if that still works.
> > > > > > > > > Can you also check the number of NAND interrupts when set to 0x0? It's
> > > > > > > > > hard to tell exactly what caused the interrupt handler to be called
> > > > > > > > > since this is a shared interrupt.          
> > > > > > > > 
> > > > > > > > When it's set to 0, I get an interrupt with CAFE_NAND_IRQ=0x40000000
> > > > > > > > (CAFE_NAND_IRQ_FLASH_RDY) right off the bat. That doesn't happen with
> > > > > > > > a mask of 0xffffffff.
> > > > > > > > 
> > > > > > > > When changing the handler to always ack CAFE_NAND_IRQ_FLASH_RDY I've
> > > > > > > > also seen CAFE_NAND_IRQ=0x80000000 (CAFE_NAND_IRQ_CMD_DONE) suggesting
> > > > > > > > that other interrupts aren't masked either.
> > > > > > > > 
> > > > > > > > It seems to be that ones indeed mask interrupts but just can't be
> > > > > > > > masked (CAFE_NAND_IRQ_CMD_DONE or CAFE_NAND_IRQ_DMA_DONE), perhaps
> > > > > > > > due to hardware bugs.
> > > > > > > >         
> > > > > > > 
> > > > > > > I pushed a new version with some interrupt-related changes [1].
> > > > > > > 
> > > > > > > [1]https://github.com/bbrezillon/linux/commits/nand/cafe-nand-exec-op-debug        
> > > > > > 
> > > > > > Works with one fix:
> > > > > > 
> > > > > > diff --git a/drivers/mtd/nand/raw/cafe_nand.c b/drivers/mtd/nand/raw/cafe_nand.c
> > > > > > index 591d79730961..e37737b7b089 100644
> > > > > > --- a/drivers/mtd/nand/raw/cafe_nand.c
> > > > > > +++ b/drivers/mtd/nand/raw/cafe_nand.c
> > > > > > @@ -801,6 +801,7 @@ static int cafe_nand_probe(struct pci_dev *pdev,
> > > > > >         if (!cafe)
> > > > > >                 return  -ENOMEM;
> > > > > >  
> > > > > > +       init_completion(&cafe->complete);      
> > > > > 
> > > > > Oops, indeed.
> > > > >       
> > > > > >         mtd = nand_to_mtd(&cafe->nand);
> > > > > >         mtd->dev.parent = &pdev->dev;
> > > > > >         nand_set_controller_data(&cafe->nand, cafe);
> > > > > > 
> > > > > > However, the mount JFFS2 mount takes about twice as long as it did with
> > > > > > the polling version:      
> > > > > 
> > > > > Yes, that's not surprising. At the same time, using atomic-polling for
> > > > > something that's expected to take hundreds of microseconds is not that
> > > > > great. That means your CPU is not doing anything useful while you wait
> > > > > for the read/write/erase operation to finish.      
> > > > 
> > > > Yes. But this really is too much of a slowdown:
> > > > 
> > > >   bash-5.0# time dd count=65536 bs=2k if=/dev/mtd0 of=/dev/null
> > > >   65536+0 records in
> > > >   65536+0 records out
> > > >   
> > > >   real    0m20.191s
> > > >   user    0m0.346s
> > > >   sys     0m10.366s
> > > > 
> > > > vs (previously):
> > > >   
> > > >   bash-5.0# time dd count=65536 bs=2k if=/dev/mtd0 of=/dev/null
> > > >   65536+0 records in
> > > >   65536+0 records out
> > > >   
> > > >   real    0m7.629s
> > > >   user    0m0.010s
> > > >   sys     0m7.500s
> > > >   bash-5.0#    
> > > 
> > > Almost a factor 3. I was definitely not expecting interrupt-based waits
> > > to have such a huge impact on the perfs.
> > >   
> > > > 
> > > > Note that your CPU can't be doing anything useful before the program and
> > > > its data is loaded from the storage :)    
> > > 
> > > Well, that's only true at mount time (and if you delay the mount after
> > > the boot, your CPU might already have other things to do), but any
> > > erase/write operations are likely to monopolize your CPU for no good
> > > reason.
> > >   
> > > > 
> > > > I suppose that if someone really prefers to avoid hogging the CPU at
> > > > this cost, then it makes sense to add a knob (a module parameter or
> > > > something) that would enable the interrupt-driven operation, but
> > > > keep polling as a default.    
> > > 
> > > Let's not add more module params than we already have, it just
> > > confuses users and deciding how to wait on HW events doesn't sounds
> > > like something they should be able to choose anyway (just like passing
> > > the timing params, this should be calculated by the driver). Oh well,
> > > I'll drop the patch adding interrupt-based waits. Having the driver
> > > converted to exec_op() is more than enough :-).  
> > 
> > Just pushed a new version. If it works for you I'll send a v3.  
> 
> Thank you. That's b6b10b45dd9 in nand/cafe-nand-exec-op-debug of
> https://github.com/bbrezillon/linux/ I suppose?
> 
> Without the readl_poll_timeout() -> readl_poll_timeout_atomic() change
> it's still very slow.

Should be fixed now.

> 
> Also, commit f89355b6b6 ("mtd: rawnand: cafe: Return IRQ_HANDLED when
> appropriate") looks somewhat suspicious to me. Previously it wrote the
> pending interrupt bits back into CAFE_NAND_IRQ, now you're masking them
> out in CAFE_NAND_IRQ_MASK (which already should be 0xffffffff) at this
> point. Why?

If interrupts are masked we don't need to clear them. We only clear
them before executing an operation to start from a fresh state.

> I thought the write back to CAFE_NAND_IRQ serves to ack the
> interrupts that came up but we don't handle elsewhere because we weren't
> expecting them.

If we reach the handler and all our irqs are masked, that means the irq
was not for us, which is possible since the irq line is shared. We
really should to return IRQ_NONE in that case, and clearing pending
interrupts is useless, since they are masked anyway. Since we read
the interrupt status from exec_op(), I thought it'd be better to never
clear any interrupt bits instead of clearing all bits but the CMD_DONE,
DMA_DONE and FLASH_RDY.

> 
> As you correctly pointed out; the source of the interrupts I'm seeing
> could be something else than the CAFE chip -- the camera or the MMC
> card. I'm not sure though; camera is certainly off and there shouldn't
> be much going on about the MMC card. I'm testing with a init=/bin/bash
> installation off a SD-card currently. I guess I can try switching to the
> USB flash stick and disable the camera and MMC altogether.

Okay, if that happens that would be a HW bug (or an interrupt coming
from somewhere else, maybe PCI errors?)? Can you print the values of
CAFE_GLOBAL_IRQ and CAFE_GLOBAL_IRQ_MASK in your irq handler?

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

^ permalink raw reply	[flat|nested] 46+ messages in thread

* Re: [PATCH v2 19/19] mtd: rawnand: cafe: Get rid of the last printk()
  2020-05-05 10:13 ` [PATCH v2 19/19] mtd: rawnand: cafe: Get rid of the last printk() Boris Brezillon
@ 2020-05-10 21:43   ` Miquel Raynal
  0 siblings, 0 replies; 46+ messages in thread
From: Miquel Raynal @ 2020-05-10 21:43 UTC (permalink / raw)
  To: Boris Brezillon
  Cc: Lubomir Rintel, Tudor Ambarus, linux-mtd, Vignesh Raghavendra,
	Richard Weinberger

Hi Boris,

Boris Brezillon <boris.brezillon@collabora.com> wrote on Tue,  5 May
2020 12:13:53 +0200:

> Replace the last printk() by a dev_dbg().
> 
> Signed-off-by: Boris Brezillon <boris.brezillon@collabora.com>
> ---

Reviewed-by: Miquel Raynal <miquel.raynal@bootlin.com>

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

^ permalink raw reply	[flat|nested] 46+ messages in thread

* Re: [PATCH v2 18/19] mtd: rawnand: cafe: Drop the cafe_{readl,writel}() wrappers
  2020-05-05 10:13 ` [PATCH v2 18/19] mtd: rawnand: cafe: Drop the cafe_{readl, writel}() wrappers Boris Brezillon
@ 2020-05-10 21:45   ` Miquel Raynal
  0 siblings, 0 replies; 46+ messages in thread
From: Miquel Raynal @ 2020-05-10 21:45 UTC (permalink / raw)
  To: Boris Brezillon
  Cc: Lubomir Rintel, Tudor Ambarus, linux-mtd, Vignesh Raghavendra,
	Richard Weinberger


Boris Brezillon <boris.brezillon@collabora.com> wrote on Tue,  5 May
2020 12:13:52 +0200:

> Given how long this driver has been there we can safely assume that
> nobody cares about PIO support. Getting rid of these macros allows for
> easy register name greping.
> 
> Signed-off-by: Boris Brezillon <boris.brezillon@collabora.com>
> Suggested-by: Lubomir Rintel <lkundrak@v3.sk>
> ---
> Changes in v2:
> * New patch
> ---

I don't understand the need for this kind of macro really...

Reviewed-by: Miquel Raynal <miquel.raynal@bootlin.com>

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

^ permalink raw reply	[flat|nested] 46+ messages in thread

* Re: [PATCH v2 13/19] mtd: rawnand: cafe: Don't split things when reading/writing a page
  2020-05-05 10:13 ` [PATCH v2 13/19] mtd: rawnand: cafe: Don't split things when reading/writing a page Boris Brezillon
@ 2020-05-10 21:49   ` Miquel Raynal
  0 siblings, 0 replies; 46+ messages in thread
From: Miquel Raynal @ 2020-05-10 21:49 UTC (permalink / raw)
  To: Boris Brezillon
  Cc: Lubomir Rintel, Tudor Ambarus, linux-mtd, Vignesh Raghavendra,
	Richard Weinberger


Boris Brezillon <boris.brezillon@collabora.com> wrote on Tue,  5 May
2020 12:13:47 +0200:

> Calling nand_read_page_op(pagesize)/nand_prog_page_begin_op(pagesize)
> and expecting to get a pagesize+oobsize read from/written to the
> read/write buffer is fragile and only works because of hacks done
> in cmdfunc(). Let's read/write the page in one go, using the page
> cache buffer as a bounce buffer instead of relying on guesses done
> in cafe_nand_cmdfunc().
> 
> Signed-off-by: Boris Brezillon <boris.brezillon@collabora.com>
> Tested-by: Lubomir Rintel <lkundrak@v3.sk>
> ---
> Changes in v2:
> * Add T-b
> * None
> ---
>  drivers/mtd/nand/raw/cafe_nand.c | 16 +++++++++++-----
>  1 file changed, 11 insertions(+), 5 deletions(-)
> 
> diff --git a/drivers/mtd/nand/raw/cafe_nand.c b/drivers/mtd/nand/raw/cafe_nand.c
> index f7e537836d55..36685bee9d83 100644
> --- a/drivers/mtd/nand/raw/cafe_nand.c
> +++ b/drivers/mtd/nand/raw/cafe_nand.c
> @@ -470,6 +470,7 @@ static int cafe_nand_read_page(struct nand_chip *chip, uint8_t *buf,
>  {
>  	struct mtd_info *mtd = nand_to_mtd(chip);
>  	struct cafe_priv *cafe = nand_get_controller_data(chip);
> +	void *pagebuf = nand_get_data_buf(chip);
>  	unsigned int max_bitflips = 0;
>  	u32 ecc_result, status;
>  
> @@ -477,8 +478,11 @@ static int cafe_nand_read_page(struct nand_chip *chip, uint8_t *buf,
>  		cafe_readl(cafe, NAND_ECC_RESULT),
>  		cafe_readl(cafe, NAND_ECC_SYN_REG(0)));
>  
> -	nand_read_page_op(chip, page, 0, buf, mtd->writesize);
> -	chip->legacy.read_buf(chip, chip->oob_poi, mtd->oobsize);
> +	nand_read_page_op(chip, page, 0, pagebuf,
> +			  mtd->writesize + mtd->oobsize);

Shouldn't accesses to the OOB area be under conditions like if
(oob_required)? Unless of course reading the OOB like this is mandatory
in order to get the ECC engine working - I did not check.

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

^ permalink raw reply	[flat|nested] 46+ messages in thread

* Re: [PATCH v2 07/19] mtd: rawnand: cafe: Factor out the controller initialization logic
  2020-05-05 10:13 ` [PATCH v2 07/19] mtd: rawnand: cafe: Factor out the controller initialization logic Boris Brezillon
@ 2020-05-10 21:49   ` Miquel Raynal
  0 siblings, 0 replies; 46+ messages in thread
From: Miquel Raynal @ 2020-05-10 21:49 UTC (permalink / raw)
  To: Boris Brezillon
  Cc: Lubomir Rintel, Tudor Ambarus, linux-mtd, Vignesh Raghavendra,
	Richard Weinberger

Hi Boris,

Boris Brezillon <boris.brezillon@collabora.com> wrote on Tue,  5 May
2020 12:13:41 +0200:

> The same code is present in the probe and resume path. Let's create
> an init helper to factor that out.
> 
> Signed-off-by: Boris Brezillon <boris.brezillon@collabora.com>
> Tested-by: Lubomir Rintel <lkundrak@v3.sk>
> ---
> Changes in v2:
> * Add R-b/T-b
> * Add a blank line before return statement
> ---


Reviewed-by: Miquel Raynal <miquel.raynal@bootlin.com>

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

^ permalink raw reply	[flat|nested] 46+ messages in thread

* Re: [PATCH v2 00/19] mtd: rawnand: cafe: Convert to exec_op() (and more)
  2020-05-10  7:35                               ` Boris Brezillon
@ 2020-05-11  8:23                                 ` Boris Brezillon
       [not found]                                   ` <20200512164057.GC604838@furthur.local>
  0 siblings, 1 reply; 46+ messages in thread
From: Boris Brezillon @ 2020-05-11  8:23 UTC (permalink / raw)
  To: Lubomir Rintel
  Cc: Richard Weinberger, Tudor Ambarus, linux-mtd,
	Vignesh Raghavendra, Miquel Raynal

On Sun, 10 May 2020 09:35:49 +0200
Boris Brezillon <boris.brezillon@collabora.com> wrote:

> On Sun, 10 May 2020 09:21:08 +0200
> Lubomir Rintel <lkundrak@v3.sk> wrote:
> 
> > On Sun, May 10, 2020 at 08:45:41AM +0200, Boris Brezillon wrote:  
> > > On Sun, 10 May 2020 08:31:05 +0200
> > > Boris Brezillon <boris.brezillon@collabora.com> wrote:
> > >     
> > > > On Sat, 9 May 2020 22:28:55 +0200
> > > > Lubomir Rintel <lkundrak@v3.sk> wrote:
> > > >     
> > > > > On Sat, May 09, 2020 at 10:01:02PM +0200, Boris Brezillon wrote:      
> > > > > > On Sat, 9 May 2020 21:34:40 +0200
> > > > > > Lubomir Rintel <lkundrak@v3.sk> wrote:
> > > > > >         
> > > > > > > On Thu, May 07, 2020 at 10:12:57PM +0200, Boris Brezillon wrote:        
> > > > > > > > On Thu, 7 May 2020 15:47:08 +0200
> > > > > > > > Lubomir Rintel <lkundrak@v3.sk> wrote:
> > > > > > > >           
> > > > > > > > > On Wed, May 06, 2020 at 11:35:52PM +0200, Boris Brezillon wrote:          
> > > > > > > > > > On Wed, 6 May 2020 22:36:35 +0200
> > > > > > > > > > Lubomir Rintel <lkundrak@v3.sk> wrote:
> > > > > > > > > >             
> > > > > > > > > > > > We really should mask IRQs (AKA disable IRQs in my naming convention
> > > > > > > > > > > > :-)) here, unless we want to switch to interrupt-based waits (which
> > > > > > > > > > > > would be a good thing when we have DMA or WAIT_RDY involved). Having an
> > > > > > > > > > > > interrupt handler in the current implementation doesn't make any sense
> > > > > > > > > > > > (that's assuming the IRQ_STATUS bits are updated even if the interrupts
> > > > > > > > > > > > are disabled, which am not sure is a valid assumption in this case).              
> > > > > > > > > > > 
> > > > > > > > > > > I have no idea why the interrupt handler is there. Perhaps some
> > > > > > > > > > > interrupts can't be masked and need an ack or something.            
> > > > > > > > > > 
> > > > > > > > > > Can you try to set NAND_IRQ_MASK to 0x0 and see if that still works.
> > > > > > > > > > Can you also check the number of NAND interrupts when set to 0x0? It's
> > > > > > > > > > hard to tell exactly what caused the interrupt handler to be called
> > > > > > > > > > since this is a shared interrupt.            
> > > > > > > > > 
> > > > > > > > > When it's set to 0, I get an interrupt with CAFE_NAND_IRQ=0x40000000
> > > > > > > > > (CAFE_NAND_IRQ_FLASH_RDY) right off the bat. That doesn't happen with
> > > > > > > > > a mask of 0xffffffff.
> > > > > > > > > 
> > > > > > > > > When changing the handler to always ack CAFE_NAND_IRQ_FLASH_RDY I've
> > > > > > > > > also seen CAFE_NAND_IRQ=0x80000000 (CAFE_NAND_IRQ_CMD_DONE) suggesting
> > > > > > > > > that other interrupts aren't masked either.
> > > > > > > > > 
> > > > > > > > > It seems to be that ones indeed mask interrupts but just can't be
> > > > > > > > > masked (CAFE_NAND_IRQ_CMD_DONE or CAFE_NAND_IRQ_DMA_DONE), perhaps
> > > > > > > > > due to hardware bugs.
> > > > > > > > >           
> > > > > > > > 
> > > > > > > > I pushed a new version with some interrupt-related changes [1].
> > > > > > > > 
> > > > > > > > [1]https://github.com/bbrezillon/linux/commits/nand/cafe-nand-exec-op-debug          
> > > > > > > 
> > > > > > > Works with one fix:
> > > > > > > 
> > > > > > > diff --git a/drivers/mtd/nand/raw/cafe_nand.c b/drivers/mtd/nand/raw/cafe_nand.c
> > > > > > > index 591d79730961..e37737b7b089 100644
> > > > > > > --- a/drivers/mtd/nand/raw/cafe_nand.c
> > > > > > > +++ b/drivers/mtd/nand/raw/cafe_nand.c
> > > > > > > @@ -801,6 +801,7 @@ static int cafe_nand_probe(struct pci_dev *pdev,
> > > > > > >         if (!cafe)
> > > > > > >                 return  -ENOMEM;
> > > > > > >  
> > > > > > > +       init_completion(&cafe->complete);        
> > > > > > 
> > > > > > Oops, indeed.
> > > > > >         
> > > > > > >         mtd = nand_to_mtd(&cafe->nand);
> > > > > > >         mtd->dev.parent = &pdev->dev;
> > > > > > >         nand_set_controller_data(&cafe->nand, cafe);
> > > > > > > 
> > > > > > > However, the mount JFFS2 mount takes about twice as long as it did with
> > > > > > > the polling version:        
> > > > > > 
> > > > > > Yes, that's not surprising. At the same time, using atomic-polling for
> > > > > > something that's expected to take hundreds of microseconds is not that
> > > > > > great. That means your CPU is not doing anything useful while you wait
> > > > > > for the read/write/erase operation to finish.        
> > > > > 
> > > > > Yes. But this really is too much of a slowdown:
> > > > > 
> > > > >   bash-5.0# time dd count=65536 bs=2k if=/dev/mtd0 of=/dev/null
> > > > >   65536+0 records in
> > > > >   65536+0 records out
> > > > >   
> > > > >   real    0m20.191s
> > > > >   user    0m0.346s
> > > > >   sys     0m10.366s
> > > > > 
> > > > > vs (previously):
> > > > >   
> > > > >   bash-5.0# time dd count=65536 bs=2k if=/dev/mtd0 of=/dev/null
> > > > >   65536+0 records in
> > > > >   65536+0 records out
> > > > >   
> > > > >   real    0m7.629s
> > > > >   user    0m0.010s
> > > > >   sys     0m7.500s
> > > > >   bash-5.0#      
> > > > 
> > > > Almost a factor 3. I was definitely not expecting interrupt-based waits
> > > > to have such a huge impact on the perfs.
> > > >     
> > > > > 
> > > > > Note that your CPU can't be doing anything useful before the program and
> > > > > its data is loaded from the storage :)      
> > > > 
> > > > Well, that's only true at mount time (and if you delay the mount after
> > > > the boot, your CPU might already have other things to do), but any
> > > > erase/write operations are likely to monopolize your CPU for no good
> > > > reason.
> > > >     
> > > > > 
> > > > > I suppose that if someone really prefers to avoid hogging the CPU at
> > > > > this cost, then it makes sense to add a knob (a module parameter or
> > > > > something) that would enable the interrupt-driven operation, but
> > > > > keep polling as a default.      
> > > > 
> > > > Let's not add more module params than we already have, it just
> > > > confuses users and deciding how to wait on HW events doesn't sounds
> > > > like something they should be able to choose anyway (just like passing
> > > > the timing params, this should be calculated by the driver). Oh well,
> > > > I'll drop the patch adding interrupt-based waits. Having the driver
> > > > converted to exec_op() is more than enough :-).    
> > > 
> > > Just pushed a new version. If it works for you I'll send a v3.    
> > 
> > Thank you. That's b6b10b45dd9 in nand/cafe-nand-exec-op-debug of
> > https://github.com/bbrezillon/linux/ I suppose?
> > 
> > Without the readl_poll_timeout() -> readl_poll_timeout_atomic() change
> > it's still very slow.  
> 
> Should be fixed now.
> 
> > 
> > Also, commit f89355b6b6 ("mtd: rawnand: cafe: Return IRQ_HANDLED when
> > appropriate") looks somewhat suspicious to me. Previously it wrote the
> > pending interrupt bits back into CAFE_NAND_IRQ, now you're masking them
> > out in CAFE_NAND_IRQ_MASK (which already should be 0xffffffff) at this
> > point. Why?  
> 
> If interrupts are masked we don't need to clear them. We only clear
> them before executing an operation to start from a fresh state.
> 
> > I thought the write back to CAFE_NAND_IRQ serves to ack the
> > interrupts that came up but we don't handle elsewhere because we weren't
> > expecting them.  
> 
> If we reach the handler and all our irqs are masked, that means the irq
> was not for us, which is possible since the irq line is shared. We
> really should to return IRQ_NONE in that case, and clearing pending
> interrupts is useless, since they are masked anyway. Since we read
> the interrupt status from exec_op(), I thought it'd be better to never
> clear any interrupt bits instead of clearing all bits but the CMD_DONE,
> DMA_DONE and FLASH_RDY.
> 
> > 
> > As you correctly pointed out; the source of the interrupts I'm seeing
> > could be something else than the CAFE chip -- the camera or the MMC
> > card. I'm not sure though; camera is certainly off and there shouldn't
> > be much going on about the MMC card. I'm testing with a init=/bin/bash
> > installation off a SD-card currently. I guess I can try switching to the
> > USB flash stick and disable the camera and MMC altogether.  
> 
> Okay, if that happens that would be a HW bug (or an interrupt coming
> from somewhere else, maybe PCI errors?)? Can you print the values of
> CAFE_GLOBAL_IRQ and CAFE_GLOBAL_IRQ_MASK in your irq handler?

If you think that's less risky, I can drop "mtd: rawnand: cafe: Return
IRQ_HANDLED when appropriate" and go for your initial fix (avoid
clearing FLSH_READY interrupt). It just feels like the current
implementation is papering over a bug.

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

^ permalink raw reply	[flat|nested] 46+ messages in thread

* Re: [PATCH v2 00/19] mtd: rawnand: cafe: Convert to exec_op() (and more)
       [not found]                                   ` <20200512164057.GC604838@furthur.local>
@ 2020-05-12 19:50                                     ` Boris Brezillon
  2020-05-13 17:10                                     ` Boris Brezillon
  1 sibling, 0 replies; 46+ messages in thread
From: Boris Brezillon @ 2020-05-12 19:50 UTC (permalink / raw)
  To: Lubomir Rintel
  Cc: Richard Weinberger, Tudor Ambarus, linux-mtd,
	Vignesh Raghavendra, Miquel Raynal

On Tue, 12 May 2020 18:40:57 +0200
Lubomir Rintel <lkundrak@v3.sk> wrote:

> > > > 
> > > > As you correctly pointed out; the source of the interrupts I'm seeing
> > > > could be something else than the CAFE chip -- the camera or the MMC
> > > > card. I'm not sure though; camera is certainly off and there shouldn't
> > > > be much going on about the MMC card. I'm testing with a init=/bin/bash
> > > > installation off a SD-card currently. I guess I can try switching to the
> > > > USB flash stick and disable the camera and MMC altogether.    
> > > 
> > > Okay, if that happens that would be a HW bug (or an interrupt coming
> > > from somewhere else, maybe PCI errors?)? Can you print the values of
> > > CAFE_GLOBAL_IRQ and CAFE_GLOBAL_IRQ_MASK in your irq handler?  
> > 
> > If you think that's less risky, I can drop "mtd: rawnand: cafe: Return
> > IRQ_HANDLED when appropriate" and go for your initial fix (avoid
> > clearing FLSH_READY interrupt). It just feels like the current
> > implementation is papering over a bug.  
> 
> I don't really mind the patch; I was just not sure why you removed the
> acks and re-set the mask and suspected that maybe it was not
> intentional.
> 
> That said, I've now disabled the camera and mmc and did my usual test
> of mounting the filesystem and I'm seeing zero interrupts.
> 
> I suppose it's safe to assume that contrary to what I was imagining,
> the masking works well and the interrupts I was seeing are indeed from
> elsewhere (I guess the MMC driver polling the controller or something).
> 
> Also, the re-set of the mask from the interrupt handler is not realy
> necessary (but I certainly wouldn't complain if you keep it in place).

Indeed. It was needed for the interrupt-based wait, but I've dropped
that patch. I guess we can simply get rid of the irq handler and the
request_irq() call.

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

^ permalink raw reply	[flat|nested] 46+ messages in thread

* Re: [PATCH v2 00/19] mtd: rawnand: cafe: Convert to exec_op() (and more)
       [not found]                                   ` <20200512164057.GC604838@furthur.local>
  2020-05-12 19:50                                     ` Boris Brezillon
@ 2020-05-13 17:10                                     ` Boris Brezillon
       [not found]                                       ` <20200515144703.GA1245784@furthur.local>
  1 sibling, 1 reply; 46+ messages in thread
From: Boris Brezillon @ 2020-05-13 17:10 UTC (permalink / raw)
  To: Lubomir Rintel
  Cc: Richard Weinberger, Tudor Ambarus, linux-mtd,
	Vignesh Raghavendra, Miquel Raynal

Hi Lubomir,

On Tue, 12 May 2020 18:40:57 +0200
Lubomir Rintel <lkundrak@v3.sk> wrote:

> I don't really mind the patch; I was just not sure why you removed the
> acks and re-set the mask and suspected that maybe it was not
> intentional.
> 
> That said, I've now disabled the camera and mmc and did my usual test
> of mounting the filesystem and I'm seeing zero interrupts.
> 
> I suppose it's safe to assume that contrary to what I was imagining,
> the masking works well and the interrupts I was seeing are indeed from
> elsewhere (I guess the MMC driver polling the controller or something).
> 
> Also, the re-set of the mask from the interrupt handler is not realy
> necessary (but I certainly wouldn't complain if you keep it in place).

I pushed a new version to my nand/cafe-nand-exec-op-debug branch. This
time I get rid of the IRQ handler as it's not used anyway. Let me know
if that keeps working an I'll send a v3.

Thanks,

Boris

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

^ permalink raw reply	[flat|nested] 46+ messages in thread

* Re: [PATCH v2 00/19] mtd: rawnand: cafe: Convert to exec_op() (and more)
       [not found]                                           ` <20200516145650.GA1433661@furthur.local>
@ 2020-05-16 19:08                                             ` Boris Brezillon
  2020-05-16 20:18                                               ` Boris Brezillon
  0 siblings, 1 reply; 46+ messages in thread
From: Boris Brezillon @ 2020-05-16 19:08 UTC (permalink / raw)
  To: Lubomir Rintel
  Cc: Richard Weinberger, Tudor Ambarus, linux-mtd,
	Vignesh Raghavendra, Miquel Raynal

On Sat, 16 May 2020 16:56:50 +0200
Lubomir Rintel <lkundrak@v3.sk> wrote:

> On Fri, May 15, 2020 at 09:25:43PM +0200, Lubomir Rintel wrote:
> > On Fri, May 15, 2020 at 04:47:07PM +0200, Lubomir Rintel wrote:  
> > > On Wed, May 13, 2020 at 07:10:38PM +0200, Boris Brezillon wrote:  
> > > > Hi Lubomir,
> > > > 
> > > > On Tue, 12 May 2020 18:40:57 +0200
> > > > Lubomir Rintel <lkundrak@v3.sk> wrote:
> > > >   
> > > > > I don't really mind the patch; I was just not sure why you removed the
> > > > > acks and re-set the mask and suspected that maybe it was not
> > > > > intentional.
> > > > > 
> > > > > That said, I've now disabled the camera and mmc and did my usual test
> > > > > of mounting the filesystem and I'm seeing zero interrupts.
> > > > > 
> > > > > I suppose it's safe to assume that contrary to what I was imagining,
> > > > > the masking works well and the interrupts I was seeing are indeed from
> > > > > elsewhere (I guess the MMC driver polling the controller or something).
> > > > > 
> > > > > Also, the re-set of the mask from the interrupt handler is not realy
> > > > > necessary (but I certainly wouldn't complain if you keep it in place).  
> > > > 
> > > > I pushed a new version to my nand/cafe-nand-exec-op-debug branch. This
> > > > time I get rid of the IRQ handler as it's not used anyway. Let me know
> > > > if that keeps working an I'll send a v3.  
> > > 
> > > I can confirm that your branch (as of 12ef1918985f "mtd: rawnand: cafe: Get
> > > rid of the last printk()") is working great here:
> > > 
> > >   bash-5.0# time mount -t jffs2 mtd0 /mnt
> > >   jffs2: notice: (101) jffs2_build_xattr_subsystem: complete building xattr subsystem, 0 of xdatum (0 unchecked, 0 orphan) and 0 of xref (0 dead, 0 orphan) .
> > >   
> > >   real    0m7.319s
> > >   user    0m0.000s
> > >   sys     0m7.294s
> > >   bash-5.0# uname -a
> > >   Linux (none) 5.7.0-rc3-00097-g12ef1918985f #114 PREEMPT Fri May 15 16:35:01 CEST 2020 i586 GNU/Linux
> > >   bash-5.0#   
> > 
> > Spoke too soon again. Seems like the writes don't make it to the device:
> > 
> >   bash-5.0# mount -t jffs2 /dev/mtdblock0 /mnt
> >   jffs2: Empty flash at 0x045a5798 ends at 0x045a5800
> >   jffs2: notice: (98) jffs2_build_xattr_subsystem: complete building xattr subsystem, 1 of xdatum (0 unchecked, 0 orphan) and 1 of xref (0 dead, 0 orphan) f.
> >   bash-5.0# touch /mnt/meh
> >   bash-5.0# sync 
> >   jffs2: jffs2_flush_wbuf(): Write failed with -5
> >   jffs2: jffs2_flush_wbuf(): Write failed with -5
> >   jffs2: jffs2_flush_wbuf(): Write failed with -5
> >   jffs2: jffs2_flush_wbuf(): Write failed with -5
> >   bash-5.0# 
> > 
> > I'll follow up once I know more; with some traces or hopefully a fix.  
> 
> Hi again. Hope you're having a good weekend.
> 
> Some good news and some bad news. Good news is that now I got around to
> building an image with mtd_debug and got around to making erase, write
> adn read work, withut the hassle of dealing with jffs2 (and hassle of
> dealing with corrupted image from eariler attempts).
> 
> The bad news is that I have very little idea about what I'm actually
> doing. Here's the branch with changes I've done, with my notes in
> the commit messages:
> 
>   git fetch git://git.kernel.org/pub/scm/linux/kernel/git/lkundrak/linux.git \
>       lr/nand/cafe-nand-exec-op-debug
> 
> The relevant changes:
> 
>   6ee7e0d11e19 fixup! mtd: rawnand: cafe: Demistify register fields

This one is valid.

>   565d5f126e86 fixup! mtd: rawnand: cafe: Demistify register fields

Here it should be

#define CAFE_NAND_ECC_SYN_REG(x)		((((x) / 2) * 4) + 0x50)

but maybe the loop is no longer valid after that.

>   064d381b4615 fixup! mtd: rawnand: cafe: Demistify register fields

This one looks good too.

> 
>     During the test with JFFS2 filesystem, I was seeing a metric ton of ECC
>     errors. I have no clue where they came from because they presumably happened
>     on an asynchronous writeback, but they no longer happen and I believe
>     some of the above was to blame. Unfortunely I didn't investigate
>     further, because in my setup it is hugely inconvenient to beat the image
>     back into shape.
> 
>   085a6ad43151 Revert "mtd: rawnand: cafe: Don't leave ECC enabled in the write path"
> 
>     This triggered a WARN_ON(). Probably not too important, because the
>     code in question gets thrown out afterwards.

Oops. Maybe I should move it after the exec_op() conversion then.

> 
>   4a9d95bf6d6b fixup! mtd: rawnand: cafe: Add exec_op() support
> 
>     An straightforward fix for page write op.

Yep, that one is valid, thanks for the fix.

> 
>   6959a724994d XXX add address to CMD_STATUS
> 
>     Tricky, and I have no idea what's going on. Perhaps you'll have an
>     idea how to either address this more reasonably. As usual, I'm happy
>     to apply patches with extra tracing if necessary.

Duh, that one is super weird. I wonder if it doesn't have to do with
the fact we're using DMA. Can you try with the DMA disabled? I see
there's also a non-memory read mode, but even the standard mode should
work according to the diagram page 37 of the spec [1].

[1]http://wiki.laptop.org/images/5/5c/88ALP01_Datasheet_July_2007.pdf

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

^ permalink raw reply	[flat|nested] 46+ messages in thread

* Re: [PATCH v2 00/19] mtd: rawnand: cafe: Convert to exec_op() (and more)
  2020-05-16 19:08                                             ` Boris Brezillon
@ 2020-05-16 20:18                                               ` Boris Brezillon
       [not found]                                                 ` <20200517164709.GA1651421@furthur.local>
  0 siblings, 1 reply; 46+ messages in thread
From: Boris Brezillon @ 2020-05-16 20:18 UTC (permalink / raw)
  To: Lubomir Rintel
  Cc: Richard Weinberger, Tudor Ambarus, linux-mtd,
	Vignesh Raghavendra, Miquel Raynal

On Sat, 16 May 2020 21:08:57 +0200
Boris Brezillon <boris.brezillon@collabora.com> wrote:

> On Sat, 16 May 2020 16:56:50 +0200
> Lubomir Rintel <lkundrak@v3.sk> wrote:
> 
> > On Fri, May 15, 2020 at 09:25:43PM +0200, Lubomir Rintel wrote:  
> > > On Fri, May 15, 2020 at 04:47:07PM +0200, Lubomir Rintel wrote:    
> > > > On Wed, May 13, 2020 at 07:10:38PM +0200, Boris Brezillon wrote:    
> > > > > Hi Lubomir,
> > > > > 
> > > > > On Tue, 12 May 2020 18:40:57 +0200
> > > > > Lubomir Rintel <lkundrak@v3.sk> wrote:
> > > > >     
> > > > > > I don't really mind the patch; I was just not sure why you removed the
> > > > > > acks and re-set the mask and suspected that maybe it was not
> > > > > > intentional.
> > > > > > 
> > > > > > That said, I've now disabled the camera and mmc and did my usual test
> > > > > > of mounting the filesystem and I'm seeing zero interrupts.
> > > > > > 
> > > > > > I suppose it's safe to assume that contrary to what I was imagining,
> > > > > > the masking works well and the interrupts I was seeing are indeed from
> > > > > > elsewhere (I guess the MMC driver polling the controller or something).
> > > > > > 
> > > > > > Also, the re-set of the mask from the interrupt handler is not realy
> > > > > > necessary (but I certainly wouldn't complain if you keep it in place).    
> > > > > 
> > > > > I pushed a new version to my nand/cafe-nand-exec-op-debug branch. This
> > > > > time I get rid of the IRQ handler as it's not used anyway. Let me know
> > > > > if that keeps working an I'll send a v3.    
> > > > 
> > > > I can confirm that your branch (as of 12ef1918985f "mtd: rawnand: cafe: Get
> > > > rid of the last printk()") is working great here:
> > > > 
> > > >   bash-5.0# time mount -t jffs2 mtd0 /mnt
> > > >   jffs2: notice: (101) jffs2_build_xattr_subsystem: complete building xattr subsystem, 0 of xdatum (0 unchecked, 0 orphan) and 0 of xref (0 dead, 0 orphan) .
> > > >   
> > > >   real    0m7.319s
> > > >   user    0m0.000s
> > > >   sys     0m7.294s
> > > >   bash-5.0# uname -a
> > > >   Linux (none) 5.7.0-rc3-00097-g12ef1918985f #114 PREEMPT Fri May 15 16:35:01 CEST 2020 i586 GNU/Linux
> > > >   bash-5.0#     
> > > 
> > > Spoke too soon again. Seems like the writes don't make it to the device:
> > > 
> > >   bash-5.0# mount -t jffs2 /dev/mtdblock0 /mnt
> > >   jffs2: Empty flash at 0x045a5798 ends at 0x045a5800
> > >   jffs2: notice: (98) jffs2_build_xattr_subsystem: complete building xattr subsystem, 1 of xdatum (0 unchecked, 0 orphan) and 1 of xref (0 dead, 0 orphan) f.
> > >   bash-5.0# touch /mnt/meh
> > >   bash-5.0# sync 
> > >   jffs2: jffs2_flush_wbuf(): Write failed with -5
> > >   jffs2: jffs2_flush_wbuf(): Write failed with -5
> > >   jffs2: jffs2_flush_wbuf(): Write failed with -5
> > >   jffs2: jffs2_flush_wbuf(): Write failed with -5
> > >   bash-5.0# 
> > > 
> > > I'll follow up once I know more; with some traces or hopefully a fix.    
> > 
> > Hi again. Hope you're having a good weekend.
> > 
> > Some good news and some bad news. Good news is that now I got around to
> > building an image with mtd_debug and got around to making erase, write
> > adn read work, withut the hassle of dealing with jffs2 (and hassle of
> > dealing with corrupted image from eariler attempts).
> > 
> > The bad news is that I have very little idea about what I'm actually
> > doing. Here's the branch with changes I've done, with my notes in
> > the commit messages:
> > 
> >   git fetch git://git.kernel.org/pub/scm/linux/kernel/git/lkundrak/linux.git \
> >       lr/nand/cafe-nand-exec-op-debug
> > 
> > The relevant changes:
> > 
> >   6ee7e0d11e19 fixup! mtd: rawnand: cafe: Demistify register fields  
> 
> This one is valid.
> 
> >   565d5f126e86 fixup! mtd: rawnand: cafe: Demistify register fields  
> 
> Here it should be
> 
> #define CAFE_NAND_ECC_SYN_REG(x)		((((x) / 2) * 4) + 0x50)
> 
> but maybe the loop is no longer valid after that.
> 
> >   064d381b4615 fixup! mtd: rawnand: cafe: Demistify register fields  
> 
> This one looks good too.
> 
> > 
> >     During the test with JFFS2 filesystem, I was seeing a metric ton of ECC
> >     errors. I have no clue where they came from because they presumably happened
> >     on an asynchronous writeback, but they no longer happen and I believe
> >     some of the above was to blame. Unfortunely I didn't investigate
> >     further, because in my setup it is hugely inconvenient to beat the image
> >     back into shape.
> > 
> >   085a6ad43151 Revert "mtd: rawnand: cafe: Don't leave ECC enabled in the write path"
> > 
> >     This triggered a WARN_ON(). Probably not too important, because the
> >     code in question gets thrown out afterwards.  
> 
> Oops. Maybe I should move it after the exec_op() conversion then.
> 
> > 
> >   4a9d95bf6d6b fixup! mtd: rawnand: cafe: Add exec_op() support
> > 
> >     An straightforward fix for page write op.  
> 
> Yep, that one is valid, thanks for the fix.
> 
> > 
> >   6959a724994d XXX add address to CMD_STATUS
> > 
> >     Tricky, and I have no idea what's going on. Perhaps you'll have an
> >     idea how to either address this more reasonably. As usual, I'm happy
> >     to apply patches with extra tracing if necessary.  
> 
> Duh, that one is super weird. I wonder if it doesn't have to do with
> the fact we're using DMA. Can you try with the DMA disabled? I see
> there's also a non-memory read mode, but even the standard mode should
> work according to the diagram page 37 of the spec [1].

Can you also dump the timing registers and find what's the NAND clk
rate? It could be that tCLR (Timing reg 3) is not big enough.

> 
> [1]http://wiki.laptop.org/images/5/5c/88ALP01_Datasheet_July_2007.pdf


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

^ permalink raw reply	[flat|nested] 46+ messages in thread

* Re: [PATCH v2 00/19] mtd: rawnand: cafe: Convert to exec_op() (and more)
       [not found]                                                 ` <20200517164709.GA1651421@furthur.local>
@ 2020-05-18 14:50                                                   ` Boris Brezillon
       [not found]                                                     ` <20200520072331.GJ1695525@furthur.local>
  0 siblings, 1 reply; 46+ messages in thread
From: Boris Brezillon @ 2020-05-18 14:50 UTC (permalink / raw)
  To: Lubomir Rintel
  Cc: Richard Weinberger, Tudor Ambarus, linux-mtd,
	Vignesh Raghavendra, Miquel Raynal

On Sun, 17 May 2020 18:47:09 +0200
Lubomir Rintel <lkundrak@v3.sk> wrote:

> On Sat, May 16, 2020 at 10:18:37PM +0200, Boris Brezillon wrote:
> > On Sat, 16 May 2020 21:08:57 +0200
> > Boris Brezillon <boris.brezillon@collabora.com> wrote:
> >   
> > > On Sat, 16 May 2020 16:56:50 +0200
> > > Lubomir Rintel <lkundrak@v3.sk> wrote:
> > >   
> > > > On Fri, May 15, 2020 at 09:25:43PM +0200, Lubomir Rintel wrote:    
> > > > > On Fri, May 15, 2020 at 04:47:07PM +0200, Lubomir Rintel wrote:      
> > > > > > On Wed, May 13, 2020 at 07:10:38PM +0200, Boris Brezillon wrote:      
> > > > > > > Hi Lubomir,
> > > > > > > 
> > > > > > > On Tue, 12 May 2020 18:40:57 +0200
> > > > > > > Lubomir Rintel <lkundrak@v3.sk> wrote:
> > > > > > >       
> > > > > > > > I don't really mind the patch; I was just not sure why you removed the
> > > > > > > > acks and re-set the mask and suspected that maybe it was not
> > > > > > > > intentional.
> > > > > > > > 
> > > > > > > > That said, I've now disabled the camera and mmc and did my usual test
> > > > > > > > of mounting the filesystem and I'm seeing zero interrupts.
> > > > > > > > 
> > > > > > > > I suppose it's safe to assume that contrary to what I was imagining,
> > > > > > > > the masking works well and the interrupts I was seeing are indeed from
> > > > > > > > elsewhere (I guess the MMC driver polling the controller or something).
> > > > > > > > 
> > > > > > > > Also, the re-set of the mask from the interrupt handler is not realy
> > > > > > > > necessary (but I certainly wouldn't complain if you keep it in place).      
> > > > > > > 
> > > > > > > I pushed a new version to my nand/cafe-nand-exec-op-debug branch. This
> > > > > > > time I get rid of the IRQ handler as it's not used anyway. Let me know
> > > > > > > if that keeps working an I'll send a v3.      
> > > > > > 
> > > > > > I can confirm that your branch (as of 12ef1918985f "mtd: rawnand: cafe: Get
> > > > > > rid of the last printk()") is working great here:
> > > > > > 
> > > > > >   bash-5.0# time mount -t jffs2 mtd0 /mnt
> > > > > >   jffs2: notice: (101) jffs2_build_xattr_subsystem: complete building xattr subsystem, 0 of xdatum (0 unchecked, 0 orphan) and 0 of xref (0 dead, 0 orphan) .
> > > > > >   
> > > > > >   real    0m7.319s
> > > > > >   user    0m0.000s
> > > > > >   sys     0m7.294s
> > > > > >   bash-5.0# uname -a
> > > > > >   Linux (none) 5.7.0-rc3-00097-g12ef1918985f #114 PREEMPT Fri May 15 16:35:01 CEST 2020 i586 GNU/Linux
> > > > > >   bash-5.0#       
> > > > > 
> > > > > Spoke too soon again. Seems like the writes don't make it to the device:
> > > > > 
> > > > >   bash-5.0# mount -t jffs2 /dev/mtdblock0 /mnt
> > > > >   jffs2: Empty flash at 0x045a5798 ends at 0x045a5800
> > > > >   jffs2: notice: (98) jffs2_build_xattr_subsystem: complete building xattr subsystem, 1 of xdatum (0 unchecked, 0 orphan) and 1 of xref (0 dead, 0 orphan) f.
> > > > >   bash-5.0# touch /mnt/meh
> > > > >   bash-5.0# sync 
> > > > >   jffs2: jffs2_flush_wbuf(): Write failed with -5
> > > > >   jffs2: jffs2_flush_wbuf(): Write failed with -5
> > > > >   jffs2: jffs2_flush_wbuf(): Write failed with -5
> > > > >   jffs2: jffs2_flush_wbuf(): Write failed with -5
> > > > >   bash-5.0# 
> > > > > 
> > > > > I'll follow up once I know more; with some traces or hopefully a fix.      
> > > > 
> > > > Hi again. Hope you're having a good weekend.
> > > > 
> > > > Some good news and some bad news. Good news is that now I got around to
> > > > building an image with mtd_debug and got around to making erase, write
> > > > adn read work, withut the hassle of dealing with jffs2 (and hassle of
> > > > dealing with corrupted image from eariler attempts).
> > > > 
> > > > The bad news is that I have very little idea about what I'm actually
> > > > doing. Here's the branch with changes I've done, with my notes in
> > > > the commit messages:
> > > > 
> > > >   git fetch git://git.kernel.org/pub/scm/linux/kernel/git/lkundrak/linux.git \
> > > >       lr/nand/cafe-nand-exec-op-debug
> > > > 
> > > > The relevant changes:
> > > > 
> > > >   6ee7e0d11e19 fixup! mtd: rawnand: cafe: Demistify register fields    
> > > 
> > > This one is valid.
> > >   
> > > >   565d5f126e86 fixup! mtd: rawnand: cafe: Demistify register fields    
> > > 
> > > Here it should be
> > > 
> > > #define CAFE_NAND_ECC_SYN_REG(x)		((((x) / 2) * 4) + 0x50)
> > > 
> > > but maybe the loop is no longer valid after that.
> > >   
> > > >   064d381b4615 fixup! mtd: rawnand: cafe: Demistify register fields    
> > > 
> > > This one looks good too.
> > >   
> > > > 
> > > >     During the test with JFFS2 filesystem, I was seeing a metric ton of ECC
> > > >     errors. I have no clue where they came from because they presumably happened
> > > >     on an asynchronous writeback, but they no longer happen and I believe
> > > >     some of the above was to blame. Unfortunely I didn't investigate
> > > >     further, because in my setup it is hugely inconvenient to beat the image
> > > >     back into shape.
> > > > 
> > > >   085a6ad43151 Revert "mtd: rawnand: cafe: Don't leave ECC enabled in the write path"
> > > > 
> > > >     This triggered a WARN_ON(). Probably not too important, because the
> > > >     code in question gets thrown out afterwards.    
> > > 
> > > Oops. Maybe I should move it after the exec_op() conversion then.
> > >   
> > > > 
> > > >   4a9d95bf6d6b fixup! mtd: rawnand: cafe: Add exec_op() support
> > > > 
> > > >     An straightforward fix for page write op.    
> > > 
> > > Yep, that one is valid, thanks for the fix.
> > >   
> > > > 
> > > >   6959a724994d XXX add address to CMD_STATUS
> > > > 
> > > >     Tricky, and I have no idea what's going on. Perhaps you'll have an
> > > >     idea how to either address this more reasonably. As usual, I'm happy
> > > >     to apply patches with extra tracing if necessary.    
> > > 
> > > Duh, that one is super weird. I wonder if it doesn't have to do with
> > > the fact we're using DMA. Can you try with the DMA disabled?  
> 
> Disabling DMA makes things work.

Okay, I pushed a new version doing DMA only where there's at least one
address cycle.

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

^ permalink raw reply	[flat|nested] 46+ messages in thread

* Re: [PATCH v2 00/19] mtd: rawnand: cafe: Convert to exec_op() (and more)
       [not found]                                                     ` <20200520072331.GJ1695525@furthur.local>
@ 2020-05-20  7:55                                                       ` Boris Brezillon
       [not found]                                                         ` <20200524115246.GC2781@furthur.local>
  0 siblings, 1 reply; 46+ messages in thread
From: Boris Brezillon @ 2020-05-20  7:55 UTC (permalink / raw)
  To: Lubomir Rintel
  Cc: Richard Weinberger, Tudor Ambarus, linux-mtd,
	Vignesh Raghavendra, Miquel Raynal

On Wed, 20 May 2020 09:23:31 +0200
Lubomir Rintel <lkundrak@v3.sk> wrote:

> On Mon, May 18, 2020 at 04:50:24PM +0200, Boris Brezillon wrote:
> > On Sun, 17 May 2020 18:47:09 +0200
> > Lubomir Rintel <lkundrak@v3.sk> wrote:
> >   
> > > On Sat, May 16, 2020 at 10:18:37PM +0200, Boris Brezillon wrote:  
> > > > On Sat, 16 May 2020 21:08:57 +0200
> > > > Boris Brezillon <boris.brezillon@collabora.com> wrote:
> > > >     
> > > > > On Sat, 16 May 2020 16:56:50 +0200
> > > > > Lubomir Rintel <lkundrak@v3.sk> wrote:
> > > > >     
> > > > > > On Fri, May 15, 2020 at 09:25:43PM +0200, Lubomir Rintel wrote:      
> > > > > > > On Fri, May 15, 2020 at 04:47:07PM +0200, Lubomir Rintel wrote:        
> > > > > > > > On Wed, May 13, 2020 at 07:10:38PM +0200, Boris Brezillon wrote:        
> > > > > > > > > Hi Lubomir,
> > > > > > > > > 
> > > > > > > > > On Tue, 12 May 2020 18:40:57 +0200
> > > > > > > > > Lubomir Rintel <lkundrak@v3.sk> wrote:
> > > > > > > > >         
> > > > > > > > > > I don't really mind the patch; I was just not sure why you removed the
> > > > > > > > > > acks and re-set the mask and suspected that maybe it was not
> > > > > > > > > > intentional.
> > > > > > > > > > 
> > > > > > > > > > That said, I've now disabled the camera and mmc and did my usual test
> > > > > > > > > > of mounting the filesystem and I'm seeing zero interrupts.
> > > > > > > > > > 
> > > > > > > > > > I suppose it's safe to assume that contrary to what I was imagining,
> > > > > > > > > > the masking works well and the interrupts I was seeing are indeed from
> > > > > > > > > > elsewhere (I guess the MMC driver polling the controller or something).
> > > > > > > > > > 
> > > > > > > > > > Also, the re-set of the mask from the interrupt handler is not realy
> > > > > > > > > > necessary (but I certainly wouldn't complain if you keep it in place).        
> > > > > > > > > 
> > > > > > > > > I pushed a new version to my nand/cafe-nand-exec-op-debug branch. This
> > > > > > > > > time I get rid of the IRQ handler as it's not used anyway. Let me know
> > > > > > > > > if that keeps working an I'll send a v3.        
> > > > > > > > 
> > > > > > > > I can confirm that your branch (as of 12ef1918985f "mtd: rawnand: cafe: Get
> > > > > > > > rid of the last printk()") is working great here:
> > > > > > > > 
> > > > > > > >   bash-5.0# time mount -t jffs2 mtd0 /mnt
> > > > > > > >   jffs2: notice: (101) jffs2_build_xattr_subsystem: complete building xattr subsystem, 0 of xdatum (0 unchecked, 0 orphan) and 0 of xref (0 dead, 0 orphan) .
> > > > > > > >   
> > > > > > > >   real    0m7.319s
> > > > > > > >   user    0m0.000s
> > > > > > > >   sys     0m7.294s
> > > > > > > >   bash-5.0# uname -a
> > > > > > > >   Linux (none) 5.7.0-rc3-00097-g12ef1918985f #114 PREEMPT Fri May 15 16:35:01 CEST 2020 i586 GNU/Linux
> > > > > > > >   bash-5.0#         
> > > > > > > 
> > > > > > > Spoke too soon again. Seems like the writes don't make it to the device:
> > > > > > > 
> > > > > > >   bash-5.0# mount -t jffs2 /dev/mtdblock0 /mnt
> > > > > > >   jffs2: Empty flash at 0x045a5798 ends at 0x045a5800
> > > > > > >   jffs2: notice: (98) jffs2_build_xattr_subsystem: complete building xattr subsystem, 1 of xdatum (0 unchecked, 0 orphan) and 1 of xref (0 dead, 0 orphan) f.
> > > > > > >   bash-5.0# touch /mnt/meh
> > > > > > >   bash-5.0# sync 
> > > > > > >   jffs2: jffs2_flush_wbuf(): Write failed with -5
> > > > > > >   jffs2: jffs2_flush_wbuf(): Write failed with -5
> > > > > > >   jffs2: jffs2_flush_wbuf(): Write failed with -5
> > > > > > >   jffs2: jffs2_flush_wbuf(): Write failed with -5
> > > > > > >   bash-5.0# 
> > > > > > > 
> > > > > > > I'll follow up once I know more; with some traces or hopefully a fix.        
> > > > > > 
> > > > > > Hi again. Hope you're having a good weekend.
> > > > > > 
> > > > > > Some good news and some bad news. Good news is that now I got around to
> > > > > > building an image with mtd_debug and got around to making erase, write
> > > > > > adn read work, withut the hassle of dealing with jffs2 (and hassle of
> > > > > > dealing with corrupted image from eariler attempts).
> > > > > > 
> > > > > > The bad news is that I have very little idea about what I'm actually
> > > > > > doing. Here's the branch with changes I've done, with my notes in
> > > > > > the commit messages:
> > > > > > 
> > > > > >   git fetch git://git.kernel.org/pub/scm/linux/kernel/git/lkundrak/linux.git \
> > > > > >       lr/nand/cafe-nand-exec-op-debug
> > > > > > 
> > > > > > The relevant changes:
> > > > > > 
> > > > > >   6ee7e0d11e19 fixup! mtd: rawnand: cafe: Demistify register fields      
> > > > > 
> > > > > This one is valid.
> > > > >     
> > > > > >   565d5f126e86 fixup! mtd: rawnand: cafe: Demistify register fields      
> > > > > 
> > > > > Here it should be
> > > > > 
> > > > > #define CAFE_NAND_ECC_SYN_REG(x)		((((x) / 2) * 4) + 0x50)
> > > > > 
> > > > > but maybe the loop is no longer valid after that.
> > > > >     
> > > > > >   064d381b4615 fixup! mtd: rawnand: cafe: Demistify register fields      
> > > > > 
> > > > > This one looks good too.
> > > > >     
> > > > > > 
> > > > > >     During the test with JFFS2 filesystem, I was seeing a metric ton of ECC
> > > > > >     errors. I have no clue where they came from because they presumably happened
> > > > > >     on an asynchronous writeback, but they no longer happen and I believe
> > > > > >     some of the above was to blame. Unfortunely I didn't investigate
> > > > > >     further, because in my setup it is hugely inconvenient to beat the image
> > > > > >     back into shape.
> > > > > > 
> > > > > >   085a6ad43151 Revert "mtd: rawnand: cafe: Don't leave ECC enabled in the write path"
> > > > > > 
> > > > > >     This triggered a WARN_ON(). Probably not too important, because the
> > > > > >     code in question gets thrown out afterwards.      
> > > > > 
> > > > > Oops. Maybe I should move it after the exec_op() conversion then.
> > > > >     
> > > > > > 
> > > > > >   4a9d95bf6d6b fixup! mtd: rawnand: cafe: Add exec_op() support
> > > > > > 
> > > > > >     An straightforward fix for page write op.      
> > > > > 
> > > > > Yep, that one is valid, thanks for the fix.
> > > > >     
> > > > > > 
> > > > > >   6959a724994d XXX add address to CMD_STATUS
> > > > > > 
> > > > > >     Tricky, and I have no idea what's going on. Perhaps you'll have an
> > > > > >     idea how to either address this more reasonably. As usual, I'm happy
> > > > > >     to apply patches with extra tracing if necessary.      
> > > > > 
> > > > > Duh, that one is super weird. I wonder if it doesn't have to do with
> > > > > the fact we're using DMA. Can you try with the DMA disabled?    
> > > 
> > > Disabling DMA makes things work.  
> > 
> > Okay, I pushed a new version doing DMA only where there's at least one
> > address cycle.  
> 
> Ok, this is somewhat embarassing:
> 
> It doesn't work, but reverting disabling DMA altogether doesn't make it
> work now either. It might be that it doesn't behave deterministically,
> but more likely I just fucked up the testing and was testing a wrong
> tree.

No worries. It might also be me messing up with one of your fixes (I've
slightly changed the one fixing the SYN_REG() macro, and if others
have been changed, it was not intentional). What are the symptoms?
Still failures in the write path?

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

^ permalink raw reply	[flat|nested] 46+ messages in thread

* Re: [PATCH v2 00/19] mtd: rawnand: cafe: Convert to exec_op() (and more)
       [not found]                                                         ` <20200524115246.GC2781@furthur.local>
@ 2020-05-24 14:55                                                           ` Boris Brezillon
  2020-05-24 15:05                                                             ` Boris Brezillon
  2020-05-24 15:29                                                           ` Boris Brezillon
  1 sibling, 1 reply; 46+ messages in thread
From: Boris Brezillon @ 2020-05-24 14:55 UTC (permalink / raw)
  To: Lubomir Rintel
  Cc: Richard Weinberger, Tudor Ambarus, linux-mtd,
	Vignesh Raghavendra, Miquel Raynal

On Sun, 24 May 2020 13:52:46 +0200
Lubomir Rintel <lkundrak@v3.sk> wrote:

> On Wed, May 20, 2020 at 09:55:11AM +0200, Boris Brezillon wrote:
> > On Wed, 20 May 2020 09:23:31 +0200
> > Lubomir Rintel <lkundrak@v3.sk> wrote:
> >   
> > > On Mon, May 18, 2020 at 04:50:24PM +0200, Boris Brezillon wrote:  
> > > > On Sun, 17 May 2020 18:47:09 +0200
> > > > Lubomir Rintel <lkundrak@v3.sk> wrote:
> > > >     
> > > > > On Sat, May 16, 2020 at 10:18:37PM +0200, Boris Brezillon wrote:    
> > > > > > On Sat, 16 May 2020 21:08:57 +0200
> > > > > > Boris Brezillon <boris.brezillon@collabora.com> wrote:
> > > > > >       
> > > > > > > On Sat, 16 May 2020 16:56:50 +0200
> > > > > > > Lubomir Rintel <lkundrak@v3.sk> wrote:
> > > > > > >       
> > > > > > > > On Fri, May 15, 2020 at 09:25:43PM +0200, Lubomir Rintel wrote:        
> > > > > > > > > On Fri, May 15, 2020 at 04:47:07PM +0200, Lubomir Rintel wrote:          
> > > > > > > > > > On Wed, May 13, 2020 at 07:10:38PM +0200, Boris Brezillon wrote:          
> > > > > > > > > > > Hi Lubomir,
> > > > > > > > > > > 
> > > > > > > > > > > On Tue, 12 May 2020 18:40:57 +0200
> > > > > > > > > > > Lubomir Rintel <lkundrak@v3.sk> wrote:
> > > > > > > > > > >           
> > > > > > > > > > > > I don't really mind the patch; I was just not sure why you removed the
> > > > > > > > > > > > acks and re-set the mask and suspected that maybe it was not
> > > > > > > > > > > > intentional.
> > > > > > > > > > > > 
> > > > > > > > > > > > That said, I've now disabled the camera and mmc and did my usual test
> > > > > > > > > > > > of mounting the filesystem and I'm seeing zero interrupts.
> > > > > > > > > > > > 
> > > > > > > > > > > > I suppose it's safe to assume that contrary to what I was imagining,
> > > > > > > > > > > > the masking works well and the interrupts I was seeing are indeed from
> > > > > > > > > > > > elsewhere (I guess the MMC driver polling the controller or something).
> > > > > > > > > > > > 
> > > > > > > > > > > > Also, the re-set of the mask from the interrupt handler is not realy
> > > > > > > > > > > > necessary (but I certainly wouldn't complain if you keep it in place).          
> > > > > > > > > > > 
> > > > > > > > > > > I pushed a new version to my nand/cafe-nand-exec-op-debug branch. This
> > > > > > > > > > > time I get rid of the IRQ handler as it's not used anyway. Let me know
> > > > > > > > > > > if that keeps working an I'll send a v3.          
> > > > > > > > > > 
> > > > > > > > > > I can confirm that your branch (as of 12ef1918985f "mtd: rawnand: cafe: Get
> > > > > > > > > > rid of the last printk()") is working great here:
> > > > > > > > > > 
> > > > > > > > > >   bash-5.0# time mount -t jffs2 mtd0 /mnt
> > > > > > > > > >   jffs2: notice: (101) jffs2_build_xattr_subsystem: complete building xattr subsystem, 0 of xdatum (0 unchecked, 0 orphan) and 0 of xref (0 dead, 0 orphan) .
> > > > > > > > > >   
> > > > > > > > > >   real    0m7.319s
> > > > > > > > > >   user    0m0.000s
> > > > > > > > > >   sys     0m7.294s
> > > > > > > > > >   bash-5.0# uname -a
> > > > > > > > > >   Linux (none) 5.7.0-rc3-00097-g12ef1918985f #114 PREEMPT Fri May 15 16:35:01 CEST 2020 i586 GNU/Linux
> > > > > > > > > >   bash-5.0#           
> > > > > > > > > 
> > > > > > > > > Spoke too soon again. Seems like the writes don't make it to the device:
> > > > > > > > > 
> > > > > > > > >   bash-5.0# mount -t jffs2 /dev/mtdblock0 /mnt
> > > > > > > > >   jffs2: Empty flash at 0x045a5798 ends at 0x045a5800
> > > > > > > > >   jffs2: notice: (98) jffs2_build_xattr_subsystem: complete building xattr subsystem, 1 of xdatum (0 unchecked, 0 orphan) and 1 of xref (0 dead, 0 orphan) f.
> > > > > > > > >   bash-5.0# touch /mnt/meh
> > > > > > > > >   bash-5.0# sync 
> > > > > > > > >   jffs2: jffs2_flush_wbuf(): Write failed with -5
> > > > > > > > >   jffs2: jffs2_flush_wbuf(): Write failed with -5
> > > > > > > > >   jffs2: jffs2_flush_wbuf(): Write failed with -5
> > > > > > > > >   jffs2: jffs2_flush_wbuf(): Write failed with -5
> > > > > > > > >   bash-5.0# 
> > > > > > > > > 
> > > > > > > > > I'll follow up once I know more; with some traces or hopefully a fix.          
> > > > > > > > 
> > > > > > > > Hi again. Hope you're having a good weekend.
> > > > > > > > 
> > > > > > > > Some good news and some bad news. Good news is that now I got around to
> > > > > > > > building an image with mtd_debug and got around to making erase, write
> > > > > > > > adn read work, withut the hassle of dealing with jffs2 (and hassle of
> > > > > > > > dealing with corrupted image from eariler attempts).
> > > > > > > > 
> > > > > > > > The bad news is that I have very little idea about what I'm actually
> > > > > > > > doing. Here's the branch with changes I've done, with my notes in
> > > > > > > > the commit messages:
> > > > > > > > 
> > > > > > > >   git fetch git://git.kernel.org/pub/scm/linux/kernel/git/lkundrak/linux.git \
> > > > > > > >       lr/nand/cafe-nand-exec-op-debug
> > > > > > > > 
> > > > > > > > The relevant changes:
> > > > > > > > 
> > > > > > > >   6ee7e0d11e19 fixup! mtd: rawnand: cafe: Demistify register fields        
> > > > > > > 
> > > > > > > This one is valid.
> > > > > > >       
> > > > > > > >   565d5f126e86 fixup! mtd: rawnand: cafe: Demistify register fields        
> > > > > > > 
> > > > > > > Here it should be
> > > > > > > 
> > > > > > > #define CAFE_NAND_ECC_SYN_REG(x)		((((x) / 2) * 4) + 0x50)
> > > > > > > 
> > > > > > > but maybe the loop is no longer valid after that.
> > > > > > >       
> > > > > > > >   064d381b4615 fixup! mtd: rawnand: cafe: Demistify register fields        
> > > > > > > 
> > > > > > > This one looks good too.
> > > > > > >       
> > > > > > > > 
> > > > > > > >     During the test with JFFS2 filesystem, I was seeing a metric ton of ECC
> > > > > > > >     errors. I have no clue where they came from because they presumably happened
> > > > > > > >     on an asynchronous writeback, but they no longer happen and I believe
> > > > > > > >     some of the above was to blame. Unfortunely I didn't investigate
> > > > > > > >     further, because in my setup it is hugely inconvenient to beat the image
> > > > > > > >     back into shape.
> > > > > > > > 
> > > > > > > >   085a6ad43151 Revert "mtd: rawnand: cafe: Don't leave ECC enabled in the write path"
> > > > > > > > 
> > > > > > > >     This triggered a WARN_ON(). Probably not too important, because the
> > > > > > > >     code in question gets thrown out afterwards.        
> > > > > > > 
> > > > > > > Oops. Maybe I should move it after the exec_op() conversion then.
> > > > > > >       
> > > > > > > > 
> > > > > > > >   4a9d95bf6d6b fixup! mtd: rawnand: cafe: Add exec_op() support
> > > > > > > > 
> > > > > > > >     An straightforward fix for page write op.        
> > > > > > > 
> > > > > > > Yep, that one is valid, thanks for the fix.
> > > > > > >       
> > > > > > > > 
> > > > > > > >   6959a724994d XXX add address to CMD_STATUS
> > > > > > > > 
> > > > > > > >     Tricky, and I have no idea what's going on. Perhaps you'll have an
> > > > > > > >     idea how to either address this more reasonably. As usual, I'm happy
> > > > > > > >     to apply patches with extra tracing if necessary.        
> > > > > > > 
> > > > > > > Duh, that one is super weird. I wonder if it doesn't have to do with
> > > > > > > the fact we're using DMA. Can you try with the DMA disabled?      
> > > > > 
> > > > > Disabling DMA makes things work.    
> > > > 
> > > > Okay, I pushed a new version doing DMA only where there's at least one
> > > > address cycle.    
> > > 
> > > Ok, this is somewhat embarassing:
> > > 
> > > It doesn't work, but reverting disabling DMA altogether doesn't make it
> > > work now either. It might be that it doesn't behave deterministically,
> > > but more likely I just fucked up the testing and was testing a wrong
> > > tree.  
> > 
> > No worries. It might also be me messing up with one of your fixes (I've
> > slightly changed the one fixing the SYN_REG() macro, and if others
> > have been changed, it was not intentional). What are the symptoms?
> > Still failures in the write path?  
> 
> Yes.
> 
> Now, I've looked some more into it and consulted the data sheet, and it
> seems (as the data sheet suggests) that the STAUTS and READ_ID data
> doesn't go through the same port as the transfers from the NAND memory
> array go.
> 
> We need to use the "NON_MEM" register and appropriate length registers
> as well.
> 
> This also means that neither a mistake of mine nor any funny stuff having
> been smoked have been responsible for my test results. Whatever the read
> status operation returned has in fact been what has been left in the
> data register from the previous data transfer. Also, this explains why
> DMA is avoided on ID read.
> 
> The tree that works for me is here:
> 
>   git fetch git://git.kernel.org/pub/scm/linux/kernel/git/lkundrak/linux-mmp.git \
>     lr/nand/cafe-nand-exec-op-debug
> 
> The two top commits are new and as before they're left for you to
> consider and integrate the changes.

I'd really like to avoid resorting to 'non-mem' reads if we can. Note
that 'mem' reads work just fine for READ_ID already, and I see nothing
on the controller HW interface that would explain why we need a
dedicated path for READ_STATUS either. If we really have to, because
'mem' read appear to only work when there's at least one address cycle
(as mentioned in the code), then we really want to define a new
CMD+DATA_IN(max_non_mem_data) pattern. Testing the opcode as done in
your proposal is not that great, since it doesn't cover other
operations with a CMD and DATA_IN instruction.

> 
> Below is the log from my attempt to grasp understanding of how does the
> status/id read work:
> 
>   Attempt to read 4 bytes off the status reg. The status byte ends up
>   repeated four times:
> 
>   # busybox devmem 0xfe020000 32 0x80800070                                                                                                        
>   # busybox devmem 0xfe020030
>   0xE0E0E0E0
>  
>   Read on byte of an ID: 
>   
>   # busybox devmem 0xfe020000 32 0x80100090
>   # busybox devmem 0xfe020030
>   0xE0E0E0AD
> 
>   Two bytes:
> 
>   # busybox devmem 0xfe020000 32 0x80400090                                                                                                          
>   # busybox devmem 0xfe020030
>   0xE0E0DCAD

Have you tried doing the same with a regular read
(CMD+DATA_IN(NO_DMA))? IOW, what do you get when you do:


# busybox devmem 0xfe020018 32 0x1
# busybox devmem 0xfe020040 32 0x0
# busybox devmem 0xfe020004 32 0x0
# busybox devmem 0xfe020000 32 0x84080000
# busybox devmem 0xfe021000

or

# busybox devmem 0xfe020018 32 0x4
# busybox devmem 0xfe020040 32 0x0
# busybox devmem 0xfe020004 32 0x0
# busybox devmem 0xfe020000 32 0x84080000
# busybox devmem 0xfe021000

(you can even try with more data to see if that makes a difference).

> 
> The testing I've done with this tree:
> 
>   # mtd_debug erase /dev/mtd0 0 131072                                                                                              
>   Erased 131072 bytes from address 0x00000000 in flash
>   # mtd_debug write /dev/mtd0 0 131072 xeb0                                                                                                          
>   Copied 131072 bytes from xeb0 to address 0x00000000 in flash
>   # mtd_debug read /dev/mtd0 0 131072 yeb0                                                                                                           
>   Copied 131072 bytes from address 0x00000000 in flash to yeb0
>   # md5sum xeb0 yeb0
>   8d4576a1fed8075a2f6c7a018d83e842  xeb0
>   8d4576a1fed8075a2f6c7a018d83e842  yeb0
>   # mount -t jffs2 mtd0 /mnt
>   jffs2: notice: (125) jffs2_build_xattr_subsystem: complete building xattr subsystem, 0 of xdatum (0 unchecked, 0 orphan) and 0 of xref (0 dead, 0 orphan) .
>   # touch /mnt/i-hate-computers
>   # umount /mnt
>   #
> 
> Thanks for your work and patience. Hope this helps.

Thanks for your help ;-).

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

^ permalink raw reply	[flat|nested] 46+ messages in thread

* Re: [PATCH v2 00/19] mtd: rawnand: cafe: Convert to exec_op() (and more)
  2020-05-24 14:55                                                           ` Boris Brezillon
@ 2020-05-24 15:05                                                             ` Boris Brezillon
  0 siblings, 0 replies; 46+ messages in thread
From: Boris Brezillon @ 2020-05-24 15:05 UTC (permalink / raw)
  To: Lubomir Rintel
  Cc: Richard Weinberger, Tudor Ambarus, linux-mtd,
	Vignesh Raghavendra, Miquel Raynal

On Sun, 24 May 2020 16:55:30 +0200
Boris Brezillon <boris.brezillon@collabora.com> wrote:

> Have you tried doing the same with a regular read
> (CMD+DATA_IN(NO_DMA))? IOW, what do you get when you do:
> 
> 
> # busybox devmem 0xfe020018 32 0x1
> # busybox devmem 0xfe020040 32 0x0
> # busybox devmem 0xfe020004 32 0x0
> # busybox devmem 0xfe020000 32 0x84080000

I meant

# busybox devmem 0xfe020000 32 0x84080070

> # busybox devmem 0xfe021000
> 
> or
> 
> # busybox devmem 0xfe020018 32 0x4
> # busybox devmem 0xfe020040 32 0x0
> # busybox devmem 0xfe020004 32 0x0
> # busybox devmem 0xfe020000 32 0x84080000

and

# busybox devmem 0xfe020000 32 0x84080070

> # busybox devmem 0xfe021000
> 
> (you can even try with more data to see if that makes a difference).

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

^ permalink raw reply	[flat|nested] 46+ messages in thread

* Re: [PATCH v2 00/19] mtd: rawnand: cafe: Convert to exec_op() (and more)
       [not found]                                                         ` <20200524115246.GC2781@furthur.local>
  2020-05-24 14:55                                                           ` Boris Brezillon
@ 2020-05-24 15:29                                                           ` Boris Brezillon
  1 sibling, 0 replies; 46+ messages in thread
From: Boris Brezillon @ 2020-05-24 15:29 UTC (permalink / raw)
  To: Lubomir Rintel
  Cc: Richard Weinberger, Tudor Ambarus, linux-mtd,
	Vignesh Raghavendra, Miquel Raynal

On Sun, 24 May 2020 13:52:46 +0200
Lubomir Rintel <lkundrak@v3.sk> wrote:

> > > 
> > > It doesn't work, but reverting disabling DMA altogether doesn't make it
> > > work now either. It might be that it doesn't behave deterministically,
> > > but more likely I just fucked up the testing and was testing a wrong
> > > tree.  

I've just pushed a new version [1][2] writing the DMA_CTRL
unconditionally so we don't keep the previous config (which might be a
problem if we mix DMA and !DMA accesses). Would you mind testing it?

[1]https://github.com/bbrezillon/linux/commits/nand/cafe-nand-exec-op-debug
[2]https://github.com/bbrezillon/linux/commit/9b82f0b92b17fb298bbd6328d6b84891137b9de8

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

^ permalink raw reply	[flat|nested] 46+ messages in thread

* Re: [PATCH v2 01/19] mtd: rawnand: Propage CS selection to sub operations
  2020-05-05 10:13 ` [PATCH v2 01/19] mtd: rawnand: Propage CS selection to sub operations Boris Brezillon
@ 2020-05-24 19:17   ` Miquel Raynal
  0 siblings, 0 replies; 46+ messages in thread
From: Miquel Raynal @ 2020-05-24 19:17 UTC (permalink / raw)
  To: Boris Brezillon, Miquel Raynal, linux-mtd, Lubomir Rintel
  Cc: Richard Weinberger, Vignesh Raghavendra, Tudor Ambarus

On Tue, 2020-05-05 at 10:13:35 UTC, Boris Brezillon wrote:
> Some controller using the instruction parse infrastructure might need
> to know which CS a specific sub-operation is targeting. Let's propagate
> this information.
> 
> Signed-off-by: Boris Brezillon <boris.brezillon@collabora.com>
> Reviewed-by: Miquel Raynal <miquel.raynal@bootlin.com>

Applied to https://git.kernel.org/pub/scm/linux/kernel/git/mtd/linux.git nand/next, thanks.

Miquel

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

^ permalink raw reply	[flat|nested] 46+ messages in thread

end of thread, back to index

Thread overview: 46+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-05-05 10:13 [PATCH v2 00/19] mtd: rawnand: cafe: Convert to exec_op() (and more) Boris Brezillon
2020-05-05 10:13 ` [PATCH v2 01/19] mtd: rawnand: Propage CS selection to sub operations Boris Brezillon
2020-05-24 19:17   ` Miquel Raynal
2020-05-05 10:13 ` [PATCH v2 02/19] mtd: rawnand: cafe: Get rid of an inaccurate kernel doc header Boris Brezillon
2020-05-05 10:13 ` [PATCH v2 03/19] mtd: rawnand: cafe: Rename cafe_nand_write_page_lowlevel() Boris Brezillon
2020-05-05 10:13 ` [PATCH v2 04/19] mtd: rawnand: cafe: Use a correct ECC mode and pass the ECC alg Boris Brezillon
2020-05-05 10:13 ` [PATCH v2 05/19] mtd: rawnand: cafe: Include linux/io.h instead of asm/io.h Boris Brezillon
2020-05-05 10:13 ` [PATCH v2 06/19] mtd: rawnand: cafe: Demistify register fields Boris Brezillon
     [not found]   ` <20200506204638.GB207924@furthur.local>
2020-05-06 20:53     ` Boris Brezillon
2020-05-05 10:13 ` [PATCH v2 07/19] mtd: rawnand: cafe: Factor out the controller initialization logic Boris Brezillon
2020-05-10 21:49   ` Miquel Raynal
2020-05-05 10:13 ` [PATCH v2 08/19] mtd: rawnand: cafe: Get rid of the debug module param Boris Brezillon
2020-05-05 10:13 ` [PATCH v2 09/19] mtd: rawnand: cafe: Use devm_kzalloc and devm_request_irq() Boris Brezillon
2020-05-05 10:13 ` [PATCH v2 10/19] mtd: rawnand: cafe: Get rid of a useless label Boris Brezillon
2020-05-05 10:13 ` [PATCH v2 11/19] mtd: rawnand: cafe: Explicitly inherit from nand_controller Boris Brezillon
2020-05-05 10:13 ` [PATCH v2 12/19] mtd: rawnand: cafe: Don't leave ECC enabled in the write path Boris Brezillon
2020-05-05 10:13 ` [PATCH v2 13/19] mtd: rawnand: cafe: Don't split things when reading/writing a page Boris Brezillon
2020-05-10 21:49   ` Miquel Raynal
2020-05-05 10:13 ` [PATCH v2 14/19] mtd: rawnand: cafe: Add exec_op() support Boris Brezillon
2020-05-05 10:13 ` [PATCH v2 15/19] mtd: rawnand: cafe: Get rid of the legacy interface implementation Boris Brezillon
2020-05-05 10:13 ` [PATCH v2 16/19] mtd: rawnand: cafe: Adjust the cafe_{read, write}_buf() prototypes Boris Brezillon
2020-05-05 10:13 ` [PATCH v2 17/19] mtd: rawnand: cafe: s/uint{8,16,32}_t/u{8,16,32}/ Boris Brezillon
2020-05-05 10:13 ` [PATCH v2 18/19] mtd: rawnand: cafe: Drop the cafe_{readl, writel}() wrappers Boris Brezillon
2020-05-10 21:45   ` [PATCH v2 18/19] mtd: rawnand: cafe: Drop the cafe_{readl,writel}() wrappers Miquel Raynal
2020-05-05 10:13 ` [PATCH v2 19/19] mtd: rawnand: cafe: Get rid of the last printk() Boris Brezillon
2020-05-10 21:43   ` Miquel Raynal
     [not found] ` <20200505144639.GB1997@furthur.local>
     [not found]   ` <20200505220152.GA157445@furthur.local>
2020-05-06  6:32     ` [PATCH v2 00/19] mtd: rawnand: cafe: Convert to exec_op() (and more) Boris Brezillon
     [not found]       ` <20200506155359.GA183666@furthur.local>
2020-05-06 16:11         ` Boris Brezillon
     [not found]           ` <20200506203635.GA207924@furthur.local>
2020-05-06 20:58             ` Boris Brezillon
2020-05-06 21:35             ` Boris Brezillon
     [not found]               ` <20200507134708.GA303404@furthur.local>
2020-05-07 14:11                 ` Boris Brezillon
2020-05-07 20:12                 ` Boris Brezillon
     [not found]                   ` <20200509193440.GA524772@furthur.local>
2020-05-09 20:01                     ` Boris Brezillon
     [not found]                       ` <20200509202855.GB524772@furthur.local>
2020-05-10  6:31                         ` Boris Brezillon
2020-05-10  6:45                           ` Boris Brezillon
     [not found]                             ` <20200510072108.GA587379@furthur.local>
2020-05-10  7:35                               ` Boris Brezillon
2020-05-11  8:23                                 ` Boris Brezillon
     [not found]                                   ` <20200512164057.GC604838@furthur.local>
2020-05-12 19:50                                     ` Boris Brezillon
2020-05-13 17:10                                     ` Boris Brezillon
     [not found]                                       ` <20200515144703.GA1245784@furthur.local>
     [not found]                                         ` <20200515192540.GB1245784@furthur.local>
     [not found]                                           ` <20200516145650.GA1433661@furthur.local>
2020-05-16 19:08                                             ` Boris Brezillon
2020-05-16 20:18                                               ` Boris Brezillon
     [not found]                                                 ` <20200517164709.GA1651421@furthur.local>
2020-05-18 14:50                                                   ` Boris Brezillon
     [not found]                                                     ` <20200520072331.GJ1695525@furthur.local>
2020-05-20  7:55                                                       ` Boris Brezillon
     [not found]                                                         ` <20200524115246.GC2781@furthur.local>
2020-05-24 14:55                                                           ` Boris Brezillon
2020-05-24 15:05                                                             ` Boris Brezillon
2020-05-24 15:29                                                           ` Boris Brezillon

Linux-mtd Archive on lore.kernel.org

Archives are clonable:
	git clone --mirror https://lore.kernel.org/linux-mtd/0 linux-mtd/git/0.git

	# If you have public-inbox 1.1+ installed, you may
	# initialize and index your mirror using the following commands:
	public-inbox-init -V2 linux-mtd linux-mtd/ https://lore.kernel.org/linux-mtd \
		linux-mtd@lists.infradead.org
	public-inbox-index linux-mtd

Example config snippet for mirrors

Newsgroup available over NNTP:
	nntp://nntp.lore.kernel.org/org.infradead.lists.linux-mtd


AGPL code for this site: git clone https://public-inbox.org/public-inbox.git