diff mbox series

mtd: spi-nor: macronix: add support for Macronix octaflash mx25uw51345g

Message ID 20231213084820.932217-1-haibo.chen@nxp.com
State Changes Requested
Delegated to: Ambarus Tudor
Headers show
Series mtd: spi-nor: macronix: add support for Macronix octaflash mx25uw51345g | expand

Commit Message

Bough Chen Dec. 13, 2023, 8:48 a.m. UTC
From: Haibo Chen <haibo.chen@nxp.com>

The octaflash mx25uw51345g is an xSPI compliant octal DTR flash. Here add
support for using it in octal DTR mode.

Try to verify the flash ID to check whether the flash memory in octal
DTR mode and SPI mode are correct. When reading ID in OCTAL DTR mode,
ID will appear in a repeated manner. ex: ID[0] = 0xc2, ID[1] = 0xc2,
ID[2] = 0x94, ID[3] = 0x94... Rearrange the order so that the ID check
can pass.

Based on the following patch:
https://patchwork.ozlabs.org/project/linux-mtd/patch/1621232088-12567-2-git-send-email-zhengxunli@mxic.com.tw/

Signed-off-by: Zhengxun Li <zhengxunli@mxic.com.tw>
Signed-off-by: Haibo Chen <haibo.chen@nxp.com>
---
 drivers/mtd/spi-nor/macronix.c | 91 ++++++++++++++++++++++++++++++++++
 1 file changed, 91 insertions(+)

Comments

Tudor Ambarus Dec. 15, 2023, 6:52 a.m. UTC | #1
Hi, Haibo,

Please read the following before sending v2:
https://git.kernel.org/pub/scm/linux/kernel/git/mtd/linux.git/tree/Documentation/driver-api/mtd/spi-nor.rst?h=spi-nor/next

On 13.12.2023 10:48, haibo.chen@nxp.com wrote:
> From: Haibo Chen <haibo.chen@nxp.com>
> 
> The octaflash mx25uw51345g is an xSPI compliant octal DTR flash. Here add
> support for using it in octal DTR mode.
> 
> Try to verify the flash ID to check whether the flash memory in octal
> DTR mode and SPI mode are correct. When reading ID in OCTAL DTR mode,
> ID will appear in a repeated manner. ex: ID[0] = 0xc2, ID[1] = 0xc2,
> ID[2] = 0x94, ID[3] = 0x94... Rearrange the order so that the ID check
> can pass.
> 
> Based on the following patch:
> https://patchwork.ozlabs.org/project/linux-mtd/patch/1621232088-12567-2-git-send-email-zhengxunli@mxic.com.tw/

I would have taken the patch from above if I considered it ready to be
integrated. Please sync with Zhengxun/Jaime and find out what's missing.
> 
> Signed-off-by: Zhengxun Li <zhengxunli@mxic.com.tw>
> Signed-off-by: Haibo Chen <haibo.chen@nxp.com>
> ---
>  drivers/mtd/spi-nor/macronix.c | 91 ++++++++++++++++++++++++++++++++++
>  1 file changed, 91 insertions(+)
> 
> diff --git a/drivers/mtd/spi-nor/macronix.c b/drivers/mtd/spi-nor/macronix.c
> index ea6be95e75a5..8a1ce17cff3f 100644
> --- a/drivers/mtd/spi-nor/macronix.c
> +++ b/drivers/mtd/spi-nor/macronix.c
> @@ -8,6 +8,11 @@
>  
> 
cut

> +
>  static const struct flash_info macronix_nor_parts[] = {
>  	{
>  		.id = SNOR_ID(0xc2, 0x20, 0x10),
> @@ -177,6 +261,13 @@ static const struct flash_info macronix_nor_parts[] = {
>  		.name = "mx25uw51245g",
>  		.n_banks = 4,
>  		.flags = SPI_NOR_RWW,
> +	}, {
> +		.id = SNOR_ID(0xc2, 0x84, 0x3a),
> +		.name = "mx25uw51345g",

we'll obsolete the name on new flash additions, drop it.
> +		.size = SZ_64M,
> +		.no_sfdp_flags = SECT_4K | SPI_NOR_OCTAL_DTR_READ | SPI_NOR_OCTAL_DTR_PP,

should be discovered by sfdp, isn't it?
> +		.fixup_flags = SPI_NOR_4B_OPCODES,

these too.
> +		.fixups = &octaflash_fixups,
>  	}, {
>  		.id = SNOR_ID(0xc2, 0x9e, 0x16),
>  		.name = "mx25l3255e",

Cheers,
ta
diff mbox series

Patch

diff --git a/drivers/mtd/spi-nor/macronix.c b/drivers/mtd/spi-nor/macronix.c
index ea6be95e75a5..8a1ce17cff3f 100644
--- a/drivers/mtd/spi-nor/macronix.c
+++ b/drivers/mtd/spi-nor/macronix.c
@@ -8,6 +8,11 @@ 
 
 #include "core.h"
 
+#define SPINOR_OP_WR_CR2		0x72		/* Write configuration register 2 */
+#define SPINOR_REG_MXIC_CR2_MODE	0x00000000	/* For setting octal DTR mode */
+#define SPINOR_REG_MXIC_OPI_DTR_EN	0x2		/* Enable Octal DTR */
+#define SPINOR_REG_MXIC_SPI_EN		0x0		/* Enable SPI */
+
 static int
 mx25l25635_post_bfpt_fixups(struct spi_nor *nor,
 			    const struct sfdp_parameter_header *bfpt_header,
@@ -32,6 +37,85 @@  static const struct spi_nor_fixups mx25l25635_fixups = {
 	.post_bfpt = mx25l25635_post_bfpt_fixups,
 };
 
+/**
+ * spi_nor_macronix_set_octal_dtr() - Enable/Disable octal DTR on Macronix flashes.
+ * @nor:		pointer to a 'struct spi_nor'
+ * @enable:		whether to enable Octal DTR or switch back to SPI
+ *
+ * Return: 0 on success, -errno otherwise.
+ */
+static int spi_nor_macronix_set_octal_dtr(struct spi_nor *nor, bool enable)
+{
+	struct spi_mem_op op;
+	u8 *buf = nor->bouncebuf, i;
+	int ret;
+
+	/* Set/unset the octal and DTR enable bits. */
+	ret = spi_nor_write_enable(nor);
+	if (ret)
+		return ret;
+
+	if (enable) {
+		buf[0] = SPINOR_REG_MXIC_OPI_DTR_EN;
+	} else {
+		/*
+		 * The register is 1-byte wide, but 1-byte transactions are not
+		 * allowed in 8D-8D-8D mode. Since there is no register at the
+		 * next location, just initialize the value to 0 and let the
+		 * transaction go on.
+		 */
+		buf[0] = SPINOR_REG_MXIC_SPI_EN;
+		buf[1] = 0x0;
+	}
+
+	op = (struct spi_mem_op)
+		SPI_MEM_OP(SPI_MEM_OP_CMD(SPINOR_OP_WR_CR2, 1),
+			   SPI_MEM_OP_ADDR(4, SPINOR_REG_MXIC_CR2_MODE, 1),
+			   SPI_MEM_OP_NO_DUMMY,
+			   SPI_MEM_OP_DATA_OUT(enable ? 1 : 2, buf, 1));
+
+	if (!enable)
+		spi_nor_spimem_setup_op(nor, &op, SNOR_PROTO_8_8_8_DTR);
+
+	ret = spi_mem_exec_op(nor->spimem, &op);
+	if (ret)
+		return ret;
+
+	/* Read flash ID to make sure the switch was successful. */
+	op = (struct spi_mem_op)
+		SPI_MEM_OP(SPI_MEM_OP_CMD(SPINOR_OP_RDID, 1),
+			   SPI_MEM_OP_ADDR(enable ? 4 : 0, 0, 1),
+			   SPI_MEM_OP_DUMMY(enable ? 4 : 0, 1),
+			   SPI_MEM_OP_DATA_IN(SPI_NOR_MAX_ID_LEN, buf, 1));
+
+	if (enable)
+		spi_nor_spimem_setup_op(nor, &op, SNOR_PROTO_8_8_8_DTR);
+
+	ret = spi_mem_exec_op(nor->spimem, &op);
+	if (ret)
+		return ret;
+
+	if (enable) {
+		for (i = 0; i < nor->info->id->len; i++)
+			if (buf[i * 2] != nor->info->id->bytes[i])
+				return -EINVAL;
+	} else {
+		if (memcmp(buf, nor->info->id->bytes, nor->info->id->len))
+			return -EINVAL;
+	}
+
+	return 0;
+}
+
+static void octaflash_default_init(struct spi_nor *nor)
+{
+	nor->params->set_octal_dtr = spi_nor_macronix_set_octal_dtr;
+}
+
+static struct spi_nor_fixups octaflash_fixups = {
+	.default_init = octaflash_default_init,
+};
+
 static const struct flash_info macronix_nor_parts[] = {
 	{
 		.id = SNOR_ID(0xc2, 0x20, 0x10),
@@ -177,6 +261,13 @@  static const struct flash_info macronix_nor_parts[] = {
 		.name = "mx25uw51245g",
 		.n_banks = 4,
 		.flags = SPI_NOR_RWW,
+	}, {
+		.id = SNOR_ID(0xc2, 0x84, 0x3a),
+		.name = "mx25uw51345g",
+		.size = SZ_64M,
+		.no_sfdp_flags = SECT_4K | SPI_NOR_OCTAL_DTR_READ | SPI_NOR_OCTAL_DTR_PP,
+		.fixup_flags = SPI_NOR_4B_OPCODES,
+		.fixups = &octaflash_fixups,
 	}, {
 		.id = SNOR_ID(0xc2, 0x9e, 0x16),
 		.name = "mx25l3255e",