diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2012-12-13 10:57:16 -0800 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2012-12-13 10:57:16 -0800 |
commit | b8edf848e9119bab9d999b9ca80d8520641810f2 (patch) | |
tree | 76517286b247626ed37dda41a4f946f6c34b8bff /arch/arm/mach-vt8500 | |
parent | db5b0ae00712b5176d7405e7a1dd2bfd6e8f5070 (diff) | |
parent | 3f54db784a6af9a6d53396949cbecf62edbad247 (diff) | |
download | op-kernel-dev-b8edf848e9119bab9d999b9ca80d8520641810f2.zip op-kernel-dev-b8edf848e9119bab9d999b9ca80d8520641810f2.tar.gz |
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/Kconfig | 12 | ||||
-rw-r--r-- | arch/arm/mach-vt8500/common.h | 3 | ||||
-rw-r--r-- | arch/arm/mach-vt8500/include/mach/entry-macro.S | 26 | ||||
-rw-r--r-- | arch/arm/mach-vt8500/include/mach/irqs.h | 22 | ||||
-rw-r--r-- | arch/arm/mach-vt8500/irq.c | 108 | ||||
-rw-r--r-- | arch/arm/mach-vt8500/vt8500.c | 1 |
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 0000000..2ed0b7d --- /dev/null +++ b/arch/arm/mach-vt8500/Kconfig @@ -0,0 +1,12 @@ +config ARCH_VT8500 + bool "VIA/WonderMedia 85xx" if ARCH_MULTI_V5 + default ARCH_VT8500_SINGLE + select ARCH_HAS_CPUFREQ + select ARCH_REQUIRE_GPIOLIB + select CLKDEV_LOOKUP + select CPU_ARM926T + select GENERIC_CLOCKEVENTS + select GENERIC_GPIO + select HAVE_CLK + help + 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 2b24196..6f2b843 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, /* defined in drivers/clk/clk-vt8500.c */ void __init vtwm_clk_init(void __iomem *pmc_base); +/* defined in irq.c */ +asmlinkage void vt8500_handle_irq(struct pt_regs *regs); + #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 367d1b5..0000000 --- a/arch/arm/mach-vt8500/include/mach/entry-macro.S +++ /dev/null @@ -1,26 +0,0 @@ -/* - * arch/arm/mach-vt8500/include/mach/entry-macro.S - * - * Low-level IRQ helper macros for VIA VT8500 - * - * This file is licensed under the terms of the GNU General Public - * License version 2. This program is licensed "as is" without any - * warranty of any kind, whether express or implied. - */ - - .macro get_irqnr_preamble, base, tmp - @ physical 0xd8140000 is virtual 0xf8140000 - mov \base, #0xf8000000 - orr \base, \base, #0x00140000 - .endm - - .macro get_irqnr_and_base, irqnr, irqstat, base, tmp - ldr \irqnr, [\base] - cmp \irqnr, #63 @ may be false positive, check interrupt status - bne 1001f - ldr \irqstat, [\base, #0x84] - ands \irqstat, #0x80000000 - moveq \irqnr, #0 -1001: - .endm - 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 a129fd1..0000000 --- a/arch/arm/mach-vt8500/include/mach/irqs.h +++ /dev/null @@ -1,22 +0,0 @@ -/* - * arch/arm/mach-vt8500/include/mach/irqs.h - * - * Copyright (C) 2010 Alexey Charkov <alchark@gmail.com> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* This value is just to make the core happy, never used otherwise */ -#define NR_IRQS 128 diff --git a/arch/arm/mach-vt8500/irq.c b/arch/arm/mach-vt8500/irq.c index f8f9ab9..b9cf5ce 100644 --- a/arch/arm/mach-vt8500/irq.c +++ b/arch/arm/mach-vt8500/irq.c @@ -36,7 +36,7 @@ #include <linux/of_address.h> #include <asm/irq.h> - +#include <asm/exception.h> #define VT8500_ICPC_IRQ 0x20 #define VT8500_ICPC_FIQ 0x24 @@ -66,30 +66,34 @@ #define VT8500_EDGE ( VT8500_TRIGGER_RISING \ | VT8500_TRIGGER_FALLING) -static int irq_cnt; +/* vt8500 has 1 intc, wm8505 and wm8650 have 2 */ +#define VT8500_INTC_MAX 2 -struct vt8500_irq_priv { - void __iomem *base; +struct vt8500_irq_data { + void __iomem *base; /* IO Memory base address */ + struct irq_domain *domain; /* Domain for this controller */ }; +/* Global variable for accessing io-mem addresses */ +static struct vt8500_irq_data intc[VT8500_INTC_MAX]; +static u32 active_cnt = 0; + static void vt8500_irq_mask(struct irq_data *d) { - struct vt8500_irq_priv *priv = - (struct vt8500_irq_priv *)(d->domain->host_data); + struct vt8500_irq_data *priv = d->domain->host_data; void __iomem *base = priv->base; - u8 edge; + void __iomem *stat_reg = base + VT8500_ICIS + (d->hwirq < 32 ? 0 : 4); + u8 edge, dctr; + u32 status; edge = readb(base + VT8500_ICDC + d->hwirq) & VT8500_EDGE; if (edge) { - void __iomem *stat_reg = base + VT8500_ICIS - + (d->hwirq < 32 ? 0 : 4); - unsigned status = readl(stat_reg); + status = readl(stat_reg); status |= (1 << (d->hwirq & 0x1f)); writel(status, stat_reg); } else { - u8 dctr = readb(base + VT8500_ICDC + d->hwirq); - + dctr = readb(base + VT8500_ICDC + d->hwirq); dctr &= ~VT8500_INT_ENABLE; writeb(dctr, base + VT8500_ICDC + d->hwirq); } @@ -97,8 +101,7 @@ static void vt8500_irq_mask(struct irq_data *d) static void vt8500_irq_unmask(struct irq_data *d) { - struct vt8500_irq_priv *priv = - (struct vt8500_irq_priv *)(d->domain->host_data); + struct vt8500_irq_data *priv = d->domain->host_data; void __iomem *base = priv->base; u8 dctr; @@ -109,8 +112,7 @@ static void vt8500_irq_unmask(struct irq_data *d) static int vt8500_irq_set_type(struct irq_data *d, unsigned int flow_type) { - struct vt8500_irq_priv *priv = - (struct vt8500_irq_priv *)(d->domain->host_data); + struct vt8500_irq_data *priv = d->domain->host_data; void __iomem *base = priv->base; u8 dctr; @@ -148,17 +150,15 @@ static struct irq_chip vt8500_irq_chip = { static void __init vt8500_init_irq_hw(void __iomem *base) { - unsigned int i; + u32 i; /* Enable rotating priority for IRQ */ writel(ICPC_ROTATE, base + VT8500_ICPC_IRQ); writel(0x00, base + VT8500_ICPC_FIQ); - for (i = 0; i < 64; i++) { - /* Disable all interrupts and route them to IRQ */ - writeb(VT8500_INT_DISABLE | ICDC_IRQ, - base + VT8500_ICDC + i); - } + /* Disable all interrupts and route them to IRQ */ + for (i = 0; i < 64; i++) + writeb(VT8500_INT_DISABLE | ICDC_IRQ, base + VT8500_ICDC + i); } static int vt8500_irq_map(struct irq_domain *h, unsigned int virq, @@ -175,33 +175,67 @@ static struct irq_domain_ops vt8500_irq_domain_ops = { .xlate = irq_domain_xlate_onecell, }; +asmlinkage void __exception_irq_entry vt8500_handle_irq(struct pt_regs *regs) +{ + u32 stat, i; + int irqnr, virq; + void __iomem *base; + + /* Loop through each active controller */ + for (i=0; i<active_cnt; i++) { + base = intc[i].base; + irqnr = readl_relaxed(base) & 0x3F; + /* + Highest Priority register default = 63, so check that this + is a real interrupt by checking the status register + */ + if (irqnr == 63) { + stat = readl_relaxed(base + VT8500_ICIS + 4); + if (!(stat & BIT(31))) + continue; + } + + virq = irq_find_mapping(intc[i].domain, irqnr); + handle_IRQ(virq, regs); + } +} + int __init vt8500_irq_init(struct device_node *node, struct device_node *parent) { - struct irq_domain *vt8500_irq_domain; - struct vt8500_irq_priv *priv; int irq, i; struct device_node *np = node; - priv = kzalloc(sizeof(struct vt8500_irq_priv), GFP_KERNEL); - priv->base = of_iomap(np, 0); + if (active_cnt == VT8500_INTC_MAX) { + pr_err("%s: Interrupt controllers > VT8500_INTC_MAX\n", + __func__); + goto out; + } + + intc[active_cnt].base = of_iomap(np, 0); + intc[active_cnt].domain = irq_domain_add_linear(node, 64, + &vt8500_irq_domain_ops, &intc[active_cnt]); - vt8500_irq_domain = irq_domain_add_legacy(node, 64, irq_cnt, 0, - &vt8500_irq_domain_ops, priv); - if (!vt8500_irq_domain) - pr_err("%s: Unable to add wmt irq domain!\n", __func__); + if (!intc[active_cnt].base) { + pr_err("%s: Unable to map IO memory\n", __func__); + goto out; + } + + if (!intc[active_cnt].domain) { + pr_err("%s: Unable to add irq domain!\n", __func__); + goto out; + } - irq_set_default_host(vt8500_irq_domain); + vt8500_init_irq_hw(intc[active_cnt].base); - vt8500_init_irq_hw(priv->base); + pr_info("vt8500-irq: Added interrupt controller\n"); - pr_info("Added IRQ Controller @ %x [virq_base = %d]\n", - (u32)(priv->base), irq_cnt); + active_cnt++; /* check if this is a slaved controller */ if (of_irq_count(np) != 0) { /* check that we have the correct number of interrupts */ if (of_irq_count(np) != 8) { - pr_err("%s: Incorrect IRQ map for slave controller\n", + pr_err("%s: Incorrect IRQ map for slaved controller\n", __func__); return -EINVAL; } @@ -213,9 +247,7 @@ int __init vt8500_irq_init(struct device_node *node, struct device_node *parent) pr_info("vt8500-irq: Enabled slave->parent interrupts\n"); } - - irq_cnt += 64; - +out: return 0; } diff --git a/arch/arm/mach-vt8500/vt8500.c b/arch/arm/mach-vt8500/vt8500.c index a5bd286..3c66d48 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)") .timer = &vt8500_timer, .init_machine = vt8500_init, .restart = vt8500_restart, + .handle_irq = vt8500_handle_irq, MACHINE_END |