diff options
13 files changed, 707 insertions, 461 deletions
| diff --git a/target/linux/atheros-2.6/files/arch/mips/atheros/Makefile b/target/linux/atheros-2.6/files/arch/mips/atheros/Makefile index aff65d723..2c2b991bc 100644 --- a/target/linux/atheros-2.6/files/arch/mips/atheros/Makefile +++ b/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  # for more details.  # -# Copyright (C) 2003 Atheros Communications, Inc.,  All Rights Reserved.  # Copyright (C) 2006 FON Technology, SL.  # Copyright (C) 2006 Imre Kaloz <kaloz@openwrt.org>  # Copyright (C) 2006 Felix Fietkau <nbd@openwrt.org>  # -# 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/ diff --git a/target/linux/atheros-2.6/files/arch/mips/atheros/ar5312/Makefile b/target/linux/atheros-2.6/files/arch/mips/atheros/ar5312/Makefile new file mode 100644 index 000000000..6c50d9931 --- /dev/null +++ b/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 <kaloz@openwrt.org> +# Copyright (C) 2007 Felix Fietkau <nbd@openwrt.org> +# + +obj-y := board.o irq.o diff --git a/target/linux/atheros-2.6/files/arch/mips/atheros/ar5312.h b/target/linux/atheros-2.6/files/arch/mips/atheros/ar5312/ar5312.h index 2b6b875b4..2b6b875b4 100644 --- a/target/linux/atheros-2.6/files/arch/mips/atheros/ar5312.h +++ b/target/linux/atheros-2.6/files/arch/mips/atheros/ar5312/ar5312.h diff --git a/target/linux/atheros-2.6/files/arch/mips/atheros/ar5312.c b/target/linux/atheros-2.6/files/arch/mips/atheros/ar5312/board.c index 57d56eb0e..21073dbbb 100644 --- a/target/linux/atheros-2.6/files/arch/mips/atheros/ar5312.c +++ b/target/linux/atheros-2.6/files/arch/mips/atheros/ar5312/board.c @@ -27,7 +27,7 @@  #include <asm/time.h>  #include <asm/irq.h>  #include <asm/io.h> -#include "ar531x.h" +#include "../ar531x.h"  #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)  {  	 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)  {  	u32 memsize, memcfg, bank0AC, bank1AC; diff --git a/target/linux/atheros-2.6/files/arch/mips/atheros/ar5312/irq.c b/target/linux/atheros-2.6/files/arch/mips/atheros/ar5312/irq.c new file mode 100644 index 000000000..8345a31eb --- /dev/null +++ b/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 <kaloz@openwrt.org> + * Copyright (C) 2006 Felix Fietkau <nbd@openwrt.org> + */ + +/* + * 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); +} + + diff --git a/target/linux/atheros-2.6/files/arch/mips/atheros/ar5315/Makefile b/target/linux/atheros-2.6/files/arch/mips/atheros/ar5315/Makefile new file mode 100644 index 000000000..6c50d9931 --- /dev/null +++ b/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 <kaloz@openwrt.org> +# Copyright (C) 2007 Felix Fietkau <nbd@openwrt.org> +# + +obj-y := board.o irq.o diff --git a/target/linux/atheros-2.6/files/arch/mips/atheros/ar5315.h b/target/linux/atheros-2.6/files/arch/mips/atheros/ar5315/ar5315.h index c3eeed18b..567141cb7 100644 --- a/target/linux/atheros-2.6/files/arch/mips/atheros/ar5315.h +++ b/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_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_NUM_GPIO         22 diff --git a/target/linux/atheros-2.6/files/arch/mips/atheros/ar5315.c b/target/linux/atheros-2.6/files/arch/mips/atheros/ar5315/board.c index 0255ae324..8247d8548 100644 --- a/target/linux/atheros-2.6/files/arch/mips/atheros/ar5315.c +++ b/target/linux/atheros-2.6/files/arch/mips/atheros/ar5315/board.c @@ -26,9 +26,10 @@  #include <asm/time.h>  #include <asm/irq.h>  #include <asm/io.h> -#include "ar531x.h" +#include "../ar531x.h"  static int is_5315 = 0; +  static struct resource ar5315_eth_res[] = {  	{  		.name = "eth0_membase", @@ -182,7 +183,6 @@ int __init ar5315_init_devices(void)  {  	struct ar531x_config *config;  	struct ar531x_boarddata *bcfg; -	u32 devid;  	int dev = 0;  	if (!is_5315) @@ -193,9 +193,10 @@ int __init ar5315_init_devices(void)  	bcfg = (struct ar531x_boarddata *) board_config;  #if 0 +	{  	/* 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:  			mips_machtype = MACH_ATHEROS_AR2317;  			break; @@ -204,6 +205,7 @@ int __init ar5315_init_devices(void)  		default:  			mips_machtype = MACH_ATHEROS_AR2315;  			break; +		}  	}  #endif @@ -220,48 +222,11 @@ int __init ar5315_init_devices(void)  	ar5315_devs[dev++] = &ar5315_eth;  	ar5315_devs[dev++] = &ar5315_wmac;  	ar5315_devs[dev++] = &ar5315_spiflash; +			  	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)  {  	 while (1); @@ -362,169 +327,6 @@ static void __init ar5315_time_init(void)  	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)  {  	u32 memsize, memcfg; diff --git a/target/linux/atheros-2.6/files/arch/mips/atheros/ar5315/irq.c b/target/linux/atheros-2.6/files/arch/mips/atheros/ar5315/irq.c new file mode 100644 index 000000000..3713ebd66 --- /dev/null +++ b/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 <kaloz@openwrt.org> + * Copyright (C) 2006 Felix Fietkau <nbd@openwrt.org> + */ + +/* + * 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); +} + diff --git a/target/linux/atheros-2.6/files/arch/mips/atheros/ar531x.h b/target/linux/atheros-2.6/files/arch/mips/atheros/ar531x.h index 56f63030c..5256a548c 100644 --- a/target/linux/atheros-2.6/files/arch/mips/atheros/ar531x.h +++ b/target/linux/atheros-2.6/files/arch/mips/atheros/ar531x.h @@ -3,8 +3,32 @@  #include <asm/cpu-info.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 @@ -27,11 +51,8 @@  #define DO_AR5315(...)  #endif -#include <irq.h> - -#define AR531X_HIGH_PRIO                0x10  #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" */  #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_WATCHDOG	AR531X_MISC_IRQ_BASE+7  #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 */  #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_plat_setup(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 diff --git a/target/linux/atheros-2.6/files/arch/mips/atheros/board.c b/target/linux/atheros-2.6/files/arch/mips/atheros/board.c index d26eda4d0..1ea66c0c1 100644 --- a/target/linux/atheros-2.6/files/arch/mips/atheros/board.c +++ b/target/linux/atheros-2.6/files/arch/mips/atheros/board.c @@ -23,6 +23,7 @@  #include <linux/serial.h>  #include <linux/serial_core.h>  #include <asm/bootinfo.h> +#include <asm/irq_cpu.h>  #include <asm/io.h>  #include "ar531x.h" @@ -189,4 +190,18 @@ void __init plat_timer_setup(struct irqaction *irq)  	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);) +} diff --git a/target/linux/atheros-2.6/files/arch/mips/atheros/irq.c b/target/linux/atheros-2.6/files/arch/mips/atheros/irq.c deleted file mode 100644 index 5665aa3b9..000000000 --- a/target/linux/atheros-2.6/files/arch/mips/atheros/irq.c +++ /dev/null @@ -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 <kaloz@openwrt.org> - * Copyright (C) 2006 Felix Fietkau <nbd@openwrt.org> - */ - -/* - * 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); -} diff --git a/target/linux/atheros-2.6/files/arch/mips/atheros/reset.c b/target/linux/atheros-2.6/files/arch/mips/atheros/reset.c new file mode 100644 index 000000000..d62c5e1c4 --- /dev/null +++ b/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); | 
