diff options
author | John Crispin <blogic@openwrt.org> | 2008-04-03 20:28:10 +0000 |
---|---|---|
committer | John Crispin <blogic@openwrt.org> | 2008-04-03 20:28:10 +0000 |
commit | 6766d68c8526d03c8080f54a1348a2d0948f38c4 (patch) | |
tree | d5e82292716c3d80a459d15808dbff126cdc5485 /target/linux | |
parent | e4ef075c565397307b3ae809bb901db017d3b046 (diff) | |
download | upstream-6766d68c8526d03c8080f54a1348a2d0948f38c4.tar.gz upstream-6766d68c8526d03c8080f54a1348a2d0948f38c4.tar.bz2 upstream-6766d68c8526d03c8080f54a1348a2d0948f38c4.zip |
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/linux')
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 a71c22ca2e..90f3909986 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 652e712952..8a4779a8f3 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 2c2b991bc4..0d00336fd4 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 dac83f0a3f..3768e30be0 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 ac52d9e5d8..95bcf3a458 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 8247d8548c..57d17f526a 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 750c90540d..621c7fc0b8 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 ccbda48546..59aa134a3f 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 0000000000..5e34c857cc --- /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 250507046c..73c66aca50 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 52fa3bbfcf..3230aa1155 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 2b6b875b4f..2b6b875b4f 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 567141cb76..3930cb9053 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 d790a88073..c77d74ec9f 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 0000000000..560b8cc0dc --- /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 f1aa655f69..28509a3d0c 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 fc72d82933..f1a0d0641a 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" |