aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/irqchip
diff options
context:
space:
mode:
authorMaxime Ripard <maxime.ripard@free-electrons.com>2013-03-24 05:10:04 -0400
committerMaxime Ripard <maxime.ripard@free-electrons.com>2013-04-08 15:42:46 -0400
commitd7fbc6ca35db027345a0e066c54b367e31d4fed3 (patch)
tree2414ada8047c3599413b04cbf454674941c03563 /drivers/irqchip
parentf1dc6c4f77678979868fe220c6913890e13473d8 (diff)
irqchip: sunxi: Rename sunxi to sun4i
During the introduction of the Allwinner SoC platforms, sunxi was initially meant as a generic name for all the variants of the Allwinner SoC. It was ok at the time of the support of only the A10 and A13 that looks pretty much the same, but it's beginning to be troublesome with the future addition of the Allwinner A31 (sun6i) that is quite different, and would introduce some weird logic, where sunxi would actually mean in some case sun4i and sun5i but without sun6i... Moreover, it makes the compatible strings naming scheme not consistent with other architectures, where usually for this kind of compability, we just use the oldest SoC name that has this IP, so let's do just this. Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com>
Diffstat (limited to 'drivers/irqchip')
-rw-r--r--drivers/irqchip/Makefile2
-rw-r--r--drivers/irqchip/irq-sun4i.c149
-rw-r--r--drivers/irqchip/irq-sunxi.c149
3 files changed, 150 insertions, 150 deletions
diff --git a/drivers/irqchip/Makefile b/drivers/irqchip/Makefile
index 98e3b87bdf1b..54169650f55e 100644
--- a/drivers/irqchip/Makefile
+++ b/drivers/irqchip/Makefile
@@ -4,7 +4,7 @@ obj-$(CONFIG_ARCH_BCM2835) += irq-bcm2835.o
4obj-$(CONFIG_ARCH_EXYNOS) += exynos-combiner.o 4obj-$(CONFIG_ARCH_EXYNOS) += exynos-combiner.o
5obj-$(CONFIG_METAG) += irq-metag-ext.o 5obj-$(CONFIG_METAG) += irq-metag-ext.o
6obj-$(CONFIG_METAG_PERFCOUNTER_IRQS) += irq-metag.o 6obj-$(CONFIG_METAG_PERFCOUNTER_IRQS) += irq-metag.o
7obj-$(CONFIG_ARCH_SUNXI) += irq-sunxi.o 7obj-$(CONFIG_ARCH_SUNXI) += irq-sun4i.o
8obj-$(CONFIG_ARCH_SPEAR3XX) += spear-shirq.o 8obj-$(CONFIG_ARCH_SPEAR3XX) += spear-shirq.o
9obj-$(CONFIG_ARM_GIC) += irq-gic.o 9obj-$(CONFIG_ARM_GIC) += irq-gic.o
10obj-$(CONFIG_ARM_VIC) += irq-vic.o 10obj-$(CONFIG_ARM_VIC) += irq-vic.o
diff --git a/drivers/irqchip/irq-sun4i.c b/drivers/irqchip/irq-sun4i.c
new file mode 100644
index 000000000000..b66d4ae06898
--- /dev/null
+++ b/drivers/irqchip/irq-sun4i.c
@@ -0,0 +1,149 @@
1/*
2 * Allwinner A1X SoCs IRQ chip driver.
3 *
4 * Copyright (C) 2012 Maxime Ripard
5 *
6 * Maxime Ripard <maxime.ripard@free-electrons.com>
7 *
8 * Based on code from
9 * Allwinner Technology Co., Ltd. <www.allwinnertech.com>
10 * Benn Huang <benn@allwinnertech.com>
11 *
12 * This file is licensed under the terms of the GNU General Public
13 * License version 2. This program is licensed "as is" without any
14 * warranty of any kind, whether express or implied.
15 */
16
17#include <linux/io.h>
18#include <linux/irq.h>
19#include <linux/of.h>
20#include <linux/of_address.h>
21#include <linux/of_irq.h>
22
23#include <asm/exception.h>
24#include <asm/mach/irq.h>
25
26#include "irqchip.h"
27
28#define SUN4I_IRQ_VECTOR_REG 0x00
29#define SUN4I_IRQ_PROTECTION_REG 0x08
30#define SUN4I_IRQ_NMI_CTRL_REG 0x0c
31#define SUN4I_IRQ_PENDING_REG(x) (0x10 + 0x4 * x)
32#define SUN4I_IRQ_FIQ_PENDING_REG(x) (0x20 + 0x4 * x)
33#define SUN4I_IRQ_ENABLE_REG(x) (0x40 + 0x4 * x)
34#define SUN4I_IRQ_MASK_REG(x) (0x50 + 0x4 * x)
35
36static void __iomem *sun4i_irq_base;
37static struct irq_domain *sun4i_irq_domain;
38
39static asmlinkage void __exception_irq_entry sun4i_handle_irq(struct pt_regs *regs);
40
41void sun4i_irq_ack(struct irq_data *irqd)
42{
43 unsigned int irq = irqd_to_hwirq(irqd);
44 unsigned int irq_off = irq % 32;
45 int reg = irq / 32;
46 u32 val;
47
48 val = readl(sun4i_irq_base + SUN4I_IRQ_PENDING_REG(reg));
49 writel(val | (1 << irq_off),
50 sun4i_irq_base + SUN4I_IRQ_PENDING_REG(reg));
51}
52
53static void sun4i_irq_mask(struct irq_data *irqd)
54{
55 unsigned int irq = irqd_to_hwirq(irqd);
56 unsigned int irq_off = irq % 32;
57 int reg = irq / 32;
58 u32 val;
59
60 val = readl(sun4i_irq_base + SUN4I_IRQ_ENABLE_REG(reg));
61 writel(val & ~(1 << irq_off),
62 sun4i_irq_base + SUN4I_IRQ_ENABLE_REG(reg));
63}
64
65static void sun4i_irq_unmask(struct irq_data *irqd)
66{
67 unsigned int irq = irqd_to_hwirq(irqd);
68 unsigned int irq_off = irq % 32;
69 int reg = irq / 32;
70 u32 val;
71
72 val = readl(sun4i_irq_base + SUN4I_IRQ_ENABLE_REG(reg));
73 writel(val | (1 << irq_off),
74 sun4i_irq_base + SUN4I_IRQ_ENABLE_REG(reg));
75}
76
77static struct irq_chip sun4i_irq_chip = {
78 .name = "sun4i_irq",
79 .irq_ack = sun4i_irq_ack,
80 .irq_mask = sun4i_irq_mask,
81 .irq_unmask = sun4i_irq_unmask,
82};
83
84static int sun4i_irq_map(struct irq_domain *d, unsigned int virq,
85 irq_hw_number_t hw)
86{
87 irq_set_chip_and_handler(virq, &sun4i_irq_chip,
88 handle_level_irq);
89 set_irq_flags(virq, IRQF_VALID | IRQF_PROBE);
90
91 return 0;
92}
93
94static struct irq_domain_ops sun4i_irq_ops = {
95 .map = sun4i_irq_map,
96 .xlate = irq_domain_xlate_onecell,
97};
98
99static int __init sun4i_of_init(struct device_node *node,
100 struct device_node *parent)
101{
102 sun4i_irq_base = of_iomap(node, 0);
103 if (!sun4i_irq_base)
104 panic("%s: unable to map IC registers\n",
105 node->full_name);
106
107 /* Disable all interrupts */
108 writel(0, sun4i_irq_base + SUN4I_IRQ_ENABLE_REG(0));
109 writel(0, sun4i_irq_base + SUN4I_IRQ_ENABLE_REG(1));
110 writel(0, sun4i_irq_base + SUN4I_IRQ_ENABLE_REG(2));
111
112 /* Mask all the interrupts */
113 writel(0, sun4i_irq_base + SUN4I_IRQ_MASK_REG(0));
114 writel(0, sun4i_irq_base + SUN4I_IRQ_MASK_REG(1));
115 writel(0, sun4i_irq_base + SUN4I_IRQ_MASK_REG(2));
116
117 /* Clear all the pending interrupts */
118 writel(0xffffffff, sun4i_irq_base + SUN4I_IRQ_PENDING_REG(0));
119 writel(0xffffffff, sun4i_irq_base + SUN4I_IRQ_PENDING_REG(1));
120 writel(0xffffffff, sun4i_irq_base + SUN4I_IRQ_PENDING_REG(2));
121
122 /* Enable protection mode */
123 writel(0x01, sun4i_irq_base + SUN4I_IRQ_PROTECTION_REG);
124
125 /* Configure the external interrupt source type */
126 writel(0x00, sun4i_irq_base + SUN4I_IRQ_NMI_CTRL_REG);
127
128 sun4i_irq_domain = irq_domain_add_linear(node, 3 * 32,
129 &sun4i_irq_ops, NULL);
130 if (!sun4i_irq_domain)
131 panic("%s: unable to create IRQ domain\n", node->full_name);
132
133 set_handle_irq(sun4i_handle_irq);
134
135 return 0;
136}
137IRQCHIP_DECLARE(allwinner_sun4i_ic, "allwinner,sun4i-ic", sun4i_of_init);
138
139static asmlinkage void __exception_irq_entry sun4i_handle_irq(struct pt_regs *regs)
140{
141 u32 irq, hwirq;
142
143 hwirq = readl(sun4i_irq_base + SUN4I_IRQ_VECTOR_REG) >> 2;
144 while (hwirq != 0) {
145 irq = irq_find_mapping(sun4i_irq_domain, hwirq);
146 handle_IRQ(irq, regs);
147 hwirq = readl(sun4i_irq_base + SUN4I_IRQ_VECTOR_REG) >> 2;
148 }
149}
diff --git a/drivers/irqchip/irq-sunxi.c b/drivers/irqchip/irq-sunxi.c
deleted file mode 100644
index 0fc49c577033..000000000000
--- a/drivers/irqchip/irq-sunxi.c
+++ /dev/null
@@ -1,149 +0,0 @@
1/*
2 * Allwinner A1X SoCs IRQ chip driver.
3 *
4 * Copyright (C) 2012 Maxime Ripard
5 *
6 * Maxime Ripard <maxime.ripard@free-electrons.com>
7 *
8 * Based on code from
9 * Allwinner Technology Co., Ltd. <www.allwinnertech.com>
10 * Benn Huang <benn@allwinnertech.com>
11 *
12 * This file is licensed under the terms of the GNU General Public
13 * License version 2. This program is licensed "as is" without any
14 * warranty of any kind, whether express or implied.
15 */
16
17#include <linux/io.h>
18#include <linux/irq.h>
19#include <linux/of.h>
20#include <linux/of_address.h>
21#include <linux/of_irq.h>
22
23#include <asm/exception.h>
24#include <asm/mach/irq.h>
25
26#include "irqchip.h"
27
28#define SUNXI_IRQ_VECTOR_REG 0x00
29#define SUNXI_IRQ_PROTECTION_REG 0x08
30#define SUNXI_IRQ_NMI_CTRL_REG 0x0c
31#define SUNXI_IRQ_PENDING_REG(x) (0x10 + 0x4 * x)
32#define SUNXI_IRQ_FIQ_PENDING_REG(x) (0x20 + 0x4 * x)
33#define SUNXI_IRQ_ENABLE_REG(x) (0x40 + 0x4 * x)
34#define SUNXI_IRQ_MASK_REG(x) (0x50 + 0x4 * x)
35
36static void __iomem *sunxi_irq_base;
37static struct irq_domain *sunxi_irq_domain;
38
39static asmlinkage void __exception_irq_entry sunxi_handle_irq(struct pt_regs *regs);
40
41void sunxi_irq_ack(struct irq_data *irqd)
42{
43 unsigned int irq = irqd_to_hwirq(irqd);
44 unsigned int irq_off = irq % 32;
45 int reg = irq / 32;
46 u32 val;
47
48 val = readl(sunxi_irq_base + SUNXI_IRQ_PENDING_REG(reg));
49 writel(val | (1 << irq_off),
50 sunxi_irq_base + SUNXI_IRQ_PENDING_REG(reg));
51}
52
53static void sunxi_irq_mask(struct irq_data *irqd)
54{
55 unsigned int irq = irqd_to_hwirq(irqd);
56 unsigned int irq_off = irq % 32;
57 int reg = irq / 32;
58 u32 val;
59
60 val = readl(sunxi_irq_base + SUNXI_IRQ_ENABLE_REG(reg));
61 writel(val & ~(1 << irq_off),
62 sunxi_irq_base + SUNXI_IRQ_ENABLE_REG(reg));
63}
64
65static void sunxi_irq_unmask(struct irq_data *irqd)
66{
67 unsigned int irq = irqd_to_hwirq(irqd);
68 unsigned int irq_off = irq % 32;
69 int reg = irq / 32;
70 u32 val;
71
72 val = readl(sunxi_irq_base + SUNXI_IRQ_ENABLE_REG(reg));
73 writel(val | (1 << irq_off),
74 sunxi_irq_base + SUNXI_IRQ_ENABLE_REG(reg));
75}
76
77static struct irq_chip sunxi_irq_chip = {
78 .name = "sunxi_irq",
79 .irq_ack = sunxi_irq_ack,
80 .irq_mask = sunxi_irq_mask,
81 .irq_unmask = sunxi_irq_unmask,
82};
83
84static int sunxi_irq_map(struct irq_domain *d, unsigned int virq,
85 irq_hw_number_t hw)
86{
87 irq_set_chip_and_handler(virq, &sunxi_irq_chip,
88 handle_level_irq);
89 set_irq_flags(virq, IRQF_VALID | IRQF_PROBE);
90
91 return 0;
92}
93
94static struct irq_domain_ops sunxi_irq_ops = {
95 .map = sunxi_irq_map,
96 .xlate = irq_domain_xlate_onecell,
97};
98
99static int __init sunxi_of_init(struct device_node *node,
100 struct device_node *parent)
101{
102 sunxi_irq_base = of_iomap(node, 0);
103 if (!sunxi_irq_base)
104 panic("%s: unable to map IC registers\n",
105 node->full_name);
106
107 /* Disable all interrupts */
108 writel(0, sunxi_irq_base + SUNXI_IRQ_ENABLE_REG(0));
109 writel(0, sunxi_irq_base + SUNXI_IRQ_ENABLE_REG(1));
110 writel(0, sunxi_irq_base + SUNXI_IRQ_ENABLE_REG(2));
111
112 /* Mask all the interrupts */
113 writel(0, sunxi_irq_base + SUNXI_IRQ_MASK_REG(0));
114 writel(0, sunxi_irq_base + SUNXI_IRQ_MASK_REG(1));
115 writel(0, sunxi_irq_base + SUNXI_IRQ_MASK_REG(2));
116
117 /* Clear all the pending interrupts */
118 writel(0xffffffff, sunxi_irq_base + SUNXI_IRQ_PENDING_REG(0));
119 writel(0xffffffff, sunxi_irq_base + SUNXI_IRQ_PENDING_REG(1));
120 writel(0xffffffff, sunxi_irq_base + SUNXI_IRQ_PENDING_REG(2));
121
122 /* Enable protection mode */
123 writel(0x01, sunxi_irq_base + SUNXI_IRQ_PROTECTION_REG);
124
125 /* Configure the external interrupt source type */
126 writel(0x00, sunxi_irq_base + SUNXI_IRQ_NMI_CTRL_REG);
127
128 sunxi_irq_domain = irq_domain_add_linear(node, 3 * 32,
129 &sunxi_irq_ops, NULL);
130 if (!sunxi_irq_domain)
131 panic("%s: unable to create IRQ domain\n", node->full_name);
132
133 set_handle_irq(sunxi_handle_irq);
134
135 return 0;
136}
137IRQCHIP_DECLARE(allwinner_sunxi_ic, "allwinner,sunxi-ic", sunxi_of_init);
138
139static asmlinkage void __exception_irq_entry sunxi_handle_irq(struct pt_regs *regs)
140{
141 u32 irq, hwirq;
142
143 hwirq = readl(sunxi_irq_base + SUNXI_IRQ_VECTOR_REG) >> 2;
144 while (hwirq != 0) {
145 irq = irq_find_mapping(sunxi_irq_domain, hwirq);
146 handle_IRQ(irq, regs);
147 hwirq = readl(sunxi_irq_base + SUNXI_IRQ_VECTOR_REG) >> 2;
148 }
149}