mirror of
git://projects.qi-hardware.com/openwrt-xburst.git
synced 2024-11-19 04:49:42 +02:00
add gpio support to atheros, fixes #1861, thanks Othello
git-svn-id: svn://svn.openwrt.org/openwrt/trunk@10724 3c298f89-4303-0410-b956-a3cf2f4a3e73
This commit is contained in:
parent
19910c310a
commit
66b7ecf8e0
@ -19,7 +19,7 @@ define Package/gpioctl
|
|||||||
SECTION:=utils
|
SECTION:=utils
|
||||||
CATEGORY:=Utilities
|
CATEGORY:=Utilities
|
||||||
TITLE:=Tool for controlling gpio pins
|
TITLE:=Tool for controlling gpio pins
|
||||||
DEPENDS:=@LINUX_2_6&&(@TARGET_ixp4xx||@TARGET_brcm47xx)
|
DEPENDS:=@LINUX_2_6&&(@TARGET_ixp4xx||@TARGET_brcm47xx||@TARGET_atheros)
|
||||||
endef
|
endef
|
||||||
|
|
||||||
define Package/gpioctl/description
|
define Package/gpioctl/description
|
||||||
|
@ -50,6 +50,7 @@ CONFIG_DMA_NONCOHERENT=y
|
|||||||
CONFIG_FS_POSIX_ACL=y
|
CONFIG_FS_POSIX_ACL=y
|
||||||
CONFIG_GENERIC_FIND_NEXT_BIT=y
|
CONFIG_GENERIC_FIND_NEXT_BIT=y
|
||||||
# CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ is not set
|
# CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ is not set
|
||||||
|
CONFIG_GPIO_DEVICE=y
|
||||||
CONFIG_HAS_DMA=y
|
CONFIG_HAS_DMA=y
|
||||||
CONFIG_HAS_IOMEM=y
|
CONFIG_HAS_IOMEM=y
|
||||||
CONFIG_HAS_IOPORT=y
|
CONFIG_HAS_IOPORT=y
|
||||||
@ -127,10 +128,10 @@ CONFIG_MTD_PHYSMAP_START=0x0
|
|||||||
CONFIG_MTD_REDBOOT_DIRECTORY_BLOCK=-3
|
CONFIG_MTD_REDBOOT_DIRECTORY_BLOCK=-3
|
||||||
CONFIG_MTD_REDBOOT_PARTS=y
|
CONFIG_MTD_REDBOOT_PARTS=y
|
||||||
CONFIG_MTD_REDBOOT_PARTS_READONLY=y
|
CONFIG_MTD_REDBOOT_PARTS_READONLY=y
|
||||||
# CONFIG_MTD_REDBOOT_PARTS_UNALLOCATED is not set
|
|
||||||
# CONFIG_MTD_ROM is not set
|
# CONFIG_MTD_ROM is not set
|
||||||
# CONFIG_MTD_SLRAM is not set
|
# CONFIG_MTD_SLRAM is not set
|
||||||
CONFIG_MTD_SPIFLASH=y
|
CONFIG_MTD_SPIFLASH=y
|
||||||
|
CONFIG_NEW_GPIO=y
|
||||||
# CONFIG_NO_IOPORT is not set
|
# CONFIG_NO_IOPORT is not set
|
||||||
# CONFIG_PAGE_SIZE_16KB is not set
|
# CONFIG_PAGE_SIZE_16KB is not set
|
||||||
CONFIG_PAGE_SIZE_4KB=y
|
CONFIG_PAGE_SIZE_4KB=y
|
||||||
|
@ -194,3 +194,5 @@ CONFIG_TRAD_SIGNALS=y
|
|||||||
# CONFIG_USER_NS is not set
|
# CONFIG_USER_NS is not set
|
||||||
# CONFIG_VGASTATE is not set
|
# CONFIG_VGASTATE is not set
|
||||||
CONFIG_ZONE_DMA_FLAG=0
|
CONFIG_ZONE_DMA_FLAG=0
|
||||||
|
CONFIG_NEW_GPIO=y
|
||||||
|
CONFIG_GPIO_DEVICE=y
|
||||||
|
@ -8,6 +8,6 @@
|
|||||||
# Copyright (C) 2006 Felix Fietkau <nbd@openwrt.org>
|
# 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_AR5312) += ar5312/
|
||||||
obj-$(CONFIG_ATHEROS_AR5315) += ar5315/
|
obj-$(CONFIG_ATHEROS_AR5315) += ar5315/
|
||||||
|
@ -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
|
||||||
|
|
||||||
|
@ -23,7 +23,9 @@
|
|||||||
#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>
|
||||||
|
#include <gpio.h>
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Called when an interrupt is received, this function
|
* Called when an interrupt is received, this function
|
||||||
@ -53,6 +55,8 @@ asmlinkage void ar5312_irq_dispatch(void)
|
|||||||
(void)sysRegRead(AR531X_TIMER);
|
(void)sysRegRead(AR531X_TIMER);
|
||||||
} else if (ar531x_misc_intrs & AR531X_ISR_AHBPROC)
|
} else if (ar531x_misc_intrs & AR531X_ISR_AHBPROC)
|
||||||
do_IRQ(AR531X_MISC_IRQ_AHB_PROC);
|
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))
|
else if ((ar531x_misc_intrs & AR531X_ISR_UART0))
|
||||||
do_IRQ(AR531X_MISC_IRQ_UART0);
|
do_IRQ(AR531X_MISC_IRQ_UART0);
|
||||||
else if (ar531x_misc_intrs & AR531X_ISR_WD)
|
else if (ar531x_misc_intrs & AR531X_ISR_WD)
|
||||||
|
@ -26,7 +26,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>
|
||||||
|
|
||||||
static int is_5315 = 0;
|
static int is_5315 = 0;
|
||||||
|
|
||||||
|
@ -23,7 +23,9 @@
|
|||||||
#include <asm/bootinfo.h>
|
#include <asm/bootinfo.h>
|
||||||
#include <asm/irq_cpu.h>
|
#include <asm/irq_cpu.h>
|
||||||
#include <asm/io.h>
|
#include <asm/io.h>
|
||||||
#include "../ar531x.h"
|
|
||||||
|
#include <ar531x.h>
|
||||||
|
#include <gpio.h>
|
||||||
|
|
||||||
static u32 gpiointmask = 0, gpiointval = 0;
|
static u32 gpiointmask = 0, gpiointval = 0;
|
||||||
|
|
||||||
|
@ -25,7 +25,7 @@
|
|||||||
#include <asm/bootinfo.h>
|
#include <asm/bootinfo.h>
|
||||||
#include <asm/irq_cpu.h>
|
#include <asm/irq_cpu.h>
|
||||||
#include <asm/io.h>
|
#include <asm/io.h>
|
||||||
#include "ar531x.h"
|
#include <ar531x.h>
|
||||||
|
|
||||||
char *board_config, *radio_config;
|
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_AR5312(ar5312_misc_intr_init(AR531X_MISC_IRQ_BASE);)
|
||||||
DO_AR5315(ar5315_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);
|
||||||
|
339
target/linux/atheros/files/arch/mips/atheros/gpio.c
Normal file
339
target/linux/atheros/files/arch/mips/atheros/gpio.c
Normal file
@ -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);
|
||||||
|
|
@ -23,7 +23,7 @@
|
|||||||
|
|
||||||
#include <asm/bootinfo.h>
|
#include <asm/bootinfo.h>
|
||||||
#include <asm/addrspace.h>
|
#include <asm/addrspace.h>
|
||||||
#include "ar531x.h"
|
#include <ar531x.h>
|
||||||
|
|
||||||
void __init prom_init(void)
|
void __init prom_init(void)
|
||||||
{
|
{
|
||||||
|
@ -7,8 +7,7 @@
|
|||||||
#include <linux/netlink.h>
|
#include <linux/netlink.h>
|
||||||
#include <net/sock.h>
|
#include <net/sock.h>
|
||||||
#include <asm/uaccess.h>
|
#include <asm/uaccess.h>
|
||||||
#include "ar531x.h"
|
#include <ar531x.h>
|
||||||
#include "ar5315/ar5315.h"
|
|
||||||
|
|
||||||
#define AR531X_RESET_GPIO_IRQ (AR531X_GPIO_IRQ_BASE + bcfg->resetConfigGpio)
|
#define AR531X_RESET_GPIO_IRQ (AR531X_GPIO_IRQ_BASE + bcfg->resetConfigGpio)
|
||||||
|
|
||||||
|
@ -349,6 +349,12 @@
|
|||||||
#define AR5315_GPIO_INT_LVL(x) ((x) << 6) /* interrupt level */
|
#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_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_RESET_GPIO 5
|
||||||
#define AR5315_NUM_GPIO 22
|
#define AR5315_NUM_GPIO 22
|
||||||
|
|
@ -4,8 +4,8 @@
|
|||||||
#include <linux/version.h>
|
#include <linux/version.h>
|
||||||
#include <asm/cpu-info.h>
|
#include <asm/cpu-info.h>
|
||||||
#include <ar531x_platform.h>
|
#include <ar531x_platform.h>
|
||||||
#include "ar5312/ar5312.h"
|
#include <ar5312/ar5312.h>
|
||||||
#include "ar5315/ar5315.h"
|
#include <ar5315/ar5315.h>
|
||||||
|
|
||||||
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,24))
|
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,24))
|
||||||
extern void (*board_time_init)(void);
|
extern void (*board_time_init)(void);
|
||||||
@ -76,8 +76,8 @@ static inline int clz(unsigned long val)
|
|||||||
#define AR531X_MISC_IRQ_COUNT 10
|
#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_GPIO_IRQ_BASE+0
|
||||||
#define AR531X_GPIO_IRQ(n) AR531X_MISC_IRQ_BASE+(n)+1
|
#define AR531X_GPIO_IRQ(n) AR531X_GPIO_IRQ_BASE+(n)+1
|
||||||
#define AR531X_GPIO_IRQ_COUNT 22
|
#define AR531X_GPIO_IRQ_COUNT 22
|
||||||
|
|
||||||
#define sysRegRead(phys) \
|
#define sysRegRead(phys) \
|
||||||
@ -167,4 +167,6 @@ static inline u32 sysRegMask(u32 phys, u32 mask, u32 value)
|
|||||||
return reg;
|
return reg;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#define AR531X_NUM_GPIO 8
|
||||||
|
|
||||||
#endif
|
#endif
|
134
target/linux/atheros/files/include/asm-mips/mach-atheros/gpio.h
Normal file
134
target/linux/atheros/files/include/asm-mips/mach-atheros/gpio.h
Normal file
@ -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
|
||||||
|
|
@ -1,7 +1,7 @@
|
|||||||
diff -urN linux.old/arch/mips/Kconfig linux.dev/arch/mips/Kconfig
|
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.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
|
+++ 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
|
note that a kernel built with this option selected will not be
|
||||||
able to run on normal units.
|
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_HAS_CPU_MIPS32_R1
|
||||||
+ select SYS_SUPPORTS_BIG_ENDIAN
|
+ select SYS_SUPPORTS_BIG_ENDIAN
|
||||||
+ select SYS_SUPPORTS_32BIT_KERNEL
|
+ select SYS_SUPPORTS_32BIT_KERNEL
|
||||||
|
+ select GENERIC_GPIO
|
||||||
+
|
+
|
||||||
config MIPS_COBALT
|
config MIPS_COBALT
|
||||||
bool "Cobalt Server"
|
bool "Cobalt Server"
|
||||||
select DMA_NONCOHERENT
|
select DMA_NONCOHERENT
|
||||||
@@ -658,6 +668,7 @@
|
@@ -597,6 +607,7 @@
|
||||||
|
|
||||||
endchoice
|
endchoice
|
||||||
|
|
||||||
+source "arch/mips/atheros/Kconfig"
|
+source "arch/mips/atheros/Kconfig"
|
||||||
source "arch/mips/au1000/Kconfig"
|
source "arch/mips/au1000/Kconfig"
|
||||||
source "arch/mips/ddb5xxx/Kconfig"
|
source "arch/mips/jazz/Kconfig"
|
||||||
source "arch/mips/gt64120/ev64120/Kconfig"
|
source "arch/mips/pmc-sierra/Kconfig"
|
||||||
diff -urN linux.old/arch/mips/Makefile linux.dev/arch/mips/Makefile
|
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.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
|
+++ linux.dev/arch/mips/Makefile 2007-02-03 17:40:29.193776000 +0100
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
diff -urN linux.old/arch/mips/Kconfig linux.dev/arch/mips/Kconfig
|
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.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
|
+++ 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
|
note that a kernel built with this option selected will not be
|
||||||
able to run on normal units.
|
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_HAS_CPU_MIPS32_R1
|
||||||
+ select SYS_SUPPORTS_BIG_ENDIAN
|
+ select SYS_SUPPORTS_BIG_ENDIAN
|
||||||
+ select SYS_SUPPORTS_32BIT_KERNEL
|
+ select SYS_SUPPORTS_32BIT_KERNEL
|
||||||
|
+ select GENERIC_GPIO
|
||||||
+
|
+
|
||||||
config MIPS_COBALT
|
config MIPS_COBALT
|
||||||
bool "Cobalt Server"
|
bool "Cobalt Server"
|
||||||
|
Loading…
Reference in New Issue
Block a user