Skip to content

Commit

Permalink
mtd: fix recovery after failed write-buffer operation in cfi_cmdset_0…
Browse files Browse the repository at this point in the history
…002.c

When working on a problem with some flash chips that lock up during
write-buffer operations, I think there may be a bug in the linux
handling of chips using cfi_cmdset_0002.c.

The datasheets I have found for a number of these chips all specify that
when aborting a write-buffer command, it is not enough to use the
standard reset.  Rather a "write-to-buffer-reset command" is needed.
This command is quite similar for all chips, the main variance seem to
be if the final 0xF0 can go to any address or must go to addr_unlock1.

The bug is then in the recovery handling when timing out at the end of
do_write_buffer, where using the normal reset command is not sufficient.

Without this change, if the write-buffer command fails then any
following operations on the flash also fail.

Signed-off-by: Harald Nordgard-Hansen <hhansen@pvv.org>
Signed-off-by: Artem Bityutskiy <artem.bityutskiy@linux.intel.com>
  • Loading branch information
Harald Nordgard-Hansen authored and Artem Bityutskiy committed Dec 3, 2012
1 parent ff3206b commit 070c322
Showing 1 changed file with 14 additions and 2 deletions.
16 changes: 14 additions & 2 deletions drivers/mtd/chips/cfi_cmdset_0002.c
Original file line number Diff line number Diff line change
Expand Up @@ -1536,8 +1536,20 @@ static int __xipram do_write_buffer(struct map_info *map, struct flchip *chip,
UDELAY(map, chip, adr, 1);
}

/* reset on all failures. */
map_write( map, CMD(0xF0), chip->start );
/*
* Recovery from write-buffer programming failures requires
* the write-to-buffer-reset sequence. Since the last part
* of the sequence also works as a normal reset, we can run
* the same commands regardless of why we are here.
* See e.g.
* http://www.spansion.com/Support/Application%20Notes/MirrorBit_Write_Buffer_Prog_Page_Buffer_Read_AN.pdf
*/
cfi_send_gen_cmd(0xAA, cfi->addr_unlock1, chip->start, map, cfi,
cfi->device_type, NULL);
cfi_send_gen_cmd(0x55, cfi->addr_unlock2, chip->start, map, cfi,
cfi->device_type, NULL);
cfi_send_gen_cmd(0xF0, cfi->addr_unlock1, chip->start, map, cfi,
cfi->device_type, NULL);
xip_enable(map, chip, adr);
/* FIXME - should have reset delay before continuing */

Expand Down

0 comments on commit 070c322

Please sign in to comment.