aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDaniel Tang <dt.tangr@gmail.com>2013-12-05 01:12:17 -0500
committerThomas Gleixner <tglx@linutronix.de>2014-01-22 15:48:55 -0500
commit397e7b515785cad6e10b29f3001fd80c3f519bb8 (patch)
tree14efaf3aedfb75f343135941c1275d995e0fa6bf
parent43881ec7a88a3d3b2fd6da58168173e135b41fba (diff)
irqchip: Add support for TI-NSPIRE irqchip
This patch adds support for the interrupt controllers found in some TI-Nspire models. FIQ support was taken out to simplify the driver code and may be added in later. Since Linux on this platform doesn't really use FIQs, this wasn't really that important in the first place. [ tglx: Made zevio_handle_irq static and reordered __init functions ] Signed-off-by: Daniel Tang <dt.tangr@gmail.com> Acked-by: Grant Likely <grant.likely@secretlab.ca> Link: http://lkml.kernel.org/r/1386223937-12189-1-git-send-email-dt.tangr@gmail.com Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
-rw-r--r--Documentation/devicetree/bindings/interrupt-controller/lsi,zevio-intc.txt18
-rw-r--r--drivers/irqchip/Makefile1
-rw-r--r--drivers/irqchip/irq-zevio.c127
3 files changed, 146 insertions, 0 deletions
diff --git a/Documentation/devicetree/bindings/interrupt-controller/lsi,zevio-intc.txt b/Documentation/devicetree/bindings/interrupt-controller/lsi,zevio-intc.txt
new file mode 100644
index 000000000000..aee38e7c13e7
--- /dev/null
+++ b/Documentation/devicetree/bindings/interrupt-controller/lsi,zevio-intc.txt
@@ -0,0 +1,18 @@
1TI-NSPIRE interrupt controller
2
3Required properties:
4- compatible: Compatible property value should be "lsi,zevio-intc".
5
6- reg: Physical base address of the controller and length of memory mapped
7 region.
8
9- interrupt-controller : Identifies the node as an interrupt controller
10
11Example:
12
13interrupt-controller {
14 compatible = "lsi,zevio-intc";
15 interrupt-controller;
16 reg = <0xDC000000 0x1000>;
17 #interrupt-cells = <1>;
18};
diff --git a/drivers/irqchip/Makefile b/drivers/irqchip/Makefile
index c60b9010b152..292b10645fd8 100644
--- a/drivers/irqchip/Makefile
+++ b/drivers/irqchip/Makefile
@@ -20,5 +20,6 @@ obj-$(CONFIG_SIRF_IRQ) += irq-sirfsoc.o
20obj-$(CONFIG_RENESAS_INTC_IRQPIN) += irq-renesas-intc-irqpin.o 20obj-$(CONFIG_RENESAS_INTC_IRQPIN) += irq-renesas-intc-irqpin.o
21obj-$(CONFIG_RENESAS_IRQC) += irq-renesas-irqc.o 21obj-$(CONFIG_RENESAS_IRQC) += irq-renesas-irqc.o
22obj-$(CONFIG_VERSATILE_FPGA_IRQ) += irq-versatile-fpga.o 22obj-$(CONFIG_VERSATILE_FPGA_IRQ) += irq-versatile-fpga.o
23obj-$(CONFIG_ARCH_NSPIRE) += irq-zevio.o
23obj-$(CONFIG_ARCH_VT8500) += irq-vt8500.o 24obj-$(CONFIG_ARCH_VT8500) += irq-vt8500.o
24obj-$(CONFIG_TB10X_IRQC) += irq-tb10x.o 25obj-$(CONFIG_TB10X_IRQC) += irq-tb10x.o
diff --git a/drivers/irqchip/irq-zevio.c b/drivers/irqchip/irq-zevio.c
new file mode 100644
index 000000000000..8ed04c4a43ee
--- /dev/null
+++ b/drivers/irqchip/irq-zevio.c
@@ -0,0 +1,127 @@
1/*
2 * linux/drivers/irqchip/irq-zevio.c
3 *
4 * Copyright (C) 2013 Daniel Tang <tangrs@tangrs.id.au>
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 2, as
8 * published by the Free Software Foundation.
9 *
10 */
11
12#include <linux/io.h>
13#include <linux/irq.h>
14#include <linux/of.h>
15#include <linux/of_address.h>
16#include <linux/of_irq.h>
17
18#include <asm/mach/irq.h>
19#include <asm/exception.h>
20
21#include "irqchip.h"
22
23#define IO_STATUS 0x000
24#define IO_RAW_STATUS 0x004
25#define IO_ENABLE 0x008
26#define IO_DISABLE 0x00C
27#define IO_CURRENT 0x020
28#define IO_RESET 0x028
29#define IO_MAX_PRIOTY 0x02C
30
31#define IO_IRQ_BASE 0x000
32#define IO_FIQ_BASE 0x100
33
34#define IO_INVERT_SEL 0x200
35#define IO_STICKY_SEL 0x204
36#define IO_PRIORITY_SEL 0x300
37
38#define MAX_INTRS 32
39#define FIQ_START MAX_INTRS
40
41static struct irq_domain *zevio_irq_domain;
42static void __iomem *zevio_irq_io;
43
44static void zevio_irq_ack(struct irq_data *irqd)
45{
46 struct irq_chip_generic *gc = irq_data_get_irq_chip_data(irqd);
47 struct irq_chip_regs *regs =
48 &container_of(irqd->chip, struct irq_chip_type, chip)->regs;
49
50 readl(gc->reg_base + regs->ack);
51}
52
53static asmlinkage void __exception_irq_entry zevio_handle_irq(struct pt_regs *regs)
54{
55 int irqnr;
56
57 while (readl(zevio_irq_io + IO_STATUS)) {
58 irqnr = readl(zevio_irq_io + IO_CURRENT);
59 irqnr = irq_find_mapping(zevio_irq_domain, irqnr);
60 handle_IRQ(irqnr, regs);
61 };
62}
63
64static void __init zevio_init_irq_base(void __iomem *base)
65{
66 /* Disable all interrupts */
67 writel(~0, base + IO_DISABLE);
68
69 /* Accept interrupts of all priorities */
70 writel(0xF, base + IO_MAX_PRIOTY);
71
72 /* Reset existing interrupts */
73 readl(base + IO_RESET);
74}
75
76static int __init zevio_of_init(struct device_node *node,
77 struct device_node *parent)
78{
79 unsigned int clr = IRQ_NOREQUEST | IRQ_NOPROBE | IRQ_NOAUTOEN;
80 struct irq_chip_generic *gc;
81 int ret;
82
83 if (WARN_ON(zevio_irq_io || zevio_irq_domain))
84 return -EBUSY;
85
86 zevio_irq_io = of_iomap(node, 0);
87 BUG_ON(!zevio_irq_io);
88
89 /* Do not invert interrupt status bits */
90 writel(~0, zevio_irq_io + IO_INVERT_SEL);
91
92 /* Disable sticky interrupts */
93 writel(0, zevio_irq_io + IO_STICKY_SEL);
94
95 /* We don't use IRQ priorities. Set each IRQ to highest priority. */
96 memset_io(zevio_irq_io + IO_PRIORITY_SEL, 0, MAX_INTRS * sizeof(u32));
97
98 /* Init IRQ and FIQ */
99 zevio_init_irq_base(zevio_irq_io + IO_IRQ_BASE);
100 zevio_init_irq_base(zevio_irq_io + IO_FIQ_BASE);
101
102 zevio_irq_domain = irq_domain_add_linear(node, MAX_INTRS,
103 &irq_generic_chip_ops, NULL);
104 BUG_ON(!zevio_irq_domain);
105
106 ret = irq_alloc_domain_generic_chips(zevio_irq_domain, MAX_INTRS, 1,
107 "zevio_intc", handle_level_irq,
108 clr, 0, IRQ_GC_INIT_MASK_CACHE);
109 BUG_ON(ret);
110
111 gc = irq_get_domain_generic_chip(zevio_irq_domain, 0);
112 gc->reg_base = zevio_irq_io;
113 gc->chip_types[0].chip.irq_ack = zevio_irq_ack;
114 gc->chip_types[0].chip.irq_mask = irq_gc_mask_disable_reg;
115 gc->chip_types[0].chip.irq_unmask = irq_gc_unmask_enable_reg;
116 gc->chip_types[0].regs.mask = IO_IRQ_BASE + IO_ENABLE;
117 gc->chip_types[0].regs.enable = IO_IRQ_BASE + IO_ENABLE;
118 gc->chip_types[0].regs.disable = IO_IRQ_BASE + IO_DISABLE;
119 gc->chip_types[0].regs.ack = IO_IRQ_BASE + IO_RESET;
120
121 set_handle_irq(zevio_handle_irq);
122
123 pr_info("TI-NSPIRE classic IRQ controller\n");
124 return 0;
125}
126
127IRQCHIP_DECLARE(zevio_irq, "lsi,zevio-intc", zevio_of_init);