Commit c7e1d692 authored by Linus Torvalds's avatar Linus Torvalds

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
parents ea5f39f2 3f6e6986
...@@ -2526,7 +2526,7 @@ static int cfi_atmel_unlock(struct mtd_info *mtd, loff_t ofs, uint64_t len) ...@@ -2526,7 +2526,7 @@ static int cfi_atmel_unlock(struct mtd_info *mtd, loff_t ofs, uint64_t len)
struct ppb_lock { struct ppb_lock {
struct flchip *chip; struct flchip *chip;
loff_t offset; unsigned long adr;
int locked; int locked;
}; };
...@@ -2544,8 +2544,9 @@ static int __maybe_unused do_ppb_xxlock(struct map_info *map, ...@@ -2544,8 +2544,9 @@ static int __maybe_unused do_ppb_xxlock(struct map_info *map,
unsigned long timeo; unsigned long timeo;
int ret; int ret;
adr += chip->start;
mutex_lock(&chip->mutex); mutex_lock(&chip->mutex);
ret = get_chip(map, chip, adr + chip->start, FL_LOCKING); ret = get_chip(map, chip, adr, FL_LOCKING);
if (ret) { if (ret) {
mutex_unlock(&chip->mutex); mutex_unlock(&chip->mutex);
return ret; return ret;
...@@ -2563,8 +2564,8 @@ static int __maybe_unused do_ppb_xxlock(struct map_info *map, ...@@ -2563,8 +2564,8 @@ static int __maybe_unused do_ppb_xxlock(struct map_info *map,
if (thunk == DO_XXLOCK_ONEBLOCK_LOCK) { if (thunk == DO_XXLOCK_ONEBLOCK_LOCK) {
chip->state = FL_LOCKING; chip->state = FL_LOCKING;
map_write(map, CMD(0xA0), chip->start + adr); map_write(map, CMD(0xA0), adr);
map_write(map, CMD(0x00), chip->start + adr); map_write(map, CMD(0x00), adr);
} else if (thunk == DO_XXLOCK_ONEBLOCK_UNLOCK) { } else if (thunk == DO_XXLOCK_ONEBLOCK_UNLOCK) {
/* /*
* Unlocking of one specific sector is not supported, so we * 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, ...@@ -2602,7 +2603,7 @@ static int __maybe_unused do_ppb_xxlock(struct map_info *map,
map_write(map, CMD(0x00), chip->start); map_write(map, CMD(0x00), chip->start);
chip->state = FL_READY; chip->state = FL_READY;
put_chip(map, chip, adr + chip->start); put_chip(map, chip, adr);
mutex_unlock(&chip->mutex); mutex_unlock(&chip->mutex);
return ret; return ret;
...@@ -2659,9 +2660,9 @@ static int __maybe_unused cfi_ppb_unlock(struct mtd_info *mtd, loff_t ofs, ...@@ -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 * sectors shall be unlocked, so lets keep their locking
* status at "unlocked" (locked=0) for the final re-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].chip = &cfi->chips[chipnum];
sect[sectors].offset = offset; sect[sectors].adr = adr;
sect[sectors].locked = do_ppb_xxlock( sect[sectors].locked = do_ppb_xxlock(
map, &cfi->chips[chipnum], adr, 0, map, &cfi->chips[chipnum], adr, 0,
DO_XXLOCK_ONEBLOCK_GETLOCK); DO_XXLOCK_ONEBLOCK_GETLOCK);
...@@ -2675,6 +2676,8 @@ static int __maybe_unused cfi_ppb_unlock(struct mtd_info *mtd, loff_t ofs, ...@@ -2675,6 +2676,8 @@ static int __maybe_unused cfi_ppb_unlock(struct mtd_info *mtd, loff_t ofs,
i++; i++;
if (adr >> cfi->chipshift) { if (adr >> cfi->chipshift) {
if (offset >= (ofs + len))
break;
adr = 0; adr = 0;
chipnum++; chipnum++;
...@@ -2705,7 +2708,7 @@ static int __maybe_unused cfi_ppb_unlock(struct mtd_info *mtd, loff_t ofs, ...@@ -2705,7 +2708,7 @@ static int __maybe_unused cfi_ppb_unlock(struct mtd_info *mtd, loff_t ofs,
*/ */
for (i = 0; i < sectors; i++) { for (i = 0; i < sectors; i++) {
if (sect[i].locked) 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); DO_XXLOCK_ONEBLOCK_LOCK);
} }
......
...@@ -733,8 +733,8 @@ static struct flash_info dataflash_data[] = { ...@@ -733,8 +733,8 @@ static struct flash_info dataflash_data[] = {
{ "AT45DB642x", 0x1f2800, 8192, 1056, 11, SUP_POW2PS}, { "AT45DB642x", 0x1f2800, 8192, 1056, 11, SUP_POW2PS},
{ "at45db642d", 0x1f2800, 8192, 1024, 10, SUP_POW2PS | IS_POW2PS}, { "at45db642d", 0x1f2800, 8192, 1024, 10, SUP_POW2PS | IS_POW2PS},
{ "AT45DB641E", 0x1f28000100, 32768, 264, 9, SUP_EXTID | SUP_POW2PS}, { "AT45DB641E", 0x1f28000100ULL, 32768, 264, 9, SUP_EXTID | SUP_POW2PS},
{ "at45db641e", 0x1f28000100, 32768, 256, 8, SUP_EXTID | SUP_POW2PS | IS_POW2PS}, { "at45db641e", 0x1f28000100ULL, 32768, 256, 8, SUP_EXTID | SUP_POW2PS | IS_POW2PS},
}; };
static struct flash_info *jedec_lookup(struct spi_device *spi, static struct flash_info *jedec_lookup(struct spi_device *spi,
......
...@@ -123,7 +123,11 @@ static int denali_dt_probe(struct platform_device *pdev) ...@@ -123,7 +123,11 @@ static int denali_dt_probe(struct platform_device *pdev)
if (ret) if (ret)
return 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); ret = denali_init(denali);
if (ret) if (ret)
......
...@@ -48,7 +48,7 @@ ...@@ -48,7 +48,7 @@
#define NFC_V1_V2_CONFIG (host->regs + 0x0a) #define NFC_V1_V2_CONFIG (host->regs + 0x0a)
#define NFC_V1_V2_ECC_STATUS_RESULT (host->regs + 0x0c) #define NFC_V1_V2_ECC_STATUS_RESULT (host->regs + 0x0c)
#define NFC_V1_V2_RSLTMAIN_AREA (host->regs + 0x0e) #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_V2_WRPROT (host->regs + 0x12)
#define NFC_V1_UNLOCKSTART_BLKADDR (host->regs + 0x14) #define NFC_V1_UNLOCKSTART_BLKADDR (host->regs + 0x14)
#define NFC_V1_UNLOCKEND_BLKADDR (host->regs + 0x16) #define NFC_V1_UNLOCKEND_BLKADDR (host->regs + 0x16)
...@@ -1274,6 +1274,9 @@ static void preset_v2(struct mtd_info *mtd) ...@@ -1274,6 +1274,9 @@ static void preset_v2(struct mtd_info *mtd)
writew(config1, NFC_V1_V2_CONFIG1); writew(config1, NFC_V1_V2_CONFIG1);
/* preset operation */ /* preset operation */
/* spare area size in 16-bit half-words */
writew(mtd->oobsize / 2, NFC_V21_RSLTSPARE_AREA);
/* Unlock the internal RAM Buffer */ /* Unlock the internal RAM Buffer */
writew(0x2, NFC_V1_V2_CONFIG); writew(0x2, NFC_V1_V2_CONFIG);
......
...@@ -440,7 +440,7 @@ static int nand_block_bad(struct mtd_info *mtd, loff_t ofs) ...@@ -440,7 +440,7 @@ static int nand_block_bad(struct mtd_info *mtd, loff_t ofs)
for (; page < page_end; page++) { for (; page < page_end; page++) {
res = chip->ecc.read_oob(mtd, chip, page); res = chip->ecc.read_oob(mtd, chip, page);
if (res) if (res < 0)
return res; return res;
bad = chip->oob_poi[chip->badblockpos]; bad = chip->oob_poi[chip->badblockpos];
......
...@@ -17,23 +17,47 @@ ...@@ -17,23 +17,47 @@
#include <linux/mtd/rawnand.h> #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) static int macronix_nand_init(struct nand_chip *chip)
{ {
if (nand_is_slc(chip)) if (nand_is_slc(chip))
chip->bbt_options |= NAND_BBT_SCAN2NDPAGE; chip->bbt_options |= NAND_BBT_SCAN2NDPAGE;
/* macronix_nand_fix_broken_get_timings(chip);
* 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);
}
return 0; return 0;
} }
......
...@@ -66,7 +66,9 @@ static int micron_nand_onfi_init(struct nand_chip *chip) ...@@ -66,7 +66,9 @@ static int micron_nand_onfi_init(struct nand_chip *chip)
if (p->supports_set_get_features) { if (p->supports_set_get_features) {
set_bit(ONFI_FEATURE_ADDR_READ_RETRY, p->set_feature_list); 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_ADDR_READ_RETRY, p->get_feature_list);
set_bit(ONFI_FEATURE_ON_DIE_ECC, p->get_feature_list);
} }
return 0; return 0;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment