[U-Boot] Mixed 8/16 bits NOR FLASH support (was: [PATCH V2 3/3] Add support for the LaCie ED Mini V2 board)

Albert ARIBAUD
2009-12-02T08:31:43Z

(starting a new subject as this goes beyond simply adding support for
any platform/SoC/whetever, and touches on MTD/Flash, thus also adding
Stefan as To:)

Hi Wolfgang and others,

Wolfgang Denk a ?crit :
> Dear Albert Aribaud,
>
> In message <1258239796-21528-4-git-send-email-albert.aribaud@free.fr> you wrote:
>> This board is based on the Marvell Orion5x SoC.
>> Current support is limited to console and Flash.
>> Flash support uses LEGACY as the Macronix 29LV400
>> used on ED Mini V2 is not 100% CFI compliant.
>
> And the differences are really so big that we cannot tweak the CFI
> driver?

After deeper analysis, there are two issues:

1) there is an already known quirk in that the MX29LV400CB, reputedly
compliant with the 1.0 CFI spec, has the 7th bit set in the Mfg ID byte
although it should not. That can cause a mistaken region list inversion,
however this kind of issue is known for other parts and can be handled
in the current U-boot architecture.

2) The MX29LV400 QRY bytes appear at byte offsets 0x20, 0x22, 0x24 etc,
which is normal for mixed 8/16 bit chips: the spec says they should
output their QRY bytes at the same offset and with the same spacing as
pure 16-bit chips. However, they also should duplicate these QRY bytes
at odd addresses (0x21, 0x23, 0x25 etc) so that reading bytes from 0x20
onward would yield 'Q', 'Q', 'R', 'R', 'Y', 'Y' etc. However, the
MX29LV400CB output odd bytes as zeroes, just like a pure 16-bit device,
thus producing (LSB first) 'Q', #0, 'R', #0, 'Y', #0 etc.

To add insult to injury, for other JEDEC commands such as READ ID, the
MX29LV400CB does behave correctly, that is, duplicates its even bytes to
its odd bytes. A READ ID gives 0xC2, 0xC2, 0xBA, 0xBA which is correct
as far as mixed 8/16 chip behavior is concerned.

The consequence of all this is that even a perfectly CFI-compliant code
will recognize the MX29LV400CB as a 16-bit device even though it is a
mixed device and could, or worse, should (as in my own unfortunate case)
be used in BYTE mode.

In the case of U-boot's CFI detection code, it detects the MX29LV400CB
as 16-bit because of its QRY block offset (0x20) and null upper bytes.
Then it wants to talk to it using 16-bit wide writes at 16-bit mode
offsets, which, in my case, fails.

> U-Boot 2009.11-rc1-00069-g93fb3c4-dirty (dec. 02 2009 - 09:00:04) EDMiniV2
>
> SoC: Orion5x MV88F5182-A2
> DRAM: 64 MB
> flash detect cfi
> fwc addr fff80000 cmd f0 f0 8bit x 8 bit
> fwc addr fff80000 cmd ff ff 8bit x 8 bit
> fwc addr fff80055 cmd 98 98 8bit x 8 bit
> is= cmd 51(Q) addr fff80010 is= ff 51
> fwc addr fff80555 cmd 98 98 8bit x 8 bit
> is= cmd 51(Q) addr fff80010 is= ff 51
> fwc addr fff80000 cmd f0 f0f0 16bit x 8 bit
> fwc addr fff80000 cmd ff ffff 16bit x 8 bit
> fwc addr fff800aa cmd 98 9898 16bit x 8 bit
> is= cmd 51(Q) addr fff80020 is= 0051 5151
> fwc addr fff80aaa cmd 98 9898 16bit x 8 bit
> is= cmd 51(Q) addr fff80020 is= 0051 5151
> fwc addr fff80000 cmd f0 00f0 16bit x 16 bit
> fwc addr fff80000 cmd ff 00ff 16bit x 16 bit
> fwc addr fff800aa cmd 98 0098 16bit x 16 bit
> is= cmd 51(Q) addr fff80020 is= 0051 0051
> is= cmd 52(R) addr fff80022 is= 0052 0052
> is= cmd 59(Y) addr fff80024 is= 0059 0059
> device interface is 2
> found port 2 chip 2 port 16 bits chip 16 bits
> 00 : 51 52 59 02 00 40 00 00 00 00 00 27 36 00 00 04 QRY.. at .....'6...
> 10 : 00 0a 00 05 00 04 00 13 02 00 00 00 04 00 00 40 ...............@
> 20 : 00 01 00 20 00 00 00 80 00 06 00 00 01 d0 43 61 ... ..........Ca
> fwc addr fff80000 cmd f0 00f0 16bit x 16 bit
> fwc addr fff80aaa cmd aa 00aa 16bit x 16 bit
> fwc addr fff80554 cmd 55 0055 16bit x 16 bit
> fwc addr fff80aaa cmd 90 0090 16bit x 16 bit
> fwc addr fff80000 cmd f0 00f0 16bit x 16 bit
> fwc addr fff800aa cmd 98 0098 16bit x 16 bit
> manufacturer is 2
> manufacturer id is 0xff
> device id is 0xffff
> device id2 is 0x0

Looking at the commands and addresses displayed above and at the source
code of cfi_flash.c), I think the CFI detection code never tries the
'mixed 8/16-bit chip in 8-bit mode only' case. It does try a '16bit x 8
bit' case but as it doubles the write bytes (e.g. 0xF0F0), I suspect
this is meant for pairs of interleaved chips, not for a mixed-mode chip,
for which commands need not be duplicated.

Actually, the U-boot code seems to assume that if QRY bytes start at
0x20 and are at even offsets, then the chip is 16-bit, period -- see how
portwidth is used both to calculate offsets in QRY and other JEDEC data
*and* in computing the width of writes to the flash.

If so, then this would have to be amended for mixed-mode chips in byte
mode only.

Only, before I go on with proposing a fix, I'd like to be sure I'm right
so far; thus comments are heartily welcome.

Amicalement,
--
Albert.