[U-Boot-Users] [PATCH] Fixed cfi flash read uchar bug.

Tolunay Orkun
2007-02-01T05:26:08Z

Haiying Wang wrote:
> ------------
> U-Boot 1.2.0 (Jan 31 2007 - 13:12:04)
>
> Freescale PowerPC
> CPU:
> Core: E600, Version: 0.2, (0x80040202)
> System: 8641D, Version: 2.0, (0x80900120)
> Clocks: CPU:1000 MHz, MPX: 400 MHz, DDR: 200 MHz, LBC: 50 MHz
> L2: Enabled

Pretty fast CPU you've got here :)

> Board: MPC8641HPCN
> PCI-EXPRESS1: Disabled
> I2C: ready
> DRAM: DDR: 256 MB
> FLASH: ## Unknown FLASH on Bank 1 - Size = 0x00000000 = 0 MB

It looks like you inserted the debug prints in wrong place. The output
below should have been after the debug stuff. Anyway...

> chipwidth = 2
> portwidth = 2
> interface = 1
> vendor = 0
> cfi_offset= 85
> manufacturer_id = 1
> device_id = 126
> device_id2 = 4865

Except for "vendor" everything looks OK here. I should have asked you to
print vendor right before flash_read_jedec_ids() call. It was not yet
initialized when printed. It must be correctly set as well since
flash_read_jedec_ids() uses it would not have returned correct data
otherwise.

You have a 16-bit flash accessible on 16-bit bus. The flash manufacturer
is "AMD/Spansion" or compatible and device id is 7E1301 which is correct
for your part:

http://www.amd.com/us-en/assets/content_type/white_papers_and_tech_docs/25538a1.pdf

Please note that flash_read_jedec_ids() is used for manufacturer id and
device_ids and this function in turn is using flash_read_uchar() which
worked just fine for you.

> 124 erase regions found, only 4 used

This is not correct. This is why you are blaming the flash_read_uchar()
function. But since it worked correctly before the failure to read the
number of erase regions is probably not due to the function.

>> Also try replacing following line in flash_detect_cfi() function:
>>
>> flash_write_cmd (info, 0, 0, info->cmd_reset);
>>
>> with the following two lines:
>>
>> flash_write_cmd(info, 0, 0, FLASH_CMD_RESET);
>> flash_write_cmd(info, 0, 0, AMD_CMD_RESET);

You demonstrated that this did not affect you because the output was the
same. The problem with this line was that info->cmd_reset was not yet
initialized when flash_detect_cfi() was called. This is a minor bug
since the flash was not in query mode yet. I think we can safely remove
this call as well or replace it both amd anf intel reset commands back
to back. But anyway, back to your issue.

>> If you are suspecting that the flash is not in array read mode after
>> flash_read_jedec_ids() you can easily dump the first 256 bytes of flash
>> right after [write a simple hexdump routine].
>>
>>> this function, a flash_write_cmd() follows it, then the flash_read_uchar
>> After this command, the flash should be in cfi_read mode. Hexdump the
>> first 256 bytes again. You should be able to spot easily if you landed
>> in cfi query mode or not. These are crucial before you put the blame on
>> flash_read_uchar().
> Then I dump the first 256bytes of flash, first after
> flash_read_jedec_ids(), then after flash_write_cmd(), see log:
>
> -------
> U-Boot 1.2.0 (Jan 31 2007 - 13:46:59)
>
> Freescale PowerPC
> CPU:
> Core: E600, Version: 0.2, (0x80040202)
> System: 8641D, Version: 2.0, (0x80900120)
> Clocks: CPU:1000 MHz, MPX: 400 MHz, DDR: 200 MHz, LBC: 50 MHz
> L2: Enabled
> Board: MPC8641HPCN
> PCI-EXPRESS1: Disabled
> I2C: ready
> DRAM: DDR: 256 MB
> FLASH: ## Unknown FLASH on Bank 1 - Size = 0x00000000 = 0 MB
> chipwidth = 2
> portwidth = 2
> interface = 1
> vendor = 0
> cfi_offset= 85
>
> Dump the first 256 byte of flash
> 27 05 19 56 26 6c 3d b3 44 e4 ae 15 00 2b 05 33
> 00 00 00 00 00 00 00 00 35 b6 3f 82 05 07 03 01
> 75 62 6f 6f 74 20 65 78 74 32 20 72 61 6d 64 69
> 73 6b 20 72 6f 6f 74 66 73 00 00 00 00 00 00 00
> 1f 8b 08 08 14 ae e4 44 00 03 72 6f 6f 74 66 73
> 2e 65 78 74 32 00 ec 9d 09 7c 15 d5 bd c7 cf dc
> dc dc 24 17 ac 97 a5 42 2b 68 dc 65 11 90 35 09
> 01 c2 22 6a 45 45 dc 00 17 92 90 00 d1 6c 26 81
> 62 ab 08 56 ad 5a 17 5a ad 5b 7d 16 7d f6 55 5b
> b5 58 ab e0 52 1b 97 56 6c 51 41 01 51 2c 82 62
> b5 28 02 ae d4 2e be ef ff ce 19 e6 04 6e ca e4
> 35 e3 f4 d5 f3 e7 f3 e5 cc ff ce b9 f3 9b 73 ce
> ff 2c 73 73 ef 8c 52 d6 ac 59 fb b2 5a 2a 4b a9
> 1e 87 29 f5 91 a3 d4 7d b9 4a fd 95 d7 1c 63 ff
> c2 2e 2e 97 9b 2f aa ae ea e4 ad 8e b2 66 cd da
> ff 6f a3 fb ab 38 64 a7 bd 79 6a df 5d f6 5f 47
> manufacturer_id = 1
> device_id = 126
> device_id2 = 4865
>
> Dump the first 256 byte of flash
> 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
> 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
> 00 51 00 52 00 59 00 02 00 00 00 40 00 00 00 00
> 00 00 00 00 00 00 00 27 00 36 00 00 00 00 00 07
> 00 07 00 0a 00 00 00 01 00 05 00 04 00 00 00 17
> 00 01 00 00 00 05 00 00 00 01 00 7f 00 00 00 00
> 00 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00
> 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
> 00 50 00 52 00 49 00 31 00 33 00 08 00 02 00 04
> 00 01 00 04 00 00 00 00 00 01 00 b5 00 c5 00 05
> 00 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00
> 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 02
> 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
> 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
> 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
> 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 01

Guess what this looks like a valid CFI table now. I can definitely see Q
= 0x51, R = 0x52, Y = 0x59 etc. in the correct places.

> 8 MB

It looks like the rest of the commands worked as well :) All without
changing flash_read_uchar() functionality!

> Using default environment
>
> In: serial
> Out: serial
> Err: serial
> Net: eTSEC1, eTSEC2, eTSEC3, eTSEC4
> Hit any key to stop autoboot: 0
> =>
> -------
> This time, the flash got the correct size and can be accessed. I think
> the second dump()function I added made it work, as it worked when I
> inserted a udelay after flash_write_cmd().

At this point, all data indicates that flash_read_uchar() is just fine.

I am suspecting two things:

1) Your CPU might be trying to re-order writes and reads to optimize
performance. Since the command write and data read are from different
addresses it could do this but the write command should really finish
before we access the table data. So, we might need to add powerpc "sync"
instructions in flash_write_cmd() function. Apparently CONFIG_BLACKFIN
has a similar need as well. I would add a generic "sync" for the whole
PowerPC family but there is not a conveninent CONFIG_POWERPC macro as
far as I can see. Anyway, try adding:

asm("sync;");

statements in that function. Use Blackfin as an example.

2) Because you have a rather fast CPU it is possible that we are not
allowing enough time after reset command is executed before array is in
read mode. According to the datasheet of your flash part if external
reset signal was asserted you could need up to 20usec before flash
returns to read mode. I am not sure if this delay is needed for issued
reset commands as well. We might need to add some delay after flash
reset commands. Try adding udelay(100); right after flash reset command
is sent. You can locate flash reset commands by searching
flash_write_cmd() statements that passes FLASH_CMD_RESET, AMD_CMD_RESET
or cfi->cmd_reset as the last argument.

> Please shed some lights. Thanks a lot!

I hope this helps.

Best regards,
Tolunay