From: Krzysztof Halasa <khc@pm.waw.pl>
To: barebox@lists.infradead.org
Subject: [PATCH 12] Fix NOR CFI flash driver to work on big endian systems.
Date: Tue, 21 Dec 2010 00:10:41 +0100 [thread overview]
Message-ID: <m3lj3kca6m.fsf@intrepid.localdomain> (raw)
In-Reply-To: <m362uodqms.fsf@intrepid.localdomain> (Krzysztof Halasa's message of "Mon, 20 Dec 2010 23:30:03 +0100")
Fix NOR CFI flash driver to work on big endian systems.
Basically this transforms the u8/u16/u32/u64 union into
a single u64 value.
Not tested on LE platform. Apply with caution.
Signed-off-by: Krzysztof Hałasa <khc@pm.waw.pl>
diff --git a/drivers/nor/cfi_flash.c b/drivers/nor/cfi_flash.c
index 90307d2..34031b0 100644
--- a/drivers/nor/cfi_flash.c
+++ b/drivers/nor/cfi_flash.c
@@ -77,59 +77,40 @@ static uint flash_offset_cfi[2]={FLASH_OFFSET_CFI,FLASH_OFFSET_CFI_ALT};
static void flash_add_byte (struct flash_info *info, cfiword_t * cword, uchar c)
{
-#if defined(__LITTLE_ENDIAN)
- unsigned short w;
- unsigned int l;
- unsigned long long ll;
-#endif
-
if (bankwidth_is_1(info)) {
- cword->c = c;
- } else if (bankwidth_is_2(info)) {
-#if defined(__LITTLE_ENDIAN)
- w = c;
- w <<= 8;
- cword->w = (cword->w >> 8) | w;
-#else
- cword->w = (cword->w << 8) | c;
-#endif
- } else if (bankwidth_is_4(info)) {
-#if defined(__LITTLE_ENDIAN)
- l = c;
- l <<= 24;
- cword->l = (cword->l >> 8) | l;
-#else
- cword->l = (cword->l << 8) | c;
-#endif
- } else if (bankwidth_is_8(info)) {
-#if defined(__LITTLE_ENDIAN)
- ll = c;
- ll <<= 56;
- cword->ll = (cword->ll >> 8) | ll;
+ *cword = c;
+ return;
+ }
+
+#if __BYTE_ORDER == __BIG_ENDIAN
+ *cword = (*cword << 8) | c;
#else
- cword->ll = (cword->ll << 8) | c;
+
+ if (bankwidth_is_2(info))
+ *cword = (*cword >> 8) | (u16)c << 8;
+ else if (bankwidth_is_4(info))
+ *cword = (*cword >> 8) | (u32)c << 24;
+ else if (bankwidth_is_8(info))
+ *cword = (*cword >> 8) | (u64)c << 56;
#endif
- }
}
static int flash_write_cfiword (struct flash_info *info, ulong dest,
cfiword_t cword)
{
- void *dstaddr;
+ void *dstaddr = (void *)dest;
int flag;
- dstaddr = (uchar *) dest;
-
/* Check if Flash is (sufficiently) erased */
- if (bankwidth_is_1(info)) {
- flag = ((flash_read8(dstaddr) & cword.c) == cword.c);
- } else if (bankwidth_is_2(info)) {
- flag = ((flash_read16(dstaddr) & cword.w) == cword.w);
- } else if (bankwidth_is_4(info)) {
- flag = ((flash_read32(dstaddr) & cword.l) == cword.l);
- } else if (bankwidth_is_8(info)) {
- flag = ((flash_read64(dstaddr) & cword.ll) == cword.ll);
- } else
+ if (bankwidth_is_1(info))
+ flag = ((flash_read8(dstaddr) & cword) == cword);
+ else if (bankwidth_is_2(info))
+ flag = ((flash_read16(dstaddr) & cword) == cword);
+ else if (bankwidth_is_4(info))
+ flag = ((flash_read32(dstaddr) & cword) == cword);
+ else if (bankwidth_is_8(info))
+ flag = ((flash_read64(dstaddr) & cword) == cword);
+ else
return 2;
if (!flag)
@@ -185,10 +166,8 @@ static void flash_printqry (struct cfi_qry *qry)
*/
uchar flash_read_uchar (struct flash_info *info, uint offset)
{
- uchar *cp;
-
- cp = flash_make_addr (info, 0, offset);
-#if defined(__LITTLE_ENDIAN)
+ uchar *cp = flash_make_addr(info, 0, offset);
+#if __BYTE_ORDER == __LITTLE_ENDIAN
return flash_read8(cp);
#else
return flash_read8(cp + info->portwidth - 1);
@@ -216,7 +195,7 @@ static ulong flash_read_long (struct flash_info *info, flash_sect_t sect, uint o
debug ("addr[%x] = 0x%x\n", x, flash_read8(addr + x));
}
#endif
-#if defined(__LITTLE_ENDIAN)
+#if __BYTE_ORDER == __LITTLE_ENDIAN
retval = ((flash_read8(addr) << 16) |
(flash_read8(addr + info->portwidth) << 24) |
(flash_read8(addr + 2 * info->portwidth)) |
@@ -534,7 +513,7 @@ static int write_buff (struct flash_info *info, const uchar * src, ulong addr, u
/* handle unaligned start */
if ((aln = addr - wp) != 0) {
- cword.l = 0;
+ cword = 0;
p = (uchar*)wp;
for (i = 0; i < aln; ++i)
flash_add_byte (info, &cword, flash_read8(p + i));
@@ -560,7 +539,7 @@ static int write_buff (struct flash_info *info, const uchar * src, ulong addr, u
while (cnt >= info->portwidth) {
/* prohibit buffer write when buffer_size is 1 */
if (info->buffer_size == 1) {
- cword.l = 0;
+ cword = 0;
for (i = 0; i < info->portwidth; i++)
flash_add_byte (info, &cword, *src++);
if ((rc = flash_write_cfiword (info, wp, cword)) != 0)
@@ -583,7 +562,7 @@ static int write_buff (struct flash_info *info, const uchar * src, ulong addr, u
}
#else
while (cnt >= info->portwidth) {
- cword.l = 0;
+ cword = 0;
for (i = 0; i < info->portwidth; i++) {
flash_add_byte (info, &cword, *src++);
}
@@ -600,7 +579,7 @@ static int write_buff (struct flash_info *info, const uchar * src, ulong addr, u
/*
* handle unaligned tail bytes
*/
- cword.l = 0;
+ cword = 0;
p = (uchar*)wp;
for (i = 0; (i < info->portwidth) && (cnt > 0); ++i) {
flash_add_byte (info, &cword, *src++);
@@ -672,7 +651,7 @@ static ssize_t cfi_write(struct cdev *cdev, const void *buf, size_t count, unsig
struct flash_info *finfo = (struct flash_info *)cdev->priv;
int ret;
- debug("cfi_write: buf=0x%08x addr=0x%08x count=0x%08x\n",buf, cdev->dev->map_base + offset, count);
+ debug("cfi_write: buf=0x%p addr=0x%08lx count=0x%08x\n",buf, cdev->dev->map_base + offset, count);
ret = write_buff (finfo, buf, cdev->dev->map_base + offset, count);
return ret == 0 ? count : -1;
@@ -836,17 +815,14 @@ int flash_generic_status_check (struct flash_info *info, flash_sect_t sector,
/*
* make a proper sized command based on the port and chip widths
*/
-void flash_make_cmd (struct flash_info *info, uchar cmd, void *cmdbuf)
+void flash_make_cmd(struct flash_info *info, u8 cmd, cfiword_t *cmdbuf)
{
- int i;
- uchar *cp = (uchar *) cmdbuf;
+ cfiword_t result = 0;
+ int i = info->portwidth / info->chipwidth;
-#if defined(__LITTLE_ENDIAN)
- for (i = info->portwidth; i > 0; i--)
-#else
- for (i = 1; i <= info->portwidth; i++)
-#endif
- *cp++ = (i & (info->chipwidth - 1)) ? '\0' : cmd;
+ while (i--)
+ result = (result << (8 * info->chipwidth)) | cmd;
+ *cmdbuf = result;
}
/*
@@ -860,6 +836,7 @@ void flash_write_cmd (struct flash_info *info, flash_sect_t sect, uint offset, u
addr = flash_make_addr (info, sect, offset);
flash_make_cmd (info, cmd, &cword);
+ debug("%s: %p %lX %X => %p %llX\n", __FUNCTION__, info, sect, offset, addr, cword);
flash_write_word(info, cword, addr);
}
@@ -874,14 +851,14 @@ int flash_isequal (struct flash_info *info, flash_sect_t sect, uint offset, ucha
debug ("is= cmd %x(%c) addr %p ", cmd, cmd, addr);
if (bankwidth_is_1(info)) {
- debug ("is= %x %x\n", flash_read8(addr), cword.c);
- retval = (flash_read8(addr) == cword.c);
+ debug ("is= %x %x\n", flash_read8(addr), (u8)cword);
+ retval = (flash_read8(addr) == cword);
} else if (bankwidth_is_2(info)) {
- debug ("is= %4.4x %4.4x\n", flash_read16(addr), cword.w);
- retval = (flash_read16(addr) == cword.w);
+ debug ("is= %4.4x %4.4x\n", flash_read16(addr), (u16)cword);
+ retval = (flash_read16(addr) == cword);
} else if (bankwidth_is_4(info)) {
- debug ("is= %8.8lx %8.8lx\n", flash_read32(addr), cword.l);
- retval = (flash_read32(addr) == cword.l);
+ debug ("is= %8.8lx %8.8lx\n", flash_read32(addr), (u32)cword);
+ retval = (flash_read32(addr) == cword);
} else if (bankwidth_is_8(info)) {
#ifdef DEBUG
{
@@ -889,11 +866,11 @@ int flash_isequal (struct flash_info *info, flash_sect_t sect, uint offset, ucha
char str2[20];
print_longlong (str1, flash_read32(addr));
- print_longlong (str2, cword.ll);
+ print_longlong (str2, cword);
debug ("is= %s %s\n", str1, str2);
}
#endif
- retval = (flash_read32(addr) == cword.ll);
+ retval = (flash_read64(addr) == cword);
} else
retval = 0;
@@ -902,20 +879,19 @@ int flash_isequal (struct flash_info *info, flash_sect_t sect, uint offset, ucha
int flash_isset (struct flash_info *info, flash_sect_t sect, uint offset, uchar cmd)
{
- void *addr;
+ void *addr = flash_make_addr (info, sect, offset);
cfiword_t cword;
int retval;
- addr = flash_make_addr (info, sect, offset);
flash_make_cmd (info, cmd, &cword);
if (bankwidth_is_1(info)) {
- retval = ((flash_read8(addr) & cword.c) == cword.c);
+ retval = ((flash_read8(addr) & cword) == cword);
} else if (bankwidth_is_2(info)) {
- retval = ((flash_read16(addr) & cword.w) == cword.w);
+ retval = ((flash_read16(addr) & cword) == cword);
} else if (bankwidth_is_4(info)) {
- retval = ((flash_read32(addr) & cword.l) == cword.l);
+ retval = ((flash_read32(addr) & cword) == cword);
} else if (bankwidth_is_8(info)) {
- retval = ((flash_read64(addr) & cword.ll) == cword.ll);
+ retval = ((flash_read64(addr) & cword) == cword);
} else
retval = 0;
@@ -1001,6 +977,7 @@ static int cfi_probe (struct device_d *dev)
/* Init: no FLASHes known */
info->flash_id = FLASH_UNKNOWN;
+ info->cmd_reset = FLASH_CMD_RESET;
info->size = flash_get_size(info, dev->map_base);
info->base = (void __iomem *)dev->map_base;
diff --git a/drivers/nor/cfi_flash.h b/drivers/nor/cfi_flash.h
index f9023dc..9098021 100644
--- a/drivers/nor/cfi_flash.h
+++ b/drivers/nor/cfi_flash.h
@@ -25,10 +25,12 @@
*/
#include <driver.h>
+#include <asm/byteorder.h>
#include <asm/io.h>
#include <linux/mtd/mtd.h>
typedef unsigned long flash_sect_t;
+typedef u64 cfiword_t;
struct cfi_cmd_set;
/*-----------------------------------------------------------------------
@@ -238,7 +240,7 @@ int flash_generic_status_check (struct flash_info *info, flash_sect_t sector,
uint64_t tout, char *prompt);
int flash_isequal (struct flash_info *info, flash_sect_t sect, uint offset, uchar cmd);
-void flash_make_cmd (struct flash_info *info, uchar cmd, void *cmdbuf);
+void flash_make_cmd(struct flash_info *info, uchar cmd, cfiword_t *cmdbuf);
static inline void flash_write8(u8 value, void *addr)
{
@@ -316,26 +318,19 @@ u32 jedec_read_mfr(struct flash_info *info);
#define bankwidth_is_8(info) 0
#endif
-typedef union {
- unsigned char c;
- unsigned short w;
- unsigned long l;
- unsigned long long ll;
-} cfiword_t;
-
static inline void flash_write_word(struct flash_info *info, cfiword_t datum, void *addr)
{
if (bankwidth_is_1(info)) {
- debug("fw addr %p val %02x\n", addr, datum.c);
- flash_write8(datum.c, addr);
+ debug("fw addr %p val %02x\n", addr, (u8)datum);
+ flash_write8(datum, addr);
} else if (bankwidth_is_2(info)) {
- debug("fw addr %p val %04x\n", addr, datum.w);
- flash_write16(datum.w, addr);
+ debug("fw addr %p val %04x\n", addr, (u16)datum);
+ flash_write16(datum, addr);
} else if (bankwidth_is_4(info)) {
- debug("fw addr %p val %08x\n", addr, datum.l);
- flash_write32(datum.l, addr);
+ debug("fw addr %p val %08x\n", addr, (u32)datum);
+ flash_write32(datum, addr);
} else if (bankwidth_is_8(info)) {
- flash_write64(datum.ll, addr);
+ flash_write64(datum, addr);
}
}
_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox
next prev parent reply other threads:[~2010-12-20 23:10 UTC|newest]
Thread overview: 41+ messages / expand[flat|nested] mbox.gz Atom feed top
2010-12-20 22:30 my IXP4xx-related and other patches Krzysztof Halasa
2010-12-20 22:40 ` [PATCH 1] Delete unused file common/dlmalloc.src Krzysztof Halasa
2010-12-21 9:34 ` Sascha Hauer
2010-12-20 22:42 ` [PATCH 2] Remove unused eth_get_name() prototype Krzysztof Halasa
2010-12-20 22:44 ` [PATCH 3] Flash CFI: removed unused 'size' variable Krzysztof Halasa
2010-12-20 22:45 ` [PATCH 4] Fix help text for "loadb" and "loady" commands Krzysztof Halasa
2010-12-20 22:54 ` [PATCH 5] Fix error handling with malloc, memalign etc. Memalign() can't fail now Krzysztof Halasa
2010-12-21 8:58 ` Sascha Hauer
2010-12-22 0:58 ` Jean-Christophe PLAGNIOL-VILLARD
2010-12-22 19:00 ` Krzysztof Halasa
2010-12-23 11:25 ` Krzysztof Halasa
2010-12-23 10:36 ` Sascha Hauer
2010-12-20 22:58 ` [PATCH 6] ARM: support big/little endian switching in "bootz" Krzysztof Halasa
2010-12-21 7:41 ` Sascha Hauer
2010-12-22 1:00 ` Jean-Christophe PLAGNIOL-VILLARD
2010-12-22 18:55 ` Krzysztof Halasa
2010-12-23 10:47 ` Sascha Hauer
2010-12-20 23:01 ` [PATCH 7] Fix top-level Makefile to work with GNU make 3.82 Krzysztof Halasa
2010-12-20 23:02 ` [PATCH 8] Cosmetic fixes, including format attributes for printf() and friends Krzysztof Halasa
2010-12-20 23:04 ` [PATCH 9] ARM: support big-endian processors Krzysztof Halasa
2010-12-20 23:06 ` [PATCH 10] ARM: Add support for IXP4xx CPU and for Goramo Multilink router platform Krzysztof Halasa
2010-12-21 7:42 ` Belisko Marek
2010-12-21 9:25 ` Sascha Hauer
2010-12-21 9:30 ` Juergen Beisert
2010-12-21 8:35 ` Sascha Hauer
2010-12-22 0:48 ` Krzysztof Halasa
2010-12-22 0:57 ` Jean-Christophe PLAGNIOL-VILLARD
2010-12-22 12:46 ` Sascha Hauer
2010-12-22 19:36 ` Krzysztof Halasa
2010-12-23 3:26 ` Jean-Christophe PLAGNIOL-VILLARD
2010-12-23 11:42 ` Krzysztof Halasa
2010-12-22 19:13 ` Krzysztof Halasa
2010-12-20 23:08 ` [PATCH 11] Silence few warnings Krzysztof Halasa
2010-12-20 23:10 ` Krzysztof Halasa [this message]
2010-12-22 1:01 ` [PATCH 12] Fix NOR CFI flash driver to work on big endian systems Jean-Christophe PLAGNIOL-VILLARD
2010-12-22 12:48 ` Sascha Hauer
2010-12-20 23:14 ` [PATCH 13] Fix usage of __LITTLE_ENDIAN macro Krzysztof Halasa
2010-12-21 9:17 ` my IXP4xx-related and other patches Sascha Hauer
2010-12-22 0:51 ` [PATCH 5a] Fix error handling with malloc, memalign etc. Introduce xmemalign() Krzysztof Halasa
2010-12-22 0:53 ` [PATCH 6a] ARM: support big/little endian switching in "bootz" Krzysztof Halasa
2010-12-22 0:55 ` [PATCH 10a] ARM: Add support for IXP4xx CPU and for Goramo Multilink router platform Krzysztof Halasa
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=m3lj3kca6m.fsf@intrepid.localdomain \
--to=khc@pm.waw.pl \
--cc=barebox@lists.infradead.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox