diff mbox series

[v2,2/2] spi: nor: update page program settings for is25wp256 using post bfpt fixup

Message ID 1589885187-31247-3-git-send-email-sagar.kadam@sifive.com
State New
Delegated to: Ambarus Tudor
Headers show
Series enable spi flash and update is25wp256d page write capabilities | expand

Commit Message

Sagar Shrikant Kadam May 19, 2020, 10:46 a.m. UTC
Make a generic post_bfpt fixup handler which uses part specific fixup's
based on device id, as done here for is25lp256 and is25wp256 devices.

During SFDP parsing it is seen that the IS25WP256d device is missing 4BAIT
(4-Byte address instruction table), due to which it's page program
capacity doesn't get correctly populated and the device gets configured
with 4-byte Address Serial Input Page Program i.e. SNOR_PROTO_1_1_1
even though it can work with SNOR_PROTO_1_1_4.

Here using the post bfpt fixup hooks we update the page program
settings to 4-byte QUAD Input Page program operations.

The patch is tested on HiFive Unleashed A00 board and it benefits
few seconds of average write time for entire flash write.

QUAD Input Page Program operations:
> time mtd_debug write /dev/mtd0 0 33554432 rd32M
Copied 33554432 bytes from rd32M to address 0x00000000 in flash
real    0m 35.23s
user    0m 0.00s
sys     0m 23.97s

Serial Input Page Program operations:
> time mtd_debug write /dev/mtd0 0 33554432 rd32M
Copied 33554432 bytes from rd32M to address 0x00000000 in flash
real    0m 39.25s
user    0m 0.00s
sys     0m 27.93s

Signed-off-by: Sagar Shrikant Kadam <sagar.kadam@sifive.com>
---
 drivers/mtd/spi-nor/issi.c | 72 ++++++++++++++++++++++++++++++++++++++--------
 1 file changed, 60 insertions(+), 12 deletions(-)
diff mbox series

Patch

diff --git a/drivers/mtd/spi-nor/issi.c b/drivers/mtd/spi-nor/issi.c
index ffcb60e..efa0fe7 100644
--- a/drivers/mtd/spi-nor/issi.c
+++ b/drivers/mtd/spi-nor/issi.c
@@ -8,26 +8,74 @@ 
 
 #include "core.h"
 
-static int
-is25lp256_post_bfpt_fixups(struct spi_nor *nor,
-			   const struct sfdp_parameter_header *bfpt_header,
-			   const struct sfdp_bfpt *bfpt,
-			   struct spi_nor_flash_parameter *params)
+static int issi_fix_addr_width(struct spi_nor *nor,
+			       const struct sfdp_bfpt *bfpt)
 {
 	/*
-	 * IS25LP256 supports 4B opcodes, but the BFPT advertises a
+	 * If device supports 4B opcodes, but the BFPT advertises a
 	 * BFPT_DWORD1_ADDRESS_BYTES_3_ONLY address width.
 	 * Overwrite the address width advertised by the BFPT.
 	 */
-	if ((bfpt->dwords[BFPT_DWORD(1)] & BFPT_DWORD1_ADDRESS_BYTES_MASK) ==
-		BFPT_DWORD1_ADDRESS_BYTES_3_ONLY)
+	if ((bfpt->dwords[BFPT_DWORD(1)] & BFPT_DWORD1_ADDRESS_BYTES_MASK)
+		== BFPT_DWORD1_ADDRESS_BYTES_3_ONLY)
 		nor->addr_width = 4;
 
 	return 0;
 }
 
-static struct spi_nor_fixups is25lp256_fixups = {
-	.post_bfpt = is25lp256_post_bfpt_fixups,
+static int issi_update_proto(struct spi_nor *nor,
+			     struct spi_nor_flash_parameter *params)
+{
+	/*
+	 * For a device whose 4-Byte address instruction table doesn't
+	 * get populated and the device get's configured with 4-byte
+	 * Address Serial Input Page Program i.e. SNOR_PROTO_1_1_1 even
+	 * though it supports SNOR_PROTO_1_1_4, so priorotize QUAD write
+	 * over SINGLE write if device id table holds SPI_NOR_QUAD_READ.
+	 */
+	if (nor->info->flags & SPI_NOR_QUAD_READ) {
+		params->hwcaps.mask |= SNOR_HWCAPS_PP_1_1_4;
+		spi_nor_set_pp_settings
+			(&params->page_programs[SNOR_CMD_PP_1_1_4],
+			 SPINOR_OP_PP_1_1_4,
+			 SNOR_PROTO_1_1_4);
+	}
+
+	return 0;
+}
+
+static int
+issi_post_bfpt_fixups(struct spi_nor *nor,
+		      const struct sfdp_parameter_header *bfpt_header,
+		      const struct sfdp_bfpt *bfpt,
+		      struct spi_nor_flash_parameter *params)
+{
+	long deviceid;
+
+	deviceid = (nor->info->id[1] << 8 | nor->info->id[2]);
+
+	/* As this is for same MFR i.e ISSI, just check the device ID's */
+	switch (deviceid) {
+	case 0x6019:
+		/* is25lp256 */
+		issi_fix_addr_width(nor, bfpt);
+		break;
+
+	case 0x7019:
+		/* is25wp256 */
+		issi_fix_addr_width(nor, bfpt);
+		issi_update_proto(nor, params);
+		break;
+
+	default:
+		break;
+	}
+
+	return 0;
+}
+
+static struct spi_nor_fixups is25_fixups = {
+	.post_bfpt = issi_post_bfpt_fixups,
 };
 
 static const struct flash_info issi_parts[] = {
@@ -48,7 +96,7 @@  static const struct flash_info issi_parts[] = {
 	{ "is25lp256",  INFO(0x9d6019, 0, 64 * 1024, 512,
 			     SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ |
 			     SPI_NOR_4B_OPCODES)
-		.fixups = &is25lp256_fixups },
+		.fixups = &is25_fixups },
 	{ "is25wp032",  INFO(0x9d7016, 0, 64 * 1024,  64,
 			     SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) },
 	{ "is25wp064",  INFO(0x9d7017, 0, 64 * 1024, 128,
@@ -58,7 +106,7 @@  static const struct flash_info issi_parts[] = {
 	{ "is25wp256", INFO(0x9d7019, 0, 64 * 1024, 512,
 			    SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ |
 			    SPI_NOR_4B_OPCODES)
-		.fixups = &is25lp256_fixups },
+		.fixups = &is25_fixups },
 
 	/* PMC */
 	{ "pm25lv512",   INFO(0,        0, 32 * 1024,    2, SECT_4K_PMC) },