- Set the raw NAND number of targets to the right value.
- Fix a bug uncovered by a recent patch on Spansion SPI-NOR flashes. -----BEGIN PGP SIGNATURE----- iQEzBAABCgAdFiEE9HuaYnbmDhq/XIDIJWrqGEe9VoQFAl0Pwk0ACgkQJWrqGEe9 VoS8nwf7B76jN39/g32Hfp4JT/B7cntrHzTGxfUT9NAhKa4MaI7FOU2eeTryaVdO 32OJlttV+r0Fu6p+In1VXCk4j1YlkcOaxqB1VXsMEaQ+Vt8ONVTbJX/cqyGC/ogq MZlO8Rys4MGmq7vRiZ+1SD8lOV4qXgmX3D38NjUQ1oCAMCCgJgkWYFV2tv9Eie09 2CCT3IBFj+D34qaBiM+qocGtnzWfB9477A6ZeI4BwjUe1ZtoEYeIOrCXWiywabjM msHRN1tNt5kfINnx0TkQFcnpbdDo5tMyTHCkEQt5Ewdae4vyCv7xTHTCZEttC7Ic Rx2yONzrZGQVP4c27y22K954C1jGcg== =ZiPm -----END PGP SIGNATURE----- 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
This commit is contained in:
commit
39071cf828
|
@ -4662,7 +4662,6 @@ static int nand_detect(struct nand_chip *chip, struct nand_flash_dev *type)
|
|||
memorg = nanddev_get_memorg(&chip->base);
|
||||
memorg->planes_per_lun = 1;
|
||||
memorg->luns_per_target = 1;
|
||||
memorg->ntargets = 1;
|
||||
|
||||
/*
|
||||
* 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,
|
|||
if (ret)
|
||||
return ret;
|
||||
|
||||
memorg->ntargets = maxchips;
|
||||
|
||||
/* Read the flash type */
|
||||
ret = nand_detect(chip, table);
|
||||
if (ret) {
|
||||
|
|
|
@ -1636,6 +1636,95 @@ static int sr2_bit7_quad_enable(struct spi_nor *nor)
|
|||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* spi_nor_clear_sr_bp() - clear the Status Register Block Protection bits.
|
||||
* @nor: pointer to a 'struct spi_nor'
|
||||
*
|
||||
* Read-modify-write function that clears the Block Protection bits from the
|
||||
* Status Register without affecting other bits.
|
||||
*
|
||||
* Return: 0 on success, -errno otherwise.
|
||||
*/
|
||||
static int spi_nor_clear_sr_bp(struct spi_nor *nor)
|
||||
{
|
||||
int ret;
|
||||
u8 mask = SR_BP2 | SR_BP1 | SR_BP0;
|
||||
|
||||
ret = read_sr(nor);
|
||||
if (ret < 0) {
|
||||
dev_err(nor->dev, "error while reading status register\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
write_enable(nor);
|
||||
|
||||
ret = write_sr(nor, ret & ~mask);
|
||||
if (ret) {
|
||||
dev_err(nor->dev, "write to status register failed\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = spi_nor_wait_till_ready(nor);
|
||||
if (ret)
|
||||
dev_err(nor->dev, "timeout while writing status register\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* spi_nor_spansion_clear_sr_bp() - clear the Status Register Block Protection
|
||||
* bits on spansion flashes.
|
||||
* @nor: pointer to a 'struct spi_nor'
|
||||
*
|
||||
* Read-modify-write function that clears the Block Protection bits from the
|
||||
* Status Register without affecting other bits. The function is tightly
|
||||
* coupled with the spansion_quad_enable() function. Both assume that the Write
|
||||
* Register with 16 bits, together with the Read Configuration Register (35h)
|
||||
* instructions are supported.
|
||||
*
|
||||
* Return: 0 on success, -errno otherwise.
|
||||
*/
|
||||
static int spi_nor_spansion_clear_sr_bp(struct spi_nor *nor)
|
||||
{
|
||||
int ret;
|
||||
u8 mask = SR_BP2 | SR_BP1 | SR_BP0;
|
||||
u8 sr_cr[2] = {0};
|
||||
|
||||
/* Check current Quad Enable bit value. */
|
||||
ret = read_cr(nor);
|
||||
if (ret < 0) {
|
||||
dev_err(nor->dev,
|
||||
"error while reading configuration register\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* When the configuration register Quad Enable bit is one, only the
|
||||
* Write Status (01h) command with two data bytes may be used.
|
||||
*/
|
||||
if (ret & CR_QUAD_EN_SPAN) {
|
||||
sr_cr[1] = ret;
|
||||
|
||||
ret = read_sr(nor);
|
||||
if (ret < 0) {
|
||||
dev_err(nor->dev,
|
||||
"error while reading status register\n");
|
||||
return ret;
|
||||
}
|
||||
sr_cr[0] = ret & ~mask;
|
||||
|
||||
ret = write_sr_cr(nor, sr_cr);
|
||||
if (ret)
|
||||
dev_err(nor->dev, "16-bit write register failed\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* If the Quad Enable bit is zero, use the Write Status (01h) command
|
||||
* with one data byte.
|
||||
*/
|
||||
return spi_nor_clear_sr_bp(nor);
|
||||
}
|
||||
|
||||
/* Used when the "_ext_id" is two bytes at most */
|
||||
#define INFO(_jedec_id, _ext_id, _sector_size, _n_sectors, _flags) \
|
||||
.id = { \
|
||||
|
@ -3660,6 +3749,8 @@ static int spi_nor_init_params(struct spi_nor *nor,
|
|||
default:
|
||||
/* Kept only for backward compatibility purpose. */
|
||||
params->quad_enable = spansion_quad_enable;
|
||||
if (nor->clear_sr_bp)
|
||||
nor->clear_sr_bp = spi_nor_spansion_clear_sr_bp;
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -3912,17 +4003,13 @@ static int spi_nor_init(struct spi_nor *nor)
|
|||
{
|
||||
int err;
|
||||
|
||||
/*
|
||||
* Atmel, SST, Intel/Numonyx, and others serial NOR tend to power up
|
||||
* with the software protection bits set
|
||||
*/
|
||||
if (JEDEC_MFR(nor->info) == SNOR_MFR_ATMEL ||
|
||||
JEDEC_MFR(nor->info) == SNOR_MFR_INTEL ||
|
||||
JEDEC_MFR(nor->info) == SNOR_MFR_SST ||
|
||||
nor->info->flags & SPI_NOR_HAS_LOCK) {
|
||||
write_enable(nor);
|
||||
write_sr(nor, 0);
|
||||
spi_nor_wait_till_ready(nor);
|
||||
if (nor->clear_sr_bp) {
|
||||
err = nor->clear_sr_bp(nor);
|
||||
if (err) {
|
||||
dev_err(nor->dev,
|
||||
"fail to clear block protection bits\n");
|
||||
return err;
|
||||
}
|
||||
}
|
||||
|
||||
if (nor->quad_enable) {
|
||||
|
@ -4047,6 +4134,16 @@ int spi_nor_scan(struct spi_nor *nor, const char *name,
|
|||
if (info->flags & SPI_S3AN)
|
||||
nor->flags |= SNOR_F_READY_XSR_RDY;
|
||||
|
||||
/*
|
||||
* Atmel, SST, Intel/Numonyx, and others serial NOR tend to power up
|
||||
* with the software protection bits set.
|
||||
*/
|
||||
if (JEDEC_MFR(nor->info) == SNOR_MFR_ATMEL ||
|
||||
JEDEC_MFR(nor->info) == SNOR_MFR_INTEL ||
|
||||
JEDEC_MFR(nor->info) == SNOR_MFR_SST ||
|
||||
nor->info->flags & SPI_NOR_HAS_LOCK)
|
||||
nor->clear_sr_bp = spi_nor_clear_sr_bp;
|
||||
|
||||
/* Parse the Serial Flash Discoverable Parameters table. */
|
||||
ret = spi_nor_init_params(nor, ¶ms);
|
||||
if (ret)
|
||||
|
|
|
@ -373,6 +373,8 @@ struct flash_info;
|
|||
* @flash_unlock: [FLASH-SPECIFIC] unlock a region of the SPI NOR
|
||||
* @flash_is_locked: [FLASH-SPECIFIC] check if a region of the SPI NOR is
|
||||
* @quad_enable: [FLASH-SPECIFIC] enables SPI NOR quad mode
|
||||
* @clear_sr_bp: [FLASH-SPECIFIC] clears the Block Protection Bits from
|
||||
* the SPI NOR Status Register.
|
||||
* completely locked
|
||||
* @priv: the private data
|
||||
*/
|
||||
|
@ -410,6 +412,7 @@ struct spi_nor {
|
|||
int (*flash_unlock)(struct spi_nor *nor, loff_t ofs, uint64_t len);
|
||||
int (*flash_is_locked)(struct spi_nor *nor, loff_t ofs, uint64_t len);
|
||||
int (*quad_enable)(struct spi_nor *nor);
|
||||
int (*clear_sr_bp)(struct spi_nor *nor);
|
||||
|
||||
void *priv;
|
||||
};
|
||||
|
|
Loading…
Reference in New Issue