cfi_cmdset_0001.c: Excessive erase suspends
Anders Grafström
grfstrm at users.sourceforge.net
Sat Apr 19 09:47:24 EDT 2008
Joakim Tjernlund wrote:
> Don't you need to check that the chip is suspended before you do any
> new operation?
You're right.
Here's the improved version;
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
5500 loops
status 00800080
5508 suspends
5000 loops
status 008000a0
6394 suspends
4500 loops
status 00a000a0
fffffeff
fffffffe
5169 suspends
4000 loops
status 00a000a0
fffffeff
fffffeff
5378 suspends
3500 loops
status 00a000a0
aaaaaaaa
aaaaaaaa
5715 suspends
3000 loops
status 00a000a0
55555555
55555555
6142 suspends
2500 loops
status 00a000a0
00000000
00000000
6929 suspends
It locks up when I drop it down to 2000 or less iterations in the loop between resume and suspend.
I think I need to do more testing with properly timed delays.
Is there anything else that I have missed?
/Anders
More information about the linux-mtd
mailing list