[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