* [RFC PATCH v2 00/10] ARM: at91: move aic driver to drivers/irqchips
@ 2014-03-28 17:58 Boris BREZILLON
2014-03-28 17:58 ` [RFC PATCH v2 01/10] genirq: generic chip: export irq_map_generic_chip function Boris BREZILLON
` (9 more replies)
0 siblings, 10 replies; 19+ messages in thread
From: Boris BREZILLON @ 2014-03-28 17:58 UTC (permalink / raw)
To: Rob Landley, Nicolas Ferre, Jean-Christophe Plagniol-Villard,
Thomas Gleixner
Cc: devicetree, Boris BREZILLON, linux-kernel, linux-arm-kernel,
linux-doc
Hello,
This series is a proposal to move AIC driver to the irqchip directory.
It also changes the implementation design of the interrupt controller in
several ways:
- make use of the generic chip framework whenever possible
- add support for irq muxing definition to prevent spurious interrupts
during system startup (see https://lkml.org/lkml/2013/3/8/175)
- only support dt enabled boards
Best Regards,
Boris
Changes since v1:
- rework the irq-mux bindings
Boris BREZILLON (10):
genirq: generic chip: export irq_map_generic_chip function
irqchip: atmel-aic: add new atmel AIC driver
ARM: at91: introduce OLD_IRQ_AT91 Kconfig option
ARM: at91: enclose at91_aic_xx calls in
IS_ENABLED(CONFIG_OLD_IRQ_AT91) blocks
ARM: at91: make use of the new AIC driver for dt enabled boards
irqchip: atmel-aic: move binding doc to interrupt-controller
directory
irqchip: atmel-aic: document new dt properties and children nodes
ARM: at91: remove old irq material
ARM: at91/dt: add new AIC irq mux definitions for sam9x5 SoCs
ARM: at91/dt: add new AIC irq mux definitions for sama5 SoCs
.../devicetree/bindings/arm/atmel-aic.txt | 42 -
.../bindings/interrupt-controller/atmel,aic.txt | 82 ++
arch/arm/boot/dts/at91sam9x5.dtsi | 108 +++
arch/arm/boot/dts/sama5d3.dtsi | 37 +
arch/arm/boot/dts/sama5d3_tcb1.dtsi | 20 +
arch/arm/mach-at91/Kconfig | 11 +
arch/arm/mach-at91/Kconfig.non_dt | 7 +
arch/arm/mach-at91/Makefile | 3 +-
arch/arm/mach-at91/board-dt-rm9200.c | 13 -
arch/arm/mach-at91/board-dt-sam9.c | 14 -
arch/arm/mach-at91/board-dt-sama5.c | 13 -
arch/arm/mach-at91/irq.c | 270 +------
arch/arm/mach-at91/pm.c | 32 +-
arch/arm/mach-at91/setup.c | 3 +-
drivers/irqchip/Makefile | 1 +
drivers/irqchip/irq-atmel-aic.c | 851 ++++++++++++++++++++
include/linux/irq.h | 2 +
kernel/irq/generic-chip.c | 5 +-
18 files changed, 1152 insertions(+), 362 deletions(-)
delete mode 100644 Documentation/devicetree/bindings/arm/atmel-aic.txt
create mode 100644 Documentation/devicetree/bindings/interrupt-controller/atmel,aic.txt
create mode 100644 drivers/irqchip/irq-atmel-aic.c
--
1.7.9.5
^ permalink raw reply [flat|nested] 19+ messages in thread
* [RFC PATCH v2 01/10] genirq: generic chip: export irq_map_generic_chip function
2014-03-28 17:58 [RFC PATCH v2 00/10] ARM: at91: move aic driver to drivers/irqchips Boris BREZILLON
@ 2014-03-28 17:58 ` Boris BREZILLON
2014-03-28 17:59 ` [RFC PATCH v2 02/10] irqchip: atmel-aic: add new atmel AIC driver Boris BREZILLON
` (8 subsequent siblings)
9 siblings, 0 replies; 19+ messages in thread
From: Boris BREZILLON @ 2014-03-28 17:58 UTC (permalink / raw)
To: Rob Landley, Nicolas Ferre, Jean-Christophe Plagniol-Villard,
Thomas Gleixner
Cc: devicetree, linux-doc, linux-kernel, linux-arm-kernel,
Boris BREZILLON
Export the generic irq map function in order to provide irq_domain ops with
generic mapping and specific of xlate function (needed by the new atmel
AIC driver).
Signed-off-by: Boris BREZILLON <b.brezillon.dev@gmail.com>
---
include/linux/irq.h | 2 ++
kernel/irq/generic-chip.c | 5 +++--
2 files changed, 5 insertions(+), 2 deletions(-)
diff --git a/include/linux/irq.h b/include/linux/irq.h
index 7dc1003..19b5e3b 100644
--- a/include/linux/irq.h
+++ b/include/linux/irq.h
@@ -765,6 +765,8 @@ void irq_gc_eoi(struct irq_data *d);
int irq_gc_set_wake(struct irq_data *d, unsigned int on);
/* Setup functions for irq_chip_generic */
+int irq_map_generic_chip(struct irq_domain *d, unsigned int virq,
+ irq_hw_number_t hw_irq);
struct irq_chip_generic *
irq_alloc_generic_chip(const char *name, int nr_ct, unsigned int irq_base,
void __iomem *reg_base, irq_flow_handler_t handler);
diff --git a/kernel/irq/generic-chip.c b/kernel/irq/generic-chip.c
index 452d6f2..cf80e7b 100644
--- a/kernel/irq/generic-chip.c
+++ b/kernel/irq/generic-chip.c
@@ -341,8 +341,8 @@ static struct lock_class_key irq_nested_lock_class;
/*
* irq_map_generic_chip - Map a generic chip for an irq domain
*/
-static int irq_map_generic_chip(struct irq_domain *d, unsigned int virq,
- irq_hw_number_t hw_irq)
+int irq_map_generic_chip(struct irq_domain *d, unsigned int virq,
+ irq_hw_number_t hw_irq)
{
struct irq_data *data = irq_get_irq_data(virq);
struct irq_domain_chip_generic *dgc = d->gc;
@@ -394,6 +394,7 @@ static int irq_map_generic_chip(struct irq_domain *d, unsigned int virq,
irq_modify_status(virq, dgc->irq_flags_to_clear, dgc->irq_flags_to_set);
return 0;
}
+EXPORT_SYMBOL_GPL(irq_map_generic_chip);
struct irq_domain_ops irq_generic_chip_ops = {
.map = irq_map_generic_chip,
--
1.7.9.5
^ permalink raw reply related [flat|nested] 19+ messages in thread
* [RFC PATCH v2 02/10] irqchip: atmel-aic: add new atmel AIC driver
2014-03-28 17:58 [RFC PATCH v2 00/10] ARM: at91: move aic driver to drivers/irqchips Boris BREZILLON
2014-03-28 17:58 ` [RFC PATCH v2 01/10] genirq: generic chip: export irq_map_generic_chip function Boris BREZILLON
@ 2014-03-28 17:59 ` Boris BREZILLON
2014-03-28 17:59 ` [RFC PATCH v2 03/10] ARM: at91: introduce OLD_IRQ_AT91 Kconfig option Boris BREZILLON
` (7 subsequent siblings)
9 siblings, 0 replies; 19+ messages in thread
From: Boris BREZILLON @ 2014-03-28 17:59 UTC (permalink / raw)
To: Rob Landley, Nicolas Ferre, Jean-Christophe Plagniol-Villard,
Thomas Gleixner
Cc: devicetree, linux-doc, linux-kernel, linux-arm-kernel,
Boris BREZILLON
Add new atmel AIC (Advanced Interrupt Controller) driver based on the
generic chip infrastructure.
This driver is only compatible with dt enabled board and replaces the old
implementation found in arch/arm/mach-at91/irq.c.
It also provides a new way to handle AIC irq line muxing to avoid spurious
interrupts on startup and shutdown:
- disable all muxed interrupts during AIC probe
- disable every muxed interrupt attached to a specific AIC interrupt line
when this interrupt is disabled
Signed-off-by: Boris BREZILLON <b.brezillon.dev@gmail.com>
---
drivers/irqchip/Makefile | 1 +
drivers/irqchip/irq-atmel-aic.c | 851 +++++++++++++++++++++++++++++++++++++++
2 files changed, 852 insertions(+)
create mode 100644 drivers/irqchip/irq-atmel-aic.c
diff --git a/drivers/irqchip/Makefile b/drivers/irqchip/Makefile
index 5194afb..b2950860 100644
--- a/drivers/irqchip/Makefile
+++ b/drivers/irqchip/Makefile
@@ -16,6 +16,7 @@ obj-$(CONFIG_ARCH_SPEAR3XX) += spear-shirq.o
obj-$(CONFIG_ARM_GIC) += irq-gic.o
obj-$(CONFIG_ARM_NVIC) += irq-nvic.o
obj-$(CONFIG_ARM_VIC) += irq-vic.o
+obj-$(CONFIG_ATMEL_AIC_IRQ) += irq-atmel-aic.o
obj-$(CONFIG_IMGPDC_IRQ) += irq-imgpdc.o
obj-$(CONFIG_SIRF_IRQ) += irq-sirfsoc.o
obj-$(CONFIG_RENESAS_INTC_IRQPIN) += irq-renesas-intc-irqpin.o
diff --git a/drivers/irqchip/irq-atmel-aic.c b/drivers/irqchip/irq-atmel-aic.c
new file mode 100644
index 0000000..4e5feb2
--- /dev/null
+++ b/drivers/irqchip/irq-atmel-aic.c
@@ -0,0 +1,851 @@
+/*
+ * Atmel AT91 AIC (Advanced Interrupt Controller) driver
+ *
+ * Copyright (C) 2004 SAN People
+ * Copyright (C) 2004 ATMEL
+ * Copyright (C) Rick Bronson
+ * Copyright (C) 2013 Boris BREZILLON <b.brezillon@overkiz.com>
+ *
+ * This file is licensed under the terms of the GNU General Public
+ * License version 2. This program is licensed "as is" without any
+ * warranty of any kind, whether express or implied.
+ */
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/mm.h>
+#include <linux/bitmap.h>
+#include <linux/types.h>
+#include <linux/irq.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/of_irq.h>
+#include <linux/irqdomain.h>
+#include <linux/err.h>
+#include <linux/slab.h>
+#include <linux/io.h>
+
+#include <asm/exception.h>
+#include <asm/mach/irq.h>
+
+#include "irqchip.h"
+
+/* Number of irq lines managed by AIC */
+#define NR_AIC_IRQS 32
+#define NR_AIC5_IRQS 128
+
+#define AT91_AIC5_SSR 0x0
+#define AT91_AIC5_INTSEL_MSK (0x7f << 0)
+
+#define AT91_AIC_IRQ_MIN_PRIORITY 0
+#define AT91_AIC_IRQ_MAX_PRIORITY 7
+
+#define AT91_AIC_SMR(n) ((n) * 4)
+#define AT91_AIC5_SMR 0x4
+#define AT91_AIC_PRIOR (7 << 0)
+#define AT91_AIC_SRCTYPE (3 << 5)
+#define AT91_AIC_SRCTYPE_LOW (0 << 5)
+#define AT91_AIC_SRCTYPE_FALLING (1 << 5)
+#define AT91_AIC_SRCTYPE_HIGH (2 << 5)
+#define AT91_AIC_SRCTYPE_RISING (3 << 5)
+
+#define AT91_AIC_SVR(n) (0x80 + ((n) * 4))
+#define AT91_AIC5_SVR 0x8
+#define AT91_AIC_IVR 0x100
+#define AT91_AIC5_IVR 0x10
+#define AT91_AIC_FVR 0x104
+#define AT91_AIC5_FVR 0x14
+#define AT91_AIC_ISR 0x108
+#define AT91_AIC5_ISR 0x18
+#define AT91_AIC_IRQID (0x1f << 0)
+
+#define AT91_AIC_IPR 0x10c
+#define AT91_AIC5_IPR0 0x20
+#define AT91_AIC5_IPR1 0x24
+#define AT91_AIC5_IPR2 0x28
+#define AT91_AIC5_IPR3 0x2c
+#define AT91_AIC_IMR 0x110
+#define AT91_AIC5_IMR 0x30
+#define AT91_AIC_CISR 0x114
+#define AT91_AIC5_CISR 0x34
+#define AT91_AIC_NFIQ (1 << 0)
+#define AT91_AIC_NIRQ (1 << 1)
+
+#define AT91_AIC_IECR 0x120
+#define AT91_AIC5_IECR 0x40
+#define AT91_AIC_IDCR 0x124
+#define AT91_AIC5_IDCR 0x44
+#define AT91_AIC_ICCR 0x128
+#define AT91_AIC5_ICCR 0x48
+#define AT91_AIC_ISCR 0x12c
+#define AT91_AIC5_ISCR 0x4c
+#define AT91_AIC_EOICR 0x130
+#define AT91_AIC5_EOICR 0x38
+#define AT91_AIC_SPU 0x134
+#define AT91_AIC5_SPU 0x3c
+#define AT91_AIC_DCR 0x138
+#define AT91_AIC5_DCR 0x6c
+#define AT91_AIC_DCR_PROT (1 << 0)
+#define AT91_AIC_DCR_GMSK (1 << 1)
+
+#define AT91_AIC_FFER 0x140
+#define AT91_AIC5_FFER 0x50
+#define AT91_AIC_FFDR 0x144
+#define AT91_AIC5_FFDR 0x54
+#define AT91_AIC_FFSR 0x148
+#define AT91_AIC5_FFSR 0x58
+
+enum aic_mux_irq_type {
+ AIC_MUX_1REG_IRQ,
+ AIC_MUX_3REG_IRQ,
+};
+
+struct aic_mux_irq {
+ struct list_head node;
+ enum aic_mux_irq_type type;
+ void __iomem *regs;
+ u32 mask;
+};
+
+struct aic_chip_data {
+ u32 ext_irqs;
+ struct list_head mux[32];
+};
+
+static struct irq_domain *aic_domain;
+
+static asmlinkage void __exception_irq_entry
+aic_handle(struct pt_regs *regs)
+{
+ struct irq_domain_chip_generic *dgc = aic_domain->gc;
+ struct irq_chip_generic *gc = dgc->gc[0];
+ u32 irqnr;
+ u32 irqstat;
+
+ irqnr = irq_reg_readl(gc->reg_base + AT91_AIC_IVR);
+ irqstat = irq_reg_readl(gc->reg_base + AT91_AIC_ISR);
+
+ irqnr = irq_find_mapping(aic_domain, irqnr);
+
+ if (!irqstat)
+ irq_reg_writel(0, gc->reg_base + AT91_AIC_EOICR);
+ else
+ handle_IRQ(irqnr, regs);
+}
+
+static asmlinkage void __exception_irq_entry
+aic5_handle(struct pt_regs *regs)
+{
+ struct irq_domain_chip_generic *dgc = aic_domain->gc;
+ struct irq_chip_generic *gc = dgc->gc[0];
+ u32 irqnr;
+ u32 irqstat;
+
+ irqnr = irq_reg_readl(gc->reg_base + AT91_AIC5_IVR);
+ irqstat = irq_reg_readl(gc->reg_base + AT91_AIC5_ISR);
+
+ irqnr = irq_find_mapping(aic_domain, irqnr);
+
+ if (!irqstat)
+ irq_reg_writel(0, gc->reg_base + AT91_AIC5_EOICR);
+ else
+ handle_IRQ(irqnr, regs);
+}
+
+static void aic5_mask(struct irq_data *d)
+{
+ struct irq_domain *domain = d->domain;
+ struct irq_domain_chip_generic *dgc = domain->gc;
+ struct irq_chip_generic *gc = dgc->gc[0];
+
+ /* Disable interrupt on AIC5 */
+ irq_gc_lock(gc);
+ irq_reg_writel(d->hwirq, gc->reg_base + AT91_AIC5_SSR);
+ irq_reg_writel(1, gc->reg_base + AT91_AIC5_IDCR);
+ gc->mask_cache &= ~d->mask;
+ irq_gc_unlock(gc);
+}
+
+static void aic5_unmask(struct irq_data *d)
+{
+ struct irq_domain *domain = d->domain;
+ struct irq_domain_chip_generic *dgc = domain->gc;
+ struct irq_chip_generic *gc = dgc->gc[0];
+
+ /* Enable interrupt on AIC5 */
+ irq_gc_lock(gc);
+ irq_reg_writel(d->hwirq, gc->reg_base + AT91_AIC5_SSR);
+ irq_reg_writel(1, gc->reg_base + AT91_AIC5_IECR);
+ gc->mask_cache |= d->mask;
+ irq_gc_unlock(gc);
+}
+
+static int aic_retrigger(struct irq_data *d)
+{
+ struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d);
+
+ /* Enable interrupt on AIC5 */
+ irq_gc_lock(gc);
+ irq_reg_writel(d->mask, gc->reg_base + AT91_AIC_ISCR);
+ irq_gc_unlock(gc);
+
+ return 0;
+}
+
+static int aic5_retrigger(struct irq_data *d)
+{
+ struct irq_domain *domain = d->domain;
+ struct irq_domain_chip_generic *dgc = domain->gc;
+ struct irq_chip_generic *gc = dgc->gc[0];
+
+ /* Enable interrupt on AIC5 */
+ irq_gc_lock(gc);
+ irq_reg_writel(d->hwirq, gc->reg_base + AT91_AIC5_SSR);
+ irq_reg_writel(1, gc->reg_base + AT91_AIC5_ISCR);
+ irq_gc_unlock(gc);
+
+ return 0;
+}
+
+static int aic_to_srctype(struct irq_data *d, unsigned type)
+{
+ struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d);
+ struct aic_chip_data *aic = gc->private;
+
+ switch (type) {
+ case IRQ_TYPE_LEVEL_HIGH:
+ return AT91_AIC_SRCTYPE_HIGH;
+ case IRQ_TYPE_EDGE_RISING:
+ return AT91_AIC_SRCTYPE_RISING;
+ case IRQ_TYPE_LEVEL_LOW:
+ if (d->mask & aic->ext_irqs)
+ return AT91_AIC_SRCTYPE_LOW;
+ break;
+ case IRQ_TYPE_EDGE_FALLING:
+ if (d->mask & aic->ext_irqs)
+ return AT91_AIC_SRCTYPE_FALLING;
+ break;
+ default:
+ break;
+ }
+
+ return -EINVAL;
+}
+
+static int aic_set_type(struct irq_data *d, unsigned type)
+{
+ struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d);
+ unsigned int smr;
+ int srctype;
+
+ srctype = aic_to_srctype(d, type);
+ if (srctype < 0)
+ return srctype;
+
+ smr = irq_reg_readl(gc->reg_base + AT91_AIC_SMR(d->hwirq)) &
+ ~AT91_AIC_SRCTYPE;
+ irq_reg_writel(smr | srctype, gc->reg_base + AT91_AIC_SMR(d->hwirq));
+
+ return 0;
+}
+
+static int aic5_set_type(struct irq_data *d, unsigned type)
+{
+ struct irq_domain *domain = d->domain;
+ struct irq_domain_chip_generic *dgc = domain->gc;
+ struct irq_chip_generic *gc = dgc->gc[0];
+ unsigned int smr;
+ int srctype;
+
+ srctype = aic_to_srctype(d, type);
+ if (srctype < 0)
+ return srctype;
+
+ irq_gc_lock(gc);
+ irq_reg_writel(d->hwirq, gc->reg_base + AT91_AIC5_SSR);
+ smr = irq_reg_readl(gc->reg_base + AT91_AIC5_SMR) & ~AT91_AIC_SRCTYPE;
+ irq_reg_writel(smr | srctype, gc->reg_base + AT91_AIC5_SMR);
+ irq_gc_unlock(gc);
+
+ return 0;
+}
+
+static void aic_mux_disable_irqs(struct list_head *mux_list)
+{
+ struct aic_mux_irq *irq;
+
+ list_for_each_entry(irq, mux_list, node) {
+ if (irq->type == AIC_MUX_1REG_IRQ)
+ writel(readl(irq->regs) & ~irq->mask, irq->regs);
+ else
+ writel(irq->mask, irq->regs);
+ }
+}
+
+static void aic_shutdown(struct irq_data *d)
+{
+ struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d);
+ struct irq_chip_type *ct = irq_data_get_chip_type(d);
+ struct aic_chip_data *aic = gc->private;
+ int idx = d->hwirq % 32;
+
+ aic_mux_disable_irqs(&aic->mux[idx]);
+ ct->chip.irq_mask(d);
+}
+
+#ifdef CONFIG_PM
+static void aic_suspend(struct irq_data *d)
+{
+ struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d);
+
+ irq_gc_lock(gc);
+ irq_reg_writel(gc->mask_cache, gc->reg_base + AT91_AIC_IDCR);
+ irq_reg_writel(gc->wake_active, gc->reg_base + AT91_AIC_IECR);
+ irq_gc_unlock(gc);
+}
+
+static void aic5_suspend(struct irq_data *d)
+{
+ struct irq_domain *domain = d->domain;
+ struct irq_domain_chip_generic *dgc = domain->gc;
+ struct irq_chip_generic *bgc = dgc->gc[0];
+ struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d);
+ int i;
+ u32 mask;
+
+ irq_gc_lock(bgc);
+ for (i = 0; i < dgc->irqs_per_chip; i++) {
+ mask = 1 << i;
+ if ((mask & gc->mask_cache) == (mask & gc->wake_active))
+ continue;
+
+ irq_reg_writel(i + gc->irq_base,
+ bgc->reg_base + AT91_AIC5_SSR);
+ if (mask & gc->wake_active)
+ irq_reg_writel(1, bgc->reg_base + AT91_AIC5_IECR);
+ else
+ irq_reg_writel(1, bgc->reg_base + AT91_AIC5_IDCR);
+ }
+ irq_gc_unlock(bgc);
+}
+
+static void aic_resume(struct irq_data *d)
+{
+ struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d);
+
+ irq_gc_lock(gc);
+ irq_reg_writel(gc->wake_active, gc->reg_base + AT91_AIC_IDCR);
+ irq_reg_writel(gc->mask_cache, gc->reg_base + AT91_AIC_IECR);
+ irq_gc_unlock(gc);
+}
+
+static void aic5_resume(struct irq_data *d)
+{
+ struct irq_domain *domain = d->domain;
+ struct irq_domain_chip_generic *dgc = domain->gc;
+ struct irq_chip_generic *bgc = dgc->gc[0];
+ struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d);
+ int i;
+ u32 mask;
+
+ irq_gc_lock(bgc);
+ for (i = 0; i < dgc->irqs_per_chip; i++) {
+ mask = 1 << i;
+ if ((mask & gc->mask_cache) == (mask & gc->wake_active))
+ continue;
+
+ irq_reg_writel(i + gc->irq_base,
+ bgc->reg_base + AT91_AIC5_SSR);
+ if (mask & gc->mask_cache)
+ irq_reg_writel(1, bgc->reg_base + AT91_AIC5_IECR);
+ else
+ irq_reg_writel(1, bgc->reg_base + AT91_AIC5_IDCR);
+ }
+ irq_gc_unlock(bgc);
+}
+
+static void aic_pm_shutdown(struct irq_data *d)
+{
+ struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d);
+
+ irq_gc_lock(gc);
+ irq_reg_writel(0xffffffff, gc->reg_base + AT91_AIC_IDCR);
+ irq_reg_writel(0xffffffff, gc->reg_base + AT91_AIC_ICCR);
+ irq_gc_unlock(gc);
+}
+
+static void aic5_pm_shutdown(struct irq_data *d)
+{
+ struct irq_domain *domain = d->domain;
+ struct irq_domain_chip_generic *dgc = domain->gc;
+ struct irq_chip_generic *bgc = dgc->gc[0];
+ struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d);
+ int i;
+
+ irq_gc_lock(bgc);
+ for (i = 0; i < dgc->irqs_per_chip; i++) {
+ irq_reg_writel(i + gc->irq_base,
+ bgc->reg_base + AT91_AIC5_SSR);
+ irq_reg_writel(1, bgc->reg_base + AT91_AIC5_IDCR);
+ irq_reg_writel(1, bgc->reg_base + AT91_AIC5_ICCR);
+ }
+ irq_gc_unlock(bgc);
+}
+#else
+#define aic_suspend NULL
+#define aic5_suspend NULL
+#define aic_resume NULL
+#define aic5_resume NULL
+#define aic_pm_shutdown NULL
+#define aic5_pm_shutdown NULL
+#endif /* CONFIG_PM */
+
+static void __init aic_mux_hw_init(struct irq_domain *domain)
+{
+ struct aic_chip_data *aic = domain->host_data;
+ int i;
+
+ for (i = 0; i < domain->revmap_size; i++)
+ aic_mux_disable_irqs(&aic[i / 32].mux[i % 32]);
+}
+
+static void __init aic_hw_init(struct irq_domain *domain)
+{
+ struct irq_chip_generic *gc = irq_get_domain_generic_chip(domain, 0);
+ int i;
+
+ /*
+ * Perform 8 End Of Interrupt Command to make sure AIC
+ * will not Lock out nIRQ
+ */
+ for (i = 0; i < 8; i++)
+ irq_reg_writel(0, gc->reg_base + AT91_AIC_EOICR);
+
+ /*
+ * Spurious Interrupt ID in Spurious Vector Register.
+ * When there is no current interrupt, the IRQ Vector Register
+ * reads the value stored in AIC_SPU
+ */
+ irq_reg_writel(0xffffffff, gc->reg_base + AT91_AIC_SPU);
+
+ /* No debugging in AIC: Debug (Protect) Control Register */
+ irq_reg_writel(0, gc->reg_base + AT91_AIC_DCR);
+
+ /* Disable and clear all interrupts initially */
+ irq_reg_writel(0xffffffff, gc->reg_base + AT91_AIC_IDCR);
+ irq_reg_writel(0xffffffff, gc->reg_base + AT91_AIC_ICCR);
+
+ for (i = 0; i < 32; i++)
+ irq_reg_writel(i, gc->reg_base + AT91_AIC_SVR(i));
+
+ aic_mux_hw_init(domain);
+}
+
+static void __init aic5_hw_init(struct irq_domain *domain)
+{
+ struct irq_chip_generic *gc = irq_get_domain_generic_chip(domain, 0);
+ int i;
+
+ /*
+ * Perform 8 End Of Interrupt Command to make sure AIC
+ * will not Lock out nIRQ
+ */
+ for (i = 0; i < 8; i++)
+ irq_reg_writel(0, gc->reg_base + AT91_AIC5_EOICR);
+
+ /*
+ * Spurious Interrupt ID in Spurious Vector Register.
+ * When there is no current interrupt, the IRQ Vector Register
+ * reads the value stored in AIC_SPU
+ */
+ irq_reg_writel(0xffffffff, gc->reg_base + AT91_AIC5_SPU);
+
+ /* No debugging in AIC: Debug (Protect) Control Register */
+ irq_reg_writel(0, gc->reg_base + AT91_AIC5_DCR);
+
+ /* Disable and clear all interrupts initially */
+ for (i = 0; i < domain->revmap_size; i++) {
+ irq_reg_writel(i, gc->reg_base + AT91_AIC5_SSR);
+ irq_reg_writel(i, gc->reg_base + AT91_AIC5_SVR);
+ irq_reg_writel(1, gc->reg_base + AT91_AIC5_IDCR);
+ irq_reg_writel(1, gc->reg_base + AT91_AIC5_ICCR);
+ }
+
+ aic_mux_hw_init(domain);
+}
+
+static int at91_aic_common_irq_domain_xlate(struct irq_domain *d,
+ struct device_node *ctrlr,
+ const u32 *intspec,
+ unsigned int intsize,
+ irq_hw_number_t *out_hwirq,
+ unsigned int *out_type)
+{
+ if (WARN_ON(intsize < 3))
+ return -EINVAL;
+
+ if (WARN_ON((intspec[2] < AT91_AIC_IRQ_MIN_PRIORITY) ||
+ (intspec[2] > AT91_AIC_IRQ_MAX_PRIORITY)))
+ return -EINVAL;
+
+ *out_hwirq = intspec[0];
+ *out_type = intspec[1] & IRQ_TYPE_SENSE_MASK;
+
+ return 0;
+}
+
+static int aic_irq_domain_xlate(struct irq_domain *d,
+ struct device_node *ctrlr,
+ const u32 *intspec, unsigned int intsize,
+ irq_hw_number_t *out_hwirq,
+ unsigned int *out_type)
+{
+ struct irq_domain_chip_generic *dgc = d->gc;
+ struct irq_chip_generic *gc;
+ unsigned long smr;
+ int idx;
+ int ret;
+
+ if (!dgc)
+ return -EINVAL;
+
+ ret = at91_aic_common_irq_domain_xlate(d, ctrlr, intspec, intsize,
+ out_hwirq, out_type);
+ if (ret)
+ return ret;
+
+ idx = intspec[0] / dgc->irqs_per_chip;
+ if (idx >= dgc->num_chips)
+ return -EINVAL;
+
+ gc = dgc->gc[idx];
+
+ irq_gc_lock(gc);
+ smr = irq_reg_readl(gc->reg_base + AT91_AIC5_SMR) & ~AT91_AIC_PRIOR;
+ irq_reg_writel(intspec[2] | smr, gc->reg_base + AT91_AIC5_SMR);
+ irq_gc_unlock(gc);
+
+ return 0;
+}
+
+static const struct irq_domain_ops aic_irq_ops = {
+ .map = irq_map_generic_chip,
+ .xlate = aic_irq_domain_xlate,
+};
+
+static int aic5_irq_domain_xlate(struct irq_domain *d,
+ struct device_node *ctrlr,
+ const u32 *intspec, unsigned int intsize,
+ irq_hw_number_t *out_hwirq,
+ unsigned int *out_type)
+{
+ struct irq_domain_chip_generic *dgc = d->gc;
+ struct irq_chip_generic *gc;
+ unsigned long smr;
+ int ret;
+
+ if (!dgc)
+ return -EINVAL;
+
+ ret = at91_aic_common_irq_domain_xlate(d, ctrlr, intspec, intsize,
+ out_hwirq, out_type);
+ if (ret)
+ return ret;
+
+ gc = dgc->gc[0];
+
+ irq_gc_lock(gc);
+ irq_reg_writel(*out_hwirq, gc->reg_base + AT91_AIC5_SSR);
+ smr = irq_reg_readl(gc->reg_base + AT91_AIC5_SMR) & ~AT91_AIC_PRIOR;
+ irq_reg_writel(intspec[2] | smr, gc->reg_base + AT91_AIC5_SMR);
+ irq_gc_unlock(gc);
+
+ return 0;
+}
+
+static const struct irq_domain_ops aic5_irq_ops = {
+ .map = irq_map_generic_chip,
+ .xlate = aic5_irq_domain_xlate,
+};
+
+static struct aic_mux_irq *aic_mux_irq_of_init(struct device_node *node)
+{
+ struct aic_mux_irq *irq;
+ void __iomem *regs;
+ u32 mask;
+ int ret;
+
+ ret = of_property_read_u32(node, "atmel,aic-mux-reg-mask", &mask);
+ if (ret)
+ return ERR_PTR(-EINVAL);
+
+ regs = of_iomap(node, 0);
+ if (!regs)
+ return ERR_PTR(-EINVAL);
+
+ irq = kzalloc(sizeof(*irq), GFP_KERNEL);
+ if (!irq)
+ return ERR_PTR(-ENOMEM);
+
+ INIT_LIST_HEAD(&irq->node);
+
+ irq->regs = regs;
+ irq->mask = mask;
+
+ return irq;
+}
+
+static struct aic_mux_irq *aic_mux_1reg_irq_of_init(struct device_node *node)
+{
+ struct aic_mux_irq *irq;
+
+ irq = aic_mux_irq_of_init(node);
+ if (!IS_ERR(irq))
+ irq->type = AIC_MUX_1REG_IRQ;
+
+ return irq;
+}
+
+static struct aic_mux_irq *aic_mux_3reg_irq_of_init(struct device_node *node)
+{
+ struct aic_mux_irq *irq;
+
+ irq = aic_mux_irq_of_init(node);
+ if (!IS_ERR(irq))
+ irq->type = AIC_MUX_3REG_IRQ;
+
+ return irq;
+}
+
+static const struct of_device_id aic_mux_irq_of_match[] __initconst = {
+ {
+ .compatible = "atmel,aic-mux-1reg-irq",
+ .data = aic_mux_1reg_irq_of_init,
+ },
+ {
+ .compatible = "atmel,aic-mux-3reg-irq",
+ .data = aic_mux_3reg_irq_of_init,
+ },
+ { /*sentinel*/ }
+};
+
+static void __init aic_ext_irq_of_init(struct irq_domain *domain)
+{
+ struct device_node *node = domain->of_node;
+ struct irq_chip_generic *gc;
+ struct aic_chip_data *aic;
+ struct property *prop;
+ const __be32 *p;
+ u32 hwirq;
+
+ gc = irq_get_domain_generic_chip(aic_domain, 0);
+
+ aic = gc->private;
+ aic->ext_irqs |= 1;
+
+ of_property_for_each_u32(node, "atmel,external-irqs", prop, p, hwirq) {
+ gc = irq_get_domain_generic_chip(aic_domain, hwirq);
+ if (!gc) {
+ pr_warn("AIC: external irq %d >= %d skip it\n",
+ hwirq, domain->revmap_size);
+ continue;
+ }
+
+ aic = gc->private;
+ aic->ext_irqs |= (1 << (hwirq % 32));
+ }
+}
+
+static void __init aic_mux_of_init(struct irq_domain *domain)
+{
+ struct device_node *node = domain->of_node;
+ struct device_node *mux_node;
+ const struct of_device_id *match;
+ struct aic_mux_irq *irq;
+ struct aic_mux_irq * (*mux_of_init)(struct device_node *);
+ struct irq_chip_generic *gc;
+ struct aic_chip_data *aic;
+ struct list_head *mux_list;
+ u32 hwirq;
+
+ for_each_child_of_node(node, mux_node) {
+ match = of_match_node(aic_mux_irq_of_match, mux_node);
+ if (!match)
+ continue;
+
+ if (of_property_read_u32(mux_node, "reg", &hwirq)) {
+ pr_warn("AIC: missing reg property in mux definition\n");
+ continue;
+ }
+
+ gc = irq_get_domain_generic_chip(aic_domain, hwirq);
+ if (!gc) {
+ pr_warn("AIC: irq %d >= %d skip it\n",
+ hwirq, domain->revmap_size);
+ continue;
+ }
+
+ aic = gc->private;
+ mux_list = &aic->mux[hwirq % 32];
+
+ mux_of_init = match->data;
+
+ irq = mux_of_init(mux_node);
+ if (IS_ERR(irq))
+ continue;
+
+ list_add_tail(&irq->node, mux_list);
+ }
+}
+
+static int __init aic_common_of_init(struct device_node *node,
+ const struct irq_domain_ops *ops,
+ const char *name, int maxirq)
+{
+ struct irq_chip_generic *gc;
+ struct aic_chip_data *aic;
+ void __iomem *reg_base;
+ int nirqs = maxirq;
+ int nchips;
+ int ret;
+ int i;
+ int j;
+ u32 tmp;
+
+ if (aic_domain)
+ return -EEXIST;
+
+ if (of_get_property(node, "atmel,aic-irq-mapping", &tmp))
+ nirqs = tmp * BITS_PER_BYTE;
+
+ nchips = DIV_ROUND_UP(nirqs, 32);
+
+ reg_base = of_iomap(node, 0);
+ if (!reg_base)
+ return -ENOMEM;
+
+ aic = kzalloc(nchips * sizeof(*aic), GFP_KERNEL);
+ if (!aic) {
+ ret = -ENOMEM;
+ goto err_iounmap;
+ }
+
+ aic_domain = irq_domain_add_linear(node, nirqs, ops, aic);
+ if (!aic_domain) {
+ ret = -ENOMEM;
+ goto err_free_aic;
+ }
+
+ ret = irq_alloc_domain_generic_chips(aic_domain, 32, 1, name,
+ handle_level_irq, 0, 0,
+ IRQCHIP_SKIP_SET_WAKE);
+ if (ret)
+ goto err_domain_remove;
+
+ for (i = 0; i < nchips; i++) {
+ gc = irq_get_domain_generic_chip(aic_domain, i * 32);
+
+ gc->reg_base = reg_base;
+
+ if (!of_property_read_u32_index(node, "atmel,irq-mapping",
+ i, &tmp)) {
+ gc->unused = ~tmp;
+ gc->wake_enabled = tmp;
+ } else {
+ gc->unused = 0;
+ gc->wake_enabled = ~0;
+ }
+
+ gc->chip_types[0].type = IRQ_TYPE_SENSE_MASK;
+ gc->chip_types[0].handler = handle_fasteoi_irq;
+ gc->chip_types[0].chip.irq_eoi = irq_gc_eoi;
+ gc->chip_types[0].chip.irq_set_wake = irq_gc_set_wake;
+ gc->chip_types[0].chip.irq_shutdown = aic_shutdown;
+
+ for (j = 0; j < 32; j++)
+ INIT_LIST_HEAD(&aic[i].mux[j]);
+
+ gc->private = &aic[i];
+ }
+
+ aic_mux_of_init(aic_domain);
+ aic_ext_irq_of_init(aic_domain);
+
+ return 0;
+
+err_domain_remove:
+ irq_domain_remove(aic_domain);
+
+err_free_aic:
+ kfree(aic);
+
+err_iounmap:
+ iounmap(reg_base);
+
+ return ret;
+}
+
+static int __init aic_of_init(struct device_node *node,
+ struct device_node *parent)
+{
+ struct irq_chip_generic *gc;
+ int ret;
+
+ ret = aic_common_of_init(node, &aic_irq_ops, "atmel-aic",
+ NR_AIC_IRQS);
+ if (ret)
+ return ret;
+
+ gc = irq_get_domain_generic_chip(aic_domain, 0);
+
+ gc->chip_types[0].regs.eoi = AT91_AIC_EOICR;
+ gc->chip_types[0].regs.enable = AT91_AIC_IECR;
+ gc->chip_types[0].regs.disable = AT91_AIC_IDCR;
+ gc->chip_types[0].chip.irq_mask = irq_gc_mask_disable_reg;
+ gc->chip_types[0].chip.irq_unmask = irq_gc_unmask_enable_reg;
+ gc->chip_types[0].chip.irq_retrigger = aic_retrigger;
+ gc->chip_types[0].chip.irq_set_type = aic_set_type;
+ gc->chip_types[0].chip.irq_suspend = aic_suspend;
+ gc->chip_types[0].chip.irq_resume = aic_resume;
+ gc->chip_types[0].chip.irq_pm_shutdown = aic_pm_shutdown;
+
+ aic_hw_init(aic_domain);
+ set_handle_irq(aic_handle);
+
+ return 0;
+}
+IRQCHIP_DECLARE(at91_aic, "atmel,at91rm9200-aic", aic_of_init);
+
+static int __init aic5_of_init(struct device_node *node,
+ struct device_node *parent)
+{
+ struct irq_chip_generic *gc;
+ int ret;
+ int i;
+ int nchips;
+
+ ret = aic_common_of_init(node, &aic5_irq_ops, "atmel-aic5",
+ NR_AIC5_IRQS);
+ if (ret)
+ return ret;
+
+ nchips = aic_domain->revmap_size / 32;
+ for (i = 0; i < nchips; i++) {
+ gc = irq_get_domain_generic_chip(aic_domain, i * 32);
+
+ gc->chip_types[0].regs.eoi = AT91_AIC5_EOICR;
+ gc->chip_types[0].chip.irq_mask = aic5_mask;
+ gc->chip_types[0].chip.irq_unmask = aic5_unmask;
+ gc->chip_types[0].chip.irq_retrigger = aic5_retrigger;
+ gc->chip_types[0].chip.irq_set_type = aic5_set_type;
+ gc->chip_types[0].chip.irq_suspend = aic5_suspend;
+ gc->chip_types[0].chip.irq_resume = aic5_resume;
+ gc->chip_types[0].chip.irq_pm_shutdown = aic5_pm_shutdown;
+ }
+
+ aic5_hw_init(aic_domain);
+ set_handle_irq(aic5_handle);
+
+ return 0;
+}
+IRQCHIP_DECLARE(at91_aic5, "atmel,sama5d3-aic", aic5_of_init);
--
1.7.9.5
^ permalink raw reply related [flat|nested] 19+ messages in thread
* [RFC PATCH v2 03/10] ARM: at91: introduce OLD_IRQ_AT91 Kconfig option
2014-03-28 17:58 [RFC PATCH v2 00/10] ARM: at91: move aic driver to drivers/irqchips Boris BREZILLON
2014-03-28 17:58 ` [RFC PATCH v2 01/10] genirq: generic chip: export irq_map_generic_chip function Boris BREZILLON
2014-03-28 17:59 ` [RFC PATCH v2 02/10] irqchip: atmel-aic: add new atmel AIC driver Boris BREZILLON
@ 2014-03-28 17:59 ` Boris BREZILLON
2014-03-29 9:06 ` Thomas Petazzoni
2014-03-28 17:59 ` [RFC PATCH v2 04/10] ARM: at91: enclose at91_aic_xx calls in IS_ENABLED(CONFIG_OLD_IRQ_AT91) blocks Boris BREZILLON
` (6 subsequent siblings)
9 siblings, 1 reply; 19+ messages in thread
From: Boris BREZILLON @ 2014-03-28 17:59 UTC (permalink / raw)
To: Rob Landley, Nicolas Ferre, Jean-Christophe Plagniol-Villard,
Thomas Gleixner
Cc: devicetree, linux-doc, linux-kernel, linux-arm-kernel,
Boris BREZILLON
Introduce a new Kconfig option OLD_IRQ_AT91 to prepare migration to the new
AIC driver.
Enable this option for all supported at91 SoCs (both dt and non-dt boards).
Signed-off-by: Boris BREZILLON <b.brezillon.dev@gmail.com>
---
arch/arm/mach-at91/Kconfig | 7 +++++++
arch/arm/mach-at91/Kconfig.non_dt | 7 +++++++
arch/arm/mach-at91/Makefile | 3 ++-
3 files changed, 16 insertions(+), 1 deletion(-)
diff --git a/arch/arm/mach-at91/Kconfig b/arch/arm/mach-at91/Kconfig
index 4f0e800..4f0b3e0 100644
--- a/arch/arm/mach-at91/Kconfig
+++ b/arch/arm/mach-at91/Kconfig
@@ -28,6 +28,10 @@ config OLD_CLK_AT91
bool
default AT91_PMC_UNIT && AT91_USE_OLD_CLK
+config OLD_IRQ_AT91
+ bool
+ default false
+
config AT91_SAM9_ALT_RESET
bool
default !ARCH_AT91X40
@@ -189,6 +193,7 @@ config MACH_AT91RM9200_DT
bool "Atmel AT91RM9200 Evaluation Kits with device-tree support"
depends on SOC_AT91RM9200
select USE_OF
+ select OLD_IRQ_AT91
help
Select this if you want to experiment device-tree with
an Atmel RM9200 Evaluation Kit.
@@ -197,6 +202,7 @@ config MACH_AT91SAM9_DT
bool "Atmel AT91SAM Evaluation Kits with device-tree support"
depends on SOC_AT91SAM9
select USE_OF
+ select OLD_IRQ_AT91
help
Select this if you want to experiment device-tree with
an Atmel Evaluation Kit.
@@ -205,6 +211,7 @@ config MACH_SAMA5_DT
bool "Atmel SAMA5 Evaluation Kits with device-tree support"
depends on SOC_SAMA5
select USE_OF
+ select OLD_IRQ_AT91
select PHYLIB if NETDEVICES
help
Select this if you want to experiment device-tree with
diff --git a/arch/arm/mach-at91/Kconfig.non_dt b/arch/arm/mach-at91/Kconfig.non_dt
index 1f73e9b..75b582e 100644
--- a/arch/arm/mach-at91/Kconfig.non_dt
+++ b/arch/arm/mach-at91/Kconfig.non_dt
@@ -13,31 +13,37 @@ config ARCH_AT91RM9200
bool "AT91RM9200"
select SOC_AT91RM9200
select AT91_USE_OLD_CLK
+ select OLD_IRQ_AT91
config ARCH_AT91SAM9260
bool "AT91SAM9260 or AT91SAM9XE or AT91SAM9G20"
select SOC_AT91SAM9260
select AT91_USE_OLD_CLK
+ select OLD_IRQ_AT91
config ARCH_AT91SAM9261
bool "AT91SAM9261 or AT91SAM9G10"
select SOC_AT91SAM9261
select AT91_USE_OLD_CLK
+ select OLD_IRQ_AT91
config ARCH_AT91SAM9263
bool "AT91SAM9263"
select SOC_AT91SAM9263
select AT91_USE_OLD_CLK
+ select OLD_IRQ_AT91
config ARCH_AT91SAM9RL
bool "AT91SAM9RL"
select SOC_AT91SAM9RL
select AT91_USE_OLD_CLK
+ select OLD_IRQ_AT91
config ARCH_AT91SAM9G45
bool "AT91SAM9G45"
select SOC_AT91SAM9G45
select AT91_USE_OLD_CLK
+ select OLD_IRQ_AT91
config ARCH_AT91X40
bool "AT91x40"
@@ -45,6 +51,7 @@ config ARCH_AT91X40
select ARCH_USES_GETTIMEOFFSET
select MULTI_IRQ_HANDLER
select SPARSE_IRQ
+ select OLD_IRQ_AT91
endchoice
diff --git a/arch/arm/mach-at91/Makefile b/arch/arm/mach-at91/Makefile
index 78e9cec..d972fd6 100644
--- a/arch/arm/mach-at91/Makefile
+++ b/arch/arm/mach-at91/Makefile
@@ -2,11 +2,12 @@
# Makefile for the linux kernel.
#
-obj-y := irq.o gpio.o setup.o sysirq_mask.o
+obj-y := gpio.o setup.o sysirq_mask.o
obj-m :=
obj-n :=
obj- :=
+obj-$(CONFIG_OLD_IRQ_AT91) += irq.o
obj-$(CONFIG_OLD_CLK_AT91) += clock.o
obj-$(CONFIG_AT91_SAM9_ALT_RESET) += at91sam9_alt_reset.o
obj-$(CONFIG_AT91_SAM9G45_RESET) += at91sam9g45_reset.o
--
1.7.9.5
^ permalink raw reply related [flat|nested] 19+ messages in thread
* [RFC PATCH v2 04/10] ARM: at91: enclose at91_aic_xx calls in IS_ENABLED(CONFIG_OLD_IRQ_AT91) blocks
2014-03-28 17:58 [RFC PATCH v2 00/10] ARM: at91: move aic driver to drivers/irqchips Boris BREZILLON
` (2 preceding siblings ...)
2014-03-28 17:59 ` [RFC PATCH v2 03/10] ARM: at91: introduce OLD_IRQ_AT91 Kconfig option Boris BREZILLON
@ 2014-03-28 17:59 ` Boris BREZILLON
2014-03-28 17:59 ` [RFC PATCH v2 05/10] ARM: at91: make use of the new AIC driver for dt enabled boards Boris BREZILLON
` (5 subsequent siblings)
9 siblings, 0 replies; 19+ messages in thread
From: Boris BREZILLON @ 2014-03-28 17:59 UTC (permalink / raw)
To: Rob Landley, Nicolas Ferre, Jean-Christophe Plagniol-Villard,
Thomas Gleixner
Cc: devicetree, linux-doc, linux-kernel, linux-arm-kernel,
Boris BREZILLON
Enclose at91_aic_xx calls in IS_ENABLED(CONFIG_OLD_IRQ_AT91) blocks in
order to prepare the migration to the new AIC driver.
In the new AIC driver the suspend/resume functions are called by the
generic irq framework and are no longer needed in the PM specific code.
Moreover, the new AIC driver no longer exposes the at91_aic_base variable
which is used by the at91_aic_read functions.
Signed-off-by: Boris BREZILLON <b.brezillon.dev@gmail.com>
---
arch/arm/mach-at91/pm.c | 32 ++++++++++++++++++++------------
arch/arm/mach-at91/setup.c | 3 ++-
2 files changed, 22 insertions(+), 13 deletions(-)
diff --git a/arch/arm/mach-at91/pm.c b/arch/arm/mach-at91/pm.c
index 590b52d..b9f4c5c 100644
--- a/arch/arm/mach-at91/pm.c
+++ b/arch/arm/mach-at91/pm.c
@@ -204,16 +204,19 @@ static int at91_pm_enter(suspend_state_t state)
at91_pinctrl_gpio_suspend();
else
at91_gpio_suspend();
- at91_irq_suspend();
- pr_debug("AT91: PM - wake mask %08x, pm state %d\n",
- /* remember all the always-wake irqs */
- (at91_pmc_read(AT91_PMC_PCSR)
- | (1 << AT91_ID_FIQ)
- | (1 << AT91_ID_SYS)
- | (at91_get_extern_irq()))
- & at91_aic_read(AT91_AIC_IMR),
- state);
+ if (IS_ENABLED(CONFIG_OLD_IRQ_AT91) && at91_aic_base) {
+ at91_irq_suspend();
+
+ pr_debug("AT91: PM - wake mask %08x, pm state %d\n",
+ /* remember all the always-wake irqs */
+ (at91_pmc_read(AT91_PMC_PCSR)
+ | (1 << AT91_ID_FIQ)
+ | (1 << AT91_ID_SYS)
+ | (at91_get_extern_irq()))
+ & at91_aic_read(AT91_AIC_IMR),
+ state);
+ }
switch (state) {
/*
@@ -278,12 +281,17 @@ static int at91_pm_enter(suspend_state_t state)
goto error;
}
- pr_debug("AT91: PM - wakeup %08x\n",
- at91_aic_read(AT91_AIC_IPR) & at91_aic_read(AT91_AIC_IMR));
+ if (IS_ENABLED(CONFIG_OLD_IRQ_AT91) && at91_aic_base)
+ pr_debug("AT91: PM - wakeup %08x\n",
+ at91_aic_read(AT91_AIC_IPR) &
+ at91_aic_read(AT91_AIC_IMR));
error:
target_state = PM_SUSPEND_ON;
- at91_irq_resume();
+
+ if (IS_ENABLED(CONFIG_OLD_IRQ_AT91) && at91_aic_base)
+ at91_irq_resume();
+
if (of_have_populated_dt())
at91_pinctrl_gpio_resume();
else
diff --git a/arch/arm/mach-at91/setup.c b/arch/arm/mach-at91/setup.c
index f7ca97b..1d8a6c8 100644
--- a/arch/arm/mach-at91/setup.c
+++ b/arch/arm/mach-at91/setup.c
@@ -49,7 +49,8 @@ void __init at91_init_irq_default(void)
void __init at91_init_interrupts(unsigned int *priority)
{
/* Initialize the AIC interrupt controller */
- at91_aic_init(priority, at91_boot_soc.extern_irq);
+ if (IS_ENABLED(CONFIG_OLD_IRQ_AT91))
+ at91_aic_init(priority, at91_boot_soc.extern_irq);
/* Enable GPIO interrupts */
at91_gpio_irq_setup();
--
1.7.9.5
^ permalink raw reply related [flat|nested] 19+ messages in thread
* [RFC PATCH v2 05/10] ARM: at91: make use of the new AIC driver for dt enabled boards
2014-03-28 17:58 [RFC PATCH v2 00/10] ARM: at91: move aic driver to drivers/irqchips Boris BREZILLON
` (3 preceding siblings ...)
2014-03-28 17:59 ` [RFC PATCH v2 04/10] ARM: at91: enclose at91_aic_xx calls in IS_ENABLED(CONFIG_OLD_IRQ_AT91) blocks Boris BREZILLON
@ 2014-03-28 17:59 ` Boris BREZILLON
2014-03-29 9:07 ` Thomas Petazzoni
2014-03-28 17:59 ` [RFC PATCH v2 06/10] irqchip: atmel-aic: move binding doc to interrupt-controller directory Boris BREZILLON
` (4 subsequent siblings)
9 siblings, 1 reply; 19+ messages in thread
From: Boris BREZILLON @ 2014-03-28 17:59 UTC (permalink / raw)
To: Rob Landley, Nicolas Ferre, Jean-Christophe Plagniol-Villard,
Thomas Gleixner
Cc: devicetree, Boris BREZILLON, linux-kernel, linux-arm-kernel,
linux-doc
Add a new Kconfig option for the new AIC driver
(drivers/irqchip/irq-atmel-aic.c) and remove selection of OLD_IRQ_AT91
when selecting dt boards.
Remove specific irq init code in all dt board files: this init procedure
is automatically handled in of_irq_init which is called by the arm irq core
code and is in charge of calling the appropriate aic init functions.
Signed-off-by: Boris BREZILLON <b.brezillon.dev@gmail.com>
---
arch/arm/mach-at91/Kconfig | 10 +++++++---
arch/arm/mach-at91/board-dt-rm9200.c | 13 -------------
arch/arm/mach-at91/board-dt-sam9.c | 14 --------------
arch/arm/mach-at91/board-dt-sama5.c | 13 -------------
4 files changed, 7 insertions(+), 43 deletions(-)
diff --git a/arch/arm/mach-at91/Kconfig b/arch/arm/mach-at91/Kconfig
index 4f0b3e0..7e75c4d 100644
--- a/arch/arm/mach-at91/Kconfig
+++ b/arch/arm/mach-at91/Kconfig
@@ -32,6 +32,13 @@ config OLD_IRQ_AT91
bool
default false
+config ATMEL_AIC_IRQ
+ bool
+ default USE_OF
+ select GENERIC_IRQ_CHIP
+ select IRQ_DOMAIN
+ select MULTI_IRQ_HANDLER
+
config AT91_SAM9_ALT_RESET
bool
default !ARCH_AT91X40
@@ -193,7 +200,6 @@ config MACH_AT91RM9200_DT
bool "Atmel AT91RM9200 Evaluation Kits with device-tree support"
depends on SOC_AT91RM9200
select USE_OF
- select OLD_IRQ_AT91
help
Select this if you want to experiment device-tree with
an Atmel RM9200 Evaluation Kit.
@@ -202,7 +208,6 @@ config MACH_AT91SAM9_DT
bool "Atmel AT91SAM Evaluation Kits with device-tree support"
depends on SOC_AT91SAM9
select USE_OF
- select OLD_IRQ_AT91
help
Select this if you want to experiment device-tree with
an Atmel Evaluation Kit.
@@ -211,7 +216,6 @@ config MACH_SAMA5_DT
bool "Atmel SAMA5 Evaluation Kits with device-tree support"
depends on SOC_SAMA5
select USE_OF
- select OLD_IRQ_AT91
select PHYLIB if NETDEVICES
help
Select this if you want to experiment device-tree with
diff --git a/arch/arm/mach-at91/board-dt-rm9200.c b/arch/arm/mach-at91/board-dt-rm9200.c
index 3a185fa..61ea214 100644
--- a/arch/arm/mach-at91/board-dt-rm9200.c
+++ b/arch/arm/mach-at91/board-dt-rm9200.c
@@ -24,17 +24,6 @@
#include "at91_aic.h"
#include "generic.h"
-
-static const struct of_device_id irq_of_match[] __initconst = {
- { .compatible = "atmel,at91rm9200-aic", .data = at91_aic_of_init },
- { /*sentinel*/ }
-};
-
-static void __init at91rm9200_dt_init_irq(void)
-{
- of_irq_init(irq_of_match);
-}
-
static const char *at91rm9200_dt_board_compat[] __initdata = {
"atmel,at91rm9200",
NULL
@@ -43,8 +32,6 @@ static const char *at91rm9200_dt_board_compat[] __initdata = {
DT_MACHINE_START(at91rm9200_dt, "Atmel AT91RM9200 (Device Tree)")
.init_time = at91rm9200_timer_init,
.map_io = at91_map_io,
- .handle_irq = at91_aic_handle_irq,
.init_early = at91rm9200_dt_initialize,
- .init_irq = at91rm9200_dt_init_irq,
.dt_compat = at91rm9200_dt_board_compat,
MACHINE_END
diff --git a/arch/arm/mach-at91/board-dt-sam9.c b/arch/arm/mach-at91/board-dt-sam9.c
index 3dab868..d4073c0 100644
--- a/arch/arm/mach-at91/board-dt-sam9.c
+++ b/arch/arm/mach-at91/board-dt-sam9.c
@@ -20,22 +20,10 @@
#include <asm/mach/map.h>
#include <asm/mach/irq.h>
-#include "at91_aic.h"
#include "board.h"
#include "generic.h"
-static const struct of_device_id irq_of_match[] __initconst = {
-
- { .compatible = "atmel,at91rm9200-aic", .data = at91_aic_of_init },
- { /*sentinel*/ }
-};
-
-static void __init at91_dt_init_irq(void)
-{
- of_irq_init(irq_of_match);
-}
-
static const char *at91_dt_board_compat[] __initdata = {
"atmel,at91sam9",
NULL
@@ -45,8 +33,6 @@ DT_MACHINE_START(at91sam_dt, "Atmel AT91SAM (Device Tree)")
/* Maintainer: Atmel */
.init_time = at91sam926x_pit_init,
.map_io = at91_map_io,
- .handle_irq = at91_aic_handle_irq,
.init_early = at91_dt_initialize,
- .init_irq = at91_dt_init_irq,
.dt_compat = at91_dt_board_compat,
MACHINE_END
diff --git a/arch/arm/mach-at91/board-dt-sama5.c b/arch/arm/mach-at91/board-dt-sama5.c
index 075ec05..d6fe04b 100644
--- a/arch/arm/mach-at91/board-dt-sama5.c
+++ b/arch/arm/mach-at91/board-dt-sama5.c
@@ -35,17 +35,6 @@ static void __init sama5_dt_timer_init(void)
at91sam926x_pit_init();
}
-static const struct of_device_id irq_of_match[] __initconst = {
-
- { .compatible = "atmel,sama5d3-aic", .data = at91_aic5_of_init },
- { /*sentinel*/ }
-};
-
-static void __init at91_dt_init_irq(void)
-{
- of_irq_init(irq_of_match);
-}
-
static int ksz9021rn_phy_fixup(struct phy_device *phy)
{
int value;
@@ -82,9 +71,7 @@ DT_MACHINE_START(sama5_dt, "Atmel SAMA5 (Device Tree)")
/* Maintainer: Atmel */
.init_time = sama5_dt_timer_init,
.map_io = at91_map_io,
- .handle_irq = at91_aic5_handle_irq,
.init_early = at91_dt_initialize,
- .init_irq = at91_dt_init_irq,
.init_machine = sama5_dt_device_init,
.dt_compat = sama5_dt_board_compat,
MACHINE_END
--
1.7.9.5
^ permalink raw reply related [flat|nested] 19+ messages in thread
* [RFC PATCH v2 06/10] irqchip: atmel-aic: move binding doc to interrupt-controller directory
2014-03-28 17:58 [RFC PATCH v2 00/10] ARM: at91: move aic driver to drivers/irqchips Boris BREZILLON
` (4 preceding siblings ...)
2014-03-28 17:59 ` [RFC PATCH v2 05/10] ARM: at91: make use of the new AIC driver for dt enabled boards Boris BREZILLON
@ 2014-03-28 17:59 ` Boris BREZILLON
2014-03-28 17:59 ` [RFC PATCH v2 07/10] irqchip: atmel-aic: document new dt properties and children nodes Boris BREZILLON
` (3 subsequent siblings)
9 siblings, 0 replies; 19+ messages in thread
From: Boris BREZILLON @ 2014-03-28 17:59 UTC (permalink / raw)
To: Rob Landley, Nicolas Ferre, Jean-Christophe Plagniol-Villard,
Thomas Gleixner
Cc: devicetree, Boris BREZILLON, linux-kernel, linux-arm-kernel,
linux-doc
Move atmel aic driver doc to the interrupt-controller directory as the new
driver now lays in drivers/irqchip/atmel-aic.c.
Signed-off-by: Boris BREZILLON <b.brezillon.dev@gmail.com>
---
.../atmel,aic.txt} | 0
1 file changed, 0 insertions(+), 0 deletions(-)
rename Documentation/devicetree/bindings/{arm/atmel-aic.txt => interrupt-controller/atmel,aic.txt} (100%)
diff --git a/Documentation/devicetree/bindings/arm/atmel-aic.txt b/Documentation/devicetree/bindings/interrupt-controller/atmel,aic.txt
similarity index 100%
rename from Documentation/devicetree/bindings/arm/atmel-aic.txt
rename to Documentation/devicetree/bindings/interrupt-controller/atmel,aic.txt
--
1.7.9.5
^ permalink raw reply [flat|nested] 19+ messages in thread
* [RFC PATCH v2 07/10] irqchip: atmel-aic: document new dt properties and children nodes
2014-03-28 17:58 [RFC PATCH v2 00/10] ARM: at91: move aic driver to drivers/irqchips Boris BREZILLON
` (5 preceding siblings ...)
2014-03-28 17:59 ` [RFC PATCH v2 06/10] irqchip: atmel-aic: move binding doc to interrupt-controller directory Boris BREZILLON
@ 2014-03-28 17:59 ` Boris BREZILLON
2014-03-29 9:19 ` Thomas Petazzoni
2014-03-28 17:59 ` [RFC PATCH v2 08/10] ARM: at91: remove old irq material Boris BREZILLON
` (2 subsequent siblings)
9 siblings, 1 reply; 19+ messages in thread
From: Boris BREZILLON @ 2014-03-28 17:59 UTC (permalink / raw)
To: Rob Landley, Nicolas Ferre, Jean-Christophe Plagniol-Villard,
Thomas Gleixner
Cc: devicetree, linux-doc, linux-kernel, linux-arm-kernel,
Boris BREZILLON
Add irq muxing and irq-mapping dt bindings documentation.
Signed-off-by: Boris BREZILLON <b.brezillon.dev@gmail.com>
---
.../bindings/interrupt-controller/atmel,aic.txt | 42 +++++++++++++++++++-
1 file changed, 41 insertions(+), 1 deletion(-)
diff --git a/Documentation/devicetree/bindings/interrupt-controller/atmel,aic.txt b/Documentation/devicetree/bindings/interrupt-controller/atmel,aic.txt
index 2742e9c..d46ec8e 100644
--- a/Documentation/devicetree/bindings/interrupt-controller/atmel,aic.txt
+++ b/Documentation/devicetree/bindings/interrupt-controller/atmel,aic.txt
@@ -18,8 +18,33 @@ Required properties:
The third cell is used to specify the irq priority from 0 (lowest) to 7
(highest).
- reg: Should contain AIC registers location and length
+- #address-cells: Shall be 2. The first cell encodes the irq line (or irq id).
+ The second cell encodes the register offset within the iomem range.
+- #size-cells: Shall be 1.
+- ranges: Defines the iomem ranges attached to a given irq line (e.i. irq
+ line 1 <=> SYSC range).
- atmel,external-irqs: u32 array of external irqs.
+Optional properties:
+- atmel,irq-mapping: u32 mask array representing the available irqs:
+ e.i. : atmel,irq-mapping = <0xffff1fff> => irqs 13 to 15 are unavailables
+
+Optional children nodes:
+- muxed irq entries:
+ Required properties:
+ * compatible: Shall be
+ "atmel,aic-mux-1reg-irq": irq enable/disable/retrieve-status is done by
+ setting/clearing/reading flags in a specific register
+ or
+ "atmel,aic-mux-3reg-irq": irq enable/disable/retrieve-status is done
+ by writing/reading flags in specific enable/disable/mask registers
+ * reg: encode the interrupt control register.
+ The first cell encode the irq line.
+ The second cell encode the offset register within its iomem range
+ The last cell encode the iomem region size (should always be set to 0x4).
+ * atmel,aic-mux-reg-mask: define the mask used to disable the interrupts
+ generated by the muxed entry.
+
Examples:
/*
* AIC
@@ -29,11 +54,26 @@ Examples:
interrupt-controller;
interrupt-parent;
#interrupt-cells = <3>;
+ #address-cells = <2>;
+ #size-cells = <1>;
reg = <0xfffff000 0x200>;
+ ranges = <0x1 0x0 0xffffc000 0x4000>;
+
+ dbgu_irq: irq@1,320c {
+ compatible = "atmel,aic-mux-3reg-irq";
+ reg = <1 0x320c 0x4>;
+ atmel,aic-mux-reg-mask = <0xc0001afb>;
+ };
+
+ pmc_irq: irq@1,3c64 {
+ compatible = "atmel,aic-mux-3reg-irq";
+ reg = <1 0x3c64 0x4>;
+ atmel,aic-mux-reg-mask = <0xf0f>;
+ };
};
/*
- * An interrupt generating device that is wired to an AIC.
+ * A device generating interrupts wired to the AIC.
*/
dma: dma-controller@ffffec00 {
compatible = "atmel,at91sam9g45-dma";
--
1.7.9.5
^ permalink raw reply related [flat|nested] 19+ messages in thread
* [RFC PATCH v2 08/10] ARM: at91: remove old irq material
2014-03-28 17:58 [RFC PATCH v2 00/10] ARM: at91: move aic driver to drivers/irqchips Boris BREZILLON
` (6 preceding siblings ...)
2014-03-28 17:59 ` [RFC PATCH v2 07/10] irqchip: atmel-aic: document new dt properties and children nodes Boris BREZILLON
@ 2014-03-28 17:59 ` Boris BREZILLON
2014-03-28 17:59 ` [RFC PATCH v2 09/10] ARM: at91/dt: add new AIC irq mux definitions for sam9x5 SoCs Boris BREZILLON
2014-03-28 17:59 ` [RFC PATCH v2 10/10] ARM: at91/dt: add new AIC irq mux definitions for sama5 SoCs Boris BREZILLON
9 siblings, 0 replies; 19+ messages in thread
From: Boris BREZILLON @ 2014-03-28 17:59 UTC (permalink / raw)
To: Rob Landley, Nicolas Ferre, Jean-Christophe Plagniol-Villard,
Thomas Gleixner
Cc: devicetree, linux-doc, linux-kernel, linux-arm-kernel,
Boris BREZILLON
Remove all the material related to AIC support on dt enabled SoCs.
This is now implemented within the new AIC driver
(drivers/irqchip/atmel-aic.c).
Signed-off-by: Boris BREZILLON <b.brezillon.dev@gmail.com>
---
arch/arm/mach-at91/irq.c | 270 ++--------------------------------------------
1 file changed, 6 insertions(+), 264 deletions(-)
diff --git a/arch/arm/mach-at91/irq.c b/arch/arm/mach-at91/irq.c
index 3d192c5..cdb3ec9 100644
--- a/arch/arm/mach-at91/irq.c
+++ b/arch/arm/mach-at91/irq.c
@@ -48,11 +48,6 @@ void __iomem *at91_aic_base;
static struct irq_domain *at91_aic_domain;
static struct device_node *at91_aic_np;
static unsigned int n_irqs = NR_AIC_IRQS;
-static unsigned long at91_aic_caps = 0;
-
-/* AIC5 introduces a Source Select Register */
-#define AT91_AIC_CAP_AIC5 (1 << 0)
-#define has_aic5() (at91_aic_caps & AT91_AIC_CAP_AIC5)
#ifdef CONFIG_PM
@@ -92,50 +87,14 @@ static int at91_aic_set_wake(struct irq_data *d, unsigned value)
void at91_irq_suspend(void)
{
- int bit = -1;
-
- if (has_aic5()) {
- /* disable enabled irqs */
- while ((bit = find_next_bit(backups, n_irqs, bit + 1)) < n_irqs) {
- at91_aic_write(AT91_AIC5_SSR,
- bit & AT91_AIC5_INTSEL_MSK);
- at91_aic_write(AT91_AIC5_IDCR, 1);
- }
- /* enable wakeup irqs */
- bit = -1;
- while ((bit = find_next_bit(wakeups, n_irqs, bit + 1)) < n_irqs) {
- at91_aic_write(AT91_AIC5_SSR,
- bit & AT91_AIC5_INTSEL_MSK);
- at91_aic_write(AT91_AIC5_IECR, 1);
- }
- } else {
- at91_aic_write(AT91_AIC_IDCR, *backups);
- at91_aic_write(AT91_AIC_IECR, *wakeups);
- }
+ at91_aic_write(AT91_AIC_IDCR, *backups);
+ at91_aic_write(AT91_AIC_IECR, *wakeups);
}
void at91_irq_resume(void)
{
- int bit = -1;
-
- if (has_aic5()) {
- /* disable wakeup irqs */
- while ((bit = find_next_bit(wakeups, n_irqs, bit + 1)) < n_irqs) {
- at91_aic_write(AT91_AIC5_SSR,
- bit & AT91_AIC5_INTSEL_MSK);
- at91_aic_write(AT91_AIC5_IDCR, 1);
- }
- /* enable irqs disabled for suspend */
- bit = -1;
- while ((bit = find_next_bit(backups, n_irqs, bit + 1)) < n_irqs) {
- at91_aic_write(AT91_AIC5_SSR,
- bit & AT91_AIC5_INTSEL_MSK);
- at91_aic_write(AT91_AIC5_IECR, 1);
- }
- } else {
- at91_aic_write(AT91_AIC_IDCR, *wakeups);
- at91_aic_write(AT91_AIC_IECR, *backups);
- }
+ at91_aic_write(AT91_AIC_IDCR, *wakeups);
+ at91_aic_write(AT91_AIC_IECR, *backups);
}
#else
@@ -169,21 +128,6 @@ at91_aic_handle_irq(struct pt_regs *regs)
handle_IRQ(irqnr, regs);
}
-asmlinkage void __exception_irq_entry
-at91_aic5_handle_irq(struct pt_regs *regs)
-{
- u32 irqnr;
- u32 irqstat;
-
- irqnr = at91_aic_read(AT91_AIC5_IVR);
- irqstat = at91_aic_read(AT91_AIC5_ISR);
-
- if (!irqstat)
- at91_aic_write(AT91_AIC5_EOICR, 0);
- else
- handle_IRQ(irqnr, regs);
-}
-
static void at91_aic_mask_irq(struct irq_data *d)
{
/* Disable interrupt on AIC */
@@ -192,15 +136,6 @@ static void at91_aic_mask_irq(struct irq_data *d)
clear_backup(d->hwirq);
}
-static void __maybe_unused at91_aic5_mask_irq(struct irq_data *d)
-{
- /* Disable interrupt on AIC5 */
- at91_aic_write(AT91_AIC5_SSR, d->hwirq & AT91_AIC5_INTSEL_MSK);
- at91_aic_write(AT91_AIC5_IDCR, 1);
- /* Update ISR cache */
- clear_backup(d->hwirq);
-}
-
static void at91_aic_unmask_irq(struct irq_data *d)
{
/* Enable interrupt on AIC */
@@ -209,15 +144,6 @@ static void at91_aic_unmask_irq(struct irq_data *d)
set_backup(d->hwirq);
}
-static void __maybe_unused at91_aic5_unmask_irq(struct irq_data *d)
-{
- /* Enable interrupt on AIC5 */
- at91_aic_write(AT91_AIC5_SSR, d->hwirq & AT91_AIC5_INTSEL_MSK);
- at91_aic_write(AT91_AIC5_IECR, 1);
- /* Update ISR cache */
- set_backup(d->hwirq);
-}
-
static void at91_aic_eoi(struct irq_data *d)
{
/*
@@ -227,11 +153,6 @@ static void at91_aic_eoi(struct irq_data *d)
at91_aic_write(AT91_AIC_EOICR, 0);
}
-static void __maybe_unused at91_aic5_eoi(struct irq_data *d)
-{
- at91_aic_write(AT91_AIC5_EOICR, 0);
-}
-
static unsigned long *at91_extern_irq;
u32 at91_get_extern_irq(void)
@@ -282,16 +203,8 @@ static int at91_aic_set_type(struct irq_data *d, unsigned type)
if (srctype < 0)
return srctype;
- if (has_aic5()) {
- at91_aic_write(AT91_AIC5_SSR,
- d->hwirq & AT91_AIC5_INTSEL_MSK);
- smr = at91_aic_read(AT91_AIC5_SMR) & ~AT91_AIC_SRCTYPE;
- at91_aic_write(AT91_AIC5_SMR, smr | srctype);
- } else {
- smr = at91_aic_read(AT91_AIC_SMR(d->hwirq))
- & ~AT91_AIC_SRCTYPE;
- at91_aic_write(AT91_AIC_SMR(d->hwirq), smr | srctype);
- }
+ smr = at91_aic_read(AT91_AIC_SMR(d->hwirq)) & ~AT91_AIC_SRCTYPE;
+ at91_aic_write(AT91_AIC_SMR(d->hwirq), smr | srctype);
return 0;
}
@@ -331,177 +244,6 @@ static void __init at91_aic_hw_init(unsigned int spu_vector)
at91_aic_write(AT91_AIC_ICCR, 0xFFFFFFFF);
}
-static void __init __maybe_unused at91_aic5_hw_init(unsigned int spu_vector)
-{
- int i;
-
- /*
- * Perform 8 End Of Interrupt Command to make sure AIC
- * will not Lock out nIRQ
- */
- for (i = 0; i < 8; i++)
- at91_aic_write(AT91_AIC5_EOICR, 0);
-
- /*
- * Spurious Interrupt ID in Spurious Vector Register.
- * When there is no current interrupt, the IRQ Vector Register
- * reads the value stored in AIC_SPU
- */
- at91_aic_write(AT91_AIC5_SPU, spu_vector);
-
- /* No debugging in AIC: Debug (Protect) Control Register */
- at91_aic_write(AT91_AIC5_DCR, 0);
-
- /* Disable and clear all interrupts initially */
- for (i = 0; i < n_irqs; i++) {
- at91_aic_write(AT91_AIC5_SSR, i & AT91_AIC5_INTSEL_MSK);
- at91_aic_write(AT91_AIC5_IDCR, 1);
- at91_aic_write(AT91_AIC5_ICCR, 1);
- }
-}
-
-#if defined(CONFIG_OF)
-static unsigned int *at91_aic_irq_priorities;
-
-static int at91_aic_irq_map(struct irq_domain *h, unsigned int virq,
- irq_hw_number_t hw)
-{
- /* Put virq number in Source Vector Register */
- at91_aic_write(AT91_AIC_SVR(hw), virq);
-
- /* Active Low interrupt, with priority */
- at91_aic_write(AT91_AIC_SMR(hw),
- AT91_AIC_SRCTYPE_LOW | at91_aic_irq_priorities[hw]);
-
- irq_set_chip_and_handler(virq, &at91_aic_chip, handle_fasteoi_irq);
- set_irq_flags(virq, IRQF_VALID | IRQF_PROBE);
-
- return 0;
-}
-
-static int at91_aic5_irq_map(struct irq_domain *h, unsigned int virq,
- irq_hw_number_t hw)
-{
- at91_aic_write(AT91_AIC5_SSR, hw & AT91_AIC5_INTSEL_MSK);
-
- /* Put virq number in Source Vector Register */
- at91_aic_write(AT91_AIC5_SVR, virq);
-
- /* Active Low interrupt, with priority */
- at91_aic_write(AT91_AIC5_SMR,
- AT91_AIC_SRCTYPE_LOW | at91_aic_irq_priorities[hw]);
-
- irq_set_chip_and_handler(virq, &at91_aic_chip, handle_fasteoi_irq);
- set_irq_flags(virq, IRQF_VALID | IRQF_PROBE);
-
- return 0;
-}
-
-static int at91_aic_irq_domain_xlate(struct irq_domain *d, struct device_node *ctrlr,
- const u32 *intspec, unsigned int intsize,
- irq_hw_number_t *out_hwirq, unsigned int *out_type)
-{
- if (WARN_ON(intsize < 3))
- return -EINVAL;
- if (WARN_ON(intspec[0] >= n_irqs))
- return -EINVAL;
- if (WARN_ON((intspec[2] < AT91_AIC_IRQ_MIN_PRIORITY)
- || (intspec[2] > AT91_AIC_IRQ_MAX_PRIORITY)))
- return -EINVAL;
-
- *out_hwirq = intspec[0];
- *out_type = intspec[1] & IRQ_TYPE_SENSE_MASK;
- at91_aic_irq_priorities[*out_hwirq] = intspec[2];
-
- return 0;
-}
-
-static struct irq_domain_ops at91_aic_irq_ops = {
- .map = at91_aic_irq_map,
- .xlate = at91_aic_irq_domain_xlate,
-};
-
-int __init at91_aic_of_common_init(struct device_node *node,
- struct device_node *parent)
-{
- struct property *prop;
- const __be32 *p;
- u32 val;
-
- at91_extern_irq = kzalloc(BITS_TO_LONGS(n_irqs)
- * sizeof(*at91_extern_irq), GFP_KERNEL);
- if (!at91_extern_irq)
- return -ENOMEM;
-
- if (at91_aic_pm_init()) {
- kfree(at91_extern_irq);
- return -ENOMEM;
- }
-
- at91_aic_irq_priorities = kzalloc(n_irqs
- * sizeof(*at91_aic_irq_priorities),
- GFP_KERNEL);
- if (!at91_aic_irq_priorities)
- return -ENOMEM;
-
- at91_aic_base = of_iomap(node, 0);
- at91_aic_np = node;
-
- at91_aic_domain = irq_domain_add_linear(at91_aic_np, n_irqs,
- &at91_aic_irq_ops, NULL);
- if (!at91_aic_domain)
- panic("Unable to add AIC irq domain (DT)\n");
-
- of_property_for_each_u32(node, "atmel,external-irqs", prop, p, val) {
- if (val >= n_irqs)
- pr_warn("AIC: external irq %d >= %d skip it\n",
- val, n_irqs);
- else
- set_bit(val, at91_extern_irq);
- }
-
- irq_set_default_host(at91_aic_domain);
-
- return 0;
-}
-
-int __init at91_aic_of_init(struct device_node *node,
- struct device_node *parent)
-{
- int err;
-
- err = at91_aic_of_common_init(node, parent);
- if (err)
- return err;
-
- at91_aic_hw_init(n_irqs);
-
- return 0;
-}
-
-int __init at91_aic5_of_init(struct device_node *node,
- struct device_node *parent)
-{
- int err;
-
- at91_aic_caps |= AT91_AIC_CAP_AIC5;
- n_irqs = NR_AIC5_IRQS;
- at91_aic_chip.irq_ack = at91_aic5_mask_irq;
- at91_aic_chip.irq_mask = at91_aic5_mask_irq;
- at91_aic_chip.irq_unmask = at91_aic5_unmask_irq;
- at91_aic_chip.irq_eoi = at91_aic5_eoi;
- at91_aic_irq_ops.map = at91_aic5_irq_map;
-
- err = at91_aic_of_common_init(node, parent);
- if (err)
- return err;
-
- at91_aic5_hw_init(n_irqs);
-
- return 0;
-}
-#endif
-
/*
* Initialize the AIC interrupt controller.
*/
--
1.7.9.5
^ permalink raw reply related [flat|nested] 19+ messages in thread
* [RFC PATCH v2 09/10] ARM: at91/dt: add new AIC irq mux definitions for sam9x5 SoCs
2014-03-28 17:58 [RFC PATCH v2 00/10] ARM: at91: move aic driver to drivers/irqchips Boris BREZILLON
` (7 preceding siblings ...)
2014-03-28 17:59 ` [RFC PATCH v2 08/10] ARM: at91: remove old irq material Boris BREZILLON
@ 2014-03-28 17:59 ` Boris BREZILLON
2014-03-28 17:59 ` [RFC PATCH v2 10/10] ARM: at91/dt: add new AIC irq mux definitions for sama5 SoCs Boris BREZILLON
9 siblings, 0 replies; 19+ messages in thread
From: Boris BREZILLON @ 2014-03-28 17:59 UTC (permalink / raw)
To: Rob Landley, Nicolas Ferre, Jean-Christophe Plagniol-Villard,
Thomas Gleixner
Cc: devicetree, linux-doc, linux-kernel, linux-arm-kernel,
Boris BREZILLON
Add irq line muxing definition for sam9x5 SoCs.
Signed-off-by: Boris BREZILLON <b.brezillon.dev@gmail.com>
---
arch/arm/boot/dts/at91sam9x5.dtsi | 108 +++++++++++++++++++++++++++++++++++++
1 file changed, 108 insertions(+)
diff --git a/arch/arm/boot/dts/at91sam9x5.dtsi b/arch/arm/boot/dts/at91sam9x5.dtsi
index 174219d..ccdfdf3 100644
--- a/arch/arm/boot/dts/at91sam9x5.dtsi
+++ b/arch/arm/boot/dts/at91sam9x5.dtsi
@@ -69,6 +69,114 @@
interrupt-controller;
reg = <0xfffff000 0x200>;
atmel,external-irqs = <31>;
+ #address-cells = <2>;
+ #size-cells = <1>;
+ ranges = <1 0x0 0xffffc000 0x4000>,
+ <2 0x0 0xfffff400 0x400>,
+ <3 0x0 0xfffff800 0x400>,
+ <17 0x0 0xf8008000 0x8000>;
+
+ dbgu_irq: irq-mux@1,2e0c {
+ compatible = "atmel,aic-mux-3reg-irq";
+ reg = <1 0x2e0c 0x4>;
+ atmel,aic-mux-reg-mask = <0xc00002e3>;
+ };
+
+ pmc_irq: irq-mux@1,3c64 {
+ compatible = "atmel,aic-mux-3reg-irq";
+ reg = <1 0x3c64 0x4>;
+ atmel,aic-mux-reg-mask = <0x7034b>;
+ };
+
+ pmecc_irq: irq-mux@1,2020 {
+ compatible = "atmel,aic-mux-3reg-irq";
+ reg = <1 0x2020 0x4>;
+ atmel,aic-mux-reg-mask = <0x1>;
+ };
+
+ pmerrloc_irq: irq-mux@1,2618 {
+ compatible = "atmel,aic-mux-3reg-irq";
+ reg = <1 0x2618 0x4>;
+ atmel,aic-mux-reg-mask = <0x1>;
+ };
+
+ pit_irq: irq-mux@1,3e30 {
+ compatible = "atmel,aic-mux-1reg-irq";
+ reg = <1 0x3e30 0x4>;
+ atmel,aic-mux-reg-mask = <0x2000000>;
+ };
+
+ wdt_irq: irq-mux@1,3e40 {
+ compatible = "atmel,aic-mux-1reg-irq";
+ reg = <1 0x3e40 0x4>;
+ atmel,aic-mux-reg-mask = <0x1000>;
+ };
+
+ rtc_irq: irq-mux@1,3ed4 {
+ compatible = "atmel,aic-mux-3reg-irq";
+ reg = <1 0x3ed4 0x4>;
+ atmel,aic-mux-reg-mask = <0x1f>;
+ };
+
+ pioA_irq: irq-mux@2,44 {
+ compatible = "atmel,aic-mux-3reg-irq";
+ reg = <2 0x44 0x4>;
+ atmel,aic-mux-reg-mask = <0xffffffff>;
+ };
+
+ pioB_irq: irq-mux@2,244 {
+ compatible = "atmel,aic-mux-3reg-irq";
+ reg = <2 0x244 0x4>;
+ atmel,aic-mux-reg-mask = <0xffffffff>;
+ };
+
+ pioC_irq: irq-mux@3,44 {
+ compatible = "atmel,aic-mux-3reg-irq";
+ reg = <3 0x44 0x4>;
+ atmel,aic-mux-reg-mask = <0xffffffff>;
+ };
+
+ pioD_irq: irq-mux@3,244 {
+ compatible = "atmel,aic-mux-3reg-irq";
+ reg = <3 0x244 0x4>;
+ atmel,aic-mux-reg-mask = <0xffffffff>;
+ };
+
+ tc0_irq: irq-mux@17,28 {
+ compatible = "atmel,aic-mux-3reg-irq";
+ reg = <17 0x28 0x4>;
+ atmel,aic-mux-reg-mask = <0xff>;
+ };
+
+ tc1_irq: irq-mux@17,68 {
+ compatible = "atmel,aic-mux-3reg-irq";
+ reg = <17 0x68 0x4>;
+ atmel,aic-mux-reg-mask = <0xff>;
+ };
+
+ tc2_irq: irq-mux@17,a8 {
+ compatible = "atmel,aic-mux-3reg-irq";
+ reg = <17 0xa8 0x4>;
+ atmel,aic-mux-reg-mask = <0xff>;
+ };
+
+ tc3_irq: irq-mux@17,4028 {
+ compatible = "atmel,aic-mux-3reg-irq";
+ reg = <17 0x4028 0x4>;
+ atmel,aic-mux-reg-mask = <0xff>;
+ };
+
+ tc4_irq: irq-mux@17,4068 {
+ compatible = "atmel,aic-mux-3reg-irq";
+ reg = <17 0x4068 0x4>;
+ atmel,aic-mux-reg-mask = <0xff>;
+ };
+
+ tc5_irq: irq-mux@17,40a8 {
+ compatible = "atmel,aic-mux-3reg-irq";
+ reg = <17 0x40a8 0x4>;
+ atmel,aic-mux-reg-mask = <0xff>;
+ };
};
ramc0: ramc@ffffe800 {
--
1.7.9.5
^ permalink raw reply related [flat|nested] 19+ messages in thread
* [RFC PATCH v2 10/10] ARM: at91/dt: add new AIC irq mux definitions for sama5 SoCs
2014-03-28 17:58 [RFC PATCH v2 00/10] ARM: at91: move aic driver to drivers/irqchips Boris BREZILLON
` (8 preceding siblings ...)
2014-03-28 17:59 ` [RFC PATCH v2 09/10] ARM: at91/dt: add new AIC irq mux definitions for sam9x5 SoCs Boris BREZILLON
@ 2014-03-28 17:59 ` Boris BREZILLON
9 siblings, 0 replies; 19+ messages in thread
From: Boris BREZILLON @ 2014-03-28 17:59 UTC (permalink / raw)
To: Rob Landley, Nicolas Ferre, Jean-Christophe Plagniol-Villard,
Thomas Gleixner
Cc: devicetree, linux-doc, linux-kernel, linux-arm-kernel,
Boris BREZILLON
Add irq line muxing definition for sama5 SoCs.
Signed-off-by: Boris BREZILLON <b.brezillon.dev@gmail.com>
---
arch/arm/boot/dts/sama5d3.dtsi | 37 +++++++++++++++++++++++++++++++++++
arch/arm/boot/dts/sama5d3_tcb1.dtsi | 20 +++++++++++++++++++
2 files changed, 57 insertions(+)
diff --git a/arch/arm/boot/dts/sama5d3.dtsi b/arch/arm/boot/dts/sama5d3.dtsi
index 3d5faf8..ece1f7b 100644
--- a/arch/arm/boot/dts/sama5d3.dtsi
+++ b/arch/arm/boot/dts/sama5d3.dtsi
@@ -416,6 +416,43 @@
interrupt-controller;
reg = <0xfffff000 0x200>;
atmel,external-irqs = <47>;
+ #address-cells = <2>;
+ #size-cells = <1>;
+ ranges = <1 0x0 0xffffc000 0x4000>,
+ <26 0x0 0xf0010000 0x4000>,
+ <27 0x0 0xf8014000 0x4000>;
+
+ atmel,aic-irq-mapping = <0xffffffff 0x7ffff>;
+
+ pmc_irq: irq-mux@1,3c64 {
+ compatible = "atmel,aic-mux-3reg-irq";
+ reg = <1 0x3c64 0x4>;
+ atmel,aic-mux-reg-mask = <0x5074b>;
+ };
+
+ rtc_irq: irq-mux@1,3ed4 {
+ compatible = "atmel,aic-mux-3reg-irq";
+ reg = <1 0x3ed4 0x4>;
+ atmel,aic-mux-reg-mask = <0x1f>;
+ };
+
+ tc0_irq: irq-mux@26,28 {
+ compatible = "atmel,aic-mux-3reg-irq";
+ reg = <26 0x28 0x4>;
+ atmel,aic-mux-reg-mask = <0xff>;
+ };
+
+ tc1_irq: irq-mux@26,68 {
+ compatible = "atmel,aic-mux-3reg-irq";
+ reg = <26 0x68 0x4>;
+ atmel,aic-mux-reg-mask = <0xff>;
+ };
+
+ tc2_irq: irq-mux@26,a8 {
+ compatible = "atmel,aic-mux-3reg-irq";
+ reg = <26 0xa8 0x4>;
+ atmel,aic-mux-reg-mask = <0xff>;
+ };
};
pinctrl@fffff200 {
diff --git a/arch/arm/boot/dts/sama5d3_tcb1.dtsi b/arch/arm/boot/dts/sama5d3_tcb1.dtsi
index 382b044..6060bfd 100644
--- a/arch/arm/boot/dts/sama5d3_tcb1.dtsi
+++ b/arch/arm/boot/dts/sama5d3_tcb1.dtsi
@@ -18,6 +18,26 @@
ahb {
apb {
+ aic: interrupt-controller@fffff000 {
+ tc3_irq: irq-mux@27,28 {
+ compatible = "atmel,aic-mux-3reg-irq";
+ reg = <27 0x28 0x4>;
+ atmel,aic-mux-reg-mask = <0xff>;
+ };
+
+ tc4_irq: irq-mux@27,68 {
+ compatible = "atmel,aic-mux-3reg-irq";
+ reg = <27 0x68 0x4>;
+ atmel,aic-mux-reg-mask = <0xff>;
+ };
+
+ tc5_irq: irq-mux@27,a8 {
+ compatible = "atmel,aic-mux-3reg-irq";
+ reg = <27 0xa8 0x4>;
+ atmel,aic-mux-reg-mask = <0xff>;
+ };
+ };
+
pmc: pmc@fffffc00 {
periphck {
tcb1_clk: tcb1_clk {
--
1.7.9.5
^ permalink raw reply related [flat|nested] 19+ messages in thread
* Re: [RFC PATCH v2 03/10] ARM: at91: introduce OLD_IRQ_AT91 Kconfig option
2014-03-28 17:59 ` [RFC PATCH v2 03/10] ARM: at91: introduce OLD_IRQ_AT91 Kconfig option Boris BREZILLON
@ 2014-03-29 9:06 ` Thomas Petazzoni
2014-03-29 9:12 ` Arnd Bergmann
0 siblings, 1 reply; 19+ messages in thread
From: Thomas Petazzoni @ 2014-03-29 9:06 UTC (permalink / raw)
To: Boris BREZILLON
Cc: devicetree, linux-doc, Nicolas Ferre, linux-kernel, Rob Landley,
Thomas Gleixner, Jean-Christophe Plagniol-Villard,
linux-arm-kernel
Dear Boris BREZILLON,
On Fri, 28 Mar 2014 18:59:01 +0100, Boris BREZILLON wrote:
> +config OLD_IRQ_AT91
> + bool
> + default false
I don't think "default false" is a valid Kconfig construct. It could be
"default n", but that's useless since "default n" is the default
behavior. So I believe you can simply get rid of that line.
Thomas
--
Thomas Petazzoni, CTO, Free Electrons
Embedded Linux, Kernel and Android engineering
http://free-electrons.com
^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: [RFC PATCH v2 05/10] ARM: at91: make use of the new AIC driver for dt enabled boards
2014-03-28 17:59 ` [RFC PATCH v2 05/10] ARM: at91: make use of the new AIC driver for dt enabled boards Boris BREZILLON
@ 2014-03-29 9:07 ` Thomas Petazzoni
2014-03-29 10:11 ` Boris BREZILLON
0 siblings, 1 reply; 19+ messages in thread
From: Thomas Petazzoni @ 2014-03-29 9:07 UTC (permalink / raw)
To: Boris BREZILLON
Cc: Rob Landley, Nicolas Ferre, Jean-Christophe Plagniol-Villard,
Thomas Gleixner, devicetree, linux-doc, linux-kernel,
linux-arm-kernel
Dear Boris BREZILLON,
On Fri, 28 Mar 2014 18:59:03 +0100, Boris BREZILLON wrote:
> +config ATMEL_AIC_IRQ
> + bool
> + default USE_OF
> + select GENERIC_IRQ_CHIP
> + select IRQ_DOMAIN
> + select MULTI_IRQ_HANDLER
This option should probably go in drivers/irqchip/Kconfig, no?
Thomas
--
Thomas Petazzoni, CTO, Free Electrons
Embedded Linux, Kernel and Android engineering
http://free-electrons.com
^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: [RFC PATCH v2 03/10] ARM: at91: introduce OLD_IRQ_AT91 Kconfig option
2014-03-29 9:06 ` Thomas Petazzoni
@ 2014-03-29 9:12 ` Arnd Bergmann
2014-03-29 9:52 ` Boris BREZILLON
0 siblings, 1 reply; 19+ messages in thread
From: Arnd Bergmann @ 2014-03-29 9:12 UTC (permalink / raw)
To: linux-arm-kernel
Cc: Thomas Petazzoni, Boris BREZILLON, devicetree, linux-doc,
Nicolas Ferre, linux-kernel, Rob Landley, Thomas Gleixner,
Jean-Christophe Plagniol-Villard
On Saturday 29 March 2014 10:06:39 Thomas Petazzoni wrote:
> Dear Boris BREZILLON,
>
> On Fri, 28 Mar 2014 18:59:01 +0100, Boris BREZILLON wrote:
>
> > +config OLD_IRQ_AT91
> > + bool
> > + default false
>
> I don't think "default false" is a valid Kconfig construct. It could be
> "default n", but that's useless since "default n" is the default
> behavior. So I believe you can simply get rid of that line.
I think the above is syntactically correct, but it would be highly confusing in
anyone ever does
config false
def_bool y
;-)
Aside from that, these three have completely identical meaning:
config OLD_IRQ_AT91
bool
config OLD_IRQ_AT91
def_bool n
config OLD_IRQ_AT91
bool
default n
Arnd
^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: [RFC PATCH v2 07/10] irqchip: atmel-aic: document new dt properties and children nodes
2014-03-28 17:59 ` [RFC PATCH v2 07/10] irqchip: atmel-aic: document new dt properties and children nodes Boris BREZILLON
@ 2014-03-29 9:19 ` Thomas Petazzoni
2014-03-30 13:27 ` Boris BREZILLON
2014-03-30 14:55 ` Boris BREZILLON
0 siblings, 2 replies; 19+ messages in thread
From: Thomas Petazzoni @ 2014-03-29 9:19 UTC (permalink / raw)
To: Boris BREZILLON
Cc: devicetree, linux-doc, Nicolas Ferre, linux-kernel, Rob Landley,
Thomas Gleixner, Jean-Christophe Plagniol-Villard,
linux-arm-kernel
Dear Boris BREZILLON,
On Fri, 28 Mar 2014 18:59:05 +0100, Boris BREZILLON wrote:
> +Optional children nodes:
> +- muxed irq entries:
> + Required properties:
> + * compatible: Shall be
> + "atmel,aic-mux-1reg-irq": irq enable/disable/retrieve-status is done by
> + setting/clearing/reading flags in a specific register
> + or
> + "atmel,aic-mux-3reg-irq": irq enable/disable/retrieve-status is done
> + by writing/reading flags in specific enable/disable/mask registers
> + * reg: encode the interrupt control register.
> + The first cell encode the irq line.
> + The second cell encode the offset register within its iomem range
> + The last cell encode the iomem region size (should always be set to 0x4).
> + * atmel,aic-mux-reg-mask: define the mask used to disable the interrupts
> + generated by the muxed entry.
Can you describe in more details what are these muxed irqs? Are they
interrupts raised to the AIC that may actually be related to several
devices, like a shared interrupt?
If that's the case, then what you want is to implement separate
interrupt controller drivers to handle those shared interrupts, and
demux them into multiple separate interrupts.
Note that the way you use the "ranges" property seems wrong to me:
you're using it as a "hack" to define the base address of some
peripherals that are outside the AIC, while the ranges property is
normally used to describe the address translations between a child bus
and a parent bus. Which is not what you have here, as far as I can
understand.
So could you give more details about the design of the AIC and these
muxed interrupts, to see if the DT binding you're proposing is actually
the right way of representing the hardware?
Thomas
--
Thomas Petazzoni, CTO, Free Electrons
Embedded Linux, Kernel and Android engineering
http://free-electrons.com
^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: [RFC PATCH v2 03/10] ARM: at91: introduce OLD_IRQ_AT91 Kconfig option
2014-03-29 9:12 ` Arnd Bergmann
@ 2014-03-29 9:52 ` Boris BREZILLON
0 siblings, 0 replies; 19+ messages in thread
From: Boris BREZILLON @ 2014-03-29 9:52 UTC (permalink / raw)
To: Arnd Bergmann, linux-arm-kernel
Cc: Thomas Petazzoni, devicetree, linux-doc, Nicolas Ferre,
linux-kernel, Rob Landley, Thomas Gleixner,
Jean-Christophe Plagniol-Villard
Le 29/03/2014 10:12, Arnd Bergmann a écrit :
> On Saturday 29 March 2014 10:06:39 Thomas Petazzoni wrote:
>> Dear Boris BREZILLON,
>>
>> On Fri, 28 Mar 2014 18:59:01 +0100, Boris BREZILLON wrote:
>>
>>> +config OLD_IRQ_AT91
>>> + bool
>>> + default false
>> I don't think "default false" is a valid Kconfig construct. It could be
>> "default n", but that's useless since "default n" is the default
>> behavior. So I believe you can simply get rid of that line.
I'll fix it for the next version.
> I think the above is syntactically correct, but it would be highly confusing in
> anyone ever does
>
> config false
> def_bool y
>
> ;-)
>
> Aside from that, these three have completely identical meaning:
>
> config OLD_IRQ_AT91
> bool
>
> config OLD_IRQ_AT91
> def_bool n
>
> config OLD_IRQ_AT91
> bool
> default n
>
> Arnd
>
>
Thanks for the detailled explanation :-).
Best Regards,
Boris
^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: [RFC PATCH v2 05/10] ARM: at91: make use of the new AIC driver for dt enabled boards
2014-03-29 9:07 ` Thomas Petazzoni
@ 2014-03-29 10:11 ` Boris BREZILLON
0 siblings, 0 replies; 19+ messages in thread
From: Boris BREZILLON @ 2014-03-29 10:11 UTC (permalink / raw)
To: Thomas Petazzoni
Cc: devicetree, linux-doc, Nicolas Ferre, linux-kernel, Rob Landley,
Thomas Gleixner, Jean-Christophe Plagniol-Villard,
linux-arm-kernel
Hello Thomas,
Le 29/03/2014 10:07, Thomas Petazzoni a écrit :
> Dear Boris BREZILLON,
>
> On Fri, 28 Mar 2014 18:59:03 +0100, Boris BREZILLON wrote:
>
>> +config ATMEL_AIC_IRQ
>> + bool
>> + default USE_OF
>> + select GENERIC_IRQ_CHIP
>> + select IRQ_DOMAIN
>> + select MULTI_IRQ_HANDLER
> This option should probably go in drivers/irqchip/Kconfig, no?
Absolutely, I'll move this section into drivers/irqchip/Kconfig.
Best Regards,
Boris
>
> Thomas
^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: [RFC PATCH v2 07/10] irqchip: atmel-aic: document new dt properties and children nodes
2014-03-29 9:19 ` Thomas Petazzoni
@ 2014-03-30 13:27 ` Boris BREZILLON
2014-03-30 14:55 ` Boris BREZILLON
1 sibling, 0 replies; 19+ messages in thread
From: Boris BREZILLON @ 2014-03-30 13:27 UTC (permalink / raw)
To: Thomas Petazzoni
Cc: Rob Landley, Nicolas Ferre, Jean-Christophe Plagniol-Villard,
Thomas Gleixner, devicetree, linux-doc, linux-kernel,
linux-arm-kernel
Hello Thomas,
Le 29/03/2014 10:19, Thomas Petazzoni a écrit :
> Dear Boris BREZILLON,
>
> On Fri, 28 Mar 2014 18:59:05 +0100, Boris BREZILLON wrote:
>
>> +Optional children nodes:
>> +- muxed irq entries:
>> + Required properties:
>> + * compatible: Shall be
>> + "atmel,aic-mux-1reg-irq": irq enable/disable/retrieve-status is done by
>> + setting/clearing/reading flags in a specific register
>> + or
>> + "atmel,aic-mux-3reg-irq": irq enable/disable/retrieve-status is done
>> + by writing/reading flags in specific enable/disable/mask registers
>> + * reg: encode the interrupt control register.
>> + The first cell encode the irq line.
>> + The second cell encode the offset register within its iomem range
>> + The last cell encode the iomem region size (should always be set to 0x4).
>> + * atmel,aic-mux-reg-mask: define the mask used to disable the interrupts
>> + generated by the muxed entry.
> Can you describe in more details what are these muxed irqs? Are they
> interrupts raised to the AIC that may actually be related to several
> devices, like a shared interrupt?
Exactly, muxed irqs are shared irqs.
> If that's the case, then what you want is to implement separate
> interrupt controller drivers to handle those shared interrupts, and
> demux them into multiple separate interrupts.
It may work (I'll take a look), but we may have to modify several
drivers (and
it may break the DT ABI).
>
> Note that the way you use the "ranges" property seems wrong to me:
> you're using it as a "hack" to define the base address of some
> peripherals that are outside the AIC, while the ranges property is
> normally used to describe the address translations between a child bus
> and a parent bus. Which is not what you have here, as far as I can
> understand.
This is clearly not a real bus, but more a virtual/conceptual bus where each
irq source is a bus device.
> So could you give more details about the design of the AIC and these
> muxed interrupts, to see if the DT binding you're proposing is actually
> the right way of representing the hardware?
The AIC controller muxes several peripheral irqs to one irq line.
If a given peripheral has a pending irq, and the driver requesting this
irq is
not loaded (either because it was not enabled or because it is not
loaded yet)
it may generate spurious interrupts (or even hang forever), waiting for
someone
clearing/reading the interrupt flag(s).
See this thread for an example of what can happen if we don't disable
all muxed
interrupts before enabling an IRQ line:
https://lkml.org/lkml/2013/3/8/176
In this series' implementation, I define all the muxed (or shared) interrupt
entries (using the DT) and let the AIC driver disable all the interrupt
sources
when shutting down an interrupt line or before starting the AIC controller.
This provides a generic solution to avoid these spurious interrupt issues
instead of adding several hooks in the machine specific code (one for each
impacted peripheral).
Please tell me if you see a better solution (but keep in mind, this
should be
done during early init, because the at91 init timer is using a muxed irq
line
on almost all at91 SoCs).
Best Regards,
Boris
>
> Thomas
^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: [RFC PATCH v2 07/10] irqchip: atmel-aic: document new dt properties and children nodes
2014-03-29 9:19 ` Thomas Petazzoni
2014-03-30 13:27 ` Boris BREZILLON
@ 2014-03-30 14:55 ` Boris BREZILLON
1 sibling, 0 replies; 19+ messages in thread
From: Boris BREZILLON @ 2014-03-30 14:55 UTC (permalink / raw)
To: Boris BREZILLON
Cc: Jean-Christophe Plagniol-Villard, Thomas Gleixner,
devicetree-u79uwXL29TY76Z2rM5mHXA
Hello Thomas,
Le 29/03/2014 10:19, Thomas Petazzoni a écrit :
> Dear Boris BREZILLON,
>
> On Fri, 28 Mar 2014 18:59:05 +0100, Boris BREZILLON wrote:
>
>> +Optional children nodes:
>> +- muxed irq entries:
>> + Required properties:
>> + * compatible: Shall be
>> + "atmel,aic-mux-1reg-irq": irq enable/disable/retrieve-status is done by
>> + setting/clearing/reading flags in a specific register
>> + or
>> + "atmel,aic-mux-3reg-irq": irq enable/disable/retrieve-status is done
>> + by writing/reading flags in specific enable/disable/mask registers
>> + * reg: encode the interrupt control register.
>> + The first cell encode the irq line.
>> + The second cell encode the offset register within its iomem range
>> + The last cell encode the iomem region size (should always be set to 0x4).
>> + * atmel,aic-mux-reg-mask: define the mask used to disable the interrupts
>> + generated by the muxed entry.
> Can you describe in more details what are these muxed irqs? Are they
> interrupts raised to the AIC that may actually be related to several
> devices, like a shared interrupt?
Exactly, muxed irqs are shared irqs.
> If that's the case, then what you want is to implement separate
> interrupt controller drivers to handle those shared interrupts, and
> demux them into multiple separate interrupts.
It may work (I'll take a look), but we may have to modify several drivers (and
it may break the DT ABI).
>
> Note that the way you use the "ranges" property seems wrong to me:
> you're using it as a "hack" to define the base address of some
> peripherals that are outside the AIC, while the ranges property is
> normally used to describe the address translations between a child bus
> and a parent bus. Which is not what you have here, as far as I can
> understand.
This is clearly not a real bus, but more a virtual/conceptual bus where each irq
source is a bus device.
> So could you give more details about the design of the AIC and these
> muxed interrupts, to see if the DT binding you're proposing is actually
> the right way of representing the hardware?
The AIC controller muxes several peripheral irqs to one irq line.
If a given peripheral has a pending irq, and the driver requesting this irq is
not loaded (either because it was not enabled or because it is not loaded yet)
it may generate spurious interrupts (or even hang forever), waiting for someone
clearing/reading the interrupt flag(s).
See this thread for an example of what can happen if we don't disable all muxed
interrupts before enabling an IRQ line:
https://lkml.org/lkml/2013/3/8/176
In this series' implementation, I define all the muxed (or shared) interrupt
entries (using the DT) and let the AIC driver disable all the interrupt sources
when shutting down an interrupt line or before starting the AIC controller.
This provides a generic solution to avoid these spurious interrupt issues
instead of adding several hooks in the machine specific code (one for each
impacted peripheral).
Please tell me if you see a better solution (but keep in mind, this should be
done during early init, because the at91 init timer is using a muxed irq line on
almost all at91 SoCs).
Best Regards,
Boris
>
> Thomas
--
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] 19+ messages in thread
end of thread, other threads:[~2014-03-30 14:55 UTC | newest]
Thread overview: 19+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2014-03-28 17:58 [RFC PATCH v2 00/10] ARM: at91: move aic driver to drivers/irqchips Boris BREZILLON
2014-03-28 17:58 ` [RFC PATCH v2 01/10] genirq: generic chip: export irq_map_generic_chip function Boris BREZILLON
2014-03-28 17:59 ` [RFC PATCH v2 02/10] irqchip: atmel-aic: add new atmel AIC driver Boris BREZILLON
2014-03-28 17:59 ` [RFC PATCH v2 03/10] ARM: at91: introduce OLD_IRQ_AT91 Kconfig option Boris BREZILLON
2014-03-29 9:06 ` Thomas Petazzoni
2014-03-29 9:12 ` Arnd Bergmann
2014-03-29 9:52 ` Boris BREZILLON
2014-03-28 17:59 ` [RFC PATCH v2 04/10] ARM: at91: enclose at91_aic_xx calls in IS_ENABLED(CONFIG_OLD_IRQ_AT91) blocks Boris BREZILLON
2014-03-28 17:59 ` [RFC PATCH v2 05/10] ARM: at91: make use of the new AIC driver for dt enabled boards Boris BREZILLON
2014-03-29 9:07 ` Thomas Petazzoni
2014-03-29 10:11 ` Boris BREZILLON
2014-03-28 17:59 ` [RFC PATCH v2 06/10] irqchip: atmel-aic: move binding doc to interrupt-controller directory Boris BREZILLON
2014-03-28 17:59 ` [RFC PATCH v2 07/10] irqchip: atmel-aic: document new dt properties and children nodes Boris BREZILLON
2014-03-29 9:19 ` Thomas Petazzoni
2014-03-30 13:27 ` Boris BREZILLON
2014-03-30 14:55 ` Boris BREZILLON
2014-03-28 17:59 ` [RFC PATCH v2 08/10] ARM: at91: remove old irq material Boris BREZILLON
2014-03-28 17:59 ` [RFC PATCH v2 09/10] ARM: at91/dt: add new AIC irq mux definitions for sam9x5 SoCs Boris BREZILLON
2014-03-28 17:59 ` [RFC PATCH v2 10/10] ARM: at91/dt: add new AIC irq mux definitions for sama5 SoCs Boris BREZILLON
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).