diff mbox series

[3/4] mtd: spi-nor: Add Octal 8D-8D-8D mode support for Macronix mx25uw51245g

Message ID 1573808288-19365-4-git-send-email-masonccyang@mxic.com.tw (mailing list archive)
State New, archived
Headers show
Series mtd: spi-nor: Add support for Octal 8D-8D-8D mode | expand

Commit Message

Mason Yang Nov. 15, 2019, 8:58 a.m. UTC
mx25uw51245g is a SPI NOR that supports 1-1-1/8-8-8 mode and the SFDPRD
command but returns an empty SFDP page. This forces us to add a new entry
in the flash_info table and patch spi_nor_fixups hooks to tweak flash
parameters for spi_nor_read/pp_setting() and then to enter
Octal 8D-8D-8D modes.

Signed-off-by: Boris Brezillon <boris.brezillon@bootlin.com>
Signed-off-by: Mason Yang <masonccyang@mxic.com.tw>
---
 drivers/mtd/spi-nor/spi-nor.c | 114 ++++++++++++++++++++++++++++++++++++++++++
 include/linux/mtd/spi-nor.h   |   3 ++
 2 files changed, 117 insertions(+)

Comments

Vignesh Raghavendra Dec. 4, 2019, 1:03 p.m. UTC | #1
On 15/11/19 2:28 pm, Mason Yang wrote:
> mx25uw51245g is a SPI NOR that supports 1-1-1/8-8-8 mode and the SFDPRD
> command but returns an empty SFDP page. This forces us to add a new entry
> in the flash_info table and patch spi_nor_fixups hooks to tweak flash
> parameters for spi_nor_read/pp_setting() and then to enter
> Octal 8D-8D-8D modes.
> 
> Signed-off-by: Boris Brezillon <boris.brezillon@bootlin.com>
> Signed-off-by: Mason Yang <masonccyang@mxic.com.tw>
> ---
>  drivers/mtd/spi-nor/spi-nor.c | 114 ++++++++++++++++++++++++++++++++++++++++++
>  include/linux/mtd/spi-nor.h   |   3 ++
>  2 files changed, 117 insertions(+)
> 
> diff --git a/drivers/mtd/spi-nor/spi-nor.c b/drivers/mtd/spi-nor/spi-nor.c
> index 4cdf52d..9013590 100644
> --- a/drivers/mtd/spi-nor/spi-nor.c
> +++ b/drivers/mtd/spi-nor/spi-nor.c
> @@ -615,6 +615,56 @@ static int write_disable(struct spi_nor *nor)
>  }
>  
>  /*
> + * Read configuration register 2, returning its value in the
> + * location. Return the configuration register 2 value.
> + * Returns negative if error occurred.
> + */
> +static int read_cr2(struct spi_nor *nor, u32 addr)

Please prefix spi_nor_* for all new functions. 
Also, include manf name if its vendor specific.

> +{
> +	int ret;
> +
> +	if (nor->spimem) {
> +		struct spi_mem_op op =
> +			SPI_MEM_OP(SPI_MEM_OP_CMD(SPINOR_OP_RDCR2, 1),
> +				   SPI_MEM_OP_ADDR(4, addr, 1),
> +				   SPI_MEM_OP_DUMMY(4, 1),
> +				   SPI_MEM_OP_DATA_IN(1, nor->bouncebuf, 1));
> +
> +		if (spi_nor_protocol_is_8_8_8(nor->read_proto)) {
> +			op.cmd.buswidth = 8;
> +			op.addr.buswidth = 8;
> +			op.dummy.buswidth = 8;
> +			op.data.buswidth = 8;
> +			op.cmd.nbytes = 2;
> +
> +			if (spi_nor_protocol_is_8D_8D_8D(nor->read_proto)) {
> +				op.dummy.nbytes *= 2;
> +				op.cmd.dtr = true;
> +				op.addr.dtr = true;
> +				op.dummy.dtr = true;
> +				op.data.dtr = true;
> +			}
> +
> +			if (nor->ext_cmd_mode == EXT_CMD_IS_INVERSE)
> +				op.cmd.ext_opcode = ~SPINOR_OP_RDCR2;
> +			else
> +				op.cmd.ext_opcode = SPINOR_OP_RDCR2;
> +		}
> +
> +		ret = spi_mem_exec_op(nor->spimem, &op);
> +	} else {
> +		ret = -ENOTSUPP;
> +	}
> +
> +	if (ret < 0) {
> +		dev_err(nor->dev, "error %d reading CR\n", ret);
> +		return ret;
> +	}
> +
> +	return nor->bouncebuf[0];
> +}
> +
> +/*
>   * Write configuration register 2 one byte
>   * Returns negative if error occurred.
>   */
> @@ -2275,10 +2325,72 @@ static int spi_nor_spansion_clear_sr_bp(struct spi_nor *nor)
>  	return 0;
>  }
>  
> +static void
> +spi_nor_set_read_settings(struct spi_nor_read_command *read,
> +			  u8 num_mode_clocks,
> +			  u8 num_wait_states,
> +			  u8 opcode,
> +			  enum spi_nor_protocol proto);
> +
> +static void
> +spi_nor_set_pp_settings(struct spi_nor_pp_command *pp,
> +			u8 opcode,
> +			enum spi_nor_protocol proto);
> +
> +static void
> +mx25uw51245g_default_init(struct spi_nor *nor)
> +{
> +	struct spi_nor_flash_parameter *params = &nor->params;
> +
> +	if (!(nor->spimem->spi->mode & (SPI_RX_OCTAL | SPI_TX_OCTAL)))
> +		return;
> +
> +	/* Octal 8S-8S-8S mode */
> +	params->hwcaps.mask |= SNOR_HWCAPS_OPI_FULL_STR;
> +	spi_nor_set_read_settings(&params->reads[SNOR_CMD_READ_8_8_8],
> +				  0, 20, SPINOR_OP_READ_8_8_8,
> +				  SNOR_PROTO_8_8_8);
> +
> +	spi_nor_set_pp_settings(&params->page_programs[SNOR_CMD_PP_8_8_8],
> +				SPINOR_OP_PP_8_8_8, SNOR_PROTO_8_8_8);
> +
> +	/* Octal 8D-8D-8D mode */
> +	params->hwcaps.mask |= SNOR_HWCAPS_OPI_FULL_DTR;
> +	spi_nor_set_read_settings(&params->reads[SNOR_CMD_READ_8D_8D_8D],
> +				  0, 20, SPINOR_OP_READ_8D_8D_8D,
> +				  SNOR_PROTO_8_8_8_DTR);
> +
> +	spi_nor_set_pp_settings(&params->page_programs[SNOR_CMD_PP_8D_8D_8D],
> +				SPINOR_OP_PP_8D_8D_8D, SNOR_PROTO_8_8_8_DTR);
> +
> +	nor->ext_cmd_mode = EXT_CMD_IS_INVERSE;
> +}

I don't see anything that is macronix specific here.. Can this be moved to
generic code with information parsed from SFDP table?

> +
> +static void
> +mx25uw51245g_post_sfdp_fixups(struct spi_nor *nor)
> +{
> +	struct spi_nor_flash_parameter *params = &nor->params;
> +	u8 cr2;
> +
> +	cr2 = read_cr2(nor, CR2_REG0) & CR2_REG0_MODE_MASK;
> +
> +	if (params->hwcaps.mask & SNOR_HWCAPS_OPI_FULL_DTR)
> +		cr2 |= CR2_REG0_MODE_OPI_DTR;
> +	else if (params->hwcaps.mask & SNOR_HWCAPS_OPI_FULL_STR)
> +		cr2 |= CR2_REG0_MODE_OPI_STR;
> +
> +	write_cr2(nor, CR2_REG0, cr2);
> +}
> +

I see this as a misuse of sfdp_fixups hook:

 * @post_sfdp: called after SFDP has been parsed (is also called for SPI NORs
 *             that do not support RDSFDP). Typically used to tweak various
 *             parameters that could not be extracted by other means (i.e.
 *             when information provided by the SFDP/flash_info tables are
 *             incomplete or wrong).
 *


This should only tweak options parsed by SFDP and not be used to
configure flash to a different mode. Please add a separate function 
to do so. See https://patchwork.kernel.org/patch/10638085/

Also, I guess JESD216C provides a way to discover command sequence 
to enter OPI mode?

>  static struct spi_nor_fixups mx25l25635_fixups = {
>  	.post_bfpt = mx25l25635_post_bfpt_fixups,
>  };
>  
> +static struct spi_nor_fixups mx25uw51245g_fixups = {
> +	.default_init = mx25uw51245g_default_init,
> +	.post_sfdp = mx25uw51245g_post_sfdp_fixups,
> +};
> +
>  static void gd25q256_default_init(struct spi_nor *nor)
>  {
>  	/*
> @@ -2442,6 +2554,8 @@ static void gd25q256_default_init(struct spi_nor *nor)
>  			 SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ)
>  			 .fixups = &mx25l25635_fixups },
>  	{ "mx25u25635f", INFO(0xc22539, 0, 64 * 1024, 512, SECT_4K | SPI_NOR_4B_OPCODES) },
> +	{ "mx25uw51245g", INFO(0xc2813a, 0, 64 * 1024, 1024, SECT_4K | SPI_NOR_4B_OPCODES)
> +				.fixups = &mx25uw51245g_fixups},
>  	{ "mx25v8035f",  INFO(0xc22314, 0, 64 * 1024,  16,
>  			 SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) },
>  	{ "mx25l25655e", INFO(0xc22619, 0, 64 * 1024, 512, 0) },
> diff --git a/include/linux/mtd/spi-nor.h b/include/linux/mtd/spi-nor.h
> index 2e720ca..3aa54dd 100644
> --- a/include/linux/mtd/spi-nor.h
> +++ b/include/linux/mtd/spi-nor.h
> @@ -114,6 +114,9 @@
>  /* Write CFG Reg 2 - defined in JEDEC JESD216C. */
>  #define SPINOR_OP_WRCR2		0x72	/* Write configuration register 2 */
>  
> +/* Used for Macronix flashes only */
> +#define SPINOR_OP_RDCR2		0x71	/* Read configuration register 2 */
> +
>  /* Used for Macronix and Winbond flashes. */
>  #define SPINOR_OP_EN4B		0xb7	/* Enter 4-byte mode */
>  #define SPINOR_OP_EX4B		0xe9	/* Exit 4-byte mode */
>
Mason Yang Dec. 9, 2019, 6:38 a.m. UTC | #2
Hi Vignesh,

> > 
> >  /*
> > + * Read configuration register 2, returning its value in the
> > + * location. Return the configuration register 2 value.
> > + * Returns negative if error occurred.
> > + */
> > +static int read_cr2(struct spi_nor *nor, u32 addr)
> 
> Please prefix spi_nor_* for all new functions. 
> Also, include manf name if its vendor specific.

okay, will fix it.

> 
> > +{
> > +   int ret;
> > +
> > +   if (nor->spimem) {
> > +      struct spi_mem_op op =
> > +         SPI_MEM_OP(SPI_MEM_OP_CMD(SPINOR_OP_RDCR2, 1),
> > +               SPI_MEM_OP_ADDR(4, addr, 1),
> > +               SPI_MEM_OP_DUMMY(4, 1),
> > +               SPI_MEM_OP_DATA_IN(1, nor->bouncebuf, 1));
> > +
> > +      if (spi_nor_protocol_is_8_8_8(nor->read_proto)) {
> > +         op.cmd.buswidth = 8;
> > +         op.addr.buswidth = 8;
> > +         op.dummy.buswidth = 8;
> > +         op.data.buswidth = 8;
> > +         op.cmd.nbytes = 2;
> > +
> > +         if (spi_nor_protocol_is_8D_8D_8D(nor->read_proto)) {
> > +            op.dummy.nbytes *= 2;
> > +            op.cmd.dtr = true;
> > +            op.addr.dtr = true;
> > +            op.dummy.dtr = true;
> > +            op.data.dtr = true;
> > +         }
> > +
> > +         if (nor->ext_cmd_mode == EXT_CMD_IS_INVERSE)
> > +            op.cmd.ext_opcode = ~SPINOR_OP_RDCR2;
> > +         else
> > +            op.cmd.ext_opcode = SPINOR_OP_RDCR2;
> > +      }
> > +
> > +      ret = spi_mem_exec_op(nor->spimem, &op);
> > +   } else {
> > +      ret = -ENOTSUPP;
> > +   }
> > +
> > +   if (ret < 0) {
> > +      dev_err(nor->dev, "error %d reading CR\n", ret);
> > +      return ret;
> > +   }
> > +
> > +   return nor->bouncebuf[0];
> > +}
> > +
> > +/*
> >   * Write configuration register 2 one byte
> >   * Returns negative if error occurred.
> >   */
> > @@ -2275,10 +2325,72 @@ static int spi_nor_spansion_clear_sr_bp(struct 
spi_nor *nor)
> >     return 0;
> >  }
> > 
> > +static void
> > +spi_nor_set_read_settings(struct spi_nor_read_command *read,
> > +           u8 num_mode_clocks,
> > +           u8 num_wait_states,
> > +           u8 opcode,
> > +           enum spi_nor_protocol proto);
> > +
> > +static void
> > +spi_nor_set_pp_settings(struct spi_nor_pp_command *pp,
> > +         u8 opcode,
> > +         enum spi_nor_protocol proto);
> > +
> > +static void
> > +mx25uw51245g_default_init(struct spi_nor *nor)
> > +{
> > +   struct spi_nor_flash_parameter *params = &nor->params;
> > +
> > +   if (!(nor->spimem->spi->mode & (SPI_RX_OCTAL | SPI_TX_OCTAL)))
> > +      return;
> > +
> > +   /* Octal 8S-8S-8S mode */
> > +   params->hwcaps.mask |= SNOR_HWCAPS_OPI_FULL_STR;
> > +   spi_nor_set_read_settings(&params->reads[SNOR_CMD_READ_8_8_8],
> > +              0, 20, SPINOR_OP_READ_8_8_8,
> > +              SNOR_PROTO_8_8_8);
> > +
> > +   spi_nor_set_pp_settings(&params->page_programs[SNOR_CMD_PP_8_8_8],
> > +            SPINOR_OP_PP_8_8_8, SNOR_PROTO_8_8_8);
> > +
> > +   /* Octal 8D-8D-8D mode */
> > +   params->hwcaps.mask |= SNOR_HWCAPS_OPI_FULL_DTR;
> > +   spi_nor_set_read_settings(&params->reads[SNOR_CMD_READ_8D_8D_8D],
> > +              0, 20, SPINOR_OP_READ_8D_8D_8D,
> > +              SNOR_PROTO_8_8_8_DTR);
> > +
> > + 
spi_nor_set_pp_settings(&params->page_programs[SNOR_CMD_PP_8D_8D_8D],
> > +            SPINOR_OP_PP_8D_8D_8D, SNOR_PROTO_8_8_8_DTR);
> > +
> > +   nor->ext_cmd_mode = EXT_CMD_IS_INVERSE;
> > +}
> 
> I don't see anything that is macronix specific here.. Can this be moved 
to
> generic code with information parsed from SFDP table?

This mx25uw51245g device support SFDP command but returns an empty SFDP 
page.

> 
> > +
> > +static void
> > +mx25uw51245g_post_sfdp_fixups(struct spi_nor *nor)
> > +{
> > +   struct spi_nor_flash_parameter *params = &nor->params;
> > +   u8 cr2;
> > +
> > +   cr2 = read_cr2(nor, CR2_REG0) & CR2_REG0_MODE_MASK;
> > +
> > +   if (params->hwcaps.mask & SNOR_HWCAPS_OPI_FULL_DTR)
> > +      cr2 |= CR2_REG0_MODE_OPI_DTR;
> > +   else if (params->hwcaps.mask & SNOR_HWCAPS_OPI_FULL_STR)
> > +      cr2 |= CR2_REG0_MODE_OPI_STR;
> > +
> > +   write_cr2(nor, CR2_REG0, cr2);
> > +}
> > +
> 
> I see this as a misuse of sfdp_fixups hook:
> 
>  * @post_sfdp: called after SFDP has been parsed (is also called for SPI 
NORs
>  *             that do not support RDSFDP). Typically used to tweak 
various
>  *             parameters that could not be extracted by other means 
(i.e.
>  *             when information provided by the SFDP/flash_info tables 
are
>  *             incomplete or wrong).
>  *
> 
> 
> This should only tweak options parsed by SFDP and not be used to
> configure flash to a different mode. Please add a separate function 
> to do so. See https://patchwork.kernel.org/patch/10638085/
> 

okay.
My idea is that device changed to 8D-8D-8D stateful mode after SFDP 
parsed. 
But if SFDP page table is broken in device and driver will just configure 
the device into 8D-8D-8D mode directly.


thanks for your time & comments.

Mason

CONFIDENTIALITY NOTE:

This e-mail and any attachments may contain confidential information 
and/or personal data, which is protected by applicable laws. Please be 
reminded that duplication, disclosure, distribution, or use of this e-mail 
(and/or its attachments) or any part thereof is prohibited. If you receive 
this e-mail in error, please notify us immediately and delete this mail as 
well as its attachment(s) from your system. In addition, please be 
informed that collection, processing, and/or use of personal data is 
prohibited unless expressly permitted by personal data protection laws. 
Thank you for your attention and cooperation.

Macronix International Co., Ltd.

=====================================================================



============================================================================

CONFIDENTIALITY NOTE:

This e-mail and any attachments may contain confidential information and/or personal data, which is protected by applicable laws. Please be reminded that duplication, disclosure, distribution, or use of this e-mail (and/or its attachments) or any part thereof is prohibited. If you receive this e-mail in error, please notify us immediately and delete this mail as well as its attachment(s) from your system. In addition, please be informed that collection, processing, and/or use of personal data is prohibited unless expressly permitted by personal data protection laws. Thank you for your attention and cooperation.

Macronix International Co., Ltd.

=====================================================================
diff mbox series

Patch

diff --git a/drivers/mtd/spi-nor/spi-nor.c b/drivers/mtd/spi-nor/spi-nor.c
index 4cdf52d..9013590 100644
--- a/drivers/mtd/spi-nor/spi-nor.c
+++ b/drivers/mtd/spi-nor/spi-nor.c
@@ -615,6 +615,56 @@  static int write_disable(struct spi_nor *nor)
 }
 
 /*
+ * Read configuration register 2, returning its value in the
+ * location. Return the configuration register 2 value.
+ * Returns negative if error occurred.
+ */
+static int read_cr2(struct spi_nor *nor, u32 addr)
+{
+	int ret;
+
+	if (nor->spimem) {
+		struct spi_mem_op op =
+			SPI_MEM_OP(SPI_MEM_OP_CMD(SPINOR_OP_RDCR2, 1),
+				   SPI_MEM_OP_ADDR(4, addr, 1),
+				   SPI_MEM_OP_DUMMY(4, 1),
+				   SPI_MEM_OP_DATA_IN(1, nor->bouncebuf, 1));
+
+		if (spi_nor_protocol_is_8_8_8(nor->read_proto)) {
+			op.cmd.buswidth = 8;
+			op.addr.buswidth = 8;
+			op.dummy.buswidth = 8;
+			op.data.buswidth = 8;
+			op.cmd.nbytes = 2;
+
+			if (spi_nor_protocol_is_8D_8D_8D(nor->read_proto)) {
+				op.dummy.nbytes *= 2;
+				op.cmd.dtr = true;
+				op.addr.dtr = true;
+				op.dummy.dtr = true;
+				op.data.dtr = true;
+			}
+
+			if (nor->ext_cmd_mode == EXT_CMD_IS_INVERSE)
+				op.cmd.ext_opcode = ~SPINOR_OP_RDCR2;
+			else
+				op.cmd.ext_opcode = SPINOR_OP_RDCR2;
+		}
+
+		ret = spi_mem_exec_op(nor->spimem, &op);
+	} else {
+		ret = -ENOTSUPP;
+	}
+
+	if (ret < 0) {
+		dev_err(nor->dev, "error %d reading CR\n", ret);
+		return ret;
+	}
+
+	return nor->bouncebuf[0];
+}
+
+/*
  * Write configuration register 2 one byte
  * Returns negative if error occurred.
  */
@@ -2275,10 +2325,72 @@  static int spi_nor_spansion_clear_sr_bp(struct spi_nor *nor)
 	return 0;
 }
 
+static void
+spi_nor_set_read_settings(struct spi_nor_read_command *read,
+			  u8 num_mode_clocks,
+			  u8 num_wait_states,
+			  u8 opcode,
+			  enum spi_nor_protocol proto);
+
+static void
+spi_nor_set_pp_settings(struct spi_nor_pp_command *pp,
+			u8 opcode,
+			enum spi_nor_protocol proto);
+
+static void
+mx25uw51245g_default_init(struct spi_nor *nor)
+{
+	struct spi_nor_flash_parameter *params = &nor->params;
+
+	if (!(nor->spimem->spi->mode & (SPI_RX_OCTAL | SPI_TX_OCTAL)))
+		return;
+
+	/* Octal 8S-8S-8S mode */
+	params->hwcaps.mask |= SNOR_HWCAPS_OPI_FULL_STR;
+	spi_nor_set_read_settings(&params->reads[SNOR_CMD_READ_8_8_8],
+				  0, 20, SPINOR_OP_READ_8_8_8,
+				  SNOR_PROTO_8_8_8);
+
+	spi_nor_set_pp_settings(&params->page_programs[SNOR_CMD_PP_8_8_8],
+				SPINOR_OP_PP_8_8_8, SNOR_PROTO_8_8_8);
+
+	/* Octal 8D-8D-8D mode */
+	params->hwcaps.mask |= SNOR_HWCAPS_OPI_FULL_DTR;
+	spi_nor_set_read_settings(&params->reads[SNOR_CMD_READ_8D_8D_8D],
+				  0, 20, SPINOR_OP_READ_8D_8D_8D,
+				  SNOR_PROTO_8_8_8_DTR);
+
+	spi_nor_set_pp_settings(&params->page_programs[SNOR_CMD_PP_8D_8D_8D],
+				SPINOR_OP_PP_8D_8D_8D, SNOR_PROTO_8_8_8_DTR);
+
+	nor->ext_cmd_mode = EXT_CMD_IS_INVERSE;
+}
+
+static void
+mx25uw51245g_post_sfdp_fixups(struct spi_nor *nor)
+{
+	struct spi_nor_flash_parameter *params = &nor->params;
+	u8 cr2;
+
+	cr2 = read_cr2(nor, CR2_REG0) & CR2_REG0_MODE_MASK;
+
+	if (params->hwcaps.mask & SNOR_HWCAPS_OPI_FULL_DTR)
+		cr2 |= CR2_REG0_MODE_OPI_DTR;
+	else if (params->hwcaps.mask & SNOR_HWCAPS_OPI_FULL_STR)
+		cr2 |= CR2_REG0_MODE_OPI_STR;
+
+	write_cr2(nor, CR2_REG0, cr2);
+}
+
 static struct spi_nor_fixups mx25l25635_fixups = {
 	.post_bfpt = mx25l25635_post_bfpt_fixups,
 };
 
+static struct spi_nor_fixups mx25uw51245g_fixups = {
+	.default_init = mx25uw51245g_default_init,
+	.post_sfdp = mx25uw51245g_post_sfdp_fixups,
+};
+
 static void gd25q256_default_init(struct spi_nor *nor)
 {
 	/*
@@ -2442,6 +2554,8 @@  static void gd25q256_default_init(struct spi_nor *nor)
 			 SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ)
 			 .fixups = &mx25l25635_fixups },
 	{ "mx25u25635f", INFO(0xc22539, 0, 64 * 1024, 512, SECT_4K | SPI_NOR_4B_OPCODES) },
+	{ "mx25uw51245g", INFO(0xc2813a, 0, 64 * 1024, 1024, SECT_4K | SPI_NOR_4B_OPCODES)
+				.fixups = &mx25uw51245g_fixups},
 	{ "mx25v8035f",  INFO(0xc22314, 0, 64 * 1024,  16,
 			 SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) },
 	{ "mx25l25655e", INFO(0xc22619, 0, 64 * 1024, 512, 0) },
diff --git a/include/linux/mtd/spi-nor.h b/include/linux/mtd/spi-nor.h
index 2e720ca..3aa54dd 100644
--- a/include/linux/mtd/spi-nor.h
+++ b/include/linux/mtd/spi-nor.h
@@ -114,6 +114,9 @@ 
 /* Write CFG Reg 2 - defined in JEDEC JESD216C. */
 #define SPINOR_OP_WRCR2		0x72	/* Write configuration register 2 */
 
+/* Used for Macronix flashes only */
+#define SPINOR_OP_RDCR2		0x71	/* Read configuration register 2 */
+
 /* Used for Macronix and Winbond flashes. */
 #define SPINOR_OP_EN4B		0xb7	/* Enter 4-byte mode */
 #define SPINOR_OP_EX4B		0xe9	/* Exit 4-byte mode */