diff options
Diffstat (limited to 'packages')
-rw-r--r-- | packages/linux/nslu2-kernel/2.6.15/20-timer.patch | 285 | ||||
-rw-r--r-- | packages/linux/nslu2-kernel/2.6.15/35-x1205-fix-osc.patch | 204 | ||||
-rw-r--r-- | packages/linux/nslu2-kernel/2.6.15/60-nslu2-rtc.patch | 21 | ||||
-rw-r--r-- | packages/linux/nslu2-kernel/2.6.15/90-ixp4xx-nslu2.patch | 132 |
4 files changed, 0 insertions, 642 deletions
diff --git a/packages/linux/nslu2-kernel/2.6.15/20-timer.patch b/packages/linux/nslu2-kernel/2.6.15/20-timer.patch deleted file mode 100644 index 3d4a03f616..0000000000 --- a/packages/linux/nslu2-kernel/2.6.15/20-timer.patch +++ /dev/null @@ -1,285 +0,0 @@ ---- linux-2.6.15/arch/arm/mach-ixp4xx/common.c 1970-01-01 00:00:00.000000000 +0000 -+++ linux-2.6.15/arch/arm/mach-ixp4xx/common.c 1970-01-01 00:00:00.000000000 +0000 -@@ -239,36 +239,165 @@ void __init ixp4xx_init_irq(void) - * IXP4xx timer tick - * We use OS timer1 on the CPU for the timer tick and the timestamp - * counter as a source of real clock ticks to account for missed jiffies. -+ * -+ * 'CLOCK_TICK_RATE' is the nominal number of internal ticks per second, -+ * this is significantly greater than the actual number on any ixp4xx -+ * board. Neither this nor 'LATCH' are required by this code because -+ * the only requirement is to generate HZ timer_tick calls per second. - *************************************************************************/ -+#if TICK_NSEC * HZ != 1000000000 -+ /* This will cause the jiffies to drift unnecessarily. */ -+# error CLOCK_TICK_RATE should be a multiple of HZ for this code -+#endif -+ -+/* These are the control registers for the interrupt handler, they must -+ * only be read and written by the interrupt handler and by the init -+ * method (which sets them to 0). -+ */ -+static volatile u32 last_timer_time; -+static volatile int accumulated_error; -+ -+/* Most ixp4xx boards have 66.6666MHz crystals, so default to this, reset -+ * this from the board level code if required. The following variables -+ * must be *written* only by set_board_tick_rate -+ */ -+static u32 board_tick_rate; -+static u32 board_tick_per_1000; /* board_tick_rate/1000 */ -+static u32 timer_count; -+ -+/* The following symbol may be written to change the current tick rate, -+ * it is read by the interrupt handler and used to reload the timer. -+ * The 'real' value (the one in use) is 'board_tick_rate' above. -+ * NOTE: this can be tweaked to match the actual crystal on a particular -+ * machine. -+ */ -+volatile u32 ixp4xx_board_tick_rate = 66666600; -+EXPORT_SYMBOL(ixp4xx_board_tick_rate); -+ -+/* The set API may run asynchronously in the presence of interrupts, -+ * everything it does it is both atomic and complete (notice that it -+ * doesn't change any of the 'volatile' values). The mathematics in -+ * here require the following values. Changing the board tick rate -+ * implies an unknown error in the current timestamp tick count. -+ */ -+#if IXP4XX_OST_RELOAD_MASK != 3 || IXP4XX_OST_ENABLE != 1 -+# error unexpected value for timer reload mask -+#endif -+static void set_board_tick_rate(u32 rate) { -+ u32 reload; -+ -+ /* Store the two effectively informational rate values, the -+ * error calculation is (rate - count*HZ) (above), and rate -+ * is changed first, this can cause a temporary error which -+ * will be corrected on the next interrupt. -+ */ -+ board_tick_rate = rate; -+ board_tick_per_1000 = (rate+500)/1000; -+ -+ /* Calculate the correct value to load into the timer countdown -+ * register, the low two bits must be b01 (to enable the timer). -+ * Select the top bits to be as close to the desired value as -+ * possible. -+ * -+ * First find the best value, regardless of the low two bits - -+ * this is the value used in the interrupt calculation even though -+ * it cannot necessarily be set into the register. -+ */ -+ timer_count = (rate + (HZ/2))/HZ; -+ -+ /* Now the timer_ticks are being generated at this rate, calculate -+ * an appropriate value for the register. This stores a 30 bit -+ * value which gives a period of 4*x+1, we want: -+ * -+ * 4*x+1 = board_tick_rate/HZ -+ * -+ * This needs to be rounded to the closest 4*HZ value: -+ * -+ * x = ((board_tick_rate-HZ) + (4*HZ)/2) / 4*HZ -+ * x = (board_tick_rate+HZ) / (4*HZ); -+ */ -+ reload = (board_tick_rate + HZ) / HZ; -+ reload = (reload & ~IXP4XX_OST_RELOAD_MASK) | IXP4XX_OST_ENABLE; -+ *IXP4XX_OSRT1 = reload; - --static unsigned volatile last_jiffy_time; -+ /* If the clock is drifing, look in syslog: */ -+ printk(KERN_INFO "IXP4xx: FREQ=%d COUNT=%d\n", rate, reload); -+} - --#define CLOCK_TICKS_PER_USEC ((CLOCK_TICK_RATE + USEC_PER_SEC/2) / USEC_PER_SEC) -+/* This returns the time in timer ticks since the 'last_timer_time' -+ * recorded above. Use this to avoid arithmetic errors because of -+ * the overflow when the timer wraps. -+ */ -+static inline u32 ixp4xx_timer_delta(void) -+{ -+ return *IXP4XX_OSTS - last_timer_time; -+} - - /* IRQs are disabled before entering here from do_gettimeofday() */ - static unsigned long ixp4xx_gettimeoffset(void) - { -- u32 elapsed; -- -- elapsed = *IXP4XX_OSTS - last_jiffy_time; -+ /* Return the offset of the current time from the last time -+ * timer tick in microseconds. This is only used for the -+ * gettimeofday call. -+ * -+ * The result of this API is at most about 20000 (for a 50Hz -+ * HZ - 20000 uS/tick), the input delta is at most about -+ * 1.3M - 21 bits. -+ */ -+ u32 delta = ixp4xx_timer_delta(); /* About 21 bits max */ -+ /* return delta * 1000000 / board_tick_rate; */ -+ return (delta * 1000 + board_tick_per_1000/2) / board_tick_per_1000; -+} - -- return elapsed / CLOCK_TICKS_PER_USEC; -+/* This is the correct adjustment to the counter to compensate for an -+ * error iff timer_count-1 <= exact_count <= timer_count+1 -+ */ -+static inline int adjustment(int error) { -+ if (error >= HZ) -+ return 1; -+ else if (error <= -HZ) -+ return -1; -+ return 0; - } - - static irqreturn_t ixp4xx_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs) - { -+ u32 rate; -+ u32 count; -+ int error; -+ - write_seqlock(&xtime_lock); - - /* Clear Pending Interrupt by writing '1' to it */ - *IXP4XX_OSST = IXP4XX_OSST_TIMER_1_PEND; - -+ /* If the board tick rate has been changed update the cached -+ * value. -+ */ -+ if (ixp4xx_board_tick_rate != board_tick_rate) { -+ set_board_tick_rate(ixp4xx_board_tick_rate); -+ accumulated_error = 0; -+ } -+ - /* - * Catch up with the real idea of time -+ * -+ * board_tick_rate: actual ixp4xx ticks/second, read-only -+ * accumulated_error: aggregate error/tick * HZ, read/write -+ * timer_count: best ixp4xx ticks per timer_tick, read-only - */ -- while ((*IXP4XX_OSTS - last_jiffy_time) > LATCH) { -+ rate = board_tick_rate; -+ error = accumulated_error; -+ count = timer_count; -+ do { -+ u32 adjusted_count = count + adjustment(error); -+ if (ixp4xx_timer_delta() < adjusted_count) -+ break; - timer_tick(regs); -- last_jiffy_time += LATCH; -- } -+ last_timer_time += adjusted_count; -+ error += rate - adjusted_count*HZ; -+ } while (1); -+ accumulated_error = error; - - write_sequnlock(&xtime_lock); - -@@ -281,17 +410,30 @@ static struct irqaction ixp4xx_timer_irq - .handler = ixp4xx_timer_interrupt, - }; - -+u32 ixp4xx_get_board_tick_rate(void) { -+ return board_tick_rate; -+} -+ -+EXPORT_SYMBOL(ixp4xx_get_board_tick_rate); -+ -+void ixp4xx_set_board_tick_rate(u32 rate) { -+ ixp4xx_board_tick_rate = rate; -+} -+ -+EXPORT_SYMBOL(ixp4xx_set_board_tick_rate); -+ - static void __init ixp4xx_timer_init(void) - { - /* Clear Pending Interrupt by writing '1' to it */ - *IXP4XX_OSST = IXP4XX_OSST_TIMER_1_PEND; - - /* Setup the Timer counter value */ -- *IXP4XX_OSRT1 = (LATCH & ~IXP4XX_OST_RELOAD_MASK) | IXP4XX_OST_ENABLE; -+ set_board_tick_rate(ixp4xx_board_tick_rate); - - /* Reset time-stamp counter */ - *IXP4XX_OSTS = 0; -- last_jiffy_time = 0; -+ last_timer_time = 0; -+ accumulated_error = 0; - - /* Connect the interrupt handler and enable the interrupt */ - setup_irq(IRQ_IXP4XX_TIMER1, &ixp4xx_timer_irq); -@@ -337,4 +479,3 @@ void __init ixp4xx_sys_init(void) - ARRAY_SIZE(ixp46x_devices)); - } - } -- ---- linux-2.6.15/arch/arm/mach-ixp4xx/nslu2-setup.c 1970-01-01 00:00:00.000000000 +0000 -+++ linux-2.6.15/arch/arm/mach-ixp4xx/nslu2-setup.c 1970-01-01 00:00:00.000000000 +0000 -@@ -119,6 +119,11 @@ static void nslu2_power_off(void) - - static void __init nslu2_init(void) - { -+ /* The NSLU2 has a 33MHz crystal on board - 1.01% different -+ * from the typical value. -+ */ -+ ixp4xx_set_board_tick_rate(66000000); -+ - ixp4xx_sys_init(); - - pm_power_off = nslu2_power_off; ---- linux-2.6.15/drivers/input/misc/nslu2spkr.c 1970-01-01 00:00:00.000000000 +0000 -+++ linux-2.6.15/drivers/input/misc/nslu2spkr.c 1970-01-01 00:00:00.000000000 +0000 -@@ -51,7 +51,7 @@ static int nslu2_spkr_event(struct input - } - - if (value > 20 && value < 32767) -- count = (NSLU2_FREQ / (value*4)) - 1; -+ count = (ixp4xx_get_board_tick_rate() / (value*4)) - 1; - - spin_lock_irqsave(&beep_lock, flags); - ---- linux-2.6.15/include/asm-arm/arch-ixp4xx/nslu2.h 1970-01-01 00:00:00.000000000 +0000 -+++ linux-2.6.15/include/asm-arm/arch-ixp4xx/nslu2.h 1970-01-01 00:00:00.000000000 +0000 -@@ -38,11 +38,6 @@ - #define NSLU2_PCI_INTD_PIN 8 - - --/* NSLU2 Timer */ --#define NSLU2_FREQ 66000000 --#define NSLU2_CLOCK_TICK_RATE (((NSLU2_FREQ / HZ & ~IXP4XX_OST_RELOAD_MASK) + 1) * HZ) --#define NSLU2_CLOCK_TICKS_PER_USEC ((NSLU2_CLOCK_TICK_RATE + USEC_PER_SEC/2) / USEC_PER_SEC) -- - /* GPIO */ - - #define NSLU2_GPIO0 0 ---- linux-2.6.15/include/asm-arm/arch-ixp4xx/timex.h 1970-01-01 00:00:00.000000000 +0000 -+++ linux-2.6.15/include/asm-arm/arch-ixp4xx/timex.h 1970-01-01 00:00:00.000000000 +0000 -@@ -6,10 +6,23 @@ - #include <asm/hardware.h> - - /* -- * We use IXP425 General purpose timer for our timer needs, it runs at -- * 66.66... MHz. We do a convulted calculation of CLOCK_TICK_RATE b/c the -- * timer register ignores the bottom 2 bits of the LATCH value. -+ * In linux/timex.h 'LATCH' is defined as CLOCK_TICK_RATE/HZ and -+ * is the number of internal counts per timer interrupt. Thus -+ * CLOCK_TICK_RATE is LATCH*HZ. -+ * -+ * The actual values of these numbers do not matter, because they -+ * are only used to calculate ACTHZ (rate/latch as a 24.8 fixed -+ * point number), so the value here gives a LATCH of 1 and pretty -+ * much guarantees to flush out any off-by-one errors. -+ * -+ * ACTHZ is equal to HZ, because CLOCK_TICK_RATE is a multiple of -+ * HZ, this is checked in the ixp4xx/common.c code. - */ --#define FREQ 66666666 --#define CLOCK_TICK_RATE (((FREQ / HZ & ~IXP4XX_OST_RELOAD_MASK) + 1) * HZ) -+#define CLOCK_TICK_RATE HZ - -+/* The following allow the exact board tick rate to be set and -+ * discovered. The value should be exactly twice the frequency -+ * (in Hz) of the onboard crystal. -+ */ -+extern u32 ixp4xx_get_board_tick_rate(void); -+extern void ixp4xx_set_board_tick_rate(u32 new_rate); diff --git a/packages/linux/nslu2-kernel/2.6.15/35-x1205-fix-osc.patch b/packages/linux/nslu2-kernel/2.6.15/35-x1205-fix-osc.patch deleted file mode 100644 index 44f2636c5c..0000000000 --- a/packages/linux/nslu2-kernel/2.6.15/35-x1205-fix-osc.patch +++ /dev/null @@ -1,204 +0,0 @@ - drivers/i2c/chips/x1205.c | 116 ++++++++++++++++++++++++++++++---------------- - 1 file changed, 76 insertions(+), 40 deletions(-) - ---- linux-nslu2.orig/drivers/i2c/chips/x1205.c 2005-12-12 18:59:07.000000000 +0100 -+++ linux-nslu2/drivers/i2c/chips/x1205.c 2005-12-13 21:31:32.000000000 +0100 -@@ -22,9 +22,9 @@ - #include <linux/string.h> - #include <linux/bcd.h> - #include <linux/rtc.h> -+#include <linux/delay.h> - -- --#define DRV_VERSION "1.0.0" -+#define DRV_VERSION "1.0.1" - - /* Addresses to scan: none. This chip is located at - * 0x6f and uses a two bytes register addressing. -@@ -141,35 +141,19 @@ static int x1205_validate_tm(struct rtc_ - * Epoch is initialized as 2000. Time is set to UTC. - */ - static int x1205_get_datetime(struct i2c_client *client, struct rtc_time *tm, -- u8 reg_base) -+ unsigned char reg_base) - { - unsigned char dt_addr[2] = { 0, reg_base }; -- static unsigned char sr_addr[2] = { 0, X1205_REG_SR }; - -- unsigned char buf[8], sr; -+ unsigned char buf[8]; - - struct i2c_msg msgs[] = { -- { client->addr, 0, 2, sr_addr }, /* setup read ptr */ -- { client->addr, I2C_M_RD, 1, &sr }, /* read status */ - { client->addr, 0, 2, dt_addr }, /* setup read ptr */ - { client->addr, I2C_M_RD, 8, buf }, /* read date */ - }; - -- /* read status register */ -- if ((i2c_transfer(client->adapter, &msgs[0], 2)) != 2) { -- dev_err(&client->dev, "%s: read error\n", __FUNCTION__); -- return -EIO; -- } -- -- /* check for battery failure */ -- if (sr & X1205_SR_RTCF) { -- dev_warn(&client->dev, -- "Clock had a power failure, you must set the date.\n"); -- return -EINVAL; -- } -- - /* read date registers */ -- if ((i2c_transfer(client->adapter, &msgs[2], 2)) != 2) { -+ if ((i2c_transfer(client->adapter, &msgs[0], 2)) != 2) { - dev_err(&client->dev, "%s: read error\n", __FUNCTION__); - return -EIO; - } -@@ -199,11 +183,28 @@ static int x1205_get_datetime(struct i2c - return 0; - } - -+static int x1205_get_status(struct i2c_client *client, unsigned char *sr) -+{ -+ static unsigned char sr_addr[2] = { 0, X1205_REG_SR }; -+ -+ struct i2c_msg msgs[] = { -+ { client->addr, 0, 2, sr_addr }, /* setup read ptr */ -+ { client->addr, I2C_M_RD, 1, sr }, /* read status */ -+ }; -+ -+ /* read status register */ -+ if ((i2c_transfer(client->adapter, &msgs[0], 2)) != 2) { -+ dev_err(&client->dev, "%s: read error\n", __FUNCTION__); -+ return -EIO; -+ } -+ -+ return 0; -+} -+ - static int x1205_set_datetime(struct i2c_client *client, struct rtc_time *tm, - int datetoo, u8 reg_base) - { -- int i, err, xfer; -- -+ int i, xfer; - unsigned char buf[8]; - - static const unsigned char wel[3] = { 0, X1205_REG_SR, -@@ -214,15 +215,10 @@ static int x1205_set_datetime(struct i2c - - static const unsigned char diswe[3] = { 0, X1205_REG_SR, 0 }; - -- /* check if all values in the tm struct are correct */ -- if ((err = x1205_validate_tm(tm)) < 0) -- return err; -- -- dev_dbg(&client->dev, "%s: secs=%d, mins=%d, hours=%d, " -- "mday=%d, mon=%d, year=%d, wday=%d\n", -+ dev_dbg(&client->dev, -+ "%s: secs=%d, mins=%d, hours=%d\n", - __FUNCTION__, -- tm->tm_sec, tm->tm_min, tm->tm_hour, -- tm->tm_mday, tm->tm_mon, tm->tm_year, tm->tm_wday); -+ tm->tm_sec, tm->tm_min, tm->tm_hour); - - buf[CCR_SEC] = BIN2BCD(tm->tm_sec); - buf[CCR_MIN] = BIN2BCD(tm->tm_min); -@@ -232,6 +228,11 @@ static int x1205_set_datetime(struct i2c - - /* should we also set the date? */ - if (datetoo) { -+ dev_dbg(&client->dev, -+ "%s: mday=%d, mon=%d, year=%d, wday=%d\n", -+ __FUNCTION__, -+ tm->tm_mday, tm->tm_mon, tm->tm_year, tm->tm_wday); -+ - buf[CCR_MDAY] = BIN2BCD(tm->tm_mday); - - /* month, 0 - 11 */ -@@ -280,6 +281,22 @@ static int x1205_set_datetime(struct i2c - return 0; - } - -+static int x1205_fix_osc(struct i2c_client *client) -+{ -+ int err; -+ struct rtc_time tm; -+ -+ tm.tm_hour = 0; -+ tm.tm_min = 0; -+ tm.tm_sec = 0; -+ -+ if ((err = x1205_set_datetime(client, &tm, 0, X1205_CCR_BASE)) < 0) -+ dev_err(&client->dev, -+ "unable to restart the clock\n"); -+ -+ return err; -+} -+ - static int x1205_get_dtrim(struct i2c_client *client, int *trim) - { - unsigned char dtr; -@@ -352,14 +369,17 @@ static int x1205_hctosys(struct i2c_clie - - struct rtc_time tm; - struct timespec tv; -+ unsigned char sr; - -+ if ((err = x1205_get_status(client, &sr)) < 0) -+ return err; - -- err = x1205_get_datetime(client, &tm, X1205_CCR_BASE); -- if (err) { -- dev_err(&client->dev, -- "Unable to set the system clock\n"); -+ /* Don't set if we had a power failure */ -+ if (sr & X1205_SR_RTCF) -+ return -EINVAL; -+ -+ if ((err = x1205_get_datetime(client, &tm, X1205_CCR_BASE)) < 0) - return err; -- } - - /* IMPORTANT: the RTC only stores whole seconds. It is arbitrary - * whether it stores the most close value or the value with partial -@@ -506,9 +526,9 @@ static int x1205_attach(struct i2c_adapt - - static int x1205_probe(struct i2c_adapter *adapter, int address, int kind) - { -- struct i2c_client *client; -- - int err = 0; -+ unsigned char sr; -+ struct i2c_client *client; - - dev_dbg(&adapter->dev, "%s\n", __FUNCTION__); - -@@ -543,9 +563,25 @@ static int x1205_probe(struct i2c_adapte - - dev_info(&client->dev, "chip found, driver version " DRV_VERSION "\n"); - -+ /* Check for power failures and eventualy enable the osc */ -+ if ((err = x1205_get_status(client, &sr)) == 0) { -+ if (sr & X1205_SR_RTCF) { -+ dev_err(&client->dev, -+ "power failure detected, " -+ "please set the clock\n"); -+ udelay(50); -+ x1205_fix_osc(client); -+ } -+ } -+ else -+ dev_err(&client->dev, "couldn't read status\n"); -+ - /* If requested, set the system time */ -- if (hctosys) -- x1205_hctosys(client); -+ if (hctosys) { -+ if ((err = x1205_hctosys(client)) < 0) -+ dev_err(&client->dev, -+ "unable to set the system clock\n"); -+ } - - return 0; - diff --git a/packages/linux/nslu2-kernel/2.6.15/60-nslu2-rtc.patch b/packages/linux/nslu2-kernel/2.6.15/60-nslu2-rtc.patch deleted file mode 100644 index 9e390c6b7a..0000000000 --- a/packages/linux/nslu2-kernel/2.6.15/60-nslu2-rtc.patch +++ /dev/null @@ -1,21 +0,0 @@ - arch/arm/mach-ixp4xx/nslu2-setup.c | 5 +++++ - 1 file changed, 5 insertions(+) - ---- linux-2.6.15/arch/arm/mach-ixp4xx/nslu2-setup.c 1970-01-01 00:00:00.000000000 +0000 -+++ linux-2.6.15/arch/arm/mach-ixp4xx/nslu2-setup.c 1970-01-01 00:00:00.000000000 +0000 -@@ -95,10 +95,15 @@ static struct platform_device nslu2_uart - .resource = nslu2_uart_resources, - }; - -+static struct platform_device nslu2_rtc = { -+ .name = "x1205-rtc", -+}; -+ - static struct platform_device *nslu2_devices[] __initdata = { - &nslu2_i2c_controller, - &nslu2_flash, - &nslu2_uart, -+ &nslu2_rtc, - }; - - static void nslu2_power_off(void) 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 deleted file mode 100644 index c106f7c957..0000000000 --- a/packages/linux/nslu2-kernel/2.6.15/90-ixp4xx-nslu2.patch +++ /dev/null @@ -1,132 +0,0 @@ -ixp4xx updates: - - Handle reads that don't start on a half-word boundary. - - Make it work when CPU is in little-endian mode. - -Signed-off-by: John Bowler <jbowler@acm.org> -Signed-off-by: Alessandro Zummo <a.zummo@towertech.it> -Signed-off-by: David Vrabel <dvrabel@arcom.com> - -Index: linux-2.6-working/drivers/mtd/maps/ixp4xx.c -=================================================================== ---- linux-2.6-working.orig/drivers/mtd/maps/ixp4xx.c 2005-11-16 15:19:34.000000000 +0000 -+++ linux-2.6-working/drivers/mtd/maps/ixp4xx.c 2005-11-16 16:06:54.000000000 +0000 -@@ -34,10 +34,55 @@ - - #include <linux/reboot.h> - -+/* -+ * 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. -+ * -+ * To further complicate matters, due to the way the expansion bus controller -+ * handles 32 bit reads, the byte stream ABCD is stored on the flash as: -+ * D15 D0 -+ * +---+---+ -+ * | A | B | 0 -+ * +---+---+ -+ * | C | D | 2 -+ * +---+---+ -+ * This means that on LE systems each 16 bit word must be swapped. Note that -+ * this requires CONFIG_MTD_CFI_BE_BYTE_SWAP to be enabled to 'unswap' the CFI -+ * data and other flash commands which are always in D7-D0. -+ */ - #ifndef __ARMEB__ -+#ifndef CONFIG_MTD_CFI_BE_BYTE_SWAP -+# error CONFIG_MTD_CFI_BE_BYTE_SWAP required -+#endif -+ -+static inline u16 flash_read16(void __iomem *addr) -+{ -+ return be16_to_cpu(__raw_readw((void __iomem *)((unsigned long)addr ^ 0x2))); -+} -+ -+static inline void flash_write16(u16 d, void __iomem *addr) -+{ -+ __raw_writew(cpu_to_be16(d), (void __iomem *)((unsigned long)addr ^ 0x2)); -+} -+ - #define BYTE0(h) ((h) & 0xFF) - #define BYTE1(h) (((h) >> 8) & 0xFF) -+ - #else -+ -+static inline u16 flash_read16(const void __iomem *addr) -+{ -+ return __raw_readw(addr); -+} -+ -+static inline void flash_write16(u16 d, void __iomem *addr) -+{ -+ __raw_writew(d, addr); -+} -+ - #define BYTE0(h) (((h) >> 8) & 0xFF) - #define BYTE1(h) ((h) & 0xFF) - #endif -@@ -45,7 +90,7 @@ - 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; - } - -@@ -57,19 +102,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(flash_read16(src)); -+ src++; -+ --len; - } - -- if (len & 1) -- dest[len - 1] = BYTE0(le16_to_cpu(readw(src + 2*i))); -+ while (len >= 2) { -+ u16 data = flash_read16(src); -+ *dest++ = BYTE0(data); -+ *dest++ = BYTE1(data); -+ src += 2; -+ len -= 2; -+ } -+ -+ if (len > 0) -+ *dest++ = BYTE0(flash_read16(src)); - } - - /* -@@ -79,7 +133,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); - } - - /* -@@ -87,7 +141,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 { |