3 #include <linux/bitmap.h>
4 #include <linux/init.h>
10 #include <asm/gcmpregs.h>
11 #include <linux/hardirq.h>
12 #include <asm-generic/bitops/find.h>
15 static unsigned long _gic_base
;
16 static unsigned int _irqbase
;
17 static unsigned int gic_irq_flags
[GIC_NUM_INTRS
];
18 #define GIC_IRQ_FLAG_EDGE 0x0001
20 struct gic_pcpu_mask pcpu_masks
[NR_CPUS
];
21 static struct gic_pending_regs pending_regs
[NR_CPUS
];
22 static struct gic_intrmask_regs intrmask_regs
[NR_CPUS
];
24 void gic_send_ipi(unsigned int intr
)
26 pr_debug("CPU%d: %s status %08x\n", smp_processor_id(), __func__
,
28 GICWRITE(GIC_REG(SHARED
, GIC_SH_WEDGE
), 0x80000000 | intr
);
31 /* This is Malta specific and needs to be exported */
32 static void __init
vpe_local_setup(unsigned int numvpes
)
35 unsigned long timer_interrupt
= 5, perf_interrupt
= 5;
39 * Setup the default performance counter timer interrupts
42 for (i
= 0; i
< numvpes
; i
++) {
43 GICWRITE(GIC_REG(VPE_LOCAL
, GIC_VPE_OTHER_ADDR
), i
);
45 /* Are Interrupts locally routable? */
46 GICREAD(GIC_REG(VPE_OTHER
, GIC_VPE_CTL
), vpe_ctl
);
47 if (vpe_ctl
& GIC_VPE_CTL_TIMER_RTBL_MSK
)
48 GICWRITE(GIC_REG(VPE_OTHER
, GIC_VPE_TIMER_MAP
),
49 GIC_MAP_TO_PIN_MSK
| timer_interrupt
);
51 if (vpe_ctl
& GIC_VPE_CTL_PERFCNT_RTBL_MSK
)
52 GICWRITE(GIC_REG(VPE_OTHER
, GIC_VPE_PERFCTR_MAP
),
53 GIC_MAP_TO_PIN_MSK
| perf_interrupt
);
57 unsigned int gic_get_int(void)
60 unsigned long *pending
, *intrmask
, *pcpu_mask
;
61 unsigned long *pending_abs
, *intrmask_abs
;
63 /* Get per-cpu bitmaps */
64 pending
= pending_regs
[smp_processor_id()].pending
;
65 intrmask
= intrmask_regs
[smp_processor_id()].intrmask
;
66 pcpu_mask
= pcpu_masks
[smp_processor_id()].pcpu_mask
;
68 pending_abs
= (unsigned long *) GIC_REG_ABS_ADDR(SHARED
,
69 GIC_SH_PEND_31_0_OFS
);
70 intrmask_abs
= (unsigned long *) GIC_REG_ABS_ADDR(SHARED
,
71 GIC_SH_MASK_31_0_OFS
);
73 for (i
= 0; i
< BITS_TO_LONGS(GIC_NUM_INTRS
); i
++) {
74 GICREAD(*pending_abs
, pending
[i
]);
75 GICREAD(*intrmask_abs
, intrmask
[i
]);
80 bitmap_and(pending
, pending
, intrmask
, GIC_NUM_INTRS
);
81 bitmap_and(pending
, pending
, pcpu_mask
, GIC_NUM_INTRS
);
83 i
= find_first_bit(pending
, GIC_NUM_INTRS
);
85 pr_debug("CPU%d: %s pend=%d\n", smp_processor_id(), __func__
, i
);
90 static void gic_irq_ack(struct irq_data
*d
)
92 unsigned int irq
= d
->irq
- _irqbase
;
94 pr_debug("CPU%d: %s: irq%d\n", smp_processor_id(), __func__
, irq
);
95 GIC_CLR_INTR_MASK(irq
);
97 if (gic_irq_flags
[irq
] & GIC_IRQ_FLAG_EDGE
)
98 GICWRITE(GIC_REG(SHARED
, GIC_SH_WEDGE
), irq
);
101 static void gic_mask_irq(struct irq_data
*d
)
103 unsigned int irq
= d
->irq
- _irqbase
;
104 pr_debug("CPU%d: %s: irq%d\n", smp_processor_id(), __func__
, irq
);
105 GIC_CLR_INTR_MASK(irq
);
108 static void gic_unmask_irq(struct irq_data
*d
)
110 unsigned int irq
= d
->irq
- _irqbase
;
111 pr_debug("CPU%d: %s: irq%d\n", smp_processor_id(), __func__
, irq
);
112 GIC_SET_INTR_MASK(irq
);
117 static DEFINE_SPINLOCK(gic_lock
);
119 static int gic_set_affinity(struct irq_data
*d
, const struct cpumask
*cpumask
,
122 unsigned int irq
= d
->irq
- _irqbase
;
123 cpumask_t tmp
= CPU_MASK_NONE
;
127 pr_debug("%s(%d) called\n", __func__
, irq
);
128 cpumask_and(&tmp
, cpumask
, cpu_online_mask
);
132 /* Assumption : cpumask refers to a single CPU */
133 spin_lock_irqsave(&gic_lock
, flags
);
135 /* Re-route this IRQ */
136 GIC_SH_MAP_TO_VPE_SMASK(irq
, first_cpu(tmp
));
138 /* Update the pcpu_masks */
139 for (i
= 0; i
< NR_CPUS
; i
++)
140 clear_bit(irq
, pcpu_masks
[i
].pcpu_mask
);
141 set_bit(irq
, pcpu_masks
[first_cpu(tmp
)].pcpu_mask
);
144 cpumask_copy(d
->affinity
, cpumask
);
145 spin_unlock_irqrestore(&gic_lock
, flags
);
147 return IRQ_SET_MASK_OK_NOCOPY
;
151 static struct irq_chip gic_irq_controller
= {
153 .irq_ack
= gic_irq_ack
,
154 .irq_mask
= gic_mask_irq
,
155 .irq_mask_ack
= gic_mask_irq
,
156 .irq_unmask
= gic_unmask_irq
,
157 .irq_eoi
= gic_unmask_irq
,
159 .irq_set_affinity
= gic_set_affinity
,
163 static void __init
gic_setup_intr(unsigned int intr
, unsigned int cpu
,
164 unsigned int pin
, unsigned int polarity
, unsigned int trigtype
,
167 /* Setup Intr to Pin mapping */
168 if (pin
& GIC_MAP_TO_NMI_MSK
) {
169 GICWRITE(GIC_REG_ADDR(SHARED
, GIC_SH_MAP_TO_PIN(intr
)), pin
);
170 /* FIXME: hack to route NMI to all cpu's */
171 for (cpu
= 0; cpu
< NR_CPUS
; cpu
+= 32) {
172 GICWRITE(GIC_REG_ADDR(SHARED
,
173 GIC_SH_MAP_TO_VPE_REG_OFF(intr
, cpu
)),
177 GICWRITE(GIC_REG_ADDR(SHARED
, GIC_SH_MAP_TO_PIN(intr
)),
178 GIC_MAP_TO_PIN_MSK
| pin
);
179 /* Setup Intr to CPU mapping */
180 GIC_SH_MAP_TO_VPE_SMASK(intr
, cpu
);
183 /* Setup Intr Polarity */
184 GIC_SET_POLARITY(intr
, polarity
);
186 /* Setup Intr Trigger Type */
187 GIC_SET_TRIGGER(intr
, trigtype
);
189 /* Init Intr Masks */
190 GIC_CLR_INTR_MASK(intr
);
191 /* Initialise per-cpu Interrupt software masks */
192 if (flags
& GIC_FLAG_IPI
)
193 set_bit(intr
, pcpu_masks
[cpu
].pcpu_mask
);
194 if (flags
& GIC_FLAG_TRANSPARENT
)
195 GIC_SET_INTR_MASK(intr
);
196 if (trigtype
== GIC_TRIG_EDGE
)
197 gic_irq_flags
[intr
] |= GIC_IRQ_FLAG_EDGE
;
200 static void __init
gic_basic_init(int numintrs
, int numvpes
,
201 struct gic_intr_map
*intrmap
, int mapsize
)
206 for (i
= 0; i
< numintrs
; i
++) {
207 GIC_SET_POLARITY(i
, GIC_POL_POS
);
208 GIC_SET_TRIGGER(i
, GIC_TRIG_LEVEL
);
209 GIC_CLR_INTR_MASK(i
);
210 if (i
< GIC_NUM_INTRS
)
211 gic_irq_flags
[i
] = 0;
214 /* Setup specifics */
215 for (i
= 0; i
< mapsize
; i
++) {
216 cpu
= intrmap
[i
].cpunum
;
217 if (cpu
== GIC_UNUSED
)
219 if (cpu
== 0 && i
!= 0 && intrmap
[i
].flags
== 0)
229 vpe_local_setup(numvpes
);
231 for (i
= _irqbase
; i
< (_irqbase
+ numintrs
); i
++)
232 irq_set_chip(i
, &gic_irq_controller
);
235 void __init
gic_init(unsigned long gic_base_addr
,
236 unsigned long gic_addrspace_size
,
237 struct gic_intr_map
*intr_map
, unsigned int intr_map_size
,
238 unsigned int irqbase
)
240 unsigned int gicconfig
;
241 int numvpes
, numintrs
;
243 _gic_base
= (unsigned long) ioremap_nocache(gic_base_addr
,
247 GICREAD(GIC_REG(SHARED
, GIC_SH_CONFIG
), gicconfig
);
248 numintrs
= (gicconfig
& GIC_SH_CONFIG_NUMINTRS_MSK
) >>
249 GIC_SH_CONFIG_NUMINTRS_SHF
;
250 numintrs
= ((numintrs
+ 1) * 8);
252 numvpes
= (gicconfig
& GIC_SH_CONFIG_NUMVPES_MSK
) >>
253 GIC_SH_CONFIG_NUMVPES_SHF
;
255 pr_debug("%s called\n", __func__
);
257 gic_basic_init(numintrs
, numvpes
, intr_map
, intr_map_size
);