summaryrefslogtreecommitdiffstats
path: root/target/linux/atheros/patches-2.6.28
diff options
context:
space:
mode:
Diffstat (limited to 'target/linux/atheros/patches-2.6.28')
-rw-r--r--target/linux/atheros/patches-2.6.28/100-board.patch66
-rw-r--r--target/linux/atheros/patches-2.6.28/110-spiflash.patch20
-rw-r--r--target/linux/atheros/patches-2.6.28/120-watchdog.patch25
-rw-r--r--target/linux/atheros/patches-2.6.28/130-ar2313_ethernet.patch25
-rw-r--r--target/linux/atheros/patches-2.6.28/135-ar2313_2.6.26.patch11
-rw-r--r--target/linux/atheros/patches-2.6.28/137-ar2313_2.6.28.patch144
-rw-r--r--target/linux/atheros/patches-2.6.28/140-redboot_partition_scan.patch54
-rw-r--r--target/linux/atheros/patches-2.6.28/200-ar2313_enable_mvswitch.patch70
-rw-r--r--target/linux/atheros/patches-2.6.28/901-get_c0_compare_irq_function.patch43
-rw-r--r--target/linux/atheros/patches-2.6.28/902-mips_clocksource_init_war.patch56
10 files changed, 514 insertions, 0 deletions
diff --git a/target/linux/atheros/patches-2.6.28/100-board.patch b/target/linux/atheros/patches-2.6.28/100-board.patch
new file mode 100644
index 000000000..c7f374559
--- /dev/null
+++ b/target/linux/atheros/patches-2.6.28/100-board.patch
@@ -0,0 +1,66 @@
+--- a/arch/mips/Kconfig
++++ b/arch/mips/Kconfig
+@@ -60,6 +60,18 @@ config BCM47XX
+ help
+ Support for BCM47XX based boards
+
++config ATHEROS
++ bool "Atheros SoC support (EXPERIMENTAL)"
++ depends on EXPERIMENTAL
++ select DMA_NONCOHERENT
++ select CEVT_R4K
++ select CSRC_R4K
++ select IRQ_CPU
++ select SYS_HAS_CPU_MIPS32_R1
++ select SYS_SUPPORTS_BIG_ENDIAN
++ select SYS_SUPPORTS_32BIT_KERNEL
++ select GENERIC_GPIO
++
+ config MIPS_COBALT
+ bool "Cobalt Server"
+ select CEVT_R4K
+@@ -597,6 +609,7 @@ config WR_PPMC
+
+ endchoice
+
++source "arch/mips/atheros/Kconfig"
+ source "arch/mips/alchemy/Kconfig"
+ source "arch/mips/basler/excite/Kconfig"
+ source "arch/mips/emma/Kconfig"
+--- a/arch/mips/Makefile
++++ b/arch/mips/Makefile
+@@ -278,6 +278,13 @@ libs-$(CONFIG_MIPS_XXS1500) += arch/mips
+ load-$(CONFIG_MIPS_XXS1500) += 0xffffffff80100000
+
+ #
++# Atheros AR5312/AR2312 WiSoC
++#
++core-$(CONFIG_ATHEROS) += arch/mips/atheros/
++cflags-$(CONFIG_ATHEROS) += -I$(srctree)/arch/mips/include/asm/mach-atheros
++load-$(CONFIG_ATHEROS) += 0xffffffff80041000
++
++#
+ # Cobalt Server
+ #
+ core-$(CONFIG_MIPS_COBALT) += arch/mips/cobalt/
+--- a/arch/mips/include/asm/bootinfo.h
++++ b/arch/mips/include/asm/bootinfo.h
+@@ -57,6 +57,18 @@
+ #define MACH_MIKROTIK_RB532 0 /* Mikrotik RouterBoard 532 */
+ #define MACH_MIKROTIK_RB532A 1 /* Mikrotik RouterBoard 532A */
+
++/*
++ * Valid machtype for group ATHEROS
++ */
++#define MACH_GROUP_ATHEROS 26
++#define MACH_ATHEROS_AR5312 0
++#define MACH_ATHEROS_AR2312 1
++#define MACH_ATHEROS_AR2313 2
++#define MACH_ATHEROS_AR2315 3
++#define MACH_ATHEROS_AR2316 4
++#define MACH_ATHEROS_AR2317 5
++#define MACH_ATHEROS_AR2318 6
++
+ #define CL_SIZE COMMAND_LINE_SIZE
+
+ extern char *system_type;
diff --git a/target/linux/atheros/patches-2.6.28/110-spiflash.patch b/target/linux/atheros/patches-2.6.28/110-spiflash.patch
new file mode 100644
index 000000000..4b9b9d689
--- /dev/null
+++ b/target/linux/atheros/patches-2.6.28/110-spiflash.patch
@@ -0,0 +1,20 @@
+--- a/drivers/mtd/devices/Kconfig
++++ b/drivers/mtd/devices/Kconfig
+@@ -104,6 +104,10 @@ config M25PXX_USE_FAST_READ
+ help
+ This option enables FAST_READ access supported by ST M25Pxx.
+
++config MTD_SPIFLASH
++ tristate "Atheros AR2315/6/7 SPI Flash support"
++ depends on ATHEROS_AR5315
++
+ config MTD_SLRAM
+ tristate "Uncached system RAM"
+ help
+--- a/drivers/mtd/devices/Makefile
++++ b/drivers/mtd/devices/Makefile
+@@ -16,3 +16,4 @@ obj-$(CONFIG_MTD_LART) += lart.o
+ obj-$(CONFIG_MTD_BLOCK2MTD) += block2mtd.o
+ obj-$(CONFIG_MTD_DATAFLASH) += mtd_dataflash.o
+ obj-$(CONFIG_MTD_M25P80) += m25p80.o
++obj-$(CONFIG_MTD_SPIFLASH) += spiflash.o
diff --git a/target/linux/atheros/patches-2.6.28/120-watchdog.patch b/target/linux/atheros/patches-2.6.28/120-watchdog.patch
new file mode 100644
index 000000000..88c42a2a8
--- /dev/null
+++ b/target/linux/atheros/patches-2.6.28/120-watchdog.patch
@@ -0,0 +1,25 @@
+--- a/drivers/watchdog/Kconfig
++++ b/drivers/watchdog/Kconfig
+@@ -747,6 +747,12 @@ config TXX9_WDT
+ help
+ Hardware driver for the built-in watchdog timer on TXx9 MIPS SoCs.
+
++config ATHEROS_WDT
++ tristate "Atheros wisoc Watchdog Timer"
++ depends on ATHEROS
++ help
++ Hardware driver for the Atheros wisoc Watchdog Timer.
++
+ # PARISC Architecture
+
+ # POWERPC Architecture
+--- a/drivers/watchdog/Makefile
++++ b/drivers/watchdog/Makefile
+@@ -106,6 +106,7 @@ obj-$(CONFIG_WDT_RM9K_GPI) += rm9k_wdt.o
+ obj-$(CONFIG_SIBYTE_WDOG) += sb_wdog.o
+ obj-$(CONFIG_AR7_WDT) += ar7_wdt.o
+ obj-$(CONFIG_TXX9_WDT) += txx9wdt.o
++obj-$(CONFIG_ATHEROS_WDT) += ar2315-wtd.o
+
+ # PARISC Architecture
+
diff --git a/target/linux/atheros/patches-2.6.28/130-ar2313_ethernet.patch b/target/linux/atheros/patches-2.6.28/130-ar2313_ethernet.patch
new file mode 100644
index 000000000..5c183a431
--- /dev/null
+++ b/target/linux/atheros/patches-2.6.28/130-ar2313_ethernet.patch
@@ -0,0 +1,25 @@
+--- a/drivers/net/Kconfig
++++ b/drivers/net/Kconfig
+@@ -359,6 +359,12 @@ config AX88796_93CX6
+ help
+ Select this if your platform comes with an external 93CX6 eeprom.
+
++config AR2313
++ tristate "AR2313 Ethernet support"
++ depends on NET_ETHERNET && ATHEROS
++ help
++ Support for the AR231x/531x ethernet controller
++
+ config MACE
+ tristate "MACE (Power Mac ethernet) support"
+ depends on PPC_PMAC && PPC32
+--- a/drivers/net/Makefile
++++ b/drivers/net/Makefile
+@@ -199,6 +199,7 @@ obj-$(CONFIG_EQUALIZER) += eql.o
+ obj-$(CONFIG_KORINA) += korina.o
+ obj-$(CONFIG_MIPS_JAZZ_SONIC) += jazzsonic.o
+ obj-$(CONFIG_MIPS_AU1X00_ENET) += au1000_eth.o
++obj-$(CONFIG_AR2313) += ar2313/
+ obj-$(CONFIG_MIPS_SIM_NET) += mipsnet.o
+ obj-$(CONFIG_SGI_IOC3_ETH) += ioc3-eth.o
+ obj-$(CONFIG_DECLANCE) += declance.o
diff --git a/target/linux/atheros/patches-2.6.28/135-ar2313_2.6.26.patch b/target/linux/atheros/patches-2.6.28/135-ar2313_2.6.26.patch
new file mode 100644
index 000000000..a39b46c0b
--- /dev/null
+++ b/target/linux/atheros/patches-2.6.28/135-ar2313_2.6.26.patch
@@ -0,0 +1,11 @@
+--- a/drivers/net/ar2313/ar2313.c
++++ b/drivers/net/ar2313/ar2313.c
+@@ -291,7 +291,7 @@ int __init ar2313_probe(struct platform_
+ sp->mii_bus.write = mdiobus_write;
+ sp->mii_bus.reset = mdiobus_reset;
+ sp->mii_bus.name = "ar2313_eth_mii";
+- sp->mii_bus.id = 0;
++ snprintf(sp->mii_bus.id, MII_BUS_ID_SIZE, "0");
+ sp->mii_bus.irq = kmalloc(sizeof(int), GFP_KERNEL);
+ *sp->mii_bus.irq = PHY_POLL;
+
diff --git a/target/linux/atheros/patches-2.6.28/137-ar2313_2.6.28.patch b/target/linux/atheros/patches-2.6.28/137-ar2313_2.6.28.patch
new file mode 100644
index 000000000..0f4d73263
--- /dev/null
+++ b/target/linux/atheros/patches-2.6.28/137-ar2313_2.6.28.patch
@@ -0,0 +1,144 @@
+This patch reflects changes in mdiobus implementation in kernel 2.6.28.
+--- a/drivers/net/ar2313/ar2313.c
++++ b/drivers/net/ar2313/ar2313.c
+@@ -159,10 +159,10 @@ static void rx_tasklet_func(unsigned lon
+ static void rx_tasklet_cleanup(struct net_device *dev);
+ static void ar2313_multicast_list(struct net_device *dev);
+
+-static int mdiobus_read(struct mii_bus *bus, int phy_addr, int regnum);
+-static int mdiobus_write(struct mii_bus *bus, int phy_addr, int regnum, u16 value);
+-static int mdiobus_reset(struct mii_bus *bus);
+-static int mdiobus_probe (struct net_device *dev);
++static int ar2313_mdiobus_read(struct mii_bus *bus, int phy_addr, int regnum);
++static int ar2313_mdiobus_write(struct mii_bus *bus, int phy_addr, int regnum, u16 value);
++static int ar2313_mdiobus_reset(struct mii_bus *bus);
++static int ar2313_mdiobus_probe (struct net_device *dev);
+ static void ar2313_adjust_link(struct net_device *dev);
+
+ #ifndef ERR
+@@ -286,18 +286,22 @@ int __init ar2313_probe(struct platform_
+ dev->dev_addr[0], dev->dev_addr[1], dev->dev_addr[2],
+ dev->dev_addr[3], dev->dev_addr[4], dev->dev_addr[5], dev->irq);
+
+- sp->mii_bus.priv = dev;
+- sp->mii_bus.read = mdiobus_read;
+- sp->mii_bus.write = mdiobus_write;
+- sp->mii_bus.reset = mdiobus_reset;
+- sp->mii_bus.name = "ar2313_eth_mii";
+- snprintf(sp->mii_bus.id, MII_BUS_ID_SIZE, "0");
+- sp->mii_bus.irq = kmalloc(sizeof(int), GFP_KERNEL);
+- *sp->mii_bus.irq = PHY_POLL;
++ sp->mii_bus = mdiobus_alloc();
++ if (sp->mii_bus == NULL)
++ return -1;
++
++ sp->mii_bus->priv = dev;
++ sp->mii_bus->read = ar2313_mdiobus_read;
++ sp->mii_bus->write = ar2313_mdiobus_write;
++ sp->mii_bus->reset = ar2313_mdiobus_reset;
++ sp->mii_bus->name = "ar2313_eth_mii";
++ snprintf(sp->mii_bus->id, MII_BUS_ID_SIZE, "0");
++ sp->mii_bus->irq = kmalloc(sizeof(int), GFP_KERNEL);
++ *sp->mii_bus->irq = PHY_POLL;
+
+- mdiobus_register(&sp->mii_bus);
++ mdiobus_register(sp->mii_bus);
+
+- if (mdiobus_probe(dev) != 0) {
++ if (ar2313_mdiobus_probe(dev) != 0) {
+ printk(KERN_ERR "ar2313: mdiobus_probe failed");
+ rx_tasklet_cleanup(dev);
+ ar2313_init_cleanup(dev);
+@@ -432,9 +436,12 @@ static void rx_tasklet_cleanup(struct ne
+ static int __exit ar2313_remove(struct platform_device *pdev)
+ {
+ struct net_device *dev = platform_get_drvdata(pdev);
++ struct ar2313_private *sp = netdev_priv(dev);
+ rx_tasklet_cleanup(dev);
+ ar2313_init_cleanup(dev);
+ unregister_netdev(dev);
++ mdiobus_unregister(sp->mii_bus);
++ mdiobus_free(sp->mii_bus);
+ kfree(dev);
+ return 0;
+ }
+@@ -619,7 +626,7 @@ static void ar2313_check_link(struct net
+ struct ar2313_private *sp = netdev_priv(dev);
+ u16 phyData;
+
+- phyData = mdiobus_read(&sp->mii_bus, sp->phy, MII_BMSR);
++ phyData = ar2313_mdiobus_read(sp->mii_bus, sp->phy, MII_BMSR);
+ if (sp->phyData != phyData) {
+ if (phyData & BMSR_LSTATUS) {
+ /* link is present, ready link partner ability to deterine
+@@ -628,10 +635,10 @@ static void ar2313_check_link(struct net
+ u16 reg;
+
+ sp->link = 1;
+- reg = mdiobus_read(&sp->mii_bus, sp->phy, MII_BMCR);
++ reg = ar2313_mdiobus_read(sp->mii_bus, sp->phy, MII_BMCR);
+ if (reg & BMCR_ANENABLE) {
+ /* auto neg enabled */
+- reg = mdiobus_read(&sp->mii_bus, sp->phy, MII_LPA);
++ reg = ar2313_mdiobus_read(sp->mii_bus, sp->phy, MII_LPA);
+ duplex = (reg & (LPA_100FULL | LPA_10FULL)) ? 1 : 0;
+ } else {
+ /* no auto neg, just read duplex config */
+@@ -1320,7 +1327,7 @@ static void ar2313_adjust_link(struct ne
+ ((reg << MII_ADDR_REG_SHIFT) | (phy << MII_ADDR_PHY_SHIFT))
+
+ static int
+-mdiobus_read(struct mii_bus *bus, int phy_addr, int regnum)
++ar2313_mdiobus_read(struct mii_bus *bus, int phy_addr, int regnum)
+ {
+ struct net_device *const dev = bus->priv;
+ struct ar2313_private *sp = netdev_priv(dev);
+@@ -1332,7 +1339,7 @@ mdiobus_read(struct mii_bus *bus, int ph
+ }
+
+ static int
+-mdiobus_write(struct mii_bus *bus, int phy_addr, int regnum,
++ar2313_mdiobus_write(struct mii_bus *bus, int phy_addr, int regnum,
+ u16 value)
+ {
+ struct net_device *const dev = bus->priv;
+@@ -1346,7 +1353,7 @@ mdiobus_write(struct mii_bus *bus, int p
+ return 0;
+ }
+
+-static int mdiobus_reset(struct mii_bus *bus)
++static int ar2313_mdiobus_reset(struct mii_bus *bus)
+ {
+ struct net_device *const dev = bus->priv;
+
+@@ -1355,7 +1362,7 @@ static int mdiobus_reset(struct mii_bus
+ return 0;
+ }
+
+-static int mdiobus_probe (struct net_device *dev)
++static int ar2313_mdiobus_probe (struct net_device *dev)
+ {
+ struct ar2313_private *const sp = netdev_priv(dev);
+ struct phy_device *phydev = NULL;
+@@ -1363,8 +1370,8 @@ static int mdiobus_probe (struct net_dev
+
+ /* find the first (lowest address) PHY on the current MAC's MII bus */
+ for (phy_addr = 0; phy_addr < PHY_MAX_ADDR; phy_addr++)
+- if (sp->mii_bus.phy_map[phy_addr]) {
+- phydev = sp->mii_bus.phy_map[phy_addr];
++ if (sp->mii_bus->phy_map[phy_addr]) {
++ phydev = sp->mii_bus->phy_map[phy_addr];
+ break; /* break out with first one found */
+ }
+
+--- a/drivers/net/ar2313/ar2313.h
++++ b/drivers/net/ar2313/ar2313.h
+@@ -162,7 +162,7 @@ struct ar2313_private {
+ int unloading;
+
+ struct phy_device *phy_dev;
+- struct mii_bus mii_bus;
++ struct mii_bus *mii_bus;
+ int oldduplex;
+ };
+
diff --git a/target/linux/atheros/patches-2.6.28/140-redboot_partition_scan.patch b/target/linux/atheros/patches-2.6.28/140-redboot_partition_scan.patch
new file mode 100644
index 000000000..289d4eb99
--- /dev/null
+++ b/target/linux/atheros/patches-2.6.28/140-redboot_partition_scan.patch
@@ -0,0 +1,54 @@
+--- a/drivers/mtd/redboot.c
++++ b/drivers/mtd/redboot.c
+@@ -60,31 +60,32 @@ static int parse_redboot_partitions(stru
+ static char nullstring[] = "unallocated";
+ #endif
+
++ buf = vmalloc(master->erasesize);
++ if (!buf)
++ return -ENOMEM;
++
++ restart:
+ if ( directory < 0 ) {
+ offset = master->size + directory * master->erasesize;
+- while (master->block_isbad &&
++ while (master->block_isbad &&
+ master->block_isbad(master, offset)) {
+ if (!offset) {
+ nogood:
+ printk(KERN_NOTICE "Failed to find a non-bad block to check for RedBoot partition table\n");
++ vfree(buf);
+ return -EIO;
+ }
+ offset -= master->erasesize;
+ }
+ } else {
+ offset = directory * master->erasesize;
+- while (master->block_isbad &&
++ while (master->block_isbad &&
+ master->block_isbad(master, offset)) {
+ offset += master->erasesize;
+ if (offset == master->size)
+ goto nogood;
+ }
+ }
+- buf = vmalloc(master->erasesize);
+-
+- if (!buf)
+- return -ENOMEM;
+-
+ printk(KERN_NOTICE "Searching for RedBoot partition table in %s at offset 0x%lx\n",
+ master->name, offset);
+
+@@ -156,6 +157,11 @@ static int parse_redboot_partitions(stru
+ }
+ if (i == numslots) {
+ /* Didn't find it */
++ if (offset + master->erasesize < master->size) {
++ /* not at the end of the flash yet, maybe next block :) */
++ directory++;
++ goto restart;
++ }
+ printk(KERN_NOTICE "No RedBoot partition table detected in %s\n",
+ master->name);
+ ret = 0;
diff --git a/target/linux/atheros/patches-2.6.28/200-ar2313_enable_mvswitch.patch b/target/linux/atheros/patches-2.6.28/200-ar2313_enable_mvswitch.patch
new file mode 100644
index 000000000..710314d7f
--- /dev/null
+++ b/target/linux/atheros/patches-2.6.28/200-ar2313_enable_mvswitch.patch
@@ -0,0 +1,70 @@
+--- a/drivers/net/ar2313/ar2313.c
++++ b/drivers/net/ar2313/ar2313.c
+@@ -841,6 +841,7 @@ static void ar2313_load_rx_ring(struct n
+ for (i = 0; i < nr_bufs; i++) {
+ struct sk_buff *skb;
+ ar2313_descr_t *rd;
++ int offset = RX_OFFSET;
+
+ if (sp->rx_skb[idx]) {
+ #if DEBUG_RX
+@@ -862,7 +863,9 @@ static void ar2313_load_rx_ring(struct n
+ * Make sure IP header starts on a fresh cache line.
+ */
+ skb->dev = dev;
+- skb_reserve(skb, RX_OFFSET);
++ if (sp->phy_dev)
++ offset += sp->phy_dev->pkt_align;
++ skb_reserve(skb, offset);
+ sp->rx_skb[idx] = skb;
+
+ rd = (ar2313_descr_t *) & sp->rx_ring[idx];
+@@ -953,6 +956,7 @@ static int ar2313_rx_int(struct net_devi
+ /* alloc new buffer. */
+ skb_new = dev_alloc_skb(AR2313_BUFSIZE + RX_OFFSET + 128);
+ if (skb_new != NULL) {
++ int offset;
+
+ skb = sp->rx_skb[idx];
+ /* set skb */
+@@ -960,13 +964,17 @@ static int ar2313_rx_int(struct net_devi
+ ((status >> DMA_RX_LEN_SHIFT) & 0x3fff) - CRC_LEN);
+
+ dev->stats.rx_bytes += skb->len;
+- skb->protocol = eth_type_trans(skb, dev);
++
+ /* pass the packet to upper layers */
+- netif_rx(skb);
++ sp->rx(skb);
+
+ skb_new->dev = dev;
++
+ /* 16 bit align */
+- skb_reserve(skb_new, RX_OFFSET + 32);
++ offset = RX_OFFSET + 32;
++ if (sp->phy_dev)
++ offset += sp->phy_dev->pkt_align;
++ skb_reserve(skb_new, offset);
+ /* reset descriptor's curr_addr */
+ rxdesc->addr = virt_to_phys(skb_new->data);
+
+@@ -1392,6 +1400,8 @@ static int ar2313_mdiobus_probe (struct
+ return PTR_ERR(phydev);
+ }
+
++ sp->rx = phydev->netif_rx;
++
+ /* mask with MAC supported features */
+ phydev->supported &= (SUPPORTED_10baseT_Half
+ | SUPPORTED_10baseT_Full
+--- a/drivers/net/ar2313/ar2313.h
++++ b/drivers/net/ar2313/ar2313.h
+@@ -107,6 +107,8 @@ typedef struct {
+ */
+ struct ar2313_private {
+ struct net_device *dev;
++ int (*rx)(struct sk_buff *skb);
++
+ int version;
+ u32 mb[2];
+
diff --git a/target/linux/atheros/patches-2.6.28/901-get_c0_compare_irq_function.patch b/target/linux/atheros/patches-2.6.28/901-get_c0_compare_irq_function.patch
new file mode 100644
index 000000000..9b4331cfd
--- /dev/null
+++ b/target/linux/atheros/patches-2.6.28/901-get_c0_compare_irq_function.patch
@@ -0,0 +1,43 @@
+--- a/arch/mips/kernel/traps.c
++++ b/arch/mips/kernel/traps.c
+@@ -47,6 +47,7 @@
+ #include <asm/mmu_context.h>
+ #include <asm/types.h>
+ #include <asm/stacktrace.h>
++#include <asm/time.h>
+
+ extern void check_wait(void);
+ extern asmlinkage void r4k_wait(void);
+@@ -1514,6 +1515,8 @@ void __cpuinit per_cpu_trap_init(void)
+ */
+ if (cpu_has_mips_r2) {
+ cp0_compare_irq = (read_c0_intctl() >> 29) & 7;
++ if (get_c0_compare_irq)
++ cp0_compare_irq = get_c0_compare_irq();
+ cp0_perfcount_irq = (read_c0_intctl() >> 26) & 7;
+ if (cp0_perfcount_irq == cp0_compare_irq)
+ cp0_perfcount_irq = -1;
+--- a/arch/mips/include/asm/time.h
++++ b/arch/mips/include/asm/time.h
+@@ -53,6 +53,7 @@ extern int (*perf_irq)(void);
+ #ifdef CONFIG_CEVT_R4K
+ extern int mips_clockevent_init(void);
+ extern unsigned int __weak get_c0_compare_int(void);
++extern unsigned int __weak get_c0_compare_irq(void);
+ #else
+ static inline int mips_clockevent_init(void)
+ {
+--- a/arch/mips/atheros/board.c
++++ b/arch/mips/atheros/board.c
+@@ -265,6 +265,11 @@ void (*board_time_init)(void);
+ void __init plat_time_init(void) {
+ board_time_init();
+ }
++
++unsigned int __cpuinit get_c0_compare_irq(void)
++{
++ return CP0_LEGACY_COMPARE_IRQ;
++}
+ #endif
+
+ void __init arch_init_irq(void)
diff --git a/target/linux/atheros/patches-2.6.28/902-mips_clocksource_init_war.patch b/target/linux/atheros/patches-2.6.28/902-mips_clocksource_init_war.patch
new file mode 100644
index 000000000..03a66ff13
--- /dev/null
+++ b/target/linux/atheros/patches-2.6.28/902-mips_clocksource_init_war.patch
@@ -0,0 +1,56 @@
+--- a/arch/mips/kernel/cevt-r4k.c
++++ b/arch/mips/kernel/cevt-r4k.c
+@@ -15,6 +15,22 @@
+ #include <asm/cevt-r4k.h>
+
+ /*
++ * Compare interrupt can be routed and latched outside the core,
++ * so a single execution hazard barrier may not be enough to give
++ * it time to clear as seen in the Cause register. 4 time the
++ * pipeline depth seems reasonably conservative, and empirically
++ * works better in configurations with high CPU/bus clock ratios.
++ */
++
++#define compare_change_hazard() \
++ do { \
++ irq_disable_hazard(); \
++ irq_disable_hazard(); \
++ irq_disable_hazard(); \
++ irq_disable_hazard(); \
++ } while (0)
++
++/*
+ * The SMTC Kernel for the 34K, 1004K, et. al. replaces several
+ * of these routines with SMTC-specific variants.
+ */
+@@ -30,6 +46,7 @@ static int mips_next_event(unsigned long
+ cnt = read_c0_count();
+ cnt += delta;
+ write_c0_compare(cnt);
++ compare_change_hazard();
+ res = ((int)(read_c0_count() - cnt) > 0) ? -ETIME : 0;
+ return res;
+ }
+@@ -99,22 +116,6 @@ static int c0_compare_int_pending(void)
+ return (read_c0_cause() >> cp0_compare_irq) & 0x100;
+ }
+
+-/*
+- * Compare interrupt can be routed and latched outside the core,
+- * so a single execution hazard barrier may not be enough to give
+- * it time to clear as seen in the Cause register. 4 time the
+- * pipeline depth seems reasonably conservative, and empirically
+- * works better in configurations with high CPU/bus clock ratios.
+- */
+-
+-#define compare_change_hazard() \
+- do { \
+- irq_disable_hazard(); \
+- irq_disable_hazard(); \
+- irq_disable_hazard(); \
+- irq_disable_hazard(); \
+- } while (0)
+-
+ int c0_compare_int_usable(void)
+ {
+ unsigned int delta;