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) 2013 Cavium, Inc.
9 #include <linux/interrupt.h>
10 #include <linux/cpumask.h>
11 #include <linux/kernel.h>
12 #include <linux/mutex.h>
16 #define MBOX_BITS_PER_CPU 2
18 static int cpunum_for_cpu(int cpu
)
21 return cpu_logical_map(cpu
);
23 return get_ebase_cpunum();
27 struct core_chip_data
{
28 struct mutex core_irq_mutex
;
34 static struct core_chip_data irq_core_chip_data
[8];
36 static void irq_core_ack(struct irq_data
*data
)
38 struct core_chip_data
*cd
= irq_data_get_irq_chip_data(data
);
39 unsigned int bit
= cd
->bit
;
42 * We don't need to disable IRQs to make these atomic since
43 * they are already disabled earlier in the low level
46 clear_c0_status(0x100 << bit
);
47 /* The two user interrupts must be cleared manually. */
49 clear_c0_cause(0x100 << bit
);
52 static void irq_core_eoi(struct irq_data
*data
)
54 struct core_chip_data
*cd
= irq_data_get_irq_chip_data(data
);
57 * We don't need to disable IRQs to make these atomic since
58 * they are already disabled earlier in the low level
61 set_c0_status(0x100 << cd
->bit
);
64 static void irq_core_set_enable_local(void *arg
)
66 struct irq_data
*data
= arg
;
67 struct core_chip_data
*cd
= irq_data_get_irq_chip_data(data
);
68 unsigned int mask
= 0x100 << cd
->bit
;
71 * Interrupts are already disabled, so these are atomic.
76 clear_c0_status(mask
);
80 static void irq_core_disable(struct irq_data
*data
)
82 struct core_chip_data
*cd
= irq_data_get_irq_chip_data(data
);
83 cd
->desired_en
= false;
86 static void irq_core_enable(struct irq_data
*data
)
88 struct core_chip_data
*cd
= irq_data_get_irq_chip_data(data
);
89 cd
->desired_en
= true;
92 static void irq_core_bus_lock(struct irq_data
*data
)
94 struct core_chip_data
*cd
= irq_data_get_irq_chip_data(data
);
96 mutex_lock(&cd
->core_irq_mutex
);
99 static void irq_core_bus_sync_unlock(struct irq_data
*data
)
101 struct core_chip_data
*cd
= irq_data_get_irq_chip_data(data
);
103 if (cd
->desired_en
!= cd
->current_en
) {
104 on_each_cpu(irq_core_set_enable_local
, data
, 1);
105 cd
->current_en
= cd
->desired_en
;
108 mutex_unlock(&cd
->core_irq_mutex
);
111 static struct irq_chip irq_chip_core
= {
113 .irq_enable
= irq_core_enable
,
114 .irq_disable
= irq_core_disable
,
115 .irq_ack
= irq_core_ack
,
116 .irq_eoi
= irq_core_eoi
,
117 .irq_bus_lock
= irq_core_bus_lock
,
118 .irq_bus_sync_unlock
= irq_core_bus_sync_unlock
,
120 .irq_cpu_online
= irq_core_eoi
,
121 .irq_cpu_offline
= irq_core_ack
,
122 .flags
= IRQCHIP_ONOFFLINE_ENABLED
,
125 static void __init
irq_init_core(void)
129 struct core_chip_data
*cd
;
131 /* Start with a clean slate */
132 clear_c0_status(ST0_IM
);
133 clear_c0_cause(CAUSEF_IP0
| CAUSEF_IP1
);
135 for (i
= 0; i
< ARRAY_SIZE(irq_core_chip_data
); i
++) {
136 cd
= irq_core_chip_data
+ i
;
137 cd
->current_en
= false;
138 cd
->desired_en
= false;
140 mutex_init(&cd
->core_irq_mutex
);
142 irq
= MIPS_CPU_IRQ_BASE
+ i
;
150 irq_set_chip_data(irq
, cd
);
151 irq_set_chip_and_handler(irq
, &irq_chip_core
,
160 static void __iomem
*mips_irq_chip
;
161 #define MIPS_IRQ_CHIP_NUM_BITS 0
162 #define MIPS_IRQ_CHIP_REGS 8
164 static int mips_irq_cpu_stride
;
165 static int mips_irq_chip_reg_raw
;
166 static int mips_irq_chip_reg_src
;
167 static int mips_irq_chip_reg_en
;
168 static int mips_irq_chip_reg_raw_w1s
;
169 static int mips_irq_chip_reg_raw_w1c
;
170 static int mips_irq_chip_reg_en_w1s
;
171 static int mips_irq_chip_reg_en_w1c
;
173 static void irq_pci_enable(struct irq_data
*data
)
175 u32 mask
= 1u << data
->irq
;
177 __raw_writel(mask
, mips_irq_chip
+ mips_irq_chip_reg_en_w1s
);
180 static void irq_pci_disable(struct irq_data
*data
)
182 u32 mask
= 1u << data
->irq
;
184 __raw_writel(mask
, mips_irq_chip
+ mips_irq_chip_reg_en_w1c
);
187 static void irq_pci_ack(struct irq_data
*data
)
191 static void irq_pci_mask(struct irq_data
*data
)
193 u32 mask
= 1u << data
->irq
;
195 __raw_writel(mask
, mips_irq_chip
+ mips_irq_chip_reg_en_w1c
);
198 static void irq_pci_unmask(struct irq_data
*data
)
200 u32 mask
= 1u << data
->irq
;
202 __raw_writel(mask
, mips_irq_chip
+ mips_irq_chip_reg_en_w1s
);
205 static struct irq_chip irq_chip_pci
= {
207 .irq_enable
= irq_pci_enable
,
208 .irq_disable
= irq_pci_disable
,
209 .irq_ack
= irq_pci_ack
,
210 .irq_mask
= irq_pci_mask
,
211 .irq_unmask
= irq_pci_unmask
,
214 static void irq_mbox_all(struct irq_data
*data
, void __iomem
*base
)
217 unsigned int mbox
= data
->irq
- MIPS_IRQ_MBOX0
;
220 WARN_ON(mbox
>= MBOX_BITS_PER_CPU
);
222 for_each_online_cpu(cpu
) {
223 unsigned int cpuid
= cpunum_for_cpu(cpu
);
224 mask
= 1 << (cpuid
* MBOX_BITS_PER_CPU
+ mbox
);
225 __raw_writel(mask
, base
+ (cpuid
* mips_irq_cpu_stride
));
229 static void irq_mbox_enable(struct irq_data
*data
)
231 irq_mbox_all(data
, mips_irq_chip
+ mips_irq_chip_reg_en_w1s
+ sizeof(u32
));
234 static void irq_mbox_disable(struct irq_data
*data
)
236 irq_mbox_all(data
, mips_irq_chip
+ mips_irq_chip_reg_en_w1c
+ sizeof(u32
));
239 static void irq_mbox_ack(struct irq_data
*data
)
242 unsigned int mbox
= data
->irq
- MIPS_IRQ_MBOX0
;
244 WARN_ON(mbox
>= MBOX_BITS_PER_CPU
);
246 mask
= 1 << (get_ebase_cpunum() * MBOX_BITS_PER_CPU
+ mbox
);
247 __raw_writel(mask
, mips_irq_chip
+ mips_irq_chip_reg_raw_w1c
+ sizeof(u32
));
250 void irq_mbox_ipi(int cpu
, unsigned int actions
)
252 unsigned int cpuid
= cpunum_for_cpu(cpu
);
255 WARN_ON(actions
>= (1 << MBOX_BITS_PER_CPU
));
257 mask
= actions
<< (cpuid
* MBOX_BITS_PER_CPU
);
258 __raw_writel(mask
, mips_irq_chip
+ mips_irq_chip_reg_raw_w1s
+ sizeof(u32
));
261 static void irq_mbox_cpu_onoffline(struct irq_data
*data
, void __iomem
*base
)
263 unsigned int mbox
= data
->irq
- MIPS_IRQ_MBOX0
;
264 unsigned int cpuid
= get_ebase_cpunum();
267 WARN_ON(mbox
>= MBOX_BITS_PER_CPU
);
269 mask
= 1 << (cpuid
* MBOX_BITS_PER_CPU
+ mbox
);
270 __raw_writel(mask
, base
+ (cpuid
* mips_irq_cpu_stride
));
274 static void irq_mbox_cpu_online(struct irq_data
*data
)
276 irq_mbox_cpu_onoffline(data
, mips_irq_chip
+ mips_irq_chip_reg_en_w1s
+ sizeof(u32
));
279 static void irq_mbox_cpu_offline(struct irq_data
*data
)
281 irq_mbox_cpu_onoffline(data
, mips_irq_chip
+ mips_irq_chip_reg_en_w1c
+ sizeof(u32
));
284 static struct irq_chip irq_chip_mbox
= {
286 .irq_enable
= irq_mbox_enable
,
287 .irq_disable
= irq_mbox_disable
,
288 .irq_ack
= irq_mbox_ack
,
289 .irq_cpu_online
= irq_mbox_cpu_online
,
290 .irq_cpu_offline
= irq_mbox_cpu_offline
,
291 .flags
= IRQCHIP_ONOFFLINE_ENABLED
,
294 static void __init
irq_pci_init(void)
299 mips_irq_chip
= ioremap(0x1e010000, 4096);
301 num_bits
= __raw_readl(mips_irq_chip
+ MIPS_IRQ_CHIP_NUM_BITS
);
302 stride
= 8 * (1 + ((num_bits
- 1) / 64));
305 pr_notice("mips_irq_chip: %u bits, reg stride: %d\n", num_bits
, stride
);
306 mips_irq_chip_reg_raw
= MIPS_IRQ_CHIP_REGS
+ 0 * stride
;
307 mips_irq_chip_reg_raw_w1s
= MIPS_IRQ_CHIP_REGS
+ 1 * stride
;
308 mips_irq_chip_reg_raw_w1c
= MIPS_IRQ_CHIP_REGS
+ 2 * stride
;
309 mips_irq_chip_reg_src
= MIPS_IRQ_CHIP_REGS
+ 3 * stride
;
310 mips_irq_chip_reg_en
= MIPS_IRQ_CHIP_REGS
+ 4 * stride
;
311 mips_irq_chip_reg_en_w1s
= MIPS_IRQ_CHIP_REGS
+ 5 * stride
;
312 mips_irq_chip_reg_en_w1c
= MIPS_IRQ_CHIP_REGS
+ 6 * stride
;
313 mips_irq_cpu_stride
= stride
* 4;
315 for (i
= 0; i
< 4; i
++)
316 irq_set_chip_and_handler(i
+ MIPS_IRQ_PCIA
, &irq_chip_pci
, handle_level_irq
);
318 for (i
= 0; i
< 2; i
++)
319 irq_set_chip_and_handler(i
+ MIPS_IRQ_MBOX0
, &irq_chip_mbox
, handle_percpu_irq
);
322 set_c0_status(STATUSF_IP2
);
325 static void irq_pci_dispatch(void)
327 unsigned int cpuid
= get_ebase_cpunum();
330 en
= __raw_readl(mips_irq_chip
+ mips_irq_chip_reg_src
+
331 (cpuid
* mips_irq_cpu_stride
));
334 en
= __raw_readl(mips_irq_chip
+ mips_irq_chip_reg_src
+ (cpuid
* mips_irq_cpu_stride
) + sizeof(u32
));
335 en
= (en
>> (2 * cpuid
)) & 3;
338 spurious_interrupt();
340 do_IRQ(__ffs(en
) + MIPS_IRQ_MBOX0
); /* MBOX type */
347 void __init
arch_init_irq(void)
353 asmlinkage
void plat_irq_dispatch(void)
355 unsigned int pending
= read_c0_cause() & read_c0_status() & ST0_IM
;
358 if (unlikely(!pending
)) {
359 spurious_interrupt();
363 ip
= ffs(pending
) - 1 - STATUSB_IP0
;
367 do_IRQ(MIPS_CPU_IRQ_BASE
+ ip
);