From 8c87f64f25851c27889179a66010c2cbe66e3aa7 Mon Sep 17 00:00:00 2001 From: Russell King Date: Wed, 8 Dec 2010 13:49:04 +0000 Subject: [PATCH] --- yaml --- r: 225750 b: refs/heads/master c: a0b7bd0829194c03921915a68ee4a331ee394223 h: refs/heads/master v: v3 --- [refs] | 2 +- trunk/arch/arm/common/gic.c | 69 +++++--------- .../include/asm/hardware/entry-macro-gic.S | 75 --------------- trunk/arch/arm/include/asm/hardware/gic.h | 7 +- trunk/arch/arm/include/asm/io.h | 4 +- trunk/arch/arm/kernel/smp_twd.c | 7 +- trunk/arch/arm/mach-cns3xxx/core.c | 7 +- trunk/arch/arm/mach-cns3xxx/core.h | 1 + .../mach-cns3xxx/include/mach/entry-macro.S | 66 ++++++++++++- trunk/arch/arm/mach-davinci/include/mach/io.h | 4 +- trunk/arch/arm/mach-iop13xx/include/mach/io.h | 4 +- trunk/arch/arm/mach-iop32x/include/mach/io.h | 4 +- trunk/arch/arm/mach-iop33x/include/mach/io.h | 4 +- trunk/arch/arm/mach-ixp23xx/include/mach/io.h | 4 +- trunk/arch/arm/mach-ixp4xx/include/mach/io.h | 4 +- .../arch/arm/mach-kirkwood/include/mach/io.h | 4 +- trunk/arch/arm/mach-msm/board-msm8x60.c | 7 +- .../arm/mach-omap2/include/mach/entry-macro.S | 93 ++++++++++++------- .../mach-omap2/include/mach/omap4-common.h | 1 + trunk/arch/arm/mach-omap2/omap-smp.c | 2 +- trunk/arch/arm/mach-omap2/omap4-common.c | 11 +-- trunk/arch/arm/mach-orion5x/include/mach/io.h | 4 +- trunk/arch/arm/mach-realview/core.c | 3 + trunk/arch/arm/mach-realview/core.h | 1 + .../mach-realview/include/mach/entry-macro.S | 65 ++++++++++++- trunk/arch/arm/mach-realview/platsmp.c | 2 +- trunk/arch/arm/mach-realview/realview_eb.c | 14 +-- .../arch/arm/mach-realview/realview_pb1176.c | 11 +-- .../arch/arm/mach-realview/realview_pb11mp.c | 10 +- trunk/arch/arm/mach-realview/realview_pba8.c | 6 +- trunk/arch/arm/mach-realview/realview_pbx.c | 13 ++- trunk/arch/arm/mach-s5pv310/cpu.c | 6 +- .../arch/arm/mach-s5pv310/include/mach/smp.h | 2 + trunk/arch/arm/mach-s5pv310/platsmp.c | 2 +- .../arm/mach-tegra/include/mach/entry-macro.S | 66 ++++++++++++- trunk/arch/arm/mach-tegra/include/mach/io.h | 4 +- trunk/arch/arm/mach-tegra/irq.c | 4 +- trunk/arch/arm/mach-tegra/platsmp.c | 2 +- trunk/arch/arm/mach-ux500/cpu.c | 4 +- .../arm/mach-ux500/include/mach/entry-macro.S | 68 +++++++++++++- trunk/arch/arm/mach-ux500/platsmp.c | 2 +- trunk/arch/arm/mach-vexpress/core.h | 2 + trunk/arch/arm/mach-vexpress/ct-ca9x4.c | 7 +- .../mach-vexpress/include/mach/entry-macro.S | 62 ++++++++++++- trunk/arch/arm/mach-vexpress/platsmp.c | 2 +- trunk/arch/arm/plat-omap/include/plat/io.h | 4 +- 46 files changed, 507 insertions(+), 239 deletions(-) delete mode 100644 trunk/arch/arm/include/asm/hardware/entry-macro-gic.S diff --git a/[refs] b/[refs] index 760e6802ed1b..d6bf606ed4c3 100644 --- a/[refs] +++ b/[refs] @@ -1,2 +1,2 @@ --- -refs/heads/master: ac61d143ffe2a6db4d4bcf47c21a5159d6a1b644 +refs/heads/master: a0b7bd0829194c03921915a68ee4a331ee394223 diff --git a/trunk/arch/arm/common/gic.c b/trunk/arch/arm/common/gic.c index 0b89ef001330..e6388dcd8cfa 100644 --- a/trunk/arch/arm/common/gic.c +++ b/trunk/arch/arm/common/gic.c @@ -35,9 +35,6 @@ static DEFINE_SPINLOCK(irq_controller_lock); -/* Address of GIC 0 CPU interface */ -void __iomem *gic_cpu_base_addr __read_mostly; - struct gic_chip_data { unsigned int irq_offset; void __iomem *dist_base; @@ -48,7 +45,7 @@ struct gic_chip_data { #define MAX_GIC_NR 1 #endif -static struct gic_chip_data gic_data[MAX_GIC_NR] __read_mostly; +static struct gic_chip_data gic_data[MAX_GIC_NR]; static inline void __iomem *gic_dist_base(unsigned int irq) { @@ -216,16 +213,21 @@ void __init gic_cascade_irq(unsigned int gic_nr, unsigned int irq) set_irq_chained_handler(irq, gic_handle_cascade_irq); } -static void __init gic_dist_init(struct gic_chip_data *gic, - unsigned int irq_start) +void __init gic_dist_init(unsigned int gic_nr, void __iomem *base, + unsigned int irq_start) { unsigned int gic_irqs, irq_limit, i; - void __iomem *base = gic->dist_base; u32 cpumask = 1 << smp_processor_id(); + if (gic_nr >= MAX_GIC_NR) + BUG(); + cpumask |= cpumask << 8; cpumask |= cpumask << 16; + gic_data[gic_nr].dist_base = base; + gic_data[gic_nr].irq_offset = (irq_start - 1) & ~31; + writel(0, base + GIC_DIST_CTRL); /* @@ -265,7 +267,7 @@ static void __init gic_dist_init(struct gic_chip_data *gic, /* * Limit number of interrupts registered to the platform maximum */ - irq_limit = gic->irq_offset + gic_irqs; + irq_limit = gic_data[gic_nr].irq_offset + gic_irqs; if (WARN_ON(irq_limit > NR_IRQS)) irq_limit = NR_IRQS; @@ -274,7 +276,7 @@ static void __init gic_dist_init(struct gic_chip_data *gic, */ for (i = irq_start; i < irq_limit; i++) { set_irq_chip(i, &gic_chip); - set_irq_chip_data(i, gic); + set_irq_chip_data(i, &gic_data[gic_nr]); set_irq_handler(i, handle_level_irq); set_irq_flags(i, IRQF_VALID | IRQF_PROBE); } @@ -282,12 +284,19 @@ static void __init gic_dist_init(struct gic_chip_data *gic, writel(1, base + GIC_DIST_CTRL); } -static void __cpuinit gic_cpu_init(struct gic_chip_data *gic) +void __cpuinit gic_cpu_init(unsigned int gic_nr, void __iomem *base) { - void __iomem *dist_base = gic->dist_base; - void __iomem *base = gic->cpu_base; + void __iomem *dist_base; int i; + if (gic_nr >= MAX_GIC_NR) + BUG(); + + dist_base = gic_data[gic_nr].dist_base; + BUG_ON(!dist_base); + + gic_data[gic_nr].cpu_base = base; + /* * Deal with the banked PPI and SGI interrupts - disable all * PPI interrupts, ensure all SGI interrupts are enabled. @@ -305,42 +314,6 @@ static void __cpuinit gic_cpu_init(struct gic_chip_data *gic) writel(1, base + GIC_CPU_CTRL); } -void __init gic_init(unsigned int gic_nr, unsigned int irq_start, - void __iomem *dist_base, void __iomem *cpu_base) -{ - struct gic_chip_data *gic; - - BUG_ON(gic_nr >= MAX_GIC_NR); - - gic = &gic_data[gic_nr]; - gic->dist_base = dist_base; - gic->cpu_base = cpu_base; - gic->irq_offset = (irq_start - 1) & ~31; - - if (gic_nr == 0) - gic_cpu_base_addr = cpu_base; - - gic_dist_init(gic, irq_start); - gic_cpu_init(gic); -} - -void __cpuinit gic_secondary_init(unsigned int gic_nr) -{ - BUG_ON(gic_nr >= MAX_GIC_NR); - - gic_cpu_init(&gic_data[gic_nr]); -} - -void __cpuinit gic_enable_ppi(unsigned int irq) -{ - unsigned long flags; - - local_irq_save(flags); - irq_to_desc(irq)->status |= IRQ_NOPROBE; - gic_unmask_irq(irq); - local_irq_restore(flags); -} - #ifdef CONFIG_SMP void gic_raise_softirq(const struct cpumask *mask, unsigned int irq) { diff --git a/trunk/arch/arm/include/asm/hardware/entry-macro-gic.S b/trunk/arch/arm/include/asm/hardware/entry-macro-gic.S deleted file mode 100644 index c115b82fe80a..000000000000 --- a/trunk/arch/arm/include/asm/hardware/entry-macro-gic.S +++ /dev/null @@ -1,75 +0,0 @@ -/* - * arch/arm/include/asm/hardware/entry-macro-gic.S - * - * Low-level IRQ helper macros for GIC - * - * 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. - */ - -#include - -#ifndef HAVE_GET_IRQNR_PREAMBLE - .macro get_irqnr_preamble, base, tmp - ldr \base, =gic_cpu_base_addr - ldr \base, [\base] - .endm -#endif - -/* - * The interrupt numbering scheme is defined in the - * interrupt controller spec. To wit: - * - * Interrupts 0-15 are IPI - * 16-28 are reserved - * 29-31 are local. We allow 30 to be used for the watchdog. - * 32-1020 are global - * 1021-1022 are reserved - * 1023 is "spurious" (no interrupt) - * - * For now, we ignore all local interrupts so only return an interrupt if it's - * between 30 and 1020. The test_for_ipi routine below will pick up on IPIs. - * - * A simple read from the controller will tell us the number of the highest - * priority enabled interrupt. We then just need to check whether it is in the - * valid range for an IRQ (30-1020 inclusive). - */ - - .macro get_irqnr_and_base, irqnr, irqstat, base, tmp - - ldr \irqstat, [\base, #GIC_CPU_INTACK] - /* bits 12-10 = src CPU, 9-0 = int # */ - - ldr \tmp, =1021 - bic \irqnr, \irqstat, #0x1c00 - cmp \irqnr, #29 - cmpcc \irqnr, \irqnr - cmpne \irqnr, \tmp - cmpcs \irqnr, \irqnr - .endm - -/* We assume that irqstat (the raw value of the IRQ acknowledge - * register) is preserved from the macro above. - * If there is an IPI, we immediately signal end of interrupt on the - * controller, since this requires the original irqstat value which - * we won't easily be able to recreate later. - */ - - .macro test_for_ipi, irqnr, irqstat, base, tmp - bic \irqnr, \irqstat, #0x1c00 - cmp \irqnr, #16 - strcc \irqstat, [\base, #GIC_CPU_EOI] - cmpcs \irqnr, \irqnr - .endm - -/* As above, this assumes that irqstat and base are preserved.. */ - - .macro test_for_ltirq, irqnr, irqstat, base, tmp - bic \irqnr, \irqstat, #0x1c00 - mov \tmp, #0 - cmp \irqnr, #29 - moveq \tmp, #1 - streq \irqstat, [\base, #GIC_CPU_EOI] - cmp \tmp, #0 - .endm diff --git a/trunk/arch/arm/include/asm/hardware/gic.h b/trunk/arch/arm/include/asm/hardware/gic.h index 84557d321001..7f34333bb545 100644 --- a/trunk/arch/arm/include/asm/hardware/gic.h +++ b/trunk/arch/arm/include/asm/hardware/gic.h @@ -33,13 +33,10 @@ #define GIC_DIST_SOFTINT 0xf00 #ifndef __ASSEMBLY__ -extern void __iomem *gic_cpu_base_addr; - -void gic_init(unsigned int, unsigned int, void __iomem *, void __iomem *); -void gic_secondary_init(unsigned int); +void gic_dist_init(unsigned int gic_nr, void __iomem *base, unsigned int irq_start); +void gic_cpu_init(unsigned int gic_nr, void __iomem *base); void gic_cascade_irq(unsigned int gic_nr, unsigned int irq); void gic_raise_softirq(const struct cpumask *mask, unsigned int irq); -void gic_enable_ppi(unsigned int); #endif #endif diff --git a/trunk/arch/arm/include/asm/io.h b/trunk/arch/arm/include/asm/io.h index 815efa2d4e07..91be1f8c2d25 100644 --- a/trunk/arch/arm/include/asm/io.h +++ b/trunk/arch/arm/include/asm/io.h @@ -245,13 +245,13 @@ extern void _memset_io(volatile void __iomem *, int, size_t); #define ioremap_nocache(cookie,size) __arm_ioremap(cookie, size, MT_DEVICE) #define ioremap_cached(cookie,size) __arm_ioremap(cookie, size, MT_DEVICE_CACHED) #define ioremap_wc(cookie,size) __arm_ioremap(cookie, size, MT_DEVICE_WC) -#define iounmap(cookie) __iounmap(cookie) +#define iounmap __iounmap #else #define ioremap(cookie,size) __arch_ioremap((cookie), (size), MT_DEVICE) #define ioremap_nocache(cookie,size) __arch_ioremap((cookie), (size), MT_DEVICE) #define ioremap_cached(cookie,size) __arch_ioremap((cookie), (size), MT_DEVICE_CACHED) #define ioremap_wc(cookie,size) __arch_ioremap((cookie), (size), MT_DEVICE_WC) -#define iounmap(cookie) __arch_iounmap(cookie) +#define iounmap __arch_iounmap #endif /* diff --git a/trunk/arch/arm/kernel/smp_twd.c b/trunk/arch/arm/kernel/smp_twd.c index 67f933ec4177..35882fbf37f9 100644 --- a/trunk/arch/arm/kernel/smp_twd.c +++ b/trunk/arch/arm/kernel/smp_twd.c @@ -127,6 +127,8 @@ static void __cpuinit twd_calibrate_rate(void) */ void __cpuinit twd_timer_setup(struct clock_event_device *clk) { + unsigned long flags; + twd_calibrate_rate(); clk->name = "local_timer"; @@ -141,7 +143,10 @@ void __cpuinit twd_timer_setup(struct clock_event_device *clk) clk->min_delta_ns = clockevent_delta2ns(0xf, clk); /* Make sure our local interrupt controller has this enabled */ - gic_enable_ppi(clk->irq); + local_irq_save(flags); + irq_to_desc(clk->irq)->status |= IRQ_NOPROBE; + get_irq_chip(clk->irq)->unmask(clk->irq); + local_irq_restore(flags); clockevents_register_device(clk); } diff --git a/trunk/arch/arm/mach-cns3xxx/core.c b/trunk/arch/arm/mach-cns3xxx/core.c index da30078a80c1..9ca4d581016f 100644 --- a/trunk/arch/arm/mach-cns3xxx/core.c +++ b/trunk/arch/arm/mach-cns3xxx/core.c @@ -69,10 +69,13 @@ void __init cns3xxx_map_io(void) } /* used by entry-macro.S */ +void __iomem *gic_cpu_base_addr; + void __init cns3xxx_init_irq(void) { - gic_init(0, 29, __io(CNS3XXX_TC11MP_GIC_DIST_BASE_VIRT), - __io(CNS3XXX_TC11MP_GIC_CPU_BASE_VIRT)); + gic_cpu_base_addr = __io(CNS3XXX_TC11MP_GIC_CPU_BASE_VIRT); + gic_dist_init(0, __io(CNS3XXX_TC11MP_GIC_DIST_BASE_VIRT), 29); + gic_cpu_init(0, gic_cpu_base_addr); } void cns3xxx_power_off(void) diff --git a/trunk/arch/arm/mach-cns3xxx/core.h b/trunk/arch/arm/mach-cns3xxx/core.h index ef9e5116b1a9..6b33ec11346e 100644 --- a/trunk/arch/arm/mach-cns3xxx/core.h +++ b/trunk/arch/arm/mach-cns3xxx/core.h @@ -11,6 +11,7 @@ #ifndef __CNS3XXX_CORE_H #define __CNS3XXX_CORE_H +extern void __iomem *gic_cpu_base_addr; extern struct sys_timer cns3xxx_timer; void __init cns3xxx_map_io(void); diff --git a/trunk/arch/arm/mach-cns3xxx/include/mach/entry-macro.S b/trunk/arch/arm/mach-cns3xxx/include/mach/entry-macro.S index 6bd83ed90afe..5e1c5545680f 100644 --- a/trunk/arch/arm/mach-cns3xxx/include/mach/entry-macro.S +++ b/trunk/arch/arm/mach-cns3xxx/include/mach/entry-macro.S @@ -9,10 +9,74 @@ */ #include -#include +#include .macro disable_fiq .endm + .macro get_irqnr_preamble, base, tmp + ldr \base, =gic_cpu_base_addr + ldr \base, [\base] + .endm + .macro arch_ret_to_user, tmp1, tmp2 .endm + + /* + * The interrupt numbering scheme is defined in the + * interrupt controller spec. To wit: + * + * Interrupts 0-15 are IPI + * 16-28 are reserved + * 29-31 are local. We allow 30 to be used for the watchdog. + * 32-1020 are global + * 1021-1022 are reserved + * 1023 is "spurious" (no interrupt) + * + * For now, we ignore all local interrupts so only return an interrupt if it's + * between 30 and 1020. The test_for_ipi routine below will pick up on IPIs. + * + * A simple read from the controller will tell us the number of the highest + * priority enabled interrupt. We then just need to check whether it is in the + * valid range for an IRQ (30-1020 inclusive). + */ + + .macro get_irqnr_and_base, irqnr, irqstat, base, tmp + + ldr \irqstat, [\base, #GIC_CPU_INTACK] /* bits 12-10 = src CPU, 9-0 = int # */ + + ldr \tmp, =1021 + + bic \irqnr, \irqstat, #0x1c00 + + cmp \irqnr, #29 + cmpcc \irqnr, \irqnr + cmpne \irqnr, \tmp + cmpcs \irqnr, \irqnr + + .endm + + /* We assume that irqstat (the raw value of the IRQ acknowledge + * register) is preserved from the macro above. + * If there is an IPI, we immediately signal end of interrupt on the + * controller, since this requires the original irqstat value which + * we won't easily be able to recreate later. + */ + + .macro test_for_ipi, irqnr, irqstat, base, tmp + bic \irqnr, \irqstat, #0x1c00 + cmp \irqnr, #16 + strcc \irqstat, [\base, #GIC_CPU_EOI] + cmpcs \irqnr, \irqnr + .endm + + /* As above, this assumes that irqstat and base are preserved.. */ + + .macro test_for_ltirq, irqnr, irqstat, base, tmp + bic \irqnr, \irqstat, #0x1c00 + mov \tmp, #0 + cmp \irqnr, #29 + moveq \tmp, #1 + streq \irqstat, [\base, #GIC_CPU_EOI] + cmp \tmp, #0 + .endm diff --git a/trunk/arch/arm/mach-davinci/include/mach/io.h b/trunk/arch/arm/mach-davinci/include/mach/io.h index 62b0a90309ad..d1b954955c12 100644 --- a/trunk/arch/arm/mach-davinci/include/mach/io.h +++ b/trunk/arch/arm/mach-davinci/include/mach/io.h @@ -22,8 +22,8 @@ #define __mem_isa(a) (a) #ifndef __ASSEMBLER__ -#define __arch_ioremap(p, s, t) davinci_ioremap(p, s, t) -#define __arch_iounmap(v) davinci_iounmap(v) +#define __arch_ioremap davinci_ioremap +#define __arch_iounmap davinci_iounmap void __iomem *davinci_ioremap(unsigned long phys, size_t size, unsigned int type); diff --git a/trunk/arch/arm/mach-iop13xx/include/mach/io.h b/trunk/arch/arm/mach-iop13xx/include/mach/io.h index a6e0f9e6ddcf..dffb234bb967 100644 --- a/trunk/arch/arm/mach-iop13xx/include/mach/io.h +++ b/trunk/arch/arm/mach-iop13xx/include/mach/io.h @@ -35,7 +35,7 @@ extern u32 iop13xx_atux_mem_base; extern size_t iop13xx_atue_mem_size; extern size_t iop13xx_atux_mem_size; -#define __arch_ioremap(a, s, f) __iop13xx_ioremap(a, s, f) -#define __arch_iounmap(a) __iop13xx_iounmap(a) +#define __arch_ioremap __iop13xx_ioremap +#define __arch_iounmap __iop13xx_iounmap #endif diff --git a/trunk/arch/arm/mach-iop32x/include/mach/io.h b/trunk/arch/arm/mach-iop32x/include/mach/io.h index 339e5854728b..059c783ce0b2 100644 --- a/trunk/arch/arm/mach-iop32x/include/mach/io.h +++ b/trunk/arch/arm/mach-iop32x/include/mach/io.h @@ -21,7 +21,7 @@ extern void __iop3xx_iounmap(void __iomem *addr); #define __io(p) ((void __iomem *)IOP3XX_PCI_IO_PHYS_TO_VIRT(p)) #define __mem_pci(a) (a) -#define __arch_ioremap(a, s, f) __iop3xx_ioremap(a, s, f) -#define __arch_iounmap(a) __iop3xx_iounmap(a) +#define __arch_ioremap __iop3xx_ioremap +#define __arch_iounmap __iop3xx_iounmap #endif diff --git a/trunk/arch/arm/mach-iop33x/include/mach/io.h b/trunk/arch/arm/mach-iop33x/include/mach/io.h index e99a7ed6d050..39e893e97c21 100644 --- a/trunk/arch/arm/mach-iop33x/include/mach/io.h +++ b/trunk/arch/arm/mach-iop33x/include/mach/io.h @@ -21,7 +21,7 @@ extern void __iop3xx_iounmap(void __iomem *addr); #define __io(p) ((void __iomem *)IOP3XX_PCI_IO_PHYS_TO_VIRT(p)) #define __mem_pci(a) (a) -#define __arch_ioremap(a, s, f) __iop3xx_ioremap(a, s, f) -#define __arch_iounmap(a) __iop3xx_iounmap(a) +#define __arch_ioremap __iop3xx_ioremap +#define __arch_iounmap __iop3xx_iounmap #endif diff --git a/trunk/arch/arm/mach-ixp23xx/include/mach/io.h b/trunk/arch/arm/mach-ixp23xx/include/mach/io.h index fd9ef8e519f7..a1749d0fd896 100644 --- a/trunk/arch/arm/mach-ixp23xx/include/mach/io.h +++ b/trunk/arch/arm/mach-ixp23xx/include/mach/io.h @@ -45,8 +45,8 @@ ixp23xx_iounmap(void __iomem *addr) __iounmap(addr); } -#define __arch_ioremap(a,s,f) ixp23xx_ioremap(a,s,f) -#define __arch_iounmap(a) ixp23xx_iounmap(a) +#define __arch_ioremap ixp23xx_ioremap +#define __arch_iounmap ixp23xx_iounmap #endif diff --git a/trunk/arch/arm/mach-ixp4xx/include/mach/io.h b/trunk/arch/arm/mach-ixp4xx/include/mach/io.h index de274a1f19d7..57b5410c31f4 100644 --- a/trunk/arch/arm/mach-ixp4xx/include/mach/io.h +++ b/trunk/arch/arm/mach-ixp4xx/include/mach/io.h @@ -74,8 +74,8 @@ static inline void __indirect_iounmap(void __iomem *addr) __iounmap(addr); } -#define __arch_ioremap(a, s, f) __indirect_ioremap(a, s, f) -#define __arch_iounmap(a) __indirect_iounmap(a) +#define __arch_ioremap __indirect_ioremap +#define __arch_iounmap __indirect_iounmap #define writeb(v, p) __indirect_writeb(v, p) #define writew(v, p) __indirect_writew(v, p) diff --git a/trunk/arch/arm/mach-kirkwood/include/mach/io.h b/trunk/arch/arm/mach-kirkwood/include/mach/io.h index 44e8be04f259..1aaddc364f2e 100644 --- a/trunk/arch/arm/mach-kirkwood/include/mach/io.h +++ b/trunk/arch/arm/mach-kirkwood/include/mach/io.h @@ -42,8 +42,8 @@ __arch_iounmap(void __iomem *addr) __iounmap(addr); } -#define __arch_ioremap(p, s, m) __arch_ioremap(p, s, m) -#define __arch_iounmap(a) __arch_iounmap(a) +#define __arch_ioremap __arch_ioremap +#define __arch_iounmap __arch_iounmap #define __io(a) __io(a) #define __mem_pci(a) (a) diff --git a/trunk/arch/arm/mach-msm/board-msm8x60.c b/trunk/arch/arm/mach-msm/board-msm8x60.c index 9b5eb2b4ae1b..7486a681cc71 100644 --- a/trunk/arch/arm/mach-msm/board-msm8x60.c +++ b/trunk/arch/arm/mach-msm/board-msm8x60.c @@ -28,6 +28,8 @@ #include #include +void __iomem *gic_cpu_base_addr; + unsigned long clk_get_max_axi_khz(void) { return 0; @@ -42,8 +44,9 @@ static void __init msm8x60_init_irq(void) { unsigned int i; - gic_init(0, GIC_PPI_START, MSM_QGIC_DIST_BASE, - (void *)MSM_QGIC_CPU_BASE); + gic_dist_init(0, MSM_QGIC_DIST_BASE, GIC_PPI_START); + gic_cpu_base_addr = (void *)MSM_QGIC_CPU_BASE; + gic_cpu_init(0, MSM_QGIC_CPU_BASE); /* Edge trigger PPIs except AVS_SVICINT and AVS_SVICINTSWDONE */ writel(0xFFFFD7FF, MSM_QGIC_DIST_BASE + GIC_DIST_CONFIG + 4); diff --git a/trunk/arch/arm/mach-omap2/include/mach/entry-macro.S b/trunk/arch/arm/mach-omap2/include/mach/entry-macro.S index d54c4f89a8bd..06e64e1fc28a 100644 --- a/trunk/arch/arm/mach-omap2/include/mach/entry-macro.S +++ b/trunk/arch/arm/mach-omap2/include/mach/entry-macro.S @@ -105,35 +105,6 @@ omap_irq_base: .word 0 9999: .endm -#ifdef CONFIG_SMP - /* We assume that irqstat (the raw value of the IRQ acknowledge - * register) is preserved from the macro above. - * If there is an IPI, we immediately signal end of interrupt - * on the controller, since this requires the original irqstat - * value which we won't easily be able to recreate later. - */ - - .macro test_for_ipi, irqnr, irqstat, base, tmp - bic \irqnr, \irqstat, #0x1c00 - cmp \irqnr, #16 - it cc - strcc \irqstat, [\base, #GIC_CPU_EOI] - it cs - cmpcs \irqnr, \irqnr - .endm - - /* As above, this assumes that irqstat and base are preserved */ - - .macro test_for_ltirq, irqnr, irqstat, base, tmp - bic \irqnr, \irqstat, #0x1c00 - mov \tmp, #0 - cmp \irqnr, #29 - itt eq - moveq \tmp, #1 - streq \irqstat, [\base, #GIC_CPU_EOI] - cmp \tmp, #0 - .endm -#endif /* CONFIG_SMP */ #else /* MULTI_OMAP2 */ @@ -170,16 +141,74 @@ omap_irq_base: .word 0 #ifdef CONFIG_ARCH_OMAP4 -#define HAVE_GET_IRQNR_PREAMBLE -#include .macro get_irqnr_preamble, base, tmp ldr \base, =OMAP4_IRQ_BASE .endm -#endif + /* + * The interrupt numbering scheme is defined in the + * interrupt controller spec. To wit: + * + * Interrupts 0-15 are IPI + * 16-28 are reserved + * 29-31 are local. We allow 30 to be used for the watchdog. + * 32-1020 are global + * 1021-1022 are reserved + * 1023 is "spurious" (no interrupt) + * + * For now, we ignore all local interrupts so only return an + * interrupt if it's between 30 and 1020. The test_for_ipi + * routine below will pick up on IPIs. + * A simple read from the controller will tell us the number + * of the highest priority enabled interrupt. + * We then just need to check whether it is in the + * valid range for an IRQ (30-1020 inclusive). + */ + .macro get_irqnr_and_base, irqnr, irqstat, base, tmp + ldr \irqstat, [\base, #GIC_CPU_INTACK] + ldr \tmp, =1021 + + bic \irqnr, \irqstat, #0x1c00 + + cmp \irqnr, #29 + cmpcc \irqnr, \irqnr + cmpne \irqnr, \tmp + cmpcs \irqnr, \irqnr + .endm +#endif #endif /* MULTI_OMAP2 */ +#ifdef CONFIG_SMP + /* We assume that irqstat (the raw value of the IRQ acknowledge + * register) is preserved from the macro above. + * If there is an IPI, we immediately signal end of interrupt + * on the controller, since this requires the original irqstat + * value which we won't easily be able to recreate later. + */ + + .macro test_for_ipi, irqnr, irqstat, base, tmp + bic \irqnr, \irqstat, #0x1c00 + cmp \irqnr, #16 + it cc + strcc \irqstat, [\base, #GIC_CPU_EOI] + it cs + cmpcs \irqnr, \irqnr + .endm + + /* As above, this assumes that irqstat and base are preserved */ + + .macro test_for_ltirq, irqnr, irqstat, base, tmp + bic \irqnr, \irqstat, #0x1c00 + mov \tmp, #0 + cmp \irqnr, #29 + itt eq + moveq \tmp, #1 + streq \irqstat, [\base, #GIC_CPU_EOI] + cmp \tmp, #0 + .endm +#endif /* CONFIG_SMP */ + .macro irq_prio_table .endm diff --git a/trunk/arch/arm/mach-omap2/include/mach/omap4-common.h b/trunk/arch/arm/mach-omap2/include/mach/omap4-common.h index 5b0270b28934..2744dfee1ff4 100644 --- a/trunk/arch/arm/mach-omap2/include/mach/omap4-common.h +++ b/trunk/arch/arm/mach-omap2/include/mach/omap4-common.h @@ -24,6 +24,7 @@ extern void __iomem *l2cache_base; #endif +extern void __iomem *gic_cpu_base_addr; extern void __iomem *gic_dist_base_addr; extern void __init gic_init_irq(void); diff --git a/trunk/arch/arm/mach-omap2/omap-smp.c b/trunk/arch/arm/mach-omap2/omap-smp.c index 9fbac2c39104..9e9f70e18e3c 100644 --- a/trunk/arch/arm/mach-omap2/omap-smp.c +++ b/trunk/arch/arm/mach-omap2/omap-smp.c @@ -50,7 +50,7 @@ void __cpuinit platform_secondary_init(unsigned int cpu) * core (e.g. timer irq), then they will not have been enabled * for us: do so */ - gic_secondary_init(0); + gic_cpu_init(0, gic_cpu_base_addr); /* * Synchronise with the boot thread. diff --git a/trunk/arch/arm/mach-omap2/omap4-common.c b/trunk/arch/arm/mach-omap2/omap4-common.c index 666e852988d5..2f895553e6a8 100644 --- a/trunk/arch/arm/mach-omap2/omap4-common.c +++ b/trunk/arch/arm/mach-omap2/omap4-common.c @@ -26,22 +26,21 @@ void __iomem *l2cache_base; #endif +void __iomem *gic_cpu_base_addr; void __iomem *gic_dist_base_addr; void __init gic_init_irq(void) { - void __iomem *gic_cpu_base; - /* Static mapping, never released */ gic_dist_base_addr = ioremap(OMAP44XX_GIC_DIST_BASE, SZ_4K); BUG_ON(!gic_dist_base_addr); + gic_dist_init(0, gic_dist_base_addr, 29); /* Static mapping, never released */ - gic_cpu_base = ioremap(OMAP44XX_GIC_CPU_BASE, SZ_512); - BUG_ON(!gic_cpu_base); - - gic_init(0, 29, gic_dist_base_addr, gic_cpu_base); + gic_cpu_base_addr = ioremap(OMAP44XX_GIC_CPU_BASE, SZ_512); + BUG_ON(!gic_cpu_base_addr); + gic_cpu_init(0, gic_cpu_base_addr); } #ifdef CONFIG_CACHE_L2X0 diff --git a/trunk/arch/arm/mach-orion5x/include/mach/io.h b/trunk/arch/arm/mach-orion5x/include/mach/io.h index c47b033bd999..c5196101a237 100644 --- a/trunk/arch/arm/mach-orion5x/include/mach/io.h +++ b/trunk/arch/arm/mach-orion5x/include/mach/io.h @@ -38,8 +38,8 @@ __arch_iounmap(void __iomem *addr) __iounmap(addr); } -#define __arch_ioremap(p, s, m) __arch_ioremap(p, s, m) -#define __arch_iounmap(a) __arch_iounmap(a) +#define __arch_ioremap __arch_ioremap +#define __arch_iounmap __arch_iounmap #define __io(a) __typesafe_io(a) #define __mem_pci(a) (a) diff --git a/trunk/arch/arm/mach-realview/core.c b/trunk/arch/arm/mach-realview/core.c index e292eb8c3c4e..07c08151dfe6 100644 --- a/trunk/arch/arm/mach-realview/core.c +++ b/trunk/arch/arm/mach-realview/core.c @@ -54,6 +54,9 @@ #include "core.h" +/* used by entry-macro.S and platsmp.c */ +void __iomem *gic_cpu_base_addr; + #ifdef CONFIG_ZONE_DMA /* * Adjust the zones if there are restrictions for DMA access. diff --git a/trunk/arch/arm/mach-realview/core.h b/trunk/arch/arm/mach-realview/core.h index 693239ddc39e..781bca68a9fa 100644 --- a/trunk/arch/arm/mach-realview/core.h +++ b/trunk/arch/arm/mach-realview/core.h @@ -53,6 +53,7 @@ extern struct platform_device realview_i2c_device; extern struct mmci_platform_data realview_mmc0_plat_data; extern struct mmci_platform_data realview_mmc1_plat_data; extern struct clcd_board clcd_plat_data; +extern void __iomem *gic_cpu_base_addr; extern void __iomem *timer0_va_base; extern void __iomem *timer1_va_base; extern void __iomem *timer2_va_base; diff --git a/trunk/arch/arm/mach-realview/include/mach/entry-macro.S b/trunk/arch/arm/mach-realview/include/mach/entry-macro.S index 4071164aebaa..340a5c276946 100644 --- a/trunk/arch/arm/mach-realview/include/mach/entry-macro.S +++ b/trunk/arch/arm/mach-realview/include/mach/entry-macro.S @@ -8,11 +8,74 @@ * warranty of any kind, whether express or implied. */ #include -#include +#include .macro disable_fiq .endm + .macro get_irqnr_preamble, base, tmp + ldr \base, =gic_cpu_base_addr + ldr \base, [\base] + .endm + .macro arch_ret_to_user, tmp1, tmp2 .endm + /* + * The interrupt numbering scheme is defined in the + * interrupt controller spec. To wit: + * + * Interrupts 0-15 are IPI + * 16-28 are reserved + * 29-31 are local. We allow 30 to be used for the watchdog. + * 32-1020 are global + * 1021-1022 are reserved + * 1023 is "spurious" (no interrupt) + * + * For now, we ignore all local interrupts so only return an interrupt if it's + * between 30 and 1020. The test_for_ipi routine below will pick up on IPIs. + * + * A simple read from the controller will tell us the number of the highest + * priority enabled interrupt. We then just need to check whether it is in the + * valid range for an IRQ (30-1020 inclusive). + */ + + .macro get_irqnr_and_base, irqnr, irqstat, base, tmp + + ldr \irqstat, [\base, #GIC_CPU_INTACK] /* bits 12-10 = src CPU, 9-0 = int # */ + + ldr \tmp, =1021 + + bic \irqnr, \irqstat, #0x1c00 + + cmp \irqnr, #29 + cmpcc \irqnr, \irqnr + cmpne \irqnr, \tmp + cmpcs \irqnr, \irqnr + + .endm + + /* We assume that irqstat (the raw value of the IRQ acknowledge + * register) is preserved from the macro above. + * If there is an IPI, we immediately signal end of interrupt on the + * controller, since this requires the original irqstat value which + * we won't easily be able to recreate later. + */ + + .macro test_for_ipi, irqnr, irqstat, base, tmp + bic \irqnr, \irqstat, #0x1c00 + cmp \irqnr, #16 + strcc \irqstat, [\base, #GIC_CPU_EOI] + cmpcs \irqnr, \irqnr + .endm + + /* As above, this assumes that irqstat and base are preserved.. */ + + .macro test_for_ltirq, irqnr, irqstat, base, tmp + bic \irqnr, \irqstat, #0x1c00 + mov \tmp, #0 + cmp \irqnr, #29 + moveq \tmp, #1 + streq \irqstat, [\base, #GIC_CPU_EOI] + cmp \tmp, #0 + .endm diff --git a/trunk/arch/arm/mach-realview/platsmp.c b/trunk/arch/arm/mach-realview/platsmp.c index 6da8a2e53c44..009265818d55 100644 --- a/trunk/arch/arm/mach-realview/platsmp.c +++ b/trunk/arch/arm/mach-realview/platsmp.c @@ -69,7 +69,7 @@ void __cpuinit platform_secondary_init(unsigned int cpu) * core (e.g. timer irq), then they will not have been enabled * for us: do so */ - gic_secondary_init(0); + gic_cpu_init(0, gic_cpu_base_addr); /* * let the primary processor know we're out of the diff --git a/trunk/arch/arm/mach-realview/realview_eb.c b/trunk/arch/arm/mach-realview/realview_eb.c index 6ef5c5e528b2..f2697106f809 100644 --- a/trunk/arch/arm/mach-realview/realview_eb.c +++ b/trunk/arch/arm/mach-realview/realview_eb.c @@ -364,19 +364,21 @@ static void __init gic_init_irq(void) writel(0x00000000, __io_address(REALVIEW_SYS_LOCK)); /* core tile GIC, primary */ - gic_init(0, 29, __io_address(REALVIEW_EB11MP_GIC_DIST_BASE), - __io_address(REALVIEW_EB11MP_GIC_CPU_BASE)); + gic_cpu_base_addr = __io_address(REALVIEW_EB11MP_GIC_CPU_BASE); + gic_dist_init(0, __io_address(REALVIEW_EB11MP_GIC_DIST_BASE), 29); + gic_cpu_init(0, gic_cpu_base_addr); #ifndef CONFIG_REALVIEW_EB_ARM11MP_REVB /* board GIC, secondary */ - gic_init(1, 64, __io_address(REALVIEW_EB_GIC_DIST_BASE), - __io_address(REALVIEW_EB_GIC_CPU_BASE)); + gic_dist_init(1, __io_address(REALVIEW_EB_GIC_DIST_BASE), 64); + gic_cpu_init(1, __io_address(REALVIEW_EB_GIC_CPU_BASE)); gic_cascade_irq(1, IRQ_EB11MP_EB_IRQ1); #endif } else { /* board GIC, primary */ - gic_init(0, 29, __io_address(REALVIEW_EB_GIC_DIST_BASE), - __io_address(REALVIEW_EB_GIC_CPU_BASE)); + gic_cpu_base_addr = __io_address(REALVIEW_EB_GIC_CPU_BASE); + gic_dist_init(0, __io_address(REALVIEW_EB_GIC_DIST_BASE), 29); + gic_cpu_init(0, gic_cpu_base_addr); } } diff --git a/trunk/arch/arm/mach-realview/realview_pb1176.c b/trunk/arch/arm/mach-realview/realview_pb1176.c index cbdc97a5685f..a4125619d71b 100644 --- a/trunk/arch/arm/mach-realview/realview_pb1176.c +++ b/trunk/arch/arm/mach-realview/realview_pb1176.c @@ -304,14 +304,13 @@ static struct platform_device char_lcd_device = { static void __init gic_init_irq(void) { /* ARM1176 DevChip GIC, primary */ - gic_init(0, IRQ_DC1176_GIC_START, - __io_address(REALVIEW_DC1176_GIC_DIST_BASE), - __io_address(REALVIEW_DC1176_GIC_CPU_BASE)); + gic_cpu_base_addr = __io_address(REALVIEW_DC1176_GIC_CPU_BASE); + gic_dist_init(0, __io_address(REALVIEW_DC1176_GIC_DIST_BASE), IRQ_DC1176_GIC_START); + gic_cpu_init(0, gic_cpu_base_addr); /* board GIC, secondary */ - gic_init(1, IRQ_PB1176_GIC_START, - __io_address(REALVIEW_PB1176_GIC_DIST_BASE), - __io_address(REALVIEW_PB1176_GIC_CPU_BASE)); + gic_dist_init(1, __io_address(REALVIEW_PB1176_GIC_DIST_BASE), IRQ_PB1176_GIC_START); + gic_cpu_init(1, __io_address(REALVIEW_PB1176_GIC_CPU_BASE)); gic_cascade_irq(1, IRQ_DC1176_PB_IRQ1); } diff --git a/trunk/arch/arm/mach-realview/realview_pb11mp.c b/trunk/arch/arm/mach-realview/realview_pb11mp.c index 8e8ab7d29a6a..117b95b2ca15 100644 --- a/trunk/arch/arm/mach-realview/realview_pb11mp.c +++ b/trunk/arch/arm/mach-realview/realview_pb11mp.c @@ -309,13 +309,13 @@ static void __init gic_init_irq(void) writel(0x00000000, __io_address(REALVIEW_SYS_LOCK)); /* ARM11MPCore test chip GIC, primary */ - gic_init(0, 29, __io_address(REALVIEW_TC11MP_GIC_DIST_BASE), - __io_address(REALVIEW_TC11MP_GIC_CPU_BASE)); + gic_cpu_base_addr = __io_address(REALVIEW_TC11MP_GIC_CPU_BASE); + gic_dist_init(0, __io_address(REALVIEW_TC11MP_GIC_DIST_BASE), 29); + gic_cpu_init(0, gic_cpu_base_addr); /* board GIC, secondary */ - gic_init(1, IRQ_PB11MP_GIC_START, - __io_address(REALVIEW_PB11MP_GIC_DIST_BASE), - __io_address(REALVIEW_PB11MP_GIC_CPU_BASE)); + gic_dist_init(1, __io_address(REALVIEW_PB11MP_GIC_DIST_BASE), IRQ_PB11MP_GIC_START); + gic_cpu_init(1, __io_address(REALVIEW_PB11MP_GIC_CPU_BASE)); gic_cascade_irq(1, IRQ_TC11MP_PB_IRQ1); } diff --git a/trunk/arch/arm/mach-realview/realview_pba8.c b/trunk/arch/arm/mach-realview/realview_pba8.c index 841118e3e118..929b8dc12e81 100644 --- a/trunk/arch/arm/mach-realview/realview_pba8.c +++ b/trunk/arch/arm/mach-realview/realview_pba8.c @@ -273,9 +273,9 @@ static struct platform_device pmu_device = { static void __init gic_init_irq(void) { /* ARM PB-A8 on-board GIC */ - gic_init(0, IRQ_PBA8_GIC_START, - __io_address(REALVIEW_PBA8_GIC_DIST_BASE), - __io_address(REALVIEW_PBA8_GIC_CPU_BASE)); + gic_cpu_base_addr = __io_address(REALVIEW_PBA8_GIC_CPU_BASE); + gic_dist_init(0, __io_address(REALVIEW_PBA8_GIC_DIST_BASE), IRQ_PBA8_GIC_START); + gic_cpu_init(0, __io_address(REALVIEW_PBA8_GIC_CPU_BASE)); } static void __init realview_pba8_timer_init(void) diff --git a/trunk/arch/arm/mach-realview/realview_pbx.c b/trunk/arch/arm/mach-realview/realview_pbx.c index 02b755b009db..b9f9e20031a7 100644 --- a/trunk/arch/arm/mach-realview/realview_pbx.c +++ b/trunk/arch/arm/mach-realview/realview_pbx.c @@ -313,12 +313,15 @@ static void __init gic_init_irq(void) { /* ARM PBX on-board GIC */ if (core_tile_pbx11mp() || core_tile_pbxa9mp()) { - gic_init(0, 29, __io_address(REALVIEW_PBX_TILE_GIC_DIST_BASE), - __io_address(REALVIEW_PBX_TILE_GIC_CPU_BASE)); + gic_cpu_base_addr = __io_address(REALVIEW_PBX_TILE_GIC_CPU_BASE); + gic_dist_init(0, __io_address(REALVIEW_PBX_TILE_GIC_DIST_BASE), + 29); + gic_cpu_init(0, __io_address(REALVIEW_PBX_TILE_GIC_CPU_BASE)); } else { - gic_init(0, IRQ_PBX_GIC_START, - __io_address(REALVIEW_PBX_GIC_DIST_BASE), - __io_address(REALVIEW_PBX_GIC_CPU_BASE)); + gic_cpu_base_addr = __io_address(REALVIEW_PBX_GIC_CPU_BASE); + gic_dist_init(0, __io_address(REALVIEW_PBX_GIC_DIST_BASE), + IRQ_PBX_GIC_START); + gic_cpu_init(0, __io_address(REALVIEW_PBX_GIC_CPU_BASE)); } } diff --git a/trunk/arch/arm/mach-s5pv310/cpu.c b/trunk/arch/arm/mach-s5pv310/cpu.c index 72ab289e7816..82ce4aa6d61a 100644 --- a/trunk/arch/arm/mach-s5pv310/cpu.c +++ b/trunk/arch/arm/mach-s5pv310/cpu.c @@ -24,6 +24,8 @@ #include +void __iomem *gic_cpu_base_addr; + extern int combiner_init(unsigned int combiner_nr, void __iomem *base, unsigned int irq_start); extern void combiner_cascade_irq(unsigned int combiner_nr, unsigned int irq); @@ -120,7 +122,9 @@ void __init s5pv310_init_irq(void) { int irq; - gic_init(0, IRQ_LOCALTIMER, S5P_VA_GIC_DIST, S5P_VA_GIC_CPU); + gic_cpu_base_addr = S5P_VA_GIC_CPU; + gic_dist_init(0, S5P_VA_GIC_DIST, IRQ_LOCALTIMER); + gic_cpu_init(0, S5P_VA_GIC_CPU); for (irq = 0; irq < MAX_COMBINER_NR; irq++) { combiner_init(irq, (void __iomem *)S5P_VA_COMBINER(irq), diff --git a/trunk/arch/arm/mach-s5pv310/include/mach/smp.h b/trunk/arch/arm/mach-s5pv310/include/mach/smp.h index e1cc6a251c6a..b7ec252384f4 100644 --- a/trunk/arch/arm/mach-s5pv310/include/mach/smp.h +++ b/trunk/arch/arm/mach-s5pv310/include/mach/smp.h @@ -9,6 +9,8 @@ #include #include +extern void __iomem *gic_cpu_base_addr; + /* * We use IRQ1 as the IPI */ diff --git a/trunk/arch/arm/mach-s5pv310/platsmp.c b/trunk/arch/arm/mach-s5pv310/platsmp.c index 15929c169f81..d357c198edee 100644 --- a/trunk/arch/arm/mach-s5pv310/platsmp.c +++ b/trunk/arch/arm/mach-s5pv310/platsmp.c @@ -54,7 +54,7 @@ void __cpuinit platform_secondary_init(unsigned int cpu) * core (e.g. timer irq), then they will not have been enabled * for us: do so */ - gic_secondary_init(0); + gic_cpu_init(0, gic_cpu_base_addr); /* * let the primary processor know we're out of the diff --git a/trunk/arch/arm/mach-tegra/include/mach/entry-macro.S b/trunk/arch/arm/mach-tegra/include/mach/entry-macro.S index dd165c53889d..2ba9e5c9d2f6 100644 --- a/trunk/arch/arm/mach-tegra/include/mach/entry-macro.S +++ b/trunk/arch/arm/mach-tegra/include/mach/entry-macro.S @@ -16,8 +16,8 @@ #include #if defined(CONFIG_ARM_GIC) -#define HAVE_GET_IRQNR_PREAMBLE -#include + +#include /* Uses the GIC interrupt controller built into the cpu */ #define ICTRL_BASE (IO_CPU_VIRT + 0x100) @@ -32,6 +32,68 @@ .macro arch_ret_to_user, tmp1, tmp2 .endm + + /* + * The interrupt numbering scheme is defined in the + * interrupt controller spec. To wit: + * + * Interrupts 0-15 are IPI + * 16-28 are reserved + * 29-31 are local. We allow 30 to be used for the watchdog. + * 32-1020 are global + * 1021-1022 are reserved + * 1023 is "spurious" (no interrupt) + * + * For now, we ignore all local interrupts so only return an interrupt + * if it's between 30 and 1020. The test_for_ipi routine below will + * pick up on IPIs. + * + * A simple read from the controller will tell us the number of the + * highest priority enabled interrupt. We then just need to check + * whether it is in the valid range for an IRQ (30-1020 inclusive). + */ + + .macro get_irqnr_and_base, irqnr, irqstat, base, tmp + + /* bits 12-10 = src CPU, 9-0 = int # */ + ldr \irqstat, [\base, #GIC_CPU_INTACK] + + ldr \tmp, =1021 + + bic \irqnr, \irqstat, #0x1c00 + + cmp \irqnr, #29 + cmpcc \irqnr, \irqnr + cmpne \irqnr, \tmp + cmpcs \irqnr, \irqnr + + .endm + + /* We assume that irqstat (the raw value of the IRQ acknowledge + * register) is preserved from the macro above. + * If there is an IPI, we immediately signal end of interrupt on the + * controller, since this requires the original irqstat value which + * we won't easily be able to recreate later. + */ + + .macro test_for_ipi, irqnr, irqstat, base, tmp + bic \irqnr, \irqstat, #0x1c00 + cmp \irqnr, #16 + strcc \irqstat, [\base, #GIC_CPU_EOI] + cmpcs \irqnr, \irqnr + .endm + + /* As above, this assumes that irqstat and base are preserved.. */ + + .macro test_for_ltirq, irqnr, irqstat, base, tmp + bic \irqnr, \irqstat, #0x1c00 + mov \tmp, #0 + cmp \irqnr, #29 + moveq \tmp, #1 + streq \irqstat, [\base, #GIC_CPU_EOI] + cmp \tmp, #0 + .endm + #else /* legacy interrupt controller for AP16 */ .macro disable_fiq diff --git a/trunk/arch/arm/mach-tegra/include/mach/io.h b/trunk/arch/arm/mach-tegra/include/mach/io.h index f0981b1ac59e..4cea2230c8dc 100644 --- a/trunk/arch/arm/mach-tegra/include/mach/io.h +++ b/trunk/arch/arm/mach-tegra/include/mach/io.h @@ -65,8 +65,8 @@ #ifndef __ASSEMBLER__ -#define __arch_ioremap(p, s, t) tegra_ioremap(p, s, t) -#define __arch_iounmap(v) tegra_iounmap(v) +#define __arch_ioremap tegra_ioremap +#define __arch_iounmap tegra_iounmap void __iomem *tegra_ioremap(unsigned long phys, size_t size, unsigned int type); void tegra_iounmap(volatile void __iomem *addr); diff --git a/trunk/arch/arm/mach-tegra/irq.c b/trunk/arch/arm/mach-tegra/irq.c index 5407de01abf0..50a8dfb9a0cf 100644 --- a/trunk/arch/arm/mach-tegra/irq.c +++ b/trunk/arch/arm/mach-tegra/irq.c @@ -94,8 +94,8 @@ void __init tegra_init_irq(void) writel(0, ictlr_to_virt(i) + ICTLR_CPU_IEP_CLASS); } - gic_init(0, 29, IO_ADDRESS(TEGRA_ARM_INT_DIST_BASE), - IO_ADDRESS(TEGRA_ARM_PERIF_BASE + 0x100)); + gic_dist_init(0, IO_ADDRESS(TEGRA_ARM_INT_DIST_BASE), 29); + gic_cpu_init(0, IO_ADDRESS(TEGRA_ARM_PERIF_BASE + 0x100)); gic = get_irq_chip(29); gic_unmask_irq = gic->unmask; diff --git a/trunk/arch/arm/mach-tegra/platsmp.c b/trunk/arch/arm/mach-tegra/platsmp.c index 3b7376c4f356..1c0fd92cab39 100644 --- a/trunk/arch/arm/mach-tegra/platsmp.c +++ b/trunk/arch/arm/mach-tegra/platsmp.c @@ -48,7 +48,7 @@ void __cpuinit platform_secondary_init(unsigned int cpu) * core (e.g. timer irq), then they will not have been enabled * for us: do so */ - gic_secondary_init(0); + gic_cpu_init(0, IO_ADDRESS(TEGRA_ARM_PERIF_BASE) + 0x100); /* * Synchronise with the boot thread. diff --git a/trunk/arch/arm/mach-ux500/cpu.c b/trunk/arch/arm/mach-ux500/cpu.c index 7328c0179769..608a1372b172 100644 --- a/trunk/arch/arm/mach-ux500/cpu.c +++ b/trunk/arch/arm/mach-ux500/cpu.c @@ -61,8 +61,8 @@ void __init ux500_init_devices(void) void __init ux500_init_irq(void) { - gic_init(0, 29, __io_address(UX500_GIC_DIST_BASE), - __io_address(UX500_GIC_CPU_BASE)); + gic_dist_init(0, __io_address(UX500_GIC_DIST_BASE), 29); + gic_cpu_init(0, __io_address(UX500_GIC_CPU_BASE)); /* * Init clocks here so that they are available for system timer diff --git a/trunk/arch/arm/mach-ux500/include/mach/entry-macro.S b/trunk/arch/arm/mach-ux500/include/mach/entry-macro.S index a37f585a3ecb..60ea88db8283 100644 --- a/trunk/arch/arm/mach-ux500/include/mach/entry-macro.S +++ b/trunk/arch/arm/mach-ux500/include/mach/entry-macro.S @@ -11,8 +11,7 @@ * warranty of any kind, whether express or implied. */ #include -#define HAVE_GET_IRQNR_PREAMBLE -#include +#include .macro disable_fiq .endm @@ -23,3 +22,68 @@ .macro arch_ret_to_user, tmp1, tmp2 .endm + + /* + * The interrupt numbering scheme is defined in the + * interrupt controller spec. To wit: + * + * Interrupts 0-15 are IPI + * 16-28 are reserved + * 29-31 are local. We allow 30 to be used for the watchdog. + * 32-1020 are global + * 1021-1022 are reserved + * 1023 is "spurious" (no interrupt) + * + * For now, we ignore all local interrupts so only return an + * interrupt if it's between 30 and 1020. The test_for_ipi + * routine below will pick up on IPIs. + * + * A simple read from the controller will tell us the number + * of the highest priority enabled interrupt. We then just + * need to check whether it is in the valid range for an + * IRQ (30-1020 inclusive). + */ + + .macro get_irqnr_and_base, irqnr, irqstat, base, tmp + + /* bits 12-10 = src CPU, 9-0 = int # */ + ldr \irqstat, [\base, #GIC_CPU_INTACK] + + ldr \tmp, =1021 + + bic \irqnr, \irqstat, #0x1c00 + + cmp \irqnr, #29 + cmpcc \irqnr, \irqnr + cmpne \irqnr, \tmp + cmpcs \irqnr, \irqnr + + .endm + + /* We assume that irqstat (the raw value of the IRQ + * acknowledge register) is preserved from the macro above. + * If there is an IPI, we immediately signal end of + * interrupt on the controller, since this requires the + * original irqstat value which we won't easily be able + * to recreate later. + */ + + .macro test_for_ipi, irqnr, irqstat, base, tmp + bic \irqnr, \irqstat, #0x1c00 + cmp \irqnr, #16 + strcc \irqstat, [\base, #GIC_CPU_EOI] + cmpcs \irqnr, \irqnr + .endm + + /* As above, this assumes that irqstat and base + * are preserved.. + */ + + .macro test_for_ltirq, irqnr, irqstat, base, tmp + bic \irqnr, \irqstat, #0x1c00 + mov \tmp, #0 + cmp \irqnr, #29 + moveq \tmp, #1 + streq \irqstat, [\base, #GIC_CPU_EOI] + cmp \tmp, #0 + .endm diff --git a/trunk/arch/arm/mach-ux500/platsmp.c b/trunk/arch/arm/mach-ux500/platsmp.c index b5077b4c419f..9e4c678de785 100644 --- a/trunk/arch/arm/mach-ux500/platsmp.c +++ b/trunk/arch/arm/mach-ux500/platsmp.c @@ -44,7 +44,7 @@ void __cpuinit platform_secondary_init(unsigned int cpu) * core (e.g. timer irq), then they will not have been enabled * for us: do so */ - gic_secondary_init(0); + gic_cpu_init(0, __io_address(UX500_GIC_CPU_BASE)); /* * let the primary processor know we're out of the diff --git a/trunk/arch/arm/mach-vexpress/core.h b/trunk/arch/arm/mach-vexpress/core.h index 362780d868de..57dd95ce41f9 100644 --- a/trunk/arch/arm/mach-vexpress/core.h +++ b/trunk/arch/arm/mach-vexpress/core.h @@ -22,3 +22,5 @@ struct map_desc; void v2m_map_io(struct map_desc *tile, size_t num); extern struct sys_timer v2m_timer; + +extern void __iomem *gic_cpu_base_addr; diff --git a/trunk/arch/arm/mach-vexpress/ct-ca9x4.c b/trunk/arch/arm/mach-vexpress/ct-ca9x4.c index 8e0a3b7c8638..fd25ccd7272f 100644 --- a/trunk/arch/arm/mach-vexpress/ct-ca9x4.c +++ b/trunk/arch/arm/mach-vexpress/ct-ca9x4.c @@ -60,10 +60,13 @@ static void __init ct_ca9x4_map_io(void) v2m_map_io(ct_ca9x4_io_desc, ARRAY_SIZE(ct_ca9x4_io_desc)); } +void __iomem *gic_cpu_base_addr; + static void __init ct_ca9x4_init_irq(void) { - gic_init(0, 29, MMIO_P2V(A9_MPCORE_GIC_DIST), - MMIO_P2V(A9_MPCORE_GIC_CPU)); + gic_cpu_base_addr = MMIO_P2V(A9_MPCORE_GIC_CPU); + gic_dist_init(0, MMIO_P2V(A9_MPCORE_GIC_DIST), 29); + gic_cpu_init(0, gic_cpu_base_addr); } #if 0 diff --git a/trunk/arch/arm/mach-vexpress/include/mach/entry-macro.S b/trunk/arch/arm/mach-vexpress/include/mach/entry-macro.S index 73c11297509e..20e9fb514f0a 100644 --- a/trunk/arch/arm/mach-vexpress/include/mach/entry-macro.S +++ b/trunk/arch/arm/mach-vexpress/include/mach/entry-macro.S @@ -1,7 +1,67 @@ -#include +#include .macro disable_fiq .endm + .macro get_irqnr_preamble, base, tmp + ldr \base, =gic_cpu_base_addr + ldr \base, [\base] + .endm + .macro arch_ret_to_user, tmp1, tmp2 .endm + + /* + * The interrupt numbering scheme is defined in the + * interrupt controller spec. To wit: + * + * Interrupts 0-15 are IPI + * 16-28 are reserved + * 29-31 are local. We allow 30 to be used for the watchdog. + * 32-1020 are global + * 1021-1022 are reserved + * 1023 is "spurious" (no interrupt) + * + * For now, we ignore all local interrupts so only return an interrupt if it's + * between 30 and 1020. The test_for_ipi routine below will pick up on IPIs. + * + * A simple read from the controller will tell us the number of the highest + * priority enabled interrupt. We then just need to check whether it is in the + * valid range for an IRQ (30-1020 inclusive). + */ + + .macro get_irqnr_and_base, irqnr, irqstat, base, tmp + ldr \irqstat, [\base, #GIC_CPU_INTACK] /* bits 12-10 = src CPU, 9-0 = int # */ + ldr \tmp, =1021 + bic \irqnr, \irqstat, #0x1c00 + cmp \irqnr, #29 + cmpcc \irqnr, \irqnr + cmpne \irqnr, \tmp + cmpcs \irqnr, \irqnr + .endm + + /* We assume that irqstat (the raw value of the IRQ acknowledge + * register) is preserved from the macro above. + * If there is an IPI, we immediately signal end of interrupt on the + * controller, since this requires the original irqstat value which + * we won't easily be able to recreate later. + */ + + .macro test_for_ipi, irqnr, irqstat, base, tmp + bic \irqnr, \irqstat, #0x1c00 + cmp \irqnr, #16 + strcc \irqstat, [\base, #GIC_CPU_EOI] + cmpcs \irqnr, \irqnr + .endm + + /* As above, this assumes that irqstat and base are preserved.. */ + + .macro test_for_ltirq, irqnr, irqstat, base, tmp + bic \irqnr, \irqstat, #0x1c00 + mov \tmp, #0 + cmp \irqnr, #29 + moveq \tmp, #1 + streq \irqstat, [\base, #GIC_CPU_EOI] + cmp \tmp, #0 + .endm + diff --git a/trunk/arch/arm/mach-vexpress/platsmp.c b/trunk/arch/arm/mach-vexpress/platsmp.c index dfb591031d17..670970699ba9 100644 --- a/trunk/arch/arm/mach-vexpress/platsmp.c +++ b/trunk/arch/arm/mach-vexpress/platsmp.c @@ -51,7 +51,7 @@ void __cpuinit platform_secondary_init(unsigned int cpu) * core (e.g. timer irq), then they will not have been enabled * for us: do so */ - gic_secondary_init(0); + gic_cpu_init(0, gic_cpu_base_addr); /* * let the primary processor know we're out of the diff --git a/trunk/arch/arm/plat-omap/include/plat/io.h b/trunk/arch/arm/plat-omap/include/plat/io.h index 128b549c2796..204865f91d93 100644 --- a/trunk/arch/arm/plat-omap/include/plat/io.h +++ b/trunk/arch/arm/plat-omap/include/plat/io.h @@ -294,8 +294,8 @@ static inline void omap44xx_map_common_io(void) extern void omap2_init_common_hw(struct omap_sdrc_params *sdrc_cs0, struct omap_sdrc_params *sdrc_cs1); -#define __arch_ioremap(p,s,t) omap_ioremap(p,s,t) -#define __arch_iounmap(v) omap_iounmap(v) +#define __arch_ioremap omap_ioremap +#define __arch_iounmap omap_iounmap void __iomem *omap_ioremap(unsigned long phys, size_t size, unsigned int type); void omap_iounmap(volatile void __iomem *addr);