[OpenWrt-Devel] [PATCH] kernel: mtd: spinand: Backport chip definitions

Jeff Kletsky lede at allycomm.com
Thu Oct 24 12:54:11 EDT 2019


From: Jeff Kletsky <git-commits at allycomm.com>

generic: Add/rename patches for upstream consistency

ipq40xx: generic-level patch replaces same-source patches-4.19/
         082-v4.20-mtd-spinand-winbond-Add-support-for-W25N01GV.patch

The SPI-NAND framework from Linux uses common driver code that is then
"tuned" by a tiny struct of chip-specific data that describes
available commands, timing, and layout (data and OOB data). Several
manufacturers and chips have been added since 4.19, several of which
are used in devices already supported by OpenWrt (typically with no or
"legacy" access to their NAND memory). This commit catches up the
supported-chip definitions through Linux 5.2-rc6 and linux/next.

The driver is only compiled for platforms with CONFIG_MTD_SPI_NAND=y.
This presently includes ipq40xx and pistachio, with the addition of
ath79-nand in these commits (and not ath79-generic or ath79-tiny).

Upstream patches refreshed against 4.19.75

Build-tested-on: ipq40xx
Run-tested-on: ath79-nand

Signed-off-by: Jeff Kletsky <git-commits at allycomm.com>
---
 ...nd-winbond-Add-support-for-W25N01GV.patch} |  12 +-
 ...initial-support-for-Toshiba-TC58CVG2.patch | 188 ++++++++++++++++
 ...d-support-for-GigaDevice-GD5FxGQ4xA.patch} |  12 +-
 ...support-for-all-Toshiba-Memory-produ.patch | 136 ++++++++++++
 ...upport-for-GigaDevice-GD5F1GQ4UExxG.patch} |   4 +-
 ...ne-macros-for-page-read-ops-with-thr.patch |  81 +++++++
 ...-Add-support-for-two-byte-device-IDs.patch |  48 +++++
 ...support-for-GigaDevice-GD5F1GQ4UFxxG.patch | 197 +++++++++++++++++
 ...initial-support-for-Paragon-PN26G0xA.patch | 203 ++++++++++++++++++
 9 files changed, 870 insertions(+), 11 deletions(-)
 rename target/linux/{ipq40xx/patches-4.19/082-v4.20-mtd-spinand-winbond-Add-support-for-W25N01GV.patch => generic/backport-4.19/450-v5.0-mtd-spinand-winbond-Add-support-for-W25N01GV.patch} (67%)
 create mode 100644 target/linux/generic/backport-4.19/451-v5.0-mtd-spinand-Add-initial-support-for-Toshiba-TC58CVG2.patch
 rename target/linux/generic/backport-4.19/{450-v5.0-mtd-spinand-add-support-for-GigaDevice-GD5FxGQ4xA.patch => 452-v5.0-mtd-spinand-add-support-for-GigaDevice-GD5FxGQ4xA.patch} (94%)
 create mode 100644 target/linux/generic/backport-4.19/455-v5.1-mtd-spinand-Add-support-for-all-Toshiba-Memory-produ.patch
 rename target/linux/generic/backport-4.19/{451-v5.1-mtd-spinand-Add-support-for-GigaDevice-GD5F1GQ4UExxG.patch => 456-v5.1-mtd-spinand-Add-support-for-GigaDevice-GD5F1GQ4UExxG.patch} (97%)
 create mode 100644 target/linux/generic/backport-4.19/460-v5.3-mtd-spinand-Define-macros-for-page-read-ops-with-thr.patch
 create mode 100644 target/linux/generic/backport-4.19/461-v5.3-mtd-spinand-Add-support-for-two-byte-device-IDs.patch
 create mode 100644 target/linux/generic/backport-4.19/462-v5.3-mtd-spinand-Add-support-for-GigaDevice-GD5F1GQ4UFxxG.patch
 create mode 100644 target/linux/generic/backport-4.19/463-v5.3-mtd-spinand-Add-initial-support-for-Paragon-PN26G0xA.patch

diff --git a/target/linux/ipq40xx/patches-4.19/082-v4.20-mtd-spinand-winbond-Add-support-for-W25N01GV.patch b/target/linux/generic/backport-4.19/450-v5.0-mtd-spinand-winbond-Add-support-for-W25N01GV.patch
similarity index 67%
rename from target/linux/ipq40xx/patches-4.19/082-v4.20-mtd-spinand-winbond-Add-support-for-W25N01GV.patch
rename to target/linux/generic/backport-4.19/450-v5.0-mtd-spinand-winbond-Add-support-for-W25N01GV.patch
index 22bd985124..2024577b8f 100644
--- a/target/linux/ipq40xx/patches-4.19/082-v4.20-mtd-spinand-winbond-Add-support-for-W25N01GV.patch
+++ b/target/linux/generic/backport-4.19/450-v5.0-mtd-spinand-winbond-Add-support-for-W25N01GV.patch
@@ -1,13 +1,19 @@
-From 342fc01bfd6d717602c71d96d3ef40a36e45e060 Mon Sep 17 00:00:00 2001
+From 9a4d83074769d6ecf1f5c3fef0f183b09abf3726 Mon Sep 17 00:00:00 2001
 From: Robert Marko <robimarko at gmail.com>
-Date: Fri, 5 Oct 2018 09:02:50 +0200
-Subject: [PATCH] mtd: spinand: winbond: Add support for W25N01GV
+Date: Sat, 6 Oct 2018 17:36:42 +0200
+Subject: [PATCH 1/8] mtd: spinand: winbond: Add support for W25N01GV
 
 W25N01GV is a single die version of the already supported
 W25M02GV with half the capacity. Everything else is the
 same so introduce support for W25N01GV.
 
+Datasheet:http://www.winbond.com/resource-files/w25n01gv%20revl%20050918%20unsecured.pdf
+
+Tested on 8devices Jalapeno dev board under OpenWrt running 4.19-rc5.
+
 Signed-off-by: Robert Marko <robimarko at gmail.com>
+Reviewed-by: Boris Brezillon <boris.brezillon at bootlin.com>
+Signed-off-by: Miquel Raynal <miquel.raynal at bootlin.com>
 ---
  drivers/mtd/nand/spi/winbond.c | 8 ++++++++
  1 file changed, 8 insertions(+)
diff --git a/target/linux/generic/backport-4.19/451-v5.0-mtd-spinand-Add-initial-support-for-Toshiba-TC58CVG2.patch b/target/linux/generic/backport-4.19/451-v5.0-mtd-spinand-Add-initial-support-for-Toshiba-TC58CVG2.patch
new file mode 100644
index 0000000000..ed42f0024b
--- /dev/null
+++ b/target/linux/generic/backport-4.19/451-v5.0-mtd-spinand-Add-initial-support-for-Toshiba-TC58CVG2.patch
@@ -0,0 +1,188 @@
+From 10949af1681d5bb5cdbcc012815c6e40eec17d02 Mon Sep 17 00:00:00 2001
+From: Schrempf Frieder <frieder.schrempf at kontron.De>
+Date: Thu, 8 Nov 2018 08:32:11 +0000
+Subject: [PATCH 2/8] mtd: spinand: Add initial support for Toshiba TC58CVG2S0H
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Add minimal support for the Toshiba TC58CVG2S0H SPI NAND chip.
+
+Signed-off-by: Frieder Schrempf <frieder.schrempf at kontron.de>
+Acked-by: Clément Péron <peron.clem at gmail.com>
+Signed-off-by: Miquel Raynal <miquel.raynal at bootlin.com>
+---
+ drivers/mtd/nand/spi/Makefile  |   2 +-
+ drivers/mtd/nand/spi/core.c    |   1 +
+ drivers/mtd/nand/spi/toshiba.c | 137 +++++++++++++++++++++++++++++++++
+ include/linux/mtd/spinand.h    |   1 +
+ 4 files changed, 140 insertions(+), 1 deletion(-)
+ create mode 100644 drivers/mtd/nand/spi/toshiba.c
+
+--- a/drivers/mtd/nand/spi/Makefile
++++ b/drivers/mtd/nand/spi/Makefile
+@@ -1,3 +1,3 @@
+ # SPDX-License-Identifier: GPL-2.0
+-spinand-objs := core.o macronix.o micron.o winbond.o
++spinand-objs := core.o macronix.o micron.o toshiba.o winbond.o
+ obj-$(CONFIG_MTD_SPI_NAND) += spinand.o
+--- a/drivers/mtd/nand/spi/core.c
++++ b/drivers/mtd/nand/spi/core.c
+@@ -764,6 +764,7 @@ static const struct nand_ops spinand_ops
+ static const struct spinand_manufacturer *spinand_manufacturers[] = {
+ 	&macronix_spinand_manufacturer,
+ 	&micron_spinand_manufacturer,
++	&toshiba_spinand_manufacturer,
+ 	&winbond_spinand_manufacturer,
+ };
+ 
+--- /dev/null
++++ b/drivers/mtd/nand/spi/toshiba.c
+@@ -0,0 +1,137 @@
++// SPDX-License-Identifier: GPL-2.0
++/*
++ * Copyright (c) 2018 exceet electronics GmbH
++ * Copyright (c) 2018 Kontron Electronics GmbH
++ *
++ * Author: Frieder Schrempf <frieder.schrempf at kontron.de>
++ */
++
++#include <linux/device.h>
++#include <linux/kernel.h>
++#include <linux/mtd/spinand.h>
++
++#define SPINAND_MFR_TOSHIBA		0x98
++#define TOSH_STATUS_ECC_HAS_BITFLIPS_T	(3 << 4)
++
++static SPINAND_OP_VARIANTS(read_cache_variants,
++		SPINAND_PAGE_READ_FROM_CACHE_X4_OP(0, 1, NULL, 0),
++		SPINAND_PAGE_READ_FROM_CACHE_X2_OP(0, 1, NULL, 0),
++		SPINAND_PAGE_READ_FROM_CACHE_OP(true, 0, 1, NULL, 0),
++		SPINAND_PAGE_READ_FROM_CACHE_OP(false, 0, 1, NULL, 0));
++
++static SPINAND_OP_VARIANTS(write_cache_variants,
++		SPINAND_PROG_LOAD(true, 0, NULL, 0));
++
++static SPINAND_OP_VARIANTS(update_cache_variants,
++		SPINAND_PROG_LOAD(false, 0, NULL, 0));
++
++static int tc58cvg2s0h_ooblayout_ecc(struct mtd_info *mtd, int section,
++				     struct mtd_oob_region *region)
++{
++	if (section > 7)
++		return -ERANGE;
++
++	region->offset = 128 + 16 * section;
++	region->length = 16;
++
++	return 0;
++}
++
++static int tc58cvg2s0h_ooblayout_free(struct mtd_info *mtd, int section,
++				      struct mtd_oob_region *region)
++{
++	if (section > 0)
++		return -ERANGE;
++
++	/* 2 bytes reserved for BBM */
++	region->offset = 2;
++	region->length = 126;
++
++	return 0;
++}
++
++static const struct mtd_ooblayout_ops tc58cvg2s0h_ooblayout = {
++	.ecc = tc58cvg2s0h_ooblayout_ecc,
++	.free = tc58cvg2s0h_ooblayout_free,
++};
++
++static int tc58cvg2s0h_ecc_get_status(struct spinand_device *spinand,
++				      u8 status)
++{
++	struct nand_device *nand = spinand_to_nand(spinand);
++	u8 mbf = 0;
++	struct spi_mem_op op = SPINAND_GET_FEATURE_OP(0x30, &mbf);
++
++	switch (status & STATUS_ECC_MASK) {
++	case STATUS_ECC_NO_BITFLIPS:
++		return 0;
++
++	case STATUS_ECC_UNCOR_ERROR:
++		return -EBADMSG;
++
++	case STATUS_ECC_HAS_BITFLIPS:
++	case TOSH_STATUS_ECC_HAS_BITFLIPS_T:
++		/*
++		 * Let's try to retrieve the real maximum number of bitflips
++		 * in order to avoid forcing the wear-leveling layer to move
++		 * data around if it's not necessary.
++		 */
++		if (spi_mem_exec_op(spinand->spimem, &op))
++			return nand->eccreq.strength;
++
++		mbf >>= 4;
++
++		if (WARN_ON(mbf > nand->eccreq.strength || !mbf))
++			return nand->eccreq.strength;
++
++		return mbf;
++
++	default:
++		break;
++	}
++
++	return -EINVAL;
++}
++
++static const struct spinand_info toshiba_spinand_table[] = {
++	SPINAND_INFO("TC58CVG2S0H", 0xCD,
++		     NAND_MEMORG(1, 4096, 256, 64, 2048, 1, 1, 1),
++		     NAND_ECCREQ(8, 512),
++		     SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
++					      &write_cache_variants,
++					      &update_cache_variants),
++		     SPINAND_HAS_QE_BIT,
++		     SPINAND_ECCINFO(&tc58cvg2s0h_ooblayout,
++				     tc58cvg2s0h_ecc_get_status)),
++};
++
++static int toshiba_spinand_detect(struct spinand_device *spinand)
++{
++	u8 *id = spinand->id.data;
++	int ret;
++
++	/*
++	 * Toshiba SPI NAND read ID needs a dummy byte,
++	 * so the first byte in id is garbage.
++	 */
++	if (id[1] != SPINAND_MFR_TOSHIBA)
++		return 0;
++
++	ret = spinand_match_and_init(spinand, toshiba_spinand_table,
++				     ARRAY_SIZE(toshiba_spinand_table),
++				     id[2]);
++	if (ret)
++		return ret;
++
++	return 1;
++}
++
++static const struct spinand_manufacturer_ops toshiba_spinand_manuf_ops = {
++	.detect = toshiba_spinand_detect,
++};
++
++const struct spinand_manufacturer toshiba_spinand_manufacturer = {
++	.id = SPINAND_MFR_TOSHIBA,
++	.name = "Toshiba",
++	.ops = &toshiba_spinand_manuf_ops,
++};
+--- a/include/linux/mtd/spinand.h
++++ b/include/linux/mtd/spinand.h
+@@ -196,6 +196,7 @@ struct spinand_manufacturer {
+ /* SPI NAND manufacturers */
+ extern const struct spinand_manufacturer macronix_spinand_manufacturer;
+ extern const struct spinand_manufacturer micron_spinand_manufacturer;
++extern const struct spinand_manufacturer toshiba_spinand_manufacturer;
+ extern const struct spinand_manufacturer winbond_spinand_manufacturer;
+ 
+ /**
diff --git a/target/linux/generic/backport-4.19/450-v5.0-mtd-spinand-add-support-for-GigaDevice-GD5FxGQ4xA.patch b/target/linux/generic/backport-4.19/452-v5.0-mtd-spinand-add-support-for-GigaDevice-GD5FxGQ4xA.patch
similarity index 94%
rename from target/linux/generic/backport-4.19/450-v5.0-mtd-spinand-add-support-for-GigaDevice-GD5FxGQ4xA.patch
rename to target/linux/generic/backport-4.19/452-v5.0-mtd-spinand-add-support-for-GigaDevice-GD5FxGQ4xA.patch
index 15f761ab9d..4e6f18a4cb 100644
--- a/target/linux/generic/backport-4.19/450-v5.0-mtd-spinand-add-support-for-GigaDevice-GD5FxGQ4xA.patch
+++ b/target/linux/generic/backport-4.19/452-v5.0-mtd-spinand-add-support-for-GigaDevice-GD5FxGQ4xA.patch
@@ -1,7 +1,7 @@
 From c93c613214ac70c87beab5422a60077bf126b855 Mon Sep 17 00:00:00 2001
 From: Chuanhong Guo <gch981213 at gmail.com>
 Date: Wed, 28 Nov 2018 21:07:25 +0800
-Subject: [PATCH] mtd: spinand: add support for GigaDevice GD5FxGQ4xA
+Subject: [PATCH 3/8] mtd: spinand: add support for GigaDevice GD5FxGQ4xA
 
 Add support for GigaDevice GD5F1G/2G/4GQ4xA SPI NAND.
 
@@ -11,7 +11,7 @@ Signed-off-by: Miquel Raynal <miquel.raynal at bootlin.com>
 ---
  drivers/mtd/nand/spi/Makefile     |   2 +-
  drivers/mtd/nand/spi/core.c       |   1 +
- drivers/mtd/nand/spi/gigadevice.c | 148 ++++++++++++++++++++++++++++++++++++++
+ drivers/mtd/nand/spi/gigadevice.c | 148 ++++++++++++++++++++++++++++++
  include/linux/mtd/spinand.h       |   1 +
  4 files changed, 151 insertions(+), 1 deletion(-)
  create mode 100644 drivers/mtd/nand/spi/gigadevice.c
@@ -20,8 +20,8 @@ Signed-off-by: Miquel Raynal <miquel.raynal at bootlin.com>
 +++ b/drivers/mtd/nand/spi/Makefile
 @@ -1,3 +1,3 @@
  # SPDX-License-Identifier: GPL-2.0
--spinand-objs := core.o macronix.o micron.o winbond.o
-+spinand-objs := core.o gigadevice.o macronix.o micron.o winbond.o
+-spinand-objs := core.o macronix.o micron.o toshiba.o winbond.o
++spinand-objs := core.o gigadevice.o macronix.o micron.o toshiba.o winbond.o
  obj-$(CONFIG_MTD_SPI_NAND) += spinand.o
 --- a/drivers/mtd/nand/spi/core.c
 +++ b/drivers/mtd/nand/spi/core.c
@@ -32,7 +32,7 @@ Signed-off-by: Miquel Raynal <miquel.raynal at bootlin.com>
 +	&gigadevice_spinand_manufacturer,
  	&macronix_spinand_manufacturer,
  	&micron_spinand_manufacturer,
- 	&winbond_spinand_manufacturer,
+ 	&toshiba_spinand_manufacturer,
 --- /dev/null
 +++ b/drivers/mtd/nand/spi/gigadevice.c
 @@ -0,0 +1,148 @@
@@ -193,4 +193,4 @@ Signed-off-by: Miquel Raynal <miquel.raynal at bootlin.com>
 +extern const struct spinand_manufacturer gigadevice_spinand_manufacturer;
  extern const struct spinand_manufacturer macronix_spinand_manufacturer;
  extern const struct spinand_manufacturer micron_spinand_manufacturer;
- extern const struct spinand_manufacturer winbond_spinand_manufacturer;
+ extern const struct spinand_manufacturer toshiba_spinand_manufacturer;
diff --git a/target/linux/generic/backport-4.19/455-v5.1-mtd-spinand-Add-support-for-all-Toshiba-Memory-produ.patch b/target/linux/generic/backport-4.19/455-v5.1-mtd-spinand-Add-support-for-all-Toshiba-Memory-produ.patch
new file mode 100644
index 0000000000..aad82dcf7a
--- /dev/null
+++ b/target/linux/generic/backport-4.19/455-v5.1-mtd-spinand-Add-support-for-all-Toshiba-Memory-produ.patch
@@ -0,0 +1,136 @@
+From db214513f62fd13c0a9af3bd5c5d634dba37e65d Mon Sep 17 00:00:00 2001
+From: Yoshio Furuyama <tmcmc-mb-yfuruyama7 at ml.toshiba.co.jp>
+Date: Wed, 16 Jan 2019 14:53:19 +0900
+Subject: [PATCH 7/8] mtd: spinand: Add support for all Toshiba Memory products
+
+Add device table for Toshiba Memory products.
+Also, generalize OOB layout structure and function names.
+
+Signed-off-by: Yoshio Furuyama <tmcmc-mb-yfuruyama7 at ml.toshiba.co.jp>
+Reviewed-by: Frieder Schrempf <frieder.schrempf at kontron.de>
+Signed-off-by: Miquel Raynal <miquel.raynal at bootlin.com>
+---
+ drivers/mtd/nand/spi/toshiba.c | 79 ++++++++++++++++++++++++++++------
+ 1 file changed, 65 insertions(+), 14 deletions(-)
+
+--- a/drivers/mtd/nand/spi/toshiba.c
++++ b/drivers/mtd/nand/spi/toshiba.c
+@@ -25,19 +25,19 @@ static SPINAND_OP_VARIANTS(write_cache_v
+ static SPINAND_OP_VARIANTS(update_cache_variants,
+ 		SPINAND_PROG_LOAD(false, 0, NULL, 0));
+ 
+-static int tc58cvg2s0h_ooblayout_ecc(struct mtd_info *mtd, int section,
++static int tc58cxgxsx_ooblayout_ecc(struct mtd_info *mtd, int section,
+ 				     struct mtd_oob_region *region)
+ {
+-	if (section > 7)
++	if (section > 0)
+ 		return -ERANGE;
+ 
+-	region->offset = 128 + 16 * section;
+-	region->length = 16;
++	region->offset = mtd->oobsize / 2;
++	region->length = mtd->oobsize / 2;
+ 
+ 	return 0;
+ }
+ 
+-static int tc58cvg2s0h_ooblayout_free(struct mtd_info *mtd, int section,
++static int tc58cxgxsx_ooblayout_free(struct mtd_info *mtd, int section,
+ 				      struct mtd_oob_region *region)
+ {
+ 	if (section > 0)
+@@ -45,17 +45,17 @@ static int tc58cvg2s0h_ooblayout_free(st
+ 
+ 	/* 2 bytes reserved for BBM */
+ 	region->offset = 2;
+-	region->length = 126;
++	region->length = (mtd->oobsize / 2) - 2;
+ 
+ 	return 0;
+ }
+ 
+-static const struct mtd_ooblayout_ops tc58cvg2s0h_ooblayout = {
+-	.ecc = tc58cvg2s0h_ooblayout_ecc,
+-	.free = tc58cvg2s0h_ooblayout_free,
++static const struct mtd_ooblayout_ops tc58cxgxsx_ooblayout = {
++	.ecc = tc58cxgxsx_ooblayout_ecc,
++	.free = tc58cxgxsx_ooblayout_free,
+ };
+ 
+-static int tc58cvg2s0h_ecc_get_status(struct spinand_device *spinand,
++static int tc58cxgxsx_ecc_get_status(struct spinand_device *spinand,
+ 				      u8 status)
+ {
+ 	struct nand_device *nand = spinand_to_nand(spinand);
+@@ -94,15 +94,66 @@ static int tc58cvg2s0h_ecc_get_status(st
+ }
+ 
+ static const struct spinand_info toshiba_spinand_table[] = {
+-	SPINAND_INFO("TC58CVG2S0H", 0xCD,
++	/* 3.3V 1Gb */
++	SPINAND_INFO("TC58CVG0S3", 0xC2,
++		     NAND_MEMORG(1, 2048, 128, 64, 1024, 1, 1, 1),
++		     NAND_ECCREQ(8, 512),
++		     SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
++					      &write_cache_variants,
++					      &update_cache_variants),
++		     0,
++		     SPINAND_ECCINFO(&tc58cxgxsx_ooblayout,
++				     tc58cxgxsx_ecc_get_status)),
++	/* 3.3V 2Gb */
++	SPINAND_INFO("TC58CVG1S3", 0xCB,
++		     NAND_MEMORG(1, 2048, 128, 64, 2048, 1, 1, 1),
++		     NAND_ECCREQ(8, 512),
++		     SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
++					      &write_cache_variants,
++					      &update_cache_variants),
++		     0,
++		     SPINAND_ECCINFO(&tc58cxgxsx_ooblayout,
++				     tc58cxgxsx_ecc_get_status)),
++	/* 3.3V 4Gb */
++	SPINAND_INFO("TC58CVG2S0", 0xCD,
++		     NAND_MEMORG(1, 4096, 256, 64, 2048, 1, 1, 1),
++		     NAND_ECCREQ(8, 512),
++		     SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
++					      &write_cache_variants,
++					      &update_cache_variants),
++		     0,
++		     SPINAND_ECCINFO(&tc58cxgxsx_ooblayout,
++				     tc58cxgxsx_ecc_get_status)),
++	/* 1.8V 1Gb */
++	SPINAND_INFO("TC58CYG0S3", 0xB2,
++		     NAND_MEMORG(1, 2048, 128, 64, 1024, 1, 1, 1),
++		     NAND_ECCREQ(8, 512),
++		     SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
++					      &write_cache_variants,
++					      &update_cache_variants),
++		     0,
++		     SPINAND_ECCINFO(&tc58cxgxsx_ooblayout,
++				     tc58cxgxsx_ecc_get_status)),
++	/* 1.8V 2Gb */
++	SPINAND_INFO("TC58CYG1S3", 0xBB,
++		     NAND_MEMORG(1, 2048, 128, 64, 2048, 1, 1, 1),
++		     NAND_ECCREQ(8, 512),
++		     SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
++					      &write_cache_variants,
++					      &update_cache_variants),
++		     0,
++		     SPINAND_ECCINFO(&tc58cxgxsx_ooblayout,
++				     tc58cxgxsx_ecc_get_status)),
++	/* 1.8V 4Gb */
++	SPINAND_INFO("TC58CYG2S0", 0xBD,
+ 		     NAND_MEMORG(1, 4096, 256, 64, 2048, 1, 1, 1),
+ 		     NAND_ECCREQ(8, 512),
+ 		     SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
+ 					      &write_cache_variants,
+ 					      &update_cache_variants),
+-		     SPINAND_HAS_QE_BIT,
+-		     SPINAND_ECCINFO(&tc58cvg2s0h_ooblayout,
+-				     tc58cvg2s0h_ecc_get_status)),
++		     0,
++		     SPINAND_ECCINFO(&tc58cxgxsx_ooblayout,
++				     tc58cxgxsx_ecc_get_status)),
+ };
+ 
+ static int toshiba_spinand_detect(struct spinand_device *spinand)
diff --git a/target/linux/generic/backport-4.19/451-v5.1-mtd-spinand-Add-support-for-GigaDevice-GD5F1GQ4UExxG.patch b/target/linux/generic/backport-4.19/456-v5.1-mtd-spinand-Add-support-for-GigaDevice-GD5F1GQ4UExxG.patch
similarity index 97%
rename from target/linux/generic/backport-4.19/451-v5.1-mtd-spinand-Add-support-for-GigaDevice-GD5F1GQ4UExxG.patch
rename to target/linux/generic/backport-4.19/456-v5.1-mtd-spinand-Add-support-for-GigaDevice-GD5F1GQ4UExxG.patch
index f6d6764707..8e48debf43 100644
--- a/target/linux/generic/backport-4.19/451-v5.1-mtd-spinand-Add-support-for-GigaDevice-GD5F1GQ4UExxG.patch
+++ b/target/linux/generic/backport-4.19/456-v5.1-mtd-spinand-Add-support-for-GigaDevice-GD5F1GQ4UExxG.patch
@@ -1,7 +1,7 @@
 From c40c7a990a46e5102a1cc4190557bf315d32d80d Mon Sep 17 00:00:00 2001
 From: Stefan Roese <sr at denx.de>
 Date: Thu, 24 Jan 2019 13:48:06 +0100
-Subject: [PATCH] mtd: spinand: Add support for GigaDevice GD5F1GQ4UExxG
+Subject: [PATCH 8/8] mtd: spinand: Add support for GigaDevice GD5F1GQ4UExxG
 
 Add support for GigaDevice GD5F1GQ4UExxG SPI NAND chip.
 
@@ -13,7 +13,7 @@ Cc: Boris Brezillon <bbrezillon at kernel.org>
 Reviewed-by: Boris Brezillon <bbrezillon at kernel.org>
 Signed-off-by: Miquel Raynal <miquel.raynal at bootlin.com>
 ---
- drivers/mtd/nand/spi/gigadevice.c | 83 +++++++++++++++++++++++++++++++++++++++
+ drivers/mtd/nand/spi/gigadevice.c | 83 +++++++++++++++++++++++++++++++
  1 file changed, 83 insertions(+)
 
 --- a/drivers/mtd/nand/spi/gigadevice.c
diff --git a/target/linux/generic/backport-4.19/460-v5.3-mtd-spinand-Define-macros-for-page-read-ops-with-thr.patch b/target/linux/generic/backport-4.19/460-v5.3-mtd-spinand-Define-macros-for-page-read-ops-with-thr.patch
new file mode 100644
index 0000000000..c28ae1d797
--- /dev/null
+++ b/target/linux/generic/backport-4.19/460-v5.3-mtd-spinand-Define-macros-for-page-read-ops-with-thr.patch
@@ -0,0 +1,81 @@
+From d014717d50b1efd011a3a028ce92563a4dc9bae5 Mon Sep 17 00:00:00 2001
+From: Jeff Kletsky <git-commits at allycomm.com>
+Date: Wed, 22 May 2019 15:05:53 -0700
+Subject: [PATCH 1/3] mtd: spinand: Define macros for page-read ops with
+ three-byte addresses
+
+The GigaDevice GD5F1GQ4UFxxG SPI NAND utilizes three-byte addresses
+for its page-read ops.
+
+http://www.gigadevice.com/datasheet/gd5f1gq4xfxxg/
+
+Signed-off-by: Jeff Kletsky <git-commits at allycomm.com>
+Reviewed-by: Frieder Schrempf <frieder.schrempf at kontron.de>
+Signed-off-by: Miquel Raynal <miquel.raynal at bootlin.com>
+---
+ include/linux/mtd/spinand.h | 30 ++++++++++++++++++++++++++++++
+ 1 file changed, 30 insertions(+)
+
+--- a/include/linux/mtd/spinand.h
++++ b/include/linux/mtd/spinand.h
+@@ -68,30 +68,60 @@
+ 		   SPI_MEM_OP_DUMMY(ndummy, 1),				\
+ 		   SPI_MEM_OP_DATA_IN(len, buf, 1))
+ 
++#define SPINAND_PAGE_READ_FROM_CACHE_OP_3A(fast, addr, ndummy, buf, len) \
++	SPI_MEM_OP(SPI_MEM_OP_CMD(fast ? 0x0b : 0x03, 1),		\
++		   SPI_MEM_OP_ADDR(3, addr, 1),				\
++		   SPI_MEM_OP_DUMMY(ndummy, 1),				\
++		   SPI_MEM_OP_DATA_IN(len, buf, 1))
++
+ #define SPINAND_PAGE_READ_FROM_CACHE_X2_OP(addr, ndummy, buf, len)	\
+ 	SPI_MEM_OP(SPI_MEM_OP_CMD(0x3b, 1),				\
+ 		   SPI_MEM_OP_ADDR(2, addr, 1),				\
+ 		   SPI_MEM_OP_DUMMY(ndummy, 1),				\
+ 		   SPI_MEM_OP_DATA_IN(len, buf, 2))
+ 
++#define SPINAND_PAGE_READ_FROM_CACHE_X2_OP_3A(addr, ndummy, buf, len)	\
++	SPI_MEM_OP(SPI_MEM_OP_CMD(0x3b, 1),				\
++		   SPI_MEM_OP_ADDR(3, addr, 1),				\
++		   SPI_MEM_OP_DUMMY(ndummy, 1),				\
++		   SPI_MEM_OP_DATA_IN(len, buf, 2))
++
+ #define SPINAND_PAGE_READ_FROM_CACHE_X4_OP(addr, ndummy, buf, len)	\
+ 	SPI_MEM_OP(SPI_MEM_OP_CMD(0x6b, 1),				\
+ 		   SPI_MEM_OP_ADDR(2, addr, 1),				\
+ 		   SPI_MEM_OP_DUMMY(ndummy, 1),				\
+ 		   SPI_MEM_OP_DATA_IN(len, buf, 4))
+ 
++#define SPINAND_PAGE_READ_FROM_CACHE_X4_OP_3A(addr, ndummy, buf, len)	\
++	SPI_MEM_OP(SPI_MEM_OP_CMD(0x6b, 1),				\
++		   SPI_MEM_OP_ADDR(3, addr, 1),				\
++		   SPI_MEM_OP_DUMMY(ndummy, 1),				\
++		   SPI_MEM_OP_DATA_IN(len, buf, 4))
++
+ #define SPINAND_PAGE_READ_FROM_CACHE_DUALIO_OP(addr, ndummy, buf, len)	\
+ 	SPI_MEM_OP(SPI_MEM_OP_CMD(0xbb, 1),				\
+ 		   SPI_MEM_OP_ADDR(2, addr, 2),				\
+ 		   SPI_MEM_OP_DUMMY(ndummy, 2),				\
+ 		   SPI_MEM_OP_DATA_IN(len, buf, 2))
+ 
++#define SPINAND_PAGE_READ_FROM_CACHE_DUALIO_OP_3A(addr, ndummy, buf, len) \
++	SPI_MEM_OP(SPI_MEM_OP_CMD(0xbb, 1),				\
++		   SPI_MEM_OP_ADDR(3, addr, 2),				\
++		   SPI_MEM_OP_DUMMY(ndummy, 2),				\
++		   SPI_MEM_OP_DATA_IN(len, buf, 2))
++
+ #define SPINAND_PAGE_READ_FROM_CACHE_QUADIO_OP(addr, ndummy, buf, len)	\
+ 	SPI_MEM_OP(SPI_MEM_OP_CMD(0xeb, 1),				\
+ 		   SPI_MEM_OP_ADDR(2, addr, 4),				\
+ 		   SPI_MEM_OP_DUMMY(ndummy, 4),				\
+ 		   SPI_MEM_OP_DATA_IN(len, buf, 4))
+ 
++#define SPINAND_PAGE_READ_FROM_CACHE_QUADIO_OP_3A(addr, ndummy, buf, len) \
++	SPI_MEM_OP(SPI_MEM_OP_CMD(0xeb, 1),				\
++		   SPI_MEM_OP_ADDR(3, addr, 4),				\
++		   SPI_MEM_OP_DUMMY(ndummy, 4),				\
++		   SPI_MEM_OP_DATA_IN(len, buf, 4))
++
+ #define SPINAND_PROG_EXEC_OP(addr)					\
+ 	SPI_MEM_OP(SPI_MEM_OP_CMD(0x10, 1),				\
+ 		   SPI_MEM_OP_ADDR(3, addr, 1),				\
diff --git a/target/linux/generic/backport-4.19/461-v5.3-mtd-spinand-Add-support-for-two-byte-device-IDs.patch b/target/linux/generic/backport-4.19/461-v5.3-mtd-spinand-Add-support-for-two-byte-device-IDs.patch
new file mode 100644
index 0000000000..fcbecbb762
--- /dev/null
+++ b/target/linux/generic/backport-4.19/461-v5.3-mtd-spinand-Add-support-for-two-byte-device-IDs.patch
@@ -0,0 +1,48 @@
+From 53dd94a79d3bfdaae30e5a4ebf474ea1af1d572e Mon Sep 17 00:00:00 2001
+From: Jeff Kletsky <git-commits at allycomm.com>
+Date: Wed, 22 May 2019 15:05:54 -0700
+Subject: [PATCH 2/3] mtd: spinand: Add support for two-byte device IDs
+
+The GigaDevice GD5F1GQ4UFxxG SPI NAND utilizes two-byte device IDs.
+
+http://www.gigadevice.com/datasheet/gd5f1gq4xfxxg/
+
+Signed-off-by: Jeff Kletsky <git-commits at allycomm.com>
+Reviewed-by: Frieder Schrempf <frieder.schrempf at kontron.de>
+Signed-off-by: Miquel Raynal <miquel.raynal at bootlin.com>
+---
+ drivers/mtd/nand/spi/core.c | 2 +-
+ include/linux/mtd/spinand.h | 4 ++--
+ 2 files changed, 3 insertions(+), 3 deletions(-)
+
+--- a/drivers/mtd/nand/spi/core.c
++++ b/drivers/mtd/nand/spi/core.c
+@@ -853,7 +853,7 @@ spinand_select_op_variant(struct spinand
+  */
+ int spinand_match_and_init(struct spinand_device *spinand,
+ 			   const struct spinand_info *table,
+-			   unsigned int table_size, u8 devid)
++			   unsigned int table_size, u16 devid)
+ {
+ 	struct nand_device *nand = spinand_to_nand(spinand);
+ 	unsigned int i;
+--- a/include/linux/mtd/spinand.h
++++ b/include/linux/mtd/spinand.h
+@@ -290,7 +290,7 @@ struct spinand_ecc_info {
+  */
+ struct spinand_info {
+ 	const char *model;
+-	u8 devid;
++	u16 devid;
+ 	u32 flags;
+ 	struct nand_memory_organization memorg;
+ 	struct nand_ecc_req eccreq;
+@@ -445,7 +445,7 @@ static inline void spinand_set_of_node(s
+ 
+ int spinand_match_and_init(struct spinand_device *dev,
+ 			   const struct spinand_info *table,
+-			   unsigned int table_size, u8 devid);
++			   unsigned int table_size, u16 devid);
+ 
+ int spinand_upd_cfg(struct spinand_device *spinand, u8 mask, u8 val);
+ int spinand_select_target(struct spinand_device *spinand, unsigned int target);
diff --git a/target/linux/generic/backport-4.19/462-v5.3-mtd-spinand-Add-support-for-GigaDevice-GD5F1GQ4UFxxG.patch b/target/linux/generic/backport-4.19/462-v5.3-mtd-spinand-Add-support-for-GigaDevice-GD5F1GQ4UFxxG.patch
new file mode 100644
index 0000000000..06d87ba5e0
--- /dev/null
+++ b/target/linux/generic/backport-4.19/462-v5.3-mtd-spinand-Add-support-for-GigaDevice-GD5F1GQ4UFxxG.patch
@@ -0,0 +1,197 @@
+
+IMPORTANT NOTE
+==============
+
+The content of this patch has been adapted for Linux 4.19
+
+Changes were made in Linux 5.x to add the bad-block limit
+to the metadata available to the driver, adding a parameter
+
+NAND_MEMORG(1, 2048, 128, 64, 1024, 20, 1, 1, 1),
+                                     ^- New bad-block limit
+
+This patch omits that parameter from the upstream patch
+for compatibility with the Linux 4.19 driver.
+
+=====
+
+From 049df13c4e63884fe6634db5568e08f65922256e Mon Sep 17 00:00:00 2001
+From: Jeff Kletsky <git-commits at allycomm.com>
+Date: Wed, 22 May 2019 15:05:55 -0700
+Subject: [PATCH 3/3] mtd: spinand: Add support for GigaDevice GD5F1GQ4UFxxG
+
+The GigaDevice GD5F1GQ4UFxxG SPI NAND is in current production devices
+and, while it has the same logical layout as the E-series devices,
+it differs in the SPI interfacing in significant ways.
+
+This support is contingent on previous commits to:
+
+  * Add support for two-byte device IDs
+  * Define macros for page-read ops with three-byte addresses
+
+http://www.gigadevice.com/datasheet/gd5f1gq4xfxxg/
+
+Signed-off-by: Jeff Kletsky <git-commits at allycomm.com>
+Reviewed-by: Frieder Schrempf <frieder.schrempf at kontron.de>
+Signed-off-by: Miquel Raynal <miquel.raynal at bootlin.com>
+---
+ drivers/mtd/nand/spi/gigadevice.c | 79 +++++++++++++++++++++++++------
+ 1 file changed, 64 insertions(+), 15 deletions(-)
+
+--- a/drivers/mtd/nand/spi/gigadevice.c
++++ b/drivers/mtd/nand/spi/gigadevice.c
+@@ -9,11 +9,17 @@
+ #include <linux/mtd/spinand.h>
+ 
+ #define SPINAND_MFR_GIGADEVICE			0xC8
++
+ #define GD5FXGQ4XA_STATUS_ECC_1_7_BITFLIPS	(1 << 4)
+ #define GD5FXGQ4XA_STATUS_ECC_8_BITFLIPS	(3 << 4)
+ 
+ #define GD5FXGQ4UEXXG_REG_STATUS2		0xf0
+ 
++#define GD5FXGQ4UXFXXG_STATUS_ECC_MASK		(7 << 4)
++#define GD5FXGQ4UXFXXG_STATUS_ECC_NO_BITFLIPS	(0 << 4)
++#define GD5FXGQ4UXFXXG_STATUS_ECC_1_3_BITFLIPS	(1 << 4)
++#define GD5FXGQ4UXFXXG_STATUS_ECC_UNCOR_ERROR	(7 << 4)
++
+ static SPINAND_OP_VARIANTS(read_cache_variants,
+ 		SPINAND_PAGE_READ_FROM_CACHE_QUADIO_OP(0, 2, NULL, 0),
+ 		SPINAND_PAGE_READ_FROM_CACHE_X4_OP(0, 1, NULL, 0),
+@@ -22,6 +28,14 @@ static SPINAND_OP_VARIANTS(read_cache_va
+ 		SPINAND_PAGE_READ_FROM_CACHE_OP(true, 0, 1, NULL, 0),
+ 		SPINAND_PAGE_READ_FROM_CACHE_OP(false, 0, 1, NULL, 0));
+ 
++static SPINAND_OP_VARIANTS(read_cache_variants_f,
++		SPINAND_PAGE_READ_FROM_CACHE_QUADIO_OP(0, 2, NULL, 0),
++		SPINAND_PAGE_READ_FROM_CACHE_X4_OP_3A(0, 1, NULL, 0),
++		SPINAND_PAGE_READ_FROM_CACHE_DUALIO_OP(0, 1, NULL, 0),
++		SPINAND_PAGE_READ_FROM_CACHE_X2_OP_3A(0, 1, NULL, 0),
++		SPINAND_PAGE_READ_FROM_CACHE_OP_3A(true, 0, 1, NULL, 0),
++		SPINAND_PAGE_READ_FROM_CACHE_OP_3A(false, 0, 0, NULL, 0));
++
+ static SPINAND_OP_VARIANTS(write_cache_variants,
+ 		SPINAND_PROG_LOAD_X4(true, 0, NULL, 0),
+ 		SPINAND_PROG_LOAD(true, 0, NULL, 0));
+@@ -59,6 +73,11 @@ static int gd5fxgq4xa_ooblayout_free(str
+ 	return 0;
+ }
+ 
++static const struct mtd_ooblayout_ops gd5fxgq4xa_ooblayout = {
++	.ecc = gd5fxgq4xa_ooblayout_ecc,
++	.free = gd5fxgq4xa_ooblayout_free,
++};
++
+ static int gd5fxgq4xa_ecc_get_status(struct spinand_device *spinand,
+ 					 u8 status)
+ {
+@@ -83,7 +102,7 @@ static int gd5fxgq4xa_ecc_get_status(str
+ 	return -EINVAL;
+ }
+ 
+-static int gd5fxgq4uexxg_ooblayout_ecc(struct mtd_info *mtd, int section,
++static int gd5fxgq4_variant2_ooblayout_ecc(struct mtd_info *mtd, int section,
+ 				       struct mtd_oob_region *region)
+ {
+ 	if (section)
+@@ -95,7 +114,7 @@ static int gd5fxgq4uexxg_ooblayout_ecc(s
+ 	return 0;
+ }
+ 
+-static int gd5fxgq4uexxg_ooblayout_free(struct mtd_info *mtd, int section,
++static int gd5fxgq4_variant2_ooblayout_free(struct mtd_info *mtd, int section,
+ 					struct mtd_oob_region *region)
+ {
+ 	if (section)
+@@ -108,6 +127,11 @@ static int gd5fxgq4uexxg_ooblayout_free(
+ 	return 0;
+ }
+ 
++static const struct mtd_ooblayout_ops gd5fxgq4_variant2_ooblayout = {
++	.ecc = gd5fxgq4_variant2_ooblayout_ecc,
++	.free = gd5fxgq4_variant2_ooblayout_free,
++};
++
+ static int gd5fxgq4uexxg_ecc_get_status(struct spinand_device *spinand,
+ 					u8 status)
+ {
+@@ -150,15 +174,25 @@ static int gd5fxgq4uexxg_ecc_get_status(
+ 	return -EINVAL;
+ }
+ 
+-static const struct mtd_ooblayout_ops gd5fxgq4xa_ooblayout = {
+-	.ecc = gd5fxgq4xa_ooblayout_ecc,
+-	.free = gd5fxgq4xa_ooblayout_free,
+-};
++static int gd5fxgq4ufxxg_ecc_get_status(struct spinand_device *spinand,
++					u8 status)
++{
++	switch (status & GD5FXGQ4UXFXXG_STATUS_ECC_MASK) {
++	case GD5FXGQ4UXFXXG_STATUS_ECC_NO_BITFLIPS:
++		return 0;
+ 
+-static const struct mtd_ooblayout_ops gd5fxgq4uexxg_ooblayout = {
+-	.ecc = gd5fxgq4uexxg_ooblayout_ecc,
+-	.free = gd5fxgq4uexxg_ooblayout_free,
+-};
++	case GD5FXGQ4UXFXXG_STATUS_ECC_1_3_BITFLIPS:
++		return 3;
++
++	case GD5FXGQ4UXFXXG_STATUS_ECC_UNCOR_ERROR:
++		return -EBADMSG;
++
++	default: /* (2 << 4) through (6 << 4) are 4-8 corrected errors */
++		return ((status & GD5FXGQ4UXFXXG_STATUS_ECC_MASK) >> 4) + 2;
++	}
++
++	return -EINVAL;
++}
+ 
+ static const struct spinand_info gigadevice_spinand_table[] = {
+ 	SPINAND_INFO("GD5F1GQ4xA", 0xF1,
+@@ -195,25 +229,40 @@ static const struct spinand_info gigadev
+ 					      &write_cache_variants,
+ 					      &update_cache_variants),
+ 		     0,
+-		     SPINAND_ECCINFO(&gd5fxgq4uexxg_ooblayout,
++		     SPINAND_ECCINFO(&gd5fxgq4_variant2_ooblayout,
+ 				     gd5fxgq4uexxg_ecc_get_status)),
++	SPINAND_INFO("GD5F1GQ4UFxxG", 0xb148,
++		     NAND_MEMORG(1, 2048, 128, 64, 1024, 1, 1, 1),
++		     NAND_ECCREQ(8, 512),
++		     SPINAND_INFO_OP_VARIANTS(&read_cache_variants_f,
++					      &write_cache_variants,
++					      &update_cache_variants),
++		     0,
++		     SPINAND_ECCINFO(&gd5fxgq4_variant2_ooblayout,
++				     gd5fxgq4ufxxg_ecc_get_status)),
+ };
+ 
+ static int gigadevice_spinand_detect(struct spinand_device *spinand)
+ {
+ 	u8 *id = spinand->id.data;
++	u16 did;
+ 	int ret;
+ 
+ 	/*
+-	 * For GD NANDs, There is an address byte needed to shift in before IDs
+-	 * are read out, so the first byte in raw_id is dummy.
++	 * Earlier GDF5-series devices (A,E) return [0][MID][DID]
++	 * Later (F) devices return [MID][DID1][DID2]
+ 	 */
+-	if (id[1] != SPINAND_MFR_GIGADEVICE)
++
++	if (id[0] == SPINAND_MFR_GIGADEVICE)
++		did = (id[1] << 8) + id[2];
++	else if (id[0] == 0 && id[1] == SPINAND_MFR_GIGADEVICE)
++		did = id[2];
++	else
+ 		return 0;
+ 
+ 	ret = spinand_match_and_init(spinand, gigadevice_spinand_table,
+ 				     ARRAY_SIZE(gigadevice_spinand_table),
+-				     id[2]);
++				     did);
+ 	if (ret)
+ 		return ret;
+ 
diff --git a/target/linux/generic/backport-4.19/463-v5.3-mtd-spinand-Add-initial-support-for-Paragon-PN26G0xA.patch b/target/linux/generic/backport-4.19/463-v5.3-mtd-spinand-Add-initial-support-for-Paragon-PN26G0xA.patch
new file mode 100644
index 0000000000..17b8e779bc
--- /dev/null
+++ b/target/linux/generic/backport-4.19/463-v5.3-mtd-spinand-Add-initial-support-for-Paragon-PN26G0xA.patch
@@ -0,0 +1,203 @@
+From 3552691616c940a7c4125c2678ba816653cd725e Mon Sep 17 00:00:00 2001
+From: Jeff Kletsky <git-commits at allycomm.com>
+Date: Tue, 18 Jun 2019 10:08:05 -0700
+Subject: [PATCH] mtd: spinand: Add initial support for Paragon PN26G0xA
+
+Add initial support for Paragon Technology
+PN26G01Axxxxx and PN26G02Axxxxx SPI NAND
+
+Datasheets available at
+http://www.xtxtech.com/upfile/2016082517274590.pdf
+http://www.xtxtech.com/upfile/2016082517282329.pdf
+
+Signed-off-by: Jeff Kletsky <git-commits at allycomm.com>
+Reviewed-by: Frieder Schrempf <frieder.schrempf at kontron.de>
+Signed-off-by: Miquel Raynal <miquel.raynal at bootlin.com>
+
+ADOPTED FROM UPSTREAM	due to upstream commit 377e517b5fa5 in Linux 5.2
+			which added another parameter to NAND_MEMORG
+---
+ drivers/mtd/nand/spi/Makefile  |   2 +-
+ drivers/mtd/nand/spi/core.c    |   1 +
+ drivers/mtd/nand/spi/paragon.c | 147 +++++++++++++++++++++++++++++++++
+ include/linux/mtd/spinand.h    |   1 +
+ 4 files changed, 150 insertions(+), 1 deletion(-)
+ create mode 100644 drivers/mtd/nand/spi/paragon.c
+
+--- a/drivers/mtd/nand/spi/Makefile
++++ b/drivers/mtd/nand/spi/Makefile
+@@ -1,3 +1,3 @@
+ # SPDX-License-Identifier: GPL-2.0
+-spinand-objs := core.o gigadevice.o macronix.o micron.o toshiba.o winbond.o
++spinand-objs := core.o gigadevice.o macronix.o micron.o paragon.o toshiba.o winbond.o
+ obj-$(CONFIG_MTD_SPI_NAND) += spinand.o
+--- a/drivers/mtd/nand/spi/core.c
++++ b/drivers/mtd/nand/spi/core.c
+@@ -765,6 +765,7 @@ static const struct spinand_manufacturer
+ 	&gigadevice_spinand_manufacturer,
+ 	&macronix_spinand_manufacturer,
+ 	&micron_spinand_manufacturer,
++	&paragon_spinand_manufacturer,
+ 	&toshiba_spinand_manufacturer,
+ 	&winbond_spinand_manufacturer,
+ };
+--- /dev/null
++++ b/drivers/mtd/nand/spi/paragon.c
+@@ -0,0 +1,147 @@
++// SPDX-License-Identifier: GPL-2.0
++/*
++ * Copyright (C) 2019 Jeff Kletsky
++ *
++ * Author: Jeff Kletsky <git-commits at allycomm.com>
++ */
++
++#include <linux/device.h>
++#include <linux/kernel.h>
++#include <linux/mtd/spinand.h>
++
++
++#define SPINAND_MFR_PARAGON	0xa1
++
++
++#define PN26G0XA_STATUS_ECC_BITMASK		(3 << 4)
++
++#define PN26G0XA_STATUS_ECC_NONE_DETECTED	(0 << 4)
++#define PN26G0XA_STATUS_ECC_1_7_CORRECTED	(1 << 4)
++#define PN26G0XA_STATUS_ECC_ERRORED		(2 << 4)
++#define PN26G0XA_STATUS_ECC_8_CORRECTED		(3 << 4)
++
++
++static SPINAND_OP_VARIANTS(read_cache_variants,
++		SPINAND_PAGE_READ_FROM_CACHE_QUADIO_OP(0, 2, NULL, 0),
++		SPINAND_PAGE_READ_FROM_CACHE_X4_OP(0, 1, NULL, 0),
++		SPINAND_PAGE_READ_FROM_CACHE_DUALIO_OP(0, 1, NULL, 0),
++		SPINAND_PAGE_READ_FROM_CACHE_X2_OP(0, 1, NULL, 0),
++		SPINAND_PAGE_READ_FROM_CACHE_OP(true, 0, 1, NULL, 0),
++		SPINAND_PAGE_READ_FROM_CACHE_OP(false, 0, 1, NULL, 0));
++
++static SPINAND_OP_VARIANTS(write_cache_variants,
++		SPINAND_PROG_LOAD_X4(true, 0, NULL, 0),
++		SPINAND_PROG_LOAD(true, 0, NULL, 0));
++
++static SPINAND_OP_VARIANTS(update_cache_variants,
++		SPINAND_PROG_LOAD_X4(false, 0, NULL, 0),
++		SPINAND_PROG_LOAD(false, 0, NULL, 0));
++
++
++static int pn26g0xa_ooblayout_ecc(struct mtd_info *mtd, int section,
++				   struct mtd_oob_region *region)
++{
++	if (section > 3)
++		return -ERANGE;
++
++	region->offset = 6 + (15 * section); /* 4 BBM + 2 user bytes */
++	region->length = 13;
++
++	return 0;
++}
++
++static int pn26g0xa_ooblayout_free(struct mtd_info *mtd, int section,
++				   struct mtd_oob_region *region)
++{
++	if (section > 4)
++		return -ERANGE;
++
++	if (section == 4) {
++		region->offset = 64;
++		region->length = 64;
++	} else {
++		region->offset = 4 + (15 * section);
++		region->length = 2;
++	}
++
++	return 0;
++}
++
++static int pn26g0xa_ecc_get_status(struct spinand_device *spinand,
++				   u8 status)
++{
++	switch (status & PN26G0XA_STATUS_ECC_BITMASK) {
++	case PN26G0XA_STATUS_ECC_NONE_DETECTED:
++		return 0;
++
++	case PN26G0XA_STATUS_ECC_1_7_CORRECTED:
++		return 7;	/* Return upper limit by convention */
++
++	case PN26G0XA_STATUS_ECC_8_CORRECTED:
++		return 8;
++
++	case PN26G0XA_STATUS_ECC_ERRORED:
++		return -EBADMSG;
++
++	default:
++		break;
++	}
++
++	return -EINVAL;
++}
++
++static const struct mtd_ooblayout_ops pn26g0xa_ooblayout = {
++	.ecc = pn26g0xa_ooblayout_ecc,
++	.free = pn26g0xa_ooblayout_free,
++};
++
++
++static const struct spinand_info paragon_spinand_table[] = {
++	SPINAND_INFO("PN26G01A", 0xe1,
++		     NAND_MEMORG(1, 2048, 128, 64, 1024, 1, 1, 1),
++		     NAND_ECCREQ(8, 512),
++		     SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
++					      &write_cache_variants,
++					      &update_cache_variants),
++		     0,
++		     SPINAND_ECCINFO(&pn26g0xa_ooblayout,
++				     pn26g0xa_ecc_get_status)),
++	SPINAND_INFO("PN26G02A", 0xe2,
++		     NAND_MEMORG(1, 2048, 128, 64, 2048, 1, 1, 1),
++		     NAND_ECCREQ(8, 512),
++		     SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
++					      &write_cache_variants,
++					      &update_cache_variants),
++		     0,
++		     SPINAND_ECCINFO(&pn26g0xa_ooblayout,
++				     pn26g0xa_ecc_get_status)),
++};
++
++static int paragon_spinand_detect(struct spinand_device *spinand)
++{
++	u8 *id = spinand->id.data;
++	int ret;
++
++	/* Read ID returns [0][MID][DID] */
++
++	if (id[1] != SPINAND_MFR_PARAGON)
++		return 0;
++
++	ret = spinand_match_and_init(spinand, paragon_spinand_table,
++				     ARRAY_SIZE(paragon_spinand_table),
++				     id[2]);
++	if (ret)
++		return ret;
++
++	return 1;
++}
++
++static const struct spinand_manufacturer_ops paragon_spinand_manuf_ops = {
++	.detect = paragon_spinand_detect,
++};
++
++const struct spinand_manufacturer paragon_spinand_manufacturer = {
++	.id = SPINAND_MFR_PARAGON,
++	.name = "Paragon",
++	.ops = &paragon_spinand_manuf_ops,
++};
+--- a/include/linux/mtd/spinand.h
++++ b/include/linux/mtd/spinand.h
+@@ -227,6 +227,7 @@ struct spinand_manufacturer {
+ extern const struct spinand_manufacturer gigadevice_spinand_manufacturer;
+ extern const struct spinand_manufacturer macronix_spinand_manufacturer;
+ extern const struct spinand_manufacturer micron_spinand_manufacturer;
++extern const struct spinand_manufacturer paragon_spinand_manufacturer;
+ extern const struct spinand_manufacturer toshiba_spinand_manufacturer;
+ extern const struct spinand_manufacturer winbond_spinand_manufacturer;
+ 
-- 
2.20.1


_______________________________________________
openwrt-devel mailing list
openwrt-devel at lists.openwrt.org
https://lists.openwrt.org/mailman/listinfo/openwrt-devel


More information about the openwrt-devel mailing list