devicetree.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [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).