0001
0002
0003
0004
0005
0006
0007 #include <linux/export.h>
0008 #include <linux/init.h>
0009 #include <linux/interrupt.h>
0010
0011 #include <asm/irq_cpu.h>
0012 #include <asm/i8259.h>
0013 #include <asm/mipsregs.h>
0014
0015 #include <loongson.h>
0016 #include <machine.h>
0017
0018 #define LOONGSON_TIMER_IRQ (MIPS_CPU_IRQ_BASE + 7)
0019 #define LOONGSON_NORTH_BRIDGE_IRQ (MIPS_CPU_IRQ_BASE + 6)
0020 #define LOONGSON_UART_IRQ (MIPS_CPU_IRQ_BASE + 3)
0021 #define LOONGSON_SOUTH_BRIDGE_IRQ (MIPS_CPU_IRQ_BASE + 2)
0022
0023 #define LOONGSON_INT_BIT_INT0 (1 << 11)
0024 #define LOONGSON_INT_BIT_INT1 (1 << 12)
0025
0026
0027
0028
0029
0030 int mach_i8259_irq(void)
0031 {
0032 int irq, isr;
0033
0034 irq = -1;
0035
0036 if ((LOONGSON_INTISR & LOONGSON_INTEN) & LOONGSON_INT_BIT_INT0) {
0037 raw_spin_lock(&i8259A_lock);
0038 isr = inb(PIC_MASTER_CMD) &
0039 ~inb(PIC_MASTER_IMR) & ~(1 << PIC_CASCADE_IR);
0040 if (!isr)
0041 isr = (inb(PIC_SLAVE_CMD) & ~inb(PIC_SLAVE_IMR)) << 8;
0042 irq = ffs(isr) - 1;
0043 if (unlikely(irq == 7)) {
0044
0045
0046
0047
0048
0049
0050
0051 outb(0x0B, PIC_MASTER_ISR);
0052 if (~inb(PIC_MASTER_ISR) & 0x80)
0053 irq = -1;
0054 }
0055 raw_spin_unlock(&i8259A_lock);
0056 }
0057
0058 return irq;
0059 }
0060 EXPORT_SYMBOL(mach_i8259_irq);
0061
0062 static void i8259_irqdispatch(void)
0063 {
0064 int irq;
0065
0066 irq = mach_i8259_irq();
0067 if (irq >= 0)
0068 do_IRQ(irq);
0069 else
0070 spurious_interrupt();
0071 }
0072
0073 void mach_irq_dispatch(unsigned int pending)
0074 {
0075 if (pending & CAUSEF_IP7)
0076 do_IRQ(LOONGSON_TIMER_IRQ);
0077 else if (pending & CAUSEF_IP6) {
0078 bonito_irqdispatch();
0079 } else if (pending & CAUSEF_IP3)
0080 do_IRQ(LOONGSON_UART_IRQ);
0081 else if (pending & CAUSEF_IP2)
0082 i8259_irqdispatch();
0083 else
0084 spurious_interrupt();
0085 }
0086
0087 static irqreturn_t ip6_action(int cpl, void *dev_id)
0088 {
0089 return IRQ_HANDLED;
0090 }
0091
0092 void __init mach_init_irq(void)
0093 {
0094
0095
0096
0097
0098
0099
0100
0101 LOONGSON_INTPOL = LOONGSON_INT_BIT_INT0 | LOONGSON_INT_BIT_INT1;
0102 LOONGSON_INTEDGE &= ~(LOONGSON_INT_BIT_INT0 | LOONGSON_INT_BIT_INT1);
0103
0104
0105 mips_cpu_irq_init();
0106 init_i8259_irqs();
0107 bonito_irq_init();
0108
0109
0110 if (request_irq(LOONGSON_NORTH_BRIDGE_IRQ, ip6_action,
0111 IRQF_SHARED | IRQF_NO_THREAD, "cascade", ip6_action))
0112 pr_err("Failed to register north bridge cascade interrupt\n");
0113
0114 if (request_irq(LOONGSON_SOUTH_BRIDGE_IRQ, no_action,
0115 IRQF_NO_THREAD | IRQF_NO_SUSPEND, "cascade", NULL))
0116 pr_err("Failed to register south bridge cascade interrupt\n");
0117 }