[PATCH v2] mtd: spi-nor: Describe locking support for MX25L51245G
Marek Vasut
marex at nabladev.com
Fri Oct 23 17:16:17 PDT 2026
The MX25L51245G part has similar 4-BP locking mechanism as MX25L12805D,
however, the TB bit on this part is OTP. Introduce support for Top-only
locking in case the TB bit is not set, and disable locking in case the
TB bit is fused i.e. set to Bottom mode.
Signed-off-by: Marek Vasut <marex at nabladev.com>
---
Cc: Cheng Ming Lin <chengminglin at mxic.com.tw>
Cc: Michael Walle <mwalle at kernel.org>
Cc: Miquel Raynal <miquel.raynal at bootlin.com>
Cc: Pratyush Yadav <pratyush at kernel.org>
Cc: Richard Weinberger <richard at nod.at>
Cc: Takahiro Kuwano <takahiro.kuwano at infineon.com>
Cc: Vignesh Raghavendra <vigneshr at ti.com>
Cc: linux-kernel at vger.kernel.org
Cc: linux-mtd at lists.infradead.org
---
V2: Introduce .late_init callback which enables locking only in case
the TB bit is not set
---
drivers/mtd/spi-nor/macronix.c | 53 +++++++++++++++++++++++++++++++++-
1 file changed, 52 insertions(+), 1 deletion(-)
diff --git a/drivers/mtd/spi-nor/macronix.c b/drivers/mtd/spi-nor/macronix.c
index b3fdb4b2fa1ca..11e71e254a54a 100644
--- a/drivers/mtd/spi-nor/macronix.c
+++ b/drivers/mtd/spi-nor/macronix.c
@@ -15,6 +15,9 @@
#define MXIC_NOR_REG_DOPI_EN 0x2 /* Enable Octal DTR */
#define MXIC_NOR_REG_SPI_EN 0x0 /* Enable SPI */
+#define MX25L51245G_OP_RDCR 0x15
+#define MX25L51245G_CR_TB BIT(3)
+
/* Convert dummy cycles to bit pattern */
#define MXIC_NOR_REG_DC(p) \
((20 - (p)) >> 1)
@@ -25,6 +28,49 @@
SPI_MEM_OP_NO_DUMMY, \
SPI_MEM_OP_DATA_OUT(ndata, buf, 0))
+static int mx25l51245_read_cr(struct spi_nor *nor, u8 *cr)
+{
+ int ret;
+
+ if (nor->spimem) {
+ struct spi_mem_op op = SPI_MEM_OP(SPI_MEM_OP_CMD(MX25L51245G_OP_RDCR, 0),
+ SPI_MEM_OP_NO_ADDR, SPI_MEM_OP_NO_DUMMY,
+ SPI_MEM_OP_DATA_IN(1, cr, 0));
+
+ spi_nor_spimem_setup_op(nor, &op, nor->reg_proto);
+
+ ret = spi_mem_exec_op(nor->spimem, &op);
+ } else {
+ ret = spi_nor_controller_ops_read_reg(nor, MX25L51245G_OP_RDCR, cr, 1);
+ }
+
+ if (ret)
+ dev_dbg(nor->dev, "error %d reading CR\n", ret);
+
+ return ret;
+}
+
+static int mx25l51245_late_init_fixups(struct spi_nor *nor)
+{
+ int ret;
+
+ ret = mx25l51245_read_cr(nor, nor->bouncebuf);
+ if (ret)
+ return ret;
+
+ /*
+ * MX25L51245G supports locking, but the CR register TB bit is OTP.
+ * Enable locking only in case the TB bit is not programmed, or set
+ * to 0.
+ */
+ if (nor->bouncebuf[0] & MX25L51245G_CR_TB)
+ dev_dbg(nor->dev, "CR TB is set, bottom protection not supported\n");
+ else
+ nor->params->flags |= SNOR_F_HAS_LOCK | SNOR_F_HAS_4BIT_BP;
+
+ return 0;
+}
+
static int
mx25l25635_post_bfpt_fixups(struct spi_nor *nor,
const struct sfdp_parameter_header *bfpt_header,
@@ -108,6 +154,11 @@ static const struct spi_nor_fixups mx25l25635_fixups = {
.post_sfdp = macronix_qpp4b_post_sfdp_fixups,
};
+static const struct spi_nor_fixups mx25l51245_fixups = {
+ .late_init = mx25l51245_late_init_fixups,
+ .post_sfdp = macronix_qpp4b_post_sfdp_fixups,
+};
+
static const struct spi_nor_fixups macronix_qpp4b_fixups = {
.post_sfdp = macronix_qpp4b_post_sfdp_fixups,
};
@@ -353,7 +404,7 @@ static const struct spi_nor_fixup macronix_fixups[] = {
{ .fixups = ¯onix_nor_fixups },
{ .id = SNOR_ID(0xc2, 0x20, 0x18), .fixups = &mx25l12805d_4pp3b_fixups },
{ .id = SNOR_ID(0xc2, 0x20, 0x19), .fixups = &mx25l25635_fixups },
- { .id = SNOR_ID(0xc2, 0x20, 0x1a), .fixups = ¯onix_qpp4b_fixups,
+ { .id = SNOR_ID(0xc2, 0x20, 0x1a), .fixups = &mx25l51245_fixups,
.fixup_flags = SPI_NOR_4B_OPCODES },
{ .id = SNOR_ID(0xc2, 0x20, 0x1b), .fixups = ¯onix_qpp4b_fixups },
{ .id = SNOR_ID(0xc2, 0x20, 0x1c), .fixups = ¯onix_qpp4b_fixups },
--
2.53.0
More information about the linux-mtd
mailing list