Numonyx NOR and chip->mutex bug?
Joakim Tjernlund
joakim.tjernlund at transmode.se
Thu Feb 24 06:36:00 EST 2011
>
> Anders Grafström <grfstrm at users.sourceforge.net> wrote on 2011/02/10 14:21:36:
> >
> > On 2011-02-09 22:59, Michael Cashwell wrote:
> > > On Feb 9, 2011, at 3:13 PM, Joakim Tjernlund wrote:
> > >
> > >> hmm, this sounds similar(from http://www.numonyx.com/Documents/Specification%20Updates/SU-309045_P30.pdf)
> > >>
> > >> 5. W602: erase suspend resume operation
> > >> Problem: P30 product may fail to erase in intensive erase/suspend/resume environments. This is
> > >> due to an internal firmware issue that is exhibited in certain applications that require at
> > >> least 3000 to 4000 erase/suspend/resume cycles during the erase of a single block.
> > >> Implication: Customer may see erase failure (SR reports “A0”) during a background erase. This
> > >> does not damage the device in any way, but data in the block may be disturbed from its
> > >> original state.
> >
> > I've seen this issue with Intel 28F640J5 chips as well.
> >
> > There's an old thread on it.
> > http://lists.infradead.org/pipermail/linux-mtd/2008-April/021266.html
> >
> > A delay was suggested similar to the one you're experimenting with I think.
> > http://lists.infradead.org/pipermail/linux-mtd/2008-April/021436.html
>
> Been a while but it just occurred to me that you might see something similar as
> Michael.
>
> This program of yours:
>
> static void erase_suspend(unsigned int loops)
> {
> volatile unsigned int *flash = (unsigned int *)0x41040000;
> unsigned int i;
> unsigned int suspends = 0;
> unsigned int words = 2;
> unsigned int timeout;
>
> /* Make sure there's something to erase */
> for (i = 0; i < 0x10000; i++) {
> if (flash[i] == 0xffffffff) {
> flash[i] = 0x00400040;
> flash[i] = 0;
> while ((flash[i] & 0x00800080) != 0x00800080);
> }
> }
>
> /* Clear status */
> flash[0] = 0x00500050;
>
> /* Erase */
> flash[0] = 0x00200020;
> flash[0] = 0x00d000d0;
>
> while (1) {
> /* Suspend */
> flash[0] = 0x00b000b0;
> flash[0] = 0x00700070;
> timeout = 100000;
> while ((flash[0] & 0x00800080) != 0x00800080 && --timeout);
> if (!timeout)
> printf("suspend timeout\n");
> suspends++;
>
> /* Short delay */
> for (i = 0; i < 1000; i++);
>
> /* Resume */
> flash[0] = 0x00d000d0;
> flash[0] = 0x00700070;
>
> /* Erase done ? */
> if ((flash[0] & 0x00800080) == 0x00800080) {
> printf("\nstatus %08x\n", flash[0]);
> break;
> }
>
> /* Short delay */
> for (i = 0; i < loops; i++);
> }
>
> /* Read array */
> flash[0] = 0x00ff00ff;
>
> /* Show the first 2 failed words */
> for (i = 0; i < 0x10000; i++) {
> if (flash[i] != 0xffffffff) {
> printf("%08x\n", flash[i]);
> if (--words == 0)
> break;
> }
> }
>
> printf("%d suspends\n", suspends);
> }
>
> void test_flash_erase_suspend(void)
> {
> unsigned int loops;
>
> for (loops = 6000; loops > 2000; loops -= 500) {
> printf("\n%d loops", loops);
> erase_suspend(loops);
> }
> }
>
>
> It produced this output at one occasion:
>
> 6000 loops
> status 00800080
> ffff0000
> ffff0000
> 4783 suspends
> ---------------------
> See the status 00800080 ?
> Looking at the code this should not be possible, right?
ehh, looking at my own post I see that I misread == as !=
> looking closer though it becomes clearer:
>
> if ((flash[0] & 0x00800080) == 0x00800080) {
> printf("\nstatus %08x\n", flash[0]);
> break;
> }
> There are two status reads here, one where you test and one where you
> print. I suspect that if you add a dummy status read like Michael need to do:
> stat = flash[0]; /* dummy, will contain garbage sometimes */
> stat = flash[0];
> if ((stat & 0x00800080) == 0x00800080) {
> printf("\nstatus %08x\n", stat);
> break;
> }
> You will see an improvement.
>
> Michael, have you made any progress? Can you run Anders program too?
>
> Jocke
>
>
> ______________________________________________________
> Linux MTD discussion mailing list
> http://lists.infradead.org/mailman/listinfo/linux-mtd/
More information about the linux-mtd
mailing list