mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
From: John Bowler <jbowler@acm.org>
To: "'Deepak Saxena'" <dsaxena@plexity.net>
Cc: <linux-kernel@vger.kernel.org>,
	<linux-arm-kernel@lists.arm.linux.org.uk>
Subject: [PATCH] 2.6.14-rc3 ixp4xx_copy_from little endian/alignment
Date: Thu, 27 Oct 2005 23:09:31 -0700	[thread overview]
Message-ID: <000e01c5db86$29ba4120$1001a8c0@kalmiopsis> (raw)

I'm resubmitting this because originally we just submitted it to
linux-arm-kernel and I believe this means it hasn't been seen in
the right places to get it into the MM patch set.  This patch and
the ones I will be submitting immediately afterwards or that we have
submitted before are sufficient to allow a bootable, working,
kernel on the LinkSys NSLU2 in either little-endian or big-endian
mode.  The patches have been tested against both 2.6.14 and
2.6.14-rc5-mm1 with a variety of rootfs's (arm and thumb uclibc,
arm glibc).

John Bowler <jbowler@acm.org>

>From: Alessandro Zummo
  this short patch will modify the ixp4xx mtd code in order to fix
 a couple of problems we have verified while working
 with the NSLU2. 
 
 - word-wide accesses vs byte-wide
 - little endian support
 
 There's an insightful description in the first lines of the
 patch.
 
 The author, John Bowler, has put a lot of efforts in this patch,
 verifying that this is the cleanest and shortest patch that
 can fix those problem.
 
 John and others wroted at least three different solutions
 analyzing both the current code, our needs and the 
 philosophical aspects of this code.. and I'm not kidding!
 
 The patch has been tested to work on the NSLU2 in both
 LE and BE mode.
 
 Signed-off-by: John Bowler <jbowler@acm.org>
 Signed-off-by: Alessandro Zummo <a.zummo@towertech.it>

--- linux-2.6.13/drivers/mtd/maps/ixp4xx.c	2005-10-07 15:55:08.958509801 -0700
+++ linux-2.6.13/drivers/mtd/maps/ixp4xx.c	2005-10-07 19:06:22.352484966 -0700
@@ -22,6 +22,7 @@
 #include <linux/string.h>
 #include <linux/mtd/mtd.h>
 #include <linux/mtd/map.h>
+#include <linux/mtd/cfi_endian.h>
 #include <linux/mtd/partitions.h>
 #include <linux/ioport.h>
 #include <linux/device.h>
@@ -30,18 +31,45 @@
 
 #include <linux/reboot.h>
 
+/* On a little-endian IXP4XX system (tested on NSLU2) contrary to the
+ * Intel documentation LDRH/STRH appears to XOR the address with 10b.
+ * This causes the cfi commands (sent to the command address, 0xAA for
+ * 16 bit flash) to fail.  This is fixed here by XOR'ing the address
+ * before use with 10b.  The cost of this is that the flash layout ends
+ * up with pdp-endiannes (on an LE syste), however this is not a problem
+ * as the access code consistently only accesses half words - so the
+ * endianness is not determinable on stuff which is written and read
+ * consistently in the little endian world.
+ *
+ * For flash data from the big-endian world, however, the results are
+ * weird - the pdp-endianness results in the data apparently being
+ * 2-byte swapped (as in dd conv=swab).  To work round this the 16
+ * bit values are written and read using cpu_to_cfi16 and cfi16_to_cpu,
+ * by default these are no-ops, but if the MTD driver is configed with
+ * CONFIG_MTD_CFI_BE_BYTE_SWAP the macros will byte swap the data,
+ * resulting in a consistently BE view of the flash on both BE (no
+ * op) and LE systems.  This config setting also causes the command
+ * data from the CFI implementation to get swapped - as is required
+ * so that this code will *unswap* it and give the correct command
+ * data to the flash.
+ */
 #ifndef __ARMEB__
 #define	BYTE0(h)	((h) & 0xFF)
 #define	BYTE1(h)	(((h) >> 8) & 0xFF)
+#define	FLASHWORD(a)	(*(__u16*)((u32)(a) ^ 2))
 #else
 #define	BYTE0(h)	(((h) >> 8) & 0xFF)
 #define	BYTE1(h)	((h) & 0xFF)
+#define	FLASHWORD(a)	(*(__u16*)(a))
 #endif
 
+#define FLASHW(a)	cfi16_to_cpu(FLASHWORD(a))
+#define FLASHSET(a,v)	(FLASHWORD(a) = cpu_to_cfi16(v))
+
 static map_word ixp4xx_read16(struct map_info *map, unsigned long ofs)
 {
 	map_word val;
-	val.x[0] = *(__u16 *) (map->map_priv_1 + ofs);
+	val.x[0] = FLASHW(map->map_priv_1 + ofs);
 	return val;
 }
 
@@ -53,19 +81,23 @@
 static void ixp4xx_copy_from(struct map_info *map, void *to,
 			     unsigned long from, ssize_t len)
 {
-	int i;
-	u8 *dest = (u8 *) to;
-	u16 *src = (u16 *) (map->map_priv_1 + from);
-	u16 data;
+	if (len <= 0)
+		return;
 
-	for (i = 0; i < (len / 2); i++) {
-		data = src[i];
-		dest[i * 2] = BYTE0(data);
-		dest[i * 2 + 1] = BYTE1(data);
+	u8 *dest = (u8 *) to;
+	u8 *src  = (u8 *) (map->map_priv_1 + from);
+	if (from & 1)
+		*dest++ = BYTE1(FLASHW(src-1)), ++src, --len;
+
+	while (len >= 2) {
+		u16 data = FLASHW(src); src += 2;
+		*dest++ = BYTE0(data);
+		*dest++ = BYTE1(data);
+		len -= 2;
 	}
 
-	if (len & 1)
-		dest[len - 1] = BYTE0(src[i]);
+	if (len > 0)
+		*dest++ = BYTE0(FLASHW(src));
 }
 
 /* 
@@ -75,7 +107,7 @@
 static void ixp4xx_probe_write16(struct map_info *map, map_word d, unsigned long adr)
 {
 	if (!(adr & 1))
-	       *(__u16 *) (map->map_priv_1 + adr) = d.x[0];
+	       FLASHSET(map->map_priv_1 + adr, d.x[0]);
 }
 
 /* 
@@ -83,7 +115,7 @@
  */
 static void ixp4xx_write16(struct map_info *map, map_word d, unsigned long adr)
 {
-       *(__u16 *) (map->map_priv_1 + adr) = d.x[0];
+       FLASHSET(map->map_priv_1 + adr, d.x[0]);
 }
 
 struct ixp4xx_flash_info {

-- 

 Best regards,

 Alessandro Zummo,
  Tower Technologies - Turin, Italy

  http://www.towertech.it


             reply	other threads:[~2005-10-28  7:01 UTC|newest]

Thread overview: 6+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2005-10-28  6:09 John Bowler [this message]
2005-10-28  8:13 ` Lennert Buytenhek
2005-10-28 12:40 ` David Vrabel
2005-10-28 16:32   ` John Bowler
2005-10-28 20:34     ` David Vrabel
2005-10-29  0:16       ` John Bowler

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='000e01c5db86$29ba4120$1001a8c0@kalmiopsis' \
    --to=jbowler@acm.org \
    --cc=dsaxena@plexity.net \
    --cc=linux-arm-kernel@lists.arm.linux.org.uk \
    --cc=linux-kernel@vger.kernel.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

all inboxes | Powered by JetHome®