All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v4 0/4] Mediatek MT2712 NAND FLASH Controller driver
@ 2017-05-31  3:37 ` Xiaolei Li
  0 siblings, 0 replies; 22+ messages in thread
From: Xiaolei Li @ 2017-05-31  3:37 UTC (permalink / raw)
  To: boris.brezillon, computersforpeace, matthias.bgg
  Cc: dwmw2, linux-mtd, linux-mediatek, robh+dt, rogercc.lin, yt.shen,
	srv_heupstream, xiaolei.li

The following patch-set adds support for Mediatek MT2712 NAND FLASH
Controller.

Changes on v4 relative to:
--------------------

tree    : https://github.com/bbrezillon/linux-0day
branch  : nand/next
commit  :
        'commit 2b12c057cc28 ("mtd: nand: brcmnand: Check flash #WP pin
         status before nand erase/program")'

Patch v4:
---------
- remove spare size array sort. iterate over all entries of spare size
  table and pick the best one.

Patch v3:
---------
- separate patches into 4.
- rename struct mtk_ecc_devdata and struct mtk_nfc_devdata to struct
  mtk_ecc_caps and struct mtk_nfc_caps respectively.
- add variables const u8 *ecc_strength and u8 num_ecc_strength into struct
  mtk_ecc_caps, and remove u8 max_ecc_strength.
- rename variabl u32 temp in function mtk_ecc_probe to u32 max_eccdata_size.
- remove ECC_CNFG_xBIT define, use a for loop to do ecc hw configuration.
- remove const u32 *spare_format from struct mtk_nfc_caps, and add variables
  u8 num_spare_size and u8 pageformat_spare_shift.
- remove PAGEFMT_SPARE_ define, use a for loop to do nfc hw configuration.
- sort spare size array before setting spare size.
- fix coding style issue.

Patch v2:
---------
- sperate patches into 3.
- refine DT bindings documentation about NFC and ECC compatible.
- use ecc->devdata->encode_parity_reg0 and ecc->devdata->err_mask
  directly, but hide them in define.

Tests:
------

* ubifs and jffs2 are validated on NAND device MT29F16G08ADBCA
  by 'dd' command.
* all drivers/mtd/tests/* pass.
* speed test:
  eraseblock write speed is 8318 KiB/s
  eraseblock read speed is 11374 KiB/s
  page write speed is 8155 KiB/s
  page read speed is 11290 KiB/s
  2 page write speed is 8217 KiB/s
  2 page read speed is 11354 KiB/s
  erase speed is 116472 KiB/s
  2x multi-block erase speed is 352978 KiB/s
  4x multi-block erase speed is 359750 KiB/s
  8x multi-block erase speed is 361484 KiB/s
  16x multi-block erase speed is 364116 KiB/s
  32x multi-block erase speed is 364116 KiB/s
  64x multi-block erase speed is 364116 KiB/s

Xiaolei Li (4):
  mtd: nand: mediatek: update DT bindings
  mtd: nand: mediatek: refine register NFI_PAGEFMT setting
  mtd: nand: mediatek: add support for different MTK NAND FLASH
    Controller IP
  mtd: nand: mediatek: add support for MT2712 NAND FLASH Controller

 Documentation/devicetree/bindings/mtd/mtk-nand.txt |   5 +-
 drivers/mtd/nand/mtk_ecc.c                         | 218 ++++++++++-----------
 drivers/mtd/nand/mtk_ecc.h                         |   2 +-
 drivers/mtd/nand/mtk_nand.c                        | 183 +++++++++--------
 4 files changed, 202 insertions(+), 206 deletions(-)

--
1.9.1

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

* [PATCH v4 0/4] Mediatek MT2712 NAND FLASH Controller driver
@ 2017-05-31  3:37 ` Xiaolei Li
  0 siblings, 0 replies; 22+ messages in thread
From: Xiaolei Li @ 2017-05-31  3:37 UTC (permalink / raw)
  To: boris.brezillon-wi1+55ScJUtKEb57/3fJTNBPR1lH4CV8,
	computersforpeace-Re5JQEeQqe8AvxtiuMwx3w,
	matthias.bgg-Re5JQEeQqe8AvxtiuMwx3w
  Cc: srv_heupstream-NuS5LvNUpcJWk0Htik3J/w,
	robh+dt-DgEjT+Ai2ygdnm+yROfE0A,
	linux-mtd-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	yt.shen-NuS5LvNUpcJWk0Htik3J/w,
	linux-mediatek-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	xiaolei.li-NuS5LvNUpcJWk0Htik3J/w, dwmw2-wEGCiKHe2LqWVfeAwA7xHQ,
	rogercc.lin-NuS5LvNUpcJWk0Htik3J/w

The following patch-set adds support for Mediatek MT2712 NAND FLASH
Controller.

Changes on v4 relative to:
--------------------

tree    : https://github.com/bbrezillon/linux-0day
branch  : nand/next
commit  :
        'commit 2b12c057cc28 ("mtd: nand: brcmnand: Check flash #WP pin
         status before nand erase/program")'

Patch v4:
---------
- remove spare size array sort. iterate over all entries of spare size
  table and pick the best one.

Patch v3:
---------
- separate patches into 4.
- rename struct mtk_ecc_devdata and struct mtk_nfc_devdata to struct
  mtk_ecc_caps and struct mtk_nfc_caps respectively.
- add variables const u8 *ecc_strength and u8 num_ecc_strength into struct
  mtk_ecc_caps, and remove u8 max_ecc_strength.
- rename variabl u32 temp in function mtk_ecc_probe to u32 max_eccdata_size.
- remove ECC_CNFG_xBIT define, use a for loop to do ecc hw configuration.
- remove const u32 *spare_format from struct mtk_nfc_caps, and add variables
  u8 num_spare_size and u8 pageformat_spare_shift.
- remove PAGEFMT_SPARE_ define, use a for loop to do nfc hw configuration.
- sort spare size array before setting spare size.
- fix coding style issue.

Patch v2:
---------
- sperate patches into 3.
- refine DT bindings documentation about NFC and ECC compatible.
- use ecc->devdata->encode_parity_reg0 and ecc->devdata->err_mask
  directly, but hide them in define.

Tests:
------

* ubifs and jffs2 are validated on NAND device MT29F16G08ADBCA
  by 'dd' command.
* all drivers/mtd/tests/* pass.
* speed test:
  eraseblock write speed is 8318 KiB/s
  eraseblock read speed is 11374 KiB/s
  page write speed is 8155 KiB/s
  page read speed is 11290 KiB/s
  2 page write speed is 8217 KiB/s
  2 page read speed is 11354 KiB/s
  erase speed is 116472 KiB/s
  2x multi-block erase speed is 352978 KiB/s
  4x multi-block erase speed is 359750 KiB/s
  8x multi-block erase speed is 361484 KiB/s
  16x multi-block erase speed is 364116 KiB/s
  32x multi-block erase speed is 364116 KiB/s
  64x multi-block erase speed is 364116 KiB/s

Xiaolei Li (4):
  mtd: nand: mediatek: update DT bindings
  mtd: nand: mediatek: refine register NFI_PAGEFMT setting
  mtd: nand: mediatek: add support for different MTK NAND FLASH
    Controller IP
  mtd: nand: mediatek: add support for MT2712 NAND FLASH Controller

 Documentation/devicetree/bindings/mtd/mtk-nand.txt |   5 +-
 drivers/mtd/nand/mtk_ecc.c                         | 218 ++++++++++-----------
 drivers/mtd/nand/mtk_ecc.h                         |   2 +-
 drivers/mtd/nand/mtk_nand.c                        | 183 +++++++++--------
 4 files changed, 202 insertions(+), 206 deletions(-)

--
1.9.1

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

* [PATCH v4 1/4] mtd: nand: mediatek: update DT bindings
@ 2017-05-31  3:37   ` Xiaolei Li
  0 siblings, 0 replies; 22+ messages in thread
From: Xiaolei Li @ 2017-05-31  3:37 UTC (permalink / raw)
  To: boris.brezillon, computersforpeace, matthias.bgg
  Cc: dwmw2, linux-mtd, linux-mediatek, robh+dt, rogercc.lin, yt.shen,
	srv_heupstream, xiaolei.li

Add MT2712 NAND Flash Controller dt bindings documentation.

Signed-off-by: Xiaolei Li <xiaolei.li@mediatek.com>
Reviewed-by: Matthias Brugger <matthias.bgg@gmail.com>
---
 Documentation/devicetree/bindings/mtd/mtk-nand.txt | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)

diff --git a/Documentation/devicetree/bindings/mtd/mtk-nand.txt b/Documentation/devicetree/bindings/mtd/mtk-nand.txt
index 069c192..dbf9e05 100644
--- a/Documentation/devicetree/bindings/mtd/mtk-nand.txt
+++ b/Documentation/devicetree/bindings/mtd/mtk-nand.txt
@@ -12,7 +12,8 @@ tree nodes.
 
 The first part of NFC is NAND Controller Interface (NFI) HW.
 Required NFI properties:
-- compatible:			Should be "mediatek,mtxxxx-nfc".
+- compatible:			Should be one of "mediatek,mt2701-nfc",
+				"mediatek,mt2712-nfc".
 - reg:				Base physical address and size of NFI.
 - interrupts:			Interrupts of NFI.
 - clocks:			NFI required clocks.
@@ -141,7 +142,7 @@ Example:
 ==============
 
 Required BCH properties:
-- compatible:	Should be "mediatek,mtxxxx-ecc".
+- compatible:	Should be one of "mediatek,mt2701-ecc", "mediatek,mt2712-ecc".
 - reg:		Base physical address and size of ECC.
 - interrupts:	Interrupts of ECC.
 - clocks:	ECC required clocks.
-- 
1.9.1

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

* [PATCH v4 1/4] mtd: nand: mediatek: update DT bindings
@ 2017-05-31  3:37   ` Xiaolei Li
  0 siblings, 0 replies; 22+ messages in thread
From: Xiaolei Li @ 2017-05-31  3:37 UTC (permalink / raw)
  To: boris.brezillon-wi1+55ScJUtKEb57/3fJTNBPR1lH4CV8,
	computersforpeace-Re5JQEeQqe8AvxtiuMwx3w,
	matthias.bgg-Re5JQEeQqe8AvxtiuMwx3w
  Cc: srv_heupstream-NuS5LvNUpcJWk0Htik3J/w,
	robh+dt-DgEjT+Ai2ygdnm+yROfE0A,
	linux-mtd-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	yt.shen-NuS5LvNUpcJWk0Htik3J/w,
	linux-mediatek-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	xiaolei.li-NuS5LvNUpcJWk0Htik3J/w, dwmw2-wEGCiKHe2LqWVfeAwA7xHQ,
	rogercc.lin-NuS5LvNUpcJWk0Htik3J/w

Add MT2712 NAND Flash Controller dt bindings documentation.

Signed-off-by: Xiaolei Li <xiaolei.li-NuS5LvNUpcJWk0Htik3J/w@public.gmane.org>
Reviewed-by: Matthias Brugger <matthias.bgg-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
---
 Documentation/devicetree/bindings/mtd/mtk-nand.txt | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)

diff --git a/Documentation/devicetree/bindings/mtd/mtk-nand.txt b/Documentation/devicetree/bindings/mtd/mtk-nand.txt
index 069c192..dbf9e05 100644
--- a/Documentation/devicetree/bindings/mtd/mtk-nand.txt
+++ b/Documentation/devicetree/bindings/mtd/mtk-nand.txt
@@ -12,7 +12,8 @@ tree nodes.
 
 The first part of NFC is NAND Controller Interface (NFI) HW.
 Required NFI properties:
-- compatible:			Should be "mediatek,mtxxxx-nfc".
+- compatible:			Should be one of "mediatek,mt2701-nfc",
+				"mediatek,mt2712-nfc".
 - reg:				Base physical address and size of NFI.
 - interrupts:			Interrupts of NFI.
 - clocks:			NFI required clocks.
@@ -141,7 +142,7 @@ Example:
 ==============
 
 Required BCH properties:
-- compatible:	Should be "mediatek,mtxxxx-ecc".
+- compatible:	Should be one of "mediatek,mt2701-ecc", "mediatek,mt2712-ecc".
 - reg:		Base physical address and size of ECC.
 - interrupts:	Interrupts of ECC.
 - clocks:	ECC required clocks.
-- 
1.9.1

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

* [PATCH v4 2/4] mtd: nand: mediatek: refine register NFI_PAGEFMT setting
@ 2017-05-31  3:37   ` Xiaolei Li
  0 siblings, 0 replies; 22+ messages in thread
From: Xiaolei Li @ 2017-05-31  3:37 UTC (permalink / raw)
  To: boris.brezillon, computersforpeace, matthias.bgg
  Cc: dwmw2, linux-mtd, linux-mediatek, robh+dt, rogercc.lin, yt.shen,
	srv_heupstream, xiaolei.li

The register NFI_PAGEFMT is always 32 bits length, so it is better to
do register program using writel() compare with writew().

Signed-off-by: Xiaolei Li <xiaolei.li@mediatek.com>
---
 drivers/mtd/nand/mtk_nand.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/mtd/nand/mtk_nand.c b/drivers/mtd/nand/mtk_nand.c
index 6c517c6..c28f4b7 100644
--- a/drivers/mtd/nand/mtk_nand.c
+++ b/drivers/mtd/nand/mtk_nand.c
@@ -408,7 +408,7 @@ static int mtk_nfc_hw_runtime_config(struct mtd_info *mtd)
 
 	fmt |= mtk_nand->fdm.reg_size << PAGEFMT_FDM_SHIFT;
 	fmt |= mtk_nand->fdm.ecc_size << PAGEFMT_FDM_ECC_SHIFT;
-	nfi_writew(nfc, fmt, NFI_PAGEFMT);
+	nfi_writel(nfc, fmt, NFI_PAGEFMT);
 
 	nfc->ecc_cfg.strength = chip->ecc.strength;
 	nfc->ecc_cfg.len = chip->ecc.size + mtk_nand->fdm.ecc_size;
@@ -1009,7 +1009,7 @@ static inline void mtk_nfc_hw_init(struct mtk_nfc *nfc)
 	 * 0  : poll the status of the busy/ready signal after [7:4]*16 cycles.
 	 */
 	nfi_writew(nfc, 0xf1, NFI_CNRNB);
-	nfi_writew(nfc, PAGEFMT_8K_16K, NFI_PAGEFMT);
+	nfi_writel(nfc, PAGEFMT_8K_16K, NFI_PAGEFMT);
 
 	mtk_nfc_hw_reset(nfc);
 
-- 
1.9.1

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

* [PATCH v4 2/4] mtd: nand: mediatek: refine register NFI_PAGEFMT setting
@ 2017-05-31  3:37   ` Xiaolei Li
  0 siblings, 0 replies; 22+ messages in thread
From: Xiaolei Li @ 2017-05-31  3:37 UTC (permalink / raw)
  To: boris.brezillon-wi1+55ScJUtKEb57/3fJTNBPR1lH4CV8,
	computersforpeace-Re5JQEeQqe8AvxtiuMwx3w,
	matthias.bgg-Re5JQEeQqe8AvxtiuMwx3w
  Cc: srv_heupstream-NuS5LvNUpcJWk0Htik3J/w,
	robh+dt-DgEjT+Ai2ygdnm+yROfE0A,
	linux-mtd-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	yt.shen-NuS5LvNUpcJWk0Htik3J/w,
	linux-mediatek-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	xiaolei.li-NuS5LvNUpcJWk0Htik3J/w, dwmw2-wEGCiKHe2LqWVfeAwA7xHQ,
	rogercc.lin-NuS5LvNUpcJWk0Htik3J/w

The register NFI_PAGEFMT is always 32 bits length, so it is better to
do register program using writel() compare with writew().

Signed-off-by: Xiaolei Li <xiaolei.li-NuS5LvNUpcJWk0Htik3J/w@public.gmane.org>
---
 drivers/mtd/nand/mtk_nand.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/mtd/nand/mtk_nand.c b/drivers/mtd/nand/mtk_nand.c
index 6c517c6..c28f4b7 100644
--- a/drivers/mtd/nand/mtk_nand.c
+++ b/drivers/mtd/nand/mtk_nand.c
@@ -408,7 +408,7 @@ static int mtk_nfc_hw_runtime_config(struct mtd_info *mtd)
 
 	fmt |= mtk_nand->fdm.reg_size << PAGEFMT_FDM_SHIFT;
 	fmt |= mtk_nand->fdm.ecc_size << PAGEFMT_FDM_ECC_SHIFT;
-	nfi_writew(nfc, fmt, NFI_PAGEFMT);
+	nfi_writel(nfc, fmt, NFI_PAGEFMT);
 
 	nfc->ecc_cfg.strength = chip->ecc.strength;
 	nfc->ecc_cfg.len = chip->ecc.size + mtk_nand->fdm.ecc_size;
@@ -1009,7 +1009,7 @@ static inline void mtk_nfc_hw_init(struct mtk_nfc *nfc)
 	 * 0  : poll the status of the busy/ready signal after [7:4]*16 cycles.
 	 */
 	nfi_writew(nfc, 0xf1, NFI_CNRNB);
-	nfi_writew(nfc, PAGEFMT_8K_16K, NFI_PAGEFMT);
+	nfi_writel(nfc, PAGEFMT_8K_16K, NFI_PAGEFMT);
 
 	mtk_nfc_hw_reset(nfc);
 
-- 
1.9.1

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

* [PATCH v4 3/4] mtd: nand: mediatek: add support for different MTK NAND FLASH Controller IP
@ 2017-05-31  3:37   ` Xiaolei Li
  0 siblings, 0 replies; 22+ messages in thread
From: Xiaolei Li @ 2017-05-31  3:37 UTC (permalink / raw)
  To: boris.brezillon, computersforpeace, matthias.bgg
  Cc: dwmw2, linux-mtd, linux-mediatek, robh+dt, rogercc.lin, yt.shen,
	srv_heupstream, xiaolei.li

ECC strength and spare size supported may be different among MTK NAND
FLASH Controller IPs.

This patch contains changes as following:
(1) add new struct mtk_nfc_caps to support different spare size.
(2) add new struct mtk_ecc_caps to support different ecc strength.
(3) remove ECC_CNFG_xBIT define, use a for loop to do ecc strength config.
(4) remove PAGEFMT_SPARE_ define, use a for loop to do spare format config.
(5) malloc ecc->eccdata buffer according to max ecc strength of this IP.

Signed-off-by: Xiaolei Li <xiaolei.li@mediatek.com>
---
 drivers/mtd/nand/mtk_ecc.c  | 181 ++++++++++++++++++--------------------------
 drivers/mtd/nand/mtk_ecc.h  |   2 +-
 drivers/mtd/nand/mtk_nand.c | 165 ++++++++++++++++++----------------------
 3 files changed, 149 insertions(+), 199 deletions(-)

diff --git a/drivers/mtd/nand/mtk_ecc.c b/drivers/mtd/nand/mtk_ecc.c
index dbf2562..ae51303 100644
--- a/drivers/mtd/nand/mtk_ecc.c
+++ b/drivers/mtd/nand/mtk_ecc.c
@@ -33,26 +33,6 @@
 
 #define ECC_ENCCON		(0x00)
 #define ECC_ENCCNFG		(0x04)
-#define		ECC_CNFG_4BIT		(0)
-#define		ECC_CNFG_6BIT		(1)
-#define		ECC_CNFG_8BIT		(2)
-#define		ECC_CNFG_10BIT		(3)
-#define		ECC_CNFG_12BIT		(4)
-#define		ECC_CNFG_14BIT		(5)
-#define		ECC_CNFG_16BIT		(6)
-#define		ECC_CNFG_18BIT		(7)
-#define		ECC_CNFG_20BIT		(8)
-#define		ECC_CNFG_22BIT		(9)
-#define		ECC_CNFG_24BIT		(0xa)
-#define		ECC_CNFG_28BIT		(0xb)
-#define		ECC_CNFG_32BIT		(0xc)
-#define		ECC_CNFG_36BIT		(0xd)
-#define		ECC_CNFG_40BIT		(0xe)
-#define		ECC_CNFG_44BIT		(0xf)
-#define		ECC_CNFG_48BIT		(0x10)
-#define		ECC_CNFG_52BIT		(0x11)
-#define		ECC_CNFG_56BIT		(0x12)
-#define		ECC_CNFG_60BIT		(0x13)
 #define		ECC_MODE_SHIFT		(5)
 #define		ECC_MS_SHIFT		(16)
 #define ECC_ENCDIADDR		(0x08)
@@ -66,7 +46,6 @@
 #define		DEC_CNFG_CORRECT	(0x3 << 12)
 #define ECC_DECIDLE		(0x10C)
 #define ECC_DECENUM0		(0x114)
-#define		ERR_MASK		(0x3f)
 #define ECC_DECDONE		(0x124)
 #define ECC_DECIRQ_EN		(0x200)
 #define ECC_DECIRQ_STA		(0x204)
@@ -78,8 +57,15 @@
 #define ECC_IRQ_REG(op)		((op) == ECC_ENCODE ? \
 					ECC_ENCIRQ_EN : ECC_DECIRQ_EN)
 
+struct mtk_ecc_caps {
+	u32 err_mask;
+	const u8 *ecc_strength;
+	u8 num_ecc_strength;
+};
+
 struct mtk_ecc {
 	struct device *dev;
+	const struct mtk_ecc_caps *caps;
 	void __iomem *regs;
 	struct clk *clk;
 
@@ -87,7 +73,13 @@ struct mtk_ecc {
 	struct mutex lock;
 	u32 sectors;
 
-	u8 eccdata[112];
+	u8 *eccdata;
+};
+
+/* ecc strength that mt2701 supports */
+static const u8 ecc_strength_mt2701[] = {
+	4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 28, 32, 36,
+	40, 44, 48, 52, 56, 60
 };
 
 static inline void mtk_ecc_wait_idle(struct mtk_ecc *ecc,
@@ -136,77 +128,24 @@ static irqreturn_t mtk_ecc_irq(int irq, void *id)
 	return IRQ_HANDLED;
 }
 
-static void mtk_ecc_config(struct mtk_ecc *ecc, struct mtk_ecc_config *config)
+static int mtk_ecc_config(struct mtk_ecc *ecc, struct mtk_ecc_config *config)
 {
-	u32 ecc_bit = ECC_CNFG_4BIT, dec_sz, enc_sz;
-	u32 reg;
-
-	switch (config->strength) {
-	case 4:
-		ecc_bit = ECC_CNFG_4BIT;
-		break;
-	case 6:
-		ecc_bit = ECC_CNFG_6BIT;
-		break;
-	case 8:
-		ecc_bit = ECC_CNFG_8BIT;
-		break;
-	case 10:
-		ecc_bit = ECC_CNFG_10BIT;
-		break;
-	case 12:
-		ecc_bit = ECC_CNFG_12BIT;
-		break;
-	case 14:
-		ecc_bit = ECC_CNFG_14BIT;
-		break;
-	case 16:
-		ecc_bit = ECC_CNFG_16BIT;
-		break;
-	case 18:
-		ecc_bit = ECC_CNFG_18BIT;
-		break;
-	case 20:
-		ecc_bit = ECC_CNFG_20BIT;
-		break;
-	case 22:
-		ecc_bit = ECC_CNFG_22BIT;
-		break;
-	case 24:
-		ecc_bit = ECC_CNFG_24BIT;
-		break;
-	case 28:
-		ecc_bit = ECC_CNFG_28BIT;
-		break;
-	case 32:
-		ecc_bit = ECC_CNFG_32BIT;
-		break;
-	case 36:
-		ecc_bit = ECC_CNFG_36BIT;
-		break;
-	case 40:
-		ecc_bit = ECC_CNFG_40BIT;
-		break;
-	case 44:
-		ecc_bit = ECC_CNFG_44BIT;
-		break;
-	case 48:
-		ecc_bit = ECC_CNFG_48BIT;
-		break;
-	case 52:
-		ecc_bit = ECC_CNFG_52BIT;
-		break;
-	case 56:
-		ecc_bit = ECC_CNFG_56BIT;
-		break;
-	case 60:
-		ecc_bit = ECC_CNFG_60BIT;
-		break;
-	default:
-		dev_err(ecc->dev, "invalid strength %d, default to 4 bits\n",
+	u32 ecc_bit, dec_sz, enc_sz;
+	u32 reg, i;
+
+	for (i = 0; i < ecc->caps->num_ecc_strength; i++) {
+		if (ecc->caps->ecc_strength[i] == config->strength)
+			break;
+	}
+
+	if (i == ecc->caps->num_ecc_strength) {
+		dev_err(ecc->dev, "invalid ecc strength %d\n",
 			config->strength);
+		return -EINVAL;
 	}
 
+	ecc_bit = i;
+
 	if (config->op == ECC_ENCODE) {
 		/* configure ECC encoder (in bits) */
 		enc_sz = config->len << 3;
@@ -232,6 +171,8 @@ static void mtk_ecc_config(struct mtk_ecc *ecc, struct mtk_ecc_config *config)
 		if (config->sectors)
 			ecc->sectors = 1 << (config->sectors - 1);
 	}
+
+	return 0;
 }
 
 void mtk_ecc_get_stats(struct mtk_ecc *ecc, struct mtk_ecc_stats *stats,
@@ -247,8 +188,8 @@ void mtk_ecc_get_stats(struct mtk_ecc *ecc, struct mtk_ecc_stats *stats,
 		offset = (i >> 2) << 2;
 		err = readl(ecc->regs + ECC_DECENUM0 + offset);
 		err = err >> ((i % 4) * 8);
-		err &= ERR_MASK;
-		if (err == ERR_MASK) {
+		err &= ecc->caps->err_mask;
+		if (err == ecc->caps->err_mask) {
 			/* uncorrectable errors */
 			stats->failed++;
 			continue;
@@ -322,7 +263,11 @@ int mtk_ecc_enable(struct mtk_ecc *ecc, struct mtk_ecc_config *config)
 	}
 
 	mtk_ecc_wait_idle(ecc, op);
-	mtk_ecc_config(ecc, config);
+
+	ret = mtk_ecc_config(ecc, config);
+	if (ret)
+		return ret;
+
 	writew(ECC_OP_ENABLE, ecc->regs + ECC_CTL_REG(op));
 
 	init_completion(&ecc->done);
@@ -409,37 +354,66 @@ int mtk_ecc_encode(struct mtk_ecc *ecc, struct mtk_ecc_config *config,
 }
 EXPORT_SYMBOL(mtk_ecc_encode);
 
-void mtk_ecc_adjust_strength(u32 *p)
+void mtk_ecc_adjust_strength(struct mtk_ecc *ecc, u32 *p)
 {
-	u32 ecc[] = {4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 28, 32, 36,
-			40, 44, 48, 52, 56, 60};
+	const u8 *ecc_strength = ecc->caps->ecc_strength;
 	int i;
 
-	for (i = 0; i < ARRAY_SIZE(ecc); i++) {
-		if (*p <= ecc[i]) {
+	for (i = 0; i < ecc->caps->num_ecc_strength; i++) {
+		if (*p <= ecc_strength[i]) {
 			if (!i)
-				*p = ecc[i];
-			else if (*p != ecc[i])
-				*p = ecc[i - 1];
+				*p = ecc_strength[i];
+			else if (*p != ecc_strength[i])
+				*p = ecc_strength[i - 1];
 			return;
 		}
 	}
 
-	*p = ecc[ARRAY_SIZE(ecc) - 1];
+	*p = ecc_strength[ecc->caps->num_ecc_strength - 1];
 }
 EXPORT_SYMBOL(mtk_ecc_adjust_strength);
 
+static const struct mtk_ecc_caps mtk_ecc_caps_mt2701 = {
+	.err_mask = 0x3f,
+	.ecc_strength = ecc_strength_mt2701,
+	.num_ecc_strength = 20,
+};
+
+static const struct of_device_id mtk_ecc_dt_match[] = {
+	{
+		.compatible = "mediatek,mt2701-ecc",
+		.data = &mtk_ecc_caps_mt2701,
+	},
+	{},
+};
+
 static int mtk_ecc_probe(struct platform_device *pdev)
 {
 	struct device *dev = &pdev->dev;
 	struct mtk_ecc *ecc;
 	struct resource *res;
+	const struct of_device_id *of_ecc_id = NULL;
+	u32 max_eccdata_size;
 	int irq, ret;
 
 	ecc = devm_kzalloc(dev, sizeof(*ecc), GFP_KERNEL);
 	if (!ecc)
 		return -ENOMEM;
 
+	of_ecc_id = of_match_device(mtk_ecc_dt_match, &pdev->dev);
+	if (!of_ecc_id)
+		return -ENODEV;
+
+	ecc->caps = of_ecc_id->data;
+
+	max_eccdata_size = ecc->caps->num_ecc_strength - 1;
+	max_eccdata_size = ecc->caps->ecc_strength[max_eccdata_size];
+	max_eccdata_size = (max_eccdata_size * ECC_PARITY_BITS + 7) >> 3;
+	max_eccdata_size = round_up(max_eccdata_size, 4);
+	ecc->eccdata = devm_kzalloc(dev, max_eccdata_size, GFP_KERNEL);
+	if (!ecc->eccdata)
+		return -ENOMEM;
+
 	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 	ecc->regs = devm_ioremap_resource(dev, res);
 	if (IS_ERR(ecc->regs)) {
@@ -508,11 +482,6 @@ static int mtk_ecc_resume(struct device *dev)
 static SIMPLE_DEV_PM_OPS(mtk_ecc_pm_ops, mtk_ecc_suspend, mtk_ecc_resume);
 #endif
 
-static const struct of_device_id mtk_ecc_dt_match[] = {
-	{ .compatible = "mediatek,mt2701-ecc" },
-	{},
-};
-
 MODULE_DEVICE_TABLE(of, mtk_ecc_dt_match);
 
 static struct platform_driver mtk_ecc_driver = {
diff --git a/drivers/mtd/nand/mtk_ecc.h b/drivers/mtd/nand/mtk_ecc.h
index cbeba5c..d245c14 100644
--- a/drivers/mtd/nand/mtk_ecc.h
+++ b/drivers/mtd/nand/mtk_ecc.h
@@ -42,7 +42,7 @@ struct mtk_ecc_config {
 int mtk_ecc_wait_done(struct mtk_ecc *, enum mtk_ecc_operation);
 int mtk_ecc_enable(struct mtk_ecc *, struct mtk_ecc_config *);
 void mtk_ecc_disable(struct mtk_ecc *);
-void mtk_ecc_adjust_strength(u32 *);
+void mtk_ecc_adjust_strength(struct mtk_ecc *ecc, u32 *p);
 
 struct mtk_ecc *of_mtk_ecc_get(struct device_node *);
 void mtk_ecc_release(struct mtk_ecc *);
diff --git a/drivers/mtd/nand/mtk_nand.c b/drivers/mtd/nand/mtk_nand.c
index c28f4b7..d968b59 100644
--- a/drivers/mtd/nand/mtk_nand.c
+++ b/drivers/mtd/nand/mtk_nand.c
@@ -24,6 +24,7 @@
 #include <linux/module.h>
 #include <linux/iopoll.h>
 #include <linux/of.h>
+#include <linux/of_device.h>
 #include "mtk_ecc.h"
 
 /* NAND controller register definition */
@@ -38,23 +39,6 @@
 #define NFI_PAGEFMT		(0x04)
 #define		PAGEFMT_FDM_ECC_SHIFT	(12)
 #define		PAGEFMT_FDM_SHIFT	(8)
-#define		PAGEFMT_SPARE_16	(0)
-#define		PAGEFMT_SPARE_26	(1)
-#define		PAGEFMT_SPARE_27	(2)
-#define		PAGEFMT_SPARE_28	(3)
-#define		PAGEFMT_SPARE_32	(4)
-#define		PAGEFMT_SPARE_36	(5)
-#define		PAGEFMT_SPARE_40	(6)
-#define		PAGEFMT_SPARE_44	(7)
-#define		PAGEFMT_SPARE_48	(8)
-#define		PAGEFMT_SPARE_49	(9)
-#define		PAGEFMT_SPARE_50	(0xa)
-#define		PAGEFMT_SPARE_51	(0xb)
-#define		PAGEFMT_SPARE_52	(0xc)
-#define		PAGEFMT_SPARE_62	(0xd)
-#define		PAGEFMT_SPARE_63	(0xe)
-#define		PAGEFMT_SPARE_64	(0xf)
-#define		PAGEFMT_SPARE_SHIFT	(4)
 #define		PAGEFMT_SEC_SEL_512	BIT(2)
 #define		PAGEFMT_512_2K		(0)
 #define		PAGEFMT_2K_4K		(1)
@@ -116,6 +100,12 @@
 #define MTK_MAX_SECTOR		(16)
 #define MTK_NAND_MAX_NSELS	(2)
 
+struct mtk_nfc_caps {
+	const u8 *spare_size;
+	u8 num_spare_size;
+	u8 pageformat_spare_shift;
+};
+
 struct mtk_nfc_bad_mark_ctl {
 	void (*bm_swap)(struct mtd_info *, u8 *buf, int raw);
 	u32 sec;
@@ -155,6 +145,7 @@ struct mtk_nfc {
 	struct mtk_ecc *ecc;
 
 	struct device *dev;
+	const struct mtk_nfc_caps *caps;
 	void __iomem *regs;
 
 	struct completion done;
@@ -163,6 +154,15 @@ struct mtk_nfc {
 	u8 *buffer;
 };
 
+/*
+ * supported spare size of each IP.
+ * order should be the same with the spare size bitfiled defination of
+ * register NFI_PAGEFMT.
+ */
+static const u8 spare_size_mt2701[] = {
+	16, 26, 27, 28, 32, 36, 40, 44,	48, 49, 50, 51, 52, 62, 63, 64
+};
+
 static inline struct mtk_nfc_nand_chip *to_mtk_nand(struct nand_chip *nand)
 {
 	return container_of(nand, struct mtk_nfc_nand_chip, nand);
@@ -308,7 +308,7 @@ static int mtk_nfc_hw_runtime_config(struct mtd_info *mtd)
 	struct nand_chip *chip = mtd_to_nand(mtd);
 	struct mtk_nfc_nand_chip *mtk_nand = to_mtk_nand(chip);
 	struct mtk_nfc *nfc = nand_get_controller_data(chip);
-	u32 fmt, spare;
+	u32 fmt, spare, i;
 
 	if (!mtd->writesize)
 		return 0;
@@ -352,60 +352,18 @@ static int mtk_nfc_hw_runtime_config(struct mtd_info *mtd)
 	if (chip->ecc.size == 1024)
 		spare >>= 1;
 
-	switch (spare) {
-	case 16:
-		fmt |= (PAGEFMT_SPARE_16 << PAGEFMT_SPARE_SHIFT);
-		break;
-	case 26:
-		fmt |= (PAGEFMT_SPARE_26 << PAGEFMT_SPARE_SHIFT);
-		break;
-	case 27:
-		fmt |= (PAGEFMT_SPARE_27 << PAGEFMT_SPARE_SHIFT);
-		break;
-	case 28:
-		fmt |= (PAGEFMT_SPARE_28 << PAGEFMT_SPARE_SHIFT);
-		break;
-	case 32:
-		fmt |= (PAGEFMT_SPARE_32 << PAGEFMT_SPARE_SHIFT);
-		break;
-	case 36:
-		fmt |= (PAGEFMT_SPARE_36 << PAGEFMT_SPARE_SHIFT);
-		break;
-	case 40:
-		fmt |= (PAGEFMT_SPARE_40 << PAGEFMT_SPARE_SHIFT);
-		break;
-	case 44:
-		fmt |= (PAGEFMT_SPARE_44 << PAGEFMT_SPARE_SHIFT);
-		break;
-	case 48:
-		fmt |= (PAGEFMT_SPARE_48 << PAGEFMT_SPARE_SHIFT);
-		break;
-	case 49:
-		fmt |= (PAGEFMT_SPARE_49 << PAGEFMT_SPARE_SHIFT);
-		break;
-	case 50:
-		fmt |= (PAGEFMT_SPARE_50 << PAGEFMT_SPARE_SHIFT);
-		break;
-	case 51:
-		fmt |= (PAGEFMT_SPARE_51 << PAGEFMT_SPARE_SHIFT);
-		break;
-	case 52:
-		fmt |= (PAGEFMT_SPARE_52 << PAGEFMT_SPARE_SHIFT);
-		break;
-	case 62:
-		fmt |= (PAGEFMT_SPARE_62 << PAGEFMT_SPARE_SHIFT);
-		break;
-	case 63:
-		fmt |= (PAGEFMT_SPARE_63 << PAGEFMT_SPARE_SHIFT);
-		break;
-	case 64:
-		fmt |= (PAGEFMT_SPARE_64 << PAGEFMT_SPARE_SHIFT);
-		break;
-	default:
-		dev_err(nfc->dev, "invalid spare per sector %d\n", spare);
+	for (i = 0; i < nfc->caps->num_spare_size; i++) {
+		if (nfc->caps->spare_size[i] == spare)
+			break;
+	}
+
+	if (i == nfc->caps->num_spare_size) {
+		dev_err(nfc->dev, "invalid spare size %d\n", spare);
 		return -EINVAL;
 	}
 
+	fmt |= i << nfc->caps->pageformat_spare_shift;
+
 	fmt |= mtk_nand->fdm.reg_size << PAGEFMT_FDM_SHIFT;
 	fmt |= mtk_nand->fdm.ecc_size << PAGEFMT_FDM_ECC_SHIFT;
 	nfi_writel(nfc, fmt, NFI_PAGEFMT);
@@ -1131,12 +1089,12 @@ static void mtk_nfc_set_bad_mark_ctl(struct mtk_nfc_bad_mark_ctl *bm_ctl,
 	}
 }
 
-static void mtk_nfc_set_spare_per_sector(u32 *sps, struct mtd_info *mtd)
+static int mtk_nfc_set_spare_per_sector(u32 *sps, struct mtd_info *mtd)
 {
 	struct nand_chip *nand = mtd_to_nand(mtd);
-	u32 spare[] = {16, 26, 27, 28, 32, 36, 40, 44,
-			48, 49, 50, 51, 52, 62, 63, 64};
-	u32 eccsteps, i;
+	struct mtk_nfc *nfc = nand_get_controller_data(nand);
+	const u8 *spare = nfc->caps->spare_size;
+	u32 eccsteps, i, j = 0;
 
 	eccsteps = mtd->writesize / nand->ecc.size;
 	*sps = mtd->oobsize / eccsteps;
@@ -1144,28 +1102,28 @@ static void mtk_nfc_set_spare_per_sector(u32 *sps, struct mtd_info *mtd)
 	if (nand->ecc.size == 1024)
 		*sps >>= 1;
 
-	for (i = 0; i < ARRAY_SIZE(spare); i++) {
-		if (*sps <= spare[i]) {
-			if (!i)
-				*sps = spare[i];
-			else if (*sps != spare[i])
-				*sps = spare[i - 1];
-			break;
+	for (i = 0; i < nfc->caps->num_spare_size; i++) {
+		if ((*sps >= spare[i]) && (spare[i] >= spare[j])) {
+			j = i;
+			if (*sps == spare[i])
+				break;
 		}
 	}
 
-	if (i >= ARRAY_SIZE(spare))
-		*sps = spare[ARRAY_SIZE(spare) - 1];
+	*sps = spare[j];
 
 	if (nand->ecc.size == 1024)
 		*sps <<= 1;
+
+	return 0;
 }
 
 static int mtk_nfc_ecc_init(struct device *dev, struct mtd_info *mtd)
 {
 	struct nand_chip *nand = mtd_to_nand(mtd);
+	struct mtk_nfc *nfc = nand_get_controller_data(nand);
 	u32 spare;
-	int free;
+	int free, ret;
 
 	/* support only ecc hw mode */
 	if (nand->ecc.mode != NAND_ECC_HW) {
@@ -1194,7 +1152,9 @@ static int mtk_nfc_ecc_init(struct device *dev, struct mtd_info *mtd)
 			nand->ecc.size = 1024;
 		}
 
-		mtk_nfc_set_spare_per_sector(&spare, mtd);
+		ret = mtk_nfc_set_spare_per_sector(&spare, mtd);
+		if (ret)
+			return ret;
 
 		/* calculate oob bytes except ecc parity data */
 		free = ((nand->ecc.strength * ECC_PARITY_BITS) + 7) >> 3;
@@ -1214,7 +1174,7 @@ static int mtk_nfc_ecc_init(struct device *dev, struct mtd_info *mtd)
 		}
 	}
 
-	mtk_ecc_adjust_strength(&nand->ecc.strength);
+	mtk_ecc_adjust_strength(nfc->ecc, &nand->ecc.strength);
 
 	dev_info(dev, "eccsize %d eccstrength %d\n",
 		 nand->ecc.size, nand->ecc.strength);
@@ -1312,7 +1272,10 @@ static int mtk_nfc_nand_chip_init(struct device *dev, struct mtk_nfc *nfc,
 		return -EINVAL;
 	}
 
-	mtk_nfc_set_spare_per_sector(&chip->spare_per_sector, mtd);
+	ret = mtk_nfc_set_spare_per_sector(&chip->spare_per_sector, mtd);
+	if (ret)
+		return ret;
+
 	mtk_nfc_set_fdm(&chip->fdm, mtd);
 	mtk_nfc_set_bad_mark_ctl(&chip->bad_mark, mtd);
 
@@ -1354,12 +1317,28 @@ static int mtk_nfc_nand_chips_init(struct device *dev, struct mtk_nfc *nfc)
 	return 0;
 }
 
+static const struct mtk_nfc_caps mtk_nfc_caps_mt2701 = {
+	.spare_size = spare_size_mt2701,
+	.num_spare_size = 16,
+	.pageformat_spare_shift = 4,
+};
+
+static const struct of_device_id mtk_nfc_id_table[] = {
+	{
+		.compatible = "mediatek,mt2701-nfc",
+		.data = &mtk_nfc_caps_mt2701,
+	},
+	{}
+};
+MODULE_DEVICE_TABLE(of, mtk_nfc_id_table);
+
 static int mtk_nfc_probe(struct platform_device *pdev)
 {
 	struct device *dev = &pdev->dev;
 	struct device_node *np = dev->of_node;
 	struct mtk_nfc *nfc;
 	struct resource *res;
+	const struct of_device_id *of_nfc_id = NULL;
 	int ret, irq;
 
 	nfc = devm_kzalloc(dev, sizeof(*nfc), GFP_KERNEL);
@@ -1423,6 +1402,14 @@ static int mtk_nfc_probe(struct platform_device *pdev)
 		goto clk_disable;
 	}
 
+	of_nfc_id = of_match_device(mtk_nfc_id_table, &pdev->dev);
+	if (!of_nfc_id) {
+		ret = -ENODEV;
+		goto clk_disable;
+	}
+
+	nfc->caps = of_nfc_id->data;
+
 	platform_set_drvdata(pdev, nfc);
 
 	ret = mtk_nfc_nand_chips_init(dev, nfc);
@@ -1503,12 +1490,6 @@ static int mtk_nfc_resume(struct device *dev)
 static SIMPLE_DEV_PM_OPS(mtk_nfc_pm_ops, mtk_nfc_suspend, mtk_nfc_resume);
 #endif
 
-static const struct of_device_id mtk_nfc_id_table[] = {
-	{ .compatible = "mediatek,mt2701-nfc" },
-	{}
-};
-MODULE_DEVICE_TABLE(of, mtk_nfc_id_table);
-
 static struct platform_driver mtk_nfc_driver = {
 	.probe  = mtk_nfc_probe,
 	.remove = mtk_nfc_remove,
-- 
1.9.1

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

* [PATCH v4 3/4] mtd: nand: mediatek: add support for different MTK NAND FLASH Controller IP
@ 2017-05-31  3:37   ` Xiaolei Li
  0 siblings, 0 replies; 22+ messages in thread
From: Xiaolei Li @ 2017-05-31  3:37 UTC (permalink / raw)
  To: boris.brezillon-wi1+55ScJUtKEb57/3fJTNBPR1lH4CV8,
	computersforpeace-Re5JQEeQqe8AvxtiuMwx3w,
	matthias.bgg-Re5JQEeQqe8AvxtiuMwx3w
  Cc: srv_heupstream-NuS5LvNUpcJWk0Htik3J/w,
	robh+dt-DgEjT+Ai2ygdnm+yROfE0A,
	linux-mtd-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	yt.shen-NuS5LvNUpcJWk0Htik3J/w,
	linux-mediatek-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	xiaolei.li-NuS5LvNUpcJWk0Htik3J/w, dwmw2-wEGCiKHe2LqWVfeAwA7xHQ,
	rogercc.lin-NuS5LvNUpcJWk0Htik3J/w

ECC strength and spare size supported may be different among MTK NAND
FLASH Controller IPs.

This patch contains changes as following:
(1) add new struct mtk_nfc_caps to support different spare size.
(2) add new struct mtk_ecc_caps to support different ecc strength.
(3) remove ECC_CNFG_xBIT define, use a for loop to do ecc strength config.
(4) remove PAGEFMT_SPARE_ define, use a for loop to do spare format config.
(5) malloc ecc->eccdata buffer according to max ecc strength of this IP.

Signed-off-by: Xiaolei Li <xiaolei.li-NuS5LvNUpcJWk0Htik3J/w@public.gmane.org>
---
 drivers/mtd/nand/mtk_ecc.c  | 181 ++++++++++++++++++--------------------------
 drivers/mtd/nand/mtk_ecc.h  |   2 +-
 drivers/mtd/nand/mtk_nand.c | 165 ++++++++++++++++++----------------------
 3 files changed, 149 insertions(+), 199 deletions(-)

diff --git a/drivers/mtd/nand/mtk_ecc.c b/drivers/mtd/nand/mtk_ecc.c
index dbf2562..ae51303 100644
--- a/drivers/mtd/nand/mtk_ecc.c
+++ b/drivers/mtd/nand/mtk_ecc.c
@@ -33,26 +33,6 @@
 
 #define ECC_ENCCON		(0x00)
 #define ECC_ENCCNFG		(0x04)
-#define		ECC_CNFG_4BIT		(0)
-#define		ECC_CNFG_6BIT		(1)
-#define		ECC_CNFG_8BIT		(2)
-#define		ECC_CNFG_10BIT		(3)
-#define		ECC_CNFG_12BIT		(4)
-#define		ECC_CNFG_14BIT		(5)
-#define		ECC_CNFG_16BIT		(6)
-#define		ECC_CNFG_18BIT		(7)
-#define		ECC_CNFG_20BIT		(8)
-#define		ECC_CNFG_22BIT		(9)
-#define		ECC_CNFG_24BIT		(0xa)
-#define		ECC_CNFG_28BIT		(0xb)
-#define		ECC_CNFG_32BIT		(0xc)
-#define		ECC_CNFG_36BIT		(0xd)
-#define		ECC_CNFG_40BIT		(0xe)
-#define		ECC_CNFG_44BIT		(0xf)
-#define		ECC_CNFG_48BIT		(0x10)
-#define		ECC_CNFG_52BIT		(0x11)
-#define		ECC_CNFG_56BIT		(0x12)
-#define		ECC_CNFG_60BIT		(0x13)
 #define		ECC_MODE_SHIFT		(5)
 #define		ECC_MS_SHIFT		(16)
 #define ECC_ENCDIADDR		(0x08)
@@ -66,7 +46,6 @@
 #define		DEC_CNFG_CORRECT	(0x3 << 12)
 #define ECC_DECIDLE		(0x10C)
 #define ECC_DECENUM0		(0x114)
-#define		ERR_MASK		(0x3f)
 #define ECC_DECDONE		(0x124)
 #define ECC_DECIRQ_EN		(0x200)
 #define ECC_DECIRQ_STA		(0x204)
@@ -78,8 +57,15 @@
 #define ECC_IRQ_REG(op)		((op) == ECC_ENCODE ? \
 					ECC_ENCIRQ_EN : ECC_DECIRQ_EN)
 
+struct mtk_ecc_caps {
+	u32 err_mask;
+	const u8 *ecc_strength;
+	u8 num_ecc_strength;
+};
+
 struct mtk_ecc {
 	struct device *dev;
+	const struct mtk_ecc_caps *caps;
 	void __iomem *regs;
 	struct clk *clk;
 
@@ -87,7 +73,13 @@ struct mtk_ecc {
 	struct mutex lock;
 	u32 sectors;
 
-	u8 eccdata[112];
+	u8 *eccdata;
+};
+
+/* ecc strength that mt2701 supports */
+static const u8 ecc_strength_mt2701[] = {
+	4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 28, 32, 36,
+	40, 44, 48, 52, 56, 60
 };
 
 static inline void mtk_ecc_wait_idle(struct mtk_ecc *ecc,
@@ -136,77 +128,24 @@ static irqreturn_t mtk_ecc_irq(int irq, void *id)
 	return IRQ_HANDLED;
 }
 
-static void mtk_ecc_config(struct mtk_ecc *ecc, struct mtk_ecc_config *config)
+static int mtk_ecc_config(struct mtk_ecc *ecc, struct mtk_ecc_config *config)
 {
-	u32 ecc_bit = ECC_CNFG_4BIT, dec_sz, enc_sz;
-	u32 reg;
-
-	switch (config->strength) {
-	case 4:
-		ecc_bit = ECC_CNFG_4BIT;
-		break;
-	case 6:
-		ecc_bit = ECC_CNFG_6BIT;
-		break;
-	case 8:
-		ecc_bit = ECC_CNFG_8BIT;
-		break;
-	case 10:
-		ecc_bit = ECC_CNFG_10BIT;
-		break;
-	case 12:
-		ecc_bit = ECC_CNFG_12BIT;
-		break;
-	case 14:
-		ecc_bit = ECC_CNFG_14BIT;
-		break;
-	case 16:
-		ecc_bit = ECC_CNFG_16BIT;
-		break;
-	case 18:
-		ecc_bit = ECC_CNFG_18BIT;
-		break;
-	case 20:
-		ecc_bit = ECC_CNFG_20BIT;
-		break;
-	case 22:
-		ecc_bit = ECC_CNFG_22BIT;
-		break;
-	case 24:
-		ecc_bit = ECC_CNFG_24BIT;
-		break;
-	case 28:
-		ecc_bit = ECC_CNFG_28BIT;
-		break;
-	case 32:
-		ecc_bit = ECC_CNFG_32BIT;
-		break;
-	case 36:
-		ecc_bit = ECC_CNFG_36BIT;
-		break;
-	case 40:
-		ecc_bit = ECC_CNFG_40BIT;
-		break;
-	case 44:
-		ecc_bit = ECC_CNFG_44BIT;
-		break;
-	case 48:
-		ecc_bit = ECC_CNFG_48BIT;
-		break;
-	case 52:
-		ecc_bit = ECC_CNFG_52BIT;
-		break;
-	case 56:
-		ecc_bit = ECC_CNFG_56BIT;
-		break;
-	case 60:
-		ecc_bit = ECC_CNFG_60BIT;
-		break;
-	default:
-		dev_err(ecc->dev, "invalid strength %d, default to 4 bits\n",
+	u32 ecc_bit, dec_sz, enc_sz;
+	u32 reg, i;
+
+	for (i = 0; i < ecc->caps->num_ecc_strength; i++) {
+		if (ecc->caps->ecc_strength[i] == config->strength)
+			break;
+	}
+
+	if (i == ecc->caps->num_ecc_strength) {
+		dev_err(ecc->dev, "invalid ecc strength %d\n",
 			config->strength);
+		return -EINVAL;
 	}
 
+	ecc_bit = i;
+
 	if (config->op == ECC_ENCODE) {
 		/* configure ECC encoder (in bits) */
 		enc_sz = config->len << 3;
@@ -232,6 +171,8 @@ static void mtk_ecc_config(struct mtk_ecc *ecc, struct mtk_ecc_config *config)
 		if (config->sectors)
 			ecc->sectors = 1 << (config->sectors - 1);
 	}
+
+	return 0;
 }
 
 void mtk_ecc_get_stats(struct mtk_ecc *ecc, struct mtk_ecc_stats *stats,
@@ -247,8 +188,8 @@ void mtk_ecc_get_stats(struct mtk_ecc *ecc, struct mtk_ecc_stats *stats,
 		offset = (i >> 2) << 2;
 		err = readl(ecc->regs + ECC_DECENUM0 + offset);
 		err = err >> ((i % 4) * 8);
-		err &= ERR_MASK;
-		if (err == ERR_MASK) {
+		err &= ecc->caps->err_mask;
+		if (err == ecc->caps->err_mask) {
 			/* uncorrectable errors */
 			stats->failed++;
 			continue;
@@ -322,7 +263,11 @@ int mtk_ecc_enable(struct mtk_ecc *ecc, struct mtk_ecc_config *config)
 	}
 
 	mtk_ecc_wait_idle(ecc, op);
-	mtk_ecc_config(ecc, config);
+
+	ret = mtk_ecc_config(ecc, config);
+	if (ret)
+		return ret;
+
 	writew(ECC_OP_ENABLE, ecc->regs + ECC_CTL_REG(op));
 
 	init_completion(&ecc->done);
@@ -409,37 +354,66 @@ int mtk_ecc_encode(struct mtk_ecc *ecc, struct mtk_ecc_config *config,
 }
 EXPORT_SYMBOL(mtk_ecc_encode);
 
-void mtk_ecc_adjust_strength(u32 *p)
+void mtk_ecc_adjust_strength(struct mtk_ecc *ecc, u32 *p)
 {
-	u32 ecc[] = {4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 28, 32, 36,
-			40, 44, 48, 52, 56, 60};
+	const u8 *ecc_strength = ecc->caps->ecc_strength;
 	int i;
 
-	for (i = 0; i < ARRAY_SIZE(ecc); i++) {
-		if (*p <= ecc[i]) {
+	for (i = 0; i < ecc->caps->num_ecc_strength; i++) {
+		if (*p <= ecc_strength[i]) {
 			if (!i)
-				*p = ecc[i];
-			else if (*p != ecc[i])
-				*p = ecc[i - 1];
+				*p = ecc_strength[i];
+			else if (*p != ecc_strength[i])
+				*p = ecc_strength[i - 1];
 			return;
 		}
 	}
 
-	*p = ecc[ARRAY_SIZE(ecc) - 1];
+	*p = ecc_strength[ecc->caps->num_ecc_strength - 1];
 }
 EXPORT_SYMBOL(mtk_ecc_adjust_strength);
 
+static const struct mtk_ecc_caps mtk_ecc_caps_mt2701 = {
+	.err_mask = 0x3f,
+	.ecc_strength = ecc_strength_mt2701,
+	.num_ecc_strength = 20,
+};
+
+static const struct of_device_id mtk_ecc_dt_match[] = {
+	{
+		.compatible = "mediatek,mt2701-ecc",
+		.data = &mtk_ecc_caps_mt2701,
+	},
+	{},
+};
+
 static int mtk_ecc_probe(struct platform_device *pdev)
 {
 	struct device *dev = &pdev->dev;
 	struct mtk_ecc *ecc;
 	struct resource *res;
+	const struct of_device_id *of_ecc_id = NULL;
+	u32 max_eccdata_size;
 	int irq, ret;
 
 	ecc = devm_kzalloc(dev, sizeof(*ecc), GFP_KERNEL);
 	if (!ecc)
 		return -ENOMEM;
 
+	of_ecc_id = of_match_device(mtk_ecc_dt_match, &pdev->dev);
+	if (!of_ecc_id)
+		return -ENODEV;
+
+	ecc->caps = of_ecc_id->data;
+
+	max_eccdata_size = ecc->caps->num_ecc_strength - 1;
+	max_eccdata_size = ecc->caps->ecc_strength[max_eccdata_size];
+	max_eccdata_size = (max_eccdata_size * ECC_PARITY_BITS + 7) >> 3;
+	max_eccdata_size = round_up(max_eccdata_size, 4);
+	ecc->eccdata = devm_kzalloc(dev, max_eccdata_size, GFP_KERNEL);
+	if (!ecc->eccdata)
+		return -ENOMEM;
+
 	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 	ecc->regs = devm_ioremap_resource(dev, res);
 	if (IS_ERR(ecc->regs)) {
@@ -508,11 +482,6 @@ static int mtk_ecc_resume(struct device *dev)
 static SIMPLE_DEV_PM_OPS(mtk_ecc_pm_ops, mtk_ecc_suspend, mtk_ecc_resume);
 #endif
 
-static const struct of_device_id mtk_ecc_dt_match[] = {
-	{ .compatible = "mediatek,mt2701-ecc" },
-	{},
-};
-
 MODULE_DEVICE_TABLE(of, mtk_ecc_dt_match);
 
 static struct platform_driver mtk_ecc_driver = {
diff --git a/drivers/mtd/nand/mtk_ecc.h b/drivers/mtd/nand/mtk_ecc.h
index cbeba5c..d245c14 100644
--- a/drivers/mtd/nand/mtk_ecc.h
+++ b/drivers/mtd/nand/mtk_ecc.h
@@ -42,7 +42,7 @@ struct mtk_ecc_config {
 int mtk_ecc_wait_done(struct mtk_ecc *, enum mtk_ecc_operation);
 int mtk_ecc_enable(struct mtk_ecc *, struct mtk_ecc_config *);
 void mtk_ecc_disable(struct mtk_ecc *);
-void mtk_ecc_adjust_strength(u32 *);
+void mtk_ecc_adjust_strength(struct mtk_ecc *ecc, u32 *p);
 
 struct mtk_ecc *of_mtk_ecc_get(struct device_node *);
 void mtk_ecc_release(struct mtk_ecc *);
diff --git a/drivers/mtd/nand/mtk_nand.c b/drivers/mtd/nand/mtk_nand.c
index c28f4b7..d968b59 100644
--- a/drivers/mtd/nand/mtk_nand.c
+++ b/drivers/mtd/nand/mtk_nand.c
@@ -24,6 +24,7 @@
 #include <linux/module.h>
 #include <linux/iopoll.h>
 #include <linux/of.h>
+#include <linux/of_device.h>
 #include "mtk_ecc.h"
 
 /* NAND controller register definition */
@@ -38,23 +39,6 @@
 #define NFI_PAGEFMT		(0x04)
 #define		PAGEFMT_FDM_ECC_SHIFT	(12)
 #define		PAGEFMT_FDM_SHIFT	(8)
-#define		PAGEFMT_SPARE_16	(0)
-#define		PAGEFMT_SPARE_26	(1)
-#define		PAGEFMT_SPARE_27	(2)
-#define		PAGEFMT_SPARE_28	(3)
-#define		PAGEFMT_SPARE_32	(4)
-#define		PAGEFMT_SPARE_36	(5)
-#define		PAGEFMT_SPARE_40	(6)
-#define		PAGEFMT_SPARE_44	(7)
-#define		PAGEFMT_SPARE_48	(8)
-#define		PAGEFMT_SPARE_49	(9)
-#define		PAGEFMT_SPARE_50	(0xa)
-#define		PAGEFMT_SPARE_51	(0xb)
-#define		PAGEFMT_SPARE_52	(0xc)
-#define		PAGEFMT_SPARE_62	(0xd)
-#define		PAGEFMT_SPARE_63	(0xe)
-#define		PAGEFMT_SPARE_64	(0xf)
-#define		PAGEFMT_SPARE_SHIFT	(4)
 #define		PAGEFMT_SEC_SEL_512	BIT(2)
 #define		PAGEFMT_512_2K		(0)
 #define		PAGEFMT_2K_4K		(1)
@@ -116,6 +100,12 @@
 #define MTK_MAX_SECTOR		(16)
 #define MTK_NAND_MAX_NSELS	(2)
 
+struct mtk_nfc_caps {
+	const u8 *spare_size;
+	u8 num_spare_size;
+	u8 pageformat_spare_shift;
+};
+
 struct mtk_nfc_bad_mark_ctl {
 	void (*bm_swap)(struct mtd_info *, u8 *buf, int raw);
 	u32 sec;
@@ -155,6 +145,7 @@ struct mtk_nfc {
 	struct mtk_ecc *ecc;
 
 	struct device *dev;
+	const struct mtk_nfc_caps *caps;
 	void __iomem *regs;
 
 	struct completion done;
@@ -163,6 +154,15 @@ struct mtk_nfc {
 	u8 *buffer;
 };
 
+/*
+ * supported spare size of each IP.
+ * order should be the same with the spare size bitfiled defination of
+ * register NFI_PAGEFMT.
+ */
+static const u8 spare_size_mt2701[] = {
+	16, 26, 27, 28, 32, 36, 40, 44,	48, 49, 50, 51, 52, 62, 63, 64
+};
+
 static inline struct mtk_nfc_nand_chip *to_mtk_nand(struct nand_chip *nand)
 {
 	return container_of(nand, struct mtk_nfc_nand_chip, nand);
@@ -308,7 +308,7 @@ static int mtk_nfc_hw_runtime_config(struct mtd_info *mtd)
 	struct nand_chip *chip = mtd_to_nand(mtd);
 	struct mtk_nfc_nand_chip *mtk_nand = to_mtk_nand(chip);
 	struct mtk_nfc *nfc = nand_get_controller_data(chip);
-	u32 fmt, spare;
+	u32 fmt, spare, i;
 
 	if (!mtd->writesize)
 		return 0;
@@ -352,60 +352,18 @@ static int mtk_nfc_hw_runtime_config(struct mtd_info *mtd)
 	if (chip->ecc.size == 1024)
 		spare >>= 1;
 
-	switch (spare) {
-	case 16:
-		fmt |= (PAGEFMT_SPARE_16 << PAGEFMT_SPARE_SHIFT);
-		break;
-	case 26:
-		fmt |= (PAGEFMT_SPARE_26 << PAGEFMT_SPARE_SHIFT);
-		break;
-	case 27:
-		fmt |= (PAGEFMT_SPARE_27 << PAGEFMT_SPARE_SHIFT);
-		break;
-	case 28:
-		fmt |= (PAGEFMT_SPARE_28 << PAGEFMT_SPARE_SHIFT);
-		break;
-	case 32:
-		fmt |= (PAGEFMT_SPARE_32 << PAGEFMT_SPARE_SHIFT);
-		break;
-	case 36:
-		fmt |= (PAGEFMT_SPARE_36 << PAGEFMT_SPARE_SHIFT);
-		break;
-	case 40:
-		fmt |= (PAGEFMT_SPARE_40 << PAGEFMT_SPARE_SHIFT);
-		break;
-	case 44:
-		fmt |= (PAGEFMT_SPARE_44 << PAGEFMT_SPARE_SHIFT);
-		break;
-	case 48:
-		fmt |= (PAGEFMT_SPARE_48 << PAGEFMT_SPARE_SHIFT);
-		break;
-	case 49:
-		fmt |= (PAGEFMT_SPARE_49 << PAGEFMT_SPARE_SHIFT);
-		break;
-	case 50:
-		fmt |= (PAGEFMT_SPARE_50 << PAGEFMT_SPARE_SHIFT);
-		break;
-	case 51:
-		fmt |= (PAGEFMT_SPARE_51 << PAGEFMT_SPARE_SHIFT);
-		break;
-	case 52:
-		fmt |= (PAGEFMT_SPARE_52 << PAGEFMT_SPARE_SHIFT);
-		break;
-	case 62:
-		fmt |= (PAGEFMT_SPARE_62 << PAGEFMT_SPARE_SHIFT);
-		break;
-	case 63:
-		fmt |= (PAGEFMT_SPARE_63 << PAGEFMT_SPARE_SHIFT);
-		break;
-	case 64:
-		fmt |= (PAGEFMT_SPARE_64 << PAGEFMT_SPARE_SHIFT);
-		break;
-	default:
-		dev_err(nfc->dev, "invalid spare per sector %d\n", spare);
+	for (i = 0; i < nfc->caps->num_spare_size; i++) {
+		if (nfc->caps->spare_size[i] == spare)
+			break;
+	}
+
+	if (i == nfc->caps->num_spare_size) {
+		dev_err(nfc->dev, "invalid spare size %d\n", spare);
 		return -EINVAL;
 	}
 
+	fmt |= i << nfc->caps->pageformat_spare_shift;
+
 	fmt |= mtk_nand->fdm.reg_size << PAGEFMT_FDM_SHIFT;
 	fmt |= mtk_nand->fdm.ecc_size << PAGEFMT_FDM_ECC_SHIFT;
 	nfi_writel(nfc, fmt, NFI_PAGEFMT);
@@ -1131,12 +1089,12 @@ static void mtk_nfc_set_bad_mark_ctl(struct mtk_nfc_bad_mark_ctl *bm_ctl,
 	}
 }
 
-static void mtk_nfc_set_spare_per_sector(u32 *sps, struct mtd_info *mtd)
+static int mtk_nfc_set_spare_per_sector(u32 *sps, struct mtd_info *mtd)
 {
 	struct nand_chip *nand = mtd_to_nand(mtd);
-	u32 spare[] = {16, 26, 27, 28, 32, 36, 40, 44,
-			48, 49, 50, 51, 52, 62, 63, 64};
-	u32 eccsteps, i;
+	struct mtk_nfc *nfc = nand_get_controller_data(nand);
+	const u8 *spare = nfc->caps->spare_size;
+	u32 eccsteps, i, j = 0;
 
 	eccsteps = mtd->writesize / nand->ecc.size;
 	*sps = mtd->oobsize / eccsteps;
@@ -1144,28 +1102,28 @@ static void mtk_nfc_set_spare_per_sector(u32 *sps, struct mtd_info *mtd)
 	if (nand->ecc.size == 1024)
 		*sps >>= 1;
 
-	for (i = 0; i < ARRAY_SIZE(spare); i++) {
-		if (*sps <= spare[i]) {
-			if (!i)
-				*sps = spare[i];
-			else if (*sps != spare[i])
-				*sps = spare[i - 1];
-			break;
+	for (i = 0; i < nfc->caps->num_spare_size; i++) {
+		if ((*sps >= spare[i]) && (spare[i] >= spare[j])) {
+			j = i;
+			if (*sps == spare[i])
+				break;
 		}
 	}
 
-	if (i >= ARRAY_SIZE(spare))
-		*sps = spare[ARRAY_SIZE(spare) - 1];
+	*sps = spare[j];
 
 	if (nand->ecc.size == 1024)
 		*sps <<= 1;
+
+	return 0;
 }
 
 static int mtk_nfc_ecc_init(struct device *dev, struct mtd_info *mtd)
 {
 	struct nand_chip *nand = mtd_to_nand(mtd);
+	struct mtk_nfc *nfc = nand_get_controller_data(nand);
 	u32 spare;
-	int free;
+	int free, ret;
 
 	/* support only ecc hw mode */
 	if (nand->ecc.mode != NAND_ECC_HW) {
@@ -1194,7 +1152,9 @@ static int mtk_nfc_ecc_init(struct device *dev, struct mtd_info *mtd)
 			nand->ecc.size = 1024;
 		}
 
-		mtk_nfc_set_spare_per_sector(&spare, mtd);
+		ret = mtk_nfc_set_spare_per_sector(&spare, mtd);
+		if (ret)
+			return ret;
 
 		/* calculate oob bytes except ecc parity data */
 		free = ((nand->ecc.strength * ECC_PARITY_BITS) + 7) >> 3;
@@ -1214,7 +1174,7 @@ static int mtk_nfc_ecc_init(struct device *dev, struct mtd_info *mtd)
 		}
 	}
 
-	mtk_ecc_adjust_strength(&nand->ecc.strength);
+	mtk_ecc_adjust_strength(nfc->ecc, &nand->ecc.strength);
 
 	dev_info(dev, "eccsize %d eccstrength %d\n",
 		 nand->ecc.size, nand->ecc.strength);
@@ -1312,7 +1272,10 @@ static int mtk_nfc_nand_chip_init(struct device *dev, struct mtk_nfc *nfc,
 		return -EINVAL;
 	}
 
-	mtk_nfc_set_spare_per_sector(&chip->spare_per_sector, mtd);
+	ret = mtk_nfc_set_spare_per_sector(&chip->spare_per_sector, mtd);
+	if (ret)
+		return ret;
+
 	mtk_nfc_set_fdm(&chip->fdm, mtd);
 	mtk_nfc_set_bad_mark_ctl(&chip->bad_mark, mtd);
 
@@ -1354,12 +1317,28 @@ static int mtk_nfc_nand_chips_init(struct device *dev, struct mtk_nfc *nfc)
 	return 0;
 }
 
+static const struct mtk_nfc_caps mtk_nfc_caps_mt2701 = {
+	.spare_size = spare_size_mt2701,
+	.num_spare_size = 16,
+	.pageformat_spare_shift = 4,
+};
+
+static const struct of_device_id mtk_nfc_id_table[] = {
+	{
+		.compatible = "mediatek,mt2701-nfc",
+		.data = &mtk_nfc_caps_mt2701,
+	},
+	{}
+};
+MODULE_DEVICE_TABLE(of, mtk_nfc_id_table);
+
 static int mtk_nfc_probe(struct platform_device *pdev)
 {
 	struct device *dev = &pdev->dev;
 	struct device_node *np = dev->of_node;
 	struct mtk_nfc *nfc;
 	struct resource *res;
+	const struct of_device_id *of_nfc_id = NULL;
 	int ret, irq;
 
 	nfc = devm_kzalloc(dev, sizeof(*nfc), GFP_KERNEL);
@@ -1423,6 +1402,14 @@ static int mtk_nfc_probe(struct platform_device *pdev)
 		goto clk_disable;
 	}
 
+	of_nfc_id = of_match_device(mtk_nfc_id_table, &pdev->dev);
+	if (!of_nfc_id) {
+		ret = -ENODEV;
+		goto clk_disable;
+	}
+
+	nfc->caps = of_nfc_id->data;
+
 	platform_set_drvdata(pdev, nfc);
 
 	ret = mtk_nfc_nand_chips_init(dev, nfc);
@@ -1503,12 +1490,6 @@ static int mtk_nfc_resume(struct device *dev)
 static SIMPLE_DEV_PM_OPS(mtk_nfc_pm_ops, mtk_nfc_suspend, mtk_nfc_resume);
 #endif
 
-static const struct of_device_id mtk_nfc_id_table[] = {
-	{ .compatible = "mediatek,mt2701-nfc" },
-	{}
-};
-MODULE_DEVICE_TABLE(of, mtk_nfc_id_table);
-
 static struct platform_driver mtk_nfc_driver = {
 	.probe  = mtk_nfc_probe,
 	.remove = mtk_nfc_remove,
-- 
1.9.1

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

* [PATCH v4 4/4] mtd: nand: mediatek: add support for MT2712 NAND FLASH Controller
  2017-05-31  3:37 ` Xiaolei Li
@ 2017-05-31  3:37   ` Xiaolei Li
  -1 siblings, 0 replies; 22+ messages in thread
From: Xiaolei Li @ 2017-05-31  3:37 UTC (permalink / raw)
  To: boris.brezillon, computersforpeace, matthias.bgg
  Cc: dwmw2, linux-mtd, linux-mediatek, robh+dt, rogercc.lin, yt.shen,
	srv_heupstream, xiaolei.li

MT2712 NAND FLASH Controller is similar to MT2701 except those following:
(1) MT2712 supports up to 148B spare size per 1KB size sector (the same
    with 74B spare size per 512B size sector). There are three new spare
    format: 61, 67, 74.
(2) MT2712 supports up to 80 bit ecc strength. There are three new ecc
    strength level: 68, 72, 80.
(3) MT2712 ECC encode parity data register's start offset is 0x300, and
    different with 0x10 of MT2701.
(4) MT2712 improves ecc irq function. When ECC works in ECC_NFI_MODE,
    MT2701 will generate ecc irq number the same with ecc steps during
    page read. However, MT2712 can only generate one ecc irq.

Changes of this patch are:
(1) add two new variables named pg_irq_sel, encode_parity_reg0 in struct
    mtk_ecc_caps.
(2) add new bitfield ECC_PG_IRQ_SEL for register ECC_IRQ_REG.
(3) add ecc strength array of mt2712.
(4) add spare size array of mt2712.
(5) add mt2712 nfc and ecc device compatiable and data.

Signed-off-by: Xiaolei Li <xiaolei.li@mediatek.com>
---
 drivers/mtd/nand/mtk_ecc.c  | 39 +++++++++++++++++++++++++++++++++++----
 drivers/mtd/nand/mtk_nand.c | 14 ++++++++++++++
 2 files changed, 49 insertions(+), 4 deletions(-)

diff --git a/drivers/mtd/nand/mtk_ecc.c b/drivers/mtd/nand/mtk_ecc.c
index ae51303..4958121 100644
--- a/drivers/mtd/nand/mtk_ecc.c
+++ b/drivers/mtd/nand/mtk_ecc.c
@@ -28,6 +28,7 @@
 
 #define ECC_IDLE_MASK		BIT(0)
 #define ECC_IRQ_EN		BIT(0)
+#define ECC_PG_IRQ_SEL		BIT(1)
 #define ECC_OP_ENABLE		(1)
 #define ECC_OP_DISABLE		(0)
 
@@ -37,7 +38,6 @@
 #define		ECC_MS_SHIFT		(16)
 #define ECC_ENCDIADDR		(0x08)
 #define ECC_ENCIDLE		(0x0C)
-#define ECC_ENCPAR(x)		(0x10 + (x) * sizeof(u32))
 #define ECC_ENCIRQ_EN		(0x80)
 #define ECC_ENCIRQ_STA		(0x84)
 #define ECC_DECCON		(0x100)
@@ -61,6 +61,8 @@ struct mtk_ecc_caps {
 	u32 err_mask;
 	const u8 *ecc_strength;
 	u8 num_ecc_strength;
+	u32 encode_parity_reg0;
+	int pg_irq_sel;
 };
 
 struct mtk_ecc {
@@ -76,12 +78,17 @@ struct mtk_ecc {
 	u8 *eccdata;
 };
 
-/* ecc strength that mt2701 supports */
+/* ecc strength that each IP supports */
 static const u8 ecc_strength_mt2701[] = {
 	4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 28, 32, 36,
 	40, 44, 48, 52, 56, 60
 };
 
+static const u8 ecc_strength_mt2712[] = {
+	4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 28, 32, 36,
+	40, 44, 48, 52, 56, 60, 68, 72, 80
+};
+
 static inline void mtk_ecc_wait_idle(struct mtk_ecc *ecc,
 				     enum mtk_ecc_operation op)
 {
@@ -254,6 +261,7 @@ struct mtk_ecc *of_mtk_ecc_get(struct device_node *of_node)
 int mtk_ecc_enable(struct mtk_ecc *ecc, struct mtk_ecc_config *config)
 {
 	enum mtk_ecc_operation op = config->op;
+	u16 reg_val;
 	int ret;
 
 	ret = mutex_lock_interruptible(&ecc->lock);
@@ -271,7 +279,15 @@ int mtk_ecc_enable(struct mtk_ecc *ecc, struct mtk_ecc_config *config)
 	writew(ECC_OP_ENABLE, ecc->regs + ECC_CTL_REG(op));
 
 	init_completion(&ecc->done);
-	writew(ECC_IRQ_EN, ecc->regs + ECC_IRQ_REG(op));
+	reg_val = ECC_IRQ_EN;
+	/*
+	 * For ECC_NFI_MODE, if ecc->caps->pg_irq_sel is 1, then it
+	 * means this chip can only generate one ecc irq during page
+	 * read / write. If is 0, generate one ecc irq each ecc step.
+	 */
+	if ((ecc->caps->pg_irq_sel) && (config->mode == ECC_NFI_MODE))
+		reg_val |= ECC_PG_IRQ_SEL;
+	writew(reg_val, ecc->regs + ECC_IRQ_REG(op));
 
 	return 0;
 }
@@ -341,7 +357,9 @@ int mtk_ecc_encode(struct mtk_ecc *ecc, struct mtk_ecc_config *config,
 	len = (config->strength * ECC_PARITY_BITS + 7) >> 3;
 
 	/* write the parity bytes generated by the ECC back to temp buffer */
-	__ioread32_copy(ecc->eccdata, ecc->regs + ECC_ENCPAR(0), round_up(len, 4));
+	__ioread32_copy(ecc->eccdata,
+			ecc->regs + ecc->caps->encode_parity_reg0,
+			round_up(len, 4));
 
 	/* copy into possibly unaligned OOB region with actual length */
 	memcpy(data + bytes, ecc->eccdata, len);
@@ -377,12 +395,25 @@ void mtk_ecc_adjust_strength(struct mtk_ecc *ecc, u32 *p)
 	.err_mask = 0x3f,
 	.ecc_strength = ecc_strength_mt2701,
 	.num_ecc_strength = 20,
+	.encode_parity_reg0 = 0x10,
+	.pg_irq_sel = 0,
+};
+
+static const struct mtk_ecc_caps mtk_ecc_caps_mt2712 = {
+	.err_mask = 0x7f,
+	.ecc_strength = ecc_strength_mt2712,
+	.num_ecc_strength = 23,
+	.encode_parity_reg0 = 0x300,
+	.pg_irq_sel = 1,
 };
 
 static const struct of_device_id mtk_ecc_dt_match[] = {
 	{
 		.compatible = "mediatek,mt2701-ecc",
 		.data = &mtk_ecc_caps_mt2701,
+	}, {
+		.compatible = "mediatek,mt2712-ecc",
+		.data = &mtk_ecc_caps_mt2712,
 	},
 	{},
 };
diff --git a/drivers/mtd/nand/mtk_nand.c b/drivers/mtd/nand/mtk_nand.c
index d968b59..b17a806 100644
--- a/drivers/mtd/nand/mtk_nand.c
+++ b/drivers/mtd/nand/mtk_nand.c
@@ -163,6 +163,11 @@ struct mtk_nfc {
 	16, 26, 27, 28, 32, 36, 40, 44,	48, 49, 50, 51, 52, 62, 63, 64
 };
 
+static const u8 spare_size_mt2712[] = {
+	16, 26, 27, 28, 32, 36, 40, 44, 48, 49, 50, 51, 52, 62, 61, 63, 64, 67,
+	74
+};
+
 static inline struct mtk_nfc_nand_chip *to_mtk_nand(struct nand_chip *nand)
 {
 	return container_of(nand, struct mtk_nfc_nand_chip, nand);
@@ -1323,10 +1328,19 @@ static int mtk_nfc_nand_chips_init(struct device *dev, struct mtk_nfc *nfc)
 	.pageformat_spare_shift = 4,
 };
 
+static const struct mtk_nfc_caps mtk_nfc_caps_mt2712 = {
+	.spare_size = spare_size_mt2712,
+	.num_spare_size = 19,
+	.pageformat_spare_shift = 16,
+};
+
 static const struct of_device_id mtk_nfc_id_table[] = {
 	{
 		.compatible = "mediatek,mt2701-nfc",
 		.data = &mtk_nfc_caps_mt2701,
+	}, {
+		.compatible = "mediatek,mt2712-nfc",
+		.data = &mtk_nfc_caps_mt2712,
 	},
 	{}
 };
-- 
1.9.1

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

* [PATCH v4 4/4] mtd: nand: mediatek: add support for MT2712 NAND FLASH Controller
@ 2017-05-31  3:37   ` Xiaolei Li
  0 siblings, 0 replies; 22+ messages in thread
From: Xiaolei Li @ 2017-05-31  3:37 UTC (permalink / raw)
  To: boris.brezillon, computersforpeace, matthias.bgg
  Cc: srv_heupstream, robh+dt, linux-mtd, yt.shen, linux-mediatek,
	xiaolei.li, dwmw2, rogercc.lin

MT2712 NAND FLASH Controller is similar to MT2701 except those following:
(1) MT2712 supports up to 148B spare size per 1KB size sector (the same
    with 74B spare size per 512B size sector). There are three new spare
    format: 61, 67, 74.
(2) MT2712 supports up to 80 bit ecc strength. There are three new ecc
    strength level: 68, 72, 80.
(3) MT2712 ECC encode parity data register's start offset is 0x300, and
    different with 0x10 of MT2701.
(4) MT2712 improves ecc irq function. When ECC works in ECC_NFI_MODE,
    MT2701 will generate ecc irq number the same with ecc steps during
    page read. However, MT2712 can only generate one ecc irq.

Changes of this patch are:
(1) add two new variables named pg_irq_sel, encode_parity_reg0 in struct
    mtk_ecc_caps.
(2) add new bitfield ECC_PG_IRQ_SEL for register ECC_IRQ_REG.
(3) add ecc strength array of mt2712.
(4) add spare size array of mt2712.
(5) add mt2712 nfc and ecc device compatiable and data.

Signed-off-by: Xiaolei Li <xiaolei.li@mediatek.com>
---
 drivers/mtd/nand/mtk_ecc.c  | 39 +++++++++++++++++++++++++++++++++++----
 drivers/mtd/nand/mtk_nand.c | 14 ++++++++++++++
 2 files changed, 49 insertions(+), 4 deletions(-)

diff --git a/drivers/mtd/nand/mtk_ecc.c b/drivers/mtd/nand/mtk_ecc.c
index ae51303..4958121 100644
--- a/drivers/mtd/nand/mtk_ecc.c
+++ b/drivers/mtd/nand/mtk_ecc.c
@@ -28,6 +28,7 @@
 
 #define ECC_IDLE_MASK		BIT(0)
 #define ECC_IRQ_EN		BIT(0)
+#define ECC_PG_IRQ_SEL		BIT(1)
 #define ECC_OP_ENABLE		(1)
 #define ECC_OP_DISABLE		(0)
 
@@ -37,7 +38,6 @@
 #define		ECC_MS_SHIFT		(16)
 #define ECC_ENCDIADDR		(0x08)
 #define ECC_ENCIDLE		(0x0C)
-#define ECC_ENCPAR(x)		(0x10 + (x) * sizeof(u32))
 #define ECC_ENCIRQ_EN		(0x80)
 #define ECC_ENCIRQ_STA		(0x84)
 #define ECC_DECCON		(0x100)
@@ -61,6 +61,8 @@ struct mtk_ecc_caps {
 	u32 err_mask;
 	const u8 *ecc_strength;
 	u8 num_ecc_strength;
+	u32 encode_parity_reg0;
+	int pg_irq_sel;
 };
 
 struct mtk_ecc {
@@ -76,12 +78,17 @@ struct mtk_ecc {
 	u8 *eccdata;
 };
 
-/* ecc strength that mt2701 supports */
+/* ecc strength that each IP supports */
 static const u8 ecc_strength_mt2701[] = {
 	4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 28, 32, 36,
 	40, 44, 48, 52, 56, 60
 };
 
+static const u8 ecc_strength_mt2712[] = {
+	4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 28, 32, 36,
+	40, 44, 48, 52, 56, 60, 68, 72, 80
+};
+
 static inline void mtk_ecc_wait_idle(struct mtk_ecc *ecc,
 				     enum mtk_ecc_operation op)
 {
@@ -254,6 +261,7 @@ struct mtk_ecc *of_mtk_ecc_get(struct device_node *of_node)
 int mtk_ecc_enable(struct mtk_ecc *ecc, struct mtk_ecc_config *config)
 {
 	enum mtk_ecc_operation op = config->op;
+	u16 reg_val;
 	int ret;
 
 	ret = mutex_lock_interruptible(&ecc->lock);
@@ -271,7 +279,15 @@ int mtk_ecc_enable(struct mtk_ecc *ecc, struct mtk_ecc_config *config)
 	writew(ECC_OP_ENABLE, ecc->regs + ECC_CTL_REG(op));
 
 	init_completion(&ecc->done);
-	writew(ECC_IRQ_EN, ecc->regs + ECC_IRQ_REG(op));
+	reg_val = ECC_IRQ_EN;
+	/*
+	 * For ECC_NFI_MODE, if ecc->caps->pg_irq_sel is 1, then it
+	 * means this chip can only generate one ecc irq during page
+	 * read / write. If is 0, generate one ecc irq each ecc step.
+	 */
+	if ((ecc->caps->pg_irq_sel) && (config->mode == ECC_NFI_MODE))
+		reg_val |= ECC_PG_IRQ_SEL;
+	writew(reg_val, ecc->regs + ECC_IRQ_REG(op));
 
 	return 0;
 }
@@ -341,7 +357,9 @@ int mtk_ecc_encode(struct mtk_ecc *ecc, struct mtk_ecc_config *config,
 	len = (config->strength * ECC_PARITY_BITS + 7) >> 3;
 
 	/* write the parity bytes generated by the ECC back to temp buffer */
-	__ioread32_copy(ecc->eccdata, ecc->regs + ECC_ENCPAR(0), round_up(len, 4));
+	__ioread32_copy(ecc->eccdata,
+			ecc->regs + ecc->caps->encode_parity_reg0,
+			round_up(len, 4));
 
 	/* copy into possibly unaligned OOB region with actual length */
 	memcpy(data + bytes, ecc->eccdata, len);
@@ -377,12 +395,25 @@ void mtk_ecc_adjust_strength(struct mtk_ecc *ecc, u32 *p)
 	.err_mask = 0x3f,
 	.ecc_strength = ecc_strength_mt2701,
 	.num_ecc_strength = 20,
+	.encode_parity_reg0 = 0x10,
+	.pg_irq_sel = 0,
+};
+
+static const struct mtk_ecc_caps mtk_ecc_caps_mt2712 = {
+	.err_mask = 0x7f,
+	.ecc_strength = ecc_strength_mt2712,
+	.num_ecc_strength = 23,
+	.encode_parity_reg0 = 0x300,
+	.pg_irq_sel = 1,
 };
 
 static const struct of_device_id mtk_ecc_dt_match[] = {
 	{
 		.compatible = "mediatek,mt2701-ecc",
 		.data = &mtk_ecc_caps_mt2701,
+	}, {
+		.compatible = "mediatek,mt2712-ecc",
+		.data = &mtk_ecc_caps_mt2712,
 	},
 	{},
 };
diff --git a/drivers/mtd/nand/mtk_nand.c b/drivers/mtd/nand/mtk_nand.c
index d968b59..b17a806 100644
--- a/drivers/mtd/nand/mtk_nand.c
+++ b/drivers/mtd/nand/mtk_nand.c
@@ -163,6 +163,11 @@ struct mtk_nfc {
 	16, 26, 27, 28, 32, 36, 40, 44,	48, 49, 50, 51, 52, 62, 63, 64
 };
 
+static const u8 spare_size_mt2712[] = {
+	16, 26, 27, 28, 32, 36, 40, 44, 48, 49, 50, 51, 52, 62, 61, 63, 64, 67,
+	74
+};
+
 static inline struct mtk_nfc_nand_chip *to_mtk_nand(struct nand_chip *nand)
 {
 	return container_of(nand, struct mtk_nfc_nand_chip, nand);
@@ -1323,10 +1328,19 @@ static int mtk_nfc_nand_chips_init(struct device *dev, struct mtk_nfc *nfc)
 	.pageformat_spare_shift = 4,
 };
 
+static const struct mtk_nfc_caps mtk_nfc_caps_mt2712 = {
+	.spare_size = spare_size_mt2712,
+	.num_spare_size = 19,
+	.pageformat_spare_shift = 16,
+};
+
 static const struct of_device_id mtk_nfc_id_table[] = {
 	{
 		.compatible = "mediatek,mt2701-nfc",
 		.data = &mtk_nfc_caps_mt2701,
+	}, {
+		.compatible = "mediatek,mt2712-nfc",
+		.data = &mtk_nfc_caps_mt2712,
 	},
 	{}
 };
-- 
1.9.1


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

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

* Re: [PATCH v4 3/4] mtd: nand: mediatek: add support for different MTK NAND FLASH Controller IP
  2017-05-31  3:37   ` Xiaolei Li
@ 2017-05-31  6:12     ` Boris Brezillon
  -1 siblings, 0 replies; 22+ messages in thread
From: Boris Brezillon @ 2017-05-31  6:12 UTC (permalink / raw)
  To: Xiaolei Li
  Cc: computersforpeace, matthias.bgg, dwmw2, linux-mtd,
	linux-mediatek, robh+dt, rogercc.lin, yt.shen, srv_heupstream

Le Wed, 31 May 2017 11:37:56 +0800,
Xiaolei Li <xiaolei.li@mediatek.com> a écrit :

>  
> -static void mtk_nfc_set_spare_per_sector(u32 *sps, struct mtd_info *mtd)
> +static int mtk_nfc_set_spare_per_sector(u32 *sps, struct mtd_info *mtd)

Why do you change the prototype here? You seem to always return 0
anyway.

>  {
>  	struct nand_chip *nand = mtd_to_nand(mtd);
> -	u32 spare[] = {16, 26, 27, 28, 32, 36, 40, 44,
> -			48, 49, 50, 51, 52, 62, 63, 64};
> -	u32 eccsteps, i;
> +	struct mtk_nfc *nfc = nand_get_controller_data(nand);
> +	const u8 *spare = nfc->caps->spare_size;
> +	u32 eccsteps, i, j = 0;

Can we rename 'j' into 'closest_spare'?

>  
>  	eccsteps = mtd->writesize / nand->ecc.size;
>  	*sps = mtd->oobsize / eccsteps;
> @@ -1144,28 +1102,28 @@ static void mtk_nfc_set_spare_per_sector(u32 *sps, struct mtd_info *mtd)
>  	if (nand->ecc.size == 1024)
>  		*sps >>= 1;
>  
> -	for (i = 0; i < ARRAY_SIZE(spare); i++) {
> -		if (*sps <= spare[i]) {
> -			if (!i)
> -				*sps = spare[i];
> -			else if (*sps != spare[i])
> -				*sps = spare[i - 1];
> -			break;
> +	for (i = 0; i < nfc->caps->num_spare_size; i++) {
> +		if ((*sps >= spare[i]) && (spare[i] >= spare[j])) {

Parenthesis around the 'a >= b' tests are unneeded:

		if (*sps >= spare[i] && spare[i] >= spare[j]) {

> +			j = i;
> +			if (*sps == spare[i])
> +				break;
>  		}
>  	}
>  
> -	if (i >= ARRAY_SIZE(spare))
> -		*sps = spare[ARRAY_SIZE(spare) - 1];

Maybe you could return an error if you didn't find any entry that is
less that *sps in the table, but I'm not sure this can really happen,
and the minimum spare size seems to be the same for all IPs, this is
something you can check before iterating over the array:

	if (*sps < MTK_NFC_MIN_SPARE)
		return -EINVAL;

> +	*sps = spare[j];
>  
>  	if (nand->ecc.size == 1024)
>  		*sps <<= 1;
> +
> +	return 0;
>  }

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

* Re: [PATCH v4 3/4] mtd: nand: mediatek: add support for different MTK NAND FLASH Controller IP
@ 2017-05-31  6:12     ` Boris Brezillon
  0 siblings, 0 replies; 22+ messages in thread
From: Boris Brezillon @ 2017-05-31  6:12 UTC (permalink / raw)
  To: Xiaolei Li
  Cc: srv_heupstream, yt.shen, robh+dt, linux-mtd, matthias.bgg,
	linux-mediatek, computersforpeace, dwmw2, rogercc.lin

Le Wed, 31 May 2017 11:37:56 +0800,
Xiaolei Li <xiaolei.li@mediatek.com> a écrit :

>  
> -static void mtk_nfc_set_spare_per_sector(u32 *sps, struct mtd_info *mtd)
> +static int mtk_nfc_set_spare_per_sector(u32 *sps, struct mtd_info *mtd)

Why do you change the prototype here? You seem to always return 0
anyway.

>  {
>  	struct nand_chip *nand = mtd_to_nand(mtd);
> -	u32 spare[] = {16, 26, 27, 28, 32, 36, 40, 44,
> -			48, 49, 50, 51, 52, 62, 63, 64};
> -	u32 eccsteps, i;
> +	struct mtk_nfc *nfc = nand_get_controller_data(nand);
> +	const u8 *spare = nfc->caps->spare_size;
> +	u32 eccsteps, i, j = 0;

Can we rename 'j' into 'closest_spare'?

>  
>  	eccsteps = mtd->writesize / nand->ecc.size;
>  	*sps = mtd->oobsize / eccsteps;
> @@ -1144,28 +1102,28 @@ static void mtk_nfc_set_spare_per_sector(u32 *sps, struct mtd_info *mtd)
>  	if (nand->ecc.size == 1024)
>  		*sps >>= 1;
>  
> -	for (i = 0; i < ARRAY_SIZE(spare); i++) {
> -		if (*sps <= spare[i]) {
> -			if (!i)
> -				*sps = spare[i];
> -			else if (*sps != spare[i])
> -				*sps = spare[i - 1];
> -			break;
> +	for (i = 0; i < nfc->caps->num_spare_size; i++) {
> +		if ((*sps >= spare[i]) && (spare[i] >= spare[j])) {

Parenthesis around the 'a >= b' tests are unneeded:

		if (*sps >= spare[i] && spare[i] >= spare[j]) {

> +			j = i;
> +			if (*sps == spare[i])
> +				break;
>  		}
>  	}
>  
> -	if (i >= ARRAY_SIZE(spare))
> -		*sps = spare[ARRAY_SIZE(spare) - 1];

Maybe you could return an error if you didn't find any entry that is
less that *sps in the table, but I'm not sure this can really happen,
and the minimum spare size seems to be the same for all IPs, this is
something you can check before iterating over the array:

	if (*sps < MTK_NFC_MIN_SPARE)
		return -EINVAL;

> +	*sps = spare[j];
>  
>  	if (nand->ecc.size == 1024)
>  		*sps <<= 1;
> +
> +	return 0;
>  }

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

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

* Re: [PATCH v4 3/4] mtd: nand: mediatek: add support for different MTK NAND FLASH Controller IP
  2017-05-31  6:12     ` Boris Brezillon
@ 2017-05-31  6:52       ` xiaolei li
  -1 siblings, 0 replies; 22+ messages in thread
From: xiaolei li @ 2017-05-31  6:52 UTC (permalink / raw)
  To: Boris Brezillon
  Cc: computersforpeace, matthias.bgg, dwmw2, linux-mtd,
	linux-mediatek, robh+dt, rogercc.lin, yt.shen, srv_heupstream

Hi Boris,

On Wed, 2017-05-31 at 08:12 +0200, Boris Brezillon wrote:
> Le Wed, 31 May 2017 11:37:56 +0800,
> Xiaolei Li <xiaolei.li@mediatek.com> a écrit :
> 
> >  
> > -static void mtk_nfc_set_spare_per_sector(u32 *sps, struct mtd_info *mtd)
> > +static int mtk_nfc_set_spare_per_sector(u32 *sps, struct mtd_info *mtd)
> 
> Why do you change the prototype here? You seem to always return 0
> anyway.
> 
Sorry, it should be void.

But as your suggestion below, I will keep using int here to return error
if there is no entry that is less than *sps.

> >  {
> >  	struct nand_chip *nand = mtd_to_nand(mtd);
> > -	u32 spare[] = {16, 26, 27, 28, 32, 36, 40, 44,
> > -			48, 49, 50, 51, 52, 62, 63, 64};
> > -	u32 eccsteps, i;
> > +	struct mtk_nfc *nfc = nand_get_controller_data(nand);
> > +	const u8 *spare = nfc->caps->spare_size;
> > +	u32 eccsteps, i, j = 0;
> 
> Can we rename 'j' into 'closest_spare'?
> 
ok.

> >  
> >  	eccsteps = mtd->writesize / nand->ecc.size;
> >  	*sps = mtd->oobsize / eccsteps;
> > @@ -1144,28 +1102,28 @@ static void mtk_nfc_set_spare_per_sector(u32 *sps, struct mtd_info *mtd)
> >  	if (nand->ecc.size == 1024)
> >  		*sps >>= 1;
> >  
> > -	for (i = 0; i < ARRAY_SIZE(spare); i++) {
> > -		if (*sps <= spare[i]) {
> > -			if (!i)
> > -				*sps = spare[i];
> > -			else if (*sps != spare[i])
> > -				*sps = spare[i - 1];
> > -			break;
> > +	for (i = 0; i < nfc->caps->num_spare_size; i++) {
> > +		if ((*sps >= spare[i]) && (spare[i] >= spare[j])) {
> 
> Parenthesis around the 'a >= b' tests are unneeded:
> 
> 		if (*sps >= spare[i] && spare[i] >= spare[j]) {
> 
ok.

> > +			j = i;
> > +			if (*sps == spare[i])
> > +				break;
> >  		}
> >  	}
> >  
> > -	if (i >= ARRAY_SIZE(spare))
> > -		*sps = spare[ARRAY_SIZE(spare) - 1];
> 
> Maybe you could return an error if you didn't find any entry that is
> less that *sps in the table, but I'm not sure this can really happen,
> and the minimum spare size seems to be the same for all IPs, this is
> something you can check before iterating over the array:
> 
> 	if (*sps < MTK_NFC_MIN_SPARE)
> 		return -EINVAL;
> 
OK. It seems better to check whether there is no entry that is less than
*sps.
Will add MTK_NFC_MIN_SPARE and check it.

> > +	*sps = spare[j];
> >  
> >  	if (nand->ecc.size == 1024)
> >  		*sps <<= 1;
> > +
> > +	return 0;
> >  }

Thanks.
Xiaolei

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

* Re: [PATCH v4 3/4] mtd: nand: mediatek: add support for different MTK NAND FLASH Controller IP
@ 2017-05-31  6:52       ` xiaolei li
  0 siblings, 0 replies; 22+ messages in thread
From: xiaolei li @ 2017-05-31  6:52 UTC (permalink / raw)
  To: Boris Brezillon
  Cc: srv_heupstream, yt.shen, robh+dt, linux-mtd, matthias.bgg,
	linux-mediatek, computersforpeace, dwmw2, rogercc.lin

Hi Boris,

On Wed, 2017-05-31 at 08:12 +0200, Boris Brezillon wrote:
> Le Wed, 31 May 2017 11:37:56 +0800,
> Xiaolei Li <xiaolei.li@mediatek.com> a écrit :
> 
> >  
> > -static void mtk_nfc_set_spare_per_sector(u32 *sps, struct mtd_info *mtd)
> > +static int mtk_nfc_set_spare_per_sector(u32 *sps, struct mtd_info *mtd)
> 
> Why do you change the prototype here? You seem to always return 0
> anyway.
> 
Sorry, it should be void.

But as your suggestion below, I will keep using int here to return error
if there is no entry that is less than *sps.

> >  {
> >  	struct nand_chip *nand = mtd_to_nand(mtd);
> > -	u32 spare[] = {16, 26, 27, 28, 32, 36, 40, 44,
> > -			48, 49, 50, 51, 52, 62, 63, 64};
> > -	u32 eccsteps, i;
> > +	struct mtk_nfc *nfc = nand_get_controller_data(nand);
> > +	const u8 *spare = nfc->caps->spare_size;
> > +	u32 eccsteps, i, j = 0;
> 
> Can we rename 'j' into 'closest_spare'?
> 
ok.

> >  
> >  	eccsteps = mtd->writesize / nand->ecc.size;
> >  	*sps = mtd->oobsize / eccsteps;
> > @@ -1144,28 +1102,28 @@ static void mtk_nfc_set_spare_per_sector(u32 *sps, struct mtd_info *mtd)
> >  	if (nand->ecc.size == 1024)
> >  		*sps >>= 1;
> >  
> > -	for (i = 0; i < ARRAY_SIZE(spare); i++) {
> > -		if (*sps <= spare[i]) {
> > -			if (!i)
> > -				*sps = spare[i];
> > -			else if (*sps != spare[i])
> > -				*sps = spare[i - 1];
> > -			break;
> > +	for (i = 0; i < nfc->caps->num_spare_size; i++) {
> > +		if ((*sps >= spare[i]) && (spare[i] >= spare[j])) {
> 
> Parenthesis around the 'a >= b' tests are unneeded:
> 
> 		if (*sps >= spare[i] && spare[i] >= spare[j]) {
> 
ok.

> > +			j = i;
> > +			if (*sps == spare[i])
> > +				break;
> >  		}
> >  	}
> >  
> > -	if (i >= ARRAY_SIZE(spare))
> > -		*sps = spare[ARRAY_SIZE(spare) - 1];
> 
> Maybe you could return an error if you didn't find any entry that is
> less that *sps in the table, but I'm not sure this can really happen,
> and the minimum spare size seems to be the same for all IPs, this is
> something you can check before iterating over the array:
> 
> 	if (*sps < MTK_NFC_MIN_SPARE)
> 		return -EINVAL;
> 
OK. It seems better to check whether there is no entry that is less than
*sps.
Will add MTK_NFC_MIN_SPARE and check it.

> > +	*sps = spare[j];
> >  
> >  	if (nand->ecc.size == 1024)
> >  		*sps <<= 1;
> > +
> > +	return 0;
> >  }

Thanks.
Xiaolei


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

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

* Re: [PATCH v4 1/4] mtd: nand: mediatek: update DT bindings
@ 2017-06-06 10:55     ` Matthias Brugger
  0 siblings, 0 replies; 22+ messages in thread
From: Matthias Brugger @ 2017-06-06 10:55 UTC (permalink / raw)
  To: Xiaolei Li, boris.brezillon, computersforpeace
  Cc: dwmw2, linux-mtd, linux-mediatek, robh+dt, rogercc.lin, yt.shen,
	srv_heupstream



On 31/05/17 05:37, Xiaolei Li wrote:
> Add MT2712 NAND Flash Controller dt bindings documentation.
> 
> Signed-off-by: Xiaolei Li <xiaolei.li@mediatek.com>
> Reviewed-by: Matthias Brugger <matthias.bgg@gmail.com>
> ---

Subject line should be something like;
dt-bindings: mtd: Update mediatek bindings.

>   Documentation/devicetree/bindings/mtd/mtk-nand.txt | 5 +++--
>   1 file changed, 3 insertions(+), 2 deletions(-)
> 
> diff --git a/Documentation/devicetree/bindings/mtd/mtk-nand.txt b/Documentation/devicetree/bindings/mtd/mtk-nand.txt
> index 069c192..dbf9e05 100644
> --- a/Documentation/devicetree/bindings/mtd/mtk-nand.txt
> +++ b/Documentation/devicetree/bindings/mtd/mtk-nand.txt
> @@ -12,7 +12,8 @@ tree nodes.
>   
>   The first part of NFC is NAND Controller Interface (NFI) HW.
>   Required NFI properties:
> -- compatible:			Should be "mediatek,mtxxxx-nfc".
> +- compatible:			Should be one of "mediatek,mt2701-nfc",
> +				"mediatek,mt2712-nfc".
>   - reg:				Base physical address and size of NFI.
>   - interrupts:			Interrupts of NFI.
>   - clocks:			NFI required clocks.
> @@ -141,7 +142,7 @@ Example:
>   ==============
>   
>   Required BCH properties:
> -- compatible:	Should be "mediatek,mtxxxx-ecc".
> +- compatible:	Should be one of "mediatek,mt2701-ecc", "mediatek,mt2712-ecc".
>   - reg:		Base physical address and size of ECC.
>   - interrupts:	Interrupts of ECC.
>   - clocks:	ECC required clocks.
> 

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

* Re: [PATCH v4 1/4] mtd: nand: mediatek: update DT bindings
@ 2017-06-06 10:55     ` Matthias Brugger
  0 siblings, 0 replies; 22+ messages in thread
From: Matthias Brugger @ 2017-06-06 10:55 UTC (permalink / raw)
  To: Xiaolei Li, boris.brezillon-wi1+55ScJUtKEb57/3fJTNBPR1lH4CV8,
	computersforpeace-Re5JQEeQqe8AvxtiuMwx3w
  Cc: srv_heupstream-NuS5LvNUpcJWk0Htik3J/w,
	robh+dt-DgEjT+Ai2ygdnm+yROfE0A,
	linux-mtd-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	yt.shen-NuS5LvNUpcJWk0Htik3J/w,
	linux-mediatek-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	dwmw2-wEGCiKHe2LqWVfeAwA7xHQ, rogercc.lin-NuS5LvNUpcJWk0Htik3J/w



On 31/05/17 05:37, Xiaolei Li wrote:
> Add MT2712 NAND Flash Controller dt bindings documentation.
> 
> Signed-off-by: Xiaolei Li <xiaolei.li-NuS5LvNUpcJWk0Htik3J/w@public.gmane.org>
> Reviewed-by: Matthias Brugger <matthias.bgg-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
> ---

Subject line should be something like;
dt-bindings: mtd: Update mediatek bindings.

>   Documentation/devicetree/bindings/mtd/mtk-nand.txt | 5 +++--
>   1 file changed, 3 insertions(+), 2 deletions(-)
> 
> diff --git a/Documentation/devicetree/bindings/mtd/mtk-nand.txt b/Documentation/devicetree/bindings/mtd/mtk-nand.txt
> index 069c192..dbf9e05 100644
> --- a/Documentation/devicetree/bindings/mtd/mtk-nand.txt
> +++ b/Documentation/devicetree/bindings/mtd/mtk-nand.txt
> @@ -12,7 +12,8 @@ tree nodes.
>   
>   The first part of NFC is NAND Controller Interface (NFI) HW.
>   Required NFI properties:
> -- compatible:			Should be "mediatek,mtxxxx-nfc".
> +- compatible:			Should be one of "mediatek,mt2701-nfc",
> +				"mediatek,mt2712-nfc".
>   - reg:				Base physical address and size of NFI.
>   - interrupts:			Interrupts of NFI.
>   - clocks:			NFI required clocks.
> @@ -141,7 +142,7 @@ Example:
>   ==============
>   
>   Required BCH properties:
> -- compatible:	Should be "mediatek,mtxxxx-ecc".
> +- compatible:	Should be one of "mediatek,mt2701-ecc", "mediatek,mt2712-ecc".
>   - reg:		Base physical address and size of ECC.
>   - interrupts:	Interrupts of ECC.
>   - clocks:	ECC required clocks.
> 

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

* Re: [PATCH v4 1/4] mtd: nand: mediatek: update DT bindings
@ 2017-06-07  7:24       ` xiaolei li
  0 siblings, 0 replies; 22+ messages in thread
From: xiaolei li @ 2017-06-07  7:24 UTC (permalink / raw)
  To: Matthias Brugger
  Cc: boris.brezillon, computersforpeace, dwmw2, linux-mtd,
	linux-mediatek, robh+dt, rogercc.lin, yt.shen, srv_heupstream

Hi Mattias,

On Tue, 2017-06-06 at 12:55 +0200, Matthias Brugger wrote:
> 
> On 31/05/17 05:37, Xiaolei Li wrote:
> > Add MT2712 NAND Flash Controller dt bindings documentation.
> > 
> > Signed-off-by: Xiaolei Li <xiaolei.li@mediatek.com>
> > Reviewed-by: Matthias Brugger <matthias.bgg@gmail.com>
> > ---
> 
> Subject line should be something like;
> dt-bindings: mtd: Update mediatek bindings.

This patch has been accepted on PATCH v5 by Boris. So, should I send
PATCH v6?

Thanks.
> 
> >   Documentation/devicetree/bindings/mtd/mtk-nand.txt | 5 +++--
> >   1 file changed, 3 insertions(+), 2 deletions(-)
> > 
> > diff --git a/Documentation/devicetree/bindings/mtd/mtk-nand.txt b/Documentation/devicetree/bindings/mtd/mtk-nand.txt
> > index 069c192..dbf9e05 100644
> > --- a/Documentation/devicetree/bindings/mtd/mtk-nand.txt
> > +++ b/Documentation/devicetree/bindings/mtd/mtk-nand.txt
> > @@ -12,7 +12,8 @@ tree nodes.
> >   
> >   The first part of NFC is NAND Controller Interface (NFI) HW.
> >   Required NFI properties:
> > -- compatible:			Should be "mediatek,mtxxxx-nfc".
> > +- compatible:			Should be one of "mediatek,mt2701-nfc",
> > +				"mediatek,mt2712-nfc".
> >   - reg:				Base physical address and size of NFI.
> >   - interrupts:			Interrupts of NFI.
> >   - clocks:			NFI required clocks.
> > @@ -141,7 +142,7 @@ Example:
> >   ==============
> >   
> >   Required BCH properties:
> > -- compatible:	Should be "mediatek,mtxxxx-ecc".
> > +- compatible:	Should be one of "mediatek,mt2701-ecc", "mediatek,mt2712-ecc".
> >   - reg:		Base physical address and size of ECC.
> >   - interrupts:	Interrupts of ECC.
> >   - clocks:	ECC required clocks.
> > 

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

* Re: [PATCH v4 1/4] mtd: nand: mediatek: update DT bindings
@ 2017-06-07  7:24       ` xiaolei li
  0 siblings, 0 replies; 22+ messages in thread
From: xiaolei li @ 2017-06-07  7:24 UTC (permalink / raw)
  To: Matthias Brugger
  Cc: boris.brezillon-wi1+55ScJUtKEb57/3fJTNBPR1lH4CV8,
	srv_heupstream-NuS5LvNUpcJWk0Htik3J/w,
	robh+dt-DgEjT+Ai2ygdnm+yROfE0A,
	linux-mediatek-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	yt.shen-NuS5LvNUpcJWk0Htik3J/w,
	linux-mtd-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	computersforpeace-Re5JQEeQqe8AvxtiuMwx3w,
	dwmw2-wEGCiKHe2LqWVfeAwA7xHQ, rogercc.lin-NuS5LvNUpcJWk0Htik3J/w

Hi Mattias,

On Tue, 2017-06-06 at 12:55 +0200, Matthias Brugger wrote:
> 
> On 31/05/17 05:37, Xiaolei Li wrote:
> > Add MT2712 NAND Flash Controller dt bindings documentation.
> > 
> > Signed-off-by: Xiaolei Li <xiaolei.li-NuS5LvNUpcJWk0Htik3J/w@public.gmane.org>
> > Reviewed-by: Matthias Brugger <matthias.bgg-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
> > ---
> 
> Subject line should be something like;
> dt-bindings: mtd: Update mediatek bindings.

This patch has been accepted on PATCH v5 by Boris. So, should I send
PATCH v6?

Thanks.
> 
> >   Documentation/devicetree/bindings/mtd/mtk-nand.txt | 5 +++--
> >   1 file changed, 3 insertions(+), 2 deletions(-)
> > 
> > diff --git a/Documentation/devicetree/bindings/mtd/mtk-nand.txt b/Documentation/devicetree/bindings/mtd/mtk-nand.txt
> > index 069c192..dbf9e05 100644
> > --- a/Documentation/devicetree/bindings/mtd/mtk-nand.txt
> > +++ b/Documentation/devicetree/bindings/mtd/mtk-nand.txt
> > @@ -12,7 +12,8 @@ tree nodes.
> >   
> >   The first part of NFC is NAND Controller Interface (NFI) HW.
> >   Required NFI properties:
> > -- compatible:			Should be "mediatek,mtxxxx-nfc".
> > +- compatible:			Should be one of "mediatek,mt2701-nfc",
> > +				"mediatek,mt2712-nfc".
> >   - reg:				Base physical address and size of NFI.
> >   - interrupts:			Interrupts of NFI.
> >   - clocks:			NFI required clocks.
> > @@ -141,7 +142,7 @@ Example:
> >   ==============
> >   
> >   Required BCH properties:
> > -- compatible:	Should be "mediatek,mtxxxx-ecc".
> > +- compatible:	Should be one of "mediatek,mt2701-ecc", "mediatek,mt2712-ecc".
> >   - reg:		Base physical address and size of ECC.
> >   - interrupts:	Interrupts of ECC.
> >   - clocks:	ECC required clocks.
> > 

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

* Re: [PATCH v4 1/4] mtd: nand: mediatek: update DT bindings
  2017-06-07  7:24       ` xiaolei li
@ 2017-06-07  7:34         ` Boris Brezillon
  -1 siblings, 0 replies; 22+ messages in thread
From: Boris Brezillon @ 2017-06-07  7:34 UTC (permalink / raw)
  To: xiaolei li
  Cc: Matthias Brugger, computersforpeace, dwmw2, linux-mtd,
	linux-mediatek, robh+dt, rogercc.lin, yt.shen, srv_heupstream

On Wed, 7 Jun 2017 15:24:57 +0800
xiaolei li <xiaolei.li@mediatek.com> wrote:

> Hi Mattias,
> 
> On Tue, 2017-06-06 at 12:55 +0200, Matthias Brugger wrote:
> > 
> > On 31/05/17 05:37, Xiaolei Li wrote:  
> > > Add MT2712 NAND Flash Controller dt bindings documentation.
> > > 
> > > Signed-off-by: Xiaolei Li <xiaolei.li@mediatek.com>
> > > Reviewed-by: Matthias Brugger <matthias.bgg@gmail.com>
> > > ---  
> > 
> > Subject line should be something like;
> > dt-bindings: mtd: Update mediatek bindings.  
> 
> This patch has been accepted on PATCH v5 by Boris. So, should I send
> PATCH v6?

No, I already applied the patch, and it's not such a big deal anyway.
Try to use this prefix for you future DT bindings contributions ;-).

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

* Re: [PATCH v4 1/4] mtd: nand: mediatek: update DT bindings
@ 2017-06-07  7:34         ` Boris Brezillon
  0 siblings, 0 replies; 22+ messages in thread
From: Boris Brezillon @ 2017-06-07  7:34 UTC (permalink / raw)
  To: xiaolei li
  Cc: srv_heupstream-NuS5LvNUpcJWk0Htik3J/w,
	yt.shen-NuS5LvNUpcJWk0Htik3J/w, robh+dt-DgEjT+Ai2ygdnm+yROfE0A,
	linux-mtd-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r, Matthias Brugger,
	linux-mediatek-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	computersforpeace-Re5JQEeQqe8AvxtiuMwx3w,
	dwmw2-wEGCiKHe2LqWVfeAwA7xHQ, rogercc.lin-NuS5LvNUpcJWk0Htik3J/w

On Wed, 7 Jun 2017 15:24:57 +0800
xiaolei li <xiaolei.li-NuS5LvNUpcJWk0Htik3J/w@public.gmane.org> wrote:

> Hi Mattias,
> 
> On Tue, 2017-06-06 at 12:55 +0200, Matthias Brugger wrote:
> > 
> > On 31/05/17 05:37, Xiaolei Li wrote:  
> > > Add MT2712 NAND Flash Controller dt bindings documentation.
> > > 
> > > Signed-off-by: Xiaolei Li <xiaolei.li-NuS5LvNUpcJWk0Htik3J/w@public.gmane.org>
> > > Reviewed-by: Matthias Brugger <matthias.bgg-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
> > > ---  
> > 
> > Subject line should be something like;
> > dt-bindings: mtd: Update mediatek bindings.  
> 
> This patch has been accepted on PATCH v5 by Boris. So, should I send
> PATCH v6?

No, I already applied the patch, and it's not such a big deal anyway.
Try to use this prefix for you future DT bindings contributions ;-).

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

* Re: [PATCH v4 1/4] mtd: nand: mediatek: update DT bindings
  2017-06-07  7:34         ` Boris Brezillon
@ 2017-06-07  7:37           ` xiaolei li
  -1 siblings, 0 replies; 22+ messages in thread
From: xiaolei li @ 2017-06-07  7:37 UTC (permalink / raw)
  To: Boris Brezillon
  Cc: Matthias Brugger, computersforpeace, dwmw2, linux-mtd,
	linux-mediatek, robh+dt, rogercc.lin, yt.shen, srv_heupstream

On Wed, 2017-06-07 at 09:34 +0200, Boris Brezillon wrote:
> On Wed, 7 Jun 2017 15:24:57 +0800
> xiaolei li <xiaolei.li@mediatek.com> wrote:
> 
> > Hi Mattias,
> > 
> > On Tue, 2017-06-06 at 12:55 +0200, Matthias Brugger wrote:
> > > 
> > > On 31/05/17 05:37, Xiaolei Li wrote:  
> > > > Add MT2712 NAND Flash Controller dt bindings documentation.
> > > > 
> > > > Signed-off-by: Xiaolei Li <xiaolei.li@mediatek.com>
> > > > Reviewed-by: Matthias Brugger <matthias.bgg@gmail.com>
> > > > ---  
> > > 
> > > Subject line should be something like;
> > > dt-bindings: mtd: Update mediatek bindings.  
> > 
> > This patch has been accepted on PATCH v5 by Boris. So, should I send
> > PATCH v6?
> 
> No, I already applied the patch, and it's not such a big deal anyway.
> Try to use this prefix for you future DT bindings contributions ;-).

OK. Thanks Boris, Matthias.

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

* Re: [PATCH v4 1/4] mtd: nand: mediatek: update DT bindings
@ 2017-06-07  7:37           ` xiaolei li
  0 siblings, 0 replies; 22+ messages in thread
From: xiaolei li @ 2017-06-07  7:37 UTC (permalink / raw)
  To: Boris Brezillon
  Cc: srv_heupstream-NuS5LvNUpcJWk0Htik3J/w,
	yt.shen-NuS5LvNUpcJWk0Htik3J/w, robh+dt-DgEjT+Ai2ygdnm+yROfE0A,
	linux-mtd-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r, Matthias Brugger,
	linux-mediatek-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	computersforpeace-Re5JQEeQqe8AvxtiuMwx3w,
	dwmw2-wEGCiKHe2LqWVfeAwA7xHQ, rogercc.lin-NuS5LvNUpcJWk0Htik3J/w

On Wed, 2017-06-07 at 09:34 +0200, Boris Brezillon wrote:
> On Wed, 7 Jun 2017 15:24:57 +0800
> xiaolei li <xiaolei.li-NuS5LvNUpcJWk0Htik3J/w@public.gmane.org> wrote:
> 
> > Hi Mattias,
> > 
> > On Tue, 2017-06-06 at 12:55 +0200, Matthias Brugger wrote:
> > > 
> > > On 31/05/17 05:37, Xiaolei Li wrote:  
> > > > Add MT2712 NAND Flash Controller dt bindings documentation.
> > > > 
> > > > Signed-off-by: Xiaolei Li <xiaolei.li-NuS5LvNUpcJWk0Htik3J/w@public.gmane.org>
> > > > Reviewed-by: Matthias Brugger <matthias.bgg-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
> > > > ---  
> > > 
> > > Subject line should be something like;
> > > dt-bindings: mtd: Update mediatek bindings.  
> > 
> > This patch has been accepted on PATCH v5 by Boris. So, should I send
> > PATCH v6?
> 
> No, I already applied the patch, and it's not such a big deal anyway.
> Try to use this prefix for you future DT bindings contributions ;-).

OK. Thanks Boris, Matthias.

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

end of thread, other threads:[~2017-06-07  7:37 UTC | newest]

Thread overview: 22+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2017-05-31  3:37 [PATCH v4 0/4] Mediatek MT2712 NAND FLASH Controller driver Xiaolei Li
2017-05-31  3:37 ` Xiaolei Li
2017-05-31  3:37 ` [PATCH v4 1/4] mtd: nand: mediatek: update DT bindings Xiaolei Li
2017-05-31  3:37   ` Xiaolei Li
2017-06-06 10:55   ` Matthias Brugger
2017-06-06 10:55     ` Matthias Brugger
2017-06-07  7:24     ` xiaolei li
2017-06-07  7:24       ` xiaolei li
2017-06-07  7:34       ` Boris Brezillon
2017-06-07  7:34         ` Boris Brezillon
2017-06-07  7:37         ` xiaolei li
2017-06-07  7:37           ` xiaolei li
2017-05-31  3:37 ` [PATCH v4 2/4] mtd: nand: mediatek: refine register NFI_PAGEFMT setting Xiaolei Li
2017-05-31  3:37   ` Xiaolei Li
2017-05-31  3:37 ` [PATCH v4 3/4] mtd: nand: mediatek: add support for different MTK NAND FLASH Controller IP Xiaolei Li
2017-05-31  3:37   ` Xiaolei Li
2017-05-31  6:12   ` Boris Brezillon
2017-05-31  6:12     ` Boris Brezillon
2017-05-31  6:52     ` xiaolei li
2017-05-31  6:52       ` xiaolei li
2017-05-31  3:37 ` [PATCH v4 4/4] mtd: nand: mediatek: add support for MT2712 NAND FLASH Controller Xiaolei Li
2017-05-31  3:37   ` Xiaolei Li

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.