Skip to content

Commit 39d1e33

Browse files
committed
mtd: spi-nor: Fix clearing of QE bit on lock()/unlock()
Make sure that when doing a lock() or an unlock() operation we don't clear the QE bit from Status Register 2. JESD216 revB or later offers information about the *default* Status Register commands to use (see BFPT DWORDS[15], bits 22:20). In this standard, Status Register 1 refers to the first data byte transferred on a Read Status (05h) or Write Status (01h) command. Status register 2 refers to the byte read using instruction 35h. Status register 2 is the second byte transferred in a Write Status (01h) command. Industry naming and definitions of these Status Registers may differ. The definitions are described in JESD216B, BFPT DWORDS[15], bits 22:20. There are cases in which writing only one byte to the Status Register 1 has the side-effect of clearing Status Register 2 and implicitly the Quad Enable bit. This side-effect is hit just by the BFPT_DWORD15_QER_SR2_BIT1_BUGGY and BFPT_DWORD15_QER_SR2_BIT1 cases. Suggested-by: Boris Brezillon <boris.brezillon@collabora.com> Signed-off-by: Tudor Ambarus <tudor.ambarus@microchip.com> Reviewed-by: Vignesh Raghavendra <vigneshr@ti.com>
1 parent b24eaf5 commit 39d1e33

File tree

2 files changed

+118
-5
lines changed

2 files changed

+118
-5
lines changed

drivers/mtd/spi-nor/spi-nor.c

Lines changed: 115 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -959,12 +959,19 @@ static int spi_nor_write_sr(struct spi_nor *nor, const u8 *sr, size_t len)
959959
return spi_nor_wait_till_ready(nor);
960960
}
961961

962-
/* Write status register and ensure bits in mask match written values */
963-
static int spi_nor_write_sr_and_check(struct spi_nor *nor, u8 status_new)
962+
/**
963+
* spi_nor_write_sr1_and_check() - Write one byte to the Status Register 1 and
964+
* ensure that the byte written match the received value.
965+
* @nor: pointer to a 'struct spi_nor'.
966+
* @sr1: byte value to be written to the Status Register.
967+
*
968+
* Return: 0 on success, -errno otherwise.
969+
*/
970+
static int spi_nor_write_sr1_and_check(struct spi_nor *nor, u8 sr1)
964971
{
965972
int ret;
966973

967-
nor->bouncebuf[0] = status_new;
974+
nor->bouncebuf[0] = sr1;
968975

969976
ret = spi_nor_write_sr(nor, nor->bouncebuf, 1);
970977
if (ret)
@@ -974,14 +981,96 @@ static int spi_nor_write_sr_and_check(struct spi_nor *nor, u8 status_new)
974981
if (ret)
975982
return ret;
976983

977-
if (nor->bouncebuf[0] != status_new) {
978-
dev_dbg(nor->dev, "SR: read back test failed\n");
984+
if (nor->bouncebuf[0] != sr1) {
985+
dev_dbg(nor->dev, "SR1: read back test failed\n");
986+
return -EIO;
987+
}
988+
989+
return 0;
990+
}
991+
992+
/**
993+
* spi_nor_write_16bit_sr_and_check() - Write the Status Register 1 and the
994+
* Status Register 2 in one shot. Ensure that the byte written in the Status
995+
* Register 1 match the received value, and that the 16-bit Write did not
996+
* affect what was already in the Status Register 2.
997+
* @nor: pointer to a 'struct spi_nor'.
998+
* @sr1: byte value to be written to the Status Register 1.
999+
*
1000+
* Return: 0 on success, -errno otherwise.
1001+
*/
1002+
static int spi_nor_write_16bit_sr_and_check(struct spi_nor *nor, u8 sr1)
1003+
{
1004+
int ret;
1005+
u8 *sr_cr = nor->bouncebuf;
1006+
u8 cr_written;
1007+
1008+
/* Make sure we don't overwrite the contents of Status Register 2. */
1009+
if (!(nor->flags & SNOR_F_NO_READ_CR)) {
1010+
ret = spi_nor_read_cr(nor, &sr_cr[1]);
1011+
if (ret)
1012+
return ret;
1013+
} else if (nor->params.quad_enable) {
1014+
/*
1015+
* If the Status Register 2 Read command (35h) is not
1016+
* supported, we should at least be sure we don't
1017+
* change the value of the SR2 Quad Enable bit.
1018+
*
1019+
* We can safely assume that when the Quad Enable method is
1020+
* set, the value of the QE bit is one, as a consequence of the
1021+
* nor->params.quad_enable() call.
1022+
*
1023+
* We can safely assume that the Quad Enable bit is present in
1024+
* the Status Register 2 at BIT(1). According to the JESD216
1025+
* revB standard, BFPT DWORDS[15], bits 22:20, the 16-bit
1026+
* Write Status (01h) command is available just for the cases
1027+
* in which the QE bit is described in SR2 at BIT(1).
1028+
*/
1029+
sr_cr[1] = CR_QUAD_EN_SPAN;
1030+
} else {
1031+
sr_cr[1] = 0;
1032+
}
1033+
1034+
sr_cr[0] = sr1;
1035+
1036+
ret = spi_nor_write_sr(nor, sr_cr, 2);
1037+
if (ret)
1038+
return ret;
1039+
1040+
if (nor->flags & SNOR_F_NO_READ_CR)
1041+
return 0;
1042+
1043+
cr_written = sr_cr[1];
1044+
1045+
ret = spi_nor_read_cr(nor, &sr_cr[1]);
1046+
if (ret)
1047+
return ret;
1048+
1049+
if (cr_written != sr_cr[1]) {
1050+
dev_dbg(nor->dev, "CR: read back test failed\n");
9791051
return -EIO;
9801052
}
9811053

9821054
return 0;
9831055
}
9841056

1057+
/**
1058+
* spi_nor_write_sr_and_check() - Write the Status Register 1 and ensure that
1059+
* the byte written match the received value without affecting other bits in the
1060+
* Status Register 1 and 2.
1061+
* @nor: pointer to a 'struct spi_nor'.
1062+
* @sr1: byte value to be written to the Status Register.
1063+
*
1064+
* Return: 0 on success, -errno otherwise.
1065+
*/
1066+
static int spi_nor_write_sr_and_check(struct spi_nor *nor, u8 sr1)
1067+
{
1068+
if (nor->flags & SNOR_F_HAS_16BIT_SR)
1069+
return spi_nor_write_16bit_sr_and_check(nor, sr1);
1070+
1071+
return spi_nor_write_sr1_and_check(nor, sr1);
1072+
}
1073+
9851074
/**
9861075
* spi_nor_write_sr2() - Write the Status Register 2 using the
9871076
* SPINOR_OP_WRSR2 (3eh) command.
@@ -3634,19 +3723,38 @@ static int spi_nor_parse_bfpt(struct spi_nor *nor,
36343723
break;
36353724

36363725
case BFPT_DWORD15_QER_SR2_BIT1_BUGGY:
3726+
/*
3727+
* Writing only one byte to the Status Register has the
3728+
* side-effect of clearing Status Register 2.
3729+
*/
36373730
case BFPT_DWORD15_QER_SR2_BIT1_NO_RD:
3731+
/*
3732+
* Read Configuration Register (35h) instruction is not
3733+
* supported.
3734+
*/
3735+
nor->flags |= SNOR_F_HAS_16BIT_SR | SNOR_F_NO_READ_CR;
36383736
params->quad_enable = spansion_no_read_cr_quad_enable;
36393737
break;
36403738

36413739
case BFPT_DWORD15_QER_SR1_BIT6:
3740+
nor->flags &= ~SNOR_F_HAS_16BIT_SR;
36423741
params->quad_enable = macronix_quad_enable;
36433742
break;
36443743

36453744
case BFPT_DWORD15_QER_SR2_BIT7:
3745+
nor->flags &= ~SNOR_F_HAS_16BIT_SR;
36463746
params->quad_enable = sr2_bit7_quad_enable;
36473747
break;
36483748

36493749
case BFPT_DWORD15_QER_SR2_BIT1:
3750+
/*
3751+
* JESD216 rev B or later does not specify if writing only one
3752+
* byte to the Status Register clears or not the Status
3753+
* Register 2, so let's be cautious and keep the default
3754+
* assumption of a 16-bit Write Status (01h) command.
3755+
*/
3756+
nor->flags |= SNOR_F_HAS_16BIT_SR;
3757+
36503758
params->quad_enable = spansion_read_cr_quad_enable;
36513759
break;
36523760

@@ -4613,6 +4721,8 @@ static void spi_nor_info_init_params(struct spi_nor *nor)
46134721
params->quad_enable = spansion_read_cr_quad_enable;
46144722
params->set_4byte = spansion_set_4byte;
46154723
params->setup = spi_nor_default_setup;
4724+
/* Default to 16-bit Write Status (01h) Command */
4725+
nor->flags |= SNOR_F_HAS_16BIT_SR;
46164726

46174727
/* Set SPI NOR sizes. */
46184728
params->size = (u64)info->sector_size * info->n_sectors;

include/linux/mtd/spi-nor.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -243,6 +243,9 @@ enum spi_nor_option_flags {
243243
SNOR_F_4B_OPCODES = BIT(6),
244244
SNOR_F_HAS_4BAIT = BIT(7),
245245
SNOR_F_HAS_LOCK = BIT(8),
246+
SNOR_F_HAS_16BIT_SR = BIT(9),
247+
SNOR_F_NO_READ_CR = BIT(10),
248+
246249
};
247250

248251
/**

0 commit comments

Comments
 (0)