aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm/mach-vt8500
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2012-12-13 13:57:16 -0500
committerLinus Torvalds <torvalds@linux-foundation.org>2012-12-13 13:57:16 -0500
commitb8edf848e9119bab9d999b9ca80d8520641810f2 (patch)
tree76517286b247626ed37dda41a4f946f6c34b8bff /arch/arm/mach-vt8500
parentdb5b0ae00712b5176d7405e7a1dd2bfd6e8f5070 (diff)
parent3f54db784a6af9a6d53396949cbecf62edbad247 (diff)
Merge tag 'multiplatform' of git://git.kernel.org/pub/scm/linux/kernel/git/arm/arm-soc
Pull ARM SoC multiplatform conversion patches from Olof Johansson: "Here are more patches in the progression towards multiplatform, sparse irq conversions in particular. Tegra has a handful of cleanups and general groundwork, but is not quite there yet on full enablement. Platforms that are enabled through this branch are VT8500 and Zynq. Note that i.MX was converted in one of the earlier cleanup branches as well (before we started a separate topic for multiplatform). And both new platforms for this merge window, sunxi and bcm, were merged with multiplatform support enabled." Fix up conflicts mostly as per Olof. * tag 'multiplatform' of git://git.kernel.org/pub/scm/linux/kernel/git/arm/arm-soc: (29 commits) ARM: zynq: Remove all unused mach headers ARM: zynq: add support for ARCH_MULTIPLATFORM ARM: zynq: make use of debug_ll_io_init() ARM: zynq: remove TTC early mapping ARM: tegra: move debug-macro.S to include/debug ARM: tegra: don't include iomap.h from debug-macro.S ARM: tegra: decouple uncompress.h and debug-macro.S ARM: tegra: simplify DEBUG_LL UART selection options ARM: tegra: select SPARSE_IRQ ARM: tegra: enhance timer.c to get IO address from device tree ARM: tegra: enhance timer.c to get IRQ info from device tree ARM: timer: fix checkpatch warnings ARM: tegra: add TWD to device tree ARM: tegra: define DT bindings for and instantiate RTC ARM: tegra: define DT bindings for and instantiate timer clocksource/mtu-nomadik: use apb_pclk clk: ux500: Register mtu apb_pclocks ARM: plat-nomadik: convert platforms to SPARSE_IRQ mfd/db8500-prcmu: use the irq_domain_add_simple() mfd/ab8500-core: use irq_domain_add_simple() ...
Diffstat (limited to 'arch/arm/mach-vt8500')
-rw-r--r--arch/arm/mach-vt8500/Kconfig12
-rw-r--r--arch/arm/mach-vt8500/common.h3
-rw-r--r--arch/arm/mach-vt8500/include/mach/entry-macro.S26
-rw-r--r--arch/arm/mach-vt8500/include/mach/irqs.h22
-rw-r--r--arch/arm/mach-vt8500/irq.c108
-rw-r--r--arch/arm/mach-vt8500/vt8500.c1
6 files changed, 86 insertions, 86 deletions
diff --git a/arch/arm/mach-vt8500/Kconfig b/arch/arm/mach-vt8500/Kconfig
new file mode 100644
index 000000000000..2ed0b7d95db6
--- /dev/null
+++ b/arch/arm/mach-vt8500/Kconfig
@@ -0,0 +1,12 @@
1config ARCH_VT8500
2 bool "VIA/WonderMedia 85xx" if ARCH_MULTI_V5
3 default ARCH_VT8500_SINGLE
4 select ARCH_HAS_CPUFREQ
5 select ARCH_REQUIRE_GPIOLIB
6 select CLKDEV_LOOKUP
7 select CPU_ARM926T
8 select GENERIC_CLOCKEVENTS
9 select GENERIC_GPIO
10 select HAVE_CLK
11 help
12 Support for VIA/WonderMedia VT8500/WM85xx System-on-Chip.
diff --git a/arch/arm/mach-vt8500/common.h b/arch/arm/mach-vt8500/common.h
index 2b2419646e95..6f2b843115db 100644
--- a/arch/arm/mach-vt8500/common.h
+++ b/arch/arm/mach-vt8500/common.h
@@ -25,4 +25,7 @@ int __init vt8500_irq_init(struct device_node *node,
25/* defined in drivers/clk/clk-vt8500.c */ 25/* defined in drivers/clk/clk-vt8500.c */
26void __init vtwm_clk_init(void __iomem *pmc_base); 26void __init vtwm_clk_init(void __iomem *pmc_base);
27 27
28/* defined in irq.c */
29asmlinkage void vt8500_handle_irq(struct pt_regs *regs);
30
28#endif 31#endif
diff --git a/arch/arm/mach-vt8500/include/mach/entry-macro.S b/arch/arm/mach-vt8500/include/mach/entry-macro.S
deleted file mode 100644
index 367d1b55fb9a..000000000000
--- a/arch/arm/mach-vt8500/include/mach/entry-macro.S
+++ /dev/null
@@ -1,26 +0,0 @@
1/*
2 * arch/arm/mach-vt8500/include/mach/entry-macro.S
3 *
4 * Low-level IRQ helper macros for VIA VT8500
5 *
6 * This file is licensed under the terms of the GNU General Public
7 * License version 2. This program is licensed "as is" without any
8 * warranty of any kind, whether express or implied.
9 */
10
11 .macro get_irqnr_preamble, base, tmp
12 @ physical 0xd8140000 is virtual 0xf8140000
13 mov \base, #0xf8000000
14 orr \base, \base, #0x00140000
15 .endm
16
17 .macro get_irqnr_and_base, irqnr, irqstat, base, tmp
18 ldr \irqnr, [\base]
19 cmp \irqnr, #63 @ may be false positive, check interrupt status
20 bne 1001f
21 ldr \irqstat, [\base, #0x84]
22 ands \irqstat, #0x80000000
23 moveq \irqnr, #0
241001:
25 .endm
26
diff --git a/arch/arm/mach-vt8500/include/mach/irqs.h b/arch/arm/mach-vt8500/include/mach/irqs.h
deleted file mode 100644
index a129fd1222fb..000000000000
--- a/arch/arm/mach-vt8500/include/mach/irqs.h
+++ /dev/null
@@ -1,22 +0,0 @@
1/*
2 * arch/arm/mach-vt8500/include/mach/irqs.h
3 *
4 * Copyright (C) 2010 Alexey Charkov <alchark@gmail.com>
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 as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 */
20
21/* This value is just to make the core happy, never used otherwise */
22#define NR_IRQS 128
diff --git a/arch/arm/mach-vt8500/irq.c b/arch/arm/mach-vt8500/irq.c
index f8f9ab9bc56e..b9cf5ce9efbb 100644
--- a/arch/arm/mach-vt8500/irq.c
+++ b/arch/arm/mach-vt8500/irq.c
@@ -36,7 +36,7 @@
36#include <linux/of_address.h> 36#include <linux/of_address.h>
37 37
38#include <asm/irq.h> 38#include <asm/irq.h>
39 39#include <asm/exception.h>
40 40
41#define VT8500_ICPC_IRQ 0x20 41#define VT8500_ICPC_IRQ 0x20
42#define VT8500_ICPC_FIQ 0x24 42#define VT8500_ICPC_FIQ 0x24
@@ -66,30 +66,34 @@
66#define VT8500_EDGE ( VT8500_TRIGGER_RISING \ 66#define VT8500_EDGE ( VT8500_TRIGGER_RISING \
67 | VT8500_TRIGGER_FALLING) 67 | VT8500_TRIGGER_FALLING)
68 68
69static int irq_cnt; 69/* vt8500 has 1 intc, wm8505 and wm8650 have 2 */
70#define VT8500_INTC_MAX 2
70 71
71struct vt8500_irq_priv { 72struct vt8500_irq_data {
72 void __iomem *base; 73 void __iomem *base; /* IO Memory base address */
74 struct irq_domain *domain; /* Domain for this controller */
73}; 75};
74 76
77/* Global variable for accessing io-mem addresses */
78static struct vt8500_irq_data intc[VT8500_INTC_MAX];
79static u32 active_cnt = 0;
80
75static void vt8500_irq_mask(struct irq_data *d) 81static void vt8500_irq_mask(struct irq_data *d)
76{ 82{
77 struct vt8500_irq_priv *priv = 83 struct vt8500_irq_data *priv = d->domain->host_data;
78 (struct vt8500_irq_priv *)(d->domain->host_data);
79 void __iomem *base = priv->base; 84 void __iomem *base = priv->base;
80 u8 edge; 85 void __iomem *stat_reg = base + VT8500_ICIS + (d->hwirq < 32 ? 0 : 4);
86 u8 edge, dctr;
87 u32 status;
81 88
82 edge = readb(base + VT8500_ICDC + d->hwirq) & VT8500_EDGE; 89 edge = readb(base + VT8500_ICDC + d->hwirq) & VT8500_EDGE;
83 if (edge) { 90 if (edge) {
84 void __iomem *stat_reg = base + VT8500_ICIS 91 status = readl(stat_reg);
85 + (d->hwirq < 32 ? 0 : 4);
86 unsigned status = readl(stat_reg);
87 92
88 status |= (1 << (d->hwirq & 0x1f)); 93 status |= (1 << (d->hwirq & 0x1f));
89 writel(status, stat_reg); 94 writel(status, stat_reg);
90 } else { 95 } else {
91 u8 dctr = readb(base + VT8500_ICDC + d->hwirq); 96 dctr = readb(base + VT8500_ICDC + d->hwirq);
92
93 dctr &= ~VT8500_INT_ENABLE; 97 dctr &= ~VT8500_INT_ENABLE;
94 writeb(dctr, base + VT8500_ICDC + d->hwirq); 98 writeb(dctr, base + VT8500_ICDC + d->hwirq);
95 } 99 }
@@ -97,8 +101,7 @@ static void vt8500_irq_mask(struct irq_data *d)
97 101
98static void vt8500_irq_unmask(struct irq_data *d) 102static void vt8500_irq_unmask(struct irq_data *d)
99{ 103{
100 struct vt8500_irq_priv *priv = 104 struct vt8500_irq_data *priv = d->domain->host_data;
101 (struct vt8500_irq_priv *)(d->domain->host_data);
102 void __iomem *base = priv->base; 105 void __iomem *base = priv->base;
103 u8 dctr; 106 u8 dctr;
104 107
@@ -109,8 +112,7 @@ static void vt8500_irq_unmask(struct irq_data *d)
109 112
110static int vt8500_irq_set_type(struct irq_data *d, unsigned int flow_type) 113static int vt8500_irq_set_type(struct irq_data *d, unsigned int flow_type)
111{ 114{
112 struct vt8500_irq_priv *priv = 115 struct vt8500_irq_data *priv = d->domain->host_data;
113 (struct vt8500_irq_priv *)(d->domain->host_data);
114 void __iomem *base = priv->base; 116 void __iomem *base = priv->base;
115 u8 dctr; 117 u8 dctr;
116 118
@@ -148,17 +150,15 @@ static struct irq_chip vt8500_irq_chip = {
148 150
149static void __init vt8500_init_irq_hw(void __iomem *base) 151static void __init vt8500_init_irq_hw(void __iomem *base)
150{ 152{
151 unsigned int i; 153 u32 i;
152 154
153 /* Enable rotating priority for IRQ */ 155 /* Enable rotating priority for IRQ */
154 writel(ICPC_ROTATE, base + VT8500_ICPC_IRQ); 156 writel(ICPC_ROTATE, base + VT8500_ICPC_IRQ);
155 writel(0x00, base + VT8500_ICPC_FIQ); 157 writel(0x00, base + VT8500_ICPC_FIQ);
156 158
157 for (i = 0; i < 64; i++) { 159 /* Disable all interrupts and route them to IRQ */
158 /* Disable all interrupts and route them to IRQ */ 160 for (i = 0; i < 64; i++)
159 writeb(VT8500_INT_DISABLE | ICDC_IRQ, 161 writeb(VT8500_INT_DISABLE | ICDC_IRQ, base + VT8500_ICDC + i);
160 base + VT8500_ICDC + i);
161 }
162} 162}
163 163
164static int vt8500_irq_map(struct irq_domain *h, unsigned int virq, 164static int vt8500_irq_map(struct irq_domain *h, unsigned int virq,
@@ -175,33 +175,67 @@ static struct irq_domain_ops vt8500_irq_domain_ops = {
175 .xlate = irq_domain_xlate_onecell, 175 .xlate = irq_domain_xlate_onecell,
176}; 176};
177 177
178asmlinkage void __exception_irq_entry vt8500_handle_irq(struct pt_regs *regs)
179{
180 u32 stat, i;
181 int irqnr, virq;
182 void __iomem *base;
183
184 /* Loop through each active controller */
185 for (i=0; i<active_cnt; i++) {
186 base = intc[i].base;
187 irqnr = readl_relaxed(base) & 0x3F;
188 /*
189 Highest Priority register default = 63, so check that this
190 is a real interrupt by checking the status register
191 */
192 if (irqnr == 63) {
193 stat = readl_relaxed(base + VT8500_ICIS + 4);
194 if (!(stat & BIT(31)))
195 continue;
196 }
197
198 virq = irq_find_mapping(intc[i].domain, irqnr);
199 handle_IRQ(virq, regs);
200 }
201}
202
178int __init vt8500_irq_init(struct device_node *node, struct device_node *parent) 203int __init vt8500_irq_init(struct device_node *node, struct device_node *parent)
179{ 204{
180 struct irq_domain *vt8500_irq_domain;
181 struct vt8500_irq_priv *priv;
182 int irq, i; 205 int irq, i;
183 struct device_node *np = node; 206 struct device_node *np = node;
184 207
185 priv = kzalloc(sizeof(struct vt8500_irq_priv), GFP_KERNEL); 208 if (active_cnt == VT8500_INTC_MAX) {
186 priv->base = of_iomap(np, 0); 209 pr_err("%s: Interrupt controllers > VT8500_INTC_MAX\n",
210 __func__);
211 goto out;
212 }
213
214 intc[active_cnt].base = of_iomap(np, 0);
215 intc[active_cnt].domain = irq_domain_add_linear(node, 64,
216 &vt8500_irq_domain_ops, &intc[active_cnt]);
187 217
188 vt8500_irq_domain = irq_domain_add_legacy(node, 64, irq_cnt, 0, 218 if (!intc[active_cnt].base) {
189 &vt8500_irq_domain_ops, priv); 219 pr_err("%s: Unable to map IO memory\n", __func__);
190 if (!vt8500_irq_domain) 220 goto out;
191 pr_err("%s: Unable to add wmt irq domain!\n", __func__); 221 }
222
223 if (!intc[active_cnt].domain) {
224 pr_err("%s: Unable to add irq domain!\n", __func__);
225 goto out;
226 }
192 227
193 irq_set_default_host(vt8500_irq_domain); 228 vt8500_init_irq_hw(intc[active_cnt].base);
194 229
195 vt8500_init_irq_hw(priv->base); 230 pr_info("vt8500-irq: Added interrupt controller\n");
196 231
197 pr_info("Added IRQ Controller @ %x [virq_base = %d]\n", 232 active_cnt++;
198 (u32)(priv->base), irq_cnt);
199 233
200 /* check if this is a slaved controller */ 234 /* check if this is a slaved controller */
201 if (of_irq_count(np) != 0) { 235 if (of_irq_count(np) != 0) {
202 /* check that we have the correct number of interrupts */ 236 /* check that we have the correct number of interrupts */
203 if (of_irq_count(np) != 8) { 237 if (of_irq_count(np) != 8) {
204 pr_err("%s: Incorrect IRQ map for slave controller\n", 238 pr_err("%s: Incorrect IRQ map for slaved controller\n",
205 __func__); 239 __func__);
206 return -EINVAL; 240 return -EINVAL;
207 } 241 }
@@ -213,9 +247,7 @@ int __init vt8500_irq_init(struct device_node *node, struct device_node *parent)
213 247
214 pr_info("vt8500-irq: Enabled slave->parent interrupts\n"); 248 pr_info("vt8500-irq: Enabled slave->parent interrupts\n");
215 } 249 }
216 250out:
217 irq_cnt += 64;
218
219 return 0; 251 return 0;
220} 252}
221 253
diff --git a/arch/arm/mach-vt8500/vt8500.c b/arch/arm/mach-vt8500/vt8500.c
index a5bd28692b06..3c66d48ea082 100644
--- a/arch/arm/mach-vt8500/vt8500.c
+++ b/arch/arm/mach-vt8500/vt8500.c
@@ -192,5 +192,6 @@ DT_MACHINE_START(WMT_DT, "VIA/Wondermedia SoC (Device Tree Support)")
192 .timer = &vt8500_timer, 192 .timer = &vt8500_timer,
193 .init_machine = vt8500_init, 193 .init_machine = vt8500_init,
194 .restart = vt8500_restart, 194 .restart = vt8500_restart,
195 .handle_irq = vt8500_handle_irq,
195MACHINE_END 196MACHINE_END
196 197