[U-Boot] CFI Driver Problem: flash not ready

Hi,
while tryong to convert the TQM8260 board to using the CFI flash driver (instead of a perfectly working legacy flash driver) I ran into a strange problem: after an erase operation, the CFI driver returns without any error indication, but the flash is not ready yet. It takes some more milliseconds before the flash gets ready - by then it's indeed erased, but this behaviour makes things like "saveenv" or any "erase;cp" command sequences fail with a "Flash not Erased" error message.
Symptoms look like this:
=> md 40300000 10 ; era 40300000 +1 ; md 40300000 ; echo ===== ; sleep 1 ; md 40300000 40300000: 19852003 0000000c f060dc98 ffffffff .. ......`...... 40300010: ffffffff ffffffff ffffffff ffffffff ................ 40300020: ffffffff ffffffff ffffffff ffffffff ................ 40300030: ffffffff ffffffff ffffffff ffffffff ................
. done Erased 1 sectors 40300000: 004c004c 00080008 004c004c 00080008 .L.L.....L.L.... 40300010: 004c004c 00080008 004c004c 00080008 .L.L.....L.L.... 40300020: 004c004c 00080008 004c004c 00080008 .L.L.....L.L.... 40300030: 004c004c 00080008 004c004c 00080008 .L.L.....L.L.... ===== 40300000: ffffffff ffffffff ffffffff ffffffff ................ 40300010: ffffffff ffffffff ffffffff ffffffff ................ 40300020: ffffffff ffffffff ffffffff ffffffff ................ 40300030: ffffffff ffffffff ffffffff ffffffff ................ =>
The board uses 4 x 29LV652UE-90 flash chips for a single 32 MiB flash bank, 64 bit wide; the old legacy driver showed:
Bank # 1: FUJITSU 29LV640D (64 M, uniform sector) Size: 32 MB in 128 Sectors
The CFI driver says:
Bank # 1: CFI conformant FLASH (64 x 16) Size: 32 MB in 128 Sectors AMD Standard command set, Manufacturer ID: 0x04, Device ID: 0x22D7 Erase timeout: 16384 ms, write timeout: 1 ms
CFI debugging shows nothing unusual (at least as far as I can tell):
... FLASH: flash detect cfi fwc addr 40000000 cmd f0 f0 8bit x 8 bit fwc addr 40000000 cmd ff ff 8bit x 8 bit fwc addr 40000055 cmd 98 98 8bit x 8 bit is= cmd 51(Q) addr 40000010 is= 80 51 fwc addr 40000555 cmd 98 98 8bit x 8 bit is= cmd 51(Q) addr 40000010 is= 80 51 fwc addr 40000000 cmd f0 f0f0 16bit x 8 bit fwc addr 40000000 cmd ff ffff 16bit x 8 bit fwc addr 400000aa cmd 98 9898 16bit x 8 bit is= cmd 51(Q) addr 40000020 is= 0000 5151 fwc addr 40000aaa cmd 98 9898 16bit x 8 bit is= cmd 51(Q) addr 40000020 is= 0000 5151 fwc addr 40000000 cmd f0 00f0 16bit x 16 bit fwc addr 40000000 cmd ff 00ff 16bit x 16 bit fwc addr 400000aa cmd 98 0098 16bit x 16 bit is= cmd 51(Q) addr 40000020 is= 0000 0051 fwc addr 40000aaa cmd 98 0098 16bit x 16 bit is= cmd 51(Q) addr 40000020 is= 0000 0051 fwc addr 40000000 cmd f0 f0f0f0f0 32bit x 8 bit fwc addr 40000000 cmd ff ffffffff 32bit x 8 bit fwc addr 40000154 cmd 98 98989898 32bit x 8 bit is= cmd 51(Q) addr 40000040 is= 00000000 51515151 fwc addr 40001554 cmd 98 98989898 32bit x 8 bit is= cmd 51(Q) addr 40000040 is= 00000000 51515151 fwc addr 40000000 cmd f0 00f000f0 32bit x 16 bit fwc addr 40000000 cmd ff 00ff00ff 32bit x 16 bit fwc addr 40000154 cmd 98 00980098 32bit x 16 bit is= cmd 51(Q) addr 40000040 is= 00000000 00510051 fwc addr 40001554 cmd 98 00980098 32bit x 16 bit is= cmd 51(Q) addr 40000040 is= 00000000 00510051 fwc addr 40000000 cmd f0 000000f0 32bit x 32 bit fwc addr 40000000 cmd ff 000000ff 32bit x 32 bit fwc addr 40000154 cmd 98 00000098 32bit x 32 bit is= cmd 51(Q) addr 40000040 is= 00000000 00000051 fwc addr 40001554 cmd 98 00000098 32bit x 32 bit is= cmd 51(Q) addr 40000040 is= 00000000 00000051 fwrite addr 40000000 cmd f0 f0f0f0f0f0f0f0f0 64 bit x 8 bit fwrite addr 40000000 cmd ff ffffffffffffffff 64 bit x 8 bit fwrite addr 400002a8 cmd 98 9898989898989898 64 bit x 8 bit is= cmd 51(Q) addr 40000080 is= 0051005100510051 5151515151515151 fwrite addr 40002aa8 cmd 98 9898989898989898 64 bit x 8 bit is= cmd 51(Q) addr 40000080 is= 0051005100510051 5151515151515151 fwrite addr 40000000 cmd f0 00f000f000f000f0 64 bit x 16 bit fwrite addr 40000000 cmd ff 00ff00ff00ff00ff 64 bit x 16 bit fwrite addr 400002a8 cmd 98 0098009800980098 64 bit x 16 bit is= cmd 51(Q) addr 40000080 is= 0051005100510051 0051005100510051 is= cmd 52(R) addr 40000088 is= 0052005200520052 0052005200520052 is= cmd 59(Y) addr 40000090 is= 0059005900590059 0059005900590059 device interface is 1 found port 8 chip 2 port 64 bits chip 16 bits 00 : 51 52 59 02 00 40 00 00 00 00 00 27 36 00 00 04 QRY..@.....'6... 10 : 00 0a 00 05 00 04 00 17 01 00 00 00 01 7f 00 00 ................ 20 : 01 00 00 00 00 00 00 00 00 00 00 00 00 ff ff ff ................ fwrite addr 40000000 cmd f0 00f000f000f000f0 64 bit x 16 bit fwrite addr 40002aa8 cmd aa 00aa00aa00aa00aa 64 bit x 16 bit fwrite addr 40001550 cmd 55 0055005500550055 64 bit x 16 bit fwrite addr 40002aa8 cmd 90 0090009000900090 64 bit x 16 bit fwrite addr 40000000 cmd f0 00f000f000f000f0 64 bit x 16 bit fwrite addr 400002a8 cmd 98 0098009800980098 64 bit x 16 bit manufacturer is 2 manufacturer id is 0x4 device id is 0x22d7 device id2 is 0x0 cfi version is 0x3131 size_ratio 4 port 64 bits chip 16 bits found 1 erase regions erase region 0: 0x0100007f erase_region_count = 128 erase_region_size = 65536 fwrite addr 40000000 cmd f0 00f000f000f000f0 64 bit x 16 bit 32 MB
The test from above with debug enabled looks like this:
=> md 40300000 10 ; era 40300000 +1 ; md 40300000 ; echo ===== ; sleep 1 ; md 40300000 40300000: 19852003 0000000c f060dc98 ffffffff .. ......`...... 40300010: ffffffff ffffffff ffffffff ffffffff ................ 40300020: ffffffff ffffffff ffffffff ffffffff ................ 40300030: ffffffff ffffffff ffffffff ffffffff ................
fwrite addr 40302aa8 cmd aa 00aa00aa00aa00aa 64 bit x 16 bit fwrite addr 40301550 cmd 55 0055005500550055 64 bit x 16 bit fwrite addr 40302aa8 cmd 80 0080008000800080 64 bit x 16 bit fwrite addr 40302aa8 cmd aa 00aa00aa00aa00aa 64 bit x 16 bit fwrite addr 40301550 cmd 55 0055005500550055 64 bit x 16 bit fwrite addr 40300000 cmd 30 0030003000300030 64 bit x 16 bit flash_is_busy: 0 . done Erased 1 sectors 40300000: 004c004c 00080008 004c004c 00080008 .L.L.....L.L.... 40300010: 004c004c 00080008 004c004c 00080008 .L.L.....L.L.... 40300020: 004c004c 00080008 004c004c 00080008 .L.L.....L.L.... 40300030: 004c004c 00080008 004c004c 00080008 .L.L.....L.L.... ===== 40300000: ffffffff ffffffff ffffffff ffffffff ................ 40300010: ffffffff ffffffff ffffffff ffffffff ................ 40300020: ffffffff ffffffff ffffffff ffffffff ................ 40300030: ffffffff ffffffff ffffffff ffffffff ................ =>
Why the heck does flash_is_busy() return 0 when the flashobviously is still busy?
Thanks in advance.
Best regards,
Wolfgang Denk

Hi Wolfgang,
Why the heck does flash_is_busy() return 0 when the flashobviously is still busy?
Does this use the toggle bit detection? I saw the same symptoms with Nios II. Basically, the memory controller was reading the 16-bit flash twice to obtain a full 32-bit word, then returning just the first 16-bits. So, I would never see the toggle bit changing.
Not sure if this is similar to your situation ... but it was a real pain-in-the-butt to finally understand what was happening in my situation.
Regards, --Scott

Dear Scott,
In message 48FBADA6.3090505@psyent.com you wrote:
Why the heck does flash_is_busy() return 0 when the flashobviously is still busy?
Does this use the toggle bit detection? I saw the same symptoms
Hm... how can I tell if it does?
The driver reports "AMD Standard command set", so it probably does.
with Nios II. Basically, the memory controller was reading the 16-bit flash twice to obtain a full 32-bit word, then returning just the first 16-bits. So, I would never see the toggle bit changing.
Well, I see that no real 64 bit accesses are used, so I think we will here see two 32 bit accesses to get the full 64 bit data, and probably the same thin happens.
Not sure if this is similar to your situation ... but it was a real pain-in-the-butt to finally understand what was happening in my situation.
And how did you fix it?
Best regards,
Wolfgang Denk

Dear Scott,
In message 48FBADA6.3090505@psyent.com you wrote:
Why the heck does flash_is_busy() return 0 when the flashobviously is still busy?
Does this use the toggle bit detection? I saw the same symptoms with Nios II. Basically, the memory controller was reading the 16-bit flash twice to obtain a full 32-bit word, then returning just the first 16-bits. So, I would never see the toggle bit changing.
Not sure if this is similar to your situation ... but it was a real pain-in-the-butt to finally understand what was happening in my situation.
My situation is indeed similar. The 64 bit read (which is supposed to be implemented by flash_read64()) is in fact broken downinto two 32 bit reads, with the consequence that flash_toggle() does not work any more, because of reading the *same* addresses twice we are reading alternate addresses (addr, addr+4, addr, addr+4).
This patch fixes the problem for me:
diff --git a/drivers/mtd/cfi_flash.c b/drivers/mtd/cfi_flash.c index c40bf66..24e9b9f 100644 --- a/drivers/mtd/cfi_flash.c +++ b/drivers/mtd/cfi_flash.c @@ -596,7 +596,8 @@ static int flash_toggle (flash_info_t * info, flash_sect_t sect, retval = flash_read32(addr) != flash_read32(addr); break; case FLASH_CFI_64BIT: - retval = flash_read64(addr) != flash_read64(addr); + retval = ( (flash_read32( addr ) != flash_read32( addr )) || + (flash_read32(addr+4) != flash_read32(addr+4)) ); break; default: retval = 0;
However, I'm not really happy about this. Maybe we should really implement an atomic 64 bit read operation for flash_read64()? But the only solution I could come up for this would be pretty complex:
save MSR; set Floating Point enable bit in MSR; use "lfd" instruction to perform atomic 64 bit read; use "stfd" to store value to temporary variable on stack; load u64 from temporary variable; restore saved MSR; return u64 value;
Is this worth the trouble?
Is it valid to assume that a processor which has the flashon a 64 bit bus will also have a FPU?
Would ne need to save/restore the FP register used here?
Best regards,
Wolfgang Denk

Wolfgang Denk wrote:
Why the heck does flash_is_busy() return 0 when the flashobviously is still busy?
flash_is_busy() implements the toggling check. Of course, it should work, but I remember I had in the past a similar problem and I switched to the DQ7 bit algorithm (for erasing, it means I checked 0xFF for the whole bus width). Linux mtd does not implement the toggling algorithm to check if the flash is erased and it relies on the values read from the flash. Could be a solution to add a check for 0xFF in cfi_flash.c:flash_erase() after flash_full_status_check() returns successfully ?
Best regards, Stefano Babic

I ran into this symptom once. In that instance a compiler bug caused 'volatile' not to be honored when there were two reads in a single expression, so it read the status only once and saw no toggle. The workaround was to split the expression to two statements so each read was in a different statement (the compiler has since been fixed). Check your generated ASM code.
Ross Morley
Wolfgang Denk wrote:
Hi,
while tryong to convert the TQM8260 board to using the CFI flash driver (instead of a perfectly working legacy flash driver) I ran into a strange problem: after an erase operation, the CFI driver returns without any error indication, but the flash is not ready yet. It takes some more milliseconds before the flash gets ready - by then it's indeed erased, but this behaviour makes things like "saveenv" or any "erase;cp" command sequences fail with a "Flash not Erased" error message.
Symptoms look like this:
=> md 40300000 10 ; era 40300000 +1 ; md 40300000 ; echo ===== ; sleep 1 ; md 40300000 40300000: 19852003 0000000c f060dc98 ffffffff .. ......`...... 40300010: ffffffff ffffffff ffffffff ffffffff ................ 40300020: ffffffff ffffffff ffffffff ffffffff ................ 40300030: ffffffff ffffffff ffffffff ffffffff ................
. done Erased 1 sectors 40300000: 004c004c 00080008 004c004c 00080008 .L.L.....L.L.... 40300010: 004c004c 00080008 004c004c 00080008 .L.L.....L.L.... 40300020: 004c004c 00080008 004c004c 00080008 .L.L.....L.L.... 40300030: 004c004c 00080008 004c004c 00080008 .L.L.....L.L.... ===== 40300000: ffffffff ffffffff ffffffff ffffffff ................ 40300010: ffffffff ffffffff ffffffff ffffffff ................ 40300020: ffffffff ffffffff ffffffff ffffffff ................ 40300030: ffffffff ffffffff ffffffff ffffffff ................ =>
The board uses 4 x 29LV652UE-90 flash chips for a single 32 MiB flash bank, 64 bit wide; the old legacy driver showed:
Bank # 1: FUJITSU 29LV640D (64 M, uniform sector) Size: 32 MB in 128 Sectors
The CFI driver says:
Bank # 1: CFI conformant FLASH (64 x 16) Size: 32 MB in 128 Sectors AMD Standard command set, Manufacturer ID: 0x04, Device ID: 0x22D7 Erase timeout: 16384 ms, write timeout: 1 ms
CFI debugging shows nothing unusual (at least as far as I can tell):
... FLASH: flash detect cfi fwc addr 40000000 cmd f0 f0 8bit x 8 bit fwc addr 40000000 cmd ff ff 8bit x 8 bit fwc addr 40000055 cmd 98 98 8bit x 8 bit is= cmd 51(Q) addr 40000010 is= 80 51 fwc addr 40000555 cmd 98 98 8bit x 8 bit is= cmd 51(Q) addr 40000010 is= 80 51 fwc addr 40000000 cmd f0 f0f0 16bit x 8 bit fwc addr 40000000 cmd ff ffff 16bit x 8 bit fwc addr 400000aa cmd 98 9898 16bit x 8 bit is= cmd 51(Q) addr 40000020 is= 0000 5151 fwc addr 40000aaa cmd 98 9898 16bit x 8 bit is= cmd 51(Q) addr 40000020 is= 0000 5151 fwc addr 40000000 cmd f0 00f0 16bit x 16 bit fwc addr 40000000 cmd ff 00ff 16bit x 16 bit fwc addr 400000aa cmd 98 0098 16bit x 16 bit is= cmd 51(Q) addr 40000020 is= 0000 0051 fwc addr 40000aaa cmd 98 0098 16bit x 16 bit is= cmd 51(Q) addr 40000020 is= 0000 0051 fwc addr 40000000 cmd f0 f0f0f0f0 32bit x 8 bit fwc addr 40000000 cmd ff ffffffff 32bit x 8 bit fwc addr 40000154 cmd 98 98989898 32bit x 8 bit is= cmd 51(Q) addr 40000040 is= 00000000 51515151 fwc addr 40001554 cmd 98 98989898 32bit x 8 bit is= cmd 51(Q) addr 40000040 is= 00000000 51515151 fwc addr 40000000 cmd f0 00f000f0 32bit x 16 bit fwc addr 40000000 cmd ff 00ff00ff 32bit x 16 bit fwc addr 40000154 cmd 98 00980098 32bit x 16 bit is= cmd 51(Q) addr 40000040 is= 00000000 00510051 fwc addr 40001554 cmd 98 00980098 32bit x 16 bit is= cmd 51(Q) addr 40000040 is= 00000000 00510051 fwc addr 40000000 cmd f0 000000f0 32bit x 32 bit fwc addr 40000000 cmd ff 000000ff 32bit x 32 bit fwc addr 40000154 cmd 98 00000098 32bit x 32 bit is= cmd 51(Q) addr 40000040 is= 00000000 00000051 fwc addr 40001554 cmd 98 00000098 32bit x 32 bit is= cmd 51(Q) addr 40000040 is= 00000000 00000051 fwrite addr 40000000 cmd f0 f0f0f0f0f0f0f0f0 64 bit x 8 bit fwrite addr 40000000 cmd ff ffffffffffffffff 64 bit x 8 bit fwrite addr 400002a8 cmd 98 9898989898989898 64 bit x 8 bit is= cmd 51(Q) addr 40000080 is= 0051005100510051 5151515151515151 fwrite addr 40002aa8 cmd 98 9898989898989898 64 bit x 8 bit is= cmd 51(Q) addr 40000080 is= 0051005100510051 5151515151515151 fwrite addr 40000000 cmd f0 00f000f000f000f0 64 bit x 16 bit fwrite addr 40000000 cmd ff 00ff00ff00ff00ff 64 bit x 16 bit fwrite addr 400002a8 cmd 98 0098009800980098 64 bit x 16 bit is= cmd 51(Q) addr 40000080 is= 0051005100510051 0051005100510051 is= cmd 52(R) addr 40000088 is= 0052005200520052 0052005200520052 is= cmd 59(Y) addr 40000090 is= 0059005900590059 0059005900590059 device interface is 1 found port 8 chip 2 port 64 bits chip 16 bits 00 : 51 52 59 02 00 40 00 00 00 00 00 27 36 00 00 04 QRY..@.....'6... 10 : 00 0a 00 05 00 04 00 17 01 00 00 00 01 7f 00 00 ................ 20 : 01 00 00 00 00 00 00 00 00 00 00 00 00 ff ff ff ................ fwrite addr 40000000 cmd f0 00f000f000f000f0 64 bit x 16 bit fwrite addr 40002aa8 cmd aa 00aa00aa00aa00aa 64 bit x 16 bit fwrite addr 40001550 cmd 55 0055005500550055 64 bit x 16 bit fwrite addr 40002aa8 cmd 90 0090009000900090 64 bit x 16 bit fwrite addr 40000000 cmd f0 00f000f000f000f0 64 bit x 16 bit fwrite addr 400002a8 cmd 98 0098009800980098 64 bit x 16 bit manufacturer is 2 manufacturer id is 0x4 device id is 0x22d7 device id2 is 0x0 cfi version is 0x3131 size_ratio 4 port 64 bits chip 16 bits found 1 erase regions erase region 0: 0x0100007f erase_region_count = 128 erase_region_size = 65536 fwrite addr 40000000 cmd f0 00f000f000f000f0 64 bit x 16 bit 32 MB
The test from above with debug enabled looks like this:
=> md 40300000 10 ; era 40300000 +1 ; md 40300000 ; echo ===== ; sleep 1 ; md 40300000 40300000: 19852003 0000000c f060dc98 ffffffff .. ......`...... 40300010: ffffffff ffffffff ffffffff ffffffff ................ 40300020: ffffffff ffffffff ffffffff ffffffff ................ 40300030: ffffffff ffffffff ffffffff ffffffff ................
fwrite addr 40302aa8 cmd aa 00aa00aa00aa00aa 64 bit x 16 bit fwrite addr 40301550 cmd 55 0055005500550055 64 bit x 16 bit fwrite addr 40302aa8 cmd 80 0080008000800080 64 bit x 16 bit fwrite addr 40302aa8 cmd aa 00aa00aa00aa00aa 64 bit x 16 bit fwrite addr 40301550 cmd 55 0055005500550055 64 bit x 16 bit fwrite addr 40300000 cmd 30 0030003000300030 64 bit x 16 bit flash_is_busy: 0 . done Erased 1 sectors 40300000: 004c004c 00080008 004c004c 00080008 .L.L.....L.L.... 40300010: 004c004c 00080008 004c004c 00080008 .L.L.....L.L.... 40300020: 004c004c 00080008 004c004c 00080008 .L.L.....L.L.... 40300030: 004c004c 00080008 004c004c 00080008 .L.L.....L.L.... ===== 40300000: ffffffff ffffffff ffffffff ffffffff ................ 40300010: ffffffff ffffffff ffffffff ffffffff ................ 40300020: ffffffff ffffffff ffffffff ffffffff ................ 40300030: ffffffff ffffffff ffffffff ffffffff ................ =>
Why the heck does flash_is_busy() return 0 when the flashobviously is still busy?
Thanks in advance.
Best regards,
Wolfgang Denk
participants (4)
-
Ross Morley
-
Scott McNutt
-
stefano babic
-
Wolfgang Denk