--- /dev/null
+From: Gabor Juhos <j4g8y7@gmail.com>
+Date: Wed, 23 Apr 2025 21:31:57 +0200
+Subject: [PATCH] spi: spi-qpic-snand: propagate errors from
+ qcom_spi_block_erase()
+
+The qcom_spi_block_erase() function returns with error in case of
+failure. Change the qcom_spi_send_cmdaddr() function to propagate
+these errors to the callers instead of returning with success.
+
+Fixes: 7304d1909080 ("spi: spi-qpic: add driver for QCOM SPI NAND flash Interface")
+Signed-off-by: Gabor Juhos <j4g8y7@gmail.com>
+Reviewed-by: Abel Vesa <abel.vesa@linaro.org>
+Reviewed-by: Md Sadre Alam <quic_mdalam@quicinc.com>
+---
+ drivers/spi/spi-qpic-snand.c | 3 +--
+ 1 file changed, 1 insertion(+), 2 deletions(-)
+
+
+---
+base-commit: 9c32cda43eb78f78c73aee4aa344b777714e259b
+change-id: 20250422-qpic-snand-propagate-error-9c95811ab811
+
+Best regards,
+
+--- a/drivers/spi/spi-qpic-snand.c
++++ b/drivers/spi/spi-qpic-snand.c
+@@ -1307,8 +1307,7 @@ static int qcom_spi_send_cmdaddr(struct
+ snandc->qspi->addr1 = cpu_to_le32(s_op.addr1_reg << 16);
+ snandc->qspi->addr2 = cpu_to_le32(s_op.addr2_reg);
+ snandc->qspi->cmd = cpu_to_le32(cmd);
+- qcom_spi_block_erase(snandc);
+- return 0;
++ return qcom_spi_block_erase(snandc);
+ default:
+ break;
+ }
--- /dev/null
+From: Gabor Juhos <j4g8y7@gmail.com>
+Date: Mon, 28 Apr 2025 09:30:55 +0200
+Subject: [PATCH] spi: spi-qpic-snand: fix NAND_READ_LOCATION_2 register
+ handling
+
+The precomputed value for the NAND_READ_LOCATION_2 register should be
+stored in 'snandc->regs->read_location2'.
+
+Fix the qcom_spi_set_read_loc_first() function accordingly.
+
+Fixes: 7304d1909080 ("spi: spi-qpic: add driver for QCOM SPI NAND flash Interface")
+Signed-off-by: Gabor Juhos <j4g8y7@gmail.com>
+Reviewed-by: Md Sadre Alam <quic_mdalam@quicinc.com>
+---
+ drivers/spi/spi-qpic-snand.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+
+---
+base-commit: 15cfe55ec58ace931a73e19e5367598734ceb074
+change-id: 20250428-qpic-snand-readloc2-fix-bccd07cf26d3
+
+Best regards,
+
+--- a/drivers/spi/spi-qpic-snand.c
++++ b/drivers/spi/spi-qpic-snand.c
+@@ -142,7 +142,7 @@ static void qcom_spi_set_read_loc_first(
+ else if (reg == NAND_READ_LOCATION_1)
+ snandc->regs->read_location1 = locreg_val;
+ else if (reg == NAND_READ_LOCATION_2)
+- snandc->regs->read_location1 = locreg_val;
++ snandc->regs->read_location2 = locreg_val;
+ else if (reg == NAND_READ_LOCATION_3)
+ snandc->regs->read_location3 = locreg_val;
+ }
--- /dev/null
+From: Gabor Juhos <j4g8y7@gmail.com>
+Date: Thu, 24 Apr 2025 20:10:59 +0200
+Subject: [PATCH] spi: spi-qpic-snand: remove unused 'wlen' member of
+ 'struct qpic_spi_nand'
+
+The 'wlen' member of the qpic_spi_nand structure is never used in the
+code so remove that.
+
+Signed-off-by: Gabor Juhos <j4g8y7@gmail.com>
+---
+ drivers/spi/spi-qpic-snand.c | 1 -
+ 1 file changed, 1 deletion(-)
+
+
+---
+base-commit: 9c32cda43eb78f78c73aee4aa344b777714e259b
+change-id: 20250424-qpic-snand-remove-wlen-c0cef3801a7f
+
+Best regards,
+
+--- a/drivers/spi/spi-qpic-snand.c
++++ b/drivers/spi/spi-qpic-snand.c
+@@ -116,7 +116,6 @@ struct qpic_spi_nand {
+ struct nand_ecc_engine ecc_eng;
+ u8 *data_buf;
+ u8 *oob_buf;
+- u32 wlen;
+ __le32 addr1;
+ __le32 addr2;
+ __le32 cmd;
--- /dev/null
+From: Gabor Juhos <j4g8y7@gmail.com>
+Date: Wed, 23 Apr 2025 21:31:57 +0200
+Subject: [PATCH] spi: spi-qpic-snand: propagate errors from
+ qcom_spi_block_erase()
+
+The qcom_spi_block_erase() function returns with error in case of
+failure. Change the qcom_spi_send_cmdaddr() function to propagate
+these errors to the callers instead of returning with success.
+
+Fixes: 7304d1909080 ("spi: spi-qpic: add driver for QCOM SPI NAND flash Interface")
+Signed-off-by: Gabor Juhos <j4g8y7@gmail.com>
+Reviewed-by: Abel Vesa <abel.vesa@linaro.org>
+Reviewed-by: Md Sadre Alam <quic_mdalam@quicinc.com>
+---
+ drivers/spi/spi-qpic-snand.c | 3 +--
+ 1 file changed, 1 insertion(+), 2 deletions(-)
+
+
+---
+base-commit: 9c32cda43eb78f78c73aee4aa344b777714e259b
+change-id: 20250422-qpic-snand-propagate-error-9c95811ab811
+
+Best regards,
+
+--- a/drivers/spi/spi-qpic-snand.c
++++ b/drivers/spi/spi-qpic-snand.c
+@@ -1307,8 +1307,7 @@ static int qcom_spi_send_cmdaddr(struct
+ snandc->qspi->addr1 = cpu_to_le32(s_op.addr1_reg << 16);
+ snandc->qspi->addr2 = cpu_to_le32(s_op.addr2_reg);
+ snandc->qspi->cmd = cpu_to_le32(cmd);
+- qcom_spi_block_erase(snandc);
+- return 0;
++ return qcom_spi_block_erase(snandc);
+ default:
+ break;
+ }
--- /dev/null
+From: Gabor Juhos <j4g8y7@gmail.com>
+Date: Mon, 28 Apr 2025 09:30:55 +0200
+Subject: [PATCH] spi: spi-qpic-snand: fix NAND_READ_LOCATION_2 register
+ handling
+
+The precomputed value for the NAND_READ_LOCATION_2 register should be
+stored in 'snandc->regs->read_location2'.
+
+Fix the qcom_spi_set_read_loc_first() function accordingly.
+
+Fixes: 7304d1909080 ("spi: spi-qpic: add driver for QCOM SPI NAND flash Interface")
+Signed-off-by: Gabor Juhos <j4g8y7@gmail.com>
+Reviewed-by: Md Sadre Alam <quic_mdalam@quicinc.com>
+---
+ drivers/spi/spi-qpic-snand.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+
+---
+base-commit: 15cfe55ec58ace931a73e19e5367598734ceb074
+change-id: 20250428-qpic-snand-readloc2-fix-bccd07cf26d3
+
+Best regards,
+
+--- a/drivers/spi/spi-qpic-snand.c
++++ b/drivers/spi/spi-qpic-snand.c
+@@ -142,7 +142,7 @@ static void qcom_spi_set_read_loc_first(
+ else if (reg == NAND_READ_LOCATION_1)
+ snandc->regs->read_location1 = locreg_val;
+ else if (reg == NAND_READ_LOCATION_2)
+- snandc->regs->read_location1 = locreg_val;
++ snandc->regs->read_location2 = locreg_val;
+ else if (reg == NAND_READ_LOCATION_3)
+ snandc->regs->read_location3 = locreg_val;
+ }
--- /dev/null
+From: Gabor Juhos <j4g8y7@gmail.com>
+Date: Thu, 24 Apr 2025 20:10:59 +0200
+Subject: [PATCH] spi: spi-qpic-snand: remove unused 'wlen' member of
+ 'struct qpic_spi_nand'
+
+The 'wlen' member of the qpic_spi_nand structure is never used in the
+code so remove that.
+
+Signed-off-by: Gabor Juhos <j4g8y7@gmail.com>
+---
+ drivers/spi/spi-qpic-snand.c | 1 -
+ 1 file changed, 1 deletion(-)
+
+
+---
+base-commit: 9c32cda43eb78f78c73aee4aa344b777714e259b
+change-id: 20250424-qpic-snand-remove-wlen-c0cef3801a7f
+
+Best regards,
+
+--- a/drivers/spi/spi-qpic-snand.c
++++ b/drivers/spi/spi-qpic-snand.c
+@@ -116,7 +116,6 @@ struct qpic_spi_nand {
+ struct nand_ecc_engine ecc_eng;
+ u8 *data_buf;
+ u8 *oob_buf;
+- u32 wlen;
+ __le32 addr1;
+ __le32 addr2;
+ __le32 cmd;
--- /dev/null
+From: Gabor Juhos <j4g8y7@gmail.com>
+Date: Thu, 01 May 2025 18:19:16 +0200
+Subject: [PATCH next] spi: spi-qpic-snand: validate user/chip specific ECC
+ properties
+
+The driver only supports 512 bytes ECC step size and 4 bit ECC strength
+at the moment, however it does not reject unsupported step/strength
+configurations. Due to this, whenever the driver is used with a flash
+chip which needs stronger ECC protection, the following warning is shown
+in the kernel log:
+
+ [ 0.574648] spi-nand spi0.0: GigaDevice SPI NAND was found.
+ [ 0.635748] spi-nand spi0.0: 256 MiB, block size: 128 KiB, page size: 2048, OOB size: 128
+ [ 0.649079] nand: WARNING: (null): the ECC used on your system is too weak compared to the one required by the NAND chip
+
+Although the message indicates that something is wrong, but it often gets
+unnoticed, which can cause serious problems. For example when the user
+writes something into the flash chip despite the warning, the written data
+may won't be readable by the bootloader or by the boot ROM. In the worst
+case, when the attached SPI NAND chip is the boot device, the board may not
+be able to boot anymore.
+
+Also, it is not even possible to create a backup of the flash, because
+reading its content results in bogus data. For example, dumping the first
+page of the flash gives this:
+
+ # hexdump -C -n 2048 /dev/mtd0
+ 00000000 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f |................|
+ *
+ 00000040 0f 0f 0f 0f 0f 0f 0f 0d 0f 0f 0f 0f 0f 0f 0f 0f |................|
+ 00000050 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f |................|
+ *
+ 000001c0 0f 0f 0f 0f ff 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f |................|
+ 000001d0 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f |................|
+ *
+ 00000200 0f 0f 0f 0f f5 5b ff ff 0f 0f 0f 0f 0f 0f 0f 0f |.....[..........|
+ 00000210 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f |................|
+ *
+ 000002f0 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 1f 0f 0f |................|
+ 00000300 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f |................|
+ *
+ 000003c0 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f ff 0f 0f 0f |................|
+ 000003d0 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f |................|
+ *
+ 00000400 0f 0f 0f 0f 0f 0f 0f 0f e9 74 c9 06 f5 5b ff ff |.........t...[..|
+ 00000410 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f |................|
+ *
+ 000005d0 0f 0f 0f 0f ff 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f |................|
+ 000005e0 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f |................|
+ *
+ 00000600 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f c6 be 0f c3 |................|
+ 00000610 e9 74 c9 06 f5 5b ff ff 0f 0f 0f 0f 0f 0f 0f 0f |.t...[..........|
+ 00000620 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f |................|
+ *
+ 00000770 0f 0f 0f 0f 8f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f |................|
+ 00000780 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f |................|
+ *
+ 00000800
+ #
+
+Doing the same by using the downstream kernel results in different output:
+
+ # hexdump -C -n 2048 /dev/mtd0
+ 00000000 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f |................|
+ *
+ 00000800
+ #
+
+This patch adds some sanity checks to the code to prevent using the driver
+with unsupported ECC step/strength configurations. After the change, probing
+of the driver fails in such cases:
+
+ [ 0.655038] spi-nand spi0.0: GigaDevice SPI NAND was found.
+ [ 0.659159] spi-nand spi0.0: 256 MiB, block size: 128 KiB, page size: 2048, OOB size: 128
+ [ 0.669138] qcom_snand 79b0000.spi: only 4 bits ECC strength is supported
+ [ 0.677476] nand: No suitable ECC configuration
+ [ 0.689909] spi-nand spi0.0: probe with driver spi-nand failed with error -95
+
+This helps to avoid the aforementioned hassles until support for 8 bit ECC
+strength gets implemented.
+
+Fixes: 7304d1909080 ("spi: spi-qpic: add driver for QCOM SPI NAND flash Interface")
+Signed-off-by: Gabor Juhos <j4g8y7@gmail.com>
+---
+Marked for next because it depends on commit f48d80503504 ("spi: spi-qpic-snand:
+use kmalloc() for OOB buffer allocation").
+---
+ drivers/spi/spi-qpic-snand.c | 42 +++++++++++++++++++++++++++++++++++++-----
+ 1 file changed, 37 insertions(+), 5 deletions(-)
+
+
+---
+base-commit: a7f035c2c72496cf7ac34bfaa8c289e0d4c45836
+change-id: 20250501-qpic-snand-validate-ecc-383b3e33e238
+
+Best regards,
+
+--- a/drivers/spi/spi-qpic-snand.c
++++ b/drivers/spi/spi-qpic-snand.c
+@@ -249,9 +249,11 @@ static const struct mtd_ooblayout_ops qc
+ static int qcom_spi_ecc_init_ctx_pipelined(struct nand_device *nand)
+ {
+ struct qcom_nand_controller *snandc = nand_to_qcom_snand(nand);
++ struct nand_ecc_props *reqs = &nand->ecc.requirements;
++ struct nand_ecc_props *user = &nand->ecc.user_conf;
+ struct nand_ecc_props *conf = &nand->ecc.ctx.conf;
+ struct mtd_info *mtd = nanddev_to_mtd(nand);
+- int cwperpage, bad_block_byte;
++ int cwperpage, bad_block_byte, ret;
+ struct qpic_ecc *ecc_cfg;
+
+ cwperpage = mtd->writesize / NANDC_STEP_SIZE;
+@@ -260,11 +262,39 @@ static int qcom_spi_ecc_init_ctx_pipelin
+ ecc_cfg = kzalloc(sizeof(*ecc_cfg), GFP_KERNEL);
+ if (!ecc_cfg)
+ return -ENOMEM;
++
++ if (user->step_size && user->strength) {
++ ecc_cfg->step_size = user->step_size;
++ ecc_cfg->strength = user->strength;
++ } else if (reqs->step_size && reqs->strength) {
++ ecc_cfg->step_size = reqs->step_size;
++ ecc_cfg->strength = reqs->strength;
++ } else {
++ /* use defaults */
++ ecc_cfg->step_size = NANDC_STEP_SIZE;
++ ecc_cfg->strength = 4;
++ }
++
++ if (ecc_cfg->step_size != NANDC_STEP_SIZE) {
++ dev_err(snandc->dev,
++ "only %u bytes ECC step size is supported\n",
++ NANDC_STEP_SIZE);
++ ret = -EOPNOTSUPP;
++ goto err_free_ecc_cfg;
++ }
++
++ if (ecc_cfg->strength != 4) {
++ dev_err(snandc->dev,
++ "only 4 bits ECC strength is supported\n");
++ ret = -EOPNOTSUPP;
++ goto err_free_ecc_cfg;
++ }
++
+ snandc->qspi->oob_buf = kmalloc(mtd->writesize + mtd->oobsize,
+ GFP_KERNEL);
+ if (!snandc->qspi->oob_buf) {
+- kfree(ecc_cfg);
+- return -ENOMEM;
++ ret = -ENOMEM;
++ goto err_free_ecc_cfg;
+ }
+
+ memset(snandc->qspi->oob_buf, 0xff, mtd->writesize + mtd->oobsize);
+@@ -279,8 +309,6 @@ static int qcom_spi_ecc_init_ctx_pipelin
+ ecc_cfg->bytes = ecc_cfg->ecc_bytes_hw + ecc_cfg->spare_bytes + ecc_cfg->bbm_size;
+
+ ecc_cfg->steps = 4;
+- ecc_cfg->strength = 4;
+- ecc_cfg->step_size = 512;
+ ecc_cfg->cw_data = 516;
+ ecc_cfg->cw_size = ecc_cfg->cw_data + ecc_cfg->bytes;
+ bad_block_byte = mtd->writesize - ecc_cfg->cw_size * (cwperpage - 1) + 1;
+@@ -338,6 +366,10 @@ static int qcom_spi_ecc_init_ctx_pipelin
+ ecc_cfg->strength, ecc_cfg->step_size);
+
+ return 0;
++
++err_free_ecc_cfg:
++ kfree(ecc_cfg);
++ return ret;
+ }
+
+ static void qcom_spi_ecc_cleanup_ctx_pipelined(struct nand_device *nand)
--- /dev/null
+From: Gabor Juhos <j4g8y7@gmail.com>
+Date: Fri, 02 May 2025 21:31:16 +0200
+Subject: [PATCH next 1/2] mtd: nand: qpic-common: add defines for ECC_MODE
+ values
+
+Add defines for the values of the ECC_MODE field of the NAND_DEV0_ECC_CFG
+register and change both the 'qcom-nandc' and 'spi-qpic-snand' drivers to
+use those instead of magic numbers.
+
+No functional changes. This is in preparation for adding 8 bit ECC strength
+support for the 'spi-qpic-snand' driver.
+
+Signed-off-by: Gabor Juhos <j4g8y7@gmail.com>
+---
+ drivers/mtd/nand/raw/qcom_nandc.c | 6 +++---
+ drivers/spi/spi-qpic-snand.c | 2 +-
+ include/linux/mtd/nand-qpic-common.h | 2 ++
+ 3 files changed, 6 insertions(+), 4 deletions(-)
+
+--- a/drivers/mtd/nand/raw/qcom_nandc.c
++++ b/drivers/mtd/nand/raw/qcom_nandc.c
+@@ -1379,7 +1379,7 @@ static int qcom_nand_attach_chip(struct
+ struct qcom_nand_controller *nandc = get_qcom_nand_controller(chip);
+ int cwperpage, bad_block_byte, ret;
+ bool wide_bus;
+- int ecc_mode = 1;
++ int ecc_mode = ECC_MODE_8BIT;
+
+ /* controller only supports 512 bytes data steps */
+ ecc->size = NANDC_STEP_SIZE;
+@@ -1400,7 +1400,7 @@ static int qcom_nand_attach_chip(struct
+ if (ecc->strength >= 8) {
+ /* 8 bit ECC defaults to BCH ECC on all platforms */
+ host->bch_enabled = true;
+- ecc_mode = 1;
++ ecc_mode = ECC_MODE_8BIT;
+
+ if (wide_bus) {
+ host->ecc_bytes_hw = 14;
+@@ -1420,7 +1420,7 @@ static int qcom_nand_attach_chip(struct
+ if (nandc->props->ecc_modes & ECC_BCH_4BIT) {
+ /* BCH */
+ host->bch_enabled = true;
+- ecc_mode = 0;
++ ecc_mode = ECC_MODE_4BIT;
+
+ if (wide_bus) {
+ host->ecc_bytes_hw = 8;
+--- a/drivers/spi/spi-qpic-snand.c
++++ b/drivers/spi/spi-qpic-snand.c
+@@ -349,7 +349,7 @@ static int qcom_spi_ecc_init_ctx_pipelin
+ FIELD_PREP(ECC_SW_RESET, 0) |
+ FIELD_PREP(ECC_NUM_DATA_BYTES_MASK, ecc_cfg->cw_data) |
+ FIELD_PREP(ECC_FORCE_CLK_OPEN, 1) |
+- FIELD_PREP(ECC_MODE_MASK, 0) |
++ FIELD_PREP(ECC_MODE_MASK, ECC_MODE_4BIT) |
+ FIELD_PREP(ECC_PARITY_SIZE_BYTES_BCH_MASK, ecc_cfg->ecc_bytes_hw);
+
+ ecc_cfg->ecc_buf_cfg = 0x203 << NUM_STEPS;
+--- a/include/linux/mtd/nand-qpic-common.h
++++ b/include/linux/mtd/nand-qpic-common.h
+@@ -101,6 +101,8 @@
+ #define ECC_SW_RESET BIT(1)
+ #define ECC_MODE 4
+ #define ECC_MODE_MASK GENMASK(5, 4)
++#define ECC_MODE_4BIT 0
++#define ECC_MODE_8BIT 1
+ #define ECC_PARITY_SIZE_BYTES_BCH 8
+ #define ECC_PARITY_SIZE_BYTES_BCH_MASK GENMASK(12, 8)
+ #define ECC_NUM_DATA_BYTES 16
--- /dev/null
+From: Gabor Juhos <j4g8y7@gmail.com>
+Date: Fri, 02 May 2025 21:31:17 +0200
+Subject: [PATCH next 2/2] spi: spi-qpic-snand: add support for 8 bits ECC
+ strength
+
+Even though the hardware supports 8 bits ECC strength, but that is not
+handled in the driver yet. This change adds the missing bits in order
+to allow using the driver with chips which require 8 bits ECC strength.
+
+No functional changes intended with regard to the existing 4 bits ECC
+strength support.
+
+Tested on an IPQ9574 platform using a GigaDevice GD5F2GM7REYIG chip.
+
+Signed-off-by: Gabor Juhos <j4g8y7@gmail.com>
+---
+mtdtest results:
+
+ # dmesg | grep nand
+ [ 0.678143] spi-nand spi0.0: GigaDevice SPI NAND was found.
+ [ 0.687393] spi-nand spi0.0: 256 MiB, block size: 128 KiB, page size: 2048, OOB size: 128
+ # cat /proc/mtd
+ dev: size erasesize name
+ mtd0: 10000000 00020000 "spi0.0"
+ # insmod mtd_test
+ # insmod mtd_speedtest dev=0
+ [ 63.128425]
+ [ 63.128452] =================================================
+ [ 63.128979] mtd_speedtest: MTD device: 0
+ [ 63.134622] mtd_speedtest: MTD device size 268435456, eraseblock size 131072, page size 2048, count of eraseblocks 2048, pages per eraseblock 64, OOB size 128
+ [ 63.139561] mtd_test: scanning for bad eraseblocks
+ [ 63.756447] mtd_test: scanned 2048 eraseblocks, 0 are bad
+ [ 71.085514] mtd_speedtest: testing eraseblock write speed
+ [ 202.745977] mtd_speedtest: eraseblock write speed is 1991 KiB/s
+ [ 202.746022] mtd_speedtest: testing eraseblock read speed
+ [ 284.104591] mtd_speedtest: eraseblock read speed is 3222 KiB/s
+ [ 291.405533] mtd_speedtest: testing page write speed
+ [ 422.516341] mtd_speedtest: page write speed is 1999 KiB/s
+ [ 422.516384] mtd_speedtest: testing page read speed
+ [ 504.144630] mtd_speedtest: page read speed is 3211 KiB/s
+ [ 511.476726] mtd_speedtest: testing 2 page write speed
+ [ 643.114443] mtd_speedtest: 2 page write speed is 1991 KiB/s
+ [ 643.114485] mtd_speedtest: testing 2 page read speed
+ [ 724.434752] mtd_speedtest: 2 page read speed is 3223 KiB/s
+ [ 724.434796] mtd_speedtest: Testing erase speed
+ [ 731.792729] mtd_speedtest: erase speed is 35648 KiB/s
+ [ 731.792772] mtd_speedtest: Testing 2x multi-block erase speed
+ [ 739.162513] mtd_speedtest: 2x multi-block erase speed is 35589 KiB/s
+ [ 739.162558] mtd_speedtest: Testing 4x multi-block erase speed
+ [ 746.486241] mtd_speedtest: 4x multi-block erase speed is 35820 KiB/s
+ [ 746.486287] mtd_speedtest: Testing 8x multi-block erase speed
+ [ 753.789683] mtd_speedtest: 8x multi-block erase speed is 35919 KiB/s
+ [ 753.789728] mtd_speedtest: Testing 16x multi-block erase speed
+ [ 761.093075] mtd_speedtest: 16x multi-block erase speed is 35920 KiB/s
+ [ 761.093120] mtd_speedtest: Testing 32x multi-block erase speed
+ [ 768.396145] mtd_speedtest: 32x multi-block erase speed is 35922 KiB/s
+ [ 768.396222] mtd_speedtest: Testing 64x multi-block erase speed
+ [ 775.699819] mtd_speedtest: 64x multi-block erase speed is 35918 KiB/s
+ [ 775.699863] mtd_speedtest: finished
+ [ 775.705259] =================================================
+ # insmod mtd_readtest dev=0
+ [ 919.060671]
+ [ 919.060699] =================================================
+ [ 919.061226] mtd_readtest: MTD device: 0
+ [ 919.066957] mtd_readtest: MTD device size 268435456, eraseblock size 131072, page size 2048, count of eraseblocks 2048, pages per eraseblock 64, OOB size 128
+ [ 919.070556] mtd_test: scanning for bad eraseblocks
+ [ 919.086016] mtd_test: scanned 2048 eraseblocks, 0 are bad
+ [ 919.089465] mtd_readtest: testing page read
+ [ 1090.778227] mtd_readtest: finished
+ [ 1090.778286] =================================================
+ # insmod mtd_pagetest dev=0
+ [ 1216.297313]
+ [ 1216.297341] =================================================
+ [ 1216.297867] mtd_pagetest: MTD device: 0
+ [ 1216.303509] mtd_pagetest: MTD device size 268435456, eraseblock size 131072, page size 2048, count of eraseblocks 2048, pages per eraseblock 64, OOB size 128
+ [ 1216.307213] mtd_test: scanning for bad eraseblocks
+ [ 1216.322680] mtd_test: scanned 2048 eraseblocks, 0 are bad
+ [ 1216.326077] mtd_pagetest: erasing whole device
+ [ 1223.694968] mtd_pagetest: erased 2048 eraseblocks
+ [ 1223.695009] mtd_pagetest: writing whole device
+ [ 1223.763930] mtd_pagetest: written up to eraseblock 0
+ [ 1240.268942] mtd_pagetest: written up to eraseblock 256
+ [ 1256.641498] mtd_pagetest: written up to eraseblock 512
+ [ 1273.139048] mtd_pagetest: written up to eraseblock 768
+ [ 1289.718929] mtd_pagetest: written up to eraseblock 1024
+ [ 1306.244553] mtd_pagetest: written up to eraseblock 1280
+ [ 1322.939723] mtd_pagetest: written up to eraseblock 1536
+ [ 1339.246937] mtd_pagetest: written up to eraseblock 1792
+ [ 1355.613729] mtd_pagetest: written 2048 eraseblocks
+ [ 1355.613770] mtd_pagetest: verifying all eraseblocks
+ [ 1355.854290] mtd_pagetest: verified up to eraseblock 0
+ [ 1416.657733] mtd_pagetest: verified up to eraseblock 256
+ [ 1477.384593] mtd_pagetest: verified up to eraseblock 512
+ [ 1538.008142] mtd_pagetest: verified up to eraseblock 768
+ [ 1599.080797] mtd_pagetest: verified up to eraseblock 1024
+ [ 1660.775431] mtd_pagetest: verified up to eraseblock 1280
+ [ 1722.177149] mtd_pagetest: verified up to eraseblock 1536
+ [ 1783.090166] mtd_pagetest: verified up to eraseblock 1792
+ [ 1844.450757] mtd_pagetest: verified 2048 eraseblocks
+ [ 1844.450798] mtd_pagetest: crosstest
+ [ 1844.455676] mtd_pagetest: reading page at 0x0
+ [ 1844.458603] mtd_pagetest: reading page at 0xffff800
+ [ 1844.463047] mtd_pagetest: reading page at 0x0
+ [ 1844.467790] mtd_pagetest: verifying pages read at 0x0 match
+ [ 1844.471636] mtd_pagetest: crosstest ok
+ [ 1844.477062] mtd_pagetest: erasecrosstest
+ [ 1844.480833] mtd_pagetest: erasing block 0
+ [ 1844.488498] mtd_pagetest: writing 1st page of block 0
+ [ 1844.489821] mtd_pagetest: reading 1st page of block 0
+ [ 1844.494475] mtd_pagetest: verifying 1st page of block 0
+ [ 1844.498942] mtd_pagetest: erasing block 0
+ [ 1844.507505] mtd_pagetest: writing 1st page of block 0
+ [ 1844.509042] mtd_pagetest: erasing block 2047
+ [ 1844.516725] mtd_pagetest: reading 1st page of block 0
+ [ 1844.518087] mtd_pagetest: verifying 1st page of block 0
+ [ 1844.522415] mtd_pagetest: erasecrosstest ok
+ [ 1844.527495] mtd_pagetest: erasetest
+ [ 1844.531613] mtd_pagetest: erasing block 0
+ [ 1844.538671] mtd_pagetest: writing 1st page of block 0
+ [ 1844.540249] mtd_pagetest: erasing block 0
+ [ 1844.547869] mtd_pagetest: reading 1st page of block 0
+ [ 1844.548927] mtd_pagetest: verifying 1st page of block 0 is all 0xff
+ [ 1844.553326] mtd_pagetest: erasetest ok
+ [ 1844.559440] mtd_pagetest: finished with 0 errors
+ [ 1844.563233] =================================================
+ # insmod mtd_subpagetest dev=0
+ [ 1942.429708]
+ [ 1942.429736] =================================================
+ [ 1942.430262] mtd_subpagetest: MTD device: 0
+ [ 1942.435905] mtd_subpagetest: MTD device size 268435456, eraseblock size 131072, page size 2048, subpage size 2048, count of eraseblocks 2048, pages per eraseblock 64, OOB size 128
+ [ 1942.439994] mtd_test: scanning for bad eraseblocks
+ [ 1942.457111] mtd_test: scanned 2048 eraseblocks, 0 are bad
+ [ 1949.824564] mtd_subpagetest: writing whole device
+ [ 1949.826670] mtd_subpagetest: written up to eraseblock 0
+ [ 1950.351816] mtd_subpagetest: written up to eraseblock 256
+ [ 1950.875797] mtd_subpagetest: written up to eraseblock 512
+ [ 1951.399912] mtd_subpagetest: written up to eraseblock 768
+ [ 1951.923618] mtd_subpagetest: written up to eraseblock 1024
+ [ 1952.447361] mtd_subpagetest: written up to eraseblock 1280
+ [ 1952.970834] mtd_subpagetest: written up to eraseblock 1536
+ [ 1953.494635] mtd_subpagetest: written up to eraseblock 1792
+ [ 1954.016265] mtd_subpagetest: written 2048 eraseblocks
+ [ 1954.016294] mtd_subpagetest: verifying all eraseblocks
+ [ 1954.021617] mtd_subpagetest: verified up to eraseblock 0
+ [ 1954.347458] mtd_subpagetest: verified up to eraseblock 256
+ [ 1954.667446] mtd_subpagetest: verified up to eraseblock 512
+ [ 1954.987343] mtd_subpagetest: verified up to eraseblock 768
+ [ 1955.307385] mtd_subpagetest: verified up to eraseblock 1024
+ [ 1955.627462] mtd_subpagetest: verified up to eraseblock 1280
+ [ 1955.947277] mtd_subpagetest: verified up to eraseblock 1536
+ [ 1956.266834] mtd_subpagetest: verified up to eraseblock 1792
+ [ 1956.585581] mtd_subpagetest: verified 2048 eraseblocks
+ [ 1963.889308] mtd_subpagetest: verifying all eraseblocks for 0xff
+ [ 1963.930487] mtd_subpagetest: verified up to eraseblock 0
+ [ 1974.592567] mtd_subpagetest: verified up to eraseblock 256
+ [ 1985.180953] mtd_subpagetest: verified up to eraseblock 512
+ [ 1995.805397] mtd_subpagetest: verified up to eraseblock 768
+ [ 2006.348859] mtd_subpagetest: verified up to eraseblock 1024
+ [ 2016.900530] mtd_subpagetest: verified up to eraseblock 1280
+ [ 2027.447587] mtd_subpagetest: verified up to eraseblock 1536
+ [ 2037.962383] mtd_subpagetest: verified up to eraseblock 1792
+ [ 2048.587863] mtd_subpagetest: verified 2048 eraseblocks
+ [ 2048.587906] mtd_subpagetest: writing whole device
+ [ 2048.648174] mtd_subpagetest: written up to eraseblock 0
+ [ 2062.643145] mtd_subpagetest: written up to eraseblock 256
+ [ 2076.699015] mtd_subpagetest: written up to eraseblock 512
+ [ 2091.004910] mtd_subpagetest: written up to eraseblock 768
+ [ 2105.149879] mtd_subpagetest: written up to eraseblock 1024
+ [ 2119.470691] mtd_subpagetest: written up to eraseblock 1280
+ [ 2133.746861] mtd_subpagetest: written up to eraseblock 1536
+ [ 2147.776477] mtd_subpagetest: written up to eraseblock 1792
+ [ 2161.947734] mtd_subpagetest: written 2048 eraseblocks
+ [ 2161.947776] mtd_subpagetest: verifying all eraseblocks
+ [ 2161.986109] mtd_subpagetest: verified up to eraseblock 0
+ [ 2170.818316] mtd_subpagetest: verified up to eraseblock 256
+ [ 2179.596875] mtd_subpagetest: verified up to eraseblock 512
+ [ 2188.405116] mtd_subpagetest: verified up to eraseblock 768
+ [ 2197.188588] mtd_subpagetest: verified up to eraseblock 1024
+ [ 2206.002204] mtd_subpagetest: verified up to eraseblock 1280
+ [ 2214.784815] mtd_subpagetest: verified up to eraseblock 1536
+ [ 2223.557141] mtd_subpagetest: verified up to eraseblock 1792
+ [ 2232.472832] mtd_subpagetest: verified 2048 eraseblocks
+ [ 2239.818213] mtd_subpagetest: verifying all eraseblocks for 0xff
+ [ 2239.861404] mtd_subpagetest: verified up to eraseblock 0
+ [ 2250.439035] mtd_subpagetest: verified up to eraseblock 256
+ [ 2261.176485] mtd_subpagetest: verified up to eraseblock 512
+ [ 2271.713183] mtd_subpagetest: verified up to eraseblock 768
+ [ 2282.356892] mtd_subpagetest: verified up to eraseblock 1024
+ [ 2292.891424] mtd_subpagetest: verified up to eraseblock 1280
+ [ 2303.543110] mtd_subpagetest: verified up to eraseblock 1536
+ [ 2314.116690] mtd_subpagetest: verified up to eraseblock 1792
+ [ 2324.607804] mtd_subpagetest: verified 2048 eraseblocks
+ [ 2324.607846] mtd_subpagetest: finished with 0 errors
+ [ 2324.611859] =================================================
+ # insmod mtd_oobtest dev=0
+ [ 2336.159109]
+ [ 2336.159138] =================================================
+ [ 2336.159664] mtd_oobtest: MTD device: 0
+ [ 2336.165308] mtd_oobtest: MTD device size 268435456, eraseblock size 131072, page size 2048, count of eraseblocks 2048, pages per eraseblock 64, OOB size 128
+ [ 2336.169043] mtd_test: scanning for bad eraseblocks
+ [ 2336.184354] mtd_test: scanned 2048 eraseblocks, 0 are bad
+ [ 2336.187716] mtd_oobtest: test 1 of 5
+ [ 2343.495966] mtd_oobtest: writing OOBs of whole device
+ [ 2343.496073] mtd_oobtest: written up to eraseblock 0
+ [ 2343.516803] mtd_oobtest: written up to eraseblock 256
+ [ 2343.533527] mtd_oobtest: written up to eraseblock 512
+ [ 2343.549945] mtd_oobtest: written up to eraseblock 768
+ [ 2343.563666] mtd_oobtest: written up to eraseblock 1024
+ [ 2343.575186] mtd_oobtest: written up to eraseblock 1280
+ [ 2343.584310] mtd_oobtest: written up to eraseblock 1536
+ [ 2343.593011] mtd_oobtest: written up to eraseblock 1792
+ [ 2343.600847] mtd_oobtest: written 2048 eraseblocks
+ [ 2343.600861] mtd_oobtest: verifying all eraseblocks
+ [ 2343.604542] mtd_oobtest: verified up to eraseblock 0
+ [ 2343.616606] mtd_oobtest: verified up to eraseblock 256
+ [ 2343.623992] mtd_oobtest: verified up to eraseblock 512
+ [ 2343.631390] mtd_oobtest: verified up to eraseblock 768
+ [ 2343.638788] mtd_oobtest: verified up to eraseblock 1024
+ [ 2343.646184] mtd_oobtest: verified up to eraseblock 1280
+ [ 2343.653570] mtd_oobtest: verified up to eraseblock 1536
+ [ 2343.660970] mtd_oobtest: verified up to eraseblock 1792
+ [ 2343.668356] mtd_oobtest: verified 2048 eraseblocks
+ [ 2343.668369] mtd_oobtest: test 2 of 5
+ [ 2350.985635] mtd_oobtest: writing OOBs of whole device
+ [ 2350.985743] mtd_oobtest: written up to eraseblock 0
+ [ 2351.006445] mtd_oobtest: written up to eraseblock 256
+ [ 2351.023170] mtd_oobtest: written up to eraseblock 512
+ [ 2351.039645] mtd_oobtest: written up to eraseblock 768
+ [ 2351.053395] mtd_oobtest: written up to eraseblock 1024
+ [ 2351.064954] mtd_oobtest: written up to eraseblock 1280
+ [ 2351.074144] mtd_oobtest: written up to eraseblock 1536
+ [ 2351.082848] mtd_oobtest: written up to eraseblock 1792
+ [ 2351.090707] mtd_oobtest: written 2048 eraseblocks
+ [ 2351.090721] mtd_oobtest: verifying all eraseblocks
+ [ 2351.094373] mtd_oobtest: verified up to eraseblock 0
+ [ 2351.099353] mtd_oobtest: verified up to eraseblock 256
+ [ 2351.104460] mtd_oobtest: verified up to eraseblock 512
+ [ 2351.109437] mtd_oobtest: verified up to eraseblock 768
+ [ 2351.114528] mtd_oobtest: verified up to eraseblock 1024
+ [ 2351.119683] mtd_oobtest: verified up to eraseblock 1280
+ [ 2351.124772] mtd_oobtest: verified up to eraseblock 1536
+ [ 2351.129996] mtd_oobtest: verified up to eraseblock 1792
+ [ 2351.135187] mtd_oobtest: verified 2048 eraseblocks
+ [ 2351.140130] mtd_oobtest: test 3 of 5
+ [ 2358.448438] mtd_oobtest: writing OOBs of whole device
+ [ 2358.448546] mtd_oobtest: written up to eraseblock 0
+ [ 2358.469297] mtd_oobtest: written up to eraseblock 256
+ [ 2358.486095] mtd_oobtest: written up to eraseblock 512
+ [ 2358.501993] mtd_oobtest: written up to eraseblock 768
+ [ 2358.515473] mtd_oobtest: written up to eraseblock 1024
+ [ 2358.526708] mtd_oobtest: written up to eraseblock 1280
+ [ 2358.535426] mtd_oobtest: written up to eraseblock 1536
+ [ 2358.544152] mtd_oobtest: written up to eraseblock 1792
+ [ 2358.551732] mtd_oobtest: written 2048 eraseblocks
+ [ 2358.551744] mtd_oobtest: verifying all eraseblocks
+ [ 2358.555424] mtd_oobtest: verified up to eraseblock 0
+ [ 2358.567572] mtd_oobtest: verified up to eraseblock 256
+ [ 2358.575045] mtd_oobtest: verified up to eraseblock 512
+ [ 2358.582537] mtd_oobtest: verified up to eraseblock 768
+ [ 2358.590024] mtd_oobtest: verified up to eraseblock 1024
+ [ 2358.597511] mtd_oobtest: verified up to eraseblock 1280
+ [ 2358.604984] mtd_oobtest: verified up to eraseblock 1536
+ [ 2358.612468] mtd_oobtest: verified up to eraseblock 1792
+ [ 2358.619923] mtd_oobtest: verified 2048 eraseblocks
+ [ 2358.619936] mtd_oobtest: test 4 of 5
+ [ 2365.924669] mtd_oobtest: attempting to start write past end of OOB
+ [ 2365.924711] mtd_oobtest: an error is expected...
+ [ 2365.929795] mtd_oobtest: error occurred as expected
+ [ 2365.934520] mtd_oobtest: attempting to start read past end of OOB
+ [ 2365.939150] mtd_oobtest: an error is expected...
+ [ 2365.945371] mtd_oobtest: error occurred as expected
+ [ 2365.950087] mtd_oobtest: attempting to write past end of device
+ [ 2365.954660] mtd_oobtest: an error is expected...
+ [ 2365.960623] mtd_oobtest: error occurred as expected
+ [ 2365.965422] mtd_oobtest: attempting to read past end of device
+ [ 2365.970064] mtd_oobtest: an error is expected...
+ [ 2365.975925] mtd_oobtest: error occurred as expected
+ [ 2365.984256] mtd_oobtest: attempting to write past end of device
+ [ 2365.985300] mtd_oobtest: an error is expected...
+ [ 2365.991242] mtd_oobtest: error: wrote past end of device
+ [ 2365.996064] mtd_oobtest: attempting to read past end of device
+ [ 2366.001389] mtd_oobtest: an error is expected...
+ [ 2366.007028] mtd_oobtest: error: read past end of device
+ [ 2366.011776] mtd_oobtest: test 5 of 5
+ [ 2373.317991] mtd_oobtest: writing OOBs of whole device
+ [ 2373.318034] mtd_oobtest: written up to eraseblock 0
+ [ 2373.322028] mtd_oobtest: written up to eraseblock 0
+ [ 2373.327465] mtd_oobtest: written up to eraseblock 256
+ [ 2373.331576] mtd_oobtest: written up to eraseblock 256
+ [ 2373.337501] mtd_oobtest: written up to eraseblock 512
+ [ 2373.341820] mtd_oobtest: written up to eraseblock 512
+ [ 2373.347566] mtd_oobtest: written up to eraseblock 768
+ [ 2373.351888] mtd_oobtest: written up to eraseblock 768
+ [ 2373.357634] mtd_oobtest: written up to eraseblock 1024
+ [ 2373.361957] mtd_oobtest: written up to eraseblock 1024
+ [ 2373.367710] mtd_oobtest: written up to eraseblock 1280
+ [ 2373.372113] mtd_oobtest: written up to eraseblock 1280
+ [ 2373.377841] mtd_oobtest: written up to eraseblock 1536
+ [ 2373.382355] mtd_oobtest: written up to eraseblock 1536
+ [ 2373.387962] mtd_oobtest: written up to eraseblock 1792
+ [ 2373.392597] mtd_oobtest: written up to eraseblock 1792
+ [ 2373.398190] mtd_oobtest: written 2047 eraseblocks
+ [ 2373.402838] mtd_oobtest: verifying all eraseblocks
+ [ 2373.407629] mtd_oobtest: verified up to eraseblock 0
+ [ 2373.412483] mtd_oobtest: verified up to eraseblock 256
+ [ 2373.417625] mtd_oobtest: verified up to eraseblock 512
+ [ 2373.422518] mtd_oobtest: verified up to eraseblock 768
+ [ 2373.427650] mtd_oobtest: verified up to eraseblock 1024
+ [ 2373.432760] mtd_oobtest: verified up to eraseblock 1280
+ [ 2373.437912] mtd_oobtest: verified up to eraseblock 1536
+ [ 2373.443091] mtd_oobtest: verified up to eraseblock 1792
+ [ 2373.448337] mtd_oobtest: verified 2047 eraseblocks
+ [ 2373.453358] mtd_oobtest: finished with 2 errors
+ [ 2373.458250] =================================================
+
+Note: the two errors are present even even without this patch when testing
+the driver with a flash chip requiring 4 bits ECC strength.
+
+ # insmod mtd_stresstest dev=0
+ [ 2383.256453]
+ [ 2383.256482] =================================================
+ [ 2383.257008] mtd_stresstest: MTD device: 0
+ [ 2383.262650] mtd_stresstest: MTD device size 268435456, eraseblock size 131072, page size 2048, count of eraseblocks 2048, pages per eraseblock 64, OOB size 128
+ [ 2383.268254] mtd_test: scanning for bad eraseblocks
+ [ 2383.281992] mtd_test: scanned 2048 eraseblocks, 0 are bad
+ [ 2383.285565] mtd_stresstest: doing operations
+ [ 2383.291047] mtd_stresstest: 0 operations done
+ [ 2427.841267] mtd_stresstest: 1024 operations done
+ [ 2471.142229] mtd_stresstest: 2048 operations done
+ [ 2514.405277] mtd_stresstest: 3072 operations done
+ [ 2555.451926] mtd_stresstest: 4096 operations done
+ [ 2598.107133] mtd_stresstest: 5120 operations done
+ [ 2639.936952] mtd_stresstest: 6144 operations done
+ [ 2680.724751] mtd_stresstest: 7168 operations done
+ [ 2720.344163] mtd_stresstest: 8192 operations done
+ [ 2761.645640] mtd_stresstest: 9216 operations done
+ [ 2791.760534] mtd_stresstest: finished, 10000 operations done
+ [ 2791.760817] =================================================
+ #
+---
+ drivers/spi/spi-qpic-snand.c | 21 ++++++++++++++++-----
+ 1 file changed, 16 insertions(+), 5 deletions(-)
+
+--- a/drivers/spi/spi-qpic-snand.c
++++ b/drivers/spi/spi-qpic-snand.c
+@@ -283,9 +283,22 @@ static int qcom_spi_ecc_init_ctx_pipelin
+ goto err_free_ecc_cfg;
+ }
+
+- if (ecc_cfg->strength != 4) {
++ switch (ecc_cfg->strength) {
++ case 4:
++ ecc_cfg->ecc_mode = ECC_MODE_4BIT;
++ ecc_cfg->ecc_bytes_hw = 7;
++ ecc_cfg->spare_bytes = 4;
++ break;
++
++ case 8:
++ ecc_cfg->ecc_mode = ECC_MODE_8BIT;
++ ecc_cfg->ecc_bytes_hw = 13;
++ ecc_cfg->spare_bytes = 2;
++ break;
++
++ default:
+ dev_err(snandc->dev,
+- "only 4 bits ECC strength is supported\n");
++ "only 4 or 8 bits ECC strength is supported\n");
+ ret = -EOPNOTSUPP;
+ goto err_free_ecc_cfg;
+ }
+@@ -302,8 +315,6 @@ static int qcom_spi_ecc_init_ctx_pipelin
+ nand->ecc.ctx.priv = ecc_cfg;
+ snandc->qspi->mtd = mtd;
+
+- ecc_cfg->ecc_bytes_hw = 7;
+- ecc_cfg->spare_bytes = 4;
+ ecc_cfg->bbm_size = 1;
+ ecc_cfg->bch_enabled = true;
+ ecc_cfg->bytes = ecc_cfg->ecc_bytes_hw + ecc_cfg->spare_bytes + ecc_cfg->bbm_size;
+@@ -349,7 +360,7 @@ static int qcom_spi_ecc_init_ctx_pipelin
+ FIELD_PREP(ECC_SW_RESET, 0) |
+ FIELD_PREP(ECC_NUM_DATA_BYTES_MASK, ecc_cfg->cw_data) |
+ FIELD_PREP(ECC_FORCE_CLK_OPEN, 1) |
+- FIELD_PREP(ECC_MODE_MASK, ECC_MODE_4BIT) |
++ FIELD_PREP(ECC_MODE_MASK, ecc_cfg->ecc_mode) |
+ FIELD_PREP(ECC_PARITY_SIZE_BYTES_BCH_MASK, ecc_cfg->ecc_bytes_hw);
+
+ ecc_cfg->ecc_buf_cfg = 0x203 << NUM_STEPS;
--- /dev/null
+From: Gabor Juhos <j4g8y7@gmail.com>
+Date: Thu, 01 May 2025 18:19:16 +0200
+Subject: [PATCH next] spi: spi-qpic-snand: validate user/chip specific ECC
+ properties
+
+The driver only supports 512 bytes ECC step size and 4 bit ECC strength
+at the moment, however it does not reject unsupported step/strength
+configurations. Due to this, whenever the driver is used with a flash
+chip which needs stronger ECC protection, the following warning is shown
+in the kernel log:
+
+ [ 0.574648] spi-nand spi0.0: GigaDevice SPI NAND was found.
+ [ 0.635748] spi-nand spi0.0: 256 MiB, block size: 128 KiB, page size: 2048, OOB size: 128
+ [ 0.649079] nand: WARNING: (null): the ECC used on your system is too weak compared to the one required by the NAND chip
+
+Although the message indicates that something is wrong, but it often gets
+unnoticed, which can cause serious problems. For example when the user
+writes something into the flash chip despite the warning, the written data
+may won't be readable by the bootloader or by the boot ROM. In the worst
+case, when the attached SPI NAND chip is the boot device, the board may not
+be able to boot anymore.
+
+Also, it is not even possible to create a backup of the flash, because
+reading its content results in bogus data. For example, dumping the first
+page of the flash gives this:
+
+ # hexdump -C -n 2048 /dev/mtd0
+ 00000000 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f |................|
+ *
+ 00000040 0f 0f 0f 0f 0f 0f 0f 0d 0f 0f 0f 0f 0f 0f 0f 0f |................|
+ 00000050 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f |................|
+ *
+ 000001c0 0f 0f 0f 0f ff 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f |................|
+ 000001d0 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f |................|
+ *
+ 00000200 0f 0f 0f 0f f5 5b ff ff 0f 0f 0f 0f 0f 0f 0f 0f |.....[..........|
+ 00000210 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f |................|
+ *
+ 000002f0 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 1f 0f 0f |................|
+ 00000300 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f |................|
+ *
+ 000003c0 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f ff 0f 0f 0f |................|
+ 000003d0 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f |................|
+ *
+ 00000400 0f 0f 0f 0f 0f 0f 0f 0f e9 74 c9 06 f5 5b ff ff |.........t...[..|
+ 00000410 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f |................|
+ *
+ 000005d0 0f 0f 0f 0f ff 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f |................|
+ 000005e0 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f |................|
+ *
+ 00000600 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f c6 be 0f c3 |................|
+ 00000610 e9 74 c9 06 f5 5b ff ff 0f 0f 0f 0f 0f 0f 0f 0f |.t...[..........|
+ 00000620 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f |................|
+ *
+ 00000770 0f 0f 0f 0f 8f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f |................|
+ 00000780 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f |................|
+ *
+ 00000800
+ #
+
+Doing the same by using the downstream kernel results in different output:
+
+ # hexdump -C -n 2048 /dev/mtd0
+ 00000000 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f |................|
+ *
+ 00000800
+ #
+
+This patch adds some sanity checks to the code to prevent using the driver
+with unsupported ECC step/strength configurations. After the change, probing
+of the driver fails in such cases:
+
+ [ 0.655038] spi-nand spi0.0: GigaDevice SPI NAND was found.
+ [ 0.659159] spi-nand spi0.0: 256 MiB, block size: 128 KiB, page size: 2048, OOB size: 128
+ [ 0.669138] qcom_snand 79b0000.spi: only 4 bits ECC strength is supported
+ [ 0.677476] nand: No suitable ECC configuration
+ [ 0.689909] spi-nand spi0.0: probe with driver spi-nand failed with error -95
+
+This helps to avoid the aforementioned hassles until support for 8 bit ECC
+strength gets implemented.
+
+Fixes: 7304d1909080 ("spi: spi-qpic: add driver for QCOM SPI NAND flash Interface")
+Signed-off-by: Gabor Juhos <j4g8y7@gmail.com>
+---
+Marked for next because it depends on commit f48d80503504 ("spi: spi-qpic-snand:
+use kmalloc() for OOB buffer allocation").
+---
+ drivers/spi/spi-qpic-snand.c | 42 +++++++++++++++++++++++++++++++++++++-----
+ 1 file changed, 37 insertions(+), 5 deletions(-)
+
+
+---
+base-commit: a7f035c2c72496cf7ac34bfaa8c289e0d4c45836
+change-id: 20250501-qpic-snand-validate-ecc-383b3e33e238
+
+Best regards,
+
+--- a/drivers/spi/spi-qpic-snand.c
++++ b/drivers/spi/spi-qpic-snand.c
+@@ -249,9 +249,11 @@ static const struct mtd_ooblayout_ops qc
+ static int qcom_spi_ecc_init_ctx_pipelined(struct nand_device *nand)
+ {
+ struct qcom_nand_controller *snandc = nand_to_qcom_snand(nand);
++ struct nand_ecc_props *reqs = &nand->ecc.requirements;
++ struct nand_ecc_props *user = &nand->ecc.user_conf;
+ struct nand_ecc_props *conf = &nand->ecc.ctx.conf;
+ struct mtd_info *mtd = nanddev_to_mtd(nand);
+- int cwperpage, bad_block_byte;
++ int cwperpage, bad_block_byte, ret;
+ struct qpic_ecc *ecc_cfg;
+
+ cwperpage = mtd->writesize / NANDC_STEP_SIZE;
+@@ -260,11 +262,39 @@ static int qcom_spi_ecc_init_ctx_pipelin
+ ecc_cfg = kzalloc(sizeof(*ecc_cfg), GFP_KERNEL);
+ if (!ecc_cfg)
+ return -ENOMEM;
++
++ if (user->step_size && user->strength) {
++ ecc_cfg->step_size = user->step_size;
++ ecc_cfg->strength = user->strength;
++ } else if (reqs->step_size && reqs->strength) {
++ ecc_cfg->step_size = reqs->step_size;
++ ecc_cfg->strength = reqs->strength;
++ } else {
++ /* use defaults */
++ ecc_cfg->step_size = NANDC_STEP_SIZE;
++ ecc_cfg->strength = 4;
++ }
++
++ if (ecc_cfg->step_size != NANDC_STEP_SIZE) {
++ dev_err(snandc->dev,
++ "only %u bytes ECC step size is supported\n",
++ NANDC_STEP_SIZE);
++ ret = -EOPNOTSUPP;
++ goto err_free_ecc_cfg;
++ }
++
++ if (ecc_cfg->strength != 4) {
++ dev_err(snandc->dev,
++ "only 4 bits ECC strength is supported\n");
++ ret = -EOPNOTSUPP;
++ goto err_free_ecc_cfg;
++ }
++
+ snandc->qspi->oob_buf = kmalloc(mtd->writesize + mtd->oobsize,
+ GFP_KERNEL);
+ if (!snandc->qspi->oob_buf) {
+- kfree(ecc_cfg);
+- return -ENOMEM;
++ ret = -ENOMEM;
++ goto err_free_ecc_cfg;
+ }
+
+ memset(snandc->qspi->oob_buf, 0xff, mtd->writesize + mtd->oobsize);
+@@ -279,8 +309,6 @@ static int qcom_spi_ecc_init_ctx_pipelin
+ ecc_cfg->bytes = ecc_cfg->ecc_bytes_hw + ecc_cfg->spare_bytes + ecc_cfg->bbm_size;
+
+ ecc_cfg->steps = 4;
+- ecc_cfg->strength = 4;
+- ecc_cfg->step_size = 512;
+ ecc_cfg->cw_data = 516;
+ ecc_cfg->cw_size = ecc_cfg->cw_data + ecc_cfg->bytes;
+ bad_block_byte = mtd->writesize - ecc_cfg->cw_size * (cwperpage - 1) + 1;
+@@ -338,6 +366,10 @@ static int qcom_spi_ecc_init_ctx_pipelin
+ ecc_cfg->strength, ecc_cfg->step_size);
+
+ return 0;
++
++err_free_ecc_cfg:
++ kfree(ecc_cfg);
++ return ret;
+ }
+
+ static void qcom_spi_ecc_cleanup_ctx_pipelined(struct nand_device *nand)
--- /dev/null
+From: Gabor Juhos <j4g8y7@gmail.com>
+Date: Fri, 02 May 2025 21:31:16 +0200
+Subject: [PATCH next 1/2] mtd: nand: qpic-common: add defines for ECC_MODE
+ values
+
+Add defines for the values of the ECC_MODE field of the NAND_DEV0_ECC_CFG
+register and change both the 'qcom-nandc' and 'spi-qpic-snand' drivers to
+use those instead of magic numbers.
+
+No functional changes. This is in preparation for adding 8 bit ECC strength
+support for the 'spi-qpic-snand' driver.
+
+Signed-off-by: Gabor Juhos <j4g8y7@gmail.com>
+---
+ drivers/mtd/nand/raw/qcom_nandc.c | 6 +++---
+ drivers/spi/spi-qpic-snand.c | 2 +-
+ include/linux/mtd/nand-qpic-common.h | 2 ++
+ 3 files changed, 6 insertions(+), 4 deletions(-)
+
+--- a/drivers/mtd/nand/raw/qcom_nandc.c
++++ b/drivers/mtd/nand/raw/qcom_nandc.c
+@@ -1379,7 +1379,7 @@ static int qcom_nand_attach_chip(struct
+ struct qcom_nand_controller *nandc = get_qcom_nand_controller(chip);
+ int cwperpage, bad_block_byte, ret;
+ bool wide_bus;
+- int ecc_mode = 1;
++ int ecc_mode = ECC_MODE_8BIT;
+
+ /* controller only supports 512 bytes data steps */
+ ecc->size = NANDC_STEP_SIZE;
+@@ -1400,7 +1400,7 @@ static int qcom_nand_attach_chip(struct
+ if (ecc->strength >= 8) {
+ /* 8 bit ECC defaults to BCH ECC on all platforms */
+ host->bch_enabled = true;
+- ecc_mode = 1;
++ ecc_mode = ECC_MODE_8BIT;
+
+ if (wide_bus) {
+ host->ecc_bytes_hw = 14;
+@@ -1420,7 +1420,7 @@ static int qcom_nand_attach_chip(struct
+ if (nandc->props->ecc_modes & ECC_BCH_4BIT) {
+ /* BCH */
+ host->bch_enabled = true;
+- ecc_mode = 0;
++ ecc_mode = ECC_MODE_4BIT;
+
+ if (wide_bus) {
+ host->ecc_bytes_hw = 8;
+--- a/drivers/spi/spi-qpic-snand.c
++++ b/drivers/spi/spi-qpic-snand.c
+@@ -349,7 +349,7 @@ static int qcom_spi_ecc_init_ctx_pipelin
+ FIELD_PREP(ECC_SW_RESET, 0) |
+ FIELD_PREP(ECC_NUM_DATA_BYTES_MASK, ecc_cfg->cw_data) |
+ FIELD_PREP(ECC_FORCE_CLK_OPEN, 1) |
+- FIELD_PREP(ECC_MODE_MASK, 0) |
++ FIELD_PREP(ECC_MODE_MASK, ECC_MODE_4BIT) |
+ FIELD_PREP(ECC_PARITY_SIZE_BYTES_BCH_MASK, ecc_cfg->ecc_bytes_hw);
+
+ ecc_cfg->ecc_buf_cfg = 0x203 << NUM_STEPS;
+--- a/include/linux/mtd/nand-qpic-common.h
++++ b/include/linux/mtd/nand-qpic-common.h
+@@ -101,6 +101,8 @@
+ #define ECC_SW_RESET BIT(1)
+ #define ECC_MODE 4
+ #define ECC_MODE_MASK GENMASK(5, 4)
++#define ECC_MODE_4BIT 0
++#define ECC_MODE_8BIT 1
+ #define ECC_PARITY_SIZE_BYTES_BCH 8
+ #define ECC_PARITY_SIZE_BYTES_BCH_MASK GENMASK(12, 8)
+ #define ECC_NUM_DATA_BYTES 16
--- /dev/null
+From: Gabor Juhos <j4g8y7@gmail.com>
+Date: Fri, 02 May 2025 21:31:17 +0200
+Subject: [PATCH next 2/2] spi: spi-qpic-snand: add support for 8 bits ECC
+ strength
+
+Even though the hardware supports 8 bits ECC strength, but that is not
+handled in the driver yet. This change adds the missing bits in order
+to allow using the driver with chips which require 8 bits ECC strength.
+
+No functional changes intended with regard to the existing 4 bits ECC
+strength support.
+
+Tested on an IPQ9574 platform using a GigaDevice GD5F2GM7REYIG chip.
+
+Signed-off-by: Gabor Juhos <j4g8y7@gmail.com>
+---
+mtdtest results:
+
+ # dmesg | grep nand
+ [ 0.678143] spi-nand spi0.0: GigaDevice SPI NAND was found.
+ [ 0.687393] spi-nand spi0.0: 256 MiB, block size: 128 KiB, page size: 2048, OOB size: 128
+ # cat /proc/mtd
+ dev: size erasesize name
+ mtd0: 10000000 00020000 "spi0.0"
+ # insmod mtd_test
+ # insmod mtd_speedtest dev=0
+ [ 63.128425]
+ [ 63.128452] =================================================
+ [ 63.128979] mtd_speedtest: MTD device: 0
+ [ 63.134622] mtd_speedtest: MTD device size 268435456, eraseblock size 131072, page size 2048, count of eraseblocks 2048, pages per eraseblock 64, OOB size 128
+ [ 63.139561] mtd_test: scanning for bad eraseblocks
+ [ 63.756447] mtd_test: scanned 2048 eraseblocks, 0 are bad
+ [ 71.085514] mtd_speedtest: testing eraseblock write speed
+ [ 202.745977] mtd_speedtest: eraseblock write speed is 1991 KiB/s
+ [ 202.746022] mtd_speedtest: testing eraseblock read speed
+ [ 284.104591] mtd_speedtest: eraseblock read speed is 3222 KiB/s
+ [ 291.405533] mtd_speedtest: testing page write speed
+ [ 422.516341] mtd_speedtest: page write speed is 1999 KiB/s
+ [ 422.516384] mtd_speedtest: testing page read speed
+ [ 504.144630] mtd_speedtest: page read speed is 3211 KiB/s
+ [ 511.476726] mtd_speedtest: testing 2 page write speed
+ [ 643.114443] mtd_speedtest: 2 page write speed is 1991 KiB/s
+ [ 643.114485] mtd_speedtest: testing 2 page read speed
+ [ 724.434752] mtd_speedtest: 2 page read speed is 3223 KiB/s
+ [ 724.434796] mtd_speedtest: Testing erase speed
+ [ 731.792729] mtd_speedtest: erase speed is 35648 KiB/s
+ [ 731.792772] mtd_speedtest: Testing 2x multi-block erase speed
+ [ 739.162513] mtd_speedtest: 2x multi-block erase speed is 35589 KiB/s
+ [ 739.162558] mtd_speedtest: Testing 4x multi-block erase speed
+ [ 746.486241] mtd_speedtest: 4x multi-block erase speed is 35820 KiB/s
+ [ 746.486287] mtd_speedtest: Testing 8x multi-block erase speed
+ [ 753.789683] mtd_speedtest: 8x multi-block erase speed is 35919 KiB/s
+ [ 753.789728] mtd_speedtest: Testing 16x multi-block erase speed
+ [ 761.093075] mtd_speedtest: 16x multi-block erase speed is 35920 KiB/s
+ [ 761.093120] mtd_speedtest: Testing 32x multi-block erase speed
+ [ 768.396145] mtd_speedtest: 32x multi-block erase speed is 35922 KiB/s
+ [ 768.396222] mtd_speedtest: Testing 64x multi-block erase speed
+ [ 775.699819] mtd_speedtest: 64x multi-block erase speed is 35918 KiB/s
+ [ 775.699863] mtd_speedtest: finished
+ [ 775.705259] =================================================
+ # insmod mtd_readtest dev=0
+ [ 919.060671]
+ [ 919.060699] =================================================
+ [ 919.061226] mtd_readtest: MTD device: 0
+ [ 919.066957] mtd_readtest: MTD device size 268435456, eraseblock size 131072, page size 2048, count of eraseblocks 2048, pages per eraseblock 64, OOB size 128
+ [ 919.070556] mtd_test: scanning for bad eraseblocks
+ [ 919.086016] mtd_test: scanned 2048 eraseblocks, 0 are bad
+ [ 919.089465] mtd_readtest: testing page read
+ [ 1090.778227] mtd_readtest: finished
+ [ 1090.778286] =================================================
+ # insmod mtd_pagetest dev=0
+ [ 1216.297313]
+ [ 1216.297341] =================================================
+ [ 1216.297867] mtd_pagetest: MTD device: 0
+ [ 1216.303509] mtd_pagetest: MTD device size 268435456, eraseblock size 131072, page size 2048, count of eraseblocks 2048, pages per eraseblock 64, OOB size 128
+ [ 1216.307213] mtd_test: scanning for bad eraseblocks
+ [ 1216.322680] mtd_test: scanned 2048 eraseblocks, 0 are bad
+ [ 1216.326077] mtd_pagetest: erasing whole device
+ [ 1223.694968] mtd_pagetest: erased 2048 eraseblocks
+ [ 1223.695009] mtd_pagetest: writing whole device
+ [ 1223.763930] mtd_pagetest: written up to eraseblock 0
+ [ 1240.268942] mtd_pagetest: written up to eraseblock 256
+ [ 1256.641498] mtd_pagetest: written up to eraseblock 512
+ [ 1273.139048] mtd_pagetest: written up to eraseblock 768
+ [ 1289.718929] mtd_pagetest: written up to eraseblock 1024
+ [ 1306.244553] mtd_pagetest: written up to eraseblock 1280
+ [ 1322.939723] mtd_pagetest: written up to eraseblock 1536
+ [ 1339.246937] mtd_pagetest: written up to eraseblock 1792
+ [ 1355.613729] mtd_pagetest: written 2048 eraseblocks
+ [ 1355.613770] mtd_pagetest: verifying all eraseblocks
+ [ 1355.854290] mtd_pagetest: verified up to eraseblock 0
+ [ 1416.657733] mtd_pagetest: verified up to eraseblock 256
+ [ 1477.384593] mtd_pagetest: verified up to eraseblock 512
+ [ 1538.008142] mtd_pagetest: verified up to eraseblock 768
+ [ 1599.080797] mtd_pagetest: verified up to eraseblock 1024
+ [ 1660.775431] mtd_pagetest: verified up to eraseblock 1280
+ [ 1722.177149] mtd_pagetest: verified up to eraseblock 1536
+ [ 1783.090166] mtd_pagetest: verified up to eraseblock 1792
+ [ 1844.450757] mtd_pagetest: verified 2048 eraseblocks
+ [ 1844.450798] mtd_pagetest: crosstest
+ [ 1844.455676] mtd_pagetest: reading page at 0x0
+ [ 1844.458603] mtd_pagetest: reading page at 0xffff800
+ [ 1844.463047] mtd_pagetest: reading page at 0x0
+ [ 1844.467790] mtd_pagetest: verifying pages read at 0x0 match
+ [ 1844.471636] mtd_pagetest: crosstest ok
+ [ 1844.477062] mtd_pagetest: erasecrosstest
+ [ 1844.480833] mtd_pagetest: erasing block 0
+ [ 1844.488498] mtd_pagetest: writing 1st page of block 0
+ [ 1844.489821] mtd_pagetest: reading 1st page of block 0
+ [ 1844.494475] mtd_pagetest: verifying 1st page of block 0
+ [ 1844.498942] mtd_pagetest: erasing block 0
+ [ 1844.507505] mtd_pagetest: writing 1st page of block 0
+ [ 1844.509042] mtd_pagetest: erasing block 2047
+ [ 1844.516725] mtd_pagetest: reading 1st page of block 0
+ [ 1844.518087] mtd_pagetest: verifying 1st page of block 0
+ [ 1844.522415] mtd_pagetest: erasecrosstest ok
+ [ 1844.527495] mtd_pagetest: erasetest
+ [ 1844.531613] mtd_pagetest: erasing block 0
+ [ 1844.538671] mtd_pagetest: writing 1st page of block 0
+ [ 1844.540249] mtd_pagetest: erasing block 0
+ [ 1844.547869] mtd_pagetest: reading 1st page of block 0
+ [ 1844.548927] mtd_pagetest: verifying 1st page of block 0 is all 0xff
+ [ 1844.553326] mtd_pagetest: erasetest ok
+ [ 1844.559440] mtd_pagetest: finished with 0 errors
+ [ 1844.563233] =================================================
+ # insmod mtd_subpagetest dev=0
+ [ 1942.429708]
+ [ 1942.429736] =================================================
+ [ 1942.430262] mtd_subpagetest: MTD device: 0
+ [ 1942.435905] mtd_subpagetest: MTD device size 268435456, eraseblock size 131072, page size 2048, subpage size 2048, count of eraseblocks 2048, pages per eraseblock 64, OOB size 128
+ [ 1942.439994] mtd_test: scanning for bad eraseblocks
+ [ 1942.457111] mtd_test: scanned 2048 eraseblocks, 0 are bad
+ [ 1949.824564] mtd_subpagetest: writing whole device
+ [ 1949.826670] mtd_subpagetest: written up to eraseblock 0
+ [ 1950.351816] mtd_subpagetest: written up to eraseblock 256
+ [ 1950.875797] mtd_subpagetest: written up to eraseblock 512
+ [ 1951.399912] mtd_subpagetest: written up to eraseblock 768
+ [ 1951.923618] mtd_subpagetest: written up to eraseblock 1024
+ [ 1952.447361] mtd_subpagetest: written up to eraseblock 1280
+ [ 1952.970834] mtd_subpagetest: written up to eraseblock 1536
+ [ 1953.494635] mtd_subpagetest: written up to eraseblock 1792
+ [ 1954.016265] mtd_subpagetest: written 2048 eraseblocks
+ [ 1954.016294] mtd_subpagetest: verifying all eraseblocks
+ [ 1954.021617] mtd_subpagetest: verified up to eraseblock 0
+ [ 1954.347458] mtd_subpagetest: verified up to eraseblock 256
+ [ 1954.667446] mtd_subpagetest: verified up to eraseblock 512
+ [ 1954.987343] mtd_subpagetest: verified up to eraseblock 768
+ [ 1955.307385] mtd_subpagetest: verified up to eraseblock 1024
+ [ 1955.627462] mtd_subpagetest: verified up to eraseblock 1280
+ [ 1955.947277] mtd_subpagetest: verified up to eraseblock 1536
+ [ 1956.266834] mtd_subpagetest: verified up to eraseblock 1792
+ [ 1956.585581] mtd_subpagetest: verified 2048 eraseblocks
+ [ 1963.889308] mtd_subpagetest: verifying all eraseblocks for 0xff
+ [ 1963.930487] mtd_subpagetest: verified up to eraseblock 0
+ [ 1974.592567] mtd_subpagetest: verified up to eraseblock 256
+ [ 1985.180953] mtd_subpagetest: verified up to eraseblock 512
+ [ 1995.805397] mtd_subpagetest: verified up to eraseblock 768
+ [ 2006.348859] mtd_subpagetest: verified up to eraseblock 1024
+ [ 2016.900530] mtd_subpagetest: verified up to eraseblock 1280
+ [ 2027.447587] mtd_subpagetest: verified up to eraseblock 1536
+ [ 2037.962383] mtd_subpagetest: verified up to eraseblock 1792
+ [ 2048.587863] mtd_subpagetest: verified 2048 eraseblocks
+ [ 2048.587906] mtd_subpagetest: writing whole device
+ [ 2048.648174] mtd_subpagetest: written up to eraseblock 0
+ [ 2062.643145] mtd_subpagetest: written up to eraseblock 256
+ [ 2076.699015] mtd_subpagetest: written up to eraseblock 512
+ [ 2091.004910] mtd_subpagetest: written up to eraseblock 768
+ [ 2105.149879] mtd_subpagetest: written up to eraseblock 1024
+ [ 2119.470691] mtd_subpagetest: written up to eraseblock 1280
+ [ 2133.746861] mtd_subpagetest: written up to eraseblock 1536
+ [ 2147.776477] mtd_subpagetest: written up to eraseblock 1792
+ [ 2161.947734] mtd_subpagetest: written 2048 eraseblocks
+ [ 2161.947776] mtd_subpagetest: verifying all eraseblocks
+ [ 2161.986109] mtd_subpagetest: verified up to eraseblock 0
+ [ 2170.818316] mtd_subpagetest: verified up to eraseblock 256
+ [ 2179.596875] mtd_subpagetest: verified up to eraseblock 512
+ [ 2188.405116] mtd_subpagetest: verified up to eraseblock 768
+ [ 2197.188588] mtd_subpagetest: verified up to eraseblock 1024
+ [ 2206.002204] mtd_subpagetest: verified up to eraseblock 1280
+ [ 2214.784815] mtd_subpagetest: verified up to eraseblock 1536
+ [ 2223.557141] mtd_subpagetest: verified up to eraseblock 1792
+ [ 2232.472832] mtd_subpagetest: verified 2048 eraseblocks
+ [ 2239.818213] mtd_subpagetest: verifying all eraseblocks for 0xff
+ [ 2239.861404] mtd_subpagetest: verified up to eraseblock 0
+ [ 2250.439035] mtd_subpagetest: verified up to eraseblock 256
+ [ 2261.176485] mtd_subpagetest: verified up to eraseblock 512
+ [ 2271.713183] mtd_subpagetest: verified up to eraseblock 768
+ [ 2282.356892] mtd_subpagetest: verified up to eraseblock 1024
+ [ 2292.891424] mtd_subpagetest: verified up to eraseblock 1280
+ [ 2303.543110] mtd_subpagetest: verified up to eraseblock 1536
+ [ 2314.116690] mtd_subpagetest: verified up to eraseblock 1792
+ [ 2324.607804] mtd_subpagetest: verified 2048 eraseblocks
+ [ 2324.607846] mtd_subpagetest: finished with 0 errors
+ [ 2324.611859] =================================================
+ # insmod mtd_oobtest dev=0
+ [ 2336.159109]
+ [ 2336.159138] =================================================
+ [ 2336.159664] mtd_oobtest: MTD device: 0
+ [ 2336.165308] mtd_oobtest: MTD device size 268435456, eraseblock size 131072, page size 2048, count of eraseblocks 2048, pages per eraseblock 64, OOB size 128
+ [ 2336.169043] mtd_test: scanning for bad eraseblocks
+ [ 2336.184354] mtd_test: scanned 2048 eraseblocks, 0 are bad
+ [ 2336.187716] mtd_oobtest: test 1 of 5
+ [ 2343.495966] mtd_oobtest: writing OOBs of whole device
+ [ 2343.496073] mtd_oobtest: written up to eraseblock 0
+ [ 2343.516803] mtd_oobtest: written up to eraseblock 256
+ [ 2343.533527] mtd_oobtest: written up to eraseblock 512
+ [ 2343.549945] mtd_oobtest: written up to eraseblock 768
+ [ 2343.563666] mtd_oobtest: written up to eraseblock 1024
+ [ 2343.575186] mtd_oobtest: written up to eraseblock 1280
+ [ 2343.584310] mtd_oobtest: written up to eraseblock 1536
+ [ 2343.593011] mtd_oobtest: written up to eraseblock 1792
+ [ 2343.600847] mtd_oobtest: written 2048 eraseblocks
+ [ 2343.600861] mtd_oobtest: verifying all eraseblocks
+ [ 2343.604542] mtd_oobtest: verified up to eraseblock 0
+ [ 2343.616606] mtd_oobtest: verified up to eraseblock 256
+ [ 2343.623992] mtd_oobtest: verified up to eraseblock 512
+ [ 2343.631390] mtd_oobtest: verified up to eraseblock 768
+ [ 2343.638788] mtd_oobtest: verified up to eraseblock 1024
+ [ 2343.646184] mtd_oobtest: verified up to eraseblock 1280
+ [ 2343.653570] mtd_oobtest: verified up to eraseblock 1536
+ [ 2343.660970] mtd_oobtest: verified up to eraseblock 1792
+ [ 2343.668356] mtd_oobtest: verified 2048 eraseblocks
+ [ 2343.668369] mtd_oobtest: test 2 of 5
+ [ 2350.985635] mtd_oobtest: writing OOBs of whole device
+ [ 2350.985743] mtd_oobtest: written up to eraseblock 0
+ [ 2351.006445] mtd_oobtest: written up to eraseblock 256
+ [ 2351.023170] mtd_oobtest: written up to eraseblock 512
+ [ 2351.039645] mtd_oobtest: written up to eraseblock 768
+ [ 2351.053395] mtd_oobtest: written up to eraseblock 1024
+ [ 2351.064954] mtd_oobtest: written up to eraseblock 1280
+ [ 2351.074144] mtd_oobtest: written up to eraseblock 1536
+ [ 2351.082848] mtd_oobtest: written up to eraseblock 1792
+ [ 2351.090707] mtd_oobtest: written 2048 eraseblocks
+ [ 2351.090721] mtd_oobtest: verifying all eraseblocks
+ [ 2351.094373] mtd_oobtest: verified up to eraseblock 0
+ [ 2351.099353] mtd_oobtest: verified up to eraseblock 256
+ [ 2351.104460] mtd_oobtest: verified up to eraseblock 512
+ [ 2351.109437] mtd_oobtest: verified up to eraseblock 768
+ [ 2351.114528] mtd_oobtest: verified up to eraseblock 1024
+ [ 2351.119683] mtd_oobtest: verified up to eraseblock 1280
+ [ 2351.124772] mtd_oobtest: verified up to eraseblock 1536
+ [ 2351.129996] mtd_oobtest: verified up to eraseblock 1792
+ [ 2351.135187] mtd_oobtest: verified 2048 eraseblocks
+ [ 2351.140130] mtd_oobtest: test 3 of 5
+ [ 2358.448438] mtd_oobtest: writing OOBs of whole device
+ [ 2358.448546] mtd_oobtest: written up to eraseblock 0
+ [ 2358.469297] mtd_oobtest: written up to eraseblock 256
+ [ 2358.486095] mtd_oobtest: written up to eraseblock 512
+ [ 2358.501993] mtd_oobtest: written up to eraseblock 768
+ [ 2358.515473] mtd_oobtest: written up to eraseblock 1024
+ [ 2358.526708] mtd_oobtest: written up to eraseblock 1280
+ [ 2358.535426] mtd_oobtest: written up to eraseblock 1536
+ [ 2358.544152] mtd_oobtest: written up to eraseblock 1792
+ [ 2358.551732] mtd_oobtest: written 2048 eraseblocks
+ [ 2358.551744] mtd_oobtest: verifying all eraseblocks
+ [ 2358.555424] mtd_oobtest: verified up to eraseblock 0
+ [ 2358.567572] mtd_oobtest: verified up to eraseblock 256
+ [ 2358.575045] mtd_oobtest: verified up to eraseblock 512
+ [ 2358.582537] mtd_oobtest: verified up to eraseblock 768
+ [ 2358.590024] mtd_oobtest: verified up to eraseblock 1024
+ [ 2358.597511] mtd_oobtest: verified up to eraseblock 1280
+ [ 2358.604984] mtd_oobtest: verified up to eraseblock 1536
+ [ 2358.612468] mtd_oobtest: verified up to eraseblock 1792
+ [ 2358.619923] mtd_oobtest: verified 2048 eraseblocks
+ [ 2358.619936] mtd_oobtest: test 4 of 5
+ [ 2365.924669] mtd_oobtest: attempting to start write past end of OOB
+ [ 2365.924711] mtd_oobtest: an error is expected...
+ [ 2365.929795] mtd_oobtest: error occurred as expected
+ [ 2365.934520] mtd_oobtest: attempting to start read past end of OOB
+ [ 2365.939150] mtd_oobtest: an error is expected...
+ [ 2365.945371] mtd_oobtest: error occurred as expected
+ [ 2365.950087] mtd_oobtest: attempting to write past end of device
+ [ 2365.954660] mtd_oobtest: an error is expected...
+ [ 2365.960623] mtd_oobtest: error occurred as expected
+ [ 2365.965422] mtd_oobtest: attempting to read past end of device
+ [ 2365.970064] mtd_oobtest: an error is expected...
+ [ 2365.975925] mtd_oobtest: error occurred as expected
+ [ 2365.984256] mtd_oobtest: attempting to write past end of device
+ [ 2365.985300] mtd_oobtest: an error is expected...
+ [ 2365.991242] mtd_oobtest: error: wrote past end of device
+ [ 2365.996064] mtd_oobtest: attempting to read past end of device
+ [ 2366.001389] mtd_oobtest: an error is expected...
+ [ 2366.007028] mtd_oobtest: error: read past end of device
+ [ 2366.011776] mtd_oobtest: test 5 of 5
+ [ 2373.317991] mtd_oobtest: writing OOBs of whole device
+ [ 2373.318034] mtd_oobtest: written up to eraseblock 0
+ [ 2373.322028] mtd_oobtest: written up to eraseblock 0
+ [ 2373.327465] mtd_oobtest: written up to eraseblock 256
+ [ 2373.331576] mtd_oobtest: written up to eraseblock 256
+ [ 2373.337501] mtd_oobtest: written up to eraseblock 512
+ [ 2373.341820] mtd_oobtest: written up to eraseblock 512
+ [ 2373.347566] mtd_oobtest: written up to eraseblock 768
+ [ 2373.351888] mtd_oobtest: written up to eraseblock 768
+ [ 2373.357634] mtd_oobtest: written up to eraseblock 1024
+ [ 2373.361957] mtd_oobtest: written up to eraseblock 1024
+ [ 2373.367710] mtd_oobtest: written up to eraseblock 1280
+ [ 2373.372113] mtd_oobtest: written up to eraseblock 1280
+ [ 2373.377841] mtd_oobtest: written up to eraseblock 1536
+ [ 2373.382355] mtd_oobtest: written up to eraseblock 1536
+ [ 2373.387962] mtd_oobtest: written up to eraseblock 1792
+ [ 2373.392597] mtd_oobtest: written up to eraseblock 1792
+ [ 2373.398190] mtd_oobtest: written 2047 eraseblocks
+ [ 2373.402838] mtd_oobtest: verifying all eraseblocks
+ [ 2373.407629] mtd_oobtest: verified up to eraseblock 0
+ [ 2373.412483] mtd_oobtest: verified up to eraseblock 256
+ [ 2373.417625] mtd_oobtest: verified up to eraseblock 512
+ [ 2373.422518] mtd_oobtest: verified up to eraseblock 768
+ [ 2373.427650] mtd_oobtest: verified up to eraseblock 1024
+ [ 2373.432760] mtd_oobtest: verified up to eraseblock 1280
+ [ 2373.437912] mtd_oobtest: verified up to eraseblock 1536
+ [ 2373.443091] mtd_oobtest: verified up to eraseblock 1792
+ [ 2373.448337] mtd_oobtest: verified 2047 eraseblocks
+ [ 2373.453358] mtd_oobtest: finished with 2 errors
+ [ 2373.458250] =================================================
+
+Note: the two errors are present even even without this patch when testing
+the driver with a flash chip requiring 4 bits ECC strength.
+
+ # insmod mtd_stresstest dev=0
+ [ 2383.256453]
+ [ 2383.256482] =================================================
+ [ 2383.257008] mtd_stresstest: MTD device: 0
+ [ 2383.262650] mtd_stresstest: MTD device size 268435456, eraseblock size 131072, page size 2048, count of eraseblocks 2048, pages per eraseblock 64, OOB size 128
+ [ 2383.268254] mtd_test: scanning for bad eraseblocks
+ [ 2383.281992] mtd_test: scanned 2048 eraseblocks, 0 are bad
+ [ 2383.285565] mtd_stresstest: doing operations
+ [ 2383.291047] mtd_stresstest: 0 operations done
+ [ 2427.841267] mtd_stresstest: 1024 operations done
+ [ 2471.142229] mtd_stresstest: 2048 operations done
+ [ 2514.405277] mtd_stresstest: 3072 operations done
+ [ 2555.451926] mtd_stresstest: 4096 operations done
+ [ 2598.107133] mtd_stresstest: 5120 operations done
+ [ 2639.936952] mtd_stresstest: 6144 operations done
+ [ 2680.724751] mtd_stresstest: 7168 operations done
+ [ 2720.344163] mtd_stresstest: 8192 operations done
+ [ 2761.645640] mtd_stresstest: 9216 operations done
+ [ 2791.760534] mtd_stresstest: finished, 10000 operations done
+ [ 2791.760817] =================================================
+ #
+---
+ drivers/spi/spi-qpic-snand.c | 21 ++++++++++++++++-----
+ 1 file changed, 16 insertions(+), 5 deletions(-)
+
+--- a/drivers/spi/spi-qpic-snand.c
++++ b/drivers/spi/spi-qpic-snand.c
+@@ -283,9 +283,22 @@ static int qcom_spi_ecc_init_ctx_pipelin
+ goto err_free_ecc_cfg;
+ }
+
+- if (ecc_cfg->strength != 4) {
++ switch (ecc_cfg->strength) {
++ case 4:
++ ecc_cfg->ecc_mode = ECC_MODE_4BIT;
++ ecc_cfg->ecc_bytes_hw = 7;
++ ecc_cfg->spare_bytes = 4;
++ break;
++
++ case 8:
++ ecc_cfg->ecc_mode = ECC_MODE_8BIT;
++ ecc_cfg->ecc_bytes_hw = 13;
++ ecc_cfg->spare_bytes = 2;
++ break;
++
++ default:
+ dev_err(snandc->dev,
+- "only 4 bits ECC strength is supported\n");
++ "only 4 or 8 bits ECC strength is supported\n");
+ ret = -EOPNOTSUPP;
+ goto err_free_ecc_cfg;
+ }
+@@ -302,8 +315,6 @@ static int qcom_spi_ecc_init_ctx_pipelin
+ nand->ecc.ctx.priv = ecc_cfg;
+ snandc->qspi->mtd = mtd;
+
+- ecc_cfg->ecc_bytes_hw = 7;
+- ecc_cfg->spare_bytes = 4;
+ ecc_cfg->bbm_size = 1;
+ ecc_cfg->bch_enabled = true;
+ ecc_cfg->bytes = ecc_cfg->ecc_bytes_hw + ecc_cfg->spare_bytes + ecc_cfg->bbm_size;
+@@ -349,7 +360,7 @@ static int qcom_spi_ecc_init_ctx_pipelin
+ FIELD_PREP(ECC_SW_RESET, 0) |
+ FIELD_PREP(ECC_NUM_DATA_BYTES_MASK, ecc_cfg->cw_data) |
+ FIELD_PREP(ECC_FORCE_CLK_OPEN, 1) |
+- FIELD_PREP(ECC_MODE_MASK, ECC_MODE_4BIT) |
++ FIELD_PREP(ECC_MODE_MASK, ecc_cfg->ecc_mode) |
+ FIELD_PREP(ECC_PARITY_SIZE_BYTES_BCH_MASK, ecc_cfg->ecc_bytes_hw);
+
+ ecc_cfg->ecc_buf_cfg = 0x203 << NUM_STEPS;
+++ /dev/null
-From 396886e8644d5b601126b97e0b36c40c5fb5cecf Mon Sep 17 00:00:00 2001
-From: Ziyang Huang <hzyitc@outlook.com>
-Date: Sun, 8 Sep 2024 16:40:11 +0800
-Subject: [PATCH 1/2] spi: spi-qpic-snand: support BCH8
-
-Add BCH8 error-correcting code support for QPIC SPI Nand controller.
-
-Signed-off-by: Ziyang Huang <hzyitc@outlook.com>
-Signed-off-by: George Moussalem <george.moussalem@outlook.com>
----
- drivers/spi/spi-qpic-snand.c | 12 ++++++++----
- 1 file changed, 8 insertions(+), 4 deletions(-)
-
---- a/drivers/spi/spi-qpic-snand.c
-+++ b/drivers/spi/spi-qpic-snand.c
-@@ -253,6 +253,7 @@ static int qcom_spi_ecc_init_ctx_pipelin
- struct nand_ecc_props *conf = &nand->ecc.ctx.conf;
- struct mtd_info *mtd = nanddev_to_mtd(nand);
- int cwperpage, bad_block_byte;
-+ int ecc_mode;
- struct qpic_ecc *ecc_cfg;
-
- cwperpage = mtd->writesize / NANDC_STEP_SIZE;
-@@ -273,14 +274,17 @@ static int qcom_spi_ecc_init_ctx_pipelin
- nand->ecc.ctx.priv = ecc_cfg;
- snandc->qspi->mtd = mtd;
-
-- ecc_cfg->ecc_bytes_hw = 7;
-- ecc_cfg->spare_bytes = 4;
-+ /* BCH8 or BCH4 */
-+ ecc_mode = mtd->oobsize > 64 ? 1 : 0;
-+
-+ ecc_cfg->ecc_bytes_hw = ecc_mode ? 13 : 7;
-+ ecc_cfg->spare_bytes = ecc_mode ? 2 : 4;
- ecc_cfg->bbm_size = 1;
- ecc_cfg->bch_enabled = true;
- ecc_cfg->bytes = ecc_cfg->ecc_bytes_hw + ecc_cfg->spare_bytes + ecc_cfg->bbm_size;
-
- ecc_cfg->steps = 4;
-- ecc_cfg->strength = 4;
-+ ecc_cfg->strength = ecc_mode ? 8 : 4;
- ecc_cfg->step_size = 512;
- ecc_cfg->cw_data = 516;
- ecc_cfg->cw_size = ecc_cfg->cw_data + ecc_cfg->bytes;
-@@ -322,7 +326,7 @@ static int qcom_spi_ecc_init_ctx_pipelin
- FIELD_PREP(ECC_SW_RESET, 0) |
- FIELD_PREP(ECC_NUM_DATA_BYTES_MASK, ecc_cfg->cw_data) |
- FIELD_PREP(ECC_FORCE_CLK_OPEN, 1) |
-- FIELD_PREP(ECC_MODE_MASK, 0) |
-+ FIELD_PREP(ECC_MODE_MASK, ecc_mode) |
- FIELD_PREP(ECC_PARITY_SIZE_BYTES_BCH_MASK, ecc_cfg->ecc_bytes_hw);
-
- ecc_cfg->ecc_buf_cfg = 0x203 << NUM_STEPS;
+++ /dev/null
-From 3d550dc3eb4eaa2fe1d0668ed67e835c91487d61 Mon Sep 17 00:00:00 2001
-From: Ziyang Huang <hzyitc@outlook.com>
-Date: Sun, 8 Sep 2024 16:40:11 +0800
-Subject: [PATCH 2/2] mtd: spinand: qpic only support max 4 bytes ID
-
-The QPIC SPI NAND controller supports a max of 4 bytes of device ID.
-As such, set a maximum of 4 bytes.
-
-Signed-off-by: Ziyang Huang <hzyitc@outlook.com>
-Signed-off-by: George Moussalem <george.moussalem@outlook.com>
----
- drivers/mtd/nand/spi/core.c | 2 +-
- 1 file changed, 1 insertion(+), 1 deletion(-)
-
---- a/drivers/mtd/nand/spi/core.c
-+++ b/drivers/mtd/nand/spi/core.c
-@@ -1087,7 +1087,7 @@ int spinand_match_and_init(struct spinan
- if (rdid_method != info->devid.method)
- continue;
-
-- if (memcmp(id + 1, info->devid.id, info->devid.len))
-+ if (memcmp(id + 1, info->devid.id, min(3, info->devid.len)))
- continue;
-
- nand->memorg = table[i].memorg;
+++ /dev/null
-From 589b7e9600b1e50574ce91e4d6fc903ef81d957f Mon Sep 17 00:00:00 2001
-From: INAGAKI Hiroshi <musashino.open@gmail.com>
-Date: Fri, 14 Feb 2025 18:19:58 +0900
-Subject: [PATCH] spi: spi-qpic-snand: add user_config support for ECC
-
-Make the ECC strength in the qpic-snand driver configurable via device
-tree to use the device-specific ECC strength value.
-
-Signed-off-by: INAGAKI Hiroshi <musashino.open@gmail.com>
----
---- a/drivers/spi/spi-qpic-snand.c
-+++ b/drivers/spi/spi-qpic-snand.c
-@@ -274,8 +274,20 @@ static int qcom_spi_ecc_init_ctx_pipelin
- nand->ecc.ctx.priv = ecc_cfg;
- snandc->qspi->mtd = mtd;
-
-- /* BCH8 or BCH4 */
-- ecc_mode = mtd->oobsize > 64 ? 1 : 0;
-+ /* BCH4 or BCH8 */
-+ switch (nand->ecc.user_conf.strength) {
-+ case 4:
-+ ecc_mode = 0;
-+ break;
-+ case 8:
-+ ecc_mode = 1;
-+ break;
-+ default:
-+ ecc_mode = mtd->oobsize > 64 ? 1 : 0;
-+ dev_warn(snandc->dev,
-+ "invalid ECC strength detected, configured from mtd oobsize\n");
-+ break;
-+ }
-
- ecc_cfg->ecc_bytes_hw = ecc_mode ? 13 : 7;
- ecc_cfg->spare_bytes = ecc_mode ? 2 : 4;