0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011 #include <linux/init.h>
0012 #include <linux/interrupt.h>
0013 #include <linux/list.h>
0014 #include <asm/mach/irq.h>
0015 #include <asm/irq.h>
0016 #include <asm/mach-types.h>
0017
0018 #include "hardware.h"
0019
0020 static u32 iop32x_mask;
0021
0022 static void intctl_write(u32 val)
0023 {
0024 asm volatile("mcr p6, 0, %0, c0, c0, 0" : : "r" (val));
0025 }
0026
0027 static void intstr_write(u32 val)
0028 {
0029 asm volatile("mcr p6, 0, %0, c4, c0, 0" : : "r" (val));
0030 }
0031
0032 static u32 iintsrc_read(void)
0033 {
0034 int irq;
0035
0036 asm volatile("mrc p6, 0, %0, c8, c0, 0" : "=r" (irq));
0037
0038 return irq;
0039 }
0040
0041 static void
0042 iop32x_irq_mask(struct irq_data *d)
0043 {
0044 iop32x_mask &= ~(1 << (d->irq - 1));
0045 intctl_write(iop32x_mask);
0046 }
0047
0048 static void
0049 iop32x_irq_unmask(struct irq_data *d)
0050 {
0051 iop32x_mask |= 1 << (d->irq - 1);
0052 intctl_write(iop32x_mask);
0053 }
0054
0055 struct irq_chip ext_chip = {
0056 .name = "IOP32x",
0057 .irq_ack = iop32x_irq_mask,
0058 .irq_mask = iop32x_irq_mask,
0059 .irq_unmask = iop32x_irq_unmask,
0060 };
0061
0062 static void iop_handle_irq(struct pt_regs *regs)
0063 {
0064 u32 mask;
0065
0066 iop_enable_cp6();
0067
0068 do {
0069 mask = iintsrc_read();
0070 if (mask)
0071 generic_handle_irq(fls(mask));
0072 } while (mask);
0073 }
0074
0075 void __init iop32x_init_irq(void)
0076 {
0077 int i;
0078
0079 iop_init_cp6_handler();
0080 set_handle_irq(iop_handle_irq);
0081
0082 intctl_write(0);
0083 intstr_write(0);
0084 if (machine_is_glantank() ||
0085 machine_is_iq80321() ||
0086 machine_is_iq31244() ||
0087 machine_is_n2100() ||
0088 machine_is_em7210())
0089 *IOP3XX_PCIIRSR = 0x0f;
0090
0091 for (i = 1; i < NR_IRQS; i++) {
0092 irq_set_chip_and_handler(i, &ext_chip, handle_level_irq);
0093 irq_clear_status_flags(i, IRQ_NOREQUEST | IRQ_NOPROBE);
0094 }
0095 }