浏览代码

refactor atheros system code - also add support for the reset button (sends netlink messages in the same format as broadcom-diag)

SVN-Revision: 7869
Felix Fietkau 18 年之前
父节点
当前提交
e062f4185e

+ 3 - 12
target/linux/atheros-2.6/files/arch/mips/atheros/Makefile

@@ -3,20 +3,11 @@
 # License.  See the file "COPYING" in the main directory of this archive
 # License.  See the file "COPYING" in the main directory of this archive
 # for more details.
 # for more details.
 #
 #
-# Copyright (C) 2003 Atheros Communications, Inc.,  All Rights Reserved.
 # Copyright (C) 2006 FON Technology, SL.
 # Copyright (C) 2006 FON Technology, SL.
 # Copyright (C) 2006 Imre Kaloz <[email protected]>
 # Copyright (C) 2006 Imre Kaloz <[email protected]>
 # Copyright (C) 2006 Felix Fietkau <[email protected]>
 # Copyright (C) 2006 Felix Fietkau <[email protected]>
 #
 #
 
 
-# Makefile for Atheros ar531x boards
-#
-# Note! Dependencies are done automagically by 'make dep', which also
-# removes any old dependencies. DON'T put your own dependencies here
-# unless it's something special (ie not a .c file).
-#
-
-obj-y += board.o prom.o irq.o
-obj-$(CONFIG_ATHEROS_AR5312) += ar5312.o
-obj-$(CONFIG_ATHEROS_AR5315) += ar5315.o
-
+obj-y += board.o prom.o reset.o
+obj-$(CONFIG_ATHEROS_AR5312) += ar5312/
+obj-$(CONFIG_ATHEROS_AR5315) += ar5315/

+ 11 - 0
target/linux/atheros-2.6/files/arch/mips/atheros/ar5312/Makefile

@@ -0,0 +1,11 @@
+#
+# This file is subject to the terms and conditions of the GNU General Public
+# License.  See the file "COPYING" in the main directory of this archive
+# for more details.
+#
+# Copyright (C) 2007 FON Technology, SL.
+# Copyright (C) 2007 Imre Kaloz <[email protected]>
+# Copyright (C) 2007 Felix Fietkau <[email protected]>
+#
+
+obj-y := board.o irq.o

+ 0 - 0
target/linux/atheros-2.6/files/arch/mips/atheros/ar5312.h → target/linux/atheros-2.6/files/arch/mips/atheros/ar5312/ar5312.h


+ 1 - 146
target/linux/atheros-2.6/files/arch/mips/atheros/ar5312.c → target/linux/atheros-2.6/files/arch/mips/atheros/ar5312/board.c

@@ -27,7 +27,7 @@
 #include <asm/time.h>
 #include <asm/time.h>
 #include <asm/irq.h>
 #include <asm/irq.h>
 #include <asm/io.h>
 #include <asm/io.h>
-#include "ar531x.h"
+#include "../ar531x.h"
 
 
 #define NO_PHY 0x1f
 #define NO_PHY 0x1f
 
 
@@ -312,47 +312,6 @@ int __init ar5312_init_devices(void)
 }
 }
 
 
 
 
-/*
- * Called when an interrupt is received, this function
- * determines exactly which interrupt it was, and it
- * invokes the appropriate handler.
- *
- * Implicitly, we also define interrupt priority by
- * choosing which to dispatch first.
- */
-asmlinkage void ar5312_irq_dispatch(void)
-{
-	int pending = read_c0_status() & read_c0_cause();
-
-	if (pending & CAUSEF_IP2)
-		do_IRQ(AR5312_IRQ_WLAN0_INTRS);
-	else if (pending & CAUSEF_IP3)
-		do_IRQ(AR5312_IRQ_ENET0_INTRS);
-	else if (pending & CAUSEF_IP4)
-		do_IRQ(AR5312_IRQ_ENET1_INTRS);
-	else if (pending & CAUSEF_IP5)
-		do_IRQ(AR5312_IRQ_WLAN1_INTRS);
-	else if (pending & CAUSEF_IP6) {
-		unsigned int ar531x_misc_intrs = sysRegRead(AR531X_ISR) & sysRegRead(AR531X_IMR);
-
-		if (ar531x_misc_intrs & AR531X_ISR_TIMER) {
-			do_IRQ(AR531X_MISC_IRQ_TIMER);
-			(void)sysRegRead(AR531X_TIMER);
-		} else if (ar531x_misc_intrs & AR531X_ISR_AHBPROC)
-			do_IRQ(AR531X_MISC_IRQ_AHB_PROC);
-		else if ((ar531x_misc_intrs & AR531X_ISR_UART0))
-			do_IRQ(AR531X_MISC_IRQ_UART0);
-		else if (ar531x_misc_intrs & AR531X_ISR_WD)
-			do_IRQ(AR531X_MISC_IRQ_WATCHDOG);
-		else
-			do_IRQ(AR531X_MISC_IRQ_NONE);
-	} else if (pending & CAUSEF_IP7) {
-		do_IRQ(AR531X_IRQ_CPU_CLOCK);
-	}
-	else
-		do_IRQ(AR531X_IRQ_NONE);
-}
-
 static void ar5312_halt(void)
 static void ar5312_halt(void)
 {
 {
 	 while (1);
 	 while (1);
@@ -451,110 +410,6 @@ static void __init ar5312_time_init(void)
 }
 }
 
 
 
 
-/* Enable the specified AR531X_MISC_IRQ interrupt */
-static void
-ar5312_misc_intr_enable(unsigned int irq)
-{
-	unsigned int imr;
-
-	imr = sysRegRead(AR531X_IMR);
-	imr |= (1 << (irq - AR531X_MISC_IRQ_BASE - 1));
-	sysRegWrite(AR531X_IMR, imr);
-	sysRegRead(AR531X_IMR); /* flush write buffer */
-}
-
-/* Disable the specified AR531X_MISC_IRQ interrupt */
-static void
-ar5312_misc_intr_disable(unsigned int irq)
-{
-	unsigned int imr;
-
-	imr = sysRegRead(AR531X_IMR);
-	imr &= ~(1 << (irq - AR531X_MISC_IRQ_BASE - 1));
-	sysRegWrite(AR531X_IMR, imr);
-	sysRegRead(AR531X_IMR); /* flush write buffer */
-}
-
-/* Turn on the specified AR531X_MISC_IRQ interrupt */
-static unsigned int
-ar5312_misc_intr_startup(unsigned int irq)
-{
-	ar5312_misc_intr_enable(irq);
-	return 0;
-}
-
-/* Turn off the specified AR531X_MISC_IRQ interrupt */
-static void
-ar5312_misc_intr_shutdown(unsigned int irq)
-{
-	ar5312_misc_intr_disable(irq);
-}
-
-static void
-ar5312_misc_intr_ack(unsigned int irq)
-{
-	ar5312_misc_intr_disable(irq);
-}
-
-static void
-ar5312_misc_intr_end(unsigned int irq)
-{
-	if (!(irq_desc[irq].status & (IRQ_DISABLED | IRQ_INPROGRESS)))
-		ar5312_misc_intr_enable(irq);
-}
-
-static struct irq_chip ar5312_misc_intr_controller = {
-	.typename	= "AR5312 misc",
-	.startup	= ar5312_misc_intr_startup,
-	.shutdown	= ar5312_misc_intr_shutdown,
-	.enable		= ar5312_misc_intr_enable,
-	.disable	= ar5312_misc_intr_disable,
-	.ack		= ar5312_misc_intr_ack,
-	.end		= ar5312_misc_intr_end,
-};
-
-static irqreturn_t ar5312_ahb_proc_handler(int cpl, void *dev_id)
-{
-	u32 proc1 = sysRegRead(AR531X_PROC1);
-	u32 procAddr = sysRegRead(AR531X_PROCADDR); /* clears error state */
-	u32 dma1 = sysRegRead(AR531X_DMA1);
-	u32 dmaAddr = sysRegRead(AR531X_DMAADDR);   /* clears error state */
-
-	printk("AHB interrupt: PROCADDR=0x%8.8x  PROC1=0x%8.8x  DMAADDR=0x%8.8x  DMA1=0x%8.8x\n",
-			procAddr, proc1, dmaAddr, dma1);
-		
-	machine_restart("AHB error"); /* Catastrophic failure */
-	return IRQ_HANDLED;
-}
-
-
-static struct irqaction ar5312_ahb_proc_interrupt  = {
-	.handler	= ar5312_ahb_proc_handler,
-	.flags		= SA_INTERRUPT,
-	.name		= "ar5312_ahb_proc_interrupt",
-};
-
-
-static struct irqaction cascade  = {
-	.handler	= no_action,
-	.flags		= SA_INTERRUPT,
-	.name		= "cascade",
-};
-
-void __init ar5312_misc_intr_init(int irq_base)
-{
-	int i;
-
-	for (i = irq_base; i < irq_base + AR531X_MISC_IRQ_COUNT; i++) {
-		irq_desc[i].status = IRQ_DISABLED;
-		irq_desc[i].action = NULL;
-		irq_desc[i].depth = 1;
-		irq_desc[i].chip = &ar5312_misc_intr_controller;
-	}
-	setup_irq(AR531X_MISC_IRQ_AHB_PROC, &ar5312_ahb_proc_interrupt);
-	setup_irq(AR5312_IRQ_MISC_INTRS, &cascade);
-}
-
 void __init ar5312_prom_init(void)
 void __init ar5312_prom_init(void)
 {
 {
 	u32 memsize, memcfg, bank0AC, bank1AC;
 	u32 memsize, memcfg, bank0AC, bank1AC;

+ 174 - 0
target/linux/atheros-2.6/files/arch/mips/atheros/ar5312/irq.c

@@ -0,0 +1,174 @@
+/*
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 2003 Atheros Communications, Inc.,  All Rights Reserved.
+ * Copyright (C) 2006 FON Technology, SL.
+ * Copyright (C) 2006 Imre Kaloz <[email protected]>
+ * Copyright (C) 2006 Felix Fietkau <[email protected]>
+ */
+
+/*
+ * Platform devices for Atheros SoCs
+ */
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/types.h>
+#include <linux/string.h>
+#include <linux/kernel.h>
+#include <linux/reboot.h>
+#include <asm/bootinfo.h>
+#include <asm/time.h>
+#include <asm/irq.h>
+#include <asm/io.h>
+#include "../ar531x.h"
+
+/*
+ * Called when an interrupt is received, this function
+ * determines exactly which interrupt it was, and it
+ * invokes the appropriate handler.
+ *
+ * Implicitly, we also define interrupt priority by
+ * choosing which to dispatch first.
+ */
+asmlinkage void ar5312_irq_dispatch(void)
+{
+	int pending = read_c0_status() & read_c0_cause();
+
+	if (pending & CAUSEF_IP2)
+		do_IRQ(AR5312_IRQ_WLAN0_INTRS);
+	else if (pending & CAUSEF_IP3)
+		do_IRQ(AR5312_IRQ_ENET0_INTRS);
+	else if (pending & CAUSEF_IP4)
+		do_IRQ(AR5312_IRQ_ENET1_INTRS);
+	else if (pending & CAUSEF_IP5)
+		do_IRQ(AR5312_IRQ_WLAN1_INTRS);
+	else if (pending & CAUSEF_IP6) {
+		unsigned int ar531x_misc_intrs = sysRegRead(AR531X_ISR) & sysRegRead(AR531X_IMR);
+
+		if (ar531x_misc_intrs & AR531X_ISR_TIMER) {
+			do_IRQ(AR531X_MISC_IRQ_TIMER);
+			(void)sysRegRead(AR531X_TIMER);
+		} else if (ar531x_misc_intrs & AR531X_ISR_AHBPROC)
+			do_IRQ(AR531X_MISC_IRQ_AHB_PROC);
+		else if ((ar531x_misc_intrs & AR531X_ISR_UART0))
+			do_IRQ(AR531X_MISC_IRQ_UART0);
+		else if (ar531x_misc_intrs & AR531X_ISR_WD)
+			do_IRQ(AR531X_MISC_IRQ_WATCHDOG);
+		else
+			do_IRQ(AR531X_MISC_IRQ_NONE);
+	} else if (pending & CAUSEF_IP7) {
+		do_IRQ(AR531X_IRQ_CPU_CLOCK);
+	}
+	else
+		do_IRQ(AR531X_IRQ_NONE);
+}
+
+
+/* Enable the specified AR531X_MISC_IRQ interrupt */
+static void
+ar5312_misc_intr_enable(unsigned int irq)
+{
+	unsigned int imr;
+
+	imr = sysRegRead(AR531X_IMR);
+	imr |= (1 << (irq - AR531X_MISC_IRQ_BASE - 1));
+	sysRegWrite(AR531X_IMR, imr);
+	sysRegRead(AR531X_IMR); /* flush write buffer */
+}
+
+/* Disable the specified AR531X_MISC_IRQ interrupt */
+static void
+ar5312_misc_intr_disable(unsigned int irq)
+{
+	unsigned int imr;
+
+	imr = sysRegRead(AR531X_IMR);
+	imr &= ~(1 << (irq - AR531X_MISC_IRQ_BASE - 1));
+	sysRegWrite(AR531X_IMR, imr);
+	sysRegRead(AR531X_IMR); /* flush write buffer */
+}
+
+/* Turn on the specified AR531X_MISC_IRQ interrupt */
+static unsigned int
+ar5312_misc_intr_startup(unsigned int irq)
+{
+	ar5312_misc_intr_enable(irq);
+	return 0;
+}
+
+/* Turn off the specified AR531X_MISC_IRQ interrupt */
+static void
+ar5312_misc_intr_shutdown(unsigned int irq)
+{
+	ar5312_misc_intr_disable(irq);
+}
+
+static void
+ar5312_misc_intr_ack(unsigned int irq)
+{
+	ar5312_misc_intr_disable(irq);
+}
+
+static void
+ar5312_misc_intr_end(unsigned int irq)
+{
+	if (!(irq_desc[irq].status & (IRQ_DISABLED | IRQ_INPROGRESS)))
+		ar5312_misc_intr_enable(irq);
+}
+
+static struct irq_chip ar5312_misc_intr_controller = {
+	.typename	= "AR5312 misc",
+	.startup	= ar5312_misc_intr_startup,
+	.shutdown	= ar5312_misc_intr_shutdown,
+	.enable		= ar5312_misc_intr_enable,
+	.disable	= ar5312_misc_intr_disable,
+	.ack		= ar5312_misc_intr_ack,
+	.end		= ar5312_misc_intr_end,
+};
+
+static irqreturn_t ar5312_ahb_proc_handler(int cpl, void *dev_id)
+{
+	u32 proc1 = sysRegRead(AR531X_PROC1);
+	u32 procAddr = sysRegRead(AR531X_PROCADDR); /* clears error state */
+	u32 dma1 = sysRegRead(AR531X_DMA1);
+	u32 dmaAddr = sysRegRead(AR531X_DMAADDR);   /* clears error state */
+
+	printk("AHB interrupt: PROCADDR=0x%8.8x  PROC1=0x%8.8x  DMAADDR=0x%8.8x  DMA1=0x%8.8x\n",
+			procAddr, proc1, dmaAddr, dma1);
+		
+	machine_restart("AHB error"); /* Catastrophic failure */
+	return IRQ_HANDLED;
+}
+
+
+static struct irqaction ar5312_ahb_proc_interrupt  = {
+	.handler	= ar5312_ahb_proc_handler,
+	.flags		= SA_INTERRUPT,
+	.name		= "ar5312_ahb_proc_interrupt",
+};
+
+
+static struct irqaction cascade  = {
+	.handler	= no_action,
+	.flags		= SA_INTERRUPT,
+	.name		= "cascade",
+};
+
+void __init ar5312_misc_intr_init(int irq_base)
+{
+	int i;
+
+	for (i = irq_base; i < irq_base + AR531X_MISC_IRQ_COUNT; i++) {
+		irq_desc[i].status = IRQ_DISABLED;
+		irq_desc[i].action = NULL;
+		irq_desc[i].depth = 1;
+		irq_desc[i].chip = &ar5312_misc_intr_controller;
+	}
+	setup_irq(AR531X_MISC_IRQ_AHB_PROC, &ar5312_ahb_proc_interrupt);
+	setup_irq(AR5312_IRQ_MISC_INTRS, &cascade);
+}
+
+

+ 11 - 0
target/linux/atheros-2.6/files/arch/mips/atheros/ar5315/Makefile

@@ -0,0 +1,11 @@
+#
+# This file is subject to the terms and conditions of the GNU General Public
+# License.  See the file "COPYING" in the main directory of this archive
+# for more details.
+#
+# Copyright (C) 2007 FON Technology, SL.
+# Copyright (C) 2007 Imre Kaloz <[email protected]>
+# Copyright (C) 2007 Felix Fietkau <[email protected]>
+#
+
+obj-y := board.o irq.o

+ 5 - 5
target/linux/atheros-2.6/files/arch/mips/atheros/ar5315.h → target/linux/atheros-2.6/files/arch/mips/atheros/ar5315/ar5315.h

@@ -342,12 +342,12 @@
 
 
 #define AR5315_GPIO_CR_M(x)                (1 << (x))                  /* mask for i/o */
 #define AR5315_GPIO_CR_M(x)                (1 << (x))                  /* mask for i/o */
 #define AR5315_GPIO_CR_O(x)                (1 << (x))                  /* output */
 #define AR5315_GPIO_CR_O(x)                (1 << (x))                  /* output */
-#define AR5315_GPIO_CR_I(x)                (0 << (x))                  /* input */
+#define AR5315_GPIO_CR_I(x)                (0)                         /* input */
 
 
-#define AR5315_GPIO_INT_S(x,Y)             ((x) << (8 * (Y)))          /* interrupt enable */
-#define AR5315_GPIO_INT_M(Y)               ((0x3F) << (8 * (Y)))       /* mask for int */
-#define AR5315_GPIO_INT_LVL(x,Y)           ((x) << (8 * (Y) + 6))      /* interrupt level */
-#define AR5315_GPIO_INT_LVL_M(Y)           ((0x3) << (8 * (Y) + 6))    /* mask for int level */
+#define AR5315_GPIO_INT_S(x)               (x)                         /* interrupt enable */
+#define AR5315_GPIO_INT_M                  (0x3F)                      /* mask for int */
+#define AR5315_GPIO_INT_LVL(x)             ((x) << 6)                  /* interrupt level */
+#define AR5315_GPIO_INT_LVL_M              ((0x3) << 6)                /* mask for int level */
 
 
 #define AR5315_RESET_GPIO       5
 #define AR5315_RESET_GPIO       5
 #define AR5315_NUM_GPIO         22
 #define AR5315_NUM_GPIO         22

+ 7 - 205
target/linux/atheros-2.6/files/arch/mips/atheros/ar5315.c → target/linux/atheros-2.6/files/arch/mips/atheros/ar5315/board.c

@@ -26,9 +26,10 @@
 #include <asm/time.h>
 #include <asm/time.h>
 #include <asm/irq.h>
 #include <asm/irq.h>
 #include <asm/io.h>
 #include <asm/io.h>
-#include "ar531x.h"
+#include "../ar531x.h"
 
 
 static int is_5315 = 0;
 static int is_5315 = 0;
+
 static struct resource ar5315_eth_res[] = {
 static struct resource ar5315_eth_res[] = {
 	{
 	{
 		.name = "eth0_membase",
 		.name = "eth0_membase",
@@ -182,7 +183,6 @@ int __init ar5315_init_devices(void)
 {
 {
 	struct ar531x_config *config;
 	struct ar531x_config *config;
 	struct ar531x_boarddata *bcfg;
 	struct ar531x_boarddata *bcfg;
-	u32 devid;
 	int dev = 0;
 	int dev = 0;
 
 
 	if (!is_5315)
 	if (!is_5315)
@@ -193,9 +193,10 @@ int __init ar5315_init_devices(void)
 	bcfg = (struct ar531x_boarddata *) board_config;
 	bcfg = (struct ar531x_boarddata *) board_config;
 
 
 #if 0
 #if 0
+	{
 	/* Detect the hardware based on the device ID */
 	/* Detect the hardware based on the device ID */
-	devid = sysRegRead(AR5315_SREV) & AR5315_REV_MAJ >> AR5315_REV_MAJ_S;
-	switch(devid) {
+	u32 devid = sysRegRead(AR5315_SREV) & AR5315_REV_MAJ >> AR5315_REV_MAJ_S;
+		switch(devid) {
 		case 0x9:
 		case 0x9:
 			mips_machtype = MACH_ATHEROS_AR2317;
 			mips_machtype = MACH_ATHEROS_AR2317;
 			break;
 			break;
@@ -204,6 +205,7 @@ int __init ar5315_init_devices(void)
 		default:
 		default:
 			mips_machtype = MACH_ATHEROS_AR2315;
 			mips_machtype = MACH_ATHEROS_AR2315;
 			break;
 			break;
+		}
 	}
 	}
 #endif
 #endif
 
 
@@ -220,48 +222,11 @@ int __init ar5315_init_devices(void)
 	ar5315_devs[dev++] = &ar5315_eth;
 	ar5315_devs[dev++] = &ar5315_eth;
 	ar5315_devs[dev++] = &ar5315_wmac;
 	ar5315_devs[dev++] = &ar5315_wmac;
 	ar5315_devs[dev++] = &ar5315_spiflash;
 	ar5315_devs[dev++] = &ar5315_spiflash;
+			
 
 
 	return platform_add_devices(ar5315_devs, dev);
 	return platform_add_devices(ar5315_devs, dev);
 }
 }
 
 
-
-/*
- * Called when an interrupt is received, this function
- * determines exactly which interrupt it was, and it
- * invokes the appropriate handler.
- *
- * Implicitly, we also define interrupt priority by
- * choosing which to dispatch first.
- */
-asmlinkage void ar5315_irq_dispatch(void)
-{
-	int pending = read_c0_status() & read_c0_cause();
-
-	if (pending & CAUSEF_IP3)
-		do_IRQ(AR5315_IRQ_WLAN0_INTRS);
-	else if (pending & CAUSEF_IP4)
-		do_IRQ(AR5315_IRQ_ENET0_INTRS);
-	else if (pending & CAUSEF_IP2) {
-		unsigned int ar531x_misc_intrs = sysRegRead(AR5315_ISR) & sysRegRead(AR5315_IMR);
-
-	    if (ar531x_misc_intrs & AR5315_ISR_TIMER)
-			do_IRQ(AR531X_MISC_IRQ_TIMER);
-		else if (ar531x_misc_intrs & AR5315_ISR_AHB)
-			do_IRQ(AR531X_MISC_IRQ_AHB_PROC);
-		else if (ar531x_misc_intrs & AR5315_ISR_GPIO) {
-			sysRegWrite(AR5315_ISR, sysRegRead(AR5315_IMR) | ~AR5315_ISR_GPIO);
-		} else if (ar531x_misc_intrs & AR5315_ISR_UART0)
-			do_IRQ(AR531X_MISC_IRQ_UART0);
-		else if (ar531x_misc_intrs & AR5315_ISR_WD)
-			do_IRQ(AR531X_MISC_IRQ_WATCHDOG);
-		else
-			do_IRQ(AR531X_MISC_IRQ_NONE);
-	} else if (pending & CAUSEF_IP7)
-		do_IRQ(AR531X_IRQ_CPU_CLOCK);
-	else
-		do_IRQ(AR531X_IRQ_NONE);
-}
-
 static void ar5315_halt(void)
 static void ar5315_halt(void)
 {
 {
 	 while (1);
 	 while (1);
@@ -362,169 +327,6 @@ static void __init ar5315_time_init(void)
 	mips_hpt_frequency = ar5315_cpu_frequency() / 2;
 	mips_hpt_frequency = ar5315_cpu_frequency() / 2;
 }
 }
 
 
-
-
-/* Enable the specified AR531X_MISC_IRQ interrupt */
-static void
-ar5315_misc_intr_enable(unsigned int irq)
-{
-	unsigned int imr;
-
-	imr = sysRegRead(AR5315_IMR);
-	switch(irq)
-	{
-	   case AR531X_MISC_IRQ_TIMER:
-	     imr |= AR5315_ISR_TIMER;
-	     break;
-
-	   case AR531X_MISC_IRQ_AHB_PROC:
-	     imr |= AR5315_ISR_AHB;
-	     break;
-
-	   case AR531X_MISC_IRQ_AHB_DMA:
-	     imr |= 0/* ?? */;
-	     break;
-
-	   case	AR531X_MISC_IRQ_GPIO:
-	     imr |= AR5315_ISR_GPIO;
-	     break;
-
-	   case AR531X_MISC_IRQ_UART0:
-	     imr |= AR5315_ISR_UART0;
-	     break;
-
-
-	   case	AR531X_MISC_IRQ_WATCHDOG:
-	     imr |= AR5315_ISR_WD;
-	     break;
-
-	   case AR531X_MISC_IRQ_LOCAL:
-	     imr |= 0/* ?? */;
-	     break;
-
-	}
-	sysRegWrite(AR5315_IMR, imr);
-	imr=sysRegRead(AR5315_IMR); /* flush write buffer */
-}
-
-/* Disable the specified AR531X_MISC_IRQ interrupt */
-static void
-ar5315_misc_intr_disable(unsigned int irq)
-{
-	unsigned int imr;
-
-	imr = sysRegRead(AR5315_IMR);
-	switch(irq)
-	{
-	   case AR531X_MISC_IRQ_TIMER:
-	     imr &= (~AR5315_ISR_TIMER);
-	     break;
-
-	   case AR531X_MISC_IRQ_AHB_PROC:
-	     imr &= (~AR5315_ISR_AHB);
-	     break;
-
-	   case AR531X_MISC_IRQ_AHB_DMA:
-	     imr &= 0/* ?? */;
-	     break;
-
-	   case	AR531X_MISC_IRQ_GPIO:
-	     imr &= ~AR5315_ISR_GPIO;
-	     break;
-
-	   case AR531X_MISC_IRQ_UART0:
-	     imr &= (~AR5315_ISR_UART0);
-	     break;
-
-	   case	AR531X_MISC_IRQ_WATCHDOG:
-	     imr &= (~AR5315_ISR_WD);
-	     break;
-
-	   case AR531X_MISC_IRQ_LOCAL:
-	     imr &= ~0/* ?? */;
-	     break;
-
-	}
-	sysRegWrite(AR5315_IMR, imr);
-	sysRegRead(AR5315_IMR); /* flush write buffer */
-}
-
-/* Turn on the specified AR531X_MISC_IRQ interrupt */
-static unsigned int
-ar5315_misc_intr_startup(unsigned int irq)
-{
-	ar5315_misc_intr_enable(irq);
-	return 0;
-}
-
-/* Turn off the specified AR531X_MISC_IRQ interrupt */
-static void
-ar5315_misc_intr_shutdown(unsigned int irq)
-{
-	ar5315_misc_intr_disable(irq);
-}
-
-static void
-ar5315_misc_intr_ack(unsigned int irq)
-{
-	ar5315_misc_intr_disable(irq);
-}
-
-static void
-ar5315_misc_intr_end(unsigned int irq)
-{
-	if (!(irq_desc[irq].status & (IRQ_DISABLED | IRQ_INPROGRESS)))
-		ar5315_misc_intr_enable(irq);
-}
-
-static struct irq_chip ar5315_misc_intr_controller = {
-	.typename	= "AR5315 misc",
-	.startup	= ar5315_misc_intr_startup,
-	.shutdown	= ar5315_misc_intr_shutdown,
-	.enable		= ar5315_misc_intr_enable,
-	.disable	= ar5315_misc_intr_disable,
-	.ack		= ar5315_misc_intr_ack,
-	.end		= ar5315_misc_intr_end,
-};
-
-static irqreturn_t ar5315_ahb_proc_handler(int cpl, void *dev_id)
-{
-    sysRegWrite(AR5315_AHB_ERR0,AHB_ERROR_DET);
-    sysRegRead(AR5315_AHB_ERR1);
-
-    printk("AHB fatal error\n");
-    machine_restart("AHB error"); /* Catastrophic failure */
-
-    return IRQ_HANDLED;
-}
-
-static struct irqaction ar5315_ahb_proc_interrupt  = {
-	.handler	= ar5315_ahb_proc_handler,
-	.flags		= SA_INTERRUPT,
-	.name		= "ar5315_ahb_proc_interrupt",
-};
-
-
-static struct irqaction cascade  = {
-	.handler	= no_action,
-	.flags		= SA_INTERRUPT,
-	.name		= "cascade",
-};
-
-void ar5315_misc_intr_init(int irq_base)
-{
-	int i;
-
-	for (i = irq_base; i < irq_base + AR531X_MISC_IRQ_COUNT; i++) {
-		irq_desc[i].status = IRQ_DISABLED;
-		irq_desc[i].action = NULL;
-		irq_desc[i].depth = 1;
-		irq_desc[i].chip = &ar5315_misc_intr_controller;
-	}
-	setup_irq(AR531X_MISC_IRQ_AHB_PROC, &ar5315_ahb_proc_interrupt);
-	setup_irq(AR5315_IRQ_MISC_INTRS, &cascade);
-}
-
 void __init ar5315_prom_init(void)
 void __init ar5315_prom_init(void)
 {
 {
 	u32 memsize, memcfg;
 	u32 memsize, memcfg;

+ 330 - 0
target/linux/atheros-2.6/files/arch/mips/atheros/ar5315/irq.c

@@ -0,0 +1,330 @@
+/*
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 2003 Atheros Communications, Inc.,  All Rights Reserved.
+ * Copyright (C) 2006 FON Technology, SL.
+ * Copyright (C) 2006 Imre Kaloz <[email protected]>
+ * Copyright (C) 2006 Felix Fietkau <[email protected]>
+ */
+
+/*
+ * Platform devices for Atheros SoCs
+ */
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/types.h>
+#include <linux/string.h>
+#include <linux/kernel.h>
+#include <linux/reboot.h>
+#include <linux/interrupt.h>
+#include <asm/bootinfo.h>
+#include <asm/irq_cpu.h>
+#include <asm/io.h>
+#include "../ar531x.h"
+
+static u32 gpiointmask = 0, gpiointval = 0;
+
+static inline void ar5315_gpio_irq(void)
+{
+	u32 pend;
+	sysRegWrite(AR5315_ISR, sysRegRead(AR5315_IMR) | ~AR5315_ISR_GPIO);
+
+	/* only do one gpio interrupt at a time */
+	pend = (sysRegRead(AR5315_GPIO_DI) ^ gpiointval) & gpiointmask;
+	if (!pend)
+		return;
+
+	do_IRQ(AR531X_GPIO_IRQ_BASE + 31 - clz(pend));
+}
+
+
+/*
+ * Called when an interrupt is received, this function
+ * determines exactly which interrupt it was, and it
+ * invokes the appropriate handler.
+ *
+ * Implicitly, we also define interrupt priority by
+ * choosing which to dispatch first.
+ */
+asmlinkage void ar5315_irq_dispatch(void)
+{
+	int pending = read_c0_status() & read_c0_cause();
+
+	if (pending & CAUSEF_IP3)
+		do_IRQ(AR5315_IRQ_WLAN0_INTRS);
+	else if (pending & CAUSEF_IP4)
+		do_IRQ(AR5315_IRQ_ENET0_INTRS);
+	else if (pending & CAUSEF_IP2) {
+		unsigned int ar531x_misc_intrs = sysRegRead(AR5315_ISR) & sysRegRead(AR5315_IMR);
+
+		if (ar531x_misc_intrs & AR5315_ISR_SPI)
+			do_IRQ(AR531X_MISC_IRQ_SPI);
+		else if (ar531x_misc_intrs & AR5315_ISR_TIMER)
+			do_IRQ(AR531X_MISC_IRQ_TIMER);
+		else if (ar531x_misc_intrs & AR5315_ISR_AHB)
+			do_IRQ(AR531X_MISC_IRQ_AHB_PROC);
+		else if (ar531x_misc_intrs & AR5315_ISR_GPIO)
+			ar5315_gpio_irq();
+		else if (ar531x_misc_intrs & AR5315_ISR_UART0)
+			do_IRQ(AR531X_MISC_IRQ_UART0);
+		else if (ar531x_misc_intrs & AR5315_ISR_WD)
+			do_IRQ(AR531X_MISC_IRQ_WATCHDOG);
+		else
+			do_IRQ(AR531X_MISC_IRQ_NONE);
+	} else if (pending & CAUSEF_IP7)
+		do_IRQ(AR531X_IRQ_CPU_CLOCK);
+	else
+		do_IRQ(AR531X_IRQ_NONE);
+}
+
+static void ar5315_gpio_intr_enable(unsigned int irq)
+{
+	u32 gpio, mask;
+	gpio = irq - AR531X_GPIO_IRQ_BASE;
+	mask = 1 << gpio;
+	gpiointmask |= mask;
+
+	/* reconfigure GPIO line as input */
+	sysRegMask(AR5315_GPIO_CR, AR5315_GPIO_CR_M(gpio), AR5315_GPIO_CR_I(gpio));
+	
+	/* Enable interrupt with edge detection */
+	sysRegMask(AR5315_GPIO_INT, AR5315_GPIO_INT_M | AR5315_GPIO_INT_LVL_M, gpio | AR5315_GPIO_INT_LVL(3));
+}
+
+static void ar5315_gpio_intr_disable(unsigned int irq)
+{
+	u32 gpio, mask;
+	gpio = irq - AR531X_GPIO_IRQ_BASE;
+	mask = 1 << gpio;
+
+	gpiointmask &= ~mask;
+
+	/* Disable interrupt with edge detection */
+	sysRegMask(AR5315_GPIO_INT, AR5315_GPIO_INT_M | AR5315_GPIO_INT_LVL_M, gpio | AR5315_GPIO_INT_LVL(0));
+}
+
+/* Turn on the specified AR531X_MISC_IRQ interrupt */
+static unsigned int ar5315_gpio_intr_startup(unsigned int irq)
+{
+	ar5315_gpio_intr_enable(irq);
+	return 0;
+}
+
+/* Turn off the specified AR531X_MISC_IRQ interrupt */
+static void
+ar5315_gpio_intr_shutdown(unsigned int irq)
+{
+	ar5315_gpio_intr_disable(irq);
+}
+
+static void
+ar5315_gpio_intr_ack(unsigned int irq)
+{
+	ar5315_gpio_intr_disable(irq);
+}
+
+static void
+ar5315_gpio_intr_end(unsigned int irq)
+{
+	if (!(irq_desc[irq].status & (IRQ_DISABLED | IRQ_INPROGRESS)))
+		ar5315_gpio_intr_enable(irq);
+}
+
+static struct irq_chip ar5315_gpio_intr_controller = {
+	.typename	= "AR5315 GPIO",
+	.startup	= ar5315_gpio_intr_startup,
+	.shutdown	= ar5315_gpio_intr_shutdown,
+	.enable		= ar5315_gpio_intr_enable,
+	.disable	= ar5315_gpio_intr_disable,
+	.ack		= ar5315_gpio_intr_ack,
+	.end		= ar5315_gpio_intr_end,
+};
+
+
+/* Enable the specified AR531X_MISC_IRQ interrupt */
+static void
+ar5315_misc_intr_enable(unsigned int irq)
+{
+	unsigned int imr;
+
+	imr = sysRegRead(AR5315_IMR);
+	switch(irq)
+	{
+	   case AR531X_MISC_IRQ_SPI:
+		 imr |= AR5315_ISR_SPI;
+		 break;
+
+	   case AR531X_MISC_IRQ_TIMER:
+	     imr |= AR5315_ISR_TIMER;
+	     break;
+
+	   case AR531X_MISC_IRQ_AHB_PROC:
+	     imr |= AR5315_ISR_AHB;
+	     break;
+
+	   case AR531X_MISC_IRQ_AHB_DMA:
+	     imr |= 0/* ?? */;
+	     break;
+
+	   case	AR531X_MISC_IRQ_GPIO:
+	     imr |= AR5315_ISR_GPIO;
+	     break;
+
+	   case AR531X_MISC_IRQ_UART0:
+	     imr |= AR5315_ISR_UART0;
+	     break;
+
+
+	   case	AR531X_MISC_IRQ_WATCHDOG:
+	     imr |= AR5315_ISR_WD;
+	     break;
+
+	   case AR531X_MISC_IRQ_LOCAL:
+	     imr |= 0/* ?? */;
+	     break;
+
+	}
+	sysRegWrite(AR5315_IMR, imr);
+	imr=sysRegRead(AR5315_IMR); /* flush write buffer */
+}
+
+/* Disable the specified AR531X_MISC_IRQ interrupt */
+static void
+ar5315_misc_intr_disable(unsigned int irq)
+{
+	unsigned int imr;
+
+	imr = sysRegRead(AR5315_IMR);
+	switch(irq)
+	{
+	   case AR531X_MISC_IRQ_SPI:
+		 imr &= ~AR5315_ISR_SPI;
+		 break;
+		 
+	   case AR531X_MISC_IRQ_TIMER:
+	     imr &= (~AR5315_ISR_TIMER);
+	     break;
+
+	   case AR531X_MISC_IRQ_AHB_PROC:
+	     imr &= (~AR5315_ISR_AHB);
+	     break;
+
+	   case AR531X_MISC_IRQ_AHB_DMA:
+	     imr &= 0/* ?? */;
+	     break;
+
+	   case	AR531X_MISC_IRQ_GPIO:
+	     imr &= ~AR5315_ISR_GPIO;
+	     break;
+
+	   case AR531X_MISC_IRQ_UART0:
+	     imr &= (~AR5315_ISR_UART0);
+	     break;
+
+	   case	AR531X_MISC_IRQ_WATCHDOG:
+	     imr &= (~AR5315_ISR_WD);
+	     break;
+
+	   case AR531X_MISC_IRQ_LOCAL:
+	     imr &= ~0/* ?? */;
+	     break;
+
+	}
+	sysRegWrite(AR5315_IMR, imr);
+	sysRegRead(AR5315_IMR); /* flush write buffer */
+}
+
+/* Turn on the specified AR531X_MISC_IRQ interrupt */
+static unsigned int
+ar5315_misc_intr_startup(unsigned int irq)
+{
+	ar5315_misc_intr_enable(irq);
+	return 0;
+}
+
+/* Turn off the specified AR531X_MISC_IRQ interrupt */
+static void
+ar5315_misc_intr_shutdown(unsigned int irq)
+{
+	ar5315_misc_intr_disable(irq);
+}
+
+static void
+ar5315_misc_intr_ack(unsigned int irq)
+{
+	ar5315_misc_intr_disable(irq);
+}
+
+static void
+ar5315_misc_intr_end(unsigned int irq)
+{
+	if (!(irq_desc[irq].status & (IRQ_DISABLED | IRQ_INPROGRESS)))
+		ar5315_misc_intr_enable(irq);
+}
+
+static struct irq_chip ar5315_misc_intr_controller = {
+	.typename	= "AR5315 misc",
+	.startup	= ar5315_misc_intr_startup,
+	.shutdown	= ar5315_misc_intr_shutdown,
+	.enable		= ar5315_misc_intr_enable,
+	.disable	= ar5315_misc_intr_disable,
+	.ack		= ar5315_misc_intr_ack,
+	.end		= ar5315_misc_intr_end,
+};
+
+static irqreturn_t ar5315_ahb_proc_handler(int cpl, void *dev_id)
+{
+    sysRegWrite(AR5315_AHB_ERR0,AHB_ERROR_DET);
+    sysRegRead(AR5315_AHB_ERR1);
+
+    printk("AHB fatal error\n");
+    machine_restart("AHB error"); /* Catastrophic failure */
+
+    return IRQ_HANDLED;
+}
+
+static struct irqaction ar5315_ahb_proc_interrupt  = {
+	.handler	= ar5315_ahb_proc_handler,
+	.flags		= SA_INTERRUPT,
+	.name		= "ar5315_ahb_proc_interrupt",
+};
+
+
+static struct irqaction cascade  = {
+	.handler	= no_action,
+	.flags		= SA_INTERRUPT,
+	.name		= "cascade",
+};
+
+static void ar5315_gpio_intr_init(int irq_base)
+{
+	int i;
+
+	for (i = irq_base; i < irq_base + AR531X_GPIO_IRQ_COUNT; i++) {
+		irq_desc[i].status = IRQ_DISABLED;
+		irq_desc[i].action = NULL;
+		irq_desc[i].depth = 1;
+		irq_desc[i].chip = &ar5315_gpio_intr_controller;
+	}
+	setup_irq(AR531X_MISC_IRQ_GPIO, &cascade);
+	gpiointval = sysRegRead(AR5315_GPIO_DI);
+}
+
+void ar5315_misc_intr_init(int irq_base)
+{
+	int i;
+
+	for (i = irq_base; i < irq_base + AR531X_MISC_IRQ_COUNT; i++) {
+		irq_desc[i].status = IRQ_DISABLED;
+		irq_desc[i].action = NULL;
+		irq_desc[i].depth = 1;
+		irq_desc[i].chip = &ar5315_misc_intr_controller;
+	}
+	setup_irq(AR531X_MISC_IRQ_AHB_PROC, &ar5315_ahb_proc_interrupt);
+	setup_irq(AR5315_IRQ_MISC_INTRS, &cascade);
+	ar5315_gpio_intr_init(AR531X_GPIO_IRQ_BASE);
+}
+

+ 42 - 7
target/linux/atheros-2.6/files/arch/mips/atheros/ar531x.h

@@ -3,8 +3,32 @@
 
 
 #include <asm/cpu-info.h>
 #include <asm/cpu-info.h>
 #include <ar531x_platform.h>
 #include <ar531x_platform.h>
-#include "ar5312.h"
-#include "ar5315.h"
+#include "ar5312/ar5312.h"
+#include "ar5315/ar5315.h"
+
+
+/*
+ * C access to CLZ instruction
+ * (count leading zeroes).
+ */
+static inline int clz(unsigned long val)
+{
+	int ret;
+
+	__asm__ volatile (
+		".set\tnoreorder\n\t"
+		".set\tnoat\n\t"
+		".set\tmips32\n\t"
+		"clz\t%0,%1\n\t"
+		".set\tmips0\n\t"
+		".set\tat\n\t"
+		".set\treorder"
+		: "=r" (ret)
+		: "r" (val)
+	);
+	
+	return ret;
+}
 
 
 /*                                                                             
 /*                                                                             
  * Atheros CPUs before the AR2315 are using MIPS 4Kc core, later designs are
  * Atheros CPUs before the AR2315 are using MIPS 4Kc core, later designs are
@@ -27,11 +51,8 @@
 #define DO_AR5315(...)
 #define DO_AR5315(...)
 #endif
 #endif
 
 
-#include <irq.h>
-
-#define AR531X_HIGH_PRIO                0x10
 #define AR531X_MISC_IRQ_BASE		0x20
 #define AR531X_MISC_IRQ_BASE		0x20
-#define AR531X_GPIO_IRQ_BASE            0x30
+#define AR531X_GPIO_IRQ_BASE		0x30
 
 
 /* Software's idea of interrupts handled by "CPU Interrupt Controller" */
 /* Software's idea of interrupts handled by "CPU Interrupt Controller" */
 #define AR531X_IRQ_NONE		MIPS_CPU_IRQ_BASE+0
 #define AR531X_IRQ_NONE		MIPS_CPU_IRQ_BASE+0
@@ -47,7 +68,8 @@
 #define AR531X_MISC_IRQ_UART0_DMA	AR531X_MISC_IRQ_BASE+6
 #define AR531X_MISC_IRQ_UART0_DMA	AR531X_MISC_IRQ_BASE+6
 #define AR531X_MISC_IRQ_WATCHDOG	AR531X_MISC_IRQ_BASE+7
 #define AR531X_MISC_IRQ_WATCHDOG	AR531X_MISC_IRQ_BASE+7
 #define AR531X_MISC_IRQ_LOCAL		AR531X_MISC_IRQ_BASE+8
 #define AR531X_MISC_IRQ_LOCAL		AR531X_MISC_IRQ_BASE+8
-#define AR531X_MISC_IRQ_COUNT		9
+#define AR531X_MISC_IRQ_SPI 		AR531X_MISC_IRQ_BASE+9
+#define AR531X_MISC_IRQ_COUNT		10
 
 
 /* GPIO Interrupts [0..7], share AR531X_MISC_IRQ_GPIO */
 /* GPIO Interrupts [0..7], share AR531X_MISC_IRQ_GPIO */
 #define AR531X_GPIO_IRQ_NONE            AR531X_MISC_IRQ_BASE+0
 #define AR531X_GPIO_IRQ_NONE            AR531X_MISC_IRQ_BASE+0
@@ -127,5 +149,18 @@ extern void ar5315_prom_init(void);
 extern void ar5315_misc_intr_init(int irq_base);
 extern void ar5315_misc_intr_init(int irq_base);
 extern void ar5315_plat_setup(void);
 extern void ar5315_plat_setup(void);
 extern asmlinkage void ar5315_irq_dispatch(void);
 extern asmlinkage void ar5315_irq_dispatch(void);
+extern void ar5315_pci_irq(int irq);
+static inline u32 sysRegMask(u32 phys, u32 mask, u32 value)
+{
+	u32 reg;
+	
+	reg = sysRegRead(phys);
+	reg &= ~mask;
+	reg |= value & mask;
+	sysRegWrite(phys, reg);
+	reg = sysRegRead(phys); /* flush write to the hardware */
+
+	return reg;
+}
 
 
 #endif
 #endif

+ 15 - 0
target/linux/atheros-2.6/files/arch/mips/atheros/board.c

@@ -23,6 +23,7 @@
 #include <linux/serial.h>
 #include <linux/serial.h>
 #include <linux/serial_core.h>
 #include <linux/serial_core.h>
 #include <asm/bootinfo.h>
 #include <asm/bootinfo.h>
+#include <asm/irq_cpu.h>
 #include <asm/io.h>
 #include <asm/io.h>
 #include "ar531x.h"
 #include "ar531x.h"
 
 
@@ -189,4 +190,18 @@ void __init plat_timer_setup(struct irqaction *irq)
 	write_c0_compare(count + 1000);
 	write_c0_compare(count + 1000);
 }
 }
 
 
+asmlinkage void plat_irq_dispatch(void)
+{
+	DO_AR5312(ar5312_irq_dispatch();)
+	DO_AR5315(ar5315_irq_dispatch();)
+}
 
 
+void __init arch_init_irq(void)
+{
+	clear_c0_status(ST0_IM);
+	mips_cpu_irq_init();
+
+	/* Initialize interrupt controllers */
+	DO_AR5312(ar5312_misc_intr_init(AR531X_MISC_IRQ_BASE);)
+	DO_AR5315(ar5315_misc_intr_init(AR531X_MISC_IRQ_BASE);)
+}

+ 0 - 86
target/linux/atheros-2.6/files/arch/mips/atheros/irq.c

@@ -1,86 +0,0 @@
-/*
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file "COPYING" in the main directory of this archive
- * for more details.
- *
- * Copyright (C) 2003 Atheros Communications, Inc.,  All Rights Reserved.
- * Copyright (C) 2006 FON Technology, SL.
- * Copyright (C) 2006 Imre Kaloz <[email protected]>
- * Copyright (C) 2006 Felix Fietkau <[email protected]>
- */
-
-/*
- * Interrupt support for AR531X WiSOC.
- */
-
-#include <linux/autoconf.h>
-#include <linux/init.h>
-#include <linux/kernel_stat.h>
-#include <linux/signal.h>
-#include <linux/sched.h>
-#include <linux/interrupt.h>
-#include <linux/slab.h>
-#include <linux/random.h>
-#include <linux/pm.h>
-#include <linux/delay.h>
-#include <linux/reboot.h>
-#include <linux/irq.h>
-#include <asm/bootinfo.h>
-#include <asm/mipsregs.h>
-#include <asm/irq_cpu.h>
-#include "ar531x.h"
-
-
-/* ARGSUSED */
-irqreturn_t
-spurious_irq_handler(int cpl, void *dev_id)
-{
-    /* 
-    printk("spurious_irq_handler: %d  cause=0x%8.8x  status=0x%8.8x\n",
-	   cpl, cause_intrs, status_intrs); 
-    */
-	return IRQ_NONE;
-}
-
-/* ARGSUSED */
-irqreturn_t
-spurious_misc_handler(int cpl, void *dev_id)
-{
-    /*
-    printk("spurious_misc_handler: 0x%x isr=0x%8.8x imr=0x%8.8x\n",
-	   cpl, ar531x_isr, ar531x_imr);
-    */
-	return IRQ_NONE;
-}
-
-static struct irqaction spurious_irq  = {
-	.handler	= spurious_irq_handler,
-	.flags		= SA_INTERRUPT,
-	.name		= "spurious_irq",
-};
-
-static struct irqaction spurious_misc  = {
-	.handler	= spurious_misc_handler,
-	.flags		= SA_INTERRUPT,
-	.name		= "spurious_misc",
-};
-
-asmlinkage void plat_irq_dispatch(void)
-{
-	DO_AR5312(ar5312_irq_dispatch();)
-	DO_AR5315(ar5315_irq_dispatch();)
-}
-
-void __init arch_init_irq(void)
-{
-	clear_c0_status(ST0_IM);
-	mips_cpu_irq_init();
-
-	/* Initialize interrupt controllers */
-	DO_AR5312(ar5312_misc_intr_init(AR531X_MISC_IRQ_BASE);)
-	DO_AR5315(ar5315_misc_intr_init(AR531X_MISC_IRQ_BASE);)
-
-	/* Default "spurious interrupt" handlers */
-	setup_irq(AR531X_IRQ_NONE, &spurious_irq);
-	setup_irq(AR531X_MISC_IRQ_NONE, &spurious_misc);
-}

+ 108 - 0
target/linux/atheros-2.6/files/arch/mips/atheros/reset.c

@@ -0,0 +1,108 @@
+#include <linux/module.h>
+#include <linux/timer.h>
+#include <linux/interrupt.h>
+#include <linux/kobject.h>
+#include <linux/workqueue.h>
+#include <linux/skbuff.h>
+#include <linux/netlink.h>
+#include <net/sock.h>
+#include <asm/uaccess.h>
+#include "ar531x.h"
+#include "ar5315/ar5315.h"
+
+struct event_t {
+	struct work_struct wq;
+	int set;
+	long int jiffies;
+};
+
+extern struct sock *uevent_sock;
+extern u64 uevent_next_seqnum(void);
+static int seen;
+
+static inline void add_msg(struct sk_buff *skb, char *msg)
+{
+	char *scratch;
+	scratch = skb_put(skb, strlen(msg) + 1);
+	sprintf(scratch, msg);
+}
+
+static void hotplug_button(struct work_struct *wq)
+{
+	struct sk_buff *skb;
+	struct event_t *event;
+	size_t len;
+	char *scratch, *s;
+	char buf[128];
+	
+	event = container_of(wq, struct event_t, wq);
+	if (!uevent_sock)
+		goto done;
+
+	/* allocate message with the maximum possible size */
+	s = event->set ? "pressed" : "released";
+	len = strlen(s) + 2;
+	skb = alloc_skb(len + 2048, GFP_KERNEL);
+	if (!skb)
+		goto done;
+	
+	/* add header */
+	scratch = skb_put(skb, len);
+	sprintf(scratch, "%s@",s);
+
+	/* copy keys to our continuous event payload buffer */
+	add_msg(skb, "HOME=/");
+	add_msg(skb, "PATH=/sbin:/bin:/usr/sbin:/usr/bin");
+	add_msg(skb, "SUBSYSTEM=button");
+	add_msg(skb, "BUTTON=reset");
+	add_msg(skb, (event->set ? "ACTION=pressed" : "ACTION=released"));
+	sprintf(buf, "SEEN=%ld", (event->jiffies - seen)/HZ);
+	add_msg(skb, buf);
+	snprintf(buf, 128, "SEQNUM=%llu", uevent_next_seqnum());
+	add_msg(skb, buf);
+
+	NETLINK_CB(skb).dst_group = 1;
+	netlink_broadcast(uevent_sock, skb, 0, 1, GFP_KERNEL);
+
+done:
+	kfree(event);
+}
+
+static irqreturn_t button_handler(int irq, void *dev_id)
+{
+	static int pressed = 0;
+	struct event_t *event;
+	u32 gpio = ~0;
+
+	event = (struct event_t *) kzalloc(sizeof(struct event_t), GFP_ATOMIC);
+	if (!event)
+		return IRQ_NONE;
+	
+	pressed = !pressed;
+
+	DO_AR5315(gpio = sysRegRead(AR5315_GPIO_DI);)
+	gpio &= 1 << (irq - AR531X_GPIO_IRQ_BASE);
+
+	event->set = gpio;
+	event->jiffies = jiffies;
+
+	INIT_WORK(&event->wq, (void *)(void *)hotplug_button);
+	schedule_work(&event->wq);
+
+	seen = jiffies;
+
+	return IRQ_HANDLED;
+}
+
+int __init ar531x_init_reset(void)
+{
+	struct ar531x_boarddata *bcfg;
+	bcfg = (struct ar531x_boarddata *) board_config;
+
+	seen = jiffies;
+	request_irq(AR531X_GPIO_IRQ_BASE + bcfg->resetConfigGpio, &button_handler, IRQF_SAMPLE_RANDOM, "ar531x_reset", NULL);
+
+	return 0;
+}
+
+module_init(ar531x_init_reset);