spi-qpic-snand: sync patch from upstream

Updating the spi-qpic-snand driver with the latest patches sent
upstream and remove custom patches.
These patches add error handling fixes, use of right read location in
read ops, removal of unused variable, ability to read user config and
nand chip requirements, and support for 8bits ECC strength.

Tested on: Gl.iNet GL-B3000 & Linksys MR5500, MX2000, MX5500, SPNMX56

Signed-off-by: George Moussalem <george.moussalem@outlook.com>
Signed-off-by: Robert Marko <robimarko@gmail.com>
This commit is contained in:
George Moussalem 2025-05-06 10:02:27 +04:00
parent 54e0bf3b16
commit 6c60a311fb
10 changed files with 779 additions and 78 deletions

View File

@ -0,0 +1,36 @@
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;
}

View File

@ -0,0 +1,35 @@
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;
}

View File

@ -0,0 +1,30 @@
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;

View File

@ -0,0 +1,174 @@
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)

View File

@ -0,0 +1,70 @@
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

View File

@ -0,0 +1,388 @@
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;

View File

@ -0,0 +1,46 @@
From 2e1ab53e8fcf708db51f560f7846802d406ee57d Mon Sep 17 00:00:00 2001
From: George Moussalem <george.moussalem@outlook.com>
Date: Thu, 15 May 2025 22:47:43 +0200
Subject: [PATCH] spi: spi-qpic-snand: default to 4-bit ECC
There are NAND IC-s that define 1-bit ECC as the minimal strength,
however that is unsupported by QPIC-SNAND as it only supports 4 or 8 bit
ECC.
Since most of these chips also support 4-bit ECC just fine, instead of
erroring out if 1-bit ECC is requested lets instead default to 4-bit ECC.
Fixes: 01b72ce61e8f ("qualcommax: ipq50xx: remove ECC user config from board files")
Signed-off-by: George Moussalem <george.moussalem@outlook.com>
Signed-off-by: Robert Marko <robimarko@gmail.com>
---
drivers/spi/spi-qpic-snand.c | 18 ++++++++++++++++++
1 file changed, 18 insertions(+)
--- a/drivers/spi/spi-qpic-snand.c
+++ b/drivers/spi/spi-qpic-snand.c
@@ -296,6 +296,24 @@ static int qcom_spi_ecc_init_ctx_pipelin
ecc_cfg->spare_bytes = 2;
break;
+ case 1:
+ case 2:
+ /*
+ * Many chips have set a minimum ECC strength requirement
+ * lower than 4-bits but also support higher strength, so
+ * check if ecc_cfg was set by chip reqs and try 4-bits.
+ */
+ if (reqs->strength) {
+ dev_warn(snandc->dev,
+ "ECC strength requirement of %u-bit(s) is unsupported, trying 4-bits\n",
+ reqs->strength);
+ ecc_cfg->ecc_mode = ECC_MODE_4BIT;
+ ecc_cfg->ecc_bytes_hw = 7;
+ ecc_cfg->spare_bytes = 4;
+ break;
+ } else
+ fallthrough;
+
default:
dev_err(snandc->dev,
"only 4 or 8 bits ECC strength is supported\n");

View File

@ -1,53 +0,0 @@
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;

View File

@ -1,25 +0,0 @@
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;