* [RFC PATCH 00/10] ARM: at91: move aic driver to drivers/irqchips
@ 2013-12-16 20:24 Boris BREZILLON
2013-12-16 20:24 ` [RFC PATCH 01/10] genirq: generic chip: export irq_map_generic_chip function Boris BREZILLON
` (7 more replies)
0 siblings, 8 replies; 11+ messages in thread
From: Boris BREZILLON @ 2013-12-16 20:24 UTC (permalink / raw)
To: Rob Landley, Nicolas Ferre, Jean-Christophe Plagniol-Villard,
Russell King, Thomas Gleixner, Grant Likely
Cc: Boris BREZILLON, devicetree, linux-doc, linux-kernel,
linux-arm-kernel
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
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
ARM: at91/dt: add new AIC irq mux definitions for sama5 SoCs
.../devicetree/bindings/arm/atmel-aic.txt | 41 -
.../bindings/interrupt-controller/atmel,aic.txt | 86 ++
arch/arm/boot/dts/at91sam9x5.dtsi | 111 ++-
arch/arm/boot/dts/sama5d3.dtsi | 40 +-
arch/arm/boot/dts/sama5d3_tcb1.dtsi | 22 +
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 | 879 ++++++++++++++++++++
include/linux/irq.h | 2 +
kernel/irq/generic-chip.c | 5 +-
18 files changed, 1189 insertions(+), 364 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] 11+ messages in thread
* [RFC PATCH 01/10] genirq: generic chip: export irq_map_generic_chip function
2013-12-16 20:24 [RFC PATCH 00/10] ARM: at91: move aic driver to drivers/irqchips Boris BREZILLON
@ 2013-12-16 20:24 ` Boris BREZILLON
2013-12-16 20:24 ` [RFC PATCH 03/10] ARM: at91: introduce OLD_IRQ_AT91 Kconfig option Boris BREZILLON
` (6 subsequent siblings)
7 siblings, 0 replies; 11+ messages in thread
From: Boris BREZILLON @ 2013-12-16 20:24 UTC (permalink / raw)
To: Rob Landley, Nicolas Ferre, Jean-Christophe Plagniol-Villard,
Russell King, Thomas Gleixner, Grant Likely
Cc: Boris BREZILLON, devicetree, linux-doc, linux-kernel,
linux-arm-kernel
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@overkiz.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] 11+ messages in thread
* [RFC PATCH 02/10] irqchip: atmel-aic: add new atmel AIC driver
[not found] ` <1387225461-6201-1-git-send-email-b.brezillon-ZNYIgs0QAGpBDgjK7y7TUQ@public.gmane.org>
@ 2013-12-16 20:24 ` Boris BREZILLON
2013-12-16 20:24 ` [RFC PATCH 05/10] ARM: at91: make use of the new AIC driver for dt enabled boards Boris BREZILLON
2013-12-16 21:25 ` [RFC PATCH 10/10] ARM: at91/dt: add new AIC irq mux definitions for sama5 SoCs Boris BREZILLON
2 siblings, 0 replies; 11+ messages in thread
From: Boris BREZILLON @ 2013-12-16 20:24 UTC (permalink / raw)
To: Rob Landley, Nicolas Ferre, Jean-Christophe Plagniol-Villard,
Russell King, Thomas Gleixner, Grant Likely
Cc: Boris BREZILLON, devicetree-u79uwXL29TY76Z2rM5mHXA,
linux-doc-u79uwXL29TY76Z2rM5mHXA,
linux-kernel-u79uwXL29TY76Z2rM5mHXA,
linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r
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-ZNYIgs0QAGpBDgjK7y7TUQ@public.gmane.org>
---
drivers/irqchip/Makefile | 1 +
drivers/irqchip/irq-atmel-aic.c | 879 +++++++++++++++++++++++++++++++++++++++
2 files changed, 880 insertions(+)
create mode 100644 drivers/irqchip/irq-atmel-aic.c
diff --git a/drivers/irqchip/Makefile b/drivers/irqchip/Makefile
index c60b901..b0adcd9 100644
--- a/drivers/irqchip/Makefile
+++ b/drivers/irqchip/Makefile
@@ -15,6 +15,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..f689b3a
--- /dev/null
+++ b/drivers/irqchip/irq-atmel-aic.c
@@ -0,0 +1,879 @@
+/*
+ * 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-ZNYIgs0QAGpBDgjK7y7TUQ@public.gmane.org>
+ *
+ * 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 *base;
+ u32 offset;
+ 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->base + irq->offset) & ~irq->mask,
+ irq->base + irq->offset);
+ else
+ writel(irq->mask, irq->base + irq->offset);
+ }
+}
+
+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;
+ struct of_phandle_args args;
+ struct resource res;
+ int ret;
+
+ ret = of_parse_phandle_with_fixed_args(node, "atmel,aic-mux-irq-reg",
+ 3, 0, &args);
+ if (ret) {
+ pr_warn("AIC: failed to retrieve atmel,aic-mux-irq-reg property\n");
+ return ERR_PTR(ret);
+ }
+
+ ret = of_address_to_resource(args.np, args.args[0], &res);
+ if (ret) {
+ pr_warn("AIC: failed to retrieve muxed irq line iomem info\n");
+ return ERR_PTR(ret);
+ }
+
+ if (resource_size(&res) < args.args[1]) {
+ pr_warn("AIC: wrong disable register offset\n");
+ return ERR_PTR(-EINVAL);
+ }
+
+ irq = kzalloc(sizeof(*irq), GFP_KERNEL);
+ if (!irq)
+ return ERR_PTR(-ENOMEM);
+
+ INIT_LIST_HEAD(&irq->node);
+
+ irq->base = ioremap(res.start, resource_size(&res));
+ if (!irq->base) {
+ kfree(irq);
+ return ERR_PTR(-ENOMEM);
+ }
+ irq->offset = args.args[1];
+ irq->mask = args.args[2];
+
+ 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 const struct of_device_id aic_mux_of_match[] __initconst = {
+ { .compatible = "atmel,aic-mux" },
+ { /*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 *irq_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) {
+ if (!of_match_node(aic_mux_of_match, mux_node))
+ 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];
+
+ for_each_child_of_node(mux_node, irq_node) {
+ match = of_match_node(aic_mux_irq_of_match, irq_node);
+ if (!match)
+ continue;
+
+ mux_of_init = match->data;
+
+ irq = mux_of_init(irq_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
--
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 related [flat|nested] 11+ messages in thread
* [RFC PATCH 03/10] ARM: at91: introduce OLD_IRQ_AT91 Kconfig option
2013-12-16 20:24 [RFC PATCH 00/10] ARM: at91: move aic driver to drivers/irqchips Boris BREZILLON
2013-12-16 20:24 ` [RFC PATCH 01/10] genirq: generic chip: export irq_map_generic_chip function Boris BREZILLON
@ 2013-12-16 20:24 ` Boris BREZILLON
2013-12-16 20:24 ` [RFC PATCH 04/10] ARM: at91: enclose at91_aic_xx calls in IS_ENABLED(CONFIG_OLD_IRQ_AT91) blocks Boris BREZILLON
` (5 subsequent siblings)
7 siblings, 0 replies; 11+ messages in thread
From: Boris BREZILLON @ 2013-12-16 20:24 UTC (permalink / raw)
To: Rob Landley, Nicolas Ferre, Jean-Christophe Plagniol-Villard,
Russell King, Thomas Gleixner, Grant Likely
Cc: Boris BREZILLON, devicetree, linux-doc, linux-kernel,
linux-arm-kernel
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@overkiz.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 b4f7d6f..e1e6ff4 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
@@ -190,6 +194,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.
@@ -198,6 +203,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.
@@ -206,6 +212,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 b736b57..87dc5e1 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 705b38a..960c9dd 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] 11+ messages in thread
* [RFC PATCH 04/10] ARM: at91: enclose at91_aic_xx calls in IS_ENABLED(CONFIG_OLD_IRQ_AT91) blocks
2013-12-16 20:24 [RFC PATCH 00/10] ARM: at91: move aic driver to drivers/irqchips Boris BREZILLON
2013-12-16 20:24 ` [RFC PATCH 01/10] genirq: generic chip: export irq_map_generic_chip function Boris BREZILLON
2013-12-16 20:24 ` [RFC PATCH 03/10] ARM: at91: introduce OLD_IRQ_AT91 Kconfig option Boris BREZILLON
@ 2013-12-16 20:24 ` Boris BREZILLON
2013-12-16 20:24 ` [RFC PATCH 06/10] irqchip: atmel-aic: move binding doc to interrupt-controller directory Boris BREZILLON
` (4 subsequent siblings)
7 siblings, 0 replies; 11+ messages in thread
From: Boris BREZILLON @ 2013-12-16 20:24 UTC (permalink / raw)
To: Rob Landley, Nicolas Ferre, Jean-Christophe Plagniol-Villard,
Russell King, Thomas Gleixner, Grant Likely
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@overkiz.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 d43b79f..1dc6ed3 100644
--- a/arch/arm/mach-at91/pm.c
+++ b/arch/arm/mach-at91/pm.c
@@ -207,16 +207,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) {
/*
@@ -281,12 +284,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 7d3f7cc..fa98176 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] 11+ messages in thread
* [RFC PATCH 05/10] ARM: at91: make use of the new AIC driver for dt enabled boards
[not found] ` <1387225461-6201-1-git-send-email-b.brezillon-ZNYIgs0QAGpBDgjK7y7TUQ@public.gmane.org>
2013-12-16 20:24 ` [RFC PATCH 02/10] irqchip: atmel-aic: add new atmel AIC driver Boris BREZILLON
@ 2013-12-16 20:24 ` Boris BREZILLON
2013-12-16 21:25 ` [RFC PATCH 10/10] ARM: at91/dt: add new AIC irq mux definitions for sama5 SoCs Boris BREZILLON
2 siblings, 0 replies; 11+ messages in thread
From: Boris BREZILLON @ 2013-12-16 20:24 UTC (permalink / raw)
To: Rob Landley, Nicolas Ferre, Jean-Christophe Plagniol-Villard,
Russell King, Thomas Gleixner, Grant Likely
Cc: Boris BREZILLON, devicetree-u79uwXL29TY76Z2rM5mHXA,
linux-doc-u79uwXL29TY76Z2rM5mHXA,
linux-kernel-u79uwXL29TY76Z2rM5mHXA,
linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r
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-ZNYIgs0QAGpBDgjK7y7TUQ@public.gmane.org>
---
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 e1e6ff4..80da78c 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
@@ -194,7 +201,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.
@@ -203,7 +209,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.
@@ -212,7 +217,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
--
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 related [flat|nested] 11+ messages in thread
* [RFC PATCH 06/10] irqchip: atmel-aic: move binding doc to interrupt-controller directory
2013-12-16 20:24 [RFC PATCH 00/10] ARM: at91: move aic driver to drivers/irqchips Boris BREZILLON
` (2 preceding siblings ...)
2013-12-16 20:24 ` [RFC PATCH 04/10] ARM: at91: enclose at91_aic_xx calls in IS_ENABLED(CONFIG_OLD_IRQ_AT91) blocks Boris BREZILLON
@ 2013-12-16 20:24 ` Boris BREZILLON
2013-12-16 20:24 ` [RFC PATCH 07/10] irqchip: atmel-aic: document new dt properties and children nodes Boris BREZILLON
` (3 subsequent siblings)
7 siblings, 0 replies; 11+ messages in thread
From: Boris BREZILLON @ 2013-12-16 20:24 UTC (permalink / raw)
To: Rob Landley, Nicolas Ferre, Jean-Christophe Plagniol-Villard,
Russell King, Thomas Gleixner, Grant Likely
Cc: Boris BREZILLON, devicetree, linux-doc, linux-kernel,
linux-arm-kernel
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@overkiz.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] 11+ messages in thread
* [RFC PATCH 07/10] irqchip: atmel-aic: document new dt properties and children nodes
2013-12-16 20:24 [RFC PATCH 00/10] ARM: at91: move aic driver to drivers/irqchips Boris BREZILLON
` (3 preceding siblings ...)
2013-12-16 20:24 ` [RFC PATCH 06/10] irqchip: atmel-aic: move binding doc to interrupt-controller directory Boris BREZILLON
@ 2013-12-16 20:24 ` Boris BREZILLON
2013-12-16 20:24 ` [RFC PATCH 08/10] ARM: at91: remove old irq material Boris BREZILLON
` (2 subsequent siblings)
7 siblings, 0 replies; 11+ messages in thread
From: Boris BREZILLON @ 2013-12-16 20:24 UTC (permalink / raw)
To: Rob Landley, Nicolas Ferre, Jean-Christophe Plagniol-Villard,
Russell King, Thomas Gleixner, Grant Likely
Cc: Boris BREZILLON, devicetree, linux-doc, linux-kernel,
linux-arm-kernel
Add irq muxing and irq-mapping dt binding documentation.
Signed-off-by: Boris BREZILLON <b.brezillon@overkiz.com>
---
.../bindings/interrupt-controller/atmel,aic.txt | 45 ++++++++++++++++++++
1 file changed, 45 insertions(+)
diff --git a/Documentation/devicetree/bindings/interrupt-controller/atmel,aic.txt b/Documentation/devicetree/bindings/interrupt-controller/atmel,aic.txt
index ad03121..63258c6 100644
--- a/Documentation/devicetree/bindings/interrupt-controller/atmel,aic.txt
+++ b/Documentation/devicetree/bindings/interrupt-controller/atmel,aic.txt
@@ -17,8 +17,36 @@ 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 1 (used to represent the irq line id when defining
+ irq-mux nodes).
+- #size-cells: Shall be 0.
- 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:
+- irq-mux nodes:
+ Required properties:
+ * compatible: Should be "atmel,aic-mux"
+
+ 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
+ + atmel,aic-mux-irq-reg: represent the disable or mode register used to
+ disable the given muxed irq.
+ The first cell is a phandle to the device node owning the muxed irq.
+ The second cell is the iomem range index.
+ The third cell is the disable or mode register offset.
+ The fourth cell is the mask used to disable the irq.
+
Examples:
/*
* AIC
@@ -29,6 +57,23 @@ Examples:
interrupt-parent;
#interrupt-cells = <3>;
reg = <0xfffff000 0x200>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ sysc_irq_mux: irq-mux@1 {
+ compatible = "atmel,aic-mux";
+ reg = <1>;
+
+ dbgu_irq {
+ compatible = "atmel,aic-mux-3reg-irq";
+ atmel,aic-mux-irq-reg = <&dbgu 0 0xc 0xc0001afb>;
+ };
+
+ pmc_irq {
+ compatible = "atmel,aic-mux-3reg-irq";
+ atmel,aic-mux-irq-reg = <&pmc 0 0x64 0xf0f>;
+ };
+ };
};
/*
--
1.7.9.5
^ permalink raw reply related [flat|nested] 11+ messages in thread
* [RFC PATCH 08/10] ARM: at91: remove old irq material
2013-12-16 20:24 [RFC PATCH 00/10] ARM: at91: move aic driver to drivers/irqchips Boris BREZILLON
` (4 preceding siblings ...)
2013-12-16 20:24 ` [RFC PATCH 07/10] irqchip: atmel-aic: document new dt properties and children nodes Boris BREZILLON
@ 2013-12-16 20:24 ` Boris BREZILLON
2013-12-16 20:24 ` [RFC PATCH 09/10] ARM: at91/dt: add new AIC irq mux definitions Boris BREZILLON
[not found] ` <1387225461-6201-1-git-send-email-b.brezillon-ZNYIgs0QAGpBDgjK7y7TUQ@public.gmane.org>
7 siblings, 0 replies; 11+ messages in thread
From: Boris BREZILLON @ 2013-12-16 20:24 UTC (permalink / raw)
To: Rob Landley, Nicolas Ferre, Jean-Christophe Plagniol-Villard,
Russell King, Thomas Gleixner, Grant Likely
Cc: Boris BREZILLON, devicetree, linux-doc, linux-kernel,
linux-arm-kernel
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@overkiz.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] 11+ messages in thread
* [RFC PATCH 09/10] ARM: at91/dt: add new AIC irq mux definitions
2013-12-16 20:24 [RFC PATCH 00/10] ARM: at91: move aic driver to drivers/irqchips Boris BREZILLON
` (5 preceding siblings ...)
2013-12-16 20:24 ` [RFC PATCH 08/10] ARM: at91: remove old irq material Boris BREZILLON
@ 2013-12-16 20:24 ` Boris BREZILLON
[not found] ` <1387225461-6201-1-git-send-email-b.brezillon-ZNYIgs0QAGpBDgjK7y7TUQ@public.gmane.org>
7 siblings, 0 replies; 11+ messages in thread
From: Boris BREZILLON @ 2013-12-16 20:24 UTC (permalink / raw)
To: Rob Landley, Nicolas Ferre, Jean-Christophe Plagniol-Villard,
Russell King, Thomas Gleixner, Grant Likely
Cc: Boris BREZILLON, devicetree, linux-doc, linux-kernel,
linux-arm-kernel
Add irq line muxing definition for sam9x5 SoCs.
Signed-off-by: Boris BREZILLON <b.brezillon@overkiz.com>
---
arch/arm/boot/dts/at91sam9x5.dtsi | 111 ++++++++++++++++++++++++++++++++++++-
1 file changed, 109 insertions(+), 2 deletions(-)
diff --git a/arch/arm/boot/dts/at91sam9x5.dtsi b/arch/arm/boot/dts/at91sam9x5.dtsi
index 40267a1..619e24a 100644
--- a/arch/arm/boot/dts/at91sam9x5.dtsi
+++ b/arch/arm/boot/dts/at91sam9x5.dtsi
@@ -68,6 +68,113 @@
interrupt-controller;
reg = <0xfffff000 0x200>;
atmel,external-irqs = <31>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ sysc_irq_mux: irq-mux@1 {
+ compatible = "atmel,aic-mux";
+ reg = <1>;
+
+ dbgu_irq {
+ compatible = "atmel,aic-mux-3reg-irq";
+ atmel,aic-mux-irq-reg = <&dbgu 0 0xc 0xc00002e3>;
+ };
+
+ pmc_irq {
+ compatible = "atmel,aic-mux-3reg-irq";
+ atmel,aic-mux-irq-reg = <&pmc 0 0x64 0x7034b>;
+ };
+
+ pmecc_irq {
+ compatible = "atmel,aic-mux-3reg-irq";
+ atmel,aic-mux-irq-reg = <&nand0 1 0x20 0x1>;
+ };
+
+ pmerrloc_irq {
+ compatible = "atmel,aic-mux-3reg-irq";
+ atmel,aic-mux-irq-reg = <&nand0 2 0x18 0x1>;
+ };
+
+ pit_irq {
+ compatible = "atmel,aic-mux-1reg-irq";
+ atmel,aic-mux-irq-reg = <&pit 0 0x0 0x2000000>;
+ };
+
+ wdt_irq {
+ compatible = "atmel,aic-mux-1reg-irq";
+ atmel,aic-mux-irq-reg = <&wdt 0 0x4 0x1000>;
+ };
+
+ rtc_irq {
+ compatible = "atmel,aic-mux-3reg-irq";
+ atmel,aic-mux-irq-reg = <&rtc 0 0x24 0x1f>;
+ };
+ };
+
+ pioAB_irq_mux: irq-mux@2 {
+ compatible = "atmel,aic-mux";
+ reg = <2>;
+
+ pioA_irq {
+ compatible = "atmel,aic-mux-3reg-irq";
+ atmel,aic-mux-irq-reg = <&pioA 0 0x44 0xffffffff>;
+ };
+
+ pioB_irq {
+ compatible = "atmel,aic-mux-3reg-irq";
+ atmel,aic-mux-irq-reg = <&pioB 0 0x44 0xffffffff>;
+ };
+ };
+
+ pioCD_irq_mux: irq-mux@3 {
+ compatible = "atmel,aic-mux";
+ reg = <3>;
+
+ pioC_irq {
+ compatible = "atmel,aic-mux-3reg-irq";
+ atmel,aic-mux-irq-reg = <&pioC 0 0x44 0xffffffff>;
+ };
+
+ pioD_irq {
+ compatible = "atmel,aic-mux-3reg-irq";
+ atmel,aic-mux-irq-reg = <&pioD 0 0x44 0xffffffff>;
+ };
+ };
+
+ tcb_irq_mux: irq-mux@17 {
+ compatible = "atmel,aic-mux";
+ reg = <17>;
+
+ tc0_irq {
+ compatible = "atmel,aic-mux-3reg-irq";
+ atmel,aic-mux-irq-reg = <&tcb0 0 0x28 0xff>;
+ };
+
+ tc1_irq {
+ compatible = "atmel,aic-mux-3reg-irq";
+ atmel,aic-mux-irq-reg = <&tcb0 0 0x68 0xff>;
+ };
+
+ tc2_irq {
+ compatible = "atmel,aic-mux-3reg-irq";
+ atmel,aic-mux-irq-reg = <&tcb0 0 0xa8 0xff>;
+ };
+
+ tc3_irq {
+ compatible = "atmel,aic-mux-3reg-irq";
+ atmel,aic-mux-irq-reg = <&tcb1 0 0x28 0xff>;
+ };
+
+ tc4_irq {
+ compatible = "atmel,aic-mux-3reg-irq";
+ atmel,aic-mux-irq-reg = <&tcb1 0 0x68 0xff>;
+ };
+
+ tc5_irq {
+ compatible = "atmel,aic-mux-3reg-irq";
+ atmel,aic-mux-irq-reg = <&tcb1 0 0xa8 0xff>;
+ };
+ };
};
ramc0: ramc@ffffe800 {
@@ -750,13 +857,13 @@
};
};
- watchdog@fffffe40 {
+ wdt: watchdog@fffffe40 {
compatible = "atmel,at91sam9260-wdt";
reg = <0xfffffe40 0x10>;
status = "disabled";
};
- rtc@fffffeb0 {
+ rtc: rtc@fffffeb0 {
compatible = "atmel,at91sam9x5-rtc";
reg = <0xfffffeb0 0x40>;
interrupts = <1 IRQ_TYPE_LEVEL_HIGH 7>;
--
1.7.9.5
^ permalink raw reply related [flat|nested] 11+ messages in thread
* [RFC PATCH 10/10] ARM: at91/dt: add new AIC irq mux definitions for sama5 SoCs
[not found] ` <1387225461-6201-1-git-send-email-b.brezillon-ZNYIgs0QAGpBDgjK7y7TUQ@public.gmane.org>
2013-12-16 20:24 ` [RFC PATCH 02/10] irqchip: atmel-aic: add new atmel AIC driver Boris BREZILLON
2013-12-16 20:24 ` [RFC PATCH 05/10] ARM: at91: make use of the new AIC driver for dt enabled boards Boris BREZILLON
@ 2013-12-16 21:25 ` Boris BREZILLON
2 siblings, 0 replies; 11+ messages in thread
From: Boris BREZILLON @ 2013-12-16 21:25 UTC (permalink / raw)
To: Rob Landley, Nicolas Ferre, Jean-Christophe Plagniol-Villard,
Russell King, Thomas Gleixner, Grant Likely
Cc: Boris BREZILLON, devicetree-u79uwXL29TY76Z2rM5mHXA,
linux-doc-u79uwXL29TY76Z2rM5mHXA,
linux-kernel-u79uwXL29TY76Z2rM5mHXA,
linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r
Add irq line muxing definition for sama5 SoCs.
Signed-off-by: Boris BREZILLON <b.brezillon-ZNYIgs0QAGpBDgjK7y7TUQ@public.gmane.org>
---
arch/arm/boot/dts/sama5d3.dtsi | 40 ++++++++++++++++++++++++++++++++++-
arch/arm/boot/dts/sama5d3_tcb1.dtsi | 22 +++++++++++++++++++
2 files changed, 61 insertions(+), 1 deletion(-)
diff --git a/arch/arm/boot/dts/sama5d3.dtsi b/arch/arm/boot/dts/sama5d3.dtsi
index de9fece..1e8f4b5 100644
--- a/arch/arm/boot/dts/sama5d3.dtsi
+++ b/arch/arm/boot/dts/sama5d3.dtsi
@@ -390,6 +390,44 @@
interrupt-controller;
reg = <0xfffff000 0x200>;
atmel,external-irqs = <47>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ atmel,aic-irq-mapping = <0xffffffff 0x7ffff>;
+
+ sysc_irq_mux: irq-mux@1 {
+ compatible = "atmel,aic-mux";
+ reg = <1>;
+
+ pmc_irq {
+ compatible = "atmel,aic-mux-3reg-irq";
+ atmel,aic-mux-irq-reg = <&pmc 0 0x64 0x5074b>;
+ };
+
+ rtc_irq {
+ compatible = "atmel,aic-mux-3reg-irq";
+ atmel,aic-mux-irq-reg = <&rtc 0 0x24 0x1f>;
+ };
+ };
+
+ tcb0_irq_mux: irq-mux@26 {
+ compatible = "atmel,aic-mux";
+ reg = <26>;
+
+ tc0_irq {
+ compatible = "atmel,aic-mux-3reg-irq";
+ atmel,aic-mux-irq-reg = <&tcb0 0 0x28 0xff>;
+ };
+
+ tc1_irq {
+ compatible = "atmel,aic-mux-3reg-irq";
+ atmel,aic-mux-irq-reg = <&tcb0 0 0x68 0xff>;
+ };
+
+ tc2_irq {
+ compatible = "atmel,aic-mux-3reg-irq";
+ atmel,aic-mux-irq-reg = <&tcb0 0 0xa8 0xff>;
+ };
+ };
};
pinctrl@fffff200 {
@@ -1061,7 +1099,7 @@
status = "disabled";
};
- rtc@fffffeb0 {
+ rtc: rtc@fffffeb0 {
compatible = "atmel,at91rm9200-rtc";
reg = <0xfffffeb0 0x30>;
interrupts = <1 IRQ_TYPE_LEVEL_HIGH 7>;
diff --git a/arch/arm/boot/dts/sama5d3_tcb1.dtsi b/arch/arm/boot/dts/sama5d3_tcb1.dtsi
index 382b044..123b153 100644
--- a/arch/arm/boot/dts/sama5d3_tcb1.dtsi
+++ b/arch/arm/boot/dts/sama5d3_tcb1.dtsi
@@ -18,6 +18,28 @@
ahb {
apb {
+ aic: interrupt-controller@fffff000 {
+ tcb1_irq_mux: irq-mux@27 {
+ compatible = "atmel,aic-mux";
+ reg = <27>;
+
+ tc3_irq {
+ compatible = "atmel,aic-mux-3reg-irq";
+ atmel,aic-mux-irq-reg = <&tcb1 0 0x28 0xff>;
+ };
+
+ tc4_irq {
+ compatible = "atmel,aic-mux-3reg-irq";
+ atmel,aic-mux-irq-reg = <&tcb1 0 0x68 0xff>;
+ };
+
+ tc5_irq {
+ compatible = "atmel,aic-mux-3reg-irq";
+ atmel,aic-mux-irq-reg = <&tcb1 0 0xa8 0xff>;
+ };
+ };
+ };
+
pmc: pmc@fffffc00 {
periphck {
tcb1_clk: tcb1_clk {
--
1.7.9.5
--
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 related [flat|nested] 11+ messages in thread
end of thread, other threads:[~2013-12-16 21:25 UTC | newest]
Thread overview: 11+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2013-12-16 20:24 [RFC PATCH 00/10] ARM: at91: move aic driver to drivers/irqchips Boris BREZILLON
2013-12-16 20:24 ` [RFC PATCH 01/10] genirq: generic chip: export irq_map_generic_chip function Boris BREZILLON
2013-12-16 20:24 ` [RFC PATCH 03/10] ARM: at91: introduce OLD_IRQ_AT91 Kconfig option Boris BREZILLON
2013-12-16 20:24 ` [RFC PATCH 04/10] ARM: at91: enclose at91_aic_xx calls in IS_ENABLED(CONFIG_OLD_IRQ_AT91) blocks Boris BREZILLON
2013-12-16 20:24 ` [RFC PATCH 06/10] irqchip: atmel-aic: move binding doc to interrupt-controller directory Boris BREZILLON
2013-12-16 20:24 ` [RFC PATCH 07/10] irqchip: atmel-aic: document new dt properties and children nodes Boris BREZILLON
2013-12-16 20:24 ` [RFC PATCH 08/10] ARM: at91: remove old irq material Boris BREZILLON
2013-12-16 20:24 ` [RFC PATCH 09/10] ARM: at91/dt: add new AIC irq mux definitions Boris BREZILLON
[not found] ` <1387225461-6201-1-git-send-email-b.brezillon-ZNYIgs0QAGpBDgjK7y7TUQ@public.gmane.org>
2013-12-16 20:24 ` [RFC PATCH 02/10] irqchip: atmel-aic: add new atmel AIC driver Boris BREZILLON
2013-12-16 20:24 ` [RFC PATCH 05/10] ARM: at91: make use of the new AIC driver for dt enabled boards Boris BREZILLON
2013-12-16 21:25 ` [RFC PATCH 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).