nslu2-kernel: fix IXP flash map driver (ixp4xx.c) in 2.6.15-rc1
authorJohn Bowler <jbowler@nslu2-linux.org>
Mon, 14 Nov 2005 20:32:54 +0000 (20:32 +0000)
committerOpenEmbedded Project <openembedded-devel@lists.openembedded.org>
Mon, 14 Nov 2005 20:32:54 +0000 (20:32 +0000)
packages/linux/nslu2-kernel/2.6.15/90-ixp4xx-nslu2.patch [new file with mode: 0644]
packages/linux/nslu2-kernel/2.6.15/defconfig
packages/linux/nslu2-kernel/2.6.15/mtd-little-endian-support [deleted file]
packages/linux/nslu2-kernel/2.6.15/mtd-unaligned-read-fix [deleted file]
packages/linux/nslu2-kernel_2.6.15-rc1.bb

diff --git a/packages/linux/nslu2-kernel/2.6.15/90-ixp4xx-nslu2.patch b/packages/linux/nslu2-kernel/2.6.15/90-ixp4xx-nslu2.patch
new file mode 100644 (file)
index 0000000..d349785
--- /dev/null
@@ -0,0 +1,144 @@
+--- linux-2.6.15/drivers/mtd/maps/ixp4xx.c     1970-01-01 00:00:00.000000000 +0000
++++ linux-2.6.15/drivers/mtd/maps/ixp4xx.c     1970-01-01 00:00:00.000000000 +0000
+@@ -28,24 +28,45 @@
+ #include <linux/mtd/mtd.h>
+ #include <linux/mtd/map.h>
+ #include <linux/mtd/partitions.h>
++#include <linux/mtd/cfi_endian.h>
+ #include <asm/io.h>
+ #include <asm/mach/flash.h>
+ #include <linux/reboot.h>
+-#ifndef __ARMEB__
+-#define       BYTE0(h)        ((h) & 0xFF)
+-#define       BYTE1(h)        (((h) >> 8) & 0xFF)
++/*
++ * Read a 16 bit word from flash address 'addr'.
++ * This code ensures that the ixp4xx flash behaves as a consistent byte
++ * stream (same bytes in same order) regardless of whether the CPU is
++ * running in BE or LE mode, and regardless of whether the read16 or
++ * copyfrom method is used to read the flash data.
++ *
++ * When the cpu is in little-endian mode the hardware inverts the low
++ * address lines between the MMU (including the cache) and the flash chip
++ * ('address coherency') so we need to undo the swizzling to ensure commands
++ * and the like end up on the correct flash address.  This requirement
++ * only applies to command operations, however this code cannot distinguish
++ * a command read from a data read, therefore the fix applies to the data
++ * as well as the command and must be implemented consistently throughout
++ * the map driver (here).
++ */
++static inline u16 flash_read16(const void __iomem *virt, unsigned long offset)
++{
++#ifdef __ARMEB__
++      return *(const volatile u16 __iomem *)(virt + offset);
+ #else
+-#define       BYTE0(h)        (((h) >> 8) & 0xFF)
+-#define       BYTE1(h)        ((h) & 0xFF)
++      /* Cancel the address coherency invert of address line 1 in the
++       * hardware on LE systems.
++       */
++      return *(const volatile u16 __iomem *)(virt + (offset ^ 2));
+ #endif
++}
+ static map_word ixp4xx_read16(struct map_info *map, unsigned long ofs)
+ {
+       map_word val;
+-      val.x[0] = le16_to_cpu(readw(map->virt + ofs));
++      val.x[0] = cfi16_to_cpu(flash_read16(map->virt, ofs));
+       return val;
+ }
+@@ -53,41 +74,70 @@ static map_word ixp4xx_read16(struct map
+  * The IXP4xx expansion bus only allows 16-bit wide acceses
+  * when attached to a 16-bit wide device (such as the 28F128J3A),
+  * so we can't just memcpy_fromio().
++ *
++ * This code must obtain the correct bytes in the correct order
++ * according to the configuration of the CFI subsystem.
+  */
++#if (defined CFI_BIG_ENDIAN) || ((defined CFI_HOST_ENDIAN) && (defined __ARMEB__))
++      /* BE flash */
++#define       BYTE0(h)        (((h) >> 8) & 0xFF)
++#define       BYTE1(h)        ((h) & 0xFF)
++#else
++      /* LE flash */
++#define       BYTE0(h)        ((h) & 0xFF)
++#define       BYTE1(h)        (((h) >> 8) & 0xFF)
++#endif
++
+ static void ixp4xx_copy_from(struct map_info *map, void *to,
+                            unsigned long from, ssize_t len)
+ {
+-      int i;
+-      u8 *dest = (u8 *) to;
+-      void __iomem *src = map->virt + from;
+-      u16 data;
+-
+-      for (i = 0; i < (len / 2); i++) {
+-              data = le16_to_cpu(readw(src + 2*i));
+-              dest[i * 2] = BYTE0(data);
+-              dest[i * 2 + 1] = BYTE1(data);
++      u8 *dest = to;
++      const void __iomem * const virt = map->virt;
++
++      if (len <= 0)
++              return;
++
++      if (from & 1) {
++              *dest++ = BYTE1(flash_read16(virt, from-1));
++                ++from;
++              --len;
++      }
++
++      while (len >= 2) {
++              u16 data = flash_read16(virt, from);
++              *dest++ = BYTE0(data);
++              *dest++ = BYTE1(data);
++              from += 2;
++              len -= 2;
+       }
+-      if (len & 1)
+-              dest[len - 1] = BYTE0(le16_to_cpu(readw(src + 2*i)));
++      if (len > 0)
++              *dest++ = BYTE0(flash_read16(virt, from));
+ }
+ /*
+- * Unaligned writes are ignored, causing the 8-bit
+- * probe to fail and proceed to the 16-bit probe (which succeeds).
++ * Fast write16 function without the probing check below.
+  */
+-static void ixp4xx_probe_write16(struct map_info *map, map_word d, unsigned long adr)
++static void ixp4xx_write16(struct map_info *map, map_word d, unsigned long adr)
+ {
+-      if (!(adr & 1))
+-              writew(cpu_to_le16(d.x[0]), map->virt + adr);
++#ifdef __ARMEB__
++      *(volatile u16 __iomem*)(map->virt + adr) = cpu_to_cfi16(d.x[0]);
++#else
++      /* Cancel the address coherency invert of address line 1 in the
++       * hardware on LE systems.
++       */
++      *(volatile u16 __iomem*)(map->virt + (adr ^ 2)) = cpu_to_cfi16(d.x[0]);
++#endif
+ }
+ /*
+- * Fast write16 function without the probing check above
++ * Unaligned writes are ignored, causing the 8-bit
++ * probe to fail and proceed to the 16-bit probe (which succeeds).
+  */
+-static void ixp4xx_write16(struct map_info *map, map_word d, unsigned long adr)
++static void ixp4xx_probe_write16(struct map_info *map, map_word d, unsigned long adr)
+ {
+-      writew(cpu_to_le16(d.x[0]), map->virt + adr);
++      if (!(adr & 1))
++              ixp4xx_write16(map, d, adr);
+ }
+ struct ixp4xx_flash_info {
index 3d7c7fb..9a9bc34 100644 (file)
@@ -1,7 +1,7 @@
 #
 # Automatically generated make config: don't edit
 # Linux kernel version: 2.6.15
-# Sun Nov 13 21:46:15 2005
+# Mon Nov 14 10:44:43 2005
 #
 CONFIG_ARM=y
 CONFIG_MMU=y
@@ -442,8 +442,8 @@ CONFIG_MTD_CFI=y
 CONFIG_MTD_GEN_PROBE=y
 CONFIG_MTD_CFI_ADV_OPTIONS=y
 # CONFIG_MTD_CFI_NOSWAP is not set
-# CONFIG_MTD_CFI_BE_BYTE_SWAP is not set
-CONFIG_MTD_CFI_LE_BYTE_SWAP=y
+CONFIG_MTD_CFI_BE_BYTE_SWAP=y
+# CONFIG_MTD_CFI_LE_BYTE_SWAP is not set
 CONFIG_MTD_CFI_GEOMETRY=y
 # CONFIG_MTD_MAP_BANK_WIDTH_1 is not set
 CONFIG_MTD_MAP_BANK_WIDTH_2=y
diff --git a/packages/linux/nslu2-kernel/2.6.15/mtd-little-endian-support b/packages/linux/nslu2-kernel/2.6.15/mtd-little-endian-support
deleted file mode 100644 (file)
index 7dff4a2..0000000
+++ /dev/null
@@ -1,94 +0,0 @@
-diff -u linux-2.6-working/drivers/mtd/maps/ixp4xx.c linux-2.6-working/drivers/mtd/maps/ixp4xx.c
---- linux-2.6.15/drivers/mtd/maps/ixp4xx.c     1970-01-01 00:00:00.000000000 +0000
-+++ linux-2.6.15/drivers/mtd/maps/ixp4xx.c     1970-01-01 00:00:00.000000000 +0000
-@@ -30,18 +30,42 @@
- #include <linux/reboot.h>
--#ifndef __ARMEB__
--#define       BYTE0(h)        ((h) & 0xFF)
--#define       BYTE1(h)        (((h) >> 8) & 0xFF)
--#else
- #define       BYTE0(h)        (((h) >> 8) & 0xFF)
- #define       BYTE1(h)        ((h) & 0xFF)
-+
-+/*
-+ * Read/write a 16 bit word from flash address 'addr'.
-+ *
-+ * When the cpu is in little-endian mode it swizzles the address lines
-+ * ('address coherency') so we need to undo the swizzling to ensure commands
-+ * and the like end up on the correct flash address.
-+ */
-+#ifndef __ARMEB__
-+static inline u16 flash_read16(void __iomem *addr)
-+{
-+      return le16_to_cpu(readw((void __iomem *)((unsigned long)addr ^ 0x2)));
-+}
-+
-+static inline void flash_write16(u16 d, void __iomem *addr)
-+{
-+      writew(cpu_to_le16(d), (void __iomem *)((unsigned long)addr ^ 0x2));
-+}
-+#else
-+static inline u16 flash_read16(void __iomem *addr)
-+{
-+      return le16_to_cpu(readw(addr));
-+}
-+
-+static inline void flash_write16(u16 d, void __iomem *addr)
-+{
-+      writew(cpu_to_le16(d), addr);
-+}
- #endif
- static map_word ixp4xx_read16(struct map_info *map, unsigned long ofs)
- {
-       map_word val;
--      val.x[0] = le16_to_cpu(readw(map->virt + ofs));
-+      val.x[0] = flash_read16(map->virt + ofs);
-       return val;
- }
-@@ -60,13 +84,13 @@
-               return;
-       if (from & 1) {
--              *dest++ = BYTE1(le16_to_cpu(readw(src)));
-+              *dest++ = BYTE1(flash_read16(src));
-                 src++;
-               --len;
-       }
-       while (len >= 2) {
--              u16 data = le16_to_cpu(readw(src));
-+              u16 data = flash_read16(src);
-               *dest++ = BYTE0(data);
-               *dest++ = BYTE1(data);
-               src += 2;
-@@ -74,7 +98,7 @@
-       }
-       if (len > 0)
--              *dest++ = BYTE0(le16_to_cpu(readw(src)));
-+              *dest++ = BYTE0(flash_read16(src));
- }
- /* 
-@@ -84,7 +108,7 @@
- static void ixp4xx_probe_write16(struct map_info *map, map_word d, unsigned long adr)
- {
-       if (!(adr & 1))
--              writew(cpu_to_le16(d.x[0]), map->virt + adr);
-+              flash_write16(d.x[0], map->virt + adr);
- }
- /* 
-@@ -92,7 +116,7 @@
-  */
- static void ixp4xx_write16(struct map_info *map, map_word d, unsigned long adr)
- {
--      writew(cpu_to_le16(d.x[0]), map->virt + adr);
-+      flash_write16(d.x[0], map->virt + adr);
- }
- struct ixp4xx_flash_info {
diff --git a/packages/linux/nslu2-kernel/2.6.15/mtd-unaligned-read-fix b/packages/linux/nslu2-kernel/2.6.15/mtd-unaligned-read-fix
deleted file mode 100644 (file)
index f4f468c..0000000
+++ /dev/null
@@ -1,40 +0,0 @@
-diff -u linux-2.6-working/drivers/mtd/maps/ixp4xx.c linux-2.6-working/drivers/mtd/maps/ixp4xx.c
---- linux-2.6.15/drivers/mtd/maps/ixp4xx.c     1970-01-01 00:00:00.000000000 +0000
-+++ linux-2.6.15/drivers/mtd/maps/ixp4xx.c     1970-01-01 00:00:00.000000000 +0000
-@@ -53,19 +53,28 @@
- static void ixp4xx_copy_from(struct map_info *map, void *to,
-                            unsigned long from, ssize_t len)
- {
--      int i;
-       u8 *dest = (u8 *) to;
-       void __iomem *src = map->virt + from;
--      u16 data;
--      for (i = 0; i < (len / 2); i++) {
--              data = le16_to_cpu(readw(src + 2*i));
--              dest[i * 2] = BYTE0(data);
--              dest[i * 2 + 1] = BYTE1(data);
-+      if (len <= 0)
-+              return;
-+
-+      if (from & 1) {
-+              *dest++ = BYTE1(le16_to_cpu(readw(src)));
-+                src++;
-+              --len;
-+      }
-+
-+      while (len >= 2) {
-+              u16 data = le16_to_cpu(readw(src));
-+              *dest++ = BYTE0(data);
-+              *dest++ = BYTE1(data);
-+              src += 2;
-+              len -= 2;
-       }
--      if (len & 1)
--              dest[len - 1] = BYTE0(le16_to_cpu(readw(src + 2*i)));
-+      if (len > 0)
-+              *dest++ = BYTE0(le16_to_cpu(readw(src)));
- }
- /* 
index 783ca72..aace92b 100644 (file)
@@ -25,8 +25,7 @@ N2K_PATCHES = "\
        file://75-nslu2-leds.patch;patch=1 \
        file://80-nslu2-io.patch;patch=1 \
        file://81-nslu2-class-device-create.patch;patch=1 \
-       file://mtd-unaligned-read-fix;patch=1 \
-       file://mtd-little-endian-support;patch=1 \
+       file://90-ixp4xx-nslu2.patch;patch=1 \
        file://anonymiser.patch;patch=1 \
 "