[RFC PATCH 06/34] mtd: spi-nor: Rework the ->quad_enable() selection logic

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



The goal is to move the quad_enable manufacturer specific init in the
<manuf>_post_sfdp_fixups() hooks.

First thing we do is add a spi_nor_quad_enable() wrapper that only
calls nor->quad_enable() when needed (when Quad opcodes are selected).
This way we can populate nor->quad_enable() without risking a switch
to Quad mode when we don't expect it.

Second thing we do is add an explicit no_quad_enable() implementation
so that params->quad_enable() is no longer NULL when
BFPT_DWORD15_QER_NONE is detected, and we can easily override any
manufacturer specific function when SFDP parsing succeeds.

And the last thing we do is move the default nor->quad_enable init in
spi_nor_scan() and the manufacturer specific init in
<manuf>_post_sfdp_fixups().

Signed-off-by: Boris Brezillon <boris.brezillon@xxxxxxxxxxx>
---
 drivers/mtd/spi-nor/spi-nor.c | 60 ++++++++++++++++-------------------
 1 file changed, 28 insertions(+), 32 deletions(-)

diff --git a/drivers/mtd/spi-nor/spi-nor.c b/drivers/mtd/spi-nor/spi-nor.c
index 1f15b93adc11..049b67b8f986 100644
--- a/drivers/mtd/spi-nor/spi-nor.c
+++ b/drivers/mtd/spi-nor/spi-nor.c
@@ -1385,6 +1385,11 @@ static int write_sr_cr(struct spi_nor *nor, u8 *sr_cr)
 	return 0;
 }
 
+static int no_quad_enable(struct spi_nor *nor)
+{
+	return 0;
+}
+
 /**
  * macronix_quad_enable() - set QE bit in Status Register.
  * @nor:	pointer to a 'struct spi_nor'
@@ -2836,7 +2841,7 @@ static int spi_nor_parse_bfpt(struct spi_nor *nor,
 	/* Quad Enable Requirements. */
 	switch (bfpt.dwords[BFPT_DWORD(15)] & BFPT_DWORD15_QER_MASK) {
 	case BFPT_DWORD15_QER_NONE:
-		params->quad_enable = NULL;
+		params->quad_enable = no_quad_enable;
 		break;
 
 	case BFPT_DWORD15_QER_SR2_BIT1_BUGGY:
@@ -3312,25 +3317,6 @@ static int spi_nor_init_params(struct spi_nor *nor,
 			       SPINOR_OP_SE);
 	spi_nor_init_uniform_erase_map(map, erase_mask, params->size);
 
-	/* Select the procedure to set the Quad Enable bit. */
-	if (params->hwcaps.mask & (SNOR_HWCAPS_READ_QUAD |
-				   SNOR_HWCAPS_PP_QUAD)) {
-		switch (JEDEC_MFR(info)) {
-		case SNOR_MFR_MACRONIX:
-			params->quad_enable = macronix_quad_enable;
-			break;
-
-		case SNOR_MFR_ST:
-		case SNOR_MFR_MICRON:
-			break;
-
-		default:
-			/* Kept only for backward compatibility purpose. */
-			params->quad_enable = spansion_quad_enable;
-			break;
-		}
-	}
-
 	if ((info->flags & (SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ)) &&
 	    !(info->flags & SPI_NOR_SKIP_SFDP)) {
 		struct spi_nor_flash_parameter sfdp_params;
@@ -3510,7 +3496,6 @@ static int spi_nor_setup(struct spi_nor *nor,
 			 const struct spi_nor_hwcaps *hwcaps)
 {
 	u32 ignored_mask, shared_mask;
-	bool enable_quad_io;
 	int err;
 
 	/*
@@ -3556,16 +3541,24 @@ static int spi_nor_setup(struct spi_nor *nor,
 	}
 
 	/* Enable Quad I/O if needed. */
-	enable_quad_io = (spi_nor_get_protocol_width(nor->read_proto) == 4 ||
-			  spi_nor_get_protocol_width(nor->write_proto) == 4);
-	if (enable_quad_io && params->quad_enable)
+	if (params->quad_enable)
 		nor->quad_enable = params->quad_enable;
-	else
-		nor->quad_enable = NULL;
 
 	return 0;
 }
 
+static int spi_nor_quad_enable(struct spi_nor *nor)
+{
+	if (spi_nor_get_protocol_width(nor->read_proto) != 4 &&
+	    spi_nor_get_protocol_width(nor->write_proto) != 4)
+		return 0;
+
+	if (!nor->quad_enable)
+		return 0;
+
+	return nor->quad_enable(nor);
+}
+
 static int spi_nor_init(struct spi_nor *nor)
 {
 	int err;
@@ -3583,12 +3576,10 @@ static int spi_nor_init(struct spi_nor *nor)
 		spi_nor_wait_till_ready(nor);
 	}
 
-	if (nor->quad_enable) {
-		err = nor->quad_enable(nor);
-		if (err) {
-			dev_err(nor->dev, "quad mode not supported\n");
-			return err;
-		}
+	err = spi_nor_quad_enable(nor);
+	if (err) {
+		dev_err(nor->dev, "quad mode not supported\n");
+		return err;
 	}
 
 	if (nor->addr_width == 4 && !(nor->flags & SNOR_F_4B_OPCODES)) {
@@ -3673,11 +3664,13 @@ static void st_micron_post_sfdp_fixups(struct spi_nor *nor)
 	/* All ST/Micron NORs support the unlock/lock operations. */
 	nor->flags |= SNOR_F_HAS_LOCK;
 	nor->set_4byte = st_micron_set_4byte;
+	nor->quad_enable = no_quad_enable;
 }
 
 static void macronix_post_sfdp_fixups(struct spi_nor *nor)
 {
 	nor->set_4byte = macronix_set_4byte;
+	nor->quad_enable = macronix_quad_enable;
 }
 
 static void winbond_post_sfdp_fixups(struct spi_nor *nor)
@@ -3877,6 +3870,9 @@ int spi_nor_scan(struct spi_nor *nor, const char *name,
 	if (info->flags & SPI_NOR_HAS_LOCK)
 		nor->flags |= SNOR_F_HAS_LOCK;
 
+	/* Kept only for backward compatibility purpose. */
+	nor->quad_enable = spansion_quad_enable;
+
 	/*
 	 * Post SFDP fixups. Has to be called before spi_nor_setup() because
 	 * some fixups might modify params that are then used by
-- 
2.17.1


______________________________________________________
Linux MTD discussion mailing list
http://lists.infradead.org/mailman/listinfo/linux-mtd/



[Index of Archives]     [LARTC]     [Bugtraq]     [Yosemite Forum]     [Photo]

  Powered by Linux