aboutsummaryrefslogtreecommitdiffstats
path: root/arch/mips/kernel
diff options
context:
space:
mode:
authorRalf Baechle <ralf@linux-mips.org>2012-09-28 10:29:55 -0400
committerRalf Baechle <ralf@linux-mips.org>2012-09-28 10:29:55 -0400
commitcb418b34caddc970c1513e515aaa535246a4bba3 (patch)
treeb89720b74d6a85a9407f03bb064248c7235b9dea /arch/mips/kernel
parent77a0d763c461da81c2a3fc9a7e58162a40854a1a (diff)
parentff401e52100dcdc85e572d1ad376d3307b3fe28e (diff)
Merge branch 'ralf-3.7' of git://git.linux-mips.org/pub/scm/sjhill/linux-sjhill into mips-for-linux-next
Diffstat (limited to 'arch/mips/kernel')
-rw-r--r--arch/mips/kernel/cevt-r4k.c5
-rw-r--r--arch/mips/kernel/cpu-probe.c4
-rw-r--r--arch/mips/kernel/irq-gic.c162
3 files changed, 121 insertions, 50 deletions
diff --git a/arch/mips/kernel/cevt-r4k.c b/arch/mips/kernel/cevt-r4k.c
index 51095dd9599d..75323925e537 100644
--- a/arch/mips/kernel/cevt-r4k.c
+++ b/arch/mips/kernel/cevt-r4k.c
@@ -15,6 +15,7 @@
15#include <asm/smtc_ipi.h> 15#include <asm/smtc_ipi.h>
16#include <asm/time.h> 16#include <asm/time.h>
17#include <asm/cevt-r4k.h> 17#include <asm/cevt-r4k.h>
18#include <asm/gic.h>
18 19
19/* 20/*
20 * The SMTC Kernel for the 34K, 1004K, et. al. replaces several 21 * The SMTC Kernel for the 34K, 1004K, et. al. replaces several
@@ -98,6 +99,10 @@ void mips_event_handler(struct clock_event_device *dev)
98 */ 99 */
99static int c0_compare_int_pending(void) 100static int c0_compare_int_pending(void)
100{ 101{
102#ifdef CONFIG_IRQ_GIC
103 if (cpu_has_veic)
104 return gic_get_timer_pending();
105#endif
101 return (read_c0_cause() >> cp0_compare_irq_shift) & (1ul << CAUSEB_IP); 106 return (read_c0_cause() >> cp0_compare_irq_shift) & (1ul << CAUSEB_IP);
102} 107}
103 108
diff --git a/arch/mips/kernel/cpu-probe.c b/arch/mips/kernel/cpu-probe.c
index 0beb75fb3980..bc58bd10a607 100644
--- a/arch/mips/kernel/cpu-probe.c
+++ b/arch/mips/kernel/cpu-probe.c
@@ -861,6 +861,10 @@ static inline void cpu_probe_mips(struct cpuinfo_mips *c, unsigned int cpu)
861 c->cputype = CPU_1004K; 861 c->cputype = CPU_1004K;
862 __cpu_name[cpu] = "MIPS 1004Kc"; 862 __cpu_name[cpu] = "MIPS 1004Kc";
863 break; 863 break;
864 case PRID_IMP_1074K:
865 c->cputype = CPU_74K;
866 __cpu_name[cpu] = "MIPS 1074Kc";
867 break;
864 } 868 }
865 869
866 spram_config(); 870 spram_config();
diff --git a/arch/mips/kernel/irq-gic.c b/arch/mips/kernel/irq-gic.c
index 0c527f652196..485e6a961b31 100644
--- a/arch/mips/kernel/irq-gic.c
+++ b/arch/mips/kernel/irq-gic.c
@@ -1,5 +1,11 @@
1#undef DEBUG 1/*
2 2 * This file is subject to the terms and conditions of the GNU General Public
3 * License. See the file "COPYING" in the main directory of this archive
4 * for more details.
5 *
6 * Copyright (C) 2008 Ralf Baechle (ralf@linux-mips.org)
7 * Copyright (C) 2012 MIPS Technologies, Inc. All rights reserved.
8 */
3#include <linux/bitmap.h> 9#include <linux/bitmap.h>
4#include <linux/init.h> 10#include <linux/init.h>
5#include <linux/smp.h> 11#include <linux/smp.h>
@@ -7,33 +13,80 @@
7 13
8#include <asm/io.h> 14#include <asm/io.h>
9#include <asm/gic.h> 15#include <asm/gic.h>
16#include <asm/setup.h>
17#include <asm/traps.h>
10#include <asm/gcmpregs.h> 18#include <asm/gcmpregs.h>
11#include <linux/hardirq.h> 19#include <linux/hardirq.h>
12#include <asm-generic/bitops/find.h> 20#include <asm-generic/bitops/find.h>
13 21
22unsigned long _gic_base;
23unsigned int gic_irq_base;
24unsigned int gic_irq_flags[GIC_NUM_INTRS];
14 25
15static unsigned long _gic_base; 26/* The index into this array is the vector # of the interrupt. */
16static unsigned int _irqbase; 27struct gic_shared_intr_map gic_shared_intr_map[GIC_NUM_INTRS];
17static unsigned int gic_irq_flags[GIC_NUM_INTRS];
18#define GIC_IRQ_FLAG_EDGE 0x0001
19 28
20struct gic_pcpu_mask pcpu_masks[NR_CPUS]; 29static struct gic_pcpu_mask pcpu_masks[NR_CPUS];
21static struct gic_pending_regs pending_regs[NR_CPUS]; 30static struct gic_pending_regs pending_regs[NR_CPUS];
22static struct gic_intrmask_regs intrmask_regs[NR_CPUS]; 31static struct gic_intrmask_regs intrmask_regs[NR_CPUS];
23 32
33unsigned int gic_get_timer_pending(void)
34{
35 unsigned int vpe_pending;
36
37 GICWRITE(GIC_REG(VPE_LOCAL, GIC_VPE_OTHER_ADDR), 0);
38 GICREAD(GIC_REG(VPE_OTHER, GIC_VPE_PEND), vpe_pending);
39 return (vpe_pending & GIC_VPE_PEND_TIMER_MSK);
40}
41
42void gic_bind_eic_interrupt(int irq, int set)
43{
44 /* Convert irq vector # to hw int # */
45 irq -= GIC_PIN_TO_VEC_OFFSET;
46
47 /* Set irq to use shadow set */
48 GICWRITE(GIC_REG_ADDR(VPE_LOCAL, GIC_VPE_EIC_SS(irq)), set);
49}
50
24void gic_send_ipi(unsigned int intr) 51void gic_send_ipi(unsigned int intr)
25{ 52{
26 pr_debug("CPU%d: %s status %08x\n", smp_processor_id(), __func__,
27 read_c0_status());
28 GICWRITE(GIC_REG(SHARED, GIC_SH_WEDGE), 0x80000000 | intr); 53 GICWRITE(GIC_REG(SHARED, GIC_SH_WEDGE), 0x80000000 | intr);
29} 54}
30 55
31/* This is Malta specific and needs to be exported */ 56static void gic_eic_irq_dispatch(void)
57{
58 unsigned int cause = read_c0_cause();
59 int irq;
60
61 irq = (cause & ST0_IM) >> STATUSB_IP2;
62 if (irq == 0)
63 irq = -1;
64
65 if (irq >= 0)
66 do_IRQ(gic_irq_base + irq);
67 else
68 spurious_interrupt();
69}
70
32static void __init vpe_local_setup(unsigned int numvpes) 71static void __init vpe_local_setup(unsigned int numvpes)
33{ 72{
34 int i; 73 unsigned long timer_intr = GIC_INT_TMR;
35 unsigned long timer_interrupt = 5, perf_interrupt = 5; 74 unsigned long perf_intr = GIC_INT_PERFCTR;
36 unsigned int vpe_ctl; 75 unsigned int vpe_ctl;
76 int i;
77
78 if (cpu_has_veic) {
79 /*
80 * GIC timer interrupt -> CPU HW Int X (vector X+2) ->
81 * map to pin X+2-1 (since GIC adds 1)
82 */
83 timer_intr += (GIC_CPU_TO_VEC_OFFSET - GIC_PIN_TO_VEC_OFFSET);
84 /*
85 * GIC perfcnt interrupt -> CPU HW Int X (vector X+2) ->
86 * map to pin X+2-1 (since GIC adds 1)
87 */
88 perf_intr += (GIC_CPU_TO_VEC_OFFSET - GIC_PIN_TO_VEC_OFFSET);
89 }
37 90
38 /* 91 /*
39 * Setup the default performance counter timer interrupts 92 * Setup the default performance counter timer interrupts
@@ -46,11 +99,20 @@ static void __init vpe_local_setup(unsigned int numvpes)
46 GICREAD(GIC_REG(VPE_OTHER, GIC_VPE_CTL), vpe_ctl); 99 GICREAD(GIC_REG(VPE_OTHER, GIC_VPE_CTL), vpe_ctl);
47 if (vpe_ctl & GIC_VPE_CTL_TIMER_RTBL_MSK) 100 if (vpe_ctl & GIC_VPE_CTL_TIMER_RTBL_MSK)
48 GICWRITE(GIC_REG(VPE_OTHER, GIC_VPE_TIMER_MAP), 101 GICWRITE(GIC_REG(VPE_OTHER, GIC_VPE_TIMER_MAP),
49 GIC_MAP_TO_PIN_MSK | timer_interrupt); 102 GIC_MAP_TO_PIN_MSK | timer_intr);
103 if (cpu_has_veic) {
104 set_vi_handler(timer_intr + GIC_PIN_TO_VEC_OFFSET,
105 gic_eic_irq_dispatch);
106 gic_shared_intr_map[timer_intr + GIC_PIN_TO_VEC_OFFSET].local_intr_mask |= GIC_VPE_RMASK_TIMER_MSK;
107 }
50 108
51 if (vpe_ctl & GIC_VPE_CTL_PERFCNT_RTBL_MSK) 109 if (vpe_ctl & GIC_VPE_CTL_PERFCNT_RTBL_MSK)
52 GICWRITE(GIC_REG(VPE_OTHER, GIC_VPE_PERFCTR_MAP), 110 GICWRITE(GIC_REG(VPE_OTHER, GIC_VPE_PERFCTR_MAP),
53 GIC_MAP_TO_PIN_MSK | perf_interrupt); 111 GIC_MAP_TO_PIN_MSK | perf_intr);
112 if (cpu_has_veic) {
113 set_vi_handler(perf_intr + GIC_PIN_TO_VEC_OFFSET, gic_eic_irq_dispatch);
114 gic_shared_intr_map[perf_intr + GIC_PIN_TO_VEC_OFFSET].local_intr_mask |= GIC_VPE_RMASK_PERFCNT_MSK;
115 }
54 } 116 }
55} 117}
56 118
@@ -80,51 +142,30 @@ unsigned int gic_get_int(void)
80 bitmap_and(pending, pending, intrmask, GIC_NUM_INTRS); 142 bitmap_and(pending, pending, intrmask, GIC_NUM_INTRS);
81 bitmap_and(pending, pending, pcpu_mask, GIC_NUM_INTRS); 143 bitmap_and(pending, pending, pcpu_mask, GIC_NUM_INTRS);
82 144
83 i = find_first_bit(pending, GIC_NUM_INTRS); 145 return find_first_bit(pending, GIC_NUM_INTRS);
84
85 pr_debug("CPU%d: %s pend=%d\n", smp_processor_id(), __func__, i);
86
87 return i;
88}
89
90static void gic_irq_ack(struct irq_data *d)
91{
92 unsigned int irq = d->irq - _irqbase;
93
94 pr_debug("CPU%d: %s: irq%d\n", smp_processor_id(), __func__, irq);
95 GIC_CLR_INTR_MASK(irq);
96
97 if (gic_irq_flags[irq] & GIC_IRQ_FLAG_EDGE)
98 GICWRITE(GIC_REG(SHARED, GIC_SH_WEDGE), irq);
99} 146}
100 147
101static void gic_mask_irq(struct irq_data *d) 148static void gic_mask_irq(struct irq_data *d)
102{ 149{
103 unsigned int irq = d->irq - _irqbase; 150 GIC_CLR_INTR_MASK(d->irq - gic_irq_base);
104 pr_debug("CPU%d: %s: irq%d\n", smp_processor_id(), __func__, irq);
105 GIC_CLR_INTR_MASK(irq);
106} 151}
107 152
108static void gic_unmask_irq(struct irq_data *d) 153static void gic_unmask_irq(struct irq_data *d)
109{ 154{
110 unsigned int irq = d->irq - _irqbase; 155 GIC_SET_INTR_MASK(d->irq - gic_irq_base);
111 pr_debug("CPU%d: %s: irq%d\n", smp_processor_id(), __func__, irq);
112 GIC_SET_INTR_MASK(irq);
113} 156}
114 157
115#ifdef CONFIG_SMP 158#ifdef CONFIG_SMP
116
117static DEFINE_SPINLOCK(gic_lock); 159static DEFINE_SPINLOCK(gic_lock);
118 160
119static int gic_set_affinity(struct irq_data *d, const struct cpumask *cpumask, 161static int gic_set_affinity(struct irq_data *d, const struct cpumask *cpumask,
120 bool force) 162 bool force)
121{ 163{
122 unsigned int irq = d->irq - _irqbase; 164 unsigned int irq = (d->irq - gic_irq_base);
123 cpumask_t tmp = CPU_MASK_NONE; 165 cpumask_t tmp = CPU_MASK_NONE;
124 unsigned long flags; 166 unsigned long flags;
125 int i; 167 int i;
126 168
127 pr_debug("%s(%d) called\n", __func__, irq);
128 cpumask_and(&tmp, cpumask, cpu_online_mask); 169 cpumask_and(&tmp, cpumask, cpu_online_mask);
129 if (cpus_empty(tmp)) 170 if (cpus_empty(tmp))
130 return -1; 171 return -1;
@@ -154,7 +195,7 @@ static struct irq_chip gic_irq_controller = {
154 .irq_mask = gic_mask_irq, 195 .irq_mask = gic_mask_irq,
155 .irq_mask_ack = gic_mask_irq, 196 .irq_mask_ack = gic_mask_irq,
156 .irq_unmask = gic_unmask_irq, 197 .irq_unmask = gic_unmask_irq,
157 .irq_eoi = gic_unmask_irq, 198 .irq_eoi = gic_finish_irq,
158#ifdef CONFIG_SMP 199#ifdef CONFIG_SMP
159 .irq_set_affinity = gic_set_affinity, 200 .irq_set_affinity = gic_set_affinity,
160#endif 201#endif
@@ -164,6 +205,8 @@ static void __init gic_setup_intr(unsigned int intr, unsigned int cpu,
164 unsigned int pin, unsigned int polarity, unsigned int trigtype, 205 unsigned int pin, unsigned int polarity, unsigned int trigtype,
165 unsigned int flags) 206 unsigned int flags)
166{ 207{
208 struct gic_shared_intr_map *map_ptr;
209
167 /* Setup Intr to Pin mapping */ 210 /* Setup Intr to Pin mapping */
168 if (pin & GIC_MAP_TO_NMI_MSK) { 211 if (pin & GIC_MAP_TO_NMI_MSK) {
169 GICWRITE(GIC_REG_ADDR(SHARED, GIC_SH_MAP_TO_PIN(intr)), pin); 212 GICWRITE(GIC_REG_ADDR(SHARED, GIC_SH_MAP_TO_PIN(intr)), pin);
@@ -178,6 +221,14 @@ static void __init gic_setup_intr(unsigned int intr, unsigned int cpu,
178 GIC_MAP_TO_PIN_MSK | pin); 221 GIC_MAP_TO_PIN_MSK | pin);
179 /* Setup Intr to CPU mapping */ 222 /* Setup Intr to CPU mapping */
180 GIC_SH_MAP_TO_VPE_SMASK(intr, cpu); 223 GIC_SH_MAP_TO_VPE_SMASK(intr, cpu);
224 if (cpu_has_veic) {
225 set_vi_handler(pin + GIC_PIN_TO_VEC_OFFSET,
226 gic_eic_irq_dispatch);
227 map_ptr = &gic_shared_intr_map[pin + GIC_PIN_TO_VEC_OFFSET];
228 if (map_ptr->num_shared_intr >= GIC_MAX_SHARED_INTR)
229 BUG();
230 map_ptr->intr_list[map_ptr->num_shared_intr++] = intr;
231 }
181 } 232 }
182 233
183 /* Setup Intr Polarity */ 234 /* Setup Intr Polarity */
@@ -191,26 +242,39 @@ static void __init gic_setup_intr(unsigned int intr, unsigned int cpu,
191 /* Initialise per-cpu Interrupt software masks */ 242 /* Initialise per-cpu Interrupt software masks */
192 if (flags & GIC_FLAG_IPI) 243 if (flags & GIC_FLAG_IPI)
193 set_bit(intr, pcpu_masks[cpu].pcpu_mask); 244 set_bit(intr, pcpu_masks[cpu].pcpu_mask);
194 if (flags & GIC_FLAG_TRANSPARENT) 245 if ((flags & GIC_FLAG_TRANSPARENT) && (cpu_has_veic == 0))
195 GIC_SET_INTR_MASK(intr); 246 GIC_SET_INTR_MASK(intr);
196 if (trigtype == GIC_TRIG_EDGE) 247 if (trigtype == GIC_TRIG_EDGE)
197 gic_irq_flags[intr] |= GIC_IRQ_FLAG_EDGE; 248 gic_irq_flags[intr] |= GIC_TRIG_EDGE;
198} 249}
199 250
200static void __init gic_basic_init(int numintrs, int numvpes, 251static void __init gic_basic_init(int numintrs, int numvpes,
201 struct gic_intr_map *intrmap, int mapsize) 252 struct gic_intr_map *intrmap, int mapsize)
202{ 253{
203 unsigned int i, cpu; 254 unsigned int i, cpu;
255 unsigned int pin_offset = 0;
256
257 board_bind_eic_interrupt = &gic_bind_eic_interrupt;
204 258
205 /* Setup defaults */ 259 /* Setup defaults */
206 for (i = 0; i < numintrs; i++) { 260 for (i = 0; i < numintrs; i++) {
207 GIC_SET_POLARITY(i, GIC_POL_POS); 261 GIC_SET_POLARITY(i, GIC_POL_POS);
208 GIC_SET_TRIGGER(i, GIC_TRIG_LEVEL); 262 GIC_SET_TRIGGER(i, GIC_TRIG_LEVEL);
209 GIC_CLR_INTR_MASK(i); 263 GIC_CLR_INTR_MASK(i);
210 if (i < GIC_NUM_INTRS) 264 if (i < GIC_NUM_INTRS) {
211 gic_irq_flags[i] = 0; 265 gic_irq_flags[i] = 0;
266 gic_shared_intr_map[i].num_shared_intr = 0;
267 gic_shared_intr_map[i].local_intr_mask = 0;
268 }
212 } 269 }
213 270
271 /*
272 * In EIC mode, the HW_INT# is offset by (2-1). Need to subtract
273 * one because the GIC will add one (since 0=no intr).
274 */
275 if (cpu_has_veic)
276 pin_offset = (GIC_CPU_TO_VEC_OFFSET - GIC_PIN_TO_VEC_OFFSET);
277
214 /* Setup specifics */ 278 /* Setup specifics */
215 for (i = 0; i < mapsize; i++) { 279 for (i = 0; i < mapsize; i++) {
216 cpu = intrmap[i].cpunum; 280 cpu = intrmap[i].cpunum;
@@ -220,16 +284,13 @@ static void __init gic_basic_init(int numintrs, int numvpes,
220 continue; 284 continue;
221 gic_setup_intr(i, 285 gic_setup_intr(i,
222 intrmap[i].cpunum, 286 intrmap[i].cpunum,
223 intrmap[i].pin, 287 intrmap[i].pin + pin_offset,
224 intrmap[i].polarity, 288 intrmap[i].polarity,
225 intrmap[i].trigtype, 289 intrmap[i].trigtype,
226 intrmap[i].flags); 290 intrmap[i].flags);
227 } 291 }
228 292
229 vpe_local_setup(numvpes); 293 vpe_local_setup(numvpes);
230
231 for (i = _irqbase; i < (_irqbase + numintrs); i++)
232 irq_set_chip(i, &gic_irq_controller);
233} 294}
234 295
235void __init gic_init(unsigned long gic_base_addr, 296void __init gic_init(unsigned long gic_base_addr,
@@ -242,7 +303,7 @@ void __init gic_init(unsigned long gic_base_addr,
242 303
243 _gic_base = (unsigned long) ioremap_nocache(gic_base_addr, 304 _gic_base = (unsigned long) ioremap_nocache(gic_base_addr,
244 gic_addrspace_size); 305 gic_addrspace_size);
245 _irqbase = irqbase; 306 gic_irq_base = irqbase;
246 307
247 GICREAD(GIC_REG(SHARED, GIC_SH_CONFIG), gicconfig); 308 GICREAD(GIC_REG(SHARED, GIC_SH_CONFIG), gicconfig);
248 numintrs = (gicconfig & GIC_SH_CONFIG_NUMINTRS_MSK) >> 309 numintrs = (gicconfig & GIC_SH_CONFIG_NUMINTRS_MSK) >>
@@ -251,8 +312,9 @@ void __init gic_init(unsigned long gic_base_addr,
251 312
252 numvpes = (gicconfig & GIC_SH_CONFIG_NUMVPES_MSK) >> 313 numvpes = (gicconfig & GIC_SH_CONFIG_NUMVPES_MSK) >>
253 GIC_SH_CONFIG_NUMVPES_SHF; 314 GIC_SH_CONFIG_NUMVPES_SHF;
254 315 numvpes = numvpes + 1;
255 pr_debug("%s called\n", __func__);
256 316
257 gic_basic_init(numintrs, numvpes, intr_map, intr_map_size); 317 gic_basic_init(numintrs, numvpes, intr_map, intr_map_size);
318
319 gic_platform_init(numintrs, &gic_irq_controller);
258} 320}