* Fix nanddev_mtd_erase() function to match the changes done in
e7bfb3fdbd
("mtd: Stop updating erase_info->state and calling mtd_erase_callback()") * Fix a memory leak in the Tango NAND controller driver * Fix read/write to a suspended erase block in the CFI driver * Fix the DT parsing logic in the Marvell NAND controller driver -----BEGIN PGP SIGNATURE----- iQI5BAABCAAjBQJa4taLHBxib3Jpcy5icmV6aWxsb25AYm9vdGxpbi5jb20ACgkQ Ze02AX4ItwCTBQ//cY0GR+upuxJT7d7QZio6OMHwund2FBMiYvNeDK343PUkg/kK VOoJ/1CAb4RRyq+n7vyOTsApEtq8+HmbPea1M7CWos/QShHupTarLaG+r4z2Ko95 NhroZG8F9eeYxswNTU5kTdne4XjLv1UasOmWymxUdKfHiOGwRV0aNFDLcROlDM/h ou5+5txr/BYD4QGFFpGsdVA4F9FP+f+lSkXxP3LazHh/0/JrBuQgUiUvnBOVGyvh Pgjky8Q/dToNeZA2+QPmt0TUTn02WT5+xAytfP5GdFxCd+RRpwRHvGwNVlbbSU1Z g7v2rurF9iebfF9UZQ7gMfQwZAvaXRWkczdJlirJdRzC+T1iXst6JTW7lzw4/BJd InZj+GTN67RZOQ7tEwEFmzUYyg9+FKJ+TawVaxmQqWels7GCUpKN1lgYOzqxdoBj YqZRq472FCifULkZqgmzqKKa050g1rfjilM5ckGkhgQBINExR2DT35rJJXuZ6Gko QW0K5vzKQCaElL3hNACHIejELwB9n1fyNuV21tlqIcLismrt0NGGel2ocRFVzSxr fk8pe7MeSiDNtlL5rCKqX7GWPz+fCsEfSCDZOVzvHQlpijRhpMo9D9DJ5ci9Itxd yQUTH8wI3ZVkc7eiwC1TVGrjKWRG/0Mp96l0fMOwbsiqQIjtf3hqE++oAzo= =myWm -----END PGP SIGNATURE----- Merge tag 'mtd/fixes-for-4.17-rc3' of git://git.infradead.org/linux-mtd Pull mtd fixes from Boris Brezillon: - Fix nanddev_mtd_erase() function to match the changes done ine7bfb3fdbd
("mtd: Stop updating erase_info->state and calling mtd_erase_callback()") - Fix a memory leak in the Tango NAND controller driver - Fix read/write to a suspended erase block in the CFI driver - Fix the DT parsing logic in the Marvell NAND controller driver * tag 'mtd/fixes-for-4.17-rc3' of git://git.infradead.org/linux-mtd: mtd: rawnand: marvell: fix the chip-select DT parsing logic mtd: cfi: cmdset_0002: Do not allow read/write to suspend erase block. mtd: cfi: cmdset_0001: Workaround Micron Erase suspend bug. mtd: cfi: cmdset_0001: Do not allow read/write to suspend erase block. mtd: spi-nor: cadence-quadspi: Fix page fault kernel panic mtd: nand: Fix nanddev_mtd_erase() mtd: rawnand: tango: Fix struct clk memory leak
This commit is contained in:
commit
245131e2d6
|
@ -45,6 +45,7 @@
|
|||
#define I82802AB 0x00ad
|
||||
#define I82802AC 0x00ac
|
||||
#define PF38F4476 0x881c
|
||||
#define M28F00AP30 0x8963
|
||||
/* STMicroelectronics chips */
|
||||
#define M50LPW080 0x002F
|
||||
#define M50FLW080A 0x0080
|
||||
|
@ -375,6 +376,17 @@ static void cfi_fixup_major_minor(struct cfi_private *cfi,
|
|||
extp->MinorVersion = '1';
|
||||
}
|
||||
|
||||
static int cfi_is_micron_28F00AP30(struct cfi_private *cfi, struct flchip *chip)
|
||||
{
|
||||
/*
|
||||
* Micron(was Numonyx) 1Gbit bottom boot are buggy w.r.t
|
||||
* Erase Supend for their small Erase Blocks(0x8000)
|
||||
*/
|
||||
if (cfi->mfr == CFI_MFR_INTEL && cfi->id == M28F00AP30)
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline struct cfi_pri_intelext *
|
||||
read_pri_intelext(struct map_info *map, __u16 adr)
|
||||
{
|
||||
|
@ -831,21 +843,30 @@ static int chip_ready (struct map_info *map, struct flchip *chip, unsigned long
|
|||
(mode == FL_WRITING && (cfip->SuspendCmdSupport & 1))))
|
||||
goto sleep;
|
||||
|
||||
/* Do not allow suspend iff read/write to EB address */
|
||||
if ((adr & chip->in_progress_block_mask) ==
|
||||
chip->in_progress_block_addr)
|
||||
goto sleep;
|
||||
|
||||
/* do not suspend small EBs, buggy Micron Chips */
|
||||
if (cfi_is_micron_28F00AP30(cfi, chip) &&
|
||||
(chip->in_progress_block_mask == ~(0x8000-1)))
|
||||
goto sleep;
|
||||
|
||||
/* Erase suspend */
|
||||
map_write(map, CMD(0xB0), adr);
|
||||
map_write(map, CMD(0xB0), chip->in_progress_block_addr);
|
||||
|
||||
/* If the flash has finished erasing, then 'erase suspend'
|
||||
* appears to make some (28F320) flash devices switch to
|
||||
* 'read' mode. Make sure that we switch to 'read status'
|
||||
* mode so we get the right data. --rmk
|
||||
*/
|
||||
map_write(map, CMD(0x70), adr);
|
||||
map_write(map, CMD(0x70), chip->in_progress_block_addr);
|
||||
chip->oldstate = FL_ERASING;
|
||||
chip->state = FL_ERASE_SUSPENDING;
|
||||
chip->erase_suspended = 1;
|
||||
for (;;) {
|
||||
status = map_read(map, adr);
|
||||
status = map_read(map, chip->in_progress_block_addr);
|
||||
if (map_word_andequal(map, status, status_OK, status_OK))
|
||||
break;
|
||||
|
||||
|
@ -1041,8 +1062,8 @@ static void put_chip(struct map_info *map, struct flchip *chip, unsigned long ad
|
|||
sending the 0x70 (Read Status) command to an erasing
|
||||
chip and expecting it to be ignored, that's what we
|
||||
do. */
|
||||
map_write(map, CMD(0xd0), adr);
|
||||
map_write(map, CMD(0x70), adr);
|
||||
map_write(map, CMD(0xd0), chip->in_progress_block_addr);
|
||||
map_write(map, CMD(0x70), chip->in_progress_block_addr);
|
||||
chip->oldstate = FL_READY;
|
||||
chip->state = FL_ERASING;
|
||||
break;
|
||||
|
@ -1933,6 +1954,8 @@ static int __xipram do_erase_oneblock(struct map_info *map, struct flchip *chip,
|
|||
map_write(map, CMD(0xD0), adr);
|
||||
chip->state = FL_ERASING;
|
||||
chip->erase_suspended = 0;
|
||||
chip->in_progress_block_addr = adr;
|
||||
chip->in_progress_block_mask = ~(len - 1);
|
||||
|
||||
ret = INVAL_CACHE_AND_WAIT(map, chip, adr,
|
||||
adr, len,
|
||||
|
|
|
@ -816,9 +816,10 @@ static int get_chip(struct map_info *map, struct flchip *chip, unsigned long adr
|
|||
(mode == FL_WRITING && (cfip->EraseSuspend & 0x2))))
|
||||
goto sleep;
|
||||
|
||||
/* We could check to see if we're trying to access the sector
|
||||
* that is currently being erased. However, no user will try
|
||||
* anything like that so we just wait for the timeout. */
|
||||
/* Do not allow suspend iff read/write to EB address */
|
||||
if ((adr & chip->in_progress_block_mask) ==
|
||||
chip->in_progress_block_addr)
|
||||
goto sleep;
|
||||
|
||||
/* Erase suspend */
|
||||
/* It's harmless to issue the Erase-Suspend and Erase-Resume
|
||||
|
@ -2267,6 +2268,7 @@ static int __xipram do_erase_chip(struct map_info *map, struct flchip *chip)
|
|||
chip->state = FL_ERASING;
|
||||
chip->erase_suspended = 0;
|
||||
chip->in_progress_block_addr = adr;
|
||||
chip->in_progress_block_mask = ~(map->size - 1);
|
||||
|
||||
INVALIDATE_CACHE_UDELAY(map, chip,
|
||||
adr, map->size,
|
||||
|
@ -2356,6 +2358,7 @@ static int __xipram do_erase_oneblock(struct map_info *map, struct flchip *chip,
|
|||
chip->state = FL_ERASING;
|
||||
chip->erase_suspended = 0;
|
||||
chip->in_progress_block_addr = adr;
|
||||
chip->in_progress_block_mask = ~(len - 1);
|
||||
|
||||
INVALIDATE_CACHE_UDELAY(map, chip,
|
||||
adr, len,
|
||||
|
|
|
@ -162,7 +162,6 @@ int nanddev_mtd_erase(struct mtd_info *mtd, struct erase_info *einfo)
|
|||
ret = nanddev_erase(nand, &pos);
|
||||
if (ret) {
|
||||
einfo->fail_addr = nanddev_pos_to_offs(nand, &pos);
|
||||
einfo->state = MTD_ERASE_FAILED;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
@ -170,8 +169,6 @@ int nanddev_mtd_erase(struct mtd_info *mtd, struct erase_info *einfo)
|
|||
nanddev_pos_next_eraseblock(nand, &pos);
|
||||
}
|
||||
|
||||
einfo->state = MTD_ERASE_DONE;
|
||||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(nanddev_mtd_erase);
|
||||
|
|
|
@ -2299,29 +2299,20 @@ static int marvell_nand_chip_init(struct device *dev, struct marvell_nfc *nfc,
|
|||
/*
|
||||
* The legacy "num-cs" property indicates the number of CS on the only
|
||||
* chip connected to the controller (legacy bindings does not support
|
||||
* more than one chip). CS are only incremented one by one while the RB
|
||||
* pin is always the #0.
|
||||
* more than one chip). The CS and RB pins are always the #0.
|
||||
*
|
||||
* When not using legacy bindings, a couple of "reg" and "nand-rb"
|
||||
* properties must be filled. For each chip, expressed as a subnode,
|
||||
* "reg" points to the CS lines and "nand-rb" to the RB line.
|
||||
*/
|
||||
if (pdata) {
|
||||
if (pdata || nfc->caps->legacy_of_bindings) {
|
||||
nsels = 1;
|
||||
} else if (nfc->caps->legacy_of_bindings &&
|
||||
!of_get_property(np, "num-cs", &nsels)) {
|
||||
dev_err(dev, "missing num-cs property\n");
|
||||
return -EINVAL;
|
||||
} else if (!of_get_property(np, "reg", &nsels)) {
|
||||
dev_err(dev, "missing reg property\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (!pdata)
|
||||
nsels /= sizeof(u32);
|
||||
if (!nsels) {
|
||||
dev_err(dev, "invalid reg property size\n");
|
||||
return -EINVAL;
|
||||
} else {
|
||||
nsels = of_property_count_elems_of_size(np, "reg", sizeof(u32));
|
||||
if (nsels <= 0) {
|
||||
dev_err(dev, "missing/invalid reg property\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
|
||||
/* Alloc the nand chip structure */
|
||||
|
|
|
@ -645,7 +645,7 @@ static int tango_nand_probe(struct platform_device *pdev)
|
|||
|
||||
writel_relaxed(MODE_RAW, nfc->pbus_base + PBUS_PAD_MODE);
|
||||
|
||||
clk = clk_get(&pdev->dev, NULL);
|
||||
clk = devm_clk_get(&pdev->dev, NULL);
|
||||
if (IS_ERR(clk))
|
||||
return PTR_ERR(clk);
|
||||
|
||||
|
|
|
@ -501,7 +501,9 @@ static int cqspi_indirect_read_execute(struct spi_nor *nor, u8 *rxbuf,
|
|||
void __iomem *reg_base = cqspi->iobase;
|
||||
void __iomem *ahb_base = cqspi->ahb_base;
|
||||
unsigned int remaining = n_rx;
|
||||
unsigned int mod_bytes = n_rx % 4;
|
||||
unsigned int bytes_to_read = 0;
|
||||
u8 *rxbuf_end = rxbuf + n_rx;
|
||||
int ret = 0;
|
||||
|
||||
writel(from_addr, reg_base + CQSPI_REG_INDIRECTRDSTARTADDR);
|
||||
|
@ -530,11 +532,24 @@ static int cqspi_indirect_read_execute(struct spi_nor *nor, u8 *rxbuf,
|
|||
}
|
||||
|
||||
while (bytes_to_read != 0) {
|
||||
unsigned int word_remain = round_down(remaining, 4);
|
||||
|
||||
bytes_to_read *= cqspi->fifo_width;
|
||||
bytes_to_read = bytes_to_read > remaining ?
|
||||
remaining : bytes_to_read;
|
||||
ioread32_rep(ahb_base, rxbuf,
|
||||
DIV_ROUND_UP(bytes_to_read, 4));
|
||||
bytes_to_read = round_down(bytes_to_read, 4);
|
||||
/* Read 4 byte word chunks then single bytes */
|
||||
if (bytes_to_read) {
|
||||
ioread32_rep(ahb_base, rxbuf,
|
||||
(bytes_to_read / 4));
|
||||
} else if (!word_remain && mod_bytes) {
|
||||
unsigned int temp = ioread32(ahb_base);
|
||||
|
||||
bytes_to_read = mod_bytes;
|
||||
memcpy(rxbuf, &temp, min((unsigned int)
|
||||
(rxbuf_end - rxbuf),
|
||||
bytes_to_read));
|
||||
}
|
||||
rxbuf += bytes_to_read;
|
||||
remaining -= bytes_to_read;
|
||||
bytes_to_read = cqspi_get_rd_sram_level(cqspi);
|
||||
|
|
|
@ -85,6 +85,7 @@ struct flchip {
|
|||
unsigned int write_suspended:1;
|
||||
unsigned int erase_suspended:1;
|
||||
unsigned long in_progress_block_addr;
|
||||
unsigned long in_progress_block_mask;
|
||||
|
||||
struct mutex mutex;
|
||||
wait_queue_head_t wq; /* Wait on here when we're waiting for the chip
|
||||
|
|
Loading…
Reference in New Issue