diff options
| author | blogic <blogic@3c298f89-4303-0410-b956-a3cf2f4a3e73> | 2008-04-03 20:28:10 +0000 | 
|---|---|---|
| committer | blogic <blogic@3c298f89-4303-0410-b956-a3cf2f4a3e73> | 2008-04-03 20:28:10 +0000 | 
| commit | 66b7ecf8e0e324c1bd76eb873e128a98a68dd539 (patch) | |
| tree | d5e82292716c3d80a459d15808dbff126cdc5485 /target | |
| parent | 19910c310a0169c4bf3719c93844ef7402864803 (diff) | |
add gpio support to atheros, fixes #1861, thanks Othello
git-svn-id: svn://svn.openwrt.org/openwrt/trunk@10724 3c298f89-4303-0410-b956-a3cf2f4a3e73
Diffstat (limited to 'target')
17 files changed, 531 insertions, 19 deletions
diff --git a/target/linux/atheros/config-2.6.23 b/target/linux/atheros/config-2.6.23 index a71c22ca2..90f390998 100644 --- a/target/linux/atheros/config-2.6.23 +++ b/target/linux/atheros/config-2.6.23 @@ -50,6 +50,7 @@ CONFIG_DMA_NONCOHERENT=y  CONFIG_FS_POSIX_ACL=y  CONFIG_GENERIC_FIND_NEXT_BIT=y  # CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ is not set +CONFIG_GPIO_DEVICE=y  CONFIG_HAS_DMA=y  CONFIG_HAS_IOMEM=y  CONFIG_HAS_IOPORT=y @@ -127,10 +128,10 @@ CONFIG_MTD_PHYSMAP_START=0x0  CONFIG_MTD_REDBOOT_DIRECTORY_BLOCK=-3  CONFIG_MTD_REDBOOT_PARTS=y  CONFIG_MTD_REDBOOT_PARTS_READONLY=y -# CONFIG_MTD_REDBOOT_PARTS_UNALLOCATED is not set  # CONFIG_MTD_ROM is not set  # CONFIG_MTD_SLRAM is not set  CONFIG_MTD_SPIFLASH=y +CONFIG_NEW_GPIO=y  # CONFIG_NO_IOPORT is not set  # CONFIG_PAGE_SIZE_16KB is not set  CONFIG_PAGE_SIZE_4KB=y diff --git a/target/linux/atheros/config-2.6.24 b/target/linux/atheros/config-2.6.24 index 652e71295..8a4779a8f 100644 --- a/target/linux/atheros/config-2.6.24 +++ b/target/linux/atheros/config-2.6.24 @@ -194,3 +194,5 @@ CONFIG_TRAD_SIGNALS=y  # CONFIG_USER_NS is not set  # CONFIG_VGASTATE is not set  CONFIG_ZONE_DMA_FLAG=0 +CONFIG_NEW_GPIO=y +CONFIG_GPIO_DEVICE=y diff --git a/target/linux/atheros/files/arch/mips/atheros/Makefile b/target/linux/atheros/files/arch/mips/atheros/Makefile index 2c2b991bc..0d00336fd 100644 --- a/target/linux/atheros/files/arch/mips/atheros/Makefile +++ b/target/linux/atheros/files/arch/mips/atheros/Makefile @@ -8,6 +8,6 @@  # Copyright (C) 2006 Felix Fietkau <nbd@openwrt.org>  # -obj-y += board.o prom.o reset.o +obj-y += board.o prom.o reset.o gpio.o  obj-$(CONFIG_ATHEROS_AR5312) += ar5312/  obj-$(CONFIG_ATHEROS_AR5315) += ar5315/ diff --git a/target/linux/atheros/files/arch/mips/atheros/ar5312/board.c b/target/linux/atheros/files/arch/mips/atheros/ar5312/board.c index dac83f0a3..3768e30be 100644 --- a/target/linux/atheros/files/arch/mips/atheros/ar5312/board.c +++ b/target/linux/atheros/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 diff --git a/target/linux/atheros/files/arch/mips/atheros/ar5312/irq.c b/target/linux/atheros/files/arch/mips/atheros/ar5312/irq.c index ac52d9e5d..95bcf3a45 100644 --- a/target/linux/atheros/files/arch/mips/atheros/ar5312/irq.c +++ b/target/linux/atheros/files/arch/mips/atheros/ar5312/irq.c @@ -23,7 +23,9 @@  #include <asm/time.h>  #include <asm/irq.h>  #include <asm/io.h> -#include "../ar531x.h" + +#include <ar531x.h> +#include <gpio.h>  /*   * Called when an interrupt is received, this function @@ -53,6 +55,8 @@ asmlinkage void ar5312_irq_dispatch(void)  			(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_GPIO) +			ar5312_gpio_irq_dispatch();   		else if ((ar531x_misc_intrs & AR531X_ISR_UART0))  			do_IRQ(AR531X_MISC_IRQ_UART0);  		else if (ar531x_misc_intrs & AR531X_ISR_WD) diff --git a/target/linux/atheros/files/arch/mips/atheros/ar5315/board.c b/target/linux/atheros/files/arch/mips/atheros/ar5315/board.c index 8247d8548..57d17f526 100644 --- a/target/linux/atheros/files/arch/mips/atheros/ar5315/board.c +++ b/target/linux/atheros/files/arch/mips/atheros/ar5315/board.c @@ -26,7 +26,7 @@  #include <asm/time.h>  #include <asm/irq.h>  #include <asm/io.h> -#include "../ar531x.h" +#include <ar531x.h>  static int is_5315 = 0; diff --git a/target/linux/atheros/files/arch/mips/atheros/ar5315/irq.c b/target/linux/atheros/files/arch/mips/atheros/ar5315/irq.c index 750c90540..621c7fc0b 100644 --- a/target/linux/atheros/files/arch/mips/atheros/ar5315/irq.c +++ b/target/linux/atheros/files/arch/mips/atheros/ar5315/irq.c @@ -23,7 +23,9 @@  #include <asm/bootinfo.h>  #include <asm/irq_cpu.h>  #include <asm/io.h> -#include "../ar531x.h" + +#include <ar531x.h> +#include <gpio.h>  static u32 gpiointmask = 0, gpiointval = 0; diff --git a/target/linux/atheros/files/arch/mips/atheros/board.c b/target/linux/atheros/files/arch/mips/atheros/board.c index ccbda4854..59aa134a3 100644 --- a/target/linux/atheros/files/arch/mips/atheros/board.c +++ b/target/linux/atheros/files/arch/mips/atheros/board.c @@ -25,7 +25,7 @@  #include <asm/bootinfo.h>  #include <asm/irq_cpu.h>  #include <asm/io.h> -#include "ar531x.h" +#include <ar531x.h>  char *board_config, *radio_config; @@ -216,3 +216,24 @@ void __init arch_init_irq(void)  	DO_AR5312(ar5312_misc_intr_init(AR531X_MISC_IRQ_BASE);)  	DO_AR5315(ar5315_misc_intr_init(AR531X_MISC_IRQ_BASE);)  } + +static int __init ar531x_register_gpiodev(void) +{ +	static struct resource res = { +		.start = 0xFFFFFFFF, +	}; +	struct platform_device *pdev; + +	printk(KERN_INFO "ar531x: Registering GPIODEV device\n"); +	 +	pdev = platform_device_register_simple("GPIODEV", 0, &res, 1); + +	if (!pdev) { +		printk(KERN_ERR "ar531x: GPIODEV init failed\n"); +		return -ENODEV; +	} + +	return 0; +} + +device_initcall(ar531x_register_gpiodev); diff --git a/target/linux/atheros/files/arch/mips/atheros/gpio.c b/target/linux/atheros/files/arch/mips/atheros/gpio.c new file mode 100644 index 000000000..5e34c857c --- /dev/null +++ b/target/linux/atheros/files/arch/mips/atheros/gpio.c @@ -0,0 +1,339 @@ +/* + * 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) 2007 Othello <bach_ag@hotmail.com> + */ + +/* + * Support for AR531X GPIO -- General Purpose Input/Output Pins + */ + +#include <linux/autoconf.h> +#include <linux/init.h> +#include <linux/interrupt.h> +#include <linux/types.h> +#include <linux/module.h> +#include <linux/delay.h> +#include <linux/platform_device.h> +#include <linux/irq.h> + +#include <asm/addrspace.h> +#include <asm/io.h> +#include <asm/irq_cpu.h> +#include <asm/gpio.h> +#include "ar531x.h" +/*  +   GPIO Interrupt Support +      Make use of request_irq() and the function gpio_to_irq() to trap gpio events + */ + +/* Global variables */ +static u32 ar531x_gpio_intr_Mask = 0; +/* +    AR5312: I don't have any devices with this chip. Assumed to be similar to AR5215 +    will someone who has one try the code and remove this message if it works? + */ + +#ifdef CONFIG_ATHEROS_AR5315 +/* +    AR5315: Up to 2 GPIO pins may be monitored simultaneously +    specifying more pins if you already have 2 will not have any effect +        however, the excess gpio irqs will also be triggered if a valid gpio being monitored triggers +    only high, low or edge triggered interrupt supported + */ +static unsigned int ar5315_gpio_set_type_gpio = 0; +static unsigned int ar5315_gpio_set_type_lvl = IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING; +#endif + +#ifdef CONFIG_ATHEROS_AR5312 +/* Enable the specified AR5312_GPIO_IRQ interrupt */ +static void ar5312_gpio_intr_enable(unsigned int irq) { +	u32 reg; +	unsigned int gpio; +	unsigned int imr; + +	gpio = irq - (AR531X_GPIO_IRQ(0)); +	if (gpio >= AR531X_NUM_GPIO) +		return; +	ar531x_gpio_intr_Mask |= (1<<gpio); + +	reg = sysRegRead(AR531X_GPIO_CR); +	reg &= ~(AR531X_GPIO_CR_M(gpio) | AR531X_GPIO_CR_UART(gpio) | AR531X_GPIO_CR_INT(gpio)); +	reg |= AR531X_GPIO_CR_I(gpio); +	reg |= AR531X_GPIO_CR_INT(gpio); + +	sysRegWrite(AR531X_GPIO_CR, reg); +	(void)sysRegRead(AR531X_GPIO_CR); /* flush to hardware */ + +	imr = sysRegRead(AR531X_IMR); +	imr |= AR531X_ISR_GPIO; +	sysRegWrite(AR531X_IMR, imr); +	imr = sysRegRead(AR531X_IMR); /* flush write buffer */ +} + +/* Disable the specified AR5312_GPIO_IRQ interrupt */ +static void ar5312_gpio_intr_disable(unsigned int irq) { +	u32 reg; +	unsigned int gpio; +	gpio = irq - (AR531X_GPIO_IRQ(0)); +	if (gpio >= AR531X_NUM_GPIO) +		return; + +	reg = sysRegRead(AR531X_GPIO_CR); +	reg &= ~(AR531X_GPIO_CR_M(gpio) | AR531X_GPIO_CR_UART(gpio) | AR531X_GPIO_CR_INT(gpio)); +	reg |= AR531X_GPIO_CR_I(gpio); +	/* No GPIO_CR_INT bit */ + +	sysRegWrite(AR531X_GPIO_CR, reg); +	(void)sysRegRead(AR531X_GPIO_CR); /* flush to hardware */ + +	/* Disable Interrupt if no gpio needs triggering */ +	if (ar531x_gpio_intr_Mask != 0) { +		unsigned int imr; + +		imr = sysRegRead(AR531X_IMR); +		imr &= ~AR531X_ISR_GPIO; +		sysRegWrite(AR531X_IMR, imr); +		imr = sysRegRead(AR531X_IMR); /* flush write buffer */ +	} + +	ar531x_gpio_intr_Mask &= ~(1<<gpio); +} + +/* Turn on the specified AR5312_GPIO_IRQ interrupt */ +static unsigned int ar5312_gpio_intr_startup(unsigned int irq) { +	ar5312_gpio_intr_enable(irq); +	return 0; +} + +static void ar5312_gpio_intr_end(unsigned int irq) { +	if (!(irq_desc[irq].status & (IRQ_DISABLED | IRQ_INPROGRESS))) +		ar5312_gpio_intr_enable(irq); +} + +asmlinkage void ar5312_gpio_irq_dispatch(void) { +	int i; +	u32 gpioIntPending; +	gpioIntPending = sysRegRead(AR531X_GPIO_DI) & ar531x_gpio_intr_Mask; +	sysRegWrite(AR531X_ISR, sysRegRead(AR531X_IMR) | ~AR531X_ISR_GPIO); +	for (i=0; i<AR531X_GPIO_IRQ_COUNT; i++) { +	if (gpioIntPending & (1 << i)) +		do_IRQ(AR531X_GPIO_IRQ(i)); +	} +} +#endif	/* #ifdef CONFIG_ATHEROS_AR5312 */ + +#ifdef CONFIG_ATHEROS_AR5315 +/* Enable the specified AR5315_GPIO_IRQ interrupt */ +static void ar5315_gpio_intr_enable(unsigned int irq) { +	u32 reg; +	unsigned int gpio; +	unsigned int imr; +	unsigned int i; + +	gpio = irq - (AR531X_GPIO_IRQ(0)); +	if (gpio >= AR5315_NUM_GPIO) +		return; +	ar531x_gpio_intr_Mask |= (1<<gpio); + +	reg = sysRegRead(AR5315_GPIO_CR); +	reg &= ~(AR5315_GPIO_CR_M(gpio)); +	reg |= AR5315_GPIO_CR_I(gpio); +	sysRegWrite(AR5315_GPIO_CR, reg); +	(void)sysRegRead(AR5315_GPIO_CR); /* flush write to hardware */ + +	/* Locate a free register slot to enable gpio intr  +	   will fail silently if no more slots are available +	 */ +	reg = sysRegRead(AR5315_GPIO_INT); +	for (i=0 ; i<=AR5315_GPIO_INT_MAX_Y ; i++) { +		/* Free slot means trigger level = 0 */ +		if ( AR5315_GPIO_INT_LVL_OFF == +		    (reg & AR5315_GPIO_INT_LVL_M) ) { + +			unsigned int def_lvl = AR5315_GPIO_INT_LVL_EDGE; +			if (ar5315_gpio_set_type_gpio == gpio) +				def_lvl = ar5315_gpio_set_type_lvl; + +			/* Set the gpio level trigger mode */ +/*			reg &= ~(AR5315_GPIO_INT_LVL_M(i)); */ +			reg |= AR5315_GPIO_INT_LVL(i); + +			/* Enable the gpio pin */ +			reg &= ~(AR5315_GPIO_INT_M); +			reg |= AR5315_GPIO_INT_S(i); + +			sysRegWrite(AR5315_GPIO_INT, reg); +			(void)sysRegRead(AR5315_GPIO_INT); /* flush write to hardware */ + +			/* break out of for loop */ +			break; +		} /* end if trigger level for slot i is 0 */ +	} /* end for each slot */ + +	imr = sysRegRead(AR5315_IMR); +	imr |= AR5315_ISR_GPIO; +	sysRegWrite(AR5315_IMR, imr); +	imr = sysRegRead(AR5315_IMR); /* flush write buffer */ +} + + +/* Disable the specified AR5315_GPIO_IRQ interrupt */ +static void ar5315_gpio_intr_disable(unsigned int irq) { +	u32 reg; +	unsigned int gpio; +	unsigned int i; + +	gpio = irq - (AR531X_GPIO_IRQ(0)); +	if (gpio >= AR5315_NUM_GPIO) +		return; + +	reg = sysRegRead(AR5315_GPIO_CR); +	reg &= ~(AR5315_GPIO_CR_M(gpio)); +	reg |= AR5315_GPIO_CR_I(gpio); +	sysRegWrite(AR5315_GPIO_CR, reg); +	(void)sysRegRead(AR5315_GPIO_CR); /* flush write to hardware */ + +	/* Locate a the correct register slot to disable gpio intr */ +	reg = sysRegRead(AR5315_GPIO_INT); +	for (i=0 ; i<=AR5315_GPIO_INT_MAX_Y ; i++) { +		/* If this correct  */ +		if ( AR5315_GPIO_INT_S(i) == +		    (reg & AR5315_GPIO_INT_M) ) { +			/* Clear the gpio level trigger mode */ +			reg &= ~(AR5315_GPIO_INT_LVL_M); + +			sysRegWrite(AR5315_GPIO_INT, reg); +			(void)sysRegRead(AR5315_GPIO_INT); /* flush write to hardware */ +			break; +		} /* end if trigger level for slot i is 0 */ +	} /* end for each slot */ + +	/* Disable interrupt only if no gpio needs triggering */ +	if (ar531x_gpio_intr_Mask != 0) { +		unsigned int imr; + +		imr = sysRegRead(AR5315_IMR); +		imr &= ~AR5315_ISR_GPIO; +		sysRegWrite(AR5315_IMR, imr); +		imr = sysRegRead(AR5315_IMR); /* flush write buffer */ +	} + +	ar531x_gpio_intr_Mask &= ~(1<<gpio); +} + +/* Turn on the specified AR5315_GPIO_IRQ interrupt */ +static unsigned int ar5315_gpio_intr_startup(unsigned int irq) { +	ar5315_gpio_intr_enable(irq); +	return 0; +} + +static void ar5315_gpio_intr_end(unsigned int irq) { +	if (!(irq_desc[irq].status & (IRQ_DISABLED | IRQ_INPROGRESS))) +		ar5315_gpio_intr_enable(irq); +} + +static int ar5315_gpio_intr_set_type(unsigned int irq, unsigned int flow_type) { +	ar5315_gpio_set_type_gpio = irq - (AR531X_GPIO_IRQ(0)); +	if (ar5315_gpio_set_type_gpio > AR5315_NUM_GPIO) +		return -EINVAL; +	switch (flow_type & IRQF_TRIGGER_MASK) { +		case IRQF_TRIGGER_RISING: +		case IRQF_TRIGGER_FALLING: +			printk(KERN_WARNING "AR5315 GPIO %u falling back to edge triggered\n", ar5315_gpio_set_type_gpio); +		case IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING: +			ar5315_gpio_set_type_lvl = AR5315_GPIO_INT_LVL_EDGE; +			break; +		case IRQF_TRIGGER_LOW: +			ar5315_gpio_set_type_lvl = AR5315_GPIO_INT_LVL_LOW; +			break; +		case IRQF_TRIGGER_HIGH: +			ar5315_gpio_set_type_lvl = AR5315_GPIO_INT_LVL_HIGH; +			break; +		default: +			return -EINVAL; +	} +	return 0; +} + +asmlinkage void ar5315_gpio_irq_dispatch(void){ +	int i; +	u32 gpioIntPending; +	gpioIntPending = sysRegRead(AR5315_GPIO_DI) & ar531x_gpio_intr_Mask; +	sysRegWrite(AR5315_ISR, sysRegRead(AR5315_IMR) | ~AR5315_ISR_GPIO); +	for (i=0; i<AR531X_GPIO_IRQ_COUNT; i++) { +	if (gpioIntPending & (1 << i)) +		do_IRQ(AR531X_GPIO_IRQ(i)); +	} +} +#endif /* #ifdef CONFIG_ATHEROS_AR5315  */ + +/* Common Code */ +static struct irq_chip ar531x_gpio_intr_controller = { +	.typename	= "AR531X GPIO", +}; + +/* ARGSUSED */ +irqreturn_t +spurious_gpio_handler(int cpl, void *dev_id) +{ +	u32 gpioDataIn; +	DO_AR5312(gpioDataIn = sysRegRead(AR531X_GPIO_DI);) +	DO_AR5315(gpioDataIn = sysRegRead(AR5315_GPIO_DI);) + +	printk("spurious_gpio_handler: 0x%08x dev=%p DI=0x%08x gpioIntMask=0x%08x\n", +		cpl, dev_id, gpioDataIn, ar531x_gpio_intr_Mask); + +	return IRQ_NONE; +} + +static struct irqaction spurious_gpio  = { +	.handler	= spurious_gpio_handler, +	.name		= "spurious_gpio", +}; + +/* Initialize AR531X GPIO interrupts */ +static int __init ar531x_gpio_init(void) +{ +	int i; + +	DO_AR5312( \ +		ar531x_gpio_intr_controller.startup = ar5312_gpio_intr_startup; \ +		ar531x_gpio_intr_controller.shutdown = ar5312_gpio_intr_disable; \ +		ar531x_gpio_intr_controller.enable = ar5312_gpio_intr_enable; \ +		ar531x_gpio_intr_controller.disable = ar5312_gpio_intr_disable; \ +		ar531x_gpio_intr_controller.ack = ar5312_gpio_intr_disable; \ +		ar531x_gpio_intr_controller.end = ar5312_gpio_intr_end; \ +	) + +	DO_AR5315( \ +		ar531x_gpio_intr_controller.startup = ar5315_gpio_intr_startup; \ +		ar531x_gpio_intr_controller.shutdown = ar5315_gpio_intr_disable; \ +		ar531x_gpio_intr_controller.enable = ar5315_gpio_intr_enable; \ +		ar531x_gpio_intr_controller.disable = ar5315_gpio_intr_disable; \ +		ar531x_gpio_intr_controller.ack = ar5315_gpio_intr_disable; \ +		ar531x_gpio_intr_controller.end = ar5315_gpio_intr_end; \ +		ar531x_gpio_intr_controller.set_type = ar5315_gpio_intr_set_type; \ +	) + +	for (i = AR531X_GPIO_IRQ_BASE; +	     i < AR531X_GPIO_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 = &ar531x_gpio_intr_controller; +	} + +	setup_irq(AR531X_GPIO_IRQ_NONE, &spurious_gpio); + +	return 0; +} + +subsys_initcall(ar531x_gpio_init); + diff --git a/target/linux/atheros/files/arch/mips/atheros/prom.c b/target/linux/atheros/files/arch/mips/atheros/prom.c index 250507046..73c66aca5 100644 --- a/target/linux/atheros/files/arch/mips/atheros/prom.c +++ b/target/linux/atheros/files/arch/mips/atheros/prom.c @@ -23,7 +23,7 @@  #include <asm/bootinfo.h>  #include <asm/addrspace.h> -#include "ar531x.h" +#include <ar531x.h>  void __init prom_init(void)  { diff --git a/target/linux/atheros/files/arch/mips/atheros/reset.c b/target/linux/atheros/files/arch/mips/atheros/reset.c index 52fa3bbfc..3230aa115 100644 --- a/target/linux/atheros/files/arch/mips/atheros/reset.c +++ b/target/linux/atheros/files/arch/mips/atheros/reset.c @@ -7,8 +7,7 @@  #include <linux/netlink.h>  #include <net/sock.h>  #include <asm/uaccess.h> -#include "ar531x.h" -#include "ar5315/ar5315.h" +#include <ar531x.h>  #define AR531X_RESET_GPIO_IRQ	(AR531X_GPIO_IRQ_BASE + bcfg->resetConfigGpio) diff --git a/target/linux/atheros/files/arch/mips/atheros/ar5312/ar5312.h b/target/linux/atheros/files/include/asm-mips/mach-atheros/ar5312/ar5312.h index 2b6b875b4..2b6b875b4 100644 --- a/target/linux/atheros/files/arch/mips/atheros/ar5312/ar5312.h +++ b/target/linux/atheros/files/include/asm-mips/mach-atheros/ar5312/ar5312.h diff --git a/target/linux/atheros/files/arch/mips/atheros/ar5315/ar5315.h b/target/linux/atheros/files/include/asm-mips/mach-atheros/ar5315/ar5315.h index 567141cb7..3930cb905 100644 --- a/target/linux/atheros/files/arch/mips/atheros/ar5315/ar5315.h +++ b/target/linux/atheros/files/include/asm-mips/mach-atheros/ar5315/ar5315.h @@ -349,6 +349,12 @@  #define AR5315_GPIO_INT_LVL(x)             ((x) << 6)                  /* interrupt level */  #define AR5315_GPIO_INT_LVL_M              ((0x3) << 6)                /* mask for int level */ +#define AR5315_GPIO_INT_MAX_Y				1   /* Maximum value of Y for AR5313_GPIO_INT_* macros */ +#define AR5315_GPIO_INT_LVL_OFF				0   /* Triggerring off */ +#define AR5315_GPIO_INT_LVL_LOW				1   /* Low Level Triggered */ +#define AR5315_GPIO_INT_LVL_HIGH			2   /* High Level Triggered */ +#define AR5315_GPIO_INT_LVL_EDGE			3   /* Edge Triggered */ +  #define AR5315_RESET_GPIO       5  #define AR5315_NUM_GPIO         22 diff --git a/target/linux/atheros/files/arch/mips/atheros/ar531x.h b/target/linux/atheros/files/include/asm-mips/mach-atheros/ar531x.h index d790a8807..c77d74ec9 100644 --- a/target/linux/atheros/files/arch/mips/atheros/ar531x.h +++ b/target/linux/atheros/files/include/asm-mips/mach-atheros/ar531x.h @@ -4,8 +4,8 @@  #include <linux/version.h>  #include <asm/cpu-info.h>  #include <ar531x_platform.h> -#include "ar5312/ar5312.h" -#include "ar5315/ar5315.h" +#include <ar5312/ar5312.h> +#include <ar5315/ar5315.h>  #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,24))  extern void (*board_time_init)(void); @@ -76,8 +76,8 @@ static inline int clz(unsigned long val)  #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 -#define AR531X_GPIO_IRQ(n)              AR531X_MISC_IRQ_BASE+(n)+1 +#define AR531X_GPIO_IRQ_NONE            AR531X_GPIO_IRQ_BASE+0 +#define AR531X_GPIO_IRQ(n)              AR531X_GPIO_IRQ_BASE+(n)+1  #define AR531X_GPIO_IRQ_COUNT           22  #define sysRegRead(phys)	\ @@ -167,4 +167,6 @@ static inline u32 sysRegMask(u32 phys, u32 mask, u32 value)  	return reg;  } +#define AR531X_NUM_GPIO		8 +  #endif diff --git a/target/linux/atheros/files/include/asm-mips/mach-atheros/gpio.h b/target/linux/atheros/files/include/asm-mips/mach-atheros/gpio.h new file mode 100644 index 000000000..560b8cc0d --- /dev/null +++ b/target/linux/atheros/files/include/asm-mips/mach-atheros/gpio.h @@ -0,0 +1,134 @@ +#ifndef _ATHEROS_GPIO_H_ +#define _ATHEROS_GPIO_H_ + +#include "ar531x.h" + +/* Common AR531X global variables */ +/* extern u32 ar531x_gpio_intr_Mask; */ + +/* AR5312 exported routines */ +#ifdef CONFIG_ATHEROS_AR5312 +asmlinkage void ar5312_gpio_irq_dispatch(void); +#endif + +/* AR5315 exported routines */ +#ifdef CONFIG_ATHEROS_AR5315 +asmlinkage void ar5315_gpio_irq_dispatch(void); +#endif + +/* + * Wrappers for the generic GPIO layer + */ + +/* Sets a gpio to input, or returns ENXIO for non-existent gpio */ +static inline int gpio_direction_input(unsigned gpio) { +	DO_AR5312(	if (gpio > AR531X_NUM_GPIO) {			\ +				return -ENXIO;				\ +			} else {					\ +				sysRegWrite(AR531X_GPIO_CR,		\ +					( sysRegRead(AR531X_GPIO_CR) &	\ +					  ~(AR531X_GPIO_CR_M(gpio)) ) |	\ +					  AR531X_GPIO_CR_I(gpio) );	\ +				return 0;				\ +			}						\ +	) +	DO_AR5315(	if (gpio > AR5315_NUM_GPIO) {			\ +				return -ENXIO;				\ +			} else {					\ +				sysRegWrite(AR5315_GPIO_CR,		\ +					( sysRegRead(AR5315_GPIO_CR) &	\ +					  ~(AR5315_GPIO_CR_M(gpio)) ) |	\ +					  AR5315_GPIO_CR_I(gpio) );	\ +				return 0;				\ +			}						\ +	) +} + +/* Sets a gpio to output with value, or returns ENXIO for non-existent gpio */ +static inline int gpio_direction_output(unsigned gpio, int value) { +	DO_AR5312(	if (gpio > AR531X_NUM_GPIO) {			\ +				return -ENXIO;				\ +			} else {					\ +				sysRegWrite(AR531X_GPIO_DO,		\ +					( (sysRegRead(AR531X_GPIO_DO) &	\ +					  ~(1 << gpio) ) |		\ +					  ((value!=0) << gpio)) );	\ +				sysRegWrite(AR531X_GPIO_CR,		\ +					sysRegRead(AR531X_GPIO_CR) |	\ +					AR531X_GPIO_CR_O(gpio) );	\ +				return 0;				\ +			}						\ +	) +	DO_AR5315(	if (gpio > AR5315_NUM_GPIO) {			\ +				return -ENXIO;				\ +			} else {					\ +				sysRegWrite(AR5315_GPIO_DO,		\ +					( (sysRegRead(AR5315_GPIO_DO) &	\ +					  ~(1 << gpio)) |		\ +					  ((value!=0) << gpio)) );	\ +				sysRegWrite(AR5315_GPIO_CR,		\ +					sysRegRead(AR5315_GPIO_CR) |	\ +					AR5315_GPIO_CR_O(gpio) );	\ +				return 0;				\ +			}						\ +	) +} + +/* Reads the gpio pin.  Unchecked function */ +static inline int gpio_get_value(unsigned gpio) { +	DO_AR5312(return (sysRegRead(AR531X_GPIO_DI) & (1 << gpio));) +	DO_AR5315(return (sysRegRead(AR5315_GPIO_DI) & (1 << gpio));) +} + +/* Writes to the gpio pin.  Unchecked function */ +static inline void gpio_set_value(unsigned gpio, int value) { +	DO_AR5312(	sysRegWrite(AR531X_GPIO_DO,	\ +			( (sysRegRead(AR531X_GPIO_DO) &	\ +			  ~(1 << gpio)) |		\ +			  ((value!=0) << gpio)) );	\ +	) +	DO_AR5315(	sysRegWrite(AR5315_GPIO_DO,	\ +			( (sysRegRead(AR5315_GPIO_DO) &	\ +			  ~(1 << gpio)) |		\ +			  ((value!=0) << gpio)) );	\ +	) +} + +static inline int gpio_request(unsigned gpio, const char *label) { +	return 0; +} + +static inline void gpio_free(unsigned gpio) { +} + +/* Returns IRQ to attach for gpio.  Unchecked function */ +static inline int gpio_to_irq(unsigned gpio) { +	return AR531X_GPIO_IRQ(gpio); +} + +/* Returns gpio for IRQ attached.  Unchecked function */ +static inline int irq_to_gpio(unsigned irq) { +	return (irq - (AR531X_GPIO_IRQ(0))); +} + +/* #include <asm-generic/gpio.h> */ /* cansleep wrappers */ +/* platforms that don't directly support access to GPIOs through I2C, SPI, + * or other blocking infrastructure can use these wrappers. + */ + +static inline int gpio_cansleep(unsigned gpio) { +        return 0; +} + +static inline int gpio_get_value_cansleep(unsigned gpio) { +        might_sleep(); +        return gpio_get_value(gpio); +} + +static inline void gpio_set_value_cansleep(unsigned gpio, int value) { +        might_sleep(); +        gpio_set_value(gpio, value); +} + +#endif + diff --git a/target/linux/atheros/patches-2.6.23/100-board.patch b/target/linux/atheros/patches-2.6.23/100-board.patch index f1aa655f6..28509a3d0 100644 --- a/target/linux/atheros/patches-2.6.23/100-board.patch +++ b/target/linux/atheros/patches-2.6.23/100-board.patch @@ -1,7 +1,7 @@  diff -urN linux.old/arch/mips/Kconfig linux.dev/arch/mips/Kconfig  --- linux.old/arch/mips/Kconfig	2007-02-02 23:55:52.912446784 +0100  +++ linux.dev/arch/mips/Kconfig	2007-02-03 21:50:25.262027104 +0100 -@@ -45,6 +45,15 @@ +@@ -44,6 +44,16 @@   	  note that a kernel built with this option selected will not be   	  able to run on normal units. @@ -13,18 +13,19 @@ diff -urN linux.old/arch/mips/Kconfig linux.dev/arch/mips/Kconfig  +	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 DMA_NONCOHERENT -@@ -658,6 +668,7 @@ +@@ -597,6 +607,7 @@   endchoice  +source "arch/mips/atheros/Kconfig"   source "arch/mips/au1000/Kconfig" - source "arch/mips/ddb5xxx/Kconfig" - source "arch/mips/gt64120/ev64120/Kconfig" + source "arch/mips/jazz/Kconfig" + source "arch/mips/pmc-sierra/Kconfig"  diff -urN linux.old/arch/mips/Makefile linux.dev/arch/mips/Makefile  --- linux.old/arch/mips/Makefile	2007-02-02 23:55:52.913446632 +0100  +++ linux.dev/arch/mips/Makefile	2007-02-03 17:40:29.193776000 +0100 diff --git a/target/linux/atheros/patches-2.6.24/100-board.patch b/target/linux/atheros/patches-2.6.24/100-board.patch index fc72d8293..f1a0d0641 100644 --- a/target/linux/atheros/patches-2.6.24/100-board.patch +++ b/target/linux/atheros/patches-2.6.24/100-board.patch @@ -1,7 +1,7 @@  diff -urN linux.old/arch/mips/Kconfig linux.dev/arch/mips/Kconfig  --- linux.old/arch/mips/Kconfig	2007-02-02 23:55:52.912446784 +0100  +++ linux.dev/arch/mips/Kconfig	2007-02-03 21:50:25.262027104 +0100 -@@ -45,6 +45,17 @@ +@@ -45,6 +45,18 @@   	  note that a kernel built with this option selected will not be   	  able to run on normal units. @@ -15,6 +15,7 @@ diff -urN linux.old/arch/mips/Kconfig linux.dev/arch/mips/Kconfig  +	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"  | 
