lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <20241126185834.1130949-2-va@nvidia.com>
Date: Tue, 26 Nov 2024 18:58:32 +0000
From: Vishwaroop A <va@...dia.com>
To: <tudor.ambarus@...aro.org>, <pratyush@...nel.org>, <mwalle@...nel.org>,
	<cmiquel.raynal@...tlin.com>, <thierry.reding@...il.com>, <richard@....at>,
	<vigneshr@...com>, <linux-mtd@...ts.infradead.org>,
	<linux-kernel@...r.kernel.org>, <jonathanh@...dia.com>,
	<kyarlagadda@...dia.com>, <smangipudi@...dia.com>
CC: Vishwaroop A <va@...dia.com>
Subject: [PATCH 1/3] mtd: spi-nor: Add post-get-map-id fixup for S25FS512S/S1

The SFDP Address Map for S25FS512S / S25FS512S1 devices incorrectly
reports that the map ID is 0 when it should be 1. This issue can
cause problems when trying to erase sectors on the flash device.

Add a post-get-map-id fixup for S25FS512S / S1 flash devices. The fixup
reads the values of the CR3V and CR1V registers and determines the
map ID based on those values. The fixup also checks for invalid
combinations of CR3V and CR1V values.This fixup is necessary to
workaround an issue with the SFDP Address Map for S25FS512S flash.

Change-Id: Ide18bb4ee076cd36c57b0b52b5d49b63c3caf322
Signed-off-by: Vishwaroop A <va@...dia.com>
---
 drivers/mtd/spi-nor/core.c     | 25 +++++++++++++++++++++
 drivers/mtd/spi-nor/core.h     |  4 ++++
 drivers/mtd/spi-nor/sfdp.c     |  7 ++++++
 drivers/mtd/spi-nor/spansion.c | 41 ++++++++++++++++++++++++++++++++++
 4 files changed, 77 insertions(+)

diff --git a/drivers/mtd/spi-nor/core.c b/drivers/mtd/spi-nor/core.c
index 66949d9f0cc5..a76202c6d252 100644
--- a/drivers/mtd/spi-nor/core.c
+++ b/drivers/mtd/spi-nor/core.c
@@ -2408,6 +2408,31 @@ int spi_nor_post_bfpt_fixups(struct spi_nor *nor,
 	return 0;
 }
 
+/**
+ * spi_nor_post_get_map_id_fixups - Apply post-processing fixups for map ID
+ * @nor: Pointer to the spi_nor structure
+ * @smpt: Pointer to the sector map parameter table
+ * @smpt_len: Length of the sector map parameter table
+ * @map_id: Pointer to store the updated map ID
+ *
+ * Return: 0 on success (including when no fixup is applied),
+ *         positive value if a new map_id is set,
+ *         negative value on error
+ */
+int spi_nor_post_get_map_id_fixups(struct spi_nor *nor, const u32 *smpt,
+				   u8 smpt_len, u8 *map_id)
+{
+	int ret;
+
+	if (nor->info->fixups && nor->info->fixups->post_get_map_id) {
+		ret = nor->info->fixups->post_get_map_id(nor, smpt, smpt_len);
+		if (ret < 0)
+			return ret;
+		*map_id = ret;
+	}
+	return 0;
+}
+
 static int spi_nor_select_read(struct spi_nor *nor,
 			       u32 shared_hwcaps)
 {
diff --git a/drivers/mtd/spi-nor/core.h b/drivers/mtd/spi-nor/core.h
index 5c33740ed7f5..37a9f43e1bf9 100644
--- a/drivers/mtd/spi-nor/core.h
+++ b/drivers/mtd/spi-nor/core.h
@@ -428,6 +428,7 @@ struct spi_nor_fixups {
 			 const struct sfdp_bfpt *bfpt);
 	int (*post_sfdp)(struct spi_nor *nor);
 	int (*late_init)(struct spi_nor *nor);
+	int (*post_get_map_id)(struct spi_nor *nor, const u32 *smpt, u8 smpt_len);
 };
 
 /**
@@ -661,6 +662,9 @@ int spi_nor_post_bfpt_fixups(struct spi_nor *nor,
 			     const struct sfdp_parameter_header *bfpt_header,
 			     const struct sfdp_bfpt *bfpt);
 
+int spi_nor_post_get_map_id_fixups(struct spi_nor *nor, const u32 *smpt,
+				   u8 smpt_len, u8 *map_id);
+
 void spi_nor_init_default_locking_ops(struct spi_nor *nor);
 void spi_nor_try_unlock_all(struct spi_nor *nor);
 void spi_nor_set_mtd_locking_ops(struct spi_nor *nor);
diff --git a/drivers/mtd/spi-nor/sfdp.c b/drivers/mtd/spi-nor/sfdp.c
index 21727f9a4ac6..87af29d2c28b 100644
--- a/drivers/mtd/spi-nor/sfdp.c
+++ b/drivers/mtd/spi-nor/sfdp.c
@@ -769,6 +769,13 @@ static const u32 *spi_nor_get_map_in_use(struct spi_nor *nor, const u32 *smpt,
 		map_id = map_id << 1 | !!(*buf & read_data_mask);
 	}
 
+	err = spi_nor_post_get_map_id_fixups(nor, smpt, smpt_len, &map_id);
+
+	if (err < 0) {
+		dev_err(nor->dev, "Error in post_get_map_id fixup: %d\n", err);
+		return ERR_PTR(err);
+	}
+
 	/*
 	 * If command descriptors are provided, they always precede map
 	 * descriptors in the table. There is no need to start the iteration
diff --git a/drivers/mtd/spi-nor/spansion.c b/drivers/mtd/spi-nor/spansion.c
index 5a88a6096ca8..2e1dd023a1aa 100644
--- a/drivers/mtd/spi-nor/spansion.c
+++ b/drivers/mtd/spi-nor/spansion.c
@@ -25,6 +25,7 @@
 #define SPINOR_REG_CYPRESS_STR1V					\
 	(SPINOR_REG_CYPRESS_VREG + SPINOR_REG_CYPRESS_STR1)
 #define SPINOR_REG_CYPRESS_CFR1			0x2
+#define SPINOR_REG_CYPRESS_CFR1V		0x00800002
 #define SPINOR_REG_CYPRESS_CFR1_QUAD_EN		BIT(1)	/* Quad Enable */
 #define SPINOR_REG_CYPRESS_CFR2			0x3
 #define SPINOR_REG_CYPRESS_CFR2V					\
@@ -33,6 +34,7 @@
 #define SPINOR_REG_CYPRESS_CFR2_MEMLAT_11_24	0xb
 #define SPINOR_REG_CYPRESS_CFR2_ADRBYT		BIT(7)
 #define SPINOR_REG_CYPRESS_CFR3			0x4
+#define SPINOR_REG_CYPRESS_CFR3V		0x00800004
 #define SPINOR_REG_CYPRESS_CFR3_PGSZ		BIT(4) /* Page size. */
 #define SPINOR_REG_CYPRESS_CFR5			0x6
 #define SPINOR_REG_CYPRESS_CFR5_BIT6		BIT(6)
@@ -754,8 +756,47 @@ s25fs_s_nor_post_bfpt_fixups(struct spi_nor *nor,
 	return 0;
 }
 
+static int s25fs_s_nor_post_get_map_id(struct spi_nor *nor, const u32 *smpt, u8 smpt_len)
+{
+	struct spi_mem_op op =
+		SPI_MEM_OP(SPI_MEM_OP_CMD(SPINOR_OP_RD_ANY_REG, 1),
+			   SPI_MEM_OP_ADDR(3, 0, 1),
+			   SPI_MEM_OP_NO_DUMMY,
+			   SPI_MEM_OP_DATA_IN(1, nor->bouncebuf, 1));
+
+	u8 reg_cr3v_val, reg_cr1v_val;
+	int ret;
+
+	/* Read CR3V value from Configuration Register 3 Volatile */
+	op.addr.val = SPINOR_REG_CYPRESS_CFR3V;
+	ret = spi_mem_exec_op(nor->spimem, &op);
+	if (ret)
+		return ret;
+	reg_cr3v_val = nor->bouncebuf[0];
+
+	/* Read CR1V value from Configuration Register 1 Volatile */
+	op.addr.val = SPINOR_REG_CYPRESS_CFR1V;
+	ret = spi_mem_exec_op(nor->spimem, &op);
+	if (ret)
+		return ret;
+	reg_cr1v_val = nor->bouncebuf[0];
+
+	/* Determine the map ID based on CR3V[3] and CR1V[2] values */
+	if (!(reg_cr3v_val & BIT(3)) && !(reg_cr1v_val & BIT(2)))
+		return 1; /* CR3V[3] = 0, CR1V[2] = 0, map id = 1 */
+
+	if (!(reg_cr3v_val & BIT(3)) && (reg_cr1v_val & BIT(2)))
+		return 3; /* CR3V[3] = 0, CR1V[2] = 1, map id = 3 */
+
+	if ((reg_cr3v_val & BIT(3)) && !(reg_cr1v_val & BIT(2)))
+		return 5; /* CR3V[3] = 1, CR1V[2] = 0, map id = 5 */
+
+	return 0;
+}
+
 static const struct spi_nor_fixups s25fs_s_nor_fixups = {
 	.post_bfpt = s25fs_s_nor_post_bfpt_fixups,
+	.post_get_map_id = s25fs_s_nor_post_get_map_id,
 };
 
 static const struct flash_info spansion_nor_parts[] = {
-- 
2.17.1


Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ