[PATCH 07/13] m68k: coldfire: support devicetree binding for intc-2 controller

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Add code support to the ColdFire intc-2 interrupt controller so that
it can be mapped via a devicetree binding.

This is implemented by adding IRQCHIP and IRQ_DOMAIN support. This first
version does not completely setup the interrupt controller using the IO
mapping binding passed in via the devicetree. Future changes will add
that.

Devicetree support is not yet enabled for ColdFire targets so this
interrupt controller code still supports the legacy setup for now.

Signed-off-by: Greg Ungerer <gerg@xxxxxxxxxxxxxx>
---
 arch/m68k/coldfire/intc-2.c | 59 ++++++++++++++++++++++++++++++-------
 1 file changed, 49 insertions(+), 10 deletions(-)

diff --git a/arch/m68k/coldfire/intc-2.c b/arch/m68k/coldfire/intc-2.c
index f74f0e473119..ac29106dc166 100644
--- a/arch/m68k/coldfire/intc-2.c
+++ b/arch/m68k/coldfire/intc-2.c
@@ -21,8 +21,11 @@
 #include <linux/init.h>
 #include <linux/kernel.h>
 #include <linux/interrupt.h>
-#include <linux/irq.h>
 #include <linux/io.h>
+#include <linux/irq.h>
+#include <linux/irqchip.h>
+#include <linux/of.h>
+#include <linux/of_irq.h>
 #include <asm/coldfire.h>
 #include <asm/mcfsim.h>
 #include <asm/traps.h>
@@ -49,7 +52,7 @@
 
 static void intc_irq_mask(struct irq_data *d)
 {
-	unsigned int irq = d->irq - MCFINT_VECBASE;
+	unsigned int irq = d->hwirq - MCFINT_VECBASE;
 	unsigned long imraddr;
 	u32 val, imrbit;
 
@@ -67,7 +70,7 @@ static void intc_irq_mask(struct irq_data *d)
 
 static void intc_irq_unmask(struct irq_data *d)
 {
-	unsigned int irq = d->irq - MCFINT_VECBASE;
+	unsigned int irq = d->hwirq - MCFINT_VECBASE;
 	unsigned long imraddr;
 	u32 val, imrbit;
 
@@ -95,7 +98,7 @@ static void intc_irq_unmask(struct irq_data *d)
  */
 static void intc_irq_ack(struct irq_data *d)
 {
-	unsigned int irq = d->irq;
+	unsigned int irq = d->hwirq;
 
 	__raw_writeb(0x1 << (irq - EINT0), MCFEPORT_EPFR);
 }
@@ -111,7 +114,7 @@ static u8 intc_intpri = MCFSIM_ICR_LEVEL(6) | MCFSIM_ICR_PRI(6);
 
 static unsigned int intc_irq_startup(struct irq_data *d)
 {
-	unsigned int irq = d->irq - MCFINT_VECBASE;
+	unsigned int irq = d->hwirq - MCFINT_VECBASE;
 	unsigned long icraddr;
 
 #ifdef MCFICM_INTC1
@@ -123,7 +126,7 @@ static unsigned int intc_irq_startup(struct irq_data *d)
 	if (__raw_readb(icraddr) == 0)
 		__raw_writeb(intc_intpri--, icraddr);
 
-	irq = d->irq;
+	irq = d->hwirq;
 	if ((irq >= EINT1) && (irq <= EINT7)) {
 		u8 v;
 
@@ -144,7 +147,7 @@ static unsigned int intc_irq_startup(struct irq_data *d)
 
 static int intc_irq_set_type(struct irq_data *d, unsigned int type)
 {
-	unsigned int irq = d->irq;
+	unsigned int irq = d->hwirq;
 	u16 pa, tb;
 
 	switch (type) {
@@ -192,21 +195,57 @@ static struct irq_chip intc_irq_chip_edge_port = {
 
 void __init init_IRQ(void)
 {
-	int irq;
-
 	/* Mask all interrupt sources */
 	__raw_writel(0x1, MCFICM_INTC0 + MCFINTC_IMRL);
 #ifdef MCFICM_INTC1
 	__raw_writel(0x1, MCFICM_INTC1 + MCFINTC_IMRL);
 #endif
 
+#ifdef CONFIG_IRQCHIP
+	irqchip_init();
+#else
+	int irq;
 	for (irq = MCFINT_VECBASE; (irq < MCFINT_VECBASE + NR_VECS); irq++) {
-		if ((irq >= EINT1) && (irq <=EINT7))
+		if ((irq >= EINT1) && (irq <= EINT7))
 			irq_set_chip(irq, &intc_irq_chip_edge_port);
 		else
 			irq_set_chip(irq, &intc_irq_chip);
 		irq_set_irq_type(irq, IRQ_TYPE_LEVEL_HIGH);
 		irq_set_handler(irq, handle_level_irq);
 	}
+#endif
+}
+
+#ifdef CONFIG_IRQ_DOMAIN
+static int intc_domain_map(struct irq_domain *d,
+			   unsigned int irq,
+			   irq_hw_number_t hw)
+{
+	if ((irq >= EINT1) && (irq <= EINT7))
+		irq_set_chip_and_handler(irq, &intc_irq_chip_edge_port, handle_level_irq);
+	else
+		irq_set_chip_and_handler(irq, &intc_irq_chip, handle_level_irq);
+	return 0;
+}
+
+static const struct irq_domain_ops intc_irqdomain_ops = {
+	.map = intc_domain_map,
+};
+
+static int __init intc_of_init(struct device_node *np,
+			       struct device_node *parent)
+{
+	const unsigned int num = MCFINT_VECBASE + NR_IRQS;
+	struct irq_domain *domain;
+	int irq;
+
+	domain = irq_domain_add_linear(np, num, &intc_irqdomain_ops, NULL);
+
+	for (irq = MCFINT_VECBASE; irq < num; irq++)
+		irq_create_mapping(domain, irq);
+
+	return 0;
 }
 
+IRQCHIP_DECLARE(intc, "fsl,intc-2", intc_of_init);
+#endif /* CONFIG_IRQ_DOMAIN */
-- 
2.43.0





[Index of Archives]     [Video for Linux]     [Yosemite News]     [Linux S/390]     [Linux Kernel]     [Linux SCSI]

  Powered by Linux