mail archive of the barebox mailing list
 help / color / mirror / Atom feed
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

  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