Re: [PATCH V4] mtd: spinand: Add support for XTX SPINAND

2024-04-14 Thread Dario Binacchi
Hi Bruce,

On Tue, Mar 12, 2024 at 2:43 AM Bruce Suen  wrote:
>
> Add support for XTX XT26G0xA and XT26xxxD. The driver is ported from
> linux-6.7.1. This driver is tested on Banana BPI-R3 with XT26G01A and
> XT26G12D.
>
> Signed-off-by: Bruce Suen 
> Reviewed-by: Frieder Schrempf 
> ---
> V3->V4:
> - modify commit message minor flaws
> ---
>  drivers/mtd/nand/spi/Makefile |   2 +-
>  drivers/mtd/nand/spi/core.c   |   1 +
>  drivers/mtd/nand/spi/xtx.c| 266 ++
>  include/linux/mtd/spinand.h   |   1 +
>  4 files changed, 269 insertions(+), 1 deletion(-)
>  create mode 100644 drivers/mtd/nand/spi/xtx.c
>
> diff --git a/drivers/mtd/nand/spi/Makefile b/drivers/mtd/nand/spi/Makefile
> index f172f4787f..65b836b34c 100644
> --- a/drivers/mtd/nand/spi/Makefile
> +++ b/drivers/mtd/nand/spi/Makefile
> @@ -1,5 +1,5 @@
>  # SPDX-License-Identifier: GPL-2.0
>
>  spinand-objs := core.o esmt.o gigadevice.o macronix.o micron.o paragon.o
> -spinand-objs += toshiba.o winbond.o
> +spinand-objs += toshiba.o winbond.o xtx.o
>  obj-$(CONFIG_MTD_SPI_NAND) += spinand.o
> diff --git a/drivers/mtd/nand/spi/core.c b/drivers/mtd/nand/spi/core.c
> index 8ca33459f9..62c28aa422 100644
> --- a/drivers/mtd/nand/spi/core.c
> +++ b/drivers/mtd/nand/spi/core.c
> @@ -829,6 +829,7 @@ static const struct spinand_manufacturer 
> *spinand_manufacturers[] = {
> _spinand_manufacturer,
> _spinand_manufacturer,
> _c8_spinand_manufacturer,
> +   _spinand_manufacturer,
>  };
>
>  static int spinand_manufacturer_match(struct spinand_device *spinand,
> diff --git a/drivers/mtd/nand/spi/xtx.c b/drivers/mtd/nand/spi/xtx.c
> new file mode 100644
> index 00..aee1849a71
> --- /dev/null
> +++ b/drivers/mtd/nand/spi/xtx.c
> @@ -0,0 +1,266 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/*
> + * Author:
> + * Felix Matouschek 
> + */
> +
> +#include 
> +#ifndef __UBOOT__
> +#include 
> +#include 
> +#endif
> +#include 
> +
> +#define SPINAND_MFR_XTX0x0B
> +
> +#define XT26G0XA_STATUS_ECC_MASK   GENMASK(5, 2)
> +#define XT26G0XA_STATUS_ECC_NO_DETECTED(0 << 2)
> +#define XT26G0XA_STATUS_ECC_8_CORRECTED(3 << 4)
> +#define XT26G0XA_STATUS_ECC_UNCOR_ERROR(2 << 4)
> +
> +#define XT26XXXD_STATUS_ECC3_ECC2_MASK GENMASK(7, 6)
> +#define XT26XXXD_STATUS_ECC_NO_DETECTED (0)
> +#define XT26XXXD_STATUS_ECC_1_7_CORRECTED   (1)
> +#define XT26XXXD_STATUS_ECC_8_CORRECTED (3)
> +#define XT26XXXD_STATUS_ECC_UNCOR_ERROR (2)
> +
> +static SPINAND_OP_VARIANTS(read_cache_variants,
> +   SPINAND_PAGE_READ_FROM_CACHE_QUADIO_OP(0, 1, 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 xt26g0xa_ooblayout_ecc(struct mtd_info *mtd, int section,
> + struct mtd_oob_region *region)
> +{
> +   if (section)
> +   return -ERANGE;
> +
> +   region->offset = 48;
> +   region->length = 16;
> +
> +   return 0;
> +}
> +
> +static int xt26g0xa_ooblayout_free(struct mtd_info *mtd, int section,
> +  struct mtd_oob_region *region)
> +{
> +   if (section)
> +   return -ERANGE;
> +
> +   region->offset = 1;
> +   region->length = 47;
> +
> +   return 0;
> +}
> +
> +static const struct mtd_ooblayout_ops xt26g0xa_ooblayout = {
> +   .ecc = xt26g0xa_ooblayout_ecc,
> +   .rfree = xt26g0xa_ooblayout_free,
> +};
> +
> +static int xt26g0xa_ecc_get_status(struct spinand_device *spinand,
> +  u8 status)
> +{
> +   status = status & XT26G0XA_STATUS_ECC_MASK;
> +
> +   switch (status) {
> +   case XT26G0XA_STATUS_ECC_NO_DETECTED:
> +   return 0;
> +   case XT26G0XA_STATUS_ECC_8_CORRECTED:
> +   return 8;
> +   case XT26G0XA_STATUS_ECC_UNCOR_ERROR:
> +   return -EBADMSG;
> +   default:
> +   break;
> +   }
> +
> +   /* At this point values greater than (2 << 4) are invalid  */
> +   if (status > XT26G0XA_STATUS_ECC_UNCOR_ERROR)
> +   return -EINVAL;
> +
> +   /* (1 << 2) through (7 << 2) are 1-7 corrected errors */
> +   return status >> 2;
> +}
> +
> +static int xt26xxxd_ooblayout_ecc(struct mtd_info *mtd, int section,
> + struct 

[PATCH V4] mtd: spinand: Add support for XTX SPINAND

2024-03-11 Thread Bruce Suen
Add support for XTX XT26G0xA and XT26xxxD. The driver is ported from
linux-6.7.1. This driver is tested on Banana BPI-R3 with XT26G01A and
XT26G12D.

Signed-off-by: Bruce Suen 
Reviewed-by: Frieder Schrempf 
---
V3->V4:
- modify commit message minor flaws
---
 drivers/mtd/nand/spi/Makefile |   2 +-
 drivers/mtd/nand/spi/core.c   |   1 +
 drivers/mtd/nand/spi/xtx.c| 266 ++
 include/linux/mtd/spinand.h   |   1 +
 4 files changed, 269 insertions(+), 1 deletion(-)
 create mode 100644 drivers/mtd/nand/spi/xtx.c

diff --git a/drivers/mtd/nand/spi/Makefile b/drivers/mtd/nand/spi/Makefile
index f172f4787f..65b836b34c 100644
--- a/drivers/mtd/nand/spi/Makefile
+++ b/drivers/mtd/nand/spi/Makefile
@@ -1,5 +1,5 @@
 # SPDX-License-Identifier: GPL-2.0
 
 spinand-objs := core.o esmt.o gigadevice.o macronix.o micron.o paragon.o
-spinand-objs += toshiba.o winbond.o
+spinand-objs += toshiba.o winbond.o xtx.o
 obj-$(CONFIG_MTD_SPI_NAND) += spinand.o
diff --git a/drivers/mtd/nand/spi/core.c b/drivers/mtd/nand/spi/core.c
index 8ca33459f9..62c28aa422 100644
--- a/drivers/mtd/nand/spi/core.c
+++ b/drivers/mtd/nand/spi/core.c
@@ -829,6 +829,7 @@ static const struct spinand_manufacturer 
*spinand_manufacturers[] = {
_spinand_manufacturer,
_spinand_manufacturer,
_c8_spinand_manufacturer,
+   _spinand_manufacturer,
 };
 
 static int spinand_manufacturer_match(struct spinand_device *spinand,
diff --git a/drivers/mtd/nand/spi/xtx.c b/drivers/mtd/nand/spi/xtx.c
new file mode 100644
index 00..aee1849a71
--- /dev/null
+++ b/drivers/mtd/nand/spi/xtx.c
@@ -0,0 +1,266 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Author:
+ * Felix Matouschek 
+ */
+
+#include 
+#ifndef __UBOOT__
+#include 
+#include 
+#endif
+#include 
+
+#define SPINAND_MFR_XTX0x0B
+
+#define XT26G0XA_STATUS_ECC_MASK   GENMASK(5, 2)
+#define XT26G0XA_STATUS_ECC_NO_DETECTED(0 << 2)
+#define XT26G0XA_STATUS_ECC_8_CORRECTED(3 << 4)
+#define XT26G0XA_STATUS_ECC_UNCOR_ERROR(2 << 4)
+
+#define XT26XXXD_STATUS_ECC3_ECC2_MASK GENMASK(7, 6)
+#define XT26XXXD_STATUS_ECC_NO_DETECTED (0)
+#define XT26XXXD_STATUS_ECC_1_7_CORRECTED   (1)
+#define XT26XXXD_STATUS_ECC_8_CORRECTED (3)
+#define XT26XXXD_STATUS_ECC_UNCOR_ERROR (2)
+
+static SPINAND_OP_VARIANTS(read_cache_variants,
+   SPINAND_PAGE_READ_FROM_CACHE_QUADIO_OP(0, 1, 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 xt26g0xa_ooblayout_ecc(struct mtd_info *mtd, int section,
+ struct mtd_oob_region *region)
+{
+   if (section)
+   return -ERANGE;
+
+   region->offset = 48;
+   region->length = 16;
+
+   return 0;
+}
+
+static int xt26g0xa_ooblayout_free(struct mtd_info *mtd, int section,
+  struct mtd_oob_region *region)
+{
+   if (section)
+   return -ERANGE;
+
+   region->offset = 1;
+   region->length = 47;
+
+   return 0;
+}
+
+static const struct mtd_ooblayout_ops xt26g0xa_ooblayout = {
+   .ecc = xt26g0xa_ooblayout_ecc,
+   .rfree = xt26g0xa_ooblayout_free,
+};
+
+static int xt26g0xa_ecc_get_status(struct spinand_device *spinand,
+  u8 status)
+{
+   status = status & XT26G0XA_STATUS_ECC_MASK;
+
+   switch (status) {
+   case XT26G0XA_STATUS_ECC_NO_DETECTED:
+   return 0;
+   case XT26G0XA_STATUS_ECC_8_CORRECTED:
+   return 8;
+   case XT26G0XA_STATUS_ECC_UNCOR_ERROR:
+   return -EBADMSG;
+   default:
+   break;
+   }
+
+   /* At this point values greater than (2 << 4) are invalid  */
+   if (status > XT26G0XA_STATUS_ECC_UNCOR_ERROR)
+   return -EINVAL;
+
+   /* (1 << 2) through (7 << 2) are 1-7 corrected errors */
+   return status >> 2;
+}
+
+static int xt26xxxd_ooblayout_ecc(struct mtd_info *mtd, int section,
+ struct mtd_oob_region *region)
+{
+   if (section)
+   return -ERANGE;
+
+   region->offset = mtd->oobsize / 2;
+   region->length = mtd->oobsize / 2;
+
+   return 0;
+}
+
+static int xt26xxxd_ooblayout_free(struct mtd_info *mtd, int section,
+  struct mtd_oob_region *region)
+{
+   if