aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRich Felker <dalias@libc.org>2016-08-04 00:30:37 -0400
committerJason Cooper <jason@lakedaemon.net>2016-08-08 16:28:11 -0400
commit981b58f66cfcd32dc4ebbaeef8451daf393b6c94 (patch)
tree073e7c0a2ba02297158d60e817b0b4fbb9a272e8
parenta9da291f25f014c8ee999f498305949332d58cd6 (diff)
irqchip/jcore-aic: Add J-Core AIC driver
There are two versions of the J-Core interrupt controller in use, aic1 which generates interrupts with programmable priorities, but only supports 8 irq lines and maps them to cpu traps in the range 17 to 24, and aic2 which uses traps in the range 64-127 and supports up to 128 irqs, with priorities dependent on the interrupt number. The Linux driver does not make use of priorities anyway. For simplicity, there is no aic1-specific logic in the driver beyond setting the priority register, which is necessary for interrupts to work at all. Eventually aic1 will likely be phased out, but it's currently in use in deployments and all released bitstream binaries. Signed-off-by: Rich Felker <dalias@libc.org> Link: https://lkml.kernel.org/r/c3b89ef74aaa6477575dbe2d410eb1d182503243.147018b6529.git.dalias@libc.org Signed-off-by: Jason Cooper <jason@lakedaemon.net>
-rw-r--r--drivers/irqchip/Kconfig7
-rw-r--r--drivers/irqchip/Makefile1
-rw-r--r--drivers/irqchip/irq-jcore-aic.c94
3 files changed, 102 insertions, 0 deletions
diff --git a/drivers/irqchip/Kconfig b/drivers/irqchip/Kconfig
index 7f8728984f44..43bed4e5c7ae 100644
--- a/drivers/irqchip/Kconfig
+++ b/drivers/irqchip/Kconfig
@@ -156,6 +156,13 @@ config PIC32_EVIC
156 select GENERIC_IRQ_CHIP 156 select GENERIC_IRQ_CHIP
157 select IRQ_DOMAIN 157 select IRQ_DOMAIN
158 158
159config JCORE_AIC
160 bool "J-Core integrated AIC"
161 depends on OF && (SUPERH || COMPILE_TEST)
162 select IRQ_DOMAIN
163 help
164 Support for the J-Core integrated AIC.
165
159config RENESAS_INTC_IRQPIN 166config RENESAS_INTC_IRQPIN
160 bool 167 bool
161 select IRQ_DOMAIN 168 select IRQ_DOMAIN
diff --git a/drivers/irqchip/Makefile b/drivers/irqchip/Makefile
index 4c203b6b8163..ee7e3ca0ac23 100644
--- a/drivers/irqchip/Makefile
+++ b/drivers/irqchip/Makefile
@@ -40,6 +40,7 @@ obj-$(CONFIG_I8259) += irq-i8259.o
40obj-$(CONFIG_IMGPDC_IRQ) += irq-imgpdc.o 40obj-$(CONFIG_IMGPDC_IRQ) += irq-imgpdc.o
41obj-$(CONFIG_IRQ_MIPS_CPU) += irq-mips-cpu.o 41obj-$(CONFIG_IRQ_MIPS_CPU) += irq-mips-cpu.o
42obj-$(CONFIG_SIRF_IRQ) += irq-sirfsoc.o 42obj-$(CONFIG_SIRF_IRQ) += irq-sirfsoc.o
43obj-$(CONFIG_JCORE_AIC) += irq-jcore-aic.o
43obj-$(CONFIG_RENESAS_INTC_IRQPIN) += irq-renesas-intc-irqpin.o 44obj-$(CONFIG_RENESAS_INTC_IRQPIN) += irq-renesas-intc-irqpin.o
44obj-$(CONFIG_RENESAS_IRQC) += irq-renesas-irqc.o 45obj-$(CONFIG_RENESAS_IRQC) += irq-renesas-irqc.o
45obj-$(CONFIG_VERSATILE_FPGA_IRQ) += irq-versatile-fpga.o 46obj-$(CONFIG_VERSATILE_FPGA_IRQ) += irq-versatile-fpga.o
diff --git a/drivers/irqchip/irq-jcore-aic.c b/drivers/irqchip/irq-jcore-aic.c
new file mode 100644
index 000000000000..5e5e3bb7d3c7
--- /dev/null
+++ b/drivers/irqchip/irq-jcore-aic.c
@@ -0,0 +1,94 @@
1/*
2 * J-Core SoC AIC driver
3 *
4 * Copyright (C) 2015-2016 Smart Energy Instruments, Inc.
5 *
6 * This file is subject to the terms and conditions of the GNU General Public
7 * License. See the file "COPYING" in the main directory of this archive
8 * for more details.
9 */
10
11#include <linux/irq.h>
12#include <linux/io.h>
13#include <linux/irqchip.h>
14#include <linux/irqdomain.h>
15#include <linux/cpu.h>
16#include <linux/of.h>
17#include <linux/of_address.h>
18#include <linux/of_irq.h>
19
20#define JCORE_AIC_MAX_HWIRQ 127
21#define JCORE_AIC1_MIN_HWIRQ 16
22#define JCORE_AIC2_MIN_HWIRQ 64
23
24#define JCORE_AIC1_INTPRI_REG 8
25
26static struct irq_chip jcore_aic;
27
28static int jcore_aic_irqdomain_map(struct irq_domain *d, unsigned int irq,
29 irq_hw_number_t hwirq)
30{
31 struct irq_chip *aic = d->host_data;
32
33 irq_set_chip_and_handler(irq, aic, handle_simple_irq);
34
35 return 0;
36}
37
38static const struct irq_domain_ops jcore_aic_irqdomain_ops = {
39 .map = jcore_aic_irqdomain_map,
40 .xlate = irq_domain_xlate_onecell,
41};
42
43static void noop(struct irq_data *data)
44{
45}
46
47int __init aic_irq_of_init(struct device_node *node, struct device_node *parent)
48{
49 unsigned min_irq = JCORE_AIC2_MIN_HWIRQ;
50 unsigned dom_sz = JCORE_AIC_MAX_HWIRQ+1;
51 struct irq_domain *domain;
52
53 pr_info("Initializing J-Core AIC\n");
54
55 /* AIC1 needs priority initialization to receive interrupts. */
56 if (of_device_is_compatible(node, "jcore,aic1")) {
57 unsigned cpu;
58
59 for_each_present_cpu(cpu) {
60 void __iomem *base = of_iomap(node, cpu);
61
62 if (!base) {
63 pr_err("Unable to map AIC for cpu %u\n", cpu);
64 return -ENOMEM;
65 }
66 __raw_writel(0xffffffff, base + JCORE_AIC1_INTPRI_REG);
67 iounmap(base);
68 }
69 min_irq = JCORE_AIC1_MIN_HWIRQ;
70 }
71
72 /*
73 * The irq chip framework requires either mask/unmask or enable/disable
74 * function pointers to be provided, but the hardware does not have any
75 * such mechanism; the only interrupt masking is at the cpu level and
76 * it affects all interrupts. We provide dummy mask/unmask. The hardware
77 * handles all interrupt control and clears pending status when the cpu
78 * accepts the interrupt.
79 */
80 jcore_aic.irq_mask = noop;
81 jcore_aic.irq_unmask = noop;
82 jcore_aic.name = "AIC";
83
84 domain = irq_domain_add_linear(node, dom_sz, &jcore_aic_irqdomain_ops,
85 &jcore_aic);
86 if (!domain)
87 return -ENOMEM;
88 irq_create_strict_mappings(domain, min_irq, min_irq, dom_sz - min_irq);
89
90 return 0;
91}
92
93IRQCHIP_DECLARE(jcore_aic2, "jcore,aic2", aic_irq_of_init);
94IRQCHIP_DECLARE(jcore_aic1, "jcore,aic1", aic_irq_of_init);