]> git.proxmox.com Git - mirror_ubuntu-artful-kernel.git/blame - arch/mips/loongson/loongson-3/irq.c
MIPS: Add numa api support
[mirror_ubuntu-artful-kernel.git] / arch / mips / loongson / loongson-3 / irq.c
CommitLineData
d788bfa9
HC
1#include <loongson.h>
2#include <irq.h>
3#include <linux/interrupt.h>
4#include <linux/module.h>
5
6#include <asm/irq_cpu.h>
7#include <asm/i8259.h>
8#include <asm/mipsregs.h>
9
10unsigned int ht_irq[] = {1, 3, 4, 5, 6, 7, 8, 12, 14, 15};
11
12static void ht_irqdispatch(void)
13{
14 unsigned int i, irq;
15
16 irq = LOONGSON_HT1_INT_VECTOR(0);
17 LOONGSON_HT1_INT_VECTOR(0) = irq; /* Acknowledge the IRQs */
18
19 for (i = 0; i < ARRAY_SIZE(ht_irq); i++) {
20 if (irq & (0x1 << ht_irq[i]))
21 do_IRQ(ht_irq[i]);
22 }
23}
24
25void mach_irq_dispatch(unsigned int pending)
26{
27 if (pending & CAUSEF_IP7)
28 do_IRQ(LOONGSON_TIMER_IRQ);
300459d5
HC
29#if defined(CONFIG_SMP)
30 else if (pending & CAUSEF_IP6)
31 loongson3_ipi_interrupt(NULL);
32#endif
d788bfa9
HC
33 else if (pending & CAUSEF_IP3)
34 ht_irqdispatch();
35 else if (pending & CAUSEF_IP2)
36 do_IRQ(LOONGSON_UART_IRQ);
37 else {
38 pr_err("%s : spurious interrupt\n", __func__);
39 spurious_interrupt();
40 }
41}
42
43static struct irqaction cascade_irqaction = {
44 .handler = no_action,
45 .name = "cascade",
46};
47
48static inline void mask_loongson_irq(struct irq_data *d)
49{
50 clear_c0_status(0x100 << (d->irq - MIPS_CPU_IRQ_BASE));
51 irq_disable_hazard();
300459d5
HC
52
53 /* Workaround: UART IRQ may deliver to any core */
54 if (d->irq == LOONGSON_UART_IRQ) {
55 int cpu = smp_processor_id();
56
57 LOONGSON_INT_ROUTER_INTENCLR = 1 << 10;
58 LOONGSON_INT_ROUTER_LPC = 0x10 + (1<<cpu);
59 }
d788bfa9
HC
60}
61
62static inline void unmask_loongson_irq(struct irq_data *d)
63{
300459d5
HC
64 /* Workaround: UART IRQ may deliver to any core */
65 if (d->irq == LOONGSON_UART_IRQ) {
66 int cpu = smp_processor_id();
67
68 LOONGSON_INT_ROUTER_INTENSET = 1 << 10;
69 LOONGSON_INT_ROUTER_LPC = 0x10 + (1<<cpu);
70 }
71
d788bfa9
HC
72 set_c0_status(0x100 << (d->irq - MIPS_CPU_IRQ_BASE));
73 irq_enable_hazard();
74}
75
76 /* For MIPS IRQs which shared by all cores */
77static struct irq_chip loongson_irq_chip = {
78 .name = "Loongson",
79 .irq_ack = mask_loongson_irq,
80 .irq_mask = mask_loongson_irq,
81 .irq_mask_ack = mask_loongson_irq,
82 .irq_unmask = unmask_loongson_irq,
83 .irq_eoi = unmask_loongson_irq,
84};
85
86void irq_router_init(void)
87{
88 int i;
89
90 /* route LPC int to cpu core0 int 0 */
91 LOONGSON_INT_ROUTER_LPC = LOONGSON_INT_CORE0_INT0;
92 /* route HT1 int0 ~ int7 to cpu core0 INT1*/
93 for (i = 0; i < 8; i++)
94 LOONGSON_INT_ROUTER_HT1(i) = LOONGSON_INT_CORE0_INT1;
95 /* enable HT1 interrupt */
96 LOONGSON_HT1_INTN_EN(0) = 0xffffffff;
97 /* enable router interrupt intenset */
98 LOONGSON_INT_ROUTER_INTENSET =
99 LOONGSON_INT_ROUTER_INTEN | (0xffff << 16) | 0x1 << 10;
100}
101
102void __init mach_init_irq(void)
103{
104 clear_c0_status(ST0_IM | ST0_BEV);
105
106 irq_router_init();
107 mips_cpu_irq_init();
108 init_i8259_irqs();
109 irq_set_chip_and_handler(LOONGSON_UART_IRQ,
110 &loongson_irq_chip, handle_level_irq);
111
112 /* setup HT1 irq */
113 setup_irq(LOONGSON_HT1_IRQ, &cascade_irqaction);
114
115 set_c0_status(STATUSF_IP2 | STATUSF_IP6);
116}
c4a987db
HC
117
118#ifdef CONFIG_HOTPLUG_CPU
119
120void fixup_irqs(void)
121{
122 irq_cpu_offline();
123 clear_c0_status(ST0_IM);
124}
125
126#endif