aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGerlando Falauto <gerlando.falauto@keymile.com>2012-07-03 03:09:47 -0400
committerDavid Woodhouse <David.Woodhouse@intel.com>2012-07-16 16:37:15 -0400
commit420962884379bd434a7f643d0936281b2ab4b30c (patch)
tree2570518810ff732c4083833466b2247dd1cd1bf1
parent4d363b5518dd6298b39653919828eb7d9061488c (diff)
mtd: cfi_cmdset_0002: Micron M29EW bugfixes as per TN-13-07
Fix the following issues with Micron's (formerly Numonyx) M29EW NOR flash chips, as documented on TN-13-07: - Correcting Erase Suspend Hang Ups (page 20) - Resolving the Delay After Resume Issue (page 22) Signed-off-by: Gerlando Falauto <gerlando.falauto@keymile.com> Signed-off-by: Artem Bityutskiy <Artem.Bityutskiy@linux.intel.com> Signed-off-by: David Woodhouse <David.Woodhouse@intel.com>
-rw-r--r--drivers/mtd/chips/cfi_cmdset_0002.c67
1 files changed, 67 insertions, 0 deletions
diff --git a/drivers/mtd/chips/cfi_cmdset_0002.c b/drivers/mtd/chips/cfi_cmdset_0002.c
index 22d0493a026f..5ff5c4a16943 100644
--- a/drivers/mtd/chips/cfi_cmdset_0002.c
+++ b/drivers/mtd/chips/cfi_cmdset_0002.c
@@ -431,6 +431,68 @@ static void cfi_fixup_major_minor(struct cfi_private *cfi,
431 } 431 }
432} 432}
433 433
434static int is_m29ew(struct cfi_private *cfi)
435{
436 if (cfi->mfr == CFI_MFR_INTEL &&
437 ((cfi->device_type == CFI_DEVICETYPE_X8 && (cfi->id & 0xff) == 0x7e) ||
438 (cfi->device_type == CFI_DEVICETYPE_X16 && cfi->id == 0x227e)))
439 return 1;
440 return 0;
441}
442
443/*
444 * From TN-13-07: Patching the Linux Kernel and U-Boot for M29 Flash, page 20:
445 * Some revisions of the M29EW suffer from erase suspend hang ups. In
446 * particular, it can occur when the sequence
447 * Erase Confirm -> Suspend -> Program -> Resume
448 * causes a lockup due to internal timing issues. The consequence is that the
449 * erase cannot be resumed without inserting a dummy command after programming
450 * and prior to resuming. [...] The work-around is to issue a dummy write cycle
451 * that writes an F0 command code before the RESUME command.
452 */
453static void cfi_fixup_m29ew_erase_suspend(struct map_info *map,
454 unsigned long adr)
455{
456 struct cfi_private *cfi = map->fldrv_priv;
457 /* before resume, insert a dummy 0xF0 cycle for Micron M29EW devices */
458 if (is_m29ew(cfi))
459 map_write(map, CMD(0xF0), adr);
460}
461
462/*
463 * From TN-13-07: Patching the Linux Kernel and U-Boot for M29 Flash, page 22:
464 *
465 * Some revisions of the M29EW (for example, A1 and A2 step revisions)
466 * are affected by a problem that could cause a hang up when an ERASE SUSPEND
467 * command is issued after an ERASE RESUME operation without waiting for a
468 * minimum delay. The result is that once the ERASE seems to be completed
469 * (no bits are toggling), the contents of the Flash memory block on which
470 * the erase was ongoing could be inconsistent with the expected values
471 * (typically, the array value is stuck to the 0xC0, 0xC4, 0x80, or 0x84
472 * values), causing a consequent failure of the ERASE operation.
473 * The occurrence of this issue could be high, especially when file system
474 * operations on the Flash are intensive. As a result, it is recommended
475 * that a patch be applied. Intensive file system operations can cause many
476 * calls to the garbage routine to free Flash space (also by erasing physical
477 * Flash blocks) and as a result, many consecutive SUSPEND and RESUME
478 * commands can occur. The problem disappears when a delay is inserted after
479 * the RESUME command by using the udelay() function available in Linux.
480 * The DELAY value must be tuned based on the customer's platform.
481 * The maximum value that fixes the problem in all cases is 500us.
482 * But, in our experience, a delay of 30 µs to 50 µs is sufficient
483 * in most cases.
484 * We have chosen 500µs because this latency is acceptable.
485 */
486static void cfi_fixup_m29ew_delay_after_resume(struct cfi_private *cfi)
487{
488 /*
489 * Resolving the Delay After Resume Issue see Micron TN-13-07
490 * Worst case delay must be 500µs but 30-50µs should be ok as well
491 */
492 if (is_m29ew(cfi))
493 cfi_udelay(500);
494}
495
434struct mtd_info *cfi_cmdset_0002(struct map_info *map, int primary) 496struct mtd_info *cfi_cmdset_0002(struct map_info *map, int primary)
435{ 497{
436 struct cfi_private *cfi = map->fldrv_priv; 498 struct cfi_private *cfi = map->fldrv_priv;
@@ -776,7 +838,10 @@ static void put_chip(struct map_info *map, struct flchip *chip, unsigned long ad
776 838
777 switch(chip->oldstate) { 839 switch(chip->oldstate) {
778 case FL_ERASING: 840 case FL_ERASING:
841 cfi_fixup_m29ew_erase_suspend(map,
842 chip->in_progress_block_addr);
779 map_write(map, cfi->sector_erase_cmd, chip->in_progress_block_addr); 843 map_write(map, cfi->sector_erase_cmd, chip->in_progress_block_addr);
844 cfi_fixup_m29ew_delay_after_resume(cfi);
780 chip->oldstate = FL_READY; 845 chip->oldstate = FL_READY;
781 chip->state = FL_ERASING; 846 chip->state = FL_ERASING;
782 break; 847 break;
@@ -916,6 +981,8 @@ static void __xipram xip_udelay(struct map_info *map, struct flchip *chip,
916 /* Disallow XIP again */ 981 /* Disallow XIP again */
917 local_irq_disable(); 982 local_irq_disable();
918 983
984 /* Correct Erase Suspend Hangups for M29EW */
985 cfi_fixup_m29ew_erase_suspend(map, adr);
919 /* Resume the write or erase operation */ 986 /* Resume the write or erase operation */
920 map_write(map, cfi->sector_erase_cmd, adr); 987 map_write(map, cfi->sector_erase_cmd, adr);
921 chip->state = oldstate; 988 chip->state = oldstate;