mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2026-04-29 09:22:53 -04:00
Merge tag 'mtd/fixes-for-4.18-rc3' of git://git.infradead.org/linux-mtd
Pull mtd fixes from Boris Brezillon:
"NAND fixes:
- add a quirk for a bunch of broken Macronix chips
- fix nand_block_bad() when chip->ecc.read_oob() returns a positive
value encoding the number of bitflips
- fix OOB handling in the MXC driver fo V2.1 controllers
- flag the ONFI_FEATURE_ON_DIE_ECC as supported in the Micron driver
- hardcode clk rate in the denali_dt driver to address a bad DT
representation (the proper fix will be queued for 4.19)
SPI NOR fixes:
- add an ULL constant to some ID definitions so that the ID is not
truncated on 32-bit platforms
MTD fixes:
- fix the sector unlocking logic in the CFI driver"
* tag 'mtd/fixes-for-4.18-rc3' of git://git.infradead.org/linux-mtd:
mtd: rawnand: denali_dt: set clk_x_rate to 200 MHz unconditionally
mtd: dataflash: Use ULL suffix for 64-bit constants
mtd: cfi_cmdset_0002: Avoid walking all chips when unlocking.
mtd: cfi_cmdset_0002: Fix unlocking requests crossing a chip boudary
mtd: cfi_cmdset_0002: fix SEGV unlocking multiple chips
mtd: cfi_cmdset_0002: Use right chip in do_ppb_xxlock()
mtd: rawnand: All AC chips have a broken GET_FEATURES(TIMINGS).
mtd: rawnand: fix return value check for bad block status
mtd: rawnand: mxc: set spare area size register explicitly
mtd: rawnand: micron: add ONFI_FEATURE_ON_DIE_ECC to supported features
This commit is contained in:
@@ -2526,7 +2526,7 @@ static int cfi_atmel_unlock(struct mtd_info *mtd, loff_t ofs, uint64_t len)
|
||||
|
||||
struct ppb_lock {
|
||||
struct flchip *chip;
|
||||
loff_t offset;
|
||||
unsigned long adr;
|
||||
int locked;
|
||||
};
|
||||
|
||||
@@ -2544,8 +2544,9 @@ static int __maybe_unused do_ppb_xxlock(struct map_info *map,
|
||||
unsigned long timeo;
|
||||
int ret;
|
||||
|
||||
adr += chip->start;
|
||||
mutex_lock(&chip->mutex);
|
||||
ret = get_chip(map, chip, adr + chip->start, FL_LOCKING);
|
||||
ret = get_chip(map, chip, adr, FL_LOCKING);
|
||||
if (ret) {
|
||||
mutex_unlock(&chip->mutex);
|
||||
return ret;
|
||||
@@ -2563,8 +2564,8 @@ static int __maybe_unused do_ppb_xxlock(struct map_info *map,
|
||||
|
||||
if (thunk == DO_XXLOCK_ONEBLOCK_LOCK) {
|
||||
chip->state = FL_LOCKING;
|
||||
map_write(map, CMD(0xA0), chip->start + adr);
|
||||
map_write(map, CMD(0x00), chip->start + adr);
|
||||
map_write(map, CMD(0xA0), adr);
|
||||
map_write(map, CMD(0x00), adr);
|
||||
} else if (thunk == DO_XXLOCK_ONEBLOCK_UNLOCK) {
|
||||
/*
|
||||
* Unlocking of one specific sector is not supported, so we
|
||||
@@ -2602,7 +2603,7 @@ static int __maybe_unused do_ppb_xxlock(struct map_info *map,
|
||||
map_write(map, CMD(0x00), chip->start);
|
||||
|
||||
chip->state = FL_READY;
|
||||
put_chip(map, chip, adr + chip->start);
|
||||
put_chip(map, chip, adr);
|
||||
mutex_unlock(&chip->mutex);
|
||||
|
||||
return ret;
|
||||
@@ -2659,9 +2660,9 @@ static int __maybe_unused cfi_ppb_unlock(struct mtd_info *mtd, loff_t ofs,
|
||||
* sectors shall be unlocked, so lets keep their locking
|
||||
* status at "unlocked" (locked=0) for the final re-locking.
|
||||
*/
|
||||
if ((adr < ofs) || (adr >= (ofs + len))) {
|
||||
if ((offset < ofs) || (offset >= (ofs + len))) {
|
||||
sect[sectors].chip = &cfi->chips[chipnum];
|
||||
sect[sectors].offset = offset;
|
||||
sect[sectors].adr = adr;
|
||||
sect[sectors].locked = do_ppb_xxlock(
|
||||
map, &cfi->chips[chipnum], adr, 0,
|
||||
DO_XXLOCK_ONEBLOCK_GETLOCK);
|
||||
@@ -2675,6 +2676,8 @@ static int __maybe_unused cfi_ppb_unlock(struct mtd_info *mtd, loff_t ofs,
|
||||
i++;
|
||||
|
||||
if (adr >> cfi->chipshift) {
|
||||
if (offset >= (ofs + len))
|
||||
break;
|
||||
adr = 0;
|
||||
chipnum++;
|
||||
|
||||
@@ -2705,7 +2708,7 @@ static int __maybe_unused cfi_ppb_unlock(struct mtd_info *mtd, loff_t ofs,
|
||||
*/
|
||||
for (i = 0; i < sectors; i++) {
|
||||
if (sect[i].locked)
|
||||
do_ppb_xxlock(map, sect[i].chip, sect[i].offset, 0,
|
||||
do_ppb_xxlock(map, sect[i].chip, sect[i].adr, 0,
|
||||
DO_XXLOCK_ONEBLOCK_LOCK);
|
||||
}
|
||||
|
||||
|
||||
@@ -733,8 +733,8 @@ static struct flash_info dataflash_data[] = {
|
||||
{ "AT45DB642x", 0x1f2800, 8192, 1056, 11, SUP_POW2PS},
|
||||
{ "at45db642d", 0x1f2800, 8192, 1024, 10, SUP_POW2PS | IS_POW2PS},
|
||||
|
||||
{ "AT45DB641E", 0x1f28000100, 32768, 264, 9, SUP_EXTID | SUP_POW2PS},
|
||||
{ "at45db641e", 0x1f28000100, 32768, 256, 8, SUP_EXTID | SUP_POW2PS | IS_POW2PS},
|
||||
{ "AT45DB641E", 0x1f28000100ULL, 32768, 264, 9, SUP_EXTID | SUP_POW2PS},
|
||||
{ "at45db641e", 0x1f28000100ULL, 32768, 256, 8, SUP_EXTID | SUP_POW2PS | IS_POW2PS},
|
||||
};
|
||||
|
||||
static struct flash_info *jedec_lookup(struct spi_device *spi,
|
||||
|
||||
@@ -123,7 +123,11 @@ static int denali_dt_probe(struct platform_device *pdev)
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
denali->clk_x_rate = clk_get_rate(dt->clk);
|
||||
/*
|
||||
* Hardcode the clock rate for the backward compatibility.
|
||||
* This works for both SOCFPGA and UniPhier.
|
||||
*/
|
||||
denali->clk_x_rate = 200000000;
|
||||
|
||||
ret = denali_init(denali);
|
||||
if (ret)
|
||||
|
||||
@@ -48,7 +48,7 @@
|
||||
#define NFC_V1_V2_CONFIG (host->regs + 0x0a)
|
||||
#define NFC_V1_V2_ECC_STATUS_RESULT (host->regs + 0x0c)
|
||||
#define NFC_V1_V2_RSLTMAIN_AREA (host->regs + 0x0e)
|
||||
#define NFC_V1_V2_RSLTSPARE_AREA (host->regs + 0x10)
|
||||
#define NFC_V21_RSLTSPARE_AREA (host->regs + 0x10)
|
||||
#define NFC_V1_V2_WRPROT (host->regs + 0x12)
|
||||
#define NFC_V1_UNLOCKSTART_BLKADDR (host->regs + 0x14)
|
||||
#define NFC_V1_UNLOCKEND_BLKADDR (host->regs + 0x16)
|
||||
@@ -1274,6 +1274,9 @@ static void preset_v2(struct mtd_info *mtd)
|
||||
writew(config1, NFC_V1_V2_CONFIG1);
|
||||
/* preset operation */
|
||||
|
||||
/* spare area size in 16-bit half-words */
|
||||
writew(mtd->oobsize / 2, NFC_V21_RSLTSPARE_AREA);
|
||||
|
||||
/* Unlock the internal RAM Buffer */
|
||||
writew(0x2, NFC_V1_V2_CONFIG);
|
||||
|
||||
|
||||
@@ -440,7 +440,7 @@ static int nand_block_bad(struct mtd_info *mtd, loff_t ofs)
|
||||
|
||||
for (; page < page_end; page++) {
|
||||
res = chip->ecc.read_oob(mtd, chip, page);
|
||||
if (res)
|
||||
if (res < 0)
|
||||
return res;
|
||||
|
||||
bad = chip->oob_poi[chip->badblockpos];
|
||||
|
||||
@@ -17,23 +17,47 @@
|
||||
|
||||
#include <linux/mtd/rawnand.h>
|
||||
|
||||
/*
|
||||
* Macronix AC series does not support using SET/GET_FEATURES to change
|
||||
* the timings unlike what is declared in the parameter page. Unflag
|
||||
* this feature to avoid unnecessary downturns.
|
||||
*/
|
||||
static void macronix_nand_fix_broken_get_timings(struct nand_chip *chip)
|
||||
{
|
||||
unsigned int i;
|
||||
static const char * const broken_get_timings[] = {
|
||||
"MX30LF1G18AC",
|
||||
"MX30LF1G28AC",
|
||||
"MX30LF2G18AC",
|
||||
"MX30LF2G28AC",
|
||||
"MX30LF4G18AC",
|
||||
"MX30LF4G28AC",
|
||||
"MX60LF8G18AC",
|
||||
};
|
||||
|
||||
if (!chip->parameters.supports_set_get_features)
|
||||
return;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(broken_get_timings); i++) {
|
||||
if (!strcmp(broken_get_timings[i], chip->parameters.model))
|
||||
break;
|
||||
}
|
||||
|
||||
if (i == ARRAY_SIZE(broken_get_timings))
|
||||
return;
|
||||
|
||||
bitmap_clear(chip->parameters.get_feature_list,
|
||||
ONFI_FEATURE_ADDR_TIMING_MODE, 1);
|
||||
bitmap_clear(chip->parameters.set_feature_list,
|
||||
ONFI_FEATURE_ADDR_TIMING_MODE, 1);
|
||||
}
|
||||
|
||||
static int macronix_nand_init(struct nand_chip *chip)
|
||||
{
|
||||
if (nand_is_slc(chip))
|
||||
chip->bbt_options |= NAND_BBT_SCAN2NDPAGE;
|
||||
|
||||
/*
|
||||
* MX30LF2G18AC chip does not support using SET/GET_FEATURES to change
|
||||
* the timings unlike what is declared in the parameter page. Unflag
|
||||
* this feature to avoid unnecessary downturns.
|
||||
*/
|
||||
if (chip->parameters.supports_set_get_features &&
|
||||
!strcmp("MX30LF2G18AC", chip->parameters.model)) {
|
||||
bitmap_clear(chip->parameters.get_feature_list,
|
||||
ONFI_FEATURE_ADDR_TIMING_MODE, 1);
|
||||
bitmap_clear(chip->parameters.set_feature_list,
|
||||
ONFI_FEATURE_ADDR_TIMING_MODE, 1);
|
||||
}
|
||||
macronix_nand_fix_broken_get_timings(chip);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -66,7 +66,9 @@ static int micron_nand_onfi_init(struct nand_chip *chip)
|
||||
|
||||
if (p->supports_set_get_features) {
|
||||
set_bit(ONFI_FEATURE_ADDR_READ_RETRY, p->set_feature_list);
|
||||
set_bit(ONFI_FEATURE_ON_DIE_ECC, p->set_feature_list);
|
||||
set_bit(ONFI_FEATURE_ADDR_READ_RETRY, p->get_feature_list);
|
||||
set_bit(ONFI_FEATURE_ON_DIE_ECC, p->get_feature_list);
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
Reference in New Issue
Block a user