1#undef DEBUG
2
3#include <linux/bitmap.h>
4#include <linux/init.h>
5#include <linux/smp.h>
6
7#include <asm/io.h>
8#include <asm/gic.h>
9#include <asm/gcmpregs.h>
10#include <asm/mips-boards/maltaint.h>
11#include <asm/irq.h>
12#include <linux/hardirq.h>
13#include <asm-generic/bitops/find.h>
14
15
16static unsigned long _gic_base;
17static unsigned int _irqbase;
18static unsigned int gic_irq_flags[GIC_NUM_INTRS];
19#define GIC_IRQ_FLAG_EDGE 0x0001
20
21struct gic_pcpu_mask pcpu_masks[NR_CPUS];
22static struct gic_pending_regs pending_regs[NR_CPUS];
23static struct gic_intrmask_regs intrmask_regs[NR_CPUS];
24
25void gic_send_ipi(unsigned int intr)
26{
27 pr_debug("CPU%d: %s status %08x\n", smp_processor_id(), __func__,
28 read_c0_status());
29 GICWRITE(GIC_REG(SHARED, GIC_SH_WEDGE), 0x80000000 | intr);
30}
31
32
33static void __init vpe_local_setup(unsigned int numvpes)
34{
35 int i;
36 unsigned long timer_interrupt = 5, perf_interrupt = 5;
37 unsigned int vpe_ctl;
38
39
40
41
42
43 for (i = 0; i < numvpes; i++) {
44 GICWRITE(GIC_REG(VPE_LOCAL, GIC_VPE_OTHER_ADDR), i);
45
46
47 GICREAD(GIC_REG(VPE_OTHER, GIC_VPE_CTL), vpe_ctl);
48 if (vpe_ctl & GIC_VPE_CTL_TIMER_RTBL_MSK)
49 GICWRITE(GIC_REG(VPE_OTHER, GIC_VPE_TIMER_MAP),
50 GIC_MAP_TO_PIN_MSK | timer_interrupt);
51
52 if (vpe_ctl & GIC_VPE_CTL_PERFCNT_RTBL_MSK)
53 GICWRITE(GIC_REG(VPE_OTHER, GIC_VPE_PERFCTR_MAP),
54 GIC_MAP_TO_PIN_MSK | perf_interrupt);
55 }
56}
57
58unsigned int gic_get_int(void)
59{
60 unsigned int i;
61 unsigned long *pending, *intrmask, *pcpu_mask;
62 unsigned long *pending_abs, *intrmask_abs;
63
64
65 pending = pending_regs[smp_processor_id()].pending;
66 intrmask = intrmask_regs[smp_processor_id()].intrmask;
67 pcpu_mask = pcpu_masks[smp_processor_id()].pcpu_mask;
68
69 pending_abs = (unsigned long *) GIC_REG_ABS_ADDR(SHARED,
70 GIC_SH_PEND_31_0_OFS);
71 intrmask_abs = (unsigned long *) GIC_REG_ABS_ADDR(SHARED,
72 GIC_SH_MASK_31_0_OFS);
73
74 for (i = 0; i < BITS_TO_LONGS(GIC_NUM_INTRS); i++) {
75 GICREAD(*pending_abs, pending[i]);
76 GICREAD(*intrmask_abs, intrmask[i]);
77 pending_abs++;
78 intrmask_abs++;
79 }
80
81 bitmap_and(pending, pending, intrmask, GIC_NUM_INTRS);
82 bitmap_and(pending, pending, pcpu_mask, GIC_NUM_INTRS);
83
84 i = find_first_bit(pending, GIC_NUM_INTRS);
85
86 pr_debug("CPU%d: %s pend=%d\n", smp_processor_id(), __func__, i);
87
88 return i;
89}
90
91static unsigned int gic_irq_startup(unsigned int irq)
92{
93 irq -= _irqbase;
94 pr_debug("CPU%d: %s: irq%d\n", smp_processor_id(), __func__, irq);
95 GIC_SET_INTR_MASK(irq);
96 return 0;
97}
98
99static void gic_irq_ack(unsigned int irq)
100{
101 irq -= _irqbase;
102 pr_debug("CPU%d: %s: irq%d\n", smp_processor_id(), __func__, irq);
103 GIC_CLR_INTR_MASK(irq);
104
105 if (gic_irq_flags[irq] & GIC_IRQ_FLAG_EDGE)
106 GICWRITE(GIC_REG(SHARED, GIC_SH_WEDGE), irq);
107}
108
109static void gic_mask_irq(unsigned int irq)
110{
111 irq -= _irqbase;
112 pr_debug("CPU%d: %s: irq%d\n", smp_processor_id(), __func__, irq);
113 GIC_CLR_INTR_MASK(irq);
114}
115
116static void gic_unmask_irq(unsigned int irq)
117{
118 irq -= _irqbase;
119 pr_debug("CPU%d: %s: irq%d\n", smp_processor_id(), __func__, irq);
120 GIC_SET_INTR_MASK(irq);
121}
122
123#ifdef CONFIG_SMP
124
125static DEFINE_SPINLOCK(gic_lock);
126
127static int gic_set_affinity(unsigned int irq, const struct cpumask *cpumask)
128{
129 cpumask_t tmp = CPU_MASK_NONE;
130 unsigned long flags;
131 int i;
132
133 irq -= _irqbase;
134 pr_debug(KERN_DEBUG "%s(%d) called\n", __func__, irq);
135 cpumask_and(&tmp, cpumask, cpu_online_mask);
136 if (cpus_empty(tmp))
137 return -1;
138
139
140 spin_lock_irqsave(&gic_lock, flags);
141 for (;;) {
142
143 GIC_SH_MAP_TO_VPE_SMASK(irq, first_cpu(tmp));
144
145
146 for (i = 0; i < NR_CPUS; i++)
147 clear_bit(irq, pcpu_masks[i].pcpu_mask);
148 set_bit(irq, pcpu_masks[first_cpu(tmp)].pcpu_mask);
149
150 }
151 cpumask_copy(irq_desc[irq].affinity, cpumask);
152 spin_unlock_irqrestore(&gic_lock, flags);
153
154 return 0;
155}
156#endif
157
158static struct irq_chip gic_irq_controller = {
159 .name = "MIPS GIC",
160 .startup = gic_irq_startup,
161 .ack = gic_irq_ack,
162 .mask = gic_mask_irq,
163 .mask_ack = gic_mask_irq,
164 .unmask = gic_unmask_irq,
165 .eoi = gic_unmask_irq,
166#ifdef CONFIG_SMP
167 .set_affinity = gic_set_affinity,
168#endif
169};
170
171static void __init gic_setup_intr(unsigned int intr, unsigned int cpu,
172 unsigned int pin, unsigned int polarity, unsigned int trigtype,
173 unsigned int flags)
174{
175
176 if (pin & GIC_MAP_TO_NMI_MSK) {
177 GICWRITE(GIC_REG_ADDR(SHARED, GIC_SH_MAP_TO_PIN(intr)), pin);
178
179 for (cpu = 0; cpu < NR_CPUS; cpu += 32) {
180 GICWRITE(GIC_REG_ADDR(SHARED,
181 GIC_SH_MAP_TO_VPE_REG_OFF(intr, cpu)),
182 0xffffffff);
183 }
184 } else {
185 GICWRITE(GIC_REG_ADDR(SHARED, GIC_SH_MAP_TO_PIN(intr)),
186 GIC_MAP_TO_PIN_MSK | pin);
187
188 GIC_SH_MAP_TO_VPE_SMASK(intr, cpu);
189 }
190
191
192 GIC_SET_POLARITY(intr, polarity);
193
194
195 GIC_SET_TRIGGER(intr, trigtype);
196
197
198 GIC_CLR_INTR_MASK(intr);
199
200 if (flags & GIC_FLAG_IPI)
201 set_bit(intr, pcpu_masks[cpu].pcpu_mask);
202 if (flags & GIC_FLAG_TRANSPARENT)
203 GIC_SET_INTR_MASK(intr);
204 if (trigtype == GIC_TRIG_EDGE)
205 gic_irq_flags[intr] |= GIC_IRQ_FLAG_EDGE;
206}
207
208static void __init gic_basic_init(int numintrs, int numvpes,
209 struct gic_intr_map *intrmap, int mapsize)
210{
211 unsigned int i, cpu;
212
213
214 for (i = 0; i < numintrs; i++) {
215 GIC_SET_POLARITY(i, GIC_POL_POS);
216 GIC_SET_TRIGGER(i, GIC_TRIG_LEVEL);
217 GIC_CLR_INTR_MASK(i);
218 if (i < GIC_NUM_INTRS)
219 gic_irq_flags[i] = 0;
220 }
221
222
223 for (i = 0; i < mapsize; i++) {
224 cpu = intrmap[i].cpunum;
225 if (cpu == X)
226 continue;
227 if (cpu == 0 && i != 0 && intrmap[i].flags == 0)
228 continue;
229 gic_setup_intr(i,
230 intrmap[i].cpunum,
231 intrmap[i].pin,
232 intrmap[i].polarity,
233 intrmap[i].trigtype,
234 intrmap[i].flags);
235 }
236
237 vpe_local_setup(numvpes);
238
239 for (i = _irqbase; i < (_irqbase + numintrs); i++)
240 set_irq_chip(i, &gic_irq_controller);
241}
242
243void __init gic_init(unsigned long gic_base_addr,
244 unsigned long gic_addrspace_size,
245 struct gic_intr_map *intr_map, unsigned int intr_map_size,
246 unsigned int irqbase)
247{
248 unsigned int gicconfig;
249 int numvpes, numintrs;
250
251 _gic_base = (unsigned long) ioremap_nocache(gic_base_addr,
252 gic_addrspace_size);
253 _irqbase = irqbase;
254
255 GICREAD(GIC_REG(SHARED, GIC_SH_CONFIG), gicconfig);
256 numintrs = (gicconfig & GIC_SH_CONFIG_NUMINTRS_MSK) >>
257 GIC_SH_CONFIG_NUMINTRS_SHF;
258 numintrs = ((numintrs + 1) * 8);
259
260 numvpes = (gicconfig & GIC_SH_CONFIG_NUMVPES_MSK) >>
261 GIC_SH_CONFIG_NUMVPES_SHF;
262
263 pr_debug("%s called\n", __func__);
264
265 gic_basic_init(numintrs, numvpes, intr_map, intr_map_size);
266}
267