[U-Boot-Users] [RFC] CFI Driver Little-Endian write Issue

Hello Ed Okerson,
Recently, Roy Zang released MPC7448 HPC-II platform support to this list and found a CFI Flash driver problem - North-bridge chip TSI108 working as little-endian but write to Flash is byte-swapped in a wrong way. The workaround is to enable CFG_FLASH_USE_BUFFER_WRITE in little endian setting. However, CFG_FLASH_USE_BUFFER_WRITE should have nothing to do with little endian if I am right. So I suspect flash writing with little endian could have some problems.
Once I removed little endian stuff in flash_add_byte(), CFI Driver was funtional for MPC7448 HPC-II with/without CFG_FLASH_USE_BUFFER_WRITE. So I'd like to make sure whether my fix is a general thing or just a luck.
Thanks,
Sam
___________________________________________________________ Mp3疯狂搜-新歌热歌高速下 http://music.yahoo.com.cn/?source=mail_mailbox_footer

Dear Sam,
in message 20060804123231.77800.qmail@web15908.mail.cnb.yahoo.com you wrote:
Once I removed little endian stuff in flash_add_byte(), CFI Driver was funtional for MPC7448 HPC-II with/without CFG_FLASH_USE_BUFFER_WRITE. So I'd like to make sure whether my fix is a general thing or just a luck.
Ummm... did you try running the resulting code on any real LE system?
static void flash_add_byte (flash_info_t * info, cfiword_t * cword, uchar c) { -#if defined(__LITTLE_ENDIAN)
- unsigned short w;
- unsigned int l;
- unsigned long long ll;
-#endif
...
I understand that removing this code will break all real little- endian systems.
diff --git a/include/asm-ppc/processor.h b/include/asm-ppc/processor.h index ea5b0d2..3d3c96f 100644 --- a/include/asm-ppc/processor.h +++ b/include/asm-ppc/processor.h @@ -12,6 +12,12 @@ #include <linux/config.h> #include <asm/ptrace.h> #include <asm/types.h>
+#ifdef CONFIG_MPC7448HPC2 +#ifndef __LITTLE_ENDIAN +#define __LITTLE_ENDIAN +#endif /* __LITTLE_ENDIAN ** USI-SS */ +#endif /* CONFIG_MPC7448HPC2 */
And this is definitely inappropirate, too. All PowerPC systems we have so far are BE, including yours, event hough it performs funny (read: broken) memory accesses.
Defining __LITTLE_ENDIAN on a big-endian system is fundamentally broken. I will never accept such a patch.
Best regards,
Wolfgang Denk

Wolfgang Denk wd@denx.de wrote:
Ummm... did you try running the resulting code on any real LE system?
No. I have no such a platform. I'd like to get any feedback from LE real test.
I understand that removing this code will break all real little- endian systems.
If so, then drop my fixes. The puzzle to me is the difference between TSI108 working as LE mode and a real LE case.
+#ifdef CONFIG_MPC7448HPC2 +#ifndef __LITTLE_ENDIAN +#define __LITTLE_ENDIAN
[snip]
Defining __LITTLE_ENDIAN on a big-endian system is fundamentally broken. I will never accept such a patch.
Ummm, it's just my RFC hack. Should haven't released it to list.
Thanks,
Sam
___________________________________________________________ Mp3疯狂搜-新歌热歌高速下 http://music.yahoo.com.cn/?source=mail_mailbox_footer

Sounds like it's the (in)famous byte lanes swapping issue. It's so common that Linux MTD code even includes support for this. There are even more problematic flashes like Spansion S70GL256M which consists of two parts, one big-endian and another little-endian. I had to support the lanes swapping (and even the "mixed-endian") on many customers' boards. I've attached to this mail the CFI driver version which I use. It works well on many PowerPC boards but I've got no little-endian system to test it (my tree is not fully merged with official GIT right now so I'm not sending a patch, I can prepare one if you think the approach is OK).

Hi Yuli,
On Monday 07 August 2006 13:04, Yuli Barcohen wrote:
Sounds like it's the (in)famous byte lanes swapping issue. It's so common that Linux MTD code even includes support for this. There are even more problematic flashes like Spansion S70GL256M which consists of two parts, one big-endian and another little-endian. I had to support the lanes swapping (and even the "mixed-endian") on many customers' boards. I've attached to this mail the CFI driver version which I use. It works well on many PowerPC boards but I've got no little-endian system to test it (my tree is not fully merged with official GIT right now so I'm not sending a patch, I can prepare one if you think the approach is OK).
Yes, please send a patch, so we can better see the changes to the official version. Thanks.
Best regards, Stefan

Yuli Barcohen yuli@arabellasw.com wrote:
Sounds like it's the (in)famous byte lanes swapping issue. It's so
[snip]
system to test it (my tree is not fully merged with official GIT right now so I'm not sending a patch, I can prepare one if you think the approach is OK).
Indeed, I applied this CFI Driver on MPC7448HPC2 and it did work. But a small puzzle is that CFG_FLASH_CFI_SWAP shouldn't be tied to __LITTLE_ENDIAN. According to my test, they two can be set separetely.
diff --git a/include/configs/taiga.h b/include/configs/taiga.h index 8d4e9ad..878f268 100644 --- a/include/configs/taiga.h +++ b/include/configs/taiga.h @@ -500,6 +500,7 @@ #define CFG_BOOTMAPSZ (8<<20) /* Init */ #define CFG_FLASH_CFI 1 #define CFG_FLASH_CFI_DRIVER 1 +#define CFG_FLASH_CFI_SWAP #define CFG_FLASH_USE_BUFFER_WRITE 1 /* Disable CFG_FLASH_USE_BUFFER_WRITE is OK */ #define CFG_MAX_FLASH_BANKS 1
Thanks a lot,
Sam
__________________________________________________ 赶快注册雅虎超大容量免费邮箱? http://cn.mail.yahoo.com

Indeed, I applied this CFI Driver on MPC7448HPC2 and it did work. But a small puzzle is that CFG_FLASH_CFI_SWAP shouldn't be tied to __LITTLE_ENDIAN. According to my test, they two can be set separetely.
Please try the patch I posted yesterday. define CFG_FLASH_TSI_SWAP_BYTE in your board config file.
diff --git a/include/configs/taiga.h b/include/configs/taiga.h
Where do you get this file? It should be mpc7448hpc2.h. taiga.h is our previous header file.

Zang Roy-r61911 tie-fei.zang@freescale.com wrote:
Please try the patch I posted yesterday. define CFG_FLASH_TSI_SWAP_BYTE in your board config file.
It should work as expected. But I think we could work out a more general CFI driver. So Yuli's patch is still acceptable. What do you think?
diff --git a/include/configs/taiga.h b/include/configs/taiga.h
Where do you get this file? It should be mpc7448hpc2.h. taiga.h is our previous header file.
I shorten mpc7448hpc2 as taiga for few typing in my git tree. It's content could be the same as yours.
Thanks,
Sam
___________________________________________________________ 抢注雅虎免费邮箱-3.5G容量,20M附件! http://cn.mail.yahoo.com

Please try the patch I posted yesterday. define CFG_FLASH_TSI_SWAP_BYTE in your board config file.
It should work as expected. But I think we could work out a more general CFI driver. So Yuli's patch is still acceptable. What do you think?
Where is the patch? I do not object. Our final goal is to enable the general flash driver work on the board. Roy

Zang Roy-r61911 tie-fei.zang@freescale.com wrote:
Where is the patch? I do not object. Our final goal is to enable the general flash driver work on the board.
Sorry, I misused the word patch:-). The "patch" is Yuli's cfi_flash.c in his attached file. See your mail archive. It would be there. I tested that it was OK but still need your confirmation, I am afraid.
Thanks,
Sam
___________________________________________________________ Mp3疯狂搜-新歌热歌高速下 http://music.yahoo.com.cn/?source=mail_mailbox_footer

Sam Song writes:
Zang> Where is the patch? I do not object. Our final goal is to Zang> enable the general flash driver work on the board.
Sam> Sorry, I misused the word patch:-). The "patch" is Yuli's Sam> cfi_flash.c in his attached file. See your mail archive. It Sam> would be there. I tested that it was OK but still need your Sam> confirmation, I am afraid.
OK, the patch is attached. As we know, it works on big-endian systems. On little-endian ones, it should change nothing.

+#if defined(__LITTLE_ENDIAN) && !defined(CFG_FLASH_CFI_SWAP) +#define CFG_FLASH_CFI_SWAP +#endif + [snip] -#if defined(__LITTLE_ENDIAN) +#if defined(CFG_FLASH_CFI_SWAP)
Why use CFG_FLASH_CFI_SWAP instead of __LITTLE_ENDIAN. It seems that they are equivalent.
Best Regards, Leo
-----Original Message----- From: u-boot-users-bounces@lists.sourceforge.net [mailto:u-boot-users-bounces@lists.sourceforge.net] On Behalf Of Yuli
Barcohen
Sent: Tuesday, August 08, 2006 7:00 PM To: u-boot-users@lists.sourceforge.net Cc: Sam Song; Wolfgang Denk Subject: Re: [U-Boot-Users] [RFC] CFI Driver Little-Endian write Issue
Sam Song writes:
Zang> Where is the patch? I do not object. Our final goal is to Zang> enable the general flash driver work on the board. Sam> Sorry, I misused the word patch:-). The "patch" is Yuli's Sam> cfi_flash.c in his attached file. See your mail archive. It Sam> would be there. I tested that it was OK but still need your Sam> confirmation, I am afraid.
OK, the patch is attached. As we know, it works on big-endian systems. On little-endian ones, it should change nothing.
--
========================================================================
Yuli Barcohen | Phone +972-9-765-1788 | Software Project
Leader
yuli@arabellasw.com | Fax +972-9-765-7494 | Arabella Software,
Israel
========================================================================

Li Yang writes:
Li> +#if defined(__LITTLE_ENDIAN) && !defined(CFG_FLASH_CFI_SWAP) Li> +#define CFG_FLASH_CFI_SWAP Li> +#endif Li> + [snip] Li> -#if defined(__LITTLE_ENDIAN) Li> +#if defined(CFG_FLASH_CFI_SWAP)
Li> Why use CFG_FLASH_CFI_SWAP instead of __LITTLE_ENDIAN. It seems Li> that they are equivalent.
No, they aren't. First of all, on big-endian systems __LITTLE_ENDIAN is never defined and on little-endian systems it's always defined automatically while CFG_FLASH_CFI_SWAP must be defined manually if your board has such a flash. On little-endian systems, the driver should work without the need to define CFG_FLASH_CFI_SWAP. Also, there are places in the code for __LITTLE_ENDIAN only, not for CFG_FLASH_CFI_SWAP.

Got it. It's a little bit misleading to read your patch alone.
Your patch is mostly the same with Roy's latest patch, but with a more generic name. So, I prefer your version. :)
Best Regards, Leo
-----Original Message----- From: Yuli Barcohen [mailto:yuli@arabellasw.com] Sent: Tuesday, August 08, 2006 7:26 PM To: Li Yang-r58472 Cc: u-boot-users@lists.sourceforge.net; Sam Song; Wolfgang Denk Subject: RE: [U-Boot-Users] [RFC] CFI Driver Little-Endian write Issue
Li Yang writes:
Li> +#if defined(__LITTLE_ENDIAN) && !defined(CFG_FLASH_CFI_SWAP) Li> +#define CFG_FLASH_CFI_SWAP Li> +#endif Li> + [snip] Li> -#if defined(__LITTLE_ENDIAN) Li> +#if defined(CFG_FLASH_CFI_SWAP) Li> Why use CFG_FLASH_CFI_SWAP instead of __LITTLE_ENDIAN. It
seems
Li> that they are equivalent.
No, they aren't. First of all, on big-endian systems __LITTLE_ENDIAN
is
never defined and on little-endian systems it's always defined automatically while CFG_FLASH_CFI_SWAP must be defined manually if
your
board has such a flash. On little-endian systems, the driver should
work
without the need to define CFG_FLASH_CFI_SWAP. Also, there are places
in
the code for __LITTLE_ENDIAN only, not for CFG_FLASH_CFI_SWAP.
--
========================================================================
Yuli Barcohen | Phone +972-9-765-1788 | Software Project
Leader
yuli@arabellasw.com | Fax +972-9-765-7494 | Arabella Software,
Israel
========================================================================

Got it. It's a little bit misleading to read your patch alone.
Your patch is mostly the same with Roy's latest patch, but with a more generic name. So, I prefer your version. :)
Ummm... the name is better for other board. I had thought there were few boards to get into this issue except mpc7448hpc2. Roy

Yuli Barcohen yuli@arabellasw.com wrote:
No, they aren't. First of all, on big-endian systems __LITTLE_ENDIAN is never defined and on little-endian systems it's always defined automatically while CFG_FLASH_CFI_SWAP must be defined manually if your board has such a flash. On little-endian systems, the driver should work without the need to define CFG_FLASH_CFI_SWAP. Also, there are places in the code for __LITTLE_ENDIAN only, not for CFG_FLASH_CFI_SWAP.
Seems your explaination is not the same as your patch:-). I hope I weren't clear this time.
In your patch, CFG_FLASH_CFI_SWAP is automatically defined in __LITTLE_ENDIAN case. So on __LITTLE_ENDIAN system, CFG_FLASH_CFI_SWAP MUST BE ENABLED by default.
+#if defined(__LITTLE_ENDIAN) && !defined(CFG_FLASH_CFI_SWAP) +#define CFG_FLASH_CFI_SWAP +#endif
Regards,
Sam
___________________________________________________________ Mp3疯狂搜-新歌热歌高速下 http://music.yahoo.com.cn/?source=mail_mailbox_footer

Sam Song writes:
Yuli> No, they aren't. First of all, on big-endian systems Yuli> __LITTLE_ENDIAN is never defined and on little-endian systems Yuli> it's always defined automatically while CFG_FLASH_CFI_SWAP Yuli> must be defined manually if your board has such a flash. On Yuli> little-endian systems, the driver should work without the need Yuli> to define CFG_FLASH_CFI_SWAP. Also, there are places in the Yuli> code for __LITTLE_ENDIAN only, not for CFG_FLASH_CFI_SWAP.
Sam> Seems your explaination is not the same as your patch:-).
Yes, the explanation is in English and the patch is in C:) The meaning is the same though.
Sam> I hope I weren't clear this time.
Sam> In your patch, CFG_FLASH_CFI_SWAP is automatically defined in Sam> __LITTLE_ENDIAN case. So on __LITTLE_ENDIAN system, Sam> CFG_FLASH_CFI_SWAP MUST BE ENABLED by default.
So it's exactly what I explained: little-endian systems work automatically without the need to define CFG_FLASH_CFI_SWAP. I meant, you don't have to #define CFG_FLASH_CFI_SWAP in the board configuration file to have working little-endian system. It's defined automatically when needed. Sorry if it wasn't clear enough.
Sam> +#if defined(__LITTLE_ENDIAN) && !defined(CFG_FLASH_CFI_SWAP) Sam> +#define CFG_FLASH_CFI_SWAP Sam> +#endif
If it makes things simpler, it's possible to replace
#ifdef CFG_FLASH_CFI_SWAP
by
#if defined(__LITTLE_ENDIAN) || defined(CFG_FLASH_CFI_SWAP)
and remove the above mentioned definition of CFG_FLASH_CFI_SWAP.

Yuli Barcohen yuli@arabellasw.com wrote:
Yes, the explanation is in English and the patch is in C:) The meaning is the same though.
Well said:-)
So it's exactly what I explained: little-endian systems work
Oops, it is clear to me now. Keep all the code like that.
Thanks,
Sam
___________________________________________________________ 雅虎免费邮箱-3.5G容量,20M附件 http://cn.mail.yahoo.com/

Zang> Where is the patch? I do not object. Our final goal is to Zang> enable the general flash driver work on the board. Sam> Sorry, I misused the word patch:-). The "patch" is Yuli's Sam> cfi_flash.c in his attached file. See your mail archive. It Sam> would be there. I tested that it was OK but still need your Sam> confirmation, I am afraid.
OK, the patch is attached. As we know, it works on big-endian systems. On little-endian ones, it should change nothing.
This patch is similar to my previous one. it works on my mpc7448hpc2 (tagia) board. I appreciate the method and the name you import CFG_FLASH_CFI_SWAP. I hope it can deal with similar boards.
Wolfgang, Could you apply it in your public git tree? Roy

Zang Roy-r61911 tie-fei.zang@freescale.com wrote:
This patch is similar to my previous one. it works on my mpc7448hpc2 (tagia) board. I appreciate the method and the name you import CFG_FLASH_CFI_SWAP.
[snip]
Wolfgang, Could you apply it in your public git tree? Roy
Seems it's better to create the patch in a new thread sending to the list. Besides, it is necessary to add an entry for CFG_FLASH_CFI_SWAP in README.
Thanks,
Sam
__________________________________________________ 赶快注册雅虎超大容量免费邮箱? http://cn.mail.yahoo.com

Where is the patch? I do not object. Our final goal is to enable the general flash driver work on the board.
Sorry, I misused the word patch:-). The "patch" is Yuli's cfi_flash.c in his attached file. See your mail archive. It would be there. I tested that it was OK but still need your confirmation, I am afraid.
I will try it. While it's better to provide patch. We can see the difference. Roy

Hello Ed Okerson,
Recently, Roy Zang released MPC7448 HPC-II platform support to this list and found a CFI Flash driver problem - North-bridge chip TSI108 working as little-endian but write to Flash is byte-swapped in a wrong way. The workaround is to enable CFG_FLASH_USE_BUFFER_WRITE in little endian setting. However, CFG_FLASH_USE_BUFFER_WRITE should have nothing to do with little endian if I am right. So I suspect flash writing with little endian could have some problems.
Flash writing on a pure little endian system should be right. CFG_FLASH_USE_BUFFER_WRITE could not solve the issue on mpc7448hpc2 board. Just as I mentioned before., "For handling unaligned head and tail bytes, the byte swap issue also exists. For example => cp.b 400002 fff80002 12 (from ram to flash)." There will be some adjustment for my mpc7448hpc2 patch. Now I am struggled with the tsi108 config read exception. I hope I can repost the whole patch again in this week. For cfi_flash.c driver, I add the following patch.
diff --git a/drivers/cfi_flash.c b/drivers/cfi_flash.c index fd0a186..f621bc1 100644 --- a/drivers/cfi_flash.c +++ b/drivers/cfi_flash.c @@ -268,7 +268,7 @@ inline uchar flash_read_uchar (flash_inf uchar *cp;
cp = flash_make_addr (info, 0, offset); -#if defined(__LITTLE_ENDIAN) +#if defined(__LITTLE_ENDIAN) || defined(CFG_FLASH_TSI_SWAP_BYTE) return (cp[0]); #else return (cp[info->portwidth - 1]); @@ -295,7 +295,7 @@ #ifdef DEBUG debug ("addr[%x] = 0x%x\n", x, addr[x]); } #endif -#if defined(__LITTLE_ENDIAN) +#if defined(__LITTLE_ENDIAN) || defined(CFG_FLASH_TSI_SWAP_BYTE) retval = ((addr[(info->portwidth)] << 8) | addr[0]); #else retval = ((addr[(2 * info->portwidth) - 1] << 8) | @@ -327,7 +327,7 @@ #ifdef DEBUG debug ("addr[%x] = 0x%x\n", x, addr[x]); } #endif -#if defined(__LITTLE_ENDIAN) +#if defined(__LITTLE_ENDIAN) || defined(CFG_FLASH_TSI_SWAP_BYTE) retval = (addr[0] << 16) | (addr[(info->portwidth)] << 24) | (addr[(2 * info->portwidth)]) | (addr[(3 * info->portwidth)] << 8); #else @@ -596,7 +596,6 @@ #ifdef CFG_FLASH_USE_BUFFER_WRITE int buffered_size; #endif /* get lower aligned address */ - /* get lower aligned address */ wp = (addr & ~(info->portwidth - 1));
/* handle unaligned start */ @@ -892,7 +891,7 @@ static void flash_make_cmd (flash_info_t int i; uchar *cp = (uchar *) cmdbuf;
-#if defined(__LITTLE_ENDIAN) +#if defined(__LITTLE_ENDIAN) || defined(CFG_FLASH_TSI_SWAP_BYTE) for (i = info->portwidth; i > 0; i--) #else for (i = 1; i <= info->portwidth; i++)

Zang Roy-r61911 tie-fei.zang@freescale.comwrote:
Flash writing on a pure little endian system should be right.
Out of interest, what the difference between a pure little endian system and TSI108 HLP working as LE mode?
Could we set TSI108 HLP working as BE?
Thanks a lot,
Sam
___________________________________________________________ Mp3疯狂搜-新歌热歌高速下 http://music.yahoo.com.cn/?source=mail_mailbox_footer

Flash writing on a pure little endian system should be right.
Out of interest,
Why? It just begins. If everything is OK, what should we do?
what the difference between a pure little
endian system and TSI108 HLP working as LE mode?
A pure little endian system might be X86 processor + little endian connected flash.
Could we set TSI108 HLP working as BE?
we can set register HLP_DATA_SWAP_CTRL for data swap for tsi108 HLP port. Please refer 7.6 Data Swapping chapter of the data sheet.
Roy

Zang Roy-r61911 tie-fei.zang@freescale.com wrote:
A pure little endian system might be X86 processor + little endian connected flash.
It reminded me of the fact there is probably a LE system in our LAB. I will play with it when available.
Could we set TSI108 HLP working as BE?
we can set register HLP_DATA_SWAP_CTRL for data swap for tsi108 HLP port. Please refer 7.6 Data Swapping chapter of the data sheet.
Thanks. I will check that.
Sam
___________________________________________________________ 雅虎免费邮箱-3.5G容量,20M附件 http://cn.mail.yahoo.com/

A pure little endian system might be X86 processor + little endian connected flash.
It reminded me of the fact there is probably a LE system in our LAB. I will play with it when available.
That's good.
Could we set TSI108 HLP working as BE?
we can set register HLP_DATA_SWAP_CTRL for data swap for tsi108 HLP port. Please refer 7.6 Data Swapping chapter of the data sheet.
Thanks. I will check that.
I have tried all the combinations, it does not seem workable for our issue. Roy

Zang Roy-r61911 tie-fei.zang@freescale.com wrote:
I have tried all the combinations, it does not seem workable for our issue.
That's fine. I meant to make such a try. Well, you save me from that.
Thanks a lot,
Sam
___________________________________________________________ Mp3疯狂搜-新歌热歌高速下 http://music.yahoo.com.cn/?source=mail_mailbox_footer
participants (6)
-
Li Yang-r58472
-
Sam Song
-
Stefan Roese
-
Wolfgang Denk
-
Yuli Barcohen
-
Zang Roy-r61911