* [PATCH v6 2/4] drivers: irqchip: Add STM32 external interrupts support
@ 2016-09-20 16:00 ` Alexandre TORGUE
0 siblings, 0 replies; 30+ messages in thread
From: Alexandre TORGUE @ 2016-09-20 16:00 UTC (permalink / raw)
To: Maxime Coquelin, Thomas Gleixner, Jason Cooper, Marc Zyngier,
Linus Walleij, Mark Rutland, Rob Herring, linux-gpio, arnd
Cc: linux-arm-kernel, linux-kernel, devicetree, Daniel Thompson,
bruherrera, lee.jones
The STM32 external interrupt controller consists of edge detectors that
generate interrupts requests or wake-up events.
Each line can be independently configured as interrupt or wake-up source,
and triggers either on rising, falling or both edges. Each line can also
be masked independently.
Signed-off-by: Maxime Coquelin <mcoquelin.stm32@gmail.com>
Signed-off-by: Alexandre TORGUE <alexandre.torgue@st.com>
diff --git a/drivers/irqchip/Kconfig b/drivers/irqchip/Kconfig
index 7f87289..bc62d1f 100644
--- a/drivers/irqchip/Kconfig
+++ b/drivers/irqchip/Kconfig
@@ -264,3 +264,7 @@ config EZNPS_GIC
select IRQ_DOMAIN
help
Support the EZchip NPS400 global interrupt controller
+
+config STM32_EXTI
+ bool
+ select IRQ_DOMAIN
diff --git a/drivers/irqchip/Makefile b/drivers/irqchip/Makefile
index 4c203b6..96383b2 100644
--- a/drivers/irqchip/Makefile
+++ b/drivers/irqchip/Makefile
@@ -71,3 +71,4 @@ obj-$(CONFIG_MVEBU_ODMI) += irq-mvebu-odmi.o
obj-$(CONFIG_LS_SCFG_MSI) += irq-ls-scfg-msi.o
obj-$(CONFIG_EZNPS_GIC) += irq-eznps.o
obj-$(CONFIG_ARCH_ASPEED) += irq-aspeed-vic.o
+obj-$(CONFIG_STM32_EXTI) += irq-stm32-exti.o
diff --git a/drivers/irqchip/irq-stm32-exti.c b/drivers/irqchip/irq-stm32-exti.c
new file mode 100644
index 0000000..491568c
--- /dev/null
+++ b/drivers/irqchip/irq-stm32-exti.c
@@ -0,0 +1,201 @@
+/*
+ * Copyright (C) Maxime Coquelin 2015
+ * Author: Maxime Coquelin <mcoquelin.stm32@gmail.com>
+ * License terms: GNU General Public License (GPL), version 2
+ */
+
+#include <linux/bitops.h>
+#include <linux/interrupt.h>
+#include <linux/io.h>
+#include <linux/irq.h>
+#include <linux/irqchip.h>
+#include <linux/irqchip/chained_irq.h>
+#include <linux/irqdomain.h>
+#include <linux/of_address.h>
+#include <linux/of_irq.h>
+
+#define EXTI_IMR 0x0
+#define EXTI_EMR 0x4
+#define EXTI_RTSR 0x8
+#define EXTI_FTSR 0xc
+#define EXTI_SWIER 0x10
+#define EXTI_PR 0x14
+
+static void stm32_irq_handler(struct irq_desc *desc)
+{
+ struct irq_domain *domain = irq_desc_get_handler_data(desc);
+ struct irq_chip_generic *gc = domain->gc->gc[0];
+ struct irq_chip *chip = irq_desc_get_chip(desc);
+ unsigned long pending;
+ int n;
+
+ chained_irq_enter(chip, desc);
+
+ while ((pending = irq_reg_readl(gc, EXTI_PR))) {
+ for_each_set_bit(n, &pending, BITS_PER_LONG) {
+ generic_handle_irq(irq_find_mapping(domain, n));
+ irq_reg_writel(gc, BIT(n), EXTI_PR);
+ }
+ }
+
+ chained_irq_exit(chip, desc);
+}
+
+static int stm32_irq_set_type(struct irq_data *data, unsigned int type)
+{
+ struct irq_chip_generic *gc = irq_data_get_irq_chip_data(data);
+ int pin = data->hwirq;
+ u32 rtsr, ftsr;
+
+ irq_gc_lock(gc);
+
+ rtsr = irq_reg_readl(gc, EXTI_RTSR);
+ ftsr = irq_reg_readl(gc, EXTI_FTSR);
+
+ switch (type) {
+ case IRQ_TYPE_EDGE_RISING:
+ rtsr |= BIT(pin);
+ ftsr &= ~BIT(pin);
+ break;
+ case IRQ_TYPE_EDGE_FALLING:
+ rtsr &= ~BIT(pin);
+ ftsr |= BIT(pin);
+ break;
+ case IRQ_TYPE_EDGE_BOTH:
+ rtsr |= BIT(pin);
+ ftsr |= BIT(pin);
+ break;
+ default:
+ irq_gc_unlock(gc);
+ return -EINVAL;
+ }
+
+ irq_reg_writel(gc, rtsr, EXTI_RTSR);
+ irq_reg_writel(gc, ftsr, EXTI_FTSR);
+
+ irq_gc_unlock(gc);
+
+ return 0;
+}
+
+static int stm32_irq_set_wake(struct irq_data *data, unsigned int on)
+{
+ struct irq_chip_generic *gc = irq_data_get_irq_chip_data(data);
+ int pin = data->hwirq;
+ u32 emr;
+
+ irq_gc_lock(gc);
+
+ emr = irq_reg_readl(gc, EXTI_EMR);
+ if (on)
+ emr |= BIT(pin);
+ else
+ emr &= ~BIT(pin);
+ irq_reg_writel(gc, emr, EXTI_EMR);
+
+ irq_gc_unlock(gc);
+
+ return 0;
+}
+
+static int stm32_exti_alloc(struct irq_domain *d, unsigned int virq,
+ unsigned int nr_irqs, void *data)
+{
+ struct irq_chip_generic *gc = d->gc->gc[0];
+ struct irq_fwspec *fwspec = data;
+ irq_hw_number_t hwirq;
+
+ hwirq = fwspec->param[0];
+
+ irq_map_generic_chip(d, virq, hwirq);
+ irq_domain_set_info(d, virq, hwirq, &gc->chip_types->chip, gc,
+ handle_simple_irq, NULL, NULL);
+
+ return 0;
+}
+
+static void stm32_exti_free(struct irq_domain *d, unsigned int virq,
+ unsigned int nr_irqs)
+{
+ struct irq_data *data = irq_domain_get_irq_data(d, virq);
+
+ irq_domain_reset_irq_data(data);
+}
+
+struct irq_domain_ops irq_exti_domain_ops = {
+ .map = irq_map_generic_chip,
+ .xlate = irq_domain_xlate_onetwocell,
+ .alloc = stm32_exti_alloc,
+ .free = stm32_exti_free,
+};
+
+static int __init stm32_exti_init(struct device_node *node,
+ struct device_node *parent)
+{
+ unsigned int clr = IRQ_NOREQUEST | IRQ_NOPROBE | IRQ_NOAUTOEN;
+ int nr_irqs, nr_exti, ret, i;
+ struct irq_chip_generic *gc;
+ struct irq_domain *domain;
+ void *base;
+
+ base = of_iomap(node, 0);
+ if (!base) {
+ pr_err("%s: Unable to map registers\n", node->full_name);
+ return -ENOMEM;
+ }
+
+ /* Determine number of irqs supported */
+ writel_relaxed(~0UL, base + EXTI_RTSR);
+ nr_exti = fls(readl_relaxed(base + EXTI_RTSR));
+ writel_relaxed(0, base + EXTI_RTSR);
+
+ pr_info("%s: %d External IRQs detected\n", node->full_name, nr_exti);
+
+ domain = irq_domain_add_linear(node, nr_exti,
+ &irq_exti_domain_ops, NULL);
+ if (!domain) {
+ pr_err("%s: Could not register interrupt domain.\n",
+ node->name);
+ ret = -ENOMEM;
+ goto out_unmap;
+ }
+
+ ret = irq_alloc_domain_generic_chips(domain, nr_exti, 1, "exti",
+ handle_edge_irq, clr, 0, 0);
+ if (ret) {
+ pr_err("%s: Could not allocate generic interrupt chip.\n",
+ node->full_name);
+ goto out_free_domain;
+ }
+
+ gc = domain->gc->gc[0];
+ gc->reg_base = base;
+ gc->chip_types->type = IRQ_TYPE_EDGE_BOTH;
+ gc->chip_types->chip.name = gc->chip_types[0].chip.name;
+ gc->chip_types->chip.irq_ack = irq_gc_ack_set_bit;
+ gc->chip_types->chip.irq_mask = irq_gc_mask_clr_bit;
+ gc->chip_types->chip.irq_unmask = irq_gc_mask_set_bit;
+ gc->chip_types->chip.irq_set_type = stm32_irq_set_type;
+ gc->chip_types->chip.irq_set_wake = stm32_irq_set_wake;
+ gc->chip_types->regs.ack = EXTI_PR;
+ gc->chip_types->regs.mask = EXTI_IMR;
+ gc->chip_types->handler = handle_edge_irq;
+
+ nr_irqs = of_irq_count(node);
+ for (i = 0; i < nr_irqs; i++) {
+ unsigned int irq = irq_of_parse_and_map(node, i);
+
+ irq_set_handler_data(irq, domain);
+ irq_set_chained_handler(irq, stm32_irq_handler);
+ }
+
+ return 0;
+
+out_free_domain:
+ irq_domain_remove(domain);
+out_unmap:
+ iounmap(base);
+ return ret;
+}
+
+IRQCHIP_DECLARE(stm32_exti, "st,stm32-exti", stm32_exti_init);
--
1.9.1
^ permalink raw reply related [flat|nested] 30+ messages in thread* [PATCH v6 2/4] drivers: irqchip: Add STM32 external interrupts support
@ 2016-09-20 16:00 ` Alexandre TORGUE
0 siblings, 0 replies; 30+ messages in thread
From: Alexandre TORGUE @ 2016-09-20 16:00 UTC (permalink / raw)
To: linux-arm-kernel
The STM32 external interrupt controller consists of edge detectors that
generate interrupts requests or wake-up events.
Each line can be independently configured as interrupt or wake-up source,
and triggers either on rising, falling or both edges. Each line can also
be masked independently.
Signed-off-by: Maxime Coquelin <mcoquelin.stm32@gmail.com>
Signed-off-by: Alexandre TORGUE <alexandre.torgue@st.com>
diff --git a/drivers/irqchip/Kconfig b/drivers/irqchip/Kconfig
index 7f87289..bc62d1f 100644
--- a/drivers/irqchip/Kconfig
+++ b/drivers/irqchip/Kconfig
@@ -264,3 +264,7 @@ config EZNPS_GIC
select IRQ_DOMAIN
help
Support the EZchip NPS400 global interrupt controller
+
+config STM32_EXTI
+ bool
+ select IRQ_DOMAIN
diff --git a/drivers/irqchip/Makefile b/drivers/irqchip/Makefile
index 4c203b6..96383b2 100644
--- a/drivers/irqchip/Makefile
+++ b/drivers/irqchip/Makefile
@@ -71,3 +71,4 @@ obj-$(CONFIG_MVEBU_ODMI) += irq-mvebu-odmi.o
obj-$(CONFIG_LS_SCFG_MSI) += irq-ls-scfg-msi.o
obj-$(CONFIG_EZNPS_GIC) += irq-eznps.o
obj-$(CONFIG_ARCH_ASPEED) += irq-aspeed-vic.o
+obj-$(CONFIG_STM32_EXTI) += irq-stm32-exti.o
diff --git a/drivers/irqchip/irq-stm32-exti.c b/drivers/irqchip/irq-stm32-exti.c
new file mode 100644
index 0000000..491568c
--- /dev/null
+++ b/drivers/irqchip/irq-stm32-exti.c
@@ -0,0 +1,201 @@
+/*
+ * Copyright (C) Maxime Coquelin 2015
+ * Author: Maxime Coquelin <mcoquelin.stm32@gmail.com>
+ * License terms: GNU General Public License (GPL), version 2
+ */
+
+#include <linux/bitops.h>
+#include <linux/interrupt.h>
+#include <linux/io.h>
+#include <linux/irq.h>
+#include <linux/irqchip.h>
+#include <linux/irqchip/chained_irq.h>
+#include <linux/irqdomain.h>
+#include <linux/of_address.h>
+#include <linux/of_irq.h>
+
+#define EXTI_IMR 0x0
+#define EXTI_EMR 0x4
+#define EXTI_RTSR 0x8
+#define EXTI_FTSR 0xc
+#define EXTI_SWIER 0x10
+#define EXTI_PR 0x14
+
+static void stm32_irq_handler(struct irq_desc *desc)
+{
+ struct irq_domain *domain = irq_desc_get_handler_data(desc);
+ struct irq_chip_generic *gc = domain->gc->gc[0];
+ struct irq_chip *chip = irq_desc_get_chip(desc);
+ unsigned long pending;
+ int n;
+
+ chained_irq_enter(chip, desc);
+
+ while ((pending = irq_reg_readl(gc, EXTI_PR))) {
+ for_each_set_bit(n, &pending, BITS_PER_LONG) {
+ generic_handle_irq(irq_find_mapping(domain, n));
+ irq_reg_writel(gc, BIT(n), EXTI_PR);
+ }
+ }
+
+ chained_irq_exit(chip, desc);
+}
+
+static int stm32_irq_set_type(struct irq_data *data, unsigned int type)
+{
+ struct irq_chip_generic *gc = irq_data_get_irq_chip_data(data);
+ int pin = data->hwirq;
+ u32 rtsr, ftsr;
+
+ irq_gc_lock(gc);
+
+ rtsr = irq_reg_readl(gc, EXTI_RTSR);
+ ftsr = irq_reg_readl(gc, EXTI_FTSR);
+
+ switch (type) {
+ case IRQ_TYPE_EDGE_RISING:
+ rtsr |= BIT(pin);
+ ftsr &= ~BIT(pin);
+ break;
+ case IRQ_TYPE_EDGE_FALLING:
+ rtsr &= ~BIT(pin);
+ ftsr |= BIT(pin);
+ break;
+ case IRQ_TYPE_EDGE_BOTH:
+ rtsr |= BIT(pin);
+ ftsr |= BIT(pin);
+ break;
+ default:
+ irq_gc_unlock(gc);
+ return -EINVAL;
+ }
+
+ irq_reg_writel(gc, rtsr, EXTI_RTSR);
+ irq_reg_writel(gc, ftsr, EXTI_FTSR);
+
+ irq_gc_unlock(gc);
+
+ return 0;
+}
+
+static int stm32_irq_set_wake(struct irq_data *data, unsigned int on)
+{
+ struct irq_chip_generic *gc = irq_data_get_irq_chip_data(data);
+ int pin = data->hwirq;
+ u32 emr;
+
+ irq_gc_lock(gc);
+
+ emr = irq_reg_readl(gc, EXTI_EMR);
+ if (on)
+ emr |= BIT(pin);
+ else
+ emr &= ~BIT(pin);
+ irq_reg_writel(gc, emr, EXTI_EMR);
+
+ irq_gc_unlock(gc);
+
+ return 0;
+}
+
+static int stm32_exti_alloc(struct irq_domain *d, unsigned int virq,
+ unsigned int nr_irqs, void *data)
+{
+ struct irq_chip_generic *gc = d->gc->gc[0];
+ struct irq_fwspec *fwspec = data;
+ irq_hw_number_t hwirq;
+
+ hwirq = fwspec->param[0];
+
+ irq_map_generic_chip(d, virq, hwirq);
+ irq_domain_set_info(d, virq, hwirq, &gc->chip_types->chip, gc,
+ handle_simple_irq, NULL, NULL);
+
+ return 0;
+}
+
+static void stm32_exti_free(struct irq_domain *d, unsigned int virq,
+ unsigned int nr_irqs)
+{
+ struct irq_data *data = irq_domain_get_irq_data(d, virq);
+
+ irq_domain_reset_irq_data(data);
+}
+
+struct irq_domain_ops irq_exti_domain_ops = {
+ .map = irq_map_generic_chip,
+ .xlate = irq_domain_xlate_onetwocell,
+ .alloc = stm32_exti_alloc,
+ .free = stm32_exti_free,
+};
+
+static int __init stm32_exti_init(struct device_node *node,
+ struct device_node *parent)
+{
+ unsigned int clr = IRQ_NOREQUEST | IRQ_NOPROBE | IRQ_NOAUTOEN;
+ int nr_irqs, nr_exti, ret, i;
+ struct irq_chip_generic *gc;
+ struct irq_domain *domain;
+ void *base;
+
+ base = of_iomap(node, 0);
+ if (!base) {
+ pr_err("%s: Unable to map registers\n", node->full_name);
+ return -ENOMEM;
+ }
+
+ /* Determine number of irqs supported */
+ writel_relaxed(~0UL, base + EXTI_RTSR);
+ nr_exti = fls(readl_relaxed(base + EXTI_RTSR));
+ writel_relaxed(0, base + EXTI_RTSR);
+
+ pr_info("%s: %d External IRQs detected\n", node->full_name, nr_exti);
+
+ domain = irq_domain_add_linear(node, nr_exti,
+ &irq_exti_domain_ops, NULL);
+ if (!domain) {
+ pr_err("%s: Could not register interrupt domain.\n",
+ node->name);
+ ret = -ENOMEM;
+ goto out_unmap;
+ }
+
+ ret = irq_alloc_domain_generic_chips(domain, nr_exti, 1, "exti",
+ handle_edge_irq, clr, 0, 0);
+ if (ret) {
+ pr_err("%s: Could not allocate generic interrupt chip.\n",
+ node->full_name);
+ goto out_free_domain;
+ }
+
+ gc = domain->gc->gc[0];
+ gc->reg_base = base;
+ gc->chip_types->type = IRQ_TYPE_EDGE_BOTH;
+ gc->chip_types->chip.name = gc->chip_types[0].chip.name;
+ gc->chip_types->chip.irq_ack = irq_gc_ack_set_bit;
+ gc->chip_types->chip.irq_mask = irq_gc_mask_clr_bit;
+ gc->chip_types->chip.irq_unmask = irq_gc_mask_set_bit;
+ gc->chip_types->chip.irq_set_type = stm32_irq_set_type;
+ gc->chip_types->chip.irq_set_wake = stm32_irq_set_wake;
+ gc->chip_types->regs.ack = EXTI_PR;
+ gc->chip_types->regs.mask = EXTI_IMR;
+ gc->chip_types->handler = handle_edge_irq;
+
+ nr_irqs = of_irq_count(node);
+ for (i = 0; i < nr_irqs; i++) {
+ unsigned int irq = irq_of_parse_and_map(node, i);
+
+ irq_set_handler_data(irq, domain);
+ irq_set_chained_handler(irq, stm32_irq_handler);
+ }
+
+ return 0;
+
+out_free_domain:
+ irq_domain_remove(domain);
+out_unmap:
+ iounmap(base);
+ return ret;
+}
+
+IRQCHIP_DECLARE(stm32_exti, "st,stm32-exti", stm32_exti_init);
--
1.9.1
^ permalink raw reply related [flat|nested] 30+ messages in thread* Re: [PATCH v6 2/4] drivers: irqchip: Add STM32 external interrupts support
2016-09-20 16:00 ` Alexandre TORGUE
@ 2016-09-20 20:16 ` Thomas Gleixner
-1 siblings, 0 replies; 30+ messages in thread
From: Thomas Gleixner @ 2016-09-20 20:16 UTC (permalink / raw)
To: Alexandre TORGUE
Cc: Maxime Coquelin, Jason Cooper, Marc Zyngier, Linus Walleij,
Mark Rutland, Rob Herring, linux-gpio, arnd, linux-arm-kernel,
linux-kernel, devicetree, Daniel Thompson, bruherrera, lee.jones
Alexandre,
On Tue, 20 Sep 2016, Alexandre TORGUE wrote:
> The STM32 external interrupt controller consists of edge detectors that
> generate interrupts requests or wake-up events.
>
> Each line can be independently configured as interrupt or wake-up source,
> and triggers either on rising, falling or both edges. Each line can also
> be masked independently.
>
> Signed-off-by: Maxime Coquelin <mcoquelin.stm32@gmail.com>
> Signed-off-by: Alexandre TORGUE <alexandre.torgue@st.com>
That all looks very reasonable now. The only remaining question is your SOB
chain. Who is the author of these patches? You or Maxime? If it's Maxime,
then the changelog misses a From: tag. If it's you then Maximes SOB is
bogus.
Thanks,
tglx
^ permalink raw reply [flat|nested] 30+ messages in thread
* [PATCH v6 2/4] drivers: irqchip: Add STM32 external interrupts support
@ 2016-09-20 20:16 ` Thomas Gleixner
0 siblings, 0 replies; 30+ messages in thread
From: Thomas Gleixner @ 2016-09-20 20:16 UTC (permalink / raw)
To: linux-arm-kernel
Alexandre,
On Tue, 20 Sep 2016, Alexandre TORGUE wrote:
> The STM32 external interrupt controller consists of edge detectors that
> generate interrupts requests or wake-up events.
>
> Each line can be independently configured as interrupt or wake-up source,
> and triggers either on rising, falling or both edges. Each line can also
> be masked independently.
>
> Signed-off-by: Maxime Coquelin <mcoquelin.stm32@gmail.com>
> Signed-off-by: Alexandre TORGUE <alexandre.torgue@st.com>
That all looks very reasonable now. The only remaining question is your SOB
chain. Who is the author of these patches? You or Maxime? If it's Maxime,
then the changelog misses a From: tag. If it's you then Maximes SOB is
bogus.
Thanks,
tglx
^ permalink raw reply [flat|nested] 30+ messages in thread
* Re: [PATCH v6 2/4] drivers: irqchip: Add STM32 external interrupts support
2016-09-20 20:16 ` Thomas Gleixner
(?)
@ 2016-09-21 7:45 ` Alexandre Torgue
-1 siblings, 0 replies; 30+ messages in thread
From: Alexandre Torgue @ 2016-09-21 7:45 UTC (permalink / raw)
To: Thomas Gleixner
Cc: Maxime Coquelin, Jason Cooper, Marc Zyngier, Linus Walleij,
Mark Rutland, Rob Herring, linux-gpio, arnd, linux-arm-kernel,
linux-kernel, devicetree, Daniel Thompson, bruherrera, lee.jones
Hi Thomas,
On 09/20/2016 10:16 PM, Thomas Gleixner wrote:
> Alexandre,
>
> On Tue, 20 Sep 2016, Alexandre TORGUE wrote:
>
>> The STM32 external interrupt controller consists of edge detectors that
>> generate interrupts requests or wake-up events.
>>
>> Each line can be independently configured as interrupt or wake-up source,
>> and triggers either on rising, falling or both edges. Each line can also
>> be masked independently.
>>
>> Signed-off-by: Maxime Coquelin <mcoquelin.stm32@gmail.com>
>> Signed-off-by: Alexandre TORGUE <alexandre.torgue@st.com>
>
> That all looks very reasonable now. The only remaining question is your SOB
> chain. Who is the author of these patches? You or Maxime? If it's Maxime,
> then the changelog misses a From: tag. If it's you then Maximes SOB is
> bogus.
Actually Maxime wrote the main part of this driver and sent version 1
and 2 of the series. After Linus W. reviews, rework was required to use
hierarchical domain. According to Maxime, I coded the rework (adaptation
to hierarchical domain) and sent other version of the series.
Regards
Alex
>
> Thanks,
>
> tglx
>
>
^ permalink raw reply [flat|nested] 30+ messages in thread
* Re: [PATCH v6 2/4] drivers: irqchip: Add STM32 external interrupts support
@ 2016-09-21 7:45 ` Alexandre Torgue
0 siblings, 0 replies; 30+ messages in thread
From: Alexandre Torgue @ 2016-09-21 7:45 UTC (permalink / raw)
To: Thomas Gleixner
Cc: Maxime Coquelin, Jason Cooper, Marc Zyngier, Linus Walleij,
Mark Rutland, Rob Herring, linux-gpio, arnd, linux-arm-kernel,
linux-kernel, devicetree, Daniel Thompson, bruherrera, lee.jones
Hi Thomas,
On 09/20/2016 10:16 PM, Thomas Gleixner wrote:
> Alexandre,
>
> On Tue, 20 Sep 2016, Alexandre TORGUE wrote:
>
>> The STM32 external interrupt controller consists of edge detectors that
>> generate interrupts requests or wake-up events.
>>
>> Each line can be independently configured as interrupt or wake-up source,
>> and triggers either on rising, falling or both edges. Each line can also
>> be masked independently.
>>
>> Signed-off-by: Maxime Coquelin <mcoquelin.stm32@gmail.com>
>> Signed-off-by: Alexandre TORGUE <alexandre.torgue@st.com>
>
> That all looks very reasonable now. The only remaining question is your SOB
> chain. Who is the author of these patches? You or Maxime? If it's Maxime,
> then the changelog misses a From: tag. If it's you then Maximes SOB is
> bogus.
Actually Maxime wrote the main part of this driver and sent version 1
and 2 of the series. After Linus W. reviews, rework was required to use
hierarchical domain. According to Maxime, I coded the rework (adaptation
to hierarchical domain) and sent other version of the series.
Regards
Alex
>
> Thanks,
>
> tglx
>
>
^ permalink raw reply [flat|nested] 30+ messages in thread
* [PATCH v6 2/4] drivers: irqchip: Add STM32 external interrupts support
@ 2016-09-21 7:45 ` Alexandre Torgue
0 siblings, 0 replies; 30+ messages in thread
From: Alexandre Torgue @ 2016-09-21 7:45 UTC (permalink / raw)
To: linux-arm-kernel
Hi Thomas,
On 09/20/2016 10:16 PM, Thomas Gleixner wrote:
> Alexandre,
>
> On Tue, 20 Sep 2016, Alexandre TORGUE wrote:
>
>> The STM32 external interrupt controller consists of edge detectors that
>> generate interrupts requests or wake-up events.
>>
>> Each line can be independently configured as interrupt or wake-up source,
>> and triggers either on rising, falling or both edges. Each line can also
>> be masked independently.
>>
>> Signed-off-by: Maxime Coquelin <mcoquelin.stm32@gmail.com>
>> Signed-off-by: Alexandre TORGUE <alexandre.torgue@st.com>
>
> That all looks very reasonable now. The only remaining question is your SOB
> chain. Who is the author of these patches? You or Maxime? If it's Maxime,
> then the changelog misses a From: tag. If it's you then Maximes SOB is
> bogus.
Actually Maxime wrote the main part of this driver and sent version 1
and 2 of the series. After Linus W. reviews, rework was required to use
hierarchical domain. According to Maxime, I coded the rework (adaptation
to hierarchical domain) and sent other version of the series.
Regards
Alex
>
> Thanks,
>
> tglx
>
>
^ permalink raw reply [flat|nested] 30+ messages in thread
[parent not found: <f7875786-9b5e-075a-59c8-cd32fb1c4583-qxv4g6HH51o@public.gmane.org>]
* Re: [PATCH v6 2/4] drivers: irqchip: Add STM32 external interrupts support
2016-09-21 7:45 ` Alexandre Torgue
(?)
@ 2016-09-21 7:50 ` Thomas Gleixner
-1 siblings, 0 replies; 30+ messages in thread
From: Thomas Gleixner @ 2016-09-21 7:50 UTC (permalink / raw)
To: Alexandre Torgue
Cc: Maxime Coquelin, Jason Cooper, Marc Zyngier, Linus Walleij,
Mark Rutland, Rob Herring, linux-gpio-u79uwXL29TY76Z2rM5mHXA,
arnd-r2nGTMty4D4,
linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
linux-kernel-u79uwXL29TY76Z2rM5mHXA,
devicetree-u79uwXL29TY76Z2rM5mHXA, Daniel Thompson,
bruherrera-Re5JQEeQqe8AvxtiuMwx3w,
lee.jones-QSEj5FYQhm4dnm+yROfE0A
On Wed, 21 Sep 2016, Alexandre Torgue wrote:
> Hi Thomas,
>
> On 09/20/2016 10:16 PM, Thomas Gleixner wrote:
> > Alexandre,
> >
> > On Tue, 20 Sep 2016, Alexandre TORGUE wrote:
> >
> > > The STM32 external interrupt controller consists of edge detectors that
> > > generate interrupts requests or wake-up events.
> > >
> > > Each line can be independently configured as interrupt or wake-up source,
> > > and triggers either on rising, falling or both edges. Each line can also
> > > be masked independently.
> > >
> > > Signed-off-by: Maxime Coquelin <mcoquelin.stm32-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
> > > Signed-off-by: Alexandre TORGUE <alexandre.torgue-qxv4g6HH51o@public.gmane.org>
> >
> > That all looks very reasonable now. The only remaining question is your SOB
> > chain. Who is the author of these patches? You or Maxime? If it's Maxime,
> > then the changelog misses a From: tag. If it's you then Maximes SOB is
> > bogus.
>
> Actually Maxime wrote the main part of this driver and sent version 1 and 2 of
> the series. After Linus W. reviews, rework was required to use hierarchical
> domain. According to Maxime, I coded the rework (adaptation to hierarchical
> domain) and sent other version of the series.
So I replace Maximes SOB with Originally-by: Does that apply to all four
patches?
Thanks,
tglx
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply [flat|nested] 30+ messages in thread
* Re: [PATCH v6 2/4] drivers: irqchip: Add STM32 external interrupts support
@ 2016-09-21 7:50 ` Thomas Gleixner
0 siblings, 0 replies; 30+ messages in thread
From: Thomas Gleixner @ 2016-09-21 7:50 UTC (permalink / raw)
To: Alexandre Torgue
Cc: Maxime Coquelin, Jason Cooper, Marc Zyngier, Linus Walleij,
Mark Rutland, Rob Herring, linux-gpio, arnd, linux-arm-kernel,
linux-kernel, devicetree, Daniel Thompson, bruherrera, lee.jones
On Wed, 21 Sep 2016, Alexandre Torgue wrote:
> Hi Thomas,
>
> On 09/20/2016 10:16 PM, Thomas Gleixner wrote:
> > Alexandre,
> >
> > On Tue, 20 Sep 2016, Alexandre TORGUE wrote:
> >
> > > The STM32 external interrupt controller consists of edge detectors that
> > > generate interrupts requests or wake-up events.
> > >
> > > Each line can be independently configured as interrupt or wake-up source,
> > > and triggers either on rising, falling or both edges. Each line can also
> > > be masked independently.
> > >
> > > Signed-off-by: Maxime Coquelin <mcoquelin.stm32@gmail.com>
> > > Signed-off-by: Alexandre TORGUE <alexandre.torgue@st.com>
> >
> > That all looks very reasonable now. The only remaining question is your SOB
> > chain. Who is the author of these patches? You or Maxime? If it's Maxime,
> > then the changelog misses a From: tag. If it's you then Maximes SOB is
> > bogus.
>
> Actually Maxime wrote the main part of this driver and sent version 1 and 2 of
> the series. After Linus W. reviews, rework was required to use hierarchical
> domain. According to Maxime, I coded the rework (adaptation to hierarchical
> domain) and sent other version of the series.
So I replace Maximes SOB with Originally-by: Does that apply to all four
patches?
Thanks,
tglx
^ permalink raw reply [flat|nested] 30+ messages in thread
* [PATCH v6 2/4] drivers: irqchip: Add STM32 external interrupts support
@ 2016-09-21 7:50 ` Thomas Gleixner
0 siblings, 0 replies; 30+ messages in thread
From: Thomas Gleixner @ 2016-09-21 7:50 UTC (permalink / raw)
To: linux-arm-kernel
On Wed, 21 Sep 2016, Alexandre Torgue wrote:
> Hi Thomas,
>
> On 09/20/2016 10:16 PM, Thomas Gleixner wrote:
> > Alexandre,
> >
> > On Tue, 20 Sep 2016, Alexandre TORGUE wrote:
> >
> > > The STM32 external interrupt controller consists of edge detectors that
> > > generate interrupts requests or wake-up events.
> > >
> > > Each line can be independently configured as interrupt or wake-up source,
> > > and triggers either on rising, falling or both edges. Each line can also
> > > be masked independently.
> > >
> > > Signed-off-by: Maxime Coquelin <mcoquelin.stm32@gmail.com>
> > > Signed-off-by: Alexandre TORGUE <alexandre.torgue@st.com>
> >
> > That all looks very reasonable now. The only remaining question is your SOB
> > chain. Who is the author of these patches? You or Maxime? If it's Maxime,
> > then the changelog misses a From: tag. If it's you then Maximes SOB is
> > bogus.
>
> Actually Maxime wrote the main part of this driver and sent version 1 and 2 of
> the series. After Linus W. reviews, rework was required to use hierarchical
> domain. According to Maxime, I coded the rework (adaptation to hierarchical
> domain) and sent other version of the series.
So I replace Maximes SOB with Originally-by: Does that apply to all four
patches?
Thanks,
tglx
^ permalink raw reply [flat|nested] 30+ messages in thread
* Re: [PATCH v6 2/4] drivers: irqchip: Add STM32 external interrupts support
2016-09-21 7:50 ` Thomas Gleixner
(?)
@ 2016-09-21 7:54 ` Maxime Coquelin
-1 siblings, 0 replies; 30+ messages in thread
From: Maxime Coquelin @ 2016-09-21 7:54 UTC (permalink / raw)
To: Thomas Gleixner
Cc: Alexandre Torgue, Jason Cooper, Marc Zyngier, Linus Walleij,
Mark Rutland, Rob Herring,
linux-gpio-u79uwXL29TY76Z2rM5mHXA@public.gmane.org, Arnd Bergmann,
linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r@public.gmane.org,
linux-kernel-u79uwXL29TY76Z2rM5mHXA@public.gmane.org,
devicetree-u79uwXL29TY76Z2rM5mHXA@public.gmane.org,
Daniel Thompson, Bruno Herrera, Lee Jones
2016-09-21 9:50 GMT+02:00 Thomas Gleixner <tglx-hfZtesqFncYOwBW4kG4KsQ@public.gmane.org>:
> On Wed, 21 Sep 2016, Alexandre Torgue wrote:
>
>> Hi Thomas,
>>
>> On 09/20/2016 10:16 PM, Thomas Gleixner wrote:
>> > Alexandre,
>> >
>> > On Tue, 20 Sep 2016, Alexandre TORGUE wrote:
>> >
>> > > The STM32 external interrupt controller consists of edge detectors that
>> > > generate interrupts requests or wake-up events.
>> > >
>> > > Each line can be independently configured as interrupt or wake-up source,
>> > > and triggers either on rising, falling or both edges. Each line can also
>> > > be masked independently.
>> > >
>> > > Signed-off-by: Maxime Coquelin <mcoquelin.stm32-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
>> > > Signed-off-by: Alexandre TORGUE <alexandre.torgue-qxv4g6HH51o@public.gmane.org>
>> >
>> > That all looks very reasonable now. The only remaining question is your SOB
>> > chain. Who is the author of these patches? You or Maxime? If it's Maxime,
>> > then the changelog misses a From: tag. If it's you then Maximes SOB is
>> > bogus.
>>
>> Actually Maxime wrote the main part of this driver and sent version 1 and 2 of
>> the series. After Linus W. reviews, rework was required to use hierarchical
>> domain. According to Maxime, I coded the rework (adaptation to hierarchical
>> domain) and sent other version of the series.
>
> So I replace Maximes SOB with Originally-by: Does that apply to all four
> patches?
Yes, that's fine.
Alex did a lot of rework on this series, he deserves the SoB.
Thanks,
Maxime
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply [flat|nested] 30+ messages in thread
* Re: [PATCH v6 2/4] drivers: irqchip: Add STM32 external interrupts support
@ 2016-09-21 7:54 ` Maxime Coquelin
0 siblings, 0 replies; 30+ messages in thread
From: Maxime Coquelin @ 2016-09-21 7:54 UTC (permalink / raw)
To: Thomas Gleixner
Cc: Alexandre Torgue, Jason Cooper, Marc Zyngier, Linus Walleij,
Mark Rutland, Rob Herring, linux-gpio@vger.kernel.org,
Arnd Bergmann, linux-arm-kernel@lists.infradead.org,
linux-kernel@vger.kernel.org, devicetree@vger.kernel.org,
Daniel Thompson, Bruno Herrera, Lee Jones
2016-09-21 9:50 GMT+02:00 Thomas Gleixner <tglx@linutronix.de>:
> On Wed, 21 Sep 2016, Alexandre Torgue wrote:
>
>> Hi Thomas,
>>
>> On 09/20/2016 10:16 PM, Thomas Gleixner wrote:
>> > Alexandre,
>> >
>> > On Tue, 20 Sep 2016, Alexandre TORGUE wrote:
>> >
>> > > The STM32 external interrupt controller consists of edge detectors that
>> > > generate interrupts requests or wake-up events.
>> > >
>> > > Each line can be independently configured as interrupt or wake-up source,
>> > > and triggers either on rising, falling or both edges. Each line can also
>> > > be masked independently.
>> > >
>> > > Signed-off-by: Maxime Coquelin <mcoquelin.stm32@gmail.com>
>> > > Signed-off-by: Alexandre TORGUE <alexandre.torgue@st.com>
>> >
>> > That all looks very reasonable now. The only remaining question is your SOB
>> > chain. Who is the author of these patches? You or Maxime? If it's Maxime,
>> > then the changelog misses a From: tag. If it's you then Maximes SOB is
>> > bogus.
>>
>> Actually Maxime wrote the main part of this driver and sent version 1 and 2 of
>> the series. After Linus W. reviews, rework was required to use hierarchical
>> domain. According to Maxime, I coded the rework (adaptation to hierarchical
>> domain) and sent other version of the series.
>
> So I replace Maximes SOB with Originally-by: Does that apply to all four
> patches?
Yes, that's fine.
Alex did a lot of rework on this series, he deserves the SoB.
Thanks,
Maxime
^ permalink raw reply [flat|nested] 30+ messages in thread
* [PATCH v6 2/4] drivers: irqchip: Add STM32 external interrupts support
@ 2016-09-21 7:54 ` Maxime Coquelin
0 siblings, 0 replies; 30+ messages in thread
From: Maxime Coquelin @ 2016-09-21 7:54 UTC (permalink / raw)
To: linux-arm-kernel
2016-09-21 9:50 GMT+02:00 Thomas Gleixner <tglx@linutronix.de>:
> On Wed, 21 Sep 2016, Alexandre Torgue wrote:
>
>> Hi Thomas,
>>
>> On 09/20/2016 10:16 PM, Thomas Gleixner wrote:
>> > Alexandre,
>> >
>> > On Tue, 20 Sep 2016, Alexandre TORGUE wrote:
>> >
>> > > The STM32 external interrupt controller consists of edge detectors that
>> > > generate interrupts requests or wake-up events.
>> > >
>> > > Each line can be independently configured as interrupt or wake-up source,
>> > > and triggers either on rising, falling or both edges. Each line can also
>> > > be masked independently.
>> > >
>> > > Signed-off-by: Maxime Coquelin <mcoquelin.stm32@gmail.com>
>> > > Signed-off-by: Alexandre TORGUE <alexandre.torgue@st.com>
>> >
>> > That all looks very reasonable now. The only remaining question is your SOB
>> > chain. Who is the author of these patches? You or Maxime? If it's Maxime,
>> > then the changelog misses a From: tag. If it's you then Maximes SOB is
>> > bogus.
>>
>> Actually Maxime wrote the main part of this driver and sent version 1 and 2 of
>> the series. After Linus W. reviews, rework was required to use hierarchical
>> domain. According to Maxime, I coded the rework (adaptation to hierarchical
>> domain) and sent other version of the series.
>
> So I replace Maximes SOB with Originally-by: Does that apply to all four
> patches?
Yes, that's fine.
Alex did a lot of rework on this series, he deserves the SoB.
Thanks,
Maxime
^ permalink raw reply [flat|nested] 30+ messages in thread
* [tip:irq/core] drivers/irqchip: Add STM32 external interrupts support
2016-09-20 16:00 ` Alexandre TORGUE
` (2 preceding siblings ...)
(?)
@ 2016-09-21 12:19 ` tip-bot for Alexandre TORGUE
-1 siblings, 0 replies; 30+ messages in thread
From: tip-bot for Alexandre TORGUE @ 2016-09-21 12:19 UTC (permalink / raw)
To: linux-tip-commits
Cc: alexandre.torgue, jason, mingo, tglx, hpa, daniel.thompson,
linus.walleij, robh+dt, mark.rutland, linux-kernel, marc.zyngier
Commit-ID: e072041688ca73f125719815fa4b0fd23a45152c
Gitweb: http://git.kernel.org/tip/e072041688ca73f125719815fa4b0fd23a45152c
Author: Alexandre TORGUE <alexandre.torgue@st.com>
AuthorDate: Tue, 20 Sep 2016 18:00:57 +0200
Committer: Thomas Gleixner <tglx@linutronix.de>
CommitDate: Wed, 21 Sep 2016 14:13:21 +0200
drivers/irqchip: Add STM32 external interrupts support
The STM32 external interrupt controller consists of edge detectors that
generate interrupts requests or wake-up events.
Each line can be independently configured as interrupt or wake-up source,
and triggers either on rising, falling or both edges. Each line can also
be masked independently.
Originally-from: Maxime Coquelin <mcoquelin.stm32@gmail.com>
Signed-off-by: Alexandre TORGUE <alexandre.torgue@st.com>
Cc: Mark Rutland <mark.rutland@arm.com>
Cc: devicetree@vger.kernel.org
Cc: Daniel Thompson <daniel.thompson@linaro.org>
Cc: Jason Cooper <jason@lakedaemon.net>
Cc: arnd@arndb.de
Cc: Marc Zyngier <marc.zyngier@arm.com>
Cc: bruherrera@gmail.com
Cc: Linus Walleij <linus.walleij@linaro.org>
Cc: linux-gpio@vger.kernel.org
Cc: Rob Herring <robh+dt@kernel.org>
Cc: lee.jones@linaro.org
Cc: linux-arm-kernel@lists.infradead.org
Link: http://lkml.kernel.org/r/1474387259-18926-3-git-send-email-alexandre.torgue@st.com
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
---
drivers/irqchip/Kconfig | 4 +
drivers/irqchip/Makefile | 1 +
drivers/irqchip/irq-stm32-exti.c | 201 +++++++++++++++++++++++++++++++++++++++
3 files changed, 206 insertions(+)
diff --git a/drivers/irqchip/Kconfig b/drivers/irqchip/Kconfig
index 9aeea1d..329c941 100644
--- a/drivers/irqchip/Kconfig
+++ b/drivers/irqchip/Kconfig
@@ -265,3 +265,7 @@ config EZNPS_GIC
select IRQ_DOMAIN
help
Support the EZchip NPS400 global interrupt controller
+
+config STM32_EXTI
+ bool
+ select IRQ_DOMAIN
diff --git a/drivers/irqchip/Makefile b/drivers/irqchip/Makefile
index 4c203b6..96383b2 100644
--- a/drivers/irqchip/Makefile
+++ b/drivers/irqchip/Makefile
@@ -71,3 +71,4 @@ obj-$(CONFIG_MVEBU_ODMI) += irq-mvebu-odmi.o
obj-$(CONFIG_LS_SCFG_MSI) += irq-ls-scfg-msi.o
obj-$(CONFIG_EZNPS_GIC) += irq-eznps.o
obj-$(CONFIG_ARCH_ASPEED) += irq-aspeed-vic.o
+obj-$(CONFIG_STM32_EXTI) += irq-stm32-exti.o
diff --git a/drivers/irqchip/irq-stm32-exti.c b/drivers/irqchip/irq-stm32-exti.c
new file mode 100644
index 0000000..491568c
--- /dev/null
+++ b/drivers/irqchip/irq-stm32-exti.c
@@ -0,0 +1,201 @@
+/*
+ * Copyright (C) Maxime Coquelin 2015
+ * Author: Maxime Coquelin <mcoquelin.stm32@gmail.com>
+ * License terms: GNU General Public License (GPL), version 2
+ */
+
+#include <linux/bitops.h>
+#include <linux/interrupt.h>
+#include <linux/io.h>
+#include <linux/irq.h>
+#include <linux/irqchip.h>
+#include <linux/irqchip/chained_irq.h>
+#include <linux/irqdomain.h>
+#include <linux/of_address.h>
+#include <linux/of_irq.h>
+
+#define EXTI_IMR 0x0
+#define EXTI_EMR 0x4
+#define EXTI_RTSR 0x8
+#define EXTI_FTSR 0xc
+#define EXTI_SWIER 0x10
+#define EXTI_PR 0x14
+
+static void stm32_irq_handler(struct irq_desc *desc)
+{
+ struct irq_domain *domain = irq_desc_get_handler_data(desc);
+ struct irq_chip_generic *gc = domain->gc->gc[0];
+ struct irq_chip *chip = irq_desc_get_chip(desc);
+ unsigned long pending;
+ int n;
+
+ chained_irq_enter(chip, desc);
+
+ while ((pending = irq_reg_readl(gc, EXTI_PR))) {
+ for_each_set_bit(n, &pending, BITS_PER_LONG) {
+ generic_handle_irq(irq_find_mapping(domain, n));
+ irq_reg_writel(gc, BIT(n), EXTI_PR);
+ }
+ }
+
+ chained_irq_exit(chip, desc);
+}
+
+static int stm32_irq_set_type(struct irq_data *data, unsigned int type)
+{
+ struct irq_chip_generic *gc = irq_data_get_irq_chip_data(data);
+ int pin = data->hwirq;
+ u32 rtsr, ftsr;
+
+ irq_gc_lock(gc);
+
+ rtsr = irq_reg_readl(gc, EXTI_RTSR);
+ ftsr = irq_reg_readl(gc, EXTI_FTSR);
+
+ switch (type) {
+ case IRQ_TYPE_EDGE_RISING:
+ rtsr |= BIT(pin);
+ ftsr &= ~BIT(pin);
+ break;
+ case IRQ_TYPE_EDGE_FALLING:
+ rtsr &= ~BIT(pin);
+ ftsr |= BIT(pin);
+ break;
+ case IRQ_TYPE_EDGE_BOTH:
+ rtsr |= BIT(pin);
+ ftsr |= BIT(pin);
+ break;
+ default:
+ irq_gc_unlock(gc);
+ return -EINVAL;
+ }
+
+ irq_reg_writel(gc, rtsr, EXTI_RTSR);
+ irq_reg_writel(gc, ftsr, EXTI_FTSR);
+
+ irq_gc_unlock(gc);
+
+ return 0;
+}
+
+static int stm32_irq_set_wake(struct irq_data *data, unsigned int on)
+{
+ struct irq_chip_generic *gc = irq_data_get_irq_chip_data(data);
+ int pin = data->hwirq;
+ u32 emr;
+
+ irq_gc_lock(gc);
+
+ emr = irq_reg_readl(gc, EXTI_EMR);
+ if (on)
+ emr |= BIT(pin);
+ else
+ emr &= ~BIT(pin);
+ irq_reg_writel(gc, emr, EXTI_EMR);
+
+ irq_gc_unlock(gc);
+
+ return 0;
+}
+
+static int stm32_exti_alloc(struct irq_domain *d, unsigned int virq,
+ unsigned int nr_irqs, void *data)
+{
+ struct irq_chip_generic *gc = d->gc->gc[0];
+ struct irq_fwspec *fwspec = data;
+ irq_hw_number_t hwirq;
+
+ hwirq = fwspec->param[0];
+
+ irq_map_generic_chip(d, virq, hwirq);
+ irq_domain_set_info(d, virq, hwirq, &gc->chip_types->chip, gc,
+ handle_simple_irq, NULL, NULL);
+
+ return 0;
+}
+
+static void stm32_exti_free(struct irq_domain *d, unsigned int virq,
+ unsigned int nr_irqs)
+{
+ struct irq_data *data = irq_domain_get_irq_data(d, virq);
+
+ irq_domain_reset_irq_data(data);
+}
+
+struct irq_domain_ops irq_exti_domain_ops = {
+ .map = irq_map_generic_chip,
+ .xlate = irq_domain_xlate_onetwocell,
+ .alloc = stm32_exti_alloc,
+ .free = stm32_exti_free,
+};
+
+static int __init stm32_exti_init(struct device_node *node,
+ struct device_node *parent)
+{
+ unsigned int clr = IRQ_NOREQUEST | IRQ_NOPROBE | IRQ_NOAUTOEN;
+ int nr_irqs, nr_exti, ret, i;
+ struct irq_chip_generic *gc;
+ struct irq_domain *domain;
+ void *base;
+
+ base = of_iomap(node, 0);
+ if (!base) {
+ pr_err("%s: Unable to map registers\n", node->full_name);
+ return -ENOMEM;
+ }
+
+ /* Determine number of irqs supported */
+ writel_relaxed(~0UL, base + EXTI_RTSR);
+ nr_exti = fls(readl_relaxed(base + EXTI_RTSR));
+ writel_relaxed(0, base + EXTI_RTSR);
+
+ pr_info("%s: %d External IRQs detected\n", node->full_name, nr_exti);
+
+ domain = irq_domain_add_linear(node, nr_exti,
+ &irq_exti_domain_ops, NULL);
+ if (!domain) {
+ pr_err("%s: Could not register interrupt domain.\n",
+ node->name);
+ ret = -ENOMEM;
+ goto out_unmap;
+ }
+
+ ret = irq_alloc_domain_generic_chips(domain, nr_exti, 1, "exti",
+ handle_edge_irq, clr, 0, 0);
+ if (ret) {
+ pr_err("%s: Could not allocate generic interrupt chip.\n",
+ node->full_name);
+ goto out_free_domain;
+ }
+
+ gc = domain->gc->gc[0];
+ gc->reg_base = base;
+ gc->chip_types->type = IRQ_TYPE_EDGE_BOTH;
+ gc->chip_types->chip.name = gc->chip_types[0].chip.name;
+ gc->chip_types->chip.irq_ack = irq_gc_ack_set_bit;
+ gc->chip_types->chip.irq_mask = irq_gc_mask_clr_bit;
+ gc->chip_types->chip.irq_unmask = irq_gc_mask_set_bit;
+ gc->chip_types->chip.irq_set_type = stm32_irq_set_type;
+ gc->chip_types->chip.irq_set_wake = stm32_irq_set_wake;
+ gc->chip_types->regs.ack = EXTI_PR;
+ gc->chip_types->regs.mask = EXTI_IMR;
+ gc->chip_types->handler = handle_edge_irq;
+
+ nr_irqs = of_irq_count(node);
+ for (i = 0; i < nr_irqs; i++) {
+ unsigned int irq = irq_of_parse_and_map(node, i);
+
+ irq_set_handler_data(irq, domain);
+ irq_set_chained_handler(irq, stm32_irq_handler);
+ }
+
+ return 0;
+
+out_free_domain:
+ irq_domain_remove(domain);
+out_unmap:
+ iounmap(base);
+ return ret;
+}
+
+IRQCHIP_DECLARE(stm32_exti, "st,stm32-exti", stm32_exti_init);
^ permalink raw reply related [flat|nested] 30+ messages in thread