From: Miquel Raynal Date: Tue, 26 May 2026 14:56:35 +0000 (+0200) Subject: mtd: spi-nor: swp: Create a helper that writes SR, CR and checks X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=82877fd772f7884474add88c476108b1dd670ef6;p=thirdparty%2Flinux.git mtd: spi-nor: swp: Create a helper that writes SR, CR and checks There are many helpers already to either read and/or write SR and/or CR, as well as sometimes check the returned values. In order to be able to switch from a 1 byte status register to a 2 bytes status register while keeping the same level of verification, let's introduce a new helper that writes them both (atomically) and then reads them back (separated) to compare the values. In case 2 bytes registers are not supported, we still have the usual fallback available in the helper being exported to the rest of the core. Signed-off-by: Miquel Raynal Signed-off-by: Pratyush Yadav --- diff --git a/drivers/mtd/spi-nor/core.c b/drivers/mtd/spi-nor/core.c index 394c27de02d6..2799c21d0b67 100644 --- a/drivers/mtd/spi-nor/core.c +++ b/drivers/mtd/spi-nor/core.c @@ -976,6 +976,54 @@ int spi_nor_write_16bit_cr_and_check(struct spi_nor *nor, u8 cr) return 0; } +/** + * spi_nor_write_16bit_sr_cr_and_check() - Write the Status Register 1 and the + * Configuration Register in one shot. Ensure that the bytes written in both + * registers match the received value. + * @nor: pointer to a 'struct spi_nor'. + * @regs: two-byte array with values to be written to the status and + * configuration registers. + * + * Return: 0 on success, -errno otherwise. + */ +static int spi_nor_write_16bit_sr_cr_and_check(struct spi_nor *nor, const u8 *regs) +{ + u8 written_regs[2]; + int ret; + + written_regs[0] = regs[0]; + written_regs[1] = regs[1]; + nor->bouncebuf[0] = regs[0]; + nor->bouncebuf[1] = regs[1]; + + ret = spi_nor_write_sr(nor, nor->bouncebuf, 2); + if (ret) + return ret; + + ret = spi_nor_read_sr(nor, &nor->bouncebuf[0]); + if (ret) + return ret; + + if (written_regs[0] != nor->bouncebuf[0]) { + dev_dbg(nor->dev, "SR: Read back test failed\n"); + return -EIO; + } + + if (nor->flags & SNOR_F_NO_READ_CR) + return 0; + + ret = spi_nor_read_cr(nor, &nor->bouncebuf[1]); + if (ret) + return ret; + + if (written_regs[1] != nor->bouncebuf[1]) { + dev_dbg(nor->dev, "CR: read back test failed\n"); + return -EIO; + } + + return 0; +} + /** * spi_nor_write_sr_and_check() - Write the Status Register 1 and ensure that * the byte written match the received value without affecting other bits in the @@ -993,6 +1041,23 @@ int spi_nor_write_sr_and_check(struct spi_nor *nor, u8 sr1) return spi_nor_write_sr1_and_check(nor, sr1); } +/** + * spi_nor_write_sr_cr_and_check() - Write the Status Register 1 and ensure that + * the byte written match the received value. Same for the Control Register if + * available. + * @nor: pointer to a 'struct spi_nor'. + * @regs: byte array to be written to the registers. + * + * Return: 0 on success, -errno otherwise. + */ +int spi_nor_write_sr_cr_and_check(struct spi_nor *nor, const u8 *regs) +{ + if (nor->flags & SNOR_F_HAS_16BIT_SR) + return spi_nor_write_16bit_sr_cr_and_check(nor, regs); + + return spi_nor_write_sr1_and_check(nor, regs[0]); +} + /** * spi_nor_write_sr2() - Write the Status Register 2 using the * SPINOR_OP_WRSR2 (3eh) command. diff --git a/drivers/mtd/spi-nor/core.h b/drivers/mtd/spi-nor/core.h index 65bb4b5e1e2b..0753d0a6f8b8 100644 --- a/drivers/mtd/spi-nor/core.h +++ b/drivers/mtd/spi-nor/core.h @@ -637,6 +637,7 @@ int spi_nor_read_cr(struct spi_nor *nor, u8 *cr); int spi_nor_write_sr(struct spi_nor *nor, const u8 *sr, size_t len); int spi_nor_write_sr_and_check(struct spi_nor *nor, u8 sr1); int spi_nor_write_16bit_cr_and_check(struct spi_nor *nor, u8 cr); +int spi_nor_write_sr_cr_and_check(struct spi_nor *nor, const u8 *regs); ssize_t spi_nor_read_data(struct spi_nor *nor, loff_t from, size_t len, u8 *buf);