From 6938ad40cb97a52d88a763008935340729a4acc7 Mon Sep 17 00:00:00 2001 From: Ted Juan Date: Fri, 20 Jun 2014 17:32:05 +0800 Subject: [PATCH 1/3] mtd: devices: elm: fix elm_context_save() and elm_context_restore() functions These two function's switch case lack the 'break' that make them always return error. Signed-off-by: Ted Juan Acked-by: Pekon Gupta Cc: # 3.12.x+ Signed-off-by: Brian Norris --- drivers/mtd/devices/elm.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/mtd/devices/elm.c b/drivers/mtd/devices/elm.c index 7df86948e6d4..b4f61c7fc161 100644 --- a/drivers/mtd/devices/elm.c +++ b/drivers/mtd/devices/elm.c @@ -475,6 +475,7 @@ static int elm_context_save(struct elm_info *info) ELM_SYNDROME_FRAGMENT_1 + offset); regs->elm_syndrome_fragment_0[i] = elm_read_reg(info, ELM_SYNDROME_FRAGMENT_0 + offset); + break; default: return -EINVAL; } @@ -520,6 +521,7 @@ static int elm_context_restore(struct elm_info *info) regs->elm_syndrome_fragment_1[i]); elm_write_reg(info, ELM_SYNDROME_FRAGMENT_0 + offset, regs->elm_syndrome_fragment_0[i]); + break; default: return -EINVAL; } From 54c39e9ba3a93e3848ad8f9d082c39010cfc5e73 Mon Sep 17 00:00:00 2001 From: Thomas Petazzoni Date: Wed, 2 Jul 2014 15:16:32 +0200 Subject: [PATCH 2/3] mtd: nand: reduce the warning noise when the ECC is too weak In commit 67a9ad9b8a6f ("mtd: nand: Warn the user if the selected ECC strength is too weak"), a check was added to inform the user when the ECC used for a NAND device is weaker than the recommended ECC advertised by the NAND chip. However, the warning uses WARN_ON(), which has two undesirable side-effects: - It just prints to the kernel log the fact that there is a warning in this file, at this line, but it doesn't explain anything about the warning itself. - It dumps a stack trace which is very noisy, for something that the user is most likely not able to fix. If a certain ECC used by the kernel is weaker than the advertised one, it's most likely to make sure the kernel uses an ECC that is compatible with the one used by the bootloader, and changing the bootloader may not necessarily be easy. Therefore, normal users would not be able to do anything to fix this very noisy warning, and will have to suffer from it at every kernel boot. At least every time I see this stack trace in my kernel boot log, I wonder what new thing is broken, just to realize that it's once again this NAND ECC warning. Therefore, this commit turns: ------------[ cut here ]------------ WARNING: CPU: 0 PID: 1 at /home/thomas/projets/linux-2.6/drivers/mtd/nand/nand_base.c:4051 nand_scan_tail+0x538/0x780() Modules linked in: CPU: 0 PID: 1 Comm: swapper Not tainted 3.16.0-rc3-dirty #4 [] (unwind_backtrace) from [] (show_stack+0x10/0x14) [] (show_stack) from [] (warn_slowpath_common+0x6c/0x8c) [] (warn_slowpath_common) from [] (warn_slowpath_null+0x1c/0x24) [] (warn_slowpath_null) from [] (nand_scan_tail+0x538/0x780) [] (nand_scan_tail) from [] (orion_nand_probe+0x224/0x2e4) [] (orion_nand_probe) from [] (platform_drv_probe+0x18/0x4c) [] (platform_drv_probe) from [] (really_probe+0x80/0x218) [] (really_probe) from [] (__driver_attach+0x98/0x9c) [] (__driver_attach) from [] (bus_for_each_dev+0x64/0x94) [] (bus_for_each_dev) from [] (bus_add_driver+0x144/0x1ec) [] (bus_add_driver) from [] (driver_register+0x78/0xf8) [] (driver_register) from [] (platform_driver_probe+0x20/0xb8) [] (platform_driver_probe) from [] (do_one_initcall+0x80/0x1d8) [] (do_one_initcall) from [] (kernel_init_freeable+0xf4/0x1b4) [] (kernel_init_freeable) from [] (kernel_init+0x8/0xec) [] (kernel_init) from [] (ret_from_fork+0x14/0x24) ---[ end trace 62f87d875aceccb4 ]--- Into the much shorter, and much more useful: nand: WARNING: MT29F2G08ABAEAWP: the ECC used on your system is too weak compared to the one required by the NAND chip Signed-off-by: Thomas Petazzoni Signed-off-by: Brian Norris --- drivers/mtd/nand/nand_base.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/drivers/mtd/nand/nand_base.c b/drivers/mtd/nand/nand_base.c index 41167e9e991e..4f3e80c68a26 100644 --- a/drivers/mtd/nand/nand_base.c +++ b/drivers/mtd/nand/nand_base.c @@ -4047,8 +4047,10 @@ int nand_scan_tail(struct mtd_info *mtd) ecc->layout->oobavail += ecc->layout->oobfree[i].length; mtd->oobavail = ecc->layout->oobavail; - /* ECC sanity check: warn noisily if it's too weak */ - WARN_ON(!nand_ecc_strength_good(mtd)); + /* ECC sanity check: warn if it's too weak */ + if (!nand_ecc_strength_good(mtd)) + pr_warn("WARNING: %s: the ECC used on your system is too weak compared to the one required by the NAND chip\n", + mtd->name); /* * Set the number of read / write steps for one page depending on ECC From 812c5fa82bae9f377f49000d7636c19a8b61735c Mon Sep 17 00:00:00 2001 From: Andrea Adami Date: Mon, 2 Jun 2014 23:38:35 +0200 Subject: [PATCH 3/3] mtd: cfi_cmdset_0001.c: add support for Sharp LH28F640BF NOR This family of chips was long ago supported by the pre-cfi driver. CFI code tested on several Zaurus SL-5500 (Collie) 2x16 on 32 bit bus. Function is_LH28F640BF() mimics is_m29ew() from cmdset_0002.c Buffer write fixes as seen in 2007 patch c/o Anti Sullin artecdesign.ee> http://comments.gmane.org/gmane.linux.ports.arm.kernel/36733 [Brian: this patch is semi-urgent, because the following patch switches to using CFI detection for a chip which (until now) is unsupported by the CFI driver 9218310 ARM: 8084/1: sa1100: collie: revert back to cfi_probe ] Signed-off-by: Andrea Adami Signed-off-by: Brian Norris --- drivers/mtd/chips/cfi_cmdset_0001.c | 43 +++++++++++++++++++++++++++++ 1 file changed, 43 insertions(+) diff --git a/drivers/mtd/chips/cfi_cmdset_0001.c b/drivers/mtd/chips/cfi_cmdset_0001.c index e4ec355704a6..a7543ba3e190 100644 --- a/drivers/mtd/chips/cfi_cmdset_0001.c +++ b/drivers/mtd/chips/cfi_cmdset_0001.c @@ -52,6 +52,11 @@ /* Atmel chips */ #define AT49BV640D 0x02de #define AT49BV640DT 0x02db +/* Sharp chips */ +#define LH28F640BFHE_PTTL90 0x00b0 +#define LH28F640BFHE_PBTL90 0x00b1 +#define LH28F640BFHE_PTTL70A 0x00b2 +#define LH28F640BFHE_PBTL70A 0x00b3 static int cfi_intelext_read (struct mtd_info *, loff_t, size_t, size_t *, u_char *); static int cfi_intelext_write_words(struct mtd_info *, loff_t, size_t, size_t *, const u_char *); @@ -258,6 +263,36 @@ static void fixup_st_m28w320cb(struct mtd_info *mtd) (cfi->cfiq->EraseRegionInfo[1] & 0xffff0000) | 0x3e; }; +static int is_LH28F640BF(struct cfi_private *cfi) +{ + /* Sharp LH28F640BF Family */ + if (cfi->mfr == CFI_MFR_SHARP && ( + cfi->id == LH28F640BFHE_PTTL90 || cfi->id == LH28F640BFHE_PBTL90 || + cfi->id == LH28F640BFHE_PTTL70A || cfi->id == LH28F640BFHE_PBTL70A)) + return 1; + return 0; +} + +static void fixup_LH28F640BF(struct mtd_info *mtd) +{ + struct map_info *map = mtd->priv; + struct cfi_private *cfi = map->fldrv_priv; + struct cfi_pri_intelext *extp = cfi->cmdset_priv; + + /* Reset the Partition Configuration Register on LH28F640BF + * to a single partition (PCR = 0x000): PCR is embedded into A0-A15. */ + if (is_LH28F640BF(cfi)) { + printk(KERN_INFO "Reset Partition Config. Register: 1 Partition of 4 planes\n"); + map_write(map, CMD(0x60), 0); + map_write(map, CMD(0x04), 0); + + /* We have set one single partition thus + * Simultaneous Operations are not allowed */ + printk(KERN_INFO "cfi_cmdset_0001: Simultaneous Operations disabled\n"); + extp->FeatureSupport &= ~512; + } +} + static void fixup_use_point(struct mtd_info *mtd) { struct map_info *map = mtd->priv; @@ -309,6 +344,8 @@ static struct cfi_fixup cfi_fixup_table[] = { { CFI_MFR_ST, 0x00ba, /* M28W320CT */ fixup_st_m28w320ct }, { CFI_MFR_ST, 0x00bb, /* M28W320CB */ fixup_st_m28w320cb }, { CFI_MFR_INTEL, CFI_ID_ANY, fixup_unlock_powerup_lock }, + { CFI_MFR_SHARP, CFI_ID_ANY, fixup_unlock_powerup_lock }, + { CFI_MFR_SHARP, CFI_ID_ANY, fixup_LH28F640BF }, { 0, 0, NULL } }; @@ -1649,6 +1686,12 @@ static int __xipram do_write_buffer(struct map_info *map, struct flchip *chip, initial_adr = adr; cmd_adr = adr & ~(wbufsize-1); + /* Sharp LH28F640BF chips need the first address for the + * Page Buffer Program command. See Table 5 of + * LH28F320BF, LH28F640BF, LH28F128BF Series (Appendix FUM00701) */ + if (is_LH28F640BF(cfi)) + cmd_adr = adr; + /* Let's determine this according to the interleave only once */ write_cmd = (cfi->cfiq->P_ID != P_ID_INTEL_PERFORMANCE) ? CMD(0xe8) : CMD(0xe9);