Skip to content

Commit 8583672

Browse files
ambarusvarshini-rajendran
authored andcommitted
mtd: spi-nor: macronix: Add support for mx66lm1g45g
mx66lm1g45g supports just 1-1-1, 8-8-8 and 8D-8D-8D modes. There are versions of mx66lm1g45g which do not support SFDP, thus use SPI_NOR_SKIP_SFDP. The RDID command issued through the octal peripheral interface outputs data always in STR mode for whatever reason. Since 8D-8D-8S is not common, avoid reading the ID when enabling the octal dtr mode. Instead, read back the CR2 to check if the switch was successful. Tested in 1-1-1 and 8d-8d-8d modes using sama7g5 QSPI IP. Signed-off-by: Tudor Ambarus <tudor.ambarus@microchip.com> Link: https://lore.kernel.org/r/20220209133656.374903-8-tudor.ambarus@microchip.com [varshini.rajendran@microchip.com: Rename method for enabling octal dtr in compliance with commit d499670 mtd: spi-nor: rename method for enabling or disabling octal DTR. Link: https://lore.kernel.org/r/20230714150757.15372-1-tudor.ambarus@linaro.org] Signed-off-by: Varshini Rajendran <varshini.rajendran@microchip.com> [varshini.rajendran@microchip.com: Change the return of the call back in compliance with the commit 'd534fd9787d5 mtd: spi-nor: spansion: use CLPEF as an alternative to CLSR' Link: https://lore.kernel.org/r/20230726075257.12985-2-tudor.ambarus@linaro.org] Signed-off-by: Varshini Rajendran <varshini.rajendran@microchip.com>
1 parent 9c1b1cc commit 8583672

1 file changed

Lines changed: 133 additions & 0 deletions

File tree

drivers/mtd/spi-nor/macronix.c

Lines changed: 133 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,132 @@
88

99
#include "core.h"
1010

11+
#define SPINOR_OP_READ_CR2 0x71 /* Read Configuration Register 2 */
12+
#define SPINOR_OP_WRITE_CR2 0x72 /* Write Configuration Register 2 */
13+
#define SPINOR_OP_MX_DTR_RD 0xee /* Octa DTR Read Opcode */
14+
15+
#define SPINOR_REG_CR2_MODE_ADDR 0 /* Address of Mode Enable in CR2 */
16+
#define SPINOR_REG_CR2_DTR_OPI_ENABLE BIT(1) /* DTR OPI Enable */
17+
#define SPINOR_REG_CR2_SPI 0 /* SPI Enable */
18+
19+
/**
20+
* Macronix SPI NOR flash operations.
21+
*/
22+
#define SPI_NOR_MX_READ_CR2_OP(ndummy, buf, ndata) \
23+
SPI_MEM_OP(SPI_MEM_OP_CMD(SPINOR_OP_READ_CR2, 0), \
24+
SPI_MEM_OP_ADDR(4, SPINOR_REG_CR2_MODE_ADDR, 0), \
25+
SPI_MEM_OP_DUMMY(ndummy, 0), \
26+
SPI_MEM_OP_DATA_IN(ndata, buf, 0))
27+
28+
#define SPI_NOR_MX_WRITE_CR2_OP(buf, ndata) \
29+
SPI_MEM_OP(SPI_MEM_OP_CMD(SPINOR_OP_WRITE_CR2, 0), \
30+
SPI_MEM_OP_ADDR(4, SPINOR_REG_CR2_MODE_ADDR, 0), \
31+
SPI_MEM_OP_NO_DUMMY, \
32+
SPI_MEM_OP_DATA_OUT(ndata, buf, 0))
33+
34+
static int spi_nor_macronix_read_cr2(struct spi_nor *nor, u8 ndummy, void *sr,
35+
unsigned int nbytes)
36+
{
37+
struct spi_mem_op op = SPI_NOR_MX_READ_CR2_OP(ndummy, sr, nbytes);
38+
39+
spi_nor_spimem_setup_op(nor, &op, nor->reg_proto);
40+
return spi_mem_exec_op(nor->spimem, &op);
41+
}
42+
43+
static int spi_nor_macronix_write_cr2(struct spi_nor *nor, const void *sr,
44+
unsigned int nbytes)
45+
{
46+
struct spi_mem_op op = SPI_NOR_MX_WRITE_CR2_OP(sr, nbytes);
47+
int ret;
48+
49+
spi_nor_spimem_setup_op(nor, &op, nor->reg_proto);
50+
ret = spi_nor_write_enable(nor);
51+
if (ret)
52+
return ret;
53+
return spi_mem_exec_op(nor->spimem, &op);
54+
}
55+
56+
static int spi_nor_macronix_octal_dtr_en(struct spi_nor *nor)
57+
{
58+
u8 *buf = nor->bouncebuf;
59+
int i, ret;
60+
61+
buf[0] = SPINOR_REG_CR2_DTR_OPI_ENABLE;
62+
ret = spi_nor_macronix_write_cr2(nor, buf, 1);
63+
if (ret)
64+
return ret;
65+
66+
/* Read flash ID to make sure the switch was successful. */
67+
ret = spi_nor_read_id(nor, 4, 4, buf, SNOR_PROTO_8_8_8_DTR);
68+
if (ret)
69+
return ret;
70+
71+
for (i = 0; i < nor->info->id_len; i++)
72+
if (buf[i * 2] != nor->info->id[i])
73+
return -EINVAL;
74+
return 0;
75+
}
76+
77+
static int spi_nor_macronix_octal_dtr_dis(struct spi_nor *nor)
78+
{
79+
u8 *buf = nor->bouncebuf;
80+
int ret;
81+
82+
/*
83+
* One byte transactions are not allowed in 8D-8D-8D mode. mx66lm1g45g
84+
* requires that undefined register addresses to keep their value
85+
* unchanged. Its second CR2 byte value is not defined. Read the second
86+
* byte value of CR2 so that we can write it back when disabling
87+
* Octal DTR mode.
88+
*/
89+
ret = spi_nor_macronix_read_cr2(nor, 4, buf, 2);
90+
if (ret)
91+
return ret;
92+
/* Keep the value of buf[1] unchanged.*/
93+
buf[0] = SPINOR_REG_CR2_SPI;
94+
95+
ret = spi_nor_macronix_write_cr2(nor, buf, 2);
96+
if (ret)
97+
return ret;
98+
99+
ret = spi_nor_read_id(nor, 0, 0, buf, nor->reg_proto);
100+
if (ret)
101+
return ret;
102+
103+
if (memcmp(buf, nor->info->id, nor->info->id_len)) {
104+
dev_dbg(nor->dev, "Failed to disable 8D-8D-8D mode.\n");
105+
return -EINVAL;
106+
}
107+
return 0;
108+
}
109+
110+
static int spi_nor_macronix_set_octal_dtr(struct spi_nor *nor, bool enable)
111+
{
112+
return enable ? spi_nor_macronix_octal_dtr_en(nor) :
113+
spi_nor_macronix_octal_dtr_dis(nor);
114+
}
115+
116+
static int mx66lm1g45g_late_init(struct spi_nor *nor)
117+
{
118+
nor->params->set_octal_dtr = spi_nor_macronix_set_octal_dtr;
119+
120+
/* Set the Fast Read settings. */
121+
nor->params->hwcaps.mask |= SNOR_HWCAPS_READ_8_8_8_DTR;
122+
spi_nor_set_read_settings(&nor->params->reads[SNOR_CMD_READ_8_8_8_DTR],
123+
0, 20, SPINOR_OP_MX_DTR_RD,
124+
SNOR_PROTO_8_8_8_DTR);
125+
126+
nor->cmd_ext_type = SPI_NOR_EXT_INVERT;
127+
nor->params->rdsr_dummy = 4;
128+
nor->params->rdsr_addr_nbytes = 4;
129+
130+
return 0;
131+
}
132+
133+
static struct spi_nor_fixups mx66lm1g45g_fixups = {
134+
.late_init = mx66lm1g45g_late_init,
135+
};
136+
11137
static int
12138
mx25l25635_post_bfpt_fixups(struct spi_nor *nor,
13139
const struct sfdp_parameter_header *bfpt_header,
@@ -103,6 +229,13 @@ static const struct flash_info macronix_nor_parts[] = {
103229
{ "mx66u2g45g", INFO(0xc2253c, 0, 64 * 1024, 4096)
104230
NO_SFDP_FLAGS(SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ)
105231
FIXUP_FLAGS(SPI_NOR_4B_OPCODES) },
232+
{ "mx66lm1g45g", INFO(0xc2853b, 0, 64 * 1024, 2048)
233+
NO_SFDP_FLAGS(SPI_NOR_SKIP_SFDP | SECT_4K |
234+
SPI_NOR_OCTAL_DTR_READ | SPI_NOR_OCTAL_DTR_PP)
235+
FIXUP_FLAGS(SPI_NOR_4B_OPCODES | SPI_NOR_IO_MODE_EN_VOLATILE |
236+
SPI_NOR_SOFT_RESET)
237+
.fixups = &mx66lm1g45g_fixups,
238+
},
106239
};
107240

108241
static void macronix_nor_default_init(struct spi_nor *nor)

0 commit comments

Comments
 (0)