diff options
Diffstat (limited to 'recipes/linux/linux-2.6.18/avr32-arch-neutral-gpio-api.patch')
-rw-r--r-- | recipes/linux/linux-2.6.18/avr32-arch-neutral-gpio-api.patch | 598 |
1 files changed, 598 insertions, 0 deletions
diff --git a/recipes/linux/linux-2.6.18/avr32-arch-neutral-gpio-api.patch b/recipes/linux/linux-2.6.18/avr32-arch-neutral-gpio-api.patch new file mode 100644 index 0000000000..049d5e3a94 --- /dev/null +++ b/recipes/linux/linux-2.6.18/avr32-arch-neutral-gpio-api.patch @@ -0,0 +1,598 @@ +From 05ac6cbfecf9e9b0ab46ba5f30eec8ea91b2987c Mon Sep 17 00:00:00 2001 +From: Haavard Skinnemoen <hskinnemoen@atmel.com> +Date: Mon, 13 Nov 2006 10:23:15 +0100 +Subject: [AVR32] Implement arch-neutral GPIO API + +AVR32 implementation of the arch-neutral GPIO API described by +Documentation/gpio.txt. + +This also contains a few related changes to the irq handling and +pin configuration code, to make this actually usable. + +Signed-off-by: Haavard Skinnemoen <hskinnemoen@atmel.com> +--- + arch/avr32/mach-at32ap/at32ap7000.c | 144 ++++++++++------------ + arch/avr32/mach-at32ap/pio.c | 186 +++++++++++++++++++++++++++-- + include/asm-avr32/arch-at32ap/at32ap7000.h | 26 ++++ + include/asm-avr32/arch-at32ap/gpio.h | 39 ++++++ + include/asm-avr32/arch-at32ap/irq.h | 11 + + include/asm-avr32/arch-at32ap/portmux.h | 16 -- + include/asm-avr32/gpio.h | 6 + include/asm-avr32/irq.h | 8 - + 8 files changed, 333 insertions(+), 103 deletions(-) + +Index: linux-2.6.18-avr32/arch/avr32/mach-at32ap/at32ap7000.c +=================================================================== +--- linux-2.6.18-avr32.orig/arch/avr32/mach-at32ap/at32ap7000.c 2006-11-29 16:21:12.000000000 +0100 ++++ linux-2.6.18-avr32/arch/avr32/mach-at32ap/at32ap7000.c 2006-11-29 16:22:14.000000000 +0100 +@@ -11,8 +11,9 @@ + + #include <asm/io.h> + ++#include <asm/arch/at32ap7000.h> + #include <asm/arch/board.h> +-#include <asm/arch/portmux.h> ++#include <asm/arch/gpio.h> + #include <asm/arch/sm.h> + + #include "clock.h" +@@ -67,17 +68,8 @@ static struct clk devname##_##_name = { + .index = _index, \ + } + +-enum { +- PIOA, +- PIOB, +- PIOC, +- PIOD, +-}; +- +-enum { +- FUNC_A, +- FUNC_B, +-}; ++#define select_peripheral(pin, periph, pullup) \ ++ at32_select_periph(GPIO_PIN_##pin, GPIO_##periph, pullup) + + unsigned long at32ap7000_osc_rates[3] = { + [0] = 32768, +@@ -553,26 +545,26 @@ DEV_CLK(usart, usart3, pba, 6); + + static inline void configure_usart0_pins(void) + { +- portmux_set_func(PIOA, 8, FUNC_B); /* RXD */ +- portmux_set_func(PIOA, 9, FUNC_B); /* TXD */ ++ select_peripheral(PA(8), PERIPH_B, 0); /* RXD */ ++ select_peripheral(PA(9), PERIPH_B, 0); /* TXD */ + } + + static inline void configure_usart1_pins(void) + { +- portmux_set_func(PIOA, 17, FUNC_A); /* RXD */ +- portmux_set_func(PIOA, 18, FUNC_A); /* TXD */ ++ select_peripheral(PA(17), PERIPH_A, 0); /* RXD */ ++ select_peripheral(PA(18), PERIPH_A, 0); /* TXD */ + } + + static inline void configure_usart2_pins(void) + { +- portmux_set_func(PIOB, 26, FUNC_B); /* RXD */ +- portmux_set_func(PIOB, 27, FUNC_B); /* TXD */ ++ select_peripheral(PB(26), PERIPH_B, 0); /* RXD */ ++ select_peripheral(PB(27), PERIPH_B, 0); /* TXD */ + } + + static inline void configure_usart3_pins(void) + { +- portmux_set_func(PIOB, 18, FUNC_B); /* RXD */ +- portmux_set_func(PIOB, 17, FUNC_B); /* TXD */ ++ select_peripheral(PB(18), PERIPH_B, 0); /* RXD */ ++ select_peripheral(PB(17), PERIPH_B, 0); /* TXD */ + } + + static struct platform_device *setup_usart(unsigned int id) +@@ -644,27 +636,27 @@ at32_add_device_eth(unsigned int id, str + case 0: + pdev = &macb0_device; + +- portmux_set_func(PIOC, 3, FUNC_A); /* TXD0 */ +- portmux_set_func(PIOC, 4, FUNC_A); /* TXD1 */ +- portmux_set_func(PIOC, 7, FUNC_A); /* TXEN */ +- portmux_set_func(PIOC, 8, FUNC_A); /* TXCK */ +- portmux_set_func(PIOC, 9, FUNC_A); /* RXD0 */ +- portmux_set_func(PIOC, 10, FUNC_A); /* RXD1 */ +- portmux_set_func(PIOC, 13, FUNC_A); /* RXER */ +- portmux_set_func(PIOC, 15, FUNC_A); /* RXDV */ +- portmux_set_func(PIOC, 16, FUNC_A); /* MDC */ +- portmux_set_func(PIOC, 17, FUNC_A); /* MDIO */ ++ select_peripheral(PC(3), PERIPH_A, 0); /* TXD0 */ ++ select_peripheral(PC(4), PERIPH_A, 0); /* TXD1 */ ++ select_peripheral(PC(7), PERIPH_A, 0); /* TXEN */ ++ select_peripheral(PC(8), PERIPH_A, 0); /* TXCK */ ++ select_peripheral(PC(9), PERIPH_A, 0); /* RXD0 */ ++ select_peripheral(PC(10), PERIPH_A, 0); /* RXD1 */ ++ select_peripheral(PC(13), PERIPH_A, 0); /* RXER */ ++ select_peripheral(PC(15), PERIPH_A, 0); /* RXDV */ ++ select_peripheral(PC(16), PERIPH_A, 0); /* MDC */ ++ select_peripheral(PC(17), PERIPH_A, 0); /* MDIO */ + + if (!data->is_rmii) { +- portmux_set_func(PIOC, 0, FUNC_A); /* COL */ +- portmux_set_func(PIOC, 1, FUNC_A); /* CRS */ +- portmux_set_func(PIOC, 2, FUNC_A); /* TXER */ +- portmux_set_func(PIOC, 5, FUNC_A); /* TXD2 */ +- portmux_set_func(PIOC, 6, FUNC_A); /* TXD3 */ +- portmux_set_func(PIOC, 11, FUNC_A); /* RXD2 */ +- portmux_set_func(PIOC, 12, FUNC_A); /* RXD3 */ +- portmux_set_func(PIOC, 14, FUNC_A); /* RXCK */ +- portmux_set_func(PIOC, 18, FUNC_A); /* SPD */ ++ select_peripheral(PC(0), PERIPH_A, 0); /* COL */ ++ select_peripheral(PC(1), PERIPH_A, 0); /* CRS */ ++ select_peripheral(PC(2), PERIPH_A, 0); /* TXER */ ++ select_peripheral(PC(5), PERIPH_A, 0); /* TXD2 */ ++ select_peripheral(PC(6), PERIPH_A, 0); /* TXD3 */ ++ select_peripheral(PC(11), PERIPH_A, 0); /* RXD2 */ ++ select_peripheral(PC(12), PERIPH_A, 0); /* RXD3 */ ++ select_peripheral(PC(14), PERIPH_A, 0); /* RXCK */ ++ select_peripheral(PC(18), PERIPH_A, 0); /* SPD */ + } + break; + +@@ -695,12 +687,12 @@ struct platform_device *__init at32_add_ + switch (id) { + case 0: + pdev = &spi0_device; +- portmux_set_func(PIOA, 0, FUNC_A); /* MISO */ +- portmux_set_func(PIOA, 1, FUNC_A); /* MOSI */ +- portmux_set_func(PIOA, 2, FUNC_A); /* SCK */ +- portmux_set_func(PIOA, 3, FUNC_A); /* NPCS0 */ +- portmux_set_func(PIOA, 4, FUNC_A); /* NPCS1 */ +- portmux_set_func(PIOA, 5, FUNC_A); /* NPCS2 */ ++ select_peripheral(PA(0), PERIPH_A, 0); /* MISO */ ++ select_peripheral(PA(1), PERIPH_A, 0); /* MOSI */ ++ select_peripheral(PA(2), PERIPH_A, 0); /* SCK */ ++ select_peripheral(PA(3), PERIPH_A, 0); /* NPCS0 */ ++ select_peripheral(PA(4), PERIPH_A, 0); /* NPCS1 */ ++ select_peripheral(PA(5), PERIPH_A, 0); /* NPCS2 */ + break; + + default: +@@ -743,37 +735,37 @@ at32_add_device_lcdc(unsigned int id, st + switch (id) { + case 0: + pdev = &lcdc0_device; +- portmux_set_func(PIOC, 19, FUNC_A); /* CC */ +- portmux_set_func(PIOC, 20, FUNC_A); /* HSYNC */ +- portmux_set_func(PIOC, 21, FUNC_A); /* PCLK */ +- portmux_set_func(PIOC, 22, FUNC_A); /* VSYNC */ +- portmux_set_func(PIOC, 23, FUNC_A); /* DVAL */ +- portmux_set_func(PIOC, 24, FUNC_A); /* MODE */ +- portmux_set_func(PIOC, 25, FUNC_A); /* PWR */ +- portmux_set_func(PIOC, 26, FUNC_A); /* DATA0 */ +- portmux_set_func(PIOC, 27, FUNC_A); /* DATA1 */ +- portmux_set_func(PIOC, 28, FUNC_A); /* DATA2 */ +- portmux_set_func(PIOC, 29, FUNC_A); /* DATA3 */ +- portmux_set_func(PIOC, 30, FUNC_A); /* DATA4 */ +- portmux_set_func(PIOC, 31, FUNC_A); /* DATA5 */ +- portmux_set_func(PIOD, 0, FUNC_A); /* DATA6 */ +- portmux_set_func(PIOD, 1, FUNC_A); /* DATA7 */ +- portmux_set_func(PIOD, 2, FUNC_A); /* DATA8 */ +- portmux_set_func(PIOD, 3, FUNC_A); /* DATA9 */ +- portmux_set_func(PIOD, 4, FUNC_A); /* DATA10 */ +- portmux_set_func(PIOD, 5, FUNC_A); /* DATA11 */ +- portmux_set_func(PIOD, 6, FUNC_A); /* DATA12 */ +- portmux_set_func(PIOD, 7, FUNC_A); /* DATA13 */ +- portmux_set_func(PIOD, 8, FUNC_A); /* DATA14 */ +- portmux_set_func(PIOD, 9, FUNC_A); /* DATA15 */ +- portmux_set_func(PIOD, 10, FUNC_A); /* DATA16 */ +- portmux_set_func(PIOD, 11, FUNC_A); /* DATA17 */ +- portmux_set_func(PIOD, 12, FUNC_A); /* DATA18 */ +- portmux_set_func(PIOD, 13, FUNC_A); /* DATA19 */ +- portmux_set_func(PIOD, 14, FUNC_A); /* DATA20 */ +- portmux_set_func(PIOD, 15, FUNC_A); /* DATA21 */ +- portmux_set_func(PIOD, 16, FUNC_A); /* DATA22 */ +- portmux_set_func(PIOD, 17, FUNC_A); /* DATA23 */ ++ select_peripheral(PC(19), PERIPH_A, 0); /* CC */ ++ select_peripheral(PC(20), PERIPH_A, 0); /* HSYNC */ ++ select_peripheral(PC(21), PERIPH_A, 0); /* PCLK */ ++ select_peripheral(PC(22), PERIPH_A, 0); /* VSYNC */ ++ select_peripheral(PC(23), PERIPH_A, 0); /* DVAL */ ++ select_peripheral(PC(24), PERIPH_A, 0); /* MODE */ ++ select_peripheral(PC(25), PERIPH_A, 0); /* PWR */ ++ select_peripheral(PC(26), PERIPH_A, 0); /* DATA0 */ ++ select_peripheral(PC(27), PERIPH_A, 0); /* DATA1 */ ++ select_peripheral(PC(28), PERIPH_A, 0); /* DATA2 */ ++ select_peripheral(PC(29), PERIPH_A, 0); /* DATA3 */ ++ select_peripheral(PC(30), PERIPH_A, 0); /* DATA4 */ ++ select_peripheral(PC(31), PERIPH_A, 0); /* DATA5 */ ++ select_peripheral(PD(0), PERIPH_A, 0); /* DATA6 */ ++ select_peripheral(PD(1), PERIPH_A, 0); /* DATA7 */ ++ select_peripheral(PD(2), PERIPH_A, 0); /* DATA8 */ ++ select_peripheral(PD(3), PERIPH_A, 0); /* DATA9 */ ++ select_peripheral(PD(4), PERIPH_A, 0); /* DATA10 */ ++ select_peripheral(PD(5), PERIPH_A, 0); /* DATA11 */ ++ select_peripheral(PD(6), PERIPH_A, 0); /* DATA12 */ ++ select_peripheral(PD(7), PERIPH_A, 0); /* DATA13 */ ++ select_peripheral(PD(8), PERIPH_A, 0); /* DATA14 */ ++ select_peripheral(PD(9), PERIPH_A, 0); /* DATA15 */ ++ select_peripheral(PD(10), PERIPH_A, 0); /* DATA16 */ ++ select_peripheral(PD(11), PERIPH_A, 0); /* DATA17 */ ++ select_peripheral(PD(12), PERIPH_A, 0); /* DATA18 */ ++ select_peripheral(PD(13), PERIPH_A, 0); /* DATA19 */ ++ select_peripheral(PD(14), PERIPH_A, 0); /* DATA20 */ ++ select_peripheral(PD(15), PERIPH_A, 0); /* DATA21 */ ++ select_peripheral(PD(16), PERIPH_A, 0); /* DATA22 */ ++ select_peripheral(PD(17), PERIPH_A, 0); /* DATA23 */ + + clk_set_parent(&lcdc0_pixclk, &pll0); + clk_set_rate(&lcdc0_pixclk, clk_get_rate(&pll0)); +Index: linux-2.6.18-avr32/arch/avr32/mach-at32ap/pio.c +=================================================================== +--- linux-2.6.18-avr32.orig/arch/avr32/mach-at32ap/pio.c 2006-11-29 16:21:12.000000000 +0100 ++++ linux-2.6.18-avr32/arch/avr32/mach-at32ap/pio.c 2006-11-29 16:22:14.000000000 +0100 +@@ -13,10 +13,9 @@ + #include <linux/fs.h> + #include <linux/platform_device.h> + ++#include <asm/gpio.h> + #include <asm/io.h> + +-#include <asm/arch/portmux.h> +- + #include "pio.h" + + #define MAX_NR_PIO_DEVICES 8 +@@ -25,28 +24,191 @@ struct pio_device { + void __iomem *regs; + const struct platform_device *pdev; + struct clk *clk; +- u32 alloc_mask; ++ u32 pinmux_mask; ++ u32 gpio_mask; + char name[32]; + }; + + static struct pio_device pio_dev[MAX_NR_PIO_DEVICES]; + +-void portmux_set_func(unsigned int portmux_id, unsigned int pin_id, +- unsigned int function_id) ++static struct pio_device *gpio_to_pio(unsigned int gpio) + { + struct pio_device *pio; +- u32 mask = 1 << pin_id; ++ unsigned int index; ++ ++ index = gpio >> 5; ++ if (index >= MAX_NR_PIO_DEVICES) ++ return NULL; ++ pio = &pio_dev[index]; ++ if (!pio->regs) ++ return NULL; ++ ++ return pio; ++} ++ ++/* Pin multiplexing API */ + +- BUG_ON(portmux_id >= MAX_NR_PIO_DEVICES); ++void __init at32_select_periph(unsigned int pin, unsigned int periph, ++ int use_pullup) ++{ ++ struct pio_device *pio; ++ unsigned int pin_index = pin & 0x1f; ++ u32 mask = 1 << pin_index; ++ ++ pio = gpio_to_pio(pin); ++ if (unlikely(!pio)) { ++ printk("pio: invalid pin %u\n", pin); ++ goto fail; ++ } + +- pio = &pio_dev[portmux_id]; ++ if (unlikely(test_and_set_bit(pin_index, &pio->pinmux_mask))) { ++ printk("%s: pin %u is busy\n", pio->name, pin_index); ++ goto fail; ++ } + +- if (function_id) ++ pio_writel(pio, PUER, mask); ++ if (periph) + pio_writel(pio, BSR, mask); + else + pio_writel(pio, ASR, mask); ++ + pio_writel(pio, PDR, mask); ++ if (!use_pullup) ++ pio_writel(pio, PUDR, mask); ++ ++ return; ++ ++fail: ++ dump_stack(); ++} ++ ++void __init at32_select_gpio(unsigned int pin, int enable_output, ++ int use_pullup) ++{ ++ struct pio_device *pio; ++ unsigned int pin_index = pin & 0x1f; ++ u32 mask = 1 << pin_index; ++ ++ pio = gpio_to_pio(pin); ++ if (unlikely(!pio)) { ++ printk("pio: invalid pin %u\n", pin); ++ goto fail; ++ } ++ ++ if (unlikely(test_and_set_bit(pin_index, &pio->pinmux_mask))) { ++ printk("%s: pin %u is busy\n", pio->name, pin_index); ++ goto fail; ++ } ++ ++ pio_writel(pio, PUER, mask); ++ if (enable_output) ++ pio_writel(pio, OER, mask); ++ else ++ pio_writel(pio, ODR, mask); ++ ++ pio_writel(pio, PER, mask); ++ if (!use_pullup) ++ pio_writel(pio, PUDR, mask); ++ ++ /* It's now allowed to use request_gpio on this pin */ ++ clear_bit(pin_index, &pio->gpio_mask); ++ ++ return; ++ ++fail: ++ dump_stack(); ++} ++ ++/* GPIO API */ ++ ++int gpio_request(unsigned int gpio, const char *label) ++{ ++ struct pio_device *pio; ++ unsigned int pin; ++ ++ pio = gpio_to_pio(gpio); ++ if (!pio) ++ return -ENODEV; ++ ++ pin = gpio & 0x1f; ++ if (test_and_set_bit(pin, &pio->gpio_mask)) ++ return -EBUSY; ++ ++ return 0; + } ++EXPORT_SYMBOL(gpio_request); ++ ++void gpio_free(unsigned int gpio) ++{ ++ struct pio_device *pio; ++ unsigned int pin; ++ ++ pio = gpio_to_pio(gpio); ++ if (!pio) { ++ printk(KERN_ERR ++ "gpio: attempted to free invalid pin %u\n", gpio); ++ return; ++ } ++ ++ pin = gpio & 0x1f; ++ if (!test_and_clear_bit(pin, &pio->gpio_mask)) ++ printk(KERN_ERR "gpio: freeing already-free pin %s[%u]\n", ++ pio->name, pin); ++} ++EXPORT_SYMBOL(gpio_free); ++ ++int gpio_direction_input(unsigned int gpio) ++{ ++ struct pio_device *pio; ++ unsigned int pin; ++ ++ pio = gpio_to_pio(gpio); ++ if (!pio) ++ return -ENODEV; ++ ++ pin = gpio & 0x1f; ++ pio_writel(pio, ODR, 1 << pin); ++ ++ return 0; ++} ++EXPORT_SYMBOL(gpio_direction_input); ++ ++int gpio_direction_output(unsigned int gpio) ++{ ++ struct pio_device *pio; ++ unsigned int pin; ++ ++ pio = gpio_to_pio(gpio); ++ if (!pio) ++ return -ENODEV; ++ ++ pin = gpio & 0x1f; ++ pio_writel(pio, OER, 1 << pin); ++ ++ return 0; ++} ++EXPORT_SYMBOL(gpio_direction_output); ++ ++int gpio_get_value(unsigned int gpio) ++{ ++ struct pio_device *pio = &pio_dev[gpio >> 5]; ++ ++ return (pio_readl(pio, PDSR) >> (gpio & 0x1f)) & 1; ++} ++EXPORT_SYMBOL(gpio_get_value); ++ ++void gpio_set_value(unsigned int gpio, int value) ++{ ++ struct pio_device *pio = &pio_dev[gpio >> 5]; ++ u32 mask; ++ ++ mask = 1 << (gpio & 0x1f); ++ if (value) ++ pio_writel(pio, SODR, mask); ++ else ++ pio_writel(pio, CODR, mask); ++} ++EXPORT_SYMBOL(gpio_set_value); + + static int __init pio_probe(struct platform_device *pdev) + { +@@ -113,6 +275,12 @@ void __init at32_init_pio(struct platfor + pio->pdev = pdev; + pio->regs = ioremap(regs->start, regs->end - regs->start + 1); + ++ /* ++ * request_gpio() is only valid for pins that have been ++ * configured as GPIO. ++ */ ++ pio->gpio_mask = ~0UL; ++ + pio_writel(pio, ODR, ~0UL); + pio_writel(pio, PER, ~0UL); + } +Index: linux-2.6.18-avr32/include/asm-avr32/arch-at32ap/at32ap7000.h +=================================================================== +--- /dev/null 1970-01-01 00:00:00.000000000 +0000 ++++ linux-2.6.18-avr32/include/asm-avr32/arch-at32ap/at32ap7000.h 2006-11-29 16:22:14.000000000 +0100 +@@ -0,0 +1,26 @@ ++#ifndef __ASM_ARCH_AT32AP7000_H ++#define __ASM_ARCH_AT32AP7000_H ++ ++#define GPIO_PERIPH_A 0 ++#define GPIO_PERIPH_B 1 ++ ++#define NR_GPIO_CONTROLLERS 4 ++ ++/* ++ * Pin numbers identifying specific GPIO pins on the chip. They can ++ * also be converted to IRQ numbers by passing them through ++ * gpio_to_irq(). ++ */ ++#define GPIO_PIOA_BASE (0) ++#define GPIO_PIOB_BASE (GPIO_PIOA_BASE + 32) ++#define GPIO_PIOC_BASE (GPIO_PIOB_BASE + 32) ++#define GPIO_PIOD_BASE (GPIO_PIOC_BASE + 32) ++#define GPIO_PIOE_BASE (GPIO_PIOD_BASE + 32) ++ ++#define GPIO_PIN_PA(N) (GPIO_PIOA_BASE + (N)) ++#define GPIO_PIN_PB(N) (GPIO_PIOB_BASE + (N)) ++#define GPIO_PIN_PC(N) (GPIO_PIOC_BASE + (N)) ++#define GPIO_PIN_PD(N) (GPIO_PIOD_BASE + (N)) ++#define GPIO_PIN_PE(N) (GPIO_PIOE_BASE + (N)) ++ ++#endif /* __ASM_ARCH_AT32AP7000_H */ +Index: linux-2.6.18-avr32/include/asm-avr32/arch-at32ap/gpio.h +=================================================================== +--- /dev/null 1970-01-01 00:00:00.000000000 +0000 ++++ linux-2.6.18-avr32/include/asm-avr32/arch-at32ap/gpio.h 2006-11-29 16:22:14.000000000 +0100 +@@ -0,0 +1,39 @@ ++#ifndef __ASM_AVR32_GPIO_H ++#define __ASM_AVR32_GPIO_H ++ ++#include <linux/compiler.h> ++#include <asm/irq.h> ++ ++/* ++ * Set up pin multiplexing, called from board init only. ++ * ++ * The following flags determine the initial state of the pin. ++ */ ++#define AT32_GPIOF_PULLUP 0x00000001 /* Enable pull-up */ ++#define AT32_GPIOF_OUTPUT 0x00000002 /* Enable output driver */ ++#define AT32_GPIOF_HIGH 0x00000004 /* Set output high */ ++ ++void at32_select_periph(unsigned int pin, unsigned int periph, ++ unsigned long flags); ++void at32_select_gpio(unsigned int pin, unsigned long flags); ++ ++/* Arch-neutral GPIO API */ ++int __must_check gpio_request(unsigned int gpio, const char *label); ++void gpio_free(unsigned int gpio); ++ ++int gpio_direction_input(unsigned int gpio); ++int gpio_direction_output(unsigned int gpio); ++int gpio_get_value(unsigned int gpio); ++void gpio_set_value(unsigned int gpio, int value); ++ ++static inline int gpio_to_irq(unsigned int gpio) ++{ ++ return gpio + GPIO_IRQ_BASE; ++} ++ ++static inline int irq_to_gpio(unsigned int irq) ++{ ++ return irq - GPIO_IRQ_BASE; ++} ++ ++#endif /* __ASM_AVR32_GPIO_H */ +Index: linux-2.6.18-avr32/include/asm-avr32/arch-at32ap/irq.h +=================================================================== +--- /dev/null 1970-01-01 00:00:00.000000000 +0000 ++++ linux-2.6.18-avr32/include/asm-avr32/arch-at32ap/irq.h 2006-11-29 16:22:14.000000000 +0100 +@@ -0,0 +1,11 @@ ++#ifndef __ASM_AVR32_ARCH_IRQ_H ++#define __ASM_AVR32_ARCH_IRQ_H ++ ++#define EIM_IRQ_BASE NR_INTERNAL_IRQS ++#define NR_EIM_IRQS 32 ++#define GPIO_IRQ_BASE (EIM_IRQ_BASE + NR_EIM_IRQS) ++#define NR_GPIO_IRQS (4 * 32) ++ ++#define NR_IRQS (GPIO_IRQ_BASE + NR_GPIO_IRQS) ++ ++#endif /* __ASM_AVR32_ARCH_IRQ_H */ +Index: linux-2.6.18-avr32/include/asm-avr32/arch-at32ap/portmux.h +=================================================================== +--- linux-2.6.18-avr32.orig/include/asm-avr32/arch-at32ap/portmux.h 2006-11-29 16:21:12.000000000 +0100 ++++ /dev/null 1970-01-01 00:00:00.000000000 +0000 +@@ -1,16 +0,0 @@ +-/* +- * AT32 portmux interface. +- * +- * Copyright (C) 2006 Atmel Corporation +- * +- * This program is free software; you can redistribute it and/or modify +- * it under the terms of the GNU General Public License version 2 as +- * published by the Free Software Foundation. +- */ +-#ifndef __ASM_AVR32_AT32_PORTMUX_H__ +-#define __ASM_AVR32_AT32_PORTMUX_H__ +- +-void portmux_set_func(unsigned int portmux_id, unsigned int pin_id, +- unsigned int function_id); +- +-#endif /* __ASM_AVR32_AT32_PORTMUX_H__ */ +Index: linux-2.6.18-avr32/include/asm-avr32/gpio.h +=================================================================== +--- /dev/null 1970-01-01 00:00:00.000000000 +0000 ++++ linux-2.6.18-avr32/include/asm-avr32/gpio.h 2006-11-29 16:22:14.000000000 +0100 +@@ -0,0 +1,6 @@ ++#ifndef __ASM_AVR32_GPIO_H ++#define __ASM_AVR32_GPIO_H ++ ++#include <asm/arch/gpio.h> ++ ++#endif /* __ASM_AVR32_GPIO_H */ +Index: linux-2.6.18-avr32/include/asm-avr32/irq.h +=================================================================== +--- linux-2.6.18-avr32.orig/include/asm-avr32/irq.h 2006-11-29 16:21:12.000000000 +0100 ++++ linux-2.6.18-avr32/include/asm-avr32/irq.h 2006-11-29 16:22:14.000000000 +0100 +@@ -2,8 +2,12 @@ + #define __ASM_AVR32_IRQ_H + + #define NR_INTERNAL_IRQS 64 +-#define NR_EXTERNAL_IRQS 64 +-#define NR_IRQS (NR_INTERNAL_IRQS + NR_EXTERNAL_IRQS) ++ ++#include <asm/arch/irq.h> ++ ++#ifndef NR_IRQS ++#define NR_IRQS (NR_INTERNAL_IRQS) ++#endif + + #define irq_canonicalize(i) (i) + |