[OpenWrt-Devel] [PATCH v3 4/7] ar71xx: add support to use gpio irqs
John Crispin
blogic at openwrt.org
Thu Jul 9 02:34:16 EDT 2015
Hi,
minor nitpick inline
On 07/07/2015 14:58, Günther Kelleter wrote:
> Signed-off-by: Günther Kelleter <guenther.kelleter at devolo.de>
> ---
> .../739-MIPS-ath79-add-gpio-irq-support.patch | 225 +++++++++++++++++++++
> 1 file changed, 225 insertions(+)
> create mode 100644 target/linux/ar71xx/patches-3.18/739-MIPS-ath79-add-gpio-irq-support.patch
>
> diff --git a/target/linux/ar71xx/patches-3.18/739-MIPS-ath79-add-gpio-irq-support.patch b/target/linux/ar71xx/patches-3.18/739-MIPS-ath79-add-gpio-irq-support.patch
> new file mode 100644
> index 0000000..2b90df0
> --- /dev/null
> +++ b/target/linux/ar71xx/patches-3.18/739-MIPS-ath79-add-gpio-irq-support.patch
> @@ -0,0 +1,225 @@
> +--- a/arch/mips/ath79/gpio.c
> ++++ b/arch/mips/ath79/gpio.c
> +@@ -20,9 +20,14 @@
> + #include <linux/io.h>
> + #include <linux/ioport.h>
> + #include <linux/gpio.h>
> ++#include <linux/irq.h>
> ++#include <linux/interrupt.h>
> ++
> ++#include <linux/of.h>
> +
> + #include <asm/mach-ath79/ar71xx_regs.h>
> + #include <asm/mach-ath79/ath79.h>
> ++#include <asm/mach-ath79/irq.h>
> + #include "common.h"
> +
> + void __iomem *ath79_gpio_base;
> +@@ -31,6 +36,13 @@ EXPORT_SYMBOL_GPL(ath79_gpio_base);
> + static unsigned long ath79_gpio_count;
> + static DEFINE_SPINLOCK(ath79_gpio_lock);
> +
> ++/*
> ++ * gpio_both_edge is a bitmask of which gpio pins need to have
> ++ * the detect priority flipped from the interrupt handler to
> ++ * emulate IRQ_TYPE_EDGE_BOTH.
> ++ */
> ++static unsigned long gpio_both_edge = 0;
> ++
> + static void __ath79_gpio_set_value(unsigned gpio, int value)
> + {
> + void __iomem *base = ath79_gpio_base;
> +@@ -209,6 +221,133 @@ void __init ath79_gpio_output_select(uns
> + spin_unlock_irqrestore(&ath79_gpio_lock, flags);
> + }
> +
> ++static int ath79_gpio_irq_type(struct irq_data *d, unsigned type)
> ++{
> ++ int offset = d->irq - ATH79_GPIO_IRQ_BASE;
> ++ void __iomem *base = ath79_gpio_base;
> ++ unsigned long flags;
> ++ unsigned long int_type;
> ++ unsigned long int_polarity;
> ++ unsigned long bit = (1 << offset);
> ++
> ++ spin_lock_irqsave(&ath79_gpio_lock, flags);
> ++
> ++ int_type = __raw_readl(base + AR71XX_GPIO_REG_INT_TYPE);
> ++ int_polarity = __raw_readl(base + AR71XX_GPIO_REG_INT_POLARITY);
> ++
> ++ gpio_both_edge &= ~bit;
> ++
> ++ switch (type) {
> ++ case IRQ_TYPE_EDGE_RISING:
> ++ int_type &= ~bit;
> ++ int_polarity |= bit;
> ++ break;
> ++
> ++ case IRQ_TYPE_EDGE_FALLING:
> ++ int_type &= ~bit;
> ++ int_polarity &= ~bit;
> ++ break;
> ++
> ++ case IRQ_TYPE_LEVEL_HIGH:
> ++ int_type |= bit;
> ++ int_polarity |= bit;
> ++ break;
> ++
> ++ case IRQ_TYPE_LEVEL_LOW:
> ++ int_type |= bit;
> ++ int_polarity &= ~bit;
> ++ break;
> ++
> ++ case IRQ_TYPE_EDGE_BOTH:
> ++ int_type |= bit;
> ++ /* set polarity based on current value */
> ++ if (gpio_get_value(offset)) {
> ++ int_polarity &= ~bit;
> ++ } else {
> ++ int_polarity |= bit;
> ++ }
> ++ /* flip this gpio in the interrupt handler */
> ++ gpio_both_edge |= bit;
> ++ break;
> ++
> ++ default:
> ++ spin_unlock_irqrestore(&ath79_gpio_lock, flags);
> ++ return -EINVAL;
> ++ }
> ++
> ++ __raw_writel(int_type, base + AR71XX_GPIO_REG_INT_TYPE);
> ++ __raw_writel(int_polarity, base + AR71XX_GPIO_REG_INT_POLARITY);
> ++
> ++ __raw_writel(__raw_readl(base + AR71XX_GPIO_REG_INT_MODE) | (1 << offset),
> ++ base + AR71XX_GPIO_REG_INT_MODE);
> ++
> ++ __raw_writel(__raw_readl(base + AR71XX_GPIO_REG_INT_ENABLE) & ~(1 << offset),
> ++ base + AR71XX_GPIO_REG_INT_ENABLE);
> ++
> ++ spin_unlock_irqrestore(&ath79_gpio_lock, flags);
> ++ return 0;
> ++}
> ++
> ++static void ath79_gpio_irq_enable(struct irq_data *d)
> ++{
> ++ int offset = d->irq - ATH79_GPIO_IRQ_BASE;
> ++ void __iomem *base = ath79_gpio_base;
> ++
> ++ __raw_writel(__raw_readl(base + AR71XX_GPIO_REG_INT_ENABLE) | (1 << offset),
> ++ base + AR71XX_GPIO_REG_INT_ENABLE);
> ++}
> ++
> ++static void ath79_gpio_irq_disable(struct irq_data *d)
> ++{
> ++ int offset = d->irq - ATH79_GPIO_IRQ_BASE;
> ++ void __iomem *base = ath79_gpio_base;
> ++
> ++ __raw_writel(__raw_readl(base + AR71XX_GPIO_REG_INT_ENABLE) & ~(1 << offset),
> ++ base + AR71XX_GPIO_REG_INT_ENABLE);
> ++}
> ++
> ++static struct irq_chip ath79_gpio_irqchip = {
> ++ .name = "GPIO",
> ++ .irq_enable = ath79_gpio_irq_enable,
> ++ .irq_disable = ath79_gpio_irq_disable,
> ++ .irq_set_type = ath79_gpio_irq_type,
> ++};
> ++
> ++static irqreturn_t ath79_gpio_irq(int irq, void *dev)
> ++{
> ++ void __iomem *base = ath79_gpio_base;
> ++ unsigned int stat = __raw_readl(base + AR71XX_GPIO_REG_INT_PENDING);
> ++
> ++ while (stat) {
make use of the for_each_set_bit() macro please
John
> ++ int bit_num = __ffs(stat);
> ++ unsigned long bit = (1<<bit_num);
> ++
> ++ if (bit & gpio_both_edge) {
> ++ __raw_writel(__raw_readl(base + AR71XX_GPIO_REG_INT_POLARITY) ^ bit,
> ++ base + AR71XX_GPIO_REG_INT_POLARITY);
> ++ }
> ++
> ++ generic_handle_irq(ATH79_GPIO_IRQ(bit_num));
> ++ stat &= ~bit;
> ++ }
> ++
> ++ return IRQ_HANDLED;
> ++}
> ++
> ++static int __init ath79_gpio_irq_init(struct gpio_chip *chip)
> ++{
> ++ int irq;
> ++ int irq_base = ATH79_GPIO_IRQ_BASE;
> ++
> ++ for (irq = irq_base; irq < irq_base + chip->ngpio; irq++) {
> ++ irq_set_chip_data(irq, chip);
> ++ irq_set_chip_and_handler(irq, &ath79_gpio_irqchip, handle_simple_irq);
> ++ irq_set_noprobe(irq);
> ++ }
> ++
> ++ return 0;
> ++}
> ++
> + void __init ath79_gpio_init(void)
> + {
> + int err;
> +@@ -245,6 +384,10 @@ void __init ath79_gpio_init(void)
> + err = gpiochip_add(&ath79_gpio_chip);
> + if (err)
> + panic("cannot add AR71xx GPIO chip, error=%d", err);
> ++
> ++ ath79_gpio_irq_init(&ath79_gpio_chip);
> ++
> ++ request_irq(ATH79_MISC_IRQ(2), ath79_gpio_irq, 0, "ath79-gpio", NULL);
> + }
> +
> + int gpio_get_value(unsigned gpio)
> +@@ -267,14 +410,22 @@ EXPORT_SYMBOL(gpio_set_value);
> +
> + int gpio_to_irq(unsigned gpio)
> + {
> +- /* FIXME */
> +- return -EINVAL;
> ++ if (gpio > ath79_gpio_count) {
> ++ return -EINVAL;
> ++ }
> ++
> ++ return ATH79_GPIO_IRQ_BASE + gpio;
> + }
> + EXPORT_SYMBOL(gpio_to_irq);
> +
> + int irq_to_gpio(unsigned irq)
> + {
> +- /* FIXME */
> +- return -EINVAL;
> ++ unsigned gpio = irq - ATH79_GPIO_IRQ_BASE;
> ++
> ++ if (gpio > ath79_gpio_count) {
> ++ return -EINVAL;
> ++ }
> ++
> ++ return gpio;
> + }
> + EXPORT_SYMBOL(irq_to_gpio);
> +--- a/arch/mips/include/asm/mach-ath79/irq.h
> ++++ b/arch/mips/include/asm/mach-ath79/irq.h
> +@@ -10,7 +10,7 @@
> + #define __ASM_MACH_ATH79_IRQ_H
> +
> + #define MIPS_CPU_IRQ_BASE 0
> +-#define NR_IRQS 51
> ++#define NR_IRQS 83
> +
> + #define ATH79_CPU_IRQ(_x) (MIPS_CPU_IRQ_BASE + (_x))
> +
> +@@ -30,6 +30,10 @@
> + #define ATH79_IP3_IRQ_COUNT 3
> + #define ATH79_IP3_IRQ(_x) (ATH79_IP3_IRQ_BASE + (_x))
> +
> ++#define ATH79_GPIO_IRQ_BASE (ATH79_IP3_IRQ_BASE + ATH79_IP3_IRQ_COUNT)
> ++#define ATH79_GPIO_IRQ_COUNT 32
> ++#define ATH79_GPIO_IRQ(_x) (ATH79_GPIO_IRQ_BASE + (_x))
> ++
> + #include_next <irq.h>
> +
> + #endif /* __ASM_MACH_ATH79_IRQ_H */
>
_______________________________________________
openwrt-devel mailing list
openwrt-devel at lists.openwrt.org
https://lists.openwrt.org/cgi-bin/mailman/listinfo/openwrt-devel
More information about the openwrt-devel
mailing list