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
6 * Copyright (C) 2008 Ralf Baechle (ralf@linux-mips.org)
7 * Copyright (C) 2012 MIPS Technologies, Inc. All rights reserved.
9 #include <linux/bitmap.h>
10 #include <linux/init.h>
11 #include <linux/smp.h>
12 #include <linux/irq.h>
13 #include <linux/clocksource.h>
17 #include <asm/setup.h>
18 #include <asm/traps.h>
19 #include <linux/hardirq.h>
20 #include <asm-generic/bitops/find.h>
22 unsigned int gic_frequency
;
23 unsigned int gic_present
;
24 unsigned long _gic_base
;
25 unsigned int gic_irq_base
;
26 unsigned int gic_irq_flags
[GIC_NUM_INTRS
];
28 /* The index into this array is the vector # of the interrupt. */
29 struct gic_shared_intr_map gic_shared_intr_map
[GIC_NUM_INTRS
];
31 struct gic_pcpu_mask
{
32 DECLARE_BITMAP(pcpu_mask
, GIC_NUM_INTRS
);
35 struct gic_pending_regs
{
36 DECLARE_BITMAP(pending
, GIC_NUM_INTRS
);
39 struct gic_intrmask_regs
{
40 DECLARE_BITMAP(intrmask
, GIC_NUM_INTRS
);
43 static struct gic_pcpu_mask pcpu_masks
[NR_CPUS
];
44 static struct gic_pending_regs pending_regs
[NR_CPUS
];
45 static struct gic_intrmask_regs intrmask_regs
[NR_CPUS
];
47 #if defined(CONFIG_CSRC_GIC) || defined(CONFIG_CEVT_GIC)
48 cycle_t
gic_read_count(void)
50 unsigned int hi
, hi2
, lo
;
53 GICREAD(GIC_REG(SHARED
, GIC_SH_COUNTER_63_32
), hi
);
54 GICREAD(GIC_REG(SHARED
, GIC_SH_COUNTER_31_00
), lo
);
55 GICREAD(GIC_REG(SHARED
, GIC_SH_COUNTER_63_32
), hi2
);
58 return (((cycle_t
) hi
) << 32) + lo
;
61 void gic_write_compare(cycle_t cnt
)
63 GICWRITE(GIC_REG(VPE_LOCAL
, GIC_VPE_COMPARE_HI
),
65 GICWRITE(GIC_REG(VPE_LOCAL
, GIC_VPE_COMPARE_LO
),
66 (int)(cnt
& 0xffffffff));
69 void gic_write_cpu_compare(cycle_t cnt
, int cpu
)
73 local_irq_save(flags
);
75 GICWRITE(GIC_REG(VPE_LOCAL
, GIC_VPE_OTHER_ADDR
), cpu
);
76 GICWRITE(GIC_REG(VPE_OTHER
, GIC_VPE_COMPARE_HI
),
78 GICWRITE(GIC_REG(VPE_OTHER
, GIC_VPE_COMPARE_LO
),
79 (int)(cnt
& 0xffffffff));
81 local_irq_restore(flags
);
84 cycle_t
gic_read_compare(void)
88 GICREAD(GIC_REG(VPE_LOCAL
, GIC_VPE_COMPARE_HI
), hi
);
89 GICREAD(GIC_REG(VPE_LOCAL
, GIC_VPE_COMPARE_LO
), lo
);
91 return (((cycle_t
) hi
) << 32) + lo
;
95 unsigned int gic_get_timer_pending(void)
97 unsigned int vpe_pending
;
99 GICWRITE(GIC_REG(VPE_LOCAL
, GIC_VPE_OTHER_ADDR
), 0);
100 GICREAD(GIC_REG(VPE_OTHER
, GIC_VPE_PEND
), vpe_pending
);
101 return (vpe_pending
& GIC_VPE_PEND_TIMER_MSK
);
104 void gic_bind_eic_interrupt(int irq
, int set
)
106 /* Convert irq vector # to hw int # */
107 irq
-= GIC_PIN_TO_VEC_OFFSET
;
109 /* Set irq to use shadow set */
110 GICWRITE(GIC_REG_ADDR(VPE_LOCAL
, GIC_VPE_EIC_SS(irq
)), set
);
113 void gic_send_ipi(unsigned int intr
)
115 GICWRITE(GIC_REG(SHARED
, GIC_SH_WEDGE
), 0x80000000 | intr
);
118 static void gic_eic_irq_dispatch(void)
120 unsigned int cause
= read_c0_cause();
123 irq
= (cause
& ST0_IM
) >> STATUSB_IP2
;
128 do_IRQ(gic_irq_base
+ irq
);
130 spurious_interrupt();
133 static void __init
vpe_local_setup(unsigned int numvpes
)
135 unsigned long timer_intr
= GIC_INT_TMR
;
136 unsigned long perf_intr
= GIC_INT_PERFCTR
;
137 unsigned int vpe_ctl
;
142 * GIC timer interrupt -> CPU HW Int X (vector X+2) ->
143 * map to pin X+2-1 (since GIC adds 1)
145 timer_intr
+= (GIC_CPU_TO_VEC_OFFSET
- GIC_PIN_TO_VEC_OFFSET
);
147 * GIC perfcnt interrupt -> CPU HW Int X (vector X+2) ->
148 * map to pin X+2-1 (since GIC adds 1)
150 perf_intr
+= (GIC_CPU_TO_VEC_OFFSET
- GIC_PIN_TO_VEC_OFFSET
);
154 * Setup the default performance counter timer interrupts
157 for (i
= 0; i
< numvpes
; i
++) {
158 GICWRITE(GIC_REG(VPE_LOCAL
, GIC_VPE_OTHER_ADDR
), i
);
160 /* Are Interrupts locally routable? */
161 GICREAD(GIC_REG(VPE_OTHER
, GIC_VPE_CTL
), vpe_ctl
);
162 if (vpe_ctl
& GIC_VPE_CTL_TIMER_RTBL_MSK
)
163 GICWRITE(GIC_REG(VPE_OTHER
, GIC_VPE_TIMER_MAP
),
164 GIC_MAP_TO_PIN_MSK
| timer_intr
);
166 set_vi_handler(timer_intr
+ GIC_PIN_TO_VEC_OFFSET
,
167 gic_eic_irq_dispatch
);
168 gic_shared_intr_map
[timer_intr
+ GIC_PIN_TO_VEC_OFFSET
].local_intr_mask
|= GIC_VPE_RMASK_TIMER_MSK
;
171 if (vpe_ctl
& GIC_VPE_CTL_PERFCNT_RTBL_MSK
)
172 GICWRITE(GIC_REG(VPE_OTHER
, GIC_VPE_PERFCTR_MAP
),
173 GIC_MAP_TO_PIN_MSK
| perf_intr
);
175 set_vi_handler(perf_intr
+ GIC_PIN_TO_VEC_OFFSET
, gic_eic_irq_dispatch
);
176 gic_shared_intr_map
[perf_intr
+ GIC_PIN_TO_VEC_OFFSET
].local_intr_mask
|= GIC_VPE_RMASK_PERFCNT_MSK
;
181 unsigned int gic_compare_int(void)
183 unsigned int pending
;
185 GICREAD(GIC_REG(VPE_LOCAL
, GIC_VPE_PEND
), pending
);
186 if (pending
& GIC_VPE_PEND_CMP_MSK
)
192 unsigned int gic_get_int(void)
195 unsigned long *pending
, *intrmask
, *pcpu_mask
;
196 unsigned long *pending_abs
, *intrmask_abs
;
198 /* Get per-cpu bitmaps */
199 pending
= pending_regs
[smp_processor_id()].pending
;
200 intrmask
= intrmask_regs
[smp_processor_id()].intrmask
;
201 pcpu_mask
= pcpu_masks
[smp_processor_id()].pcpu_mask
;
203 pending_abs
= (unsigned long *) GIC_REG_ABS_ADDR(SHARED
,
204 GIC_SH_PEND_31_0_OFS
);
205 intrmask_abs
= (unsigned long *) GIC_REG_ABS_ADDR(SHARED
,
206 GIC_SH_MASK_31_0_OFS
);
208 for (i
= 0; i
< BITS_TO_LONGS(GIC_NUM_INTRS
); i
++) {
209 GICREAD(*pending_abs
, pending
[i
]);
210 GICREAD(*intrmask_abs
, intrmask
[i
]);
215 bitmap_and(pending
, pending
, intrmask
, GIC_NUM_INTRS
);
216 bitmap_and(pending
, pending
, pcpu_mask
, GIC_NUM_INTRS
);
218 return find_first_bit(pending
, GIC_NUM_INTRS
);
221 static void gic_mask_irq(struct irq_data
*d
)
223 GIC_CLR_INTR_MASK(d
->irq
- gic_irq_base
);
226 static void gic_unmask_irq(struct irq_data
*d
)
228 GIC_SET_INTR_MASK(d
->irq
- gic_irq_base
);
232 static DEFINE_SPINLOCK(gic_lock
);
234 static int gic_set_affinity(struct irq_data
*d
, const struct cpumask
*cpumask
,
237 unsigned int irq
= (d
->irq
- gic_irq_base
);
238 cpumask_t tmp
= CPU_MASK_NONE
;
242 cpumask_and(&tmp
, cpumask
, cpu_online_mask
);
246 /* Assumption : cpumask refers to a single CPU */
247 spin_lock_irqsave(&gic_lock
, flags
);
249 /* Re-route this IRQ */
250 GIC_SH_MAP_TO_VPE_SMASK(irq
, first_cpu(tmp
));
252 /* Update the pcpu_masks */
253 for (i
= 0; i
< NR_CPUS
; i
++)
254 clear_bit(irq
, pcpu_masks
[i
].pcpu_mask
);
255 set_bit(irq
, pcpu_masks
[first_cpu(tmp
)].pcpu_mask
);
257 cpumask_copy(d
->affinity
, cpumask
);
258 spin_unlock_irqrestore(&gic_lock
, flags
);
260 return IRQ_SET_MASK_OK_NOCOPY
;
264 static struct irq_chip gic_irq_controller
= {
266 .irq_ack
= gic_irq_ack
,
267 .irq_mask
= gic_mask_irq
,
268 .irq_mask_ack
= gic_mask_irq
,
269 .irq_unmask
= gic_unmask_irq
,
270 .irq_eoi
= gic_finish_irq
,
272 .irq_set_affinity
= gic_set_affinity
,
276 static void __init
gic_setup_intr(unsigned int intr
, unsigned int cpu
,
277 unsigned int pin
, unsigned int polarity
, unsigned int trigtype
,
280 struct gic_shared_intr_map
*map_ptr
;
282 /* Setup Intr to Pin mapping */
283 if (pin
& GIC_MAP_TO_NMI_MSK
) {
284 GICWRITE(GIC_REG_ADDR(SHARED
, GIC_SH_MAP_TO_PIN(intr
)), pin
);
285 /* FIXME: hack to route NMI to all cpu's */
286 for (cpu
= 0; cpu
< NR_CPUS
; cpu
+= 32) {
287 GICWRITE(GIC_REG_ADDR(SHARED
,
288 GIC_SH_MAP_TO_VPE_REG_OFF(intr
, cpu
)),
292 GICWRITE(GIC_REG_ADDR(SHARED
, GIC_SH_MAP_TO_PIN(intr
)),
293 GIC_MAP_TO_PIN_MSK
| pin
);
294 /* Setup Intr to CPU mapping */
295 GIC_SH_MAP_TO_VPE_SMASK(intr
, cpu
);
297 set_vi_handler(pin
+ GIC_PIN_TO_VEC_OFFSET
,
298 gic_eic_irq_dispatch
);
299 map_ptr
= &gic_shared_intr_map
[pin
+ GIC_PIN_TO_VEC_OFFSET
];
300 if (map_ptr
->num_shared_intr
>= GIC_MAX_SHARED_INTR
)
302 map_ptr
->intr_list
[map_ptr
->num_shared_intr
++] = intr
;
306 /* Setup Intr Polarity */
307 GIC_SET_POLARITY(intr
, polarity
);
309 /* Setup Intr Trigger Type */
310 GIC_SET_TRIGGER(intr
, trigtype
);
312 /* Init Intr Masks */
313 GIC_CLR_INTR_MASK(intr
);
315 /* Initialise per-cpu Interrupt software masks */
316 set_bit(intr
, pcpu_masks
[cpu
].pcpu_mask
);
318 if ((flags
& GIC_FLAG_TRANSPARENT
) && (cpu_has_veic
== 0))
319 GIC_SET_INTR_MASK(intr
);
320 if (trigtype
== GIC_TRIG_EDGE
)
321 gic_irq_flags
[intr
] |= GIC_TRIG_EDGE
;
324 static void __init
gic_basic_init(int numintrs
, int numvpes
,
325 struct gic_intr_map
*intrmap
, int mapsize
)
328 unsigned int pin_offset
= 0;
330 board_bind_eic_interrupt
= &gic_bind_eic_interrupt
;
333 for (i
= 0; i
< numintrs
; i
++) {
334 GIC_SET_POLARITY(i
, GIC_POL_POS
);
335 GIC_SET_TRIGGER(i
, GIC_TRIG_LEVEL
);
336 GIC_CLR_INTR_MASK(i
);
337 if (i
< GIC_NUM_INTRS
) {
338 gic_irq_flags
[i
] = 0;
339 gic_shared_intr_map
[i
].num_shared_intr
= 0;
340 gic_shared_intr_map
[i
].local_intr_mask
= 0;
345 * In EIC mode, the HW_INT# is offset by (2-1). Need to subtract
346 * one because the GIC will add one (since 0=no intr).
349 pin_offset
= (GIC_CPU_TO_VEC_OFFSET
- GIC_PIN_TO_VEC_OFFSET
);
351 /* Setup specifics */
352 for (i
= 0; i
< mapsize
; i
++) {
353 cpu
= intrmap
[i
].cpunum
;
354 if (cpu
== GIC_UNUSED
)
358 intrmap
[i
].pin
+ pin_offset
,
364 vpe_local_setup(numvpes
);
367 void __init
gic_init(unsigned long gic_base_addr
,
368 unsigned long gic_addrspace_size
,
369 struct gic_intr_map
*intr_map
, unsigned int intr_map_size
,
370 unsigned int irqbase
)
372 unsigned int gicconfig
;
373 int numvpes
, numintrs
;
375 _gic_base
= (unsigned long) ioremap_nocache(gic_base_addr
,
377 gic_irq_base
= irqbase
;
379 GICREAD(GIC_REG(SHARED
, GIC_SH_CONFIG
), gicconfig
);
380 numintrs
= (gicconfig
& GIC_SH_CONFIG_NUMINTRS_MSK
) >>
381 GIC_SH_CONFIG_NUMINTRS_SHF
;
382 numintrs
= ((numintrs
+ 1) * 8);
384 numvpes
= (gicconfig
& GIC_SH_CONFIG_NUMVPES_MSK
) >>
385 GIC_SH_CONFIG_NUMVPES_SHF
;
386 numvpes
= numvpes
+ 1;
388 gic_basic_init(numintrs
, numvpes
, intr_map
, intr_map_size
);
390 gic_platform_init(numintrs
, &gic_irq_controller
);