From 9b9b83976c64fd220fde833262f6a0c385677d3b Mon Sep 17 00:00:00 2001 From: Gabor Juhos Date: Mon, 10 Dec 2007 14:05:01 +0000 Subject: [PATCH] add support for GPIO IRQs SVN-Revision: 9700 --- .../adm5120/files/arch/mips/adm5120/board.c | 2 + .../adm5120/files/arch/mips/adm5120/gpio.c | 117 ++++++++++++------ .../adm5120/files/arch/mips/adm5120/irq.c | 9 +- .../asm-mips/mach-adm5120/adm5120_info.h | 5 + .../asm-mips/mach-adm5120/adm5120_switch.h | 5 + 5 files changed, 95 insertions(+), 43 deletions(-) diff --git a/target/linux/adm5120/files/arch/mips/adm5120/board.c b/target/linux/adm5120/files/arch/mips/adm5120/board.c index c5ee4e3e72..0ac85f529f 100644 --- a/target/linux/adm5120/files/arch/mips/adm5120/board.c +++ b/target/linux/adm5120/files/arch/mips/adm5120/board.c @@ -83,6 +83,8 @@ static int __init adm5120_board_setup(void) memcpy(&adm5120_board_name, board->name, ADM5120_BOARD_NAMELEN); + adm5120_gpio_init(); + adm5120_board_reset = board->board_reset; if (board->eth_num_ports > 0) adm5120_eth_num_ports = board->eth_num_ports; diff --git a/target/linux/adm5120/files/arch/mips/adm5120/gpio.c b/target/linux/adm5120/files/arch/mips/adm5120/gpio.c index 075ea87416..a6cfdcbe09 100644 --- a/target/linux/adm5120/files/arch/mips/adm5120/gpio.c +++ b/target/linux/adm5120/files/arch/mips/adm5120/gpio.c @@ -37,7 +37,7 @@ #include #include #include - +#include #define GPIO_READ(r) readl((r)) #define GPIO_WRITE(v, r) writel((v), (r)) @@ -46,6 +46,7 @@ struct adm5120_gpio_line { u32 flags; const char *label; + int irq; }; #define GPIO_FLAG_VALID 0x01 @@ -71,36 +72,25 @@ static struct led_desc led_table[15] = { LED_DESC(4, 0), LED_DESC(4, 1), LED_DESC(4, 2) }; -static struct adm5120_gpio_line adm5120_gpio_map[ADM5120_GPIO_COUNT] = { - [ADM5120_GPIO_PIN0] = {.flags = GPIO_FLAG_VALID}, - [ADM5120_GPIO_PIN1] = {.flags = GPIO_FLAG_VALID}, - [ADM5120_GPIO_PIN2] = {.flags = GPIO_FLAG_VALID}, - [ADM5120_GPIO_PIN3] = {.flags = GPIO_FLAG_VALID}, - [ADM5120_GPIO_PIN4] = {.flags = GPIO_FLAG_VALID}, - [ADM5120_GPIO_PIN5] = {.flags = GPIO_FLAG_VALID}, - [ADM5120_GPIO_PIN6] = {.flags = GPIO_FLAG_VALID}, - [ADM5120_GPIO_PIN7] = {.flags = GPIO_FLAG_VALID}, - [ADM5120_GPIO_P0L0] = {.flags = GPIO_FLAG_VALID}, - [ADM5120_GPIO_P0L1] = {.flags = GPIO_FLAG_VALID}, - [ADM5120_GPIO_P0L2] = {.flags = GPIO_FLAG_VALID}, - [ADM5120_GPIO_P1L0] = {.flags = GPIO_FLAG_VALID}, - [ADM5120_GPIO_P1L1] = {.flags = GPIO_FLAG_VALID}, - [ADM5120_GPIO_P1L2] = {.flags = GPIO_FLAG_VALID}, - [ADM5120_GPIO_P2L0] = {.flags = GPIO_FLAG_VALID}, - [ADM5120_GPIO_P2L1] = {.flags = GPIO_FLAG_VALID}, - [ADM5120_GPIO_P2L2] = {.flags = GPIO_FLAG_VALID}, - [ADM5120_GPIO_P3L0] = {.flags = GPIO_FLAG_VALID}, - [ADM5120_GPIO_P3L1] = {.flags = GPIO_FLAG_VALID}, - [ADM5120_GPIO_P3L2] = {.flags = GPIO_FLAG_VALID}, - [ADM5120_GPIO_P4L0] = {.flags = GPIO_FLAG_VALID}, - [ADM5120_GPIO_P4L1] = {.flags = GPIO_FLAG_VALID}, - [ADM5120_GPIO_P4L2] = {.flags = GPIO_FLAG_VALID} -}; +static struct adm5120_gpio_line adm5120_gpio_map[ADM5120_GPIO_COUNT]; + +/*-------------------------------------------------------------------------*/ + +static inline int gpio_is_invalid(unsigned gpio) +{ + if ((gpio > ADM5120_GPIO_MAX) || + (adm5120_gpio_map[gpio].flags & GPIO_FLAG_VALID) == 0); + return 0; -#define gpio_is_invalid(g) ((g) > ADM5120_GPIO_MAX || \ - ((adm5120_gpio_map[(g)].flags & GPIO_FLAG_VALID) == 0)) + return 1; +} + +static inline int gpio_is_used(unsigned gpio) +{ + return ((adm5120_gpio_map[gpio].flags & GPIO_FLAG_USED) != 0); +} -#define gpio_is_used(g) ((adm5120_gpio_map[(g)].flags & GPIO_FLAG_USED) != 0) +/*-------------------------------------------------------------------------*/ /* * Helpers for GPIO lines in GPIO_CONF0 register @@ -247,6 +237,8 @@ static inline int leds_get_value(unsigned led) return 1; } +/*-------------------------------------------------------------------------*/ + /* * Main GPIO support routines */ @@ -325,29 +317,74 @@ EXPORT_SYMBOL(adm5120_gpio_free); int adm5120_gpio_to_irq(unsigned gpio) { - /* FIXME: not yet implemented */ - return -EINVAL; + if (gpio > ADM5120_GPIO_MAX) + return -EINVAL; + + return adm5120_gpio_map[gpio].irq; } EXPORT_SYMBOL(adm5120_gpio_to_irq); int adm5120_irq_to_gpio(unsigned irq) { - /* FIXME: not yet implemented */ + int i; + + for (i = 0; i < ADM5120_GPIO_COUNT; i++) + if (adm5120_gpio_map[i].irq == irq) + return i; + return -EINVAL; } EXPORT_SYMBOL(adm5120_irq_to_gpio); -static int __init adm5120_gpio_init(void) +/*-------------------------------------------------------------------------*/ + +void __init adm5120_gpio_csx0_enable(void) +{ + u32 t; + + t = SW_READ_REG(GPIO_CONF2); + t |= GPIO_CONF2_CSX0; + SW_WRITE_REG(GPIO_CONF2, t); + + adm5120_gpio_map[ADM5120_GPIO_PIN1].flags &= ~GPIO_FLAG_VALID; + adm5120_gpio_map[ADM5120_GPIO_PIN2].irq = ADM5120_IRQ_GPIO2; +} + +void __init adm5120_gpio_csx1_enable(void) +{ + u32 t; + + t = SW_READ_REG(GPIO_CONF2); + t |= GPIO_CONF2_CSX1; + SW_WRITE_REG(GPIO_CONF2, t); + + adm5120_gpio_map[ADM5120_GPIO_PIN3].flags &= ~GPIO_FLAG_VALID; + if (adm5120_package_bga()) + adm5120_gpio_map[ADM5120_GPIO_PIN4].irq = ADM5120_IRQ_GPIO4; +} + +void __init adm5120_gpio_ew_enable(void) +{ + u32 t; + + t = SW_READ_REG(GPIO_CONF2); + t |= GPIO_CONF2_EW; + SW_WRITE_REG(GPIO_CONF2, t); +} + +void __init adm5120_gpio_init(void) { int i; + SW_WRITE_REG(GPIO_CONF2, 0); + + for (i = 0; i < ADM5120_GPIO_COUNT; i++) + adm5120_gpio_map[i].flags = GPIO_FLAG_VALID; + if (adm5120_package_pqfp()) { - /* GPIO pins 4-7 are unavailable in ADM5120P */ - for (i = ADM5120_GPIO_PIN4; i <= ADM5120_GPIO_PIN7; i++) - adm5120_gpio_map[i].flags &= ~GPIO_FLAG_VALID; + adm5120_gpio_map[ADM5120_GPIO_PIN4].flags &= ~GPIO_FLAG_VALID; + adm5120_gpio_map[ADM5120_GPIO_PIN5].flags &= ~GPIO_FLAG_VALID; + adm5120_gpio_map[ADM5120_GPIO_PIN6].flags &= ~GPIO_FLAG_VALID; + adm5120_gpio_map[ADM5120_GPIO_PIN7].flags &= ~GPIO_FLAG_VALID; } - - return 0; } - -pure_initcall(adm5120_gpio_init); diff --git a/target/linux/adm5120/files/arch/mips/adm5120/irq.c b/target/linux/adm5120/files/arch/mips/adm5120/irq.c index 6e3fc62220..361dcb8628 100644 --- a/target/linux/adm5120/files/arch/mips/adm5120/irq.c +++ b/target/linux/adm5120/files/arch/mips/adm5120/irq.c @@ -76,7 +76,7 @@ static void adm5120_intc_irq_mask(unsigned int irq) static int adm5120_intc_irq_set_type(unsigned int irq, unsigned int flow_type) { /* TODO: not yet tested */ -#if 1 + unsigned int sense; unsigned long mode; int err = 0; @@ -114,13 +114,13 @@ static int adm5120_intc_irq_set_type(unsigned int irq, unsigned int flow_type) mode &= (1 << (irq-ADM5120_INTC_IRQ_BASE)); INTC_WRITE(INTC_REG_INT_MODE, mode); - /* fallthrogh */ + /* fallthrough */ default: irq_desc[irq].status &= ~IRQ_TYPE_SENSE_MASK; irq_desc[irq].status |= sense; break; } -#endif + return 0; } @@ -161,10 +161,13 @@ static void __init adm5120_intc_irq_init(int base) /* disable all interrupts */ INTC_WRITE(INTC_REG_IRQ_DISABLE, INTC_INT_ALL); + /* setup all interrupts to generate IRQ instead of FIQ */ INTC_WRITE(INTC_REG_INT_MODE, 0); + /* set active level for all external interrupts to HIGH */ INTC_WRITE(INTC_REG_INT_LEVEL, 0); + /* disable usage of the TEST_SOURCE register */ INTC_WRITE(INTC_REG_IRQ_SOURCE_SELECT, 0); diff --git a/target/linux/adm5120/files/include/asm-mips/mach-adm5120/adm5120_info.h b/target/linux/adm5120/files/include/asm-mips/mach-adm5120/adm5120_info.h index ac452ef30f..7d92a510bd 100644 --- a/target/linux/adm5120/files/include/asm-mips/mach-adm5120/adm5120_info.h +++ b/target/linux/adm5120/files/include/asm-mips/mach-adm5120/adm5120_info.h @@ -68,6 +68,11 @@ extern void adm5120_halt(void); extern void (*adm5120_board_reset)(void); +extern void adm5120_gpio_init(void) __init; +extern void adm5120_gpio_csx0_enable(void) __init; +extern void adm5120_gpio_csx1_enable(void) __init; +extern void adm5120_gpio_ew_enable(void) __init; + static inline int adm5120_package_pqfp(void) { return (adm5120_package == ADM5120_PACKAGE_PQFP); diff --git a/target/linux/adm5120/files/include/asm-mips/mach-adm5120/adm5120_switch.h b/target/linux/adm5120/files/include/asm-mips/mach-adm5120/adm5120_switch.h index a40175b03b..f96c7d50c7 100644 --- a/target/linux/adm5120/files/include/asm-mips/mach-adm5120/adm5120_switch.h +++ b/target/linux/adm5120/files/include/asm-mips/mach-adm5120/adm5120_switch.h @@ -247,6 +247,11 @@ #define GPIO_CONF0_OE_MASK (0xFF << GPIO_CONF0_OE_SHIFT) #define GPIO_CONF0_OV_MASK (0xFF << GPIO_CONF0_OV_SHIFT) +/* GPIO_CONF2 register bits */ +#define GPIO_CONF2_CSX0 BIT(4) /* enable CSX0:INTX0 on GPIO 1:2 */ +#define GPIO_CONF2_CSX1 BIT(5) /* enable CSX1:INTX1 on GPIO 3:4 */ +#define GPIO_CONF2_EW BIT(6) /* enable wait state pin for CSX0/1 */ + /* INT_STATUS/INT_MASK register bits */ #define SWITCH_INT_SHD BIT(0) /* Send High Done */ #define SWITCH_INT_SLD BIT(1) /* Send Low Done */ -- 2.30.2