Skip to content

Commit b6b2383

Browse files
Kuwano-sanambarus
authored andcommitted
mtd: spi-nor: spansion: Add s25hl-t/s25hs-t IDs and fixups
The S25HL-T/S25HS-T family is the Infineon SEMPER Flash with Quad SPI. These Infineon chips support volatile version of configuration registers and it is recommended to update volatile registers in the field application due to a risk of the non-volatile registers corruption by power interrupt. Add support for volatile QE bit. For the single-die package parts (512Mb and 1Gb), only bottom 4KB and uniform sector sizes are supported. This is due to missing or incorrect entries in SMPT. Fixup for other sector sizes configurations will be followed up as needed. Tested on Xilinx Zynq-7000 FPGA board. Signed-off-by: Takahiro Kuwano <Takahiro.Kuwano@infineon.com> Signed-off-by: Tudor Ambarus <tudor.ambarus@microchip.com> Acked-by: Michael Walle <michael@walle.cc> Link: https://lore.kernel.org/r/20220725092505.446315-8-tudor.ambarus@microchip.com
1 parent a6b50aa commit b6b2383

File tree

1 file changed

+132
-0
lines changed

1 file changed

+132
-0
lines changed

drivers/mtd/spi-nor/spansion.c

Lines changed: 132 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,8 @@
1414
#define SPINOR_OP_CLSR 0x30 /* Clear status register 1 */
1515
#define SPINOR_OP_RD_ANY_REG 0x65 /* Read any register */
1616
#define SPINOR_OP_WR_ANY_REG 0x71 /* Write any register */
17+
#define SPINOR_REG_CYPRESS_CFR1V 0x00800002
18+
#define SPINOR_REG_CYPRESS_CFR1V_QUAD_EN BIT(1) /* Quad Enable */
1719
#define SPINOR_REG_CYPRESS_CFR2V 0x00800003
1820
#define SPINOR_REG_CYPRESS_CFR2V_MEMLAT_11_24 0xb
1921
#define SPINOR_REG_CYPRESS_CFR3V 0x00800004
@@ -113,6 +115,68 @@ static int cypress_nor_octal_dtr_dis(struct spi_nor *nor)
113115
return 0;
114116
}
115117

118+
/**
119+
* cypress_nor_quad_enable_volatile() - enable Quad I/O mode in volatile
120+
* register.
121+
* @nor: pointer to a 'struct spi_nor'
122+
*
123+
* It is recommended to update volatile registers in the field application due
124+
* to a risk of the non-volatile registers corruption by power interrupt. This
125+
* function sets Quad Enable bit in CFR1 volatile. If users set the Quad Enable
126+
* bit in the CFR1 non-volatile in advance (typically by a Flash programmer
127+
* before mounting Flash on PCB), the Quad Enable bit in the CFR1 volatile is
128+
* also set during Flash power-up.
129+
*
130+
* Return: 0 on success, -errno otherwise.
131+
*/
132+
static int cypress_nor_quad_enable_volatile(struct spi_nor *nor)
133+
{
134+
struct spi_mem_op op;
135+
u8 addr_mode_nbytes = nor->params->addr_mode_nbytes;
136+
u8 cfr1v_written;
137+
int ret;
138+
139+
op = (struct spi_mem_op)
140+
CYPRESS_NOR_RD_ANY_REG_OP(addr_mode_nbytes,
141+
SPINOR_REG_CYPRESS_CFR1V,
142+
nor->bouncebuf);
143+
144+
ret = spi_nor_read_any_reg(nor, &op, nor->reg_proto);
145+
if (ret)
146+
return ret;
147+
148+
if (nor->bouncebuf[0] & SPINOR_REG_CYPRESS_CFR1V_QUAD_EN)
149+
return 0;
150+
151+
/* Update the Quad Enable bit. */
152+
nor->bouncebuf[0] |= SPINOR_REG_CYPRESS_CFR1V_QUAD_EN;
153+
op = (struct spi_mem_op)
154+
CYPRESS_NOR_WR_ANY_REG_OP(addr_mode_nbytes,
155+
SPINOR_REG_CYPRESS_CFR1V, 1,
156+
nor->bouncebuf);
157+
ret = spi_nor_write_any_volatile_reg(nor, &op, nor->reg_proto);
158+
if (ret)
159+
return ret;
160+
161+
cfr1v_written = nor->bouncebuf[0];
162+
163+
/* Read back and check it. */
164+
op = (struct spi_mem_op)
165+
CYPRESS_NOR_RD_ANY_REG_OP(addr_mode_nbytes,
166+
SPINOR_REG_CYPRESS_CFR1V,
167+
nor->bouncebuf);
168+
ret = spi_nor_read_any_reg(nor, &op, nor->reg_proto);
169+
if (ret)
170+
return ret;
171+
172+
if (nor->bouncebuf[0] != cfr1v_written) {
173+
dev_err(nor->dev, "CFR1: Read back test failed\n");
174+
return -EIO;
175+
}
176+
177+
return 0;
178+
}
179+
116180
/**
117181
* cypress_nor_set_page_size() - Set page size which corresponds to the flash
118182
* configuration.
@@ -143,6 +207,58 @@ static int cypress_nor_set_page_size(struct spi_nor *nor)
143207
return 0;
144208
}
145209

210+
static int
211+
s25hx_t_post_bfpt_fixup(struct spi_nor *nor,
212+
const struct sfdp_parameter_header *bfpt_header,
213+
const struct sfdp_bfpt *bfpt)
214+
{
215+
/* Replace Quad Enable with volatile version */
216+
nor->params->quad_enable = cypress_nor_quad_enable_volatile;
217+
218+
return cypress_nor_set_page_size(nor);
219+
}
220+
221+
static void s25hx_t_post_sfdp_fixup(struct spi_nor *nor)
222+
{
223+
struct spi_nor_erase_type *erase_type =
224+
nor->params->erase_map.erase_type;
225+
unsigned int i;
226+
227+
/*
228+
* In some parts, 3byte erase opcodes are advertised by 4BAIT.
229+
* Convert them to 4byte erase opcodes.
230+
*/
231+
for (i = 0; i < SNOR_ERASE_TYPE_MAX; i++) {
232+
switch (erase_type[i].opcode) {
233+
case SPINOR_OP_SE:
234+
erase_type[i].opcode = SPINOR_OP_SE_4B;
235+
break;
236+
case SPINOR_OP_BE_4K:
237+
erase_type[i].opcode = SPINOR_OP_BE_4K_4B;
238+
break;
239+
default:
240+
break;
241+
}
242+
}
243+
}
244+
245+
static void s25hx_t_late_init(struct spi_nor *nor)
246+
{
247+
struct spi_nor_flash_parameter *params = nor->params;
248+
249+
/* Fast Read 4B requires mode cycles */
250+
params->reads[SNOR_CMD_READ_FAST].num_mode_clocks = 8;
251+
252+
/* The writesize should be ECC data unit size */
253+
params->writesize = 16;
254+
}
255+
256+
static struct spi_nor_fixups s25hx_t_fixups = {
257+
.post_bfpt = s25hx_t_post_bfpt_fixup,
258+
.post_sfdp = s25hx_t_post_sfdp_fixup,
259+
.late_init = s25hx_t_late_init,
260+
};
261+
146262
/**
147263
* cypress_nor_octal_dtr_enable() - Enable octal DTR on Cypress flashes.
148264
* @nor: pointer to a 'struct spi_nor'
@@ -319,6 +435,22 @@ static const struct flash_info spansion_nor_parts[] = {
319435
{ "s25fl256l", INFO(0x016019, 0, 64 * 1024, 512)
320436
NO_SFDP_FLAGS(SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ)
321437
FIXUP_FLAGS(SPI_NOR_4B_OPCODES) },
438+
{ "s25hl512t", INFO6(0x342a1a, 0x0f0390, 256 * 1024, 256)
439+
PARSE_SFDP
440+
MFR_FLAGS(USE_CLSR)
441+
.fixups = &s25hx_t_fixups },
442+
{ "s25hl01gt", INFO6(0x342a1b, 0x0f0390, 256 * 1024, 512)
443+
PARSE_SFDP
444+
MFR_FLAGS(USE_CLSR)
445+
.fixups = &s25hx_t_fixups },
446+
{ "s25hs512t", INFO6(0x342b1a, 0x0f0390, 256 * 1024, 256)
447+
PARSE_SFDP
448+
MFR_FLAGS(USE_CLSR)
449+
.fixups = &s25hx_t_fixups },
450+
{ "s25hs01gt", INFO6(0x342b1b, 0x0f0390, 256 * 1024, 512)
451+
PARSE_SFDP
452+
MFR_FLAGS(USE_CLSR)
453+
.fixups = &s25hx_t_fixups },
322454
{ "cy15x104q", INFO6(0x042cc2, 0x7f7f7f, 512 * 1024, 1)
323455
FLAGS(SPI_NOR_NO_ERASE) },
324456
{ "s28hs512t", INFO(0x345b1a, 0, 256 * 1024, 256)

0 commit comments

Comments
 (0)