Skip to content

Commit 39071cf

Browse files
committed
Merge tag 'mtd/fixes-for-5.2-rc7' of git://git.kernel.org/pub/scm/linux/kernel/git/mtd/linux
Pull mtd fixes from Miquel Raynal: - Set the raw NAND number of targets to the right value - Fix a bug uncovered by a recent patch on Spansion SPI-NOR flashes * tag 'mtd/fixes-for-5.2-rc7' of git://git.kernel.org/pub/scm/linux/kernel/git/mtd/linux: mtd: spi-nor: use 16-bit WRR command when QE is set on spansion flashes mtd: rawnand: initialize ntargets with maxchips
2 parents 26df62a + 191f5c2 commit 39071cf

File tree

3 files changed

+113
-12
lines changed

3 files changed

+113
-12
lines changed

drivers/mtd/nand/raw/nand_base.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4662,7 +4662,6 @@ static int nand_detect(struct nand_chip *chip, struct nand_flash_dev *type)
46624662
memorg = nanddev_get_memorg(&chip->base);
46634663
memorg->planes_per_lun = 1;
46644664
memorg->luns_per_target = 1;
4665-
memorg->ntargets = 1;
46664665

46674666
/*
46684667
* Reset the chip, required by some chips (e.g. Micron MT29FxGxxxxx)
@@ -5027,6 +5026,8 @@ static int nand_scan_ident(struct nand_chip *chip, unsigned int maxchips,
50275026
if (ret)
50285027
return ret;
50295028

5029+
memorg->ntargets = maxchips;
5030+
50305031
/* Read the flash type */
50315032
ret = nand_detect(chip, table);
50325033
if (ret) {

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

Lines changed: 108 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1636,6 +1636,95 @@ static int sr2_bit7_quad_enable(struct spi_nor *nor)
16361636
return 0;
16371637
}
16381638

1639+
/**
1640+
* spi_nor_clear_sr_bp() - clear the Status Register Block Protection bits.
1641+
* @nor: pointer to a 'struct spi_nor'
1642+
*
1643+
* Read-modify-write function that clears the Block Protection bits from the
1644+
* Status Register without affecting other bits.
1645+
*
1646+
* Return: 0 on success, -errno otherwise.
1647+
*/
1648+
static int spi_nor_clear_sr_bp(struct spi_nor *nor)
1649+
{
1650+
int ret;
1651+
u8 mask = SR_BP2 | SR_BP1 | SR_BP0;
1652+
1653+
ret = read_sr(nor);
1654+
if (ret < 0) {
1655+
dev_err(nor->dev, "error while reading status register\n");
1656+
return ret;
1657+
}
1658+
1659+
write_enable(nor);
1660+
1661+
ret = write_sr(nor, ret & ~mask);
1662+
if (ret) {
1663+
dev_err(nor->dev, "write to status register failed\n");
1664+
return ret;
1665+
}
1666+
1667+
ret = spi_nor_wait_till_ready(nor);
1668+
if (ret)
1669+
dev_err(nor->dev, "timeout while writing status register\n");
1670+
return ret;
1671+
}
1672+
1673+
/**
1674+
* spi_nor_spansion_clear_sr_bp() - clear the Status Register Block Protection
1675+
* bits on spansion flashes.
1676+
* @nor: pointer to a 'struct spi_nor'
1677+
*
1678+
* Read-modify-write function that clears the Block Protection bits from the
1679+
* Status Register without affecting other bits. The function is tightly
1680+
* coupled with the spansion_quad_enable() function. Both assume that the Write
1681+
* Register with 16 bits, together with the Read Configuration Register (35h)
1682+
* instructions are supported.
1683+
*
1684+
* Return: 0 on success, -errno otherwise.
1685+
*/
1686+
static int spi_nor_spansion_clear_sr_bp(struct spi_nor *nor)
1687+
{
1688+
int ret;
1689+
u8 mask = SR_BP2 | SR_BP1 | SR_BP0;
1690+
u8 sr_cr[2] = {0};
1691+
1692+
/* Check current Quad Enable bit value. */
1693+
ret = read_cr(nor);
1694+
if (ret < 0) {
1695+
dev_err(nor->dev,
1696+
"error while reading configuration register\n");
1697+
return ret;
1698+
}
1699+
1700+
/*
1701+
* When the configuration register Quad Enable bit is one, only the
1702+
* Write Status (01h) command with two data bytes may be used.
1703+
*/
1704+
if (ret & CR_QUAD_EN_SPAN) {
1705+
sr_cr[1] = ret;
1706+
1707+
ret = read_sr(nor);
1708+
if (ret < 0) {
1709+
dev_err(nor->dev,
1710+
"error while reading status register\n");
1711+
return ret;
1712+
}
1713+
sr_cr[0] = ret & ~mask;
1714+
1715+
ret = write_sr_cr(nor, sr_cr);
1716+
if (ret)
1717+
dev_err(nor->dev, "16-bit write register failed\n");
1718+
return ret;
1719+
}
1720+
1721+
/*
1722+
* If the Quad Enable bit is zero, use the Write Status (01h) command
1723+
* with one data byte.
1724+
*/
1725+
return spi_nor_clear_sr_bp(nor);
1726+
}
1727+
16391728
/* Used when the "_ext_id" is two bytes at most */
16401729
#define INFO(_jedec_id, _ext_id, _sector_size, _n_sectors, _flags) \
16411730
.id = { \
@@ -3660,6 +3749,8 @@ static int spi_nor_init_params(struct spi_nor *nor,
36603749
default:
36613750
/* Kept only for backward compatibility purpose. */
36623751
params->quad_enable = spansion_quad_enable;
3752+
if (nor->clear_sr_bp)
3753+
nor->clear_sr_bp = spi_nor_spansion_clear_sr_bp;
36633754
break;
36643755
}
36653756

@@ -3912,17 +4003,13 @@ static int spi_nor_init(struct spi_nor *nor)
39124003
{
39134004
int err;
39144005

3915-
/*
3916-
* Atmel, SST, Intel/Numonyx, and others serial NOR tend to power up
3917-
* with the software protection bits set
3918-
*/
3919-
if (JEDEC_MFR(nor->info) == SNOR_MFR_ATMEL ||
3920-
JEDEC_MFR(nor->info) == SNOR_MFR_INTEL ||
3921-
JEDEC_MFR(nor->info) == SNOR_MFR_SST ||
3922-
nor->info->flags & SPI_NOR_HAS_LOCK) {
3923-
write_enable(nor);
3924-
write_sr(nor, 0);
3925-
spi_nor_wait_till_ready(nor);
4006+
if (nor->clear_sr_bp) {
4007+
err = nor->clear_sr_bp(nor);
4008+
if (err) {
4009+
dev_err(nor->dev,
4010+
"fail to clear block protection bits\n");
4011+
return err;
4012+
}
39264013
}
39274014

39284015
if (nor->quad_enable) {
@@ -4047,6 +4134,16 @@ int spi_nor_scan(struct spi_nor *nor, const char *name,
40474134
if (info->flags & SPI_S3AN)
40484135
nor->flags |= SNOR_F_READY_XSR_RDY;
40494136

4137+
/*
4138+
* Atmel, SST, Intel/Numonyx, and others serial NOR tend to power up
4139+
* with the software protection bits set.
4140+
*/
4141+
if (JEDEC_MFR(nor->info) == SNOR_MFR_ATMEL ||
4142+
JEDEC_MFR(nor->info) == SNOR_MFR_INTEL ||
4143+
JEDEC_MFR(nor->info) == SNOR_MFR_SST ||
4144+
nor->info->flags & SPI_NOR_HAS_LOCK)
4145+
nor->clear_sr_bp = spi_nor_clear_sr_bp;
4146+
40504147
/* Parse the Serial Flash Discoverable Parameters table. */
40514148
ret = spi_nor_init_params(nor, &params);
40524149
if (ret)

include/linux/mtd/spi-nor.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -373,6 +373,8 @@ struct flash_info;
373373
* @flash_unlock: [FLASH-SPECIFIC] unlock a region of the SPI NOR
374374
* @flash_is_locked: [FLASH-SPECIFIC] check if a region of the SPI NOR is
375375
* @quad_enable: [FLASH-SPECIFIC] enables SPI NOR quad mode
376+
* @clear_sr_bp: [FLASH-SPECIFIC] clears the Block Protection Bits from
377+
* the SPI NOR Status Register.
376378
* completely locked
377379
* @priv: the private data
378380
*/
@@ -410,6 +412,7 @@ struct spi_nor {
410412
int (*flash_unlock)(struct spi_nor *nor, loff_t ofs, uint64_t len);
411413
int (*flash_is_locked)(struct spi_nor *nor, loff_t ofs, uint64_t len);
412414
int (*quad_enable)(struct spi_nor *nor);
415+
int (*clear_sr_bp)(struct spi_nor *nor);
413416

414417
void *priv;
415418
};

0 commit comments

Comments
 (0)