diff options
author | John Bowler <jbowler@nslu2-linux.org> | 2005-11-14 20:32:54 +0000 |
---|---|---|
committer | OpenEmbedded Project <openembedded-devel@lists.openembedded.org> | 2005-11-14 20:32:54 +0000 |
commit | c56219e33358676f00d9589b2a09f62f402a61f4 (patch) | |
tree | 1a615a11ef4d5d5cb538a07ca381e1f562aa6887 /packages/linux | |
parent | de8b18d55c760ab7d1b687a2b3897c7742540952 (diff) |
nslu2-kernel: fix IXP flash map driver (ixp4xx.c) in 2.6.15-rc1
Diffstat (limited to 'packages/linux')
5 files changed, 148 insertions, 139 deletions
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 index 0000000000..d3497850cd --- /dev/null +++ b/packages/linux/nslu2-kernel/2.6.15/90-ixp4xx-nslu2.patch @@ -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 { diff --git a/packages/linux/nslu2-kernel/2.6.15/defconfig b/packages/linux/nslu2-kernel/2.6.15/defconfig index 3d7c7fbd14..9a9bc34c7d 100644 --- a/packages/linux/nslu2-kernel/2.6.15/defconfig +++ b/packages/linux/nslu2-kernel/2.6.15/defconfig @@ -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 index 7dff4a2a77..0000000000 --- a/packages/linux/nslu2-kernel/2.6.15/mtd-little-endian-support +++ /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 index f4f468ce85..0000000000 --- a/packages/linux/nslu2-kernel/2.6.15/mtd-unaligned-read-fix +++ /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))); - } - - /* diff --git a/packages/linux/nslu2-kernel_2.6.15-rc1.bb b/packages/linux/nslu2-kernel_2.6.15-rc1.bb index 783ca72e23..aace92b525 100644 --- a/packages/linux/nslu2-kernel_2.6.15-rc1.bb +++ b/packages/linux/nslu2-kernel_2.6.15-rc1.bb @@ -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 \ " |