Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

Merge Realview GIC code

authored by

Russell King and committed by
Russell King
4ba9dcbe 382266ad

+168 -26
+95 -14
arch/arm/common/gic.c
··· 14 14 * 15 15 * o There is one CPU Interface per CPU, which sends interrupts sent 16 16 * by the Distributor, and interrupts generated locally, to the 17 - * associated CPU. 17 + * associated CPU. The base address of the CPU interface is usually 18 + * aliased so that the same address points to different chips depending 19 + * on the CPU it is accessed from. 18 20 * 19 21 * Note that IRQs 0-31 are special - they are local to each CPU. 20 22 * As such, the enable set/clear, pending set/clear and active bit ··· 33 31 #include <asm/mach/irq.h> 34 32 #include <asm/hardware/gic.h> 35 33 36 - static void __iomem *gic_dist_base; 37 - static void __iomem *gic_cpu_base; 38 34 static DEFINE_SPINLOCK(irq_controller_lock); 35 + 36 + struct gic_chip_data { 37 + unsigned int irq_offset; 38 + void __iomem *dist_base; 39 + void __iomem *cpu_base; 40 + }; 41 + 42 + #ifndef MAX_GIC_NR 43 + #define MAX_GIC_NR 1 44 + #endif 45 + 46 + static struct gic_chip_data gic_data[MAX_GIC_NR]; 47 + 48 + static inline void __iomem *gic_dist_base(unsigned int irq) 49 + { 50 + struct gic_chip_data *gic_data = get_irq_chip_data(irq); 51 + return gic_data->dist_base; 52 + } 53 + 54 + static inline void __iomem *gic_cpu_base(unsigned int irq) 55 + { 56 + struct gic_chip_data *gic_data = get_irq_chip_data(irq); 57 + return gic_data->cpu_base; 58 + } 59 + 60 + static inline unsigned int gic_irq(unsigned int irq) 61 + { 62 + struct gic_chip_data *gic_data = get_irq_chip_data(irq); 63 + return irq - gic_data->irq_offset; 64 + } 39 65 40 66 /* 41 67 * Routines to acknowledge, disable and enable interrupts ··· 85 55 u32 mask = 1 << (irq % 32); 86 56 87 57 spin_lock(&irq_controller_lock); 88 - writel(mask, gic_dist_base + GIC_DIST_ENABLE_CLEAR + (irq / 32) * 4); 89 - writel(irq, gic_cpu_base + GIC_CPU_EOI); 58 + writel(mask, gic_dist_base(irq) + GIC_DIST_ENABLE_CLEAR + (gic_irq(irq) / 32) * 4); 59 + writel(gic_irq(irq), gic_cpu_base(irq) + GIC_CPU_EOI); 90 60 spin_unlock(&irq_controller_lock); 91 61 } 92 62 ··· 95 65 u32 mask = 1 << (irq % 32); 96 66 97 67 spin_lock(&irq_controller_lock); 98 - writel(mask, gic_dist_base + GIC_DIST_ENABLE_CLEAR + (irq / 32) * 4); 68 + writel(mask, gic_dist_base(irq) + GIC_DIST_ENABLE_CLEAR + (gic_irq(irq) / 32) * 4); 99 69 spin_unlock(&irq_controller_lock); 100 70 } 101 71 ··· 104 74 u32 mask = 1 << (irq % 32); 105 75 106 76 spin_lock(&irq_controller_lock); 107 - writel(mask, gic_dist_base + GIC_DIST_ENABLE_SET + (irq / 32) * 4); 77 + writel(mask, gic_dist_base(irq) + GIC_DIST_ENABLE_SET + (gic_irq(irq) / 32) * 4); 108 78 spin_unlock(&irq_controller_lock); 109 79 } 110 80 111 81 #ifdef CONFIG_SMP 112 82 static void gic_set_cpu(unsigned int irq, cpumask_t mask_val) 113 83 { 114 - void __iomem *reg = gic_dist_base + GIC_DIST_TARGET + (irq & ~3); 84 + void __iomem *reg = gic_dist_base(irq) + GIC_DIST_TARGET + (gic_irq(irq) & ~3); 115 85 unsigned int shift = (irq % 4) * 8; 116 86 unsigned int cpu = first_cpu(mask_val); 117 87 u32 val; ··· 125 95 } 126 96 #endif 127 97 98 + static void fastcall gic_handle_cascade_irq(unsigned int irq, 99 + struct irq_desc *desc) 100 + { 101 + struct gic_chip_data *chip_data = get_irq_data(irq); 102 + struct irq_chip *chip = get_irq_chip(irq); 103 + unsigned int cascade_irq; 104 + unsigned long status; 105 + 106 + /* primary controller ack'ing */ 107 + chip->ack(irq); 108 + 109 + spin_lock(&irq_controller_lock); 110 + status = readl(chip_data->cpu_base + GIC_CPU_INTACK); 111 + spin_unlock(&irq_controller_lock); 112 + 113 + cascade_irq = (status & 0x3ff); 114 + if (cascade_irq > 1020) 115 + goto out; 116 + if (cascade_irq < 32 || cascade_irq >= NR_IRQS) { 117 + do_bad_IRQ(cascade_irq, desc); 118 + goto out; 119 + } 120 + 121 + cascade_irq += chip_data->irq_offset; 122 + generic_handle_irq(cascade_irq); 123 + 124 + out: 125 + /* primary controller unmasking */ 126 + chip->unmask(irq); 127 + } 128 + 128 129 static struct irq_chip gic_chip = { 129 130 .name = "GIC", 130 131 .ack = gic_ack_irq, ··· 166 105 #endif 167 106 }; 168 107 169 - void __init gic_dist_init(void __iomem *base) 108 + void __init gic_cascade_irq(unsigned int gic_nr, unsigned int irq) 109 + { 110 + if (gic_nr >= MAX_GIC_NR) 111 + BUG(); 112 + if (set_irq_data(irq, &gic_data[gic_nr]) != 0) 113 + BUG(); 114 + set_irq_chained_handler(irq, gic_handle_cascade_irq); 115 + } 116 + 117 + void __init gic_dist_init(unsigned int gic_nr, void __iomem *base, 118 + unsigned int irq_start) 170 119 { 171 120 unsigned int max_irq, i; 172 121 u32 cpumask = 1 << smp_processor_id(); 173 122 123 + if (gic_nr >= MAX_GIC_NR) 124 + BUG(); 125 + 174 126 cpumask |= cpumask << 8; 175 127 cpumask |= cpumask << 16; 176 128 177 - gic_dist_base = base; 129 + gic_data[gic_nr].dist_base = base; 130 + gic_data[gic_nr].irq_offset = (irq_start - 1) & ~31; 178 131 179 132 writel(0, base + GIC_DIST_CTRL); 180 133 ··· 233 158 /* 234 159 * Setup the Linux IRQ subsystem. 235 160 */ 236 - for (i = 29; i < max_irq; i++) { 161 + for (i = irq_start; i < gic_data[gic_nr].irq_offset + max_irq; i++) { 237 162 set_irq_chip(i, &gic_chip); 163 + set_irq_chip_data(i, &gic_data[gic_nr]); 238 164 set_irq_handler(i, handle_level_irq); 239 165 set_irq_flags(i, IRQF_VALID | IRQF_PROBE); 240 166 } ··· 243 167 writel(1, base + GIC_DIST_CTRL); 244 168 } 245 169 246 - void __cpuinit gic_cpu_init(void __iomem *base) 170 + void __cpuinit gic_cpu_init(unsigned int gic_nr, void __iomem *base) 247 171 { 248 - gic_cpu_base = base; 172 + if (gic_nr >= MAX_GIC_NR) 173 + BUG(); 174 + 175 + gic_data[gic_nr].cpu_base = base; 176 + 249 177 writel(0xf0, base + GIC_CPU_PRIMASK); 250 178 writel(1, base + GIC_CPU_CTRL); 251 179 } ··· 259 179 { 260 180 unsigned long map = *cpus_addr(cpumask); 261 181 262 - writel(map << 16 | irq, gic_dist_base + GIC_DIST_SOFTINT); 182 + /* this always happens on GIC0 */ 183 + writel(map << 16 | irq, gic_data[0].dist_base + GIC_DIST_SOFTINT); 263 184 } 264 185 #endif
+10
arch/arm/mach-realview/Kconfig
··· 16 16 kernel built with this option enabled is not compatible with 17 17 other tiles. 18 18 19 + config REALVIEW_MPCORE_REVB 20 + bool "Support MPcore RevB tile" 21 + depends on REALVIEW_MPCORE 22 + default n 23 + help 24 + Enable support for the MPCore RevB tile on the Realview platform. 25 + Since there are device address differences, a 26 + kernel built with this option enabled is not compatible with 27 + other tiles. 28 + 19 29 endmenu
+1 -1
arch/arm/mach-realview/platsmp.c
··· 52 52 * core (e.g. timer irq), then they will not have been enabled 53 53 * for us: do so 54 54 */ 55 - gic_cpu_init(__io_address(REALVIEW_GIC_CPU_BASE)); 55 + gic_cpu_init(0, __io_address(REALVIEW_GIC_CPU_BASE)); 56 56 57 57 /* 58 58 * let the primary processor know we're out of the
+23 -4
arch/arm/mach-realview/realview_eb.c
··· 57 57 .pfn = __phys_to_pfn(REALVIEW_GIC_DIST_BASE), 58 58 .length = SZ_4K, 59 59 .type = MT_DEVICE, 60 + }, 61 + #ifdef CONFIG_REALVIEW_MPCORE 62 + { 63 + .virtual = IO_ADDRESS(REALVIEW_GIC1_CPU_BASE), 64 + .pfn = __phys_to_pfn(REALVIEW_GIC1_CPU_BASE), 65 + .length = SZ_4K, 66 + .type = MT_DEVICE, 60 67 }, { 68 + .virtual = IO_ADDRESS(REALVIEW_GIC1_DIST_BASE), 69 + .pfn = __phys_to_pfn(REALVIEW_GIC1_DIST_BASE), 70 + .length = SZ_4K, 71 + .type = MT_DEVICE, 72 + }, 73 + #endif 74 + { 61 75 .virtual = IO_ADDRESS(REALVIEW_SCTL_BASE), 62 76 .pfn = __phys_to_pfn(REALVIEW_SCTL_BASE), 63 77 .length = SZ_4K, ··· 152 138 #ifdef CONFIG_REALVIEW_MPCORE 153 139 unsigned int pldctrl; 154 140 writel(0x0000a05f, __io_address(REALVIEW_SYS_LOCK)); 155 - pldctrl = readl(__io_address(REALVIEW_SYS_BASE) + 0xd8); 141 + pldctrl = readl(__io_address(REALVIEW_SYS_BASE) + REALVIEW_MPCORE_SYS_PLD_CTRL1); 156 142 pldctrl |= 0x00800000; /* New irq mode */ 157 - writel(pldctrl, __io_address(REALVIEW_SYS_BASE) + 0xd8); 143 + writel(pldctrl, __io_address(REALVIEW_SYS_BASE) + REALVIEW_MPCORE_SYS_PLD_CTRL1); 158 144 writel(0x00000000, __io_address(REALVIEW_SYS_LOCK)); 159 145 #endif 160 - gic_dist_init(__io_address(REALVIEW_GIC_DIST_BASE)); 161 - gic_cpu_init(__io_address(REALVIEW_GIC_CPU_BASE)); 146 + gic_dist_init(0, __io_address(REALVIEW_GIC_DIST_BASE), 29); 147 + gic_cpu_init(0, __io_address(REALVIEW_GIC_CPU_BASE)); 148 + #ifdef CONFIG_REALVIEW_MPCORE 149 + gic_dist_init(1, __io_address(REALVIEW_GIC1_DIST_BASE), 64); 150 + gic_cpu_init(1, __io_address(REALVIEW_GIC1_CPU_BASE)); 151 + gic_cascade_irq(1, IRQ_EB_IRQ1); 152 + #endif 162 153 } 163 154 164 155 static void __init realview_eb_init(void)
+5 -3
arch/arm/mm/proc-v6.S
··· 14 14 #include <asm/assembler.h> 15 15 #include <asm/asm-offsets.h> 16 16 #include <asm/elf.h> 17 - #include <asm/hardware/arm_scu.h> 18 17 #include <asm/pgtable-hwdef.h> 19 18 #include <asm/pgtable.h> 19 + 20 + #ifdef CONFIG_SMP 21 + #include <asm/hardware/arm_scu.h> 22 + #endif 20 23 21 24 #include "proc-macros.S" 22 25 ··· 190 187 /* Set up the SCU on core 0 only */ 191 188 mrc p15, 0, r0, c0, c0, 5 @ CPU core number 192 189 ands r0, r0, #15 193 - moveq r0, #0x10000000 @ SCU_BASE 194 - orreq r0, r0, #0x00100000 190 + ldreq r0, =SCU_BASE 195 191 ldreq r5, [r0, #SCU_CTRL] 196 192 orreq r5, r5, #1 197 193 streq r5, [r0, #SCU_CTRL]
+1 -1
include/asm-arm/arch-realview/hardware.h
··· 26 26 #include <asm/arch/platform.h> 27 27 28 28 /* macro to get at IO space when running virtually */ 29 - #define IO_ADDRESS(x) (((x) & 0x0fffffff) + (((x) >> 4) & 0x0f000000) + 0xf0000000) 29 + #define IO_ADDRESS(x) ((((x) & 0x0effffff) | (((x) >> 4) & 0x0f000000)) + 0xf0000000) 30 30 #define __io_address(n) __io(IO_ADDRESS(n)) 31 31 32 32 #endif
+4 -1
include/asm-arm/arch-realview/irqs.h
··· 78 78 #define IRQ_PMU_SCU6 (IRQ_GIC_START + INT_PMU_SCU6) 79 79 #define IRQ_PMU_SCU7 (IRQ_GIC_START + INT_PMU_SCU7) 80 80 81 + #define IRQ_EB_IRQ1 (IRQ_GIC_START + INT_EB_IRQ1) 82 + #define IRQ_EB_IRQ2 (IRQ_GIC_START + INT_EB_IRQ2) 83 + 81 84 #define IRQMASK_WDOGINT INTMASK_WDOGINT 82 85 #define IRQMASK_SOFTINT INTMASK_SOFTINT 83 86 #define IRQMASK_COMMRx INTMASK_COMMRx ··· 118 115 #define IRQMASK_ETH INTMASK_ETH 119 116 #define IRQMASK_USB INTMASK_USB 120 117 121 - #define NR_IRQS (IRQ_GIC_START + 64) 118 + #define NR_IRQS (IRQ_GIC_START + 96)
+16
include/asm-arm/arch-realview/platform.h
··· 207 207 #define REALVIEW_GIC_CPU_BASE 0x10040000 /* Generic interrupt controller CPU interface */ 208 208 #define REALVIEW_GIC_DIST_BASE 0x10041000 /* Generic interrupt controller distributor */ 209 209 #else 210 + #ifdef CONFIG_REALVIEW_MPCORE_REVB 210 211 #define REALVIEW_MPCORE_SCU_BASE 0x10100000 /* SCU registers */ 211 212 #define REALVIEW_GIC_CPU_BASE 0x10100100 /* Generic interrupt controller CPU interface */ 212 213 #define REALVIEW_TWD_BASE 0x10100700 213 214 #define REALVIEW_TWD_SIZE 0x00000100 214 215 #define REALVIEW_GIC_DIST_BASE 0x10101000 /* Generic interrupt controller distributor */ 216 + #define REALVIEW_MPCORE_SYS_PLD_CTRL1 0xD8 /* Register offset for MPCore sysctl */ 217 + #else 218 + #define REALVIEW_MPCORE_SCU_BASE 0x1F000000 /* SCU registers */ 219 + #define REALVIEW_GIC_CPU_BASE 0x1F000100 /* Generic interrupt controller CPU interface */ 220 + #define REALVIEW_TWD_BASE 0x1F000700 221 + #define REALVIEW_TWD_SIZE 0x00000100 222 + #define REALVIEW_GIC_DIST_BASE 0x1F001000 /* Generic interrupt controller distributor */ 223 + #define REALVIEW_MPCORE_SYS_PLD_CTRL1 0x74 /* Register offset for MPCore sysctl */ 224 + #endif 225 + #define REALVIEW_GIC1_CPU_BASE 0x10040000 /* Generic interrupt controller CPU interface */ 226 + #define REALVIEW_GIC1_DIST_BASE 0x10041000 /* Generic interrupt controller distributor */ 215 227 #endif 216 228 #define REALVIEW_SMC_BASE 0x10080000 /* SMC */ 217 229 /* Reserved 0x10090000 - 0x100EFFFF */ ··· 318 306 #define INT_USB 29 /* USB controller */ 319 307 #define INT_TSPENINT 30 /* Touchscreen pen */ 320 308 #define INT_TSKPADINT 31 /* Touchscreen keypad */ 309 + 321 310 #else 311 + 312 + #define MAX_GIC_NR 2 313 + 322 314 #define INT_AACI 0 323 315 #define INT_TIMERINT0_1 1 324 316 #define INT_TIMERINT2_3 2
+8
include/asm-arm/arch-realview/scu.h
··· 1 + #ifndef __ASMARM_ARCH_SCU_H 2 + #define __ASMARM_ARCH_SCU_H 3 + 4 + #include <asm/arch/platform.h> 5 + 6 + #define SCU_BASE REALVIEW_MPCORE_SCU_BASE 7 + 8 + #endif
+2
include/asm-arm/hardware/arm_scu.h
··· 1 1 #ifndef ASMARM_HARDWARE_ARM_SCU_H 2 2 #define ASMARM_HARDWARE_ARM_SCU_H 3 3 4 + #include <asm/arch/scu.h> 5 + 4 6 /* 5 7 * SCU registers 6 8 */
+3 -2
include/asm-arm/hardware/gic.h
··· 33 33 #define GIC_DIST_SOFTINT 0xf00 34 34 35 35 #ifndef __ASSEMBLY__ 36 - void gic_dist_init(void __iomem *base); 37 - void gic_cpu_init(void __iomem *base); 36 + void gic_dist_init(unsigned int gic_nr, void __iomem *base, unsigned int irq_start); 37 + void gic_cpu_init(unsigned int gic_nr, void __iomem *base); 38 + void gic_cascade_irq(unsigned int gic_nr, unsigned int irq); 38 39 void gic_raise_softirq(cpumask_t cpumask, unsigned int irq); 39 40 #endif 40 41