1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32#include <linux/init.h>
33#include <linux/types.h>
34#include <linux/interrupt.h>
35#include <linux/irq.h>
36
37#include <asm/io.h>
38#include <asm/mipsregs.h>
39#include <asm/txx9/generic.h>
40#include <asm/txx9/jmr3927.h>
41
42#if JMR3927_IRQ_END > NR_IRQS
43#error JMR3927_IRQ_END > NR_IRQS
44#endif
45
46
47
48
49
50static void mask_irq_ioc(struct irq_data *d)
51{
52
53 unsigned int irq_nr = d->irq - JMR3927_IRQ_IOC;
54 unsigned char imask = jmr3927_ioc_reg_in(JMR3927_IOC_INTM_ADDR);
55 unsigned int bit = 1 << irq_nr;
56 jmr3927_ioc_reg_out(imask & ~bit, JMR3927_IOC_INTM_ADDR);
57
58 (void)jmr3927_ioc_reg_in(JMR3927_IOC_REV_ADDR);
59}
60static void unmask_irq_ioc(struct irq_data *d)
61{
62
63 unsigned int irq_nr = d->irq - JMR3927_IRQ_IOC;
64 unsigned char imask = jmr3927_ioc_reg_in(JMR3927_IOC_INTM_ADDR);
65 unsigned int bit = 1 << irq_nr;
66 jmr3927_ioc_reg_out(imask | bit, JMR3927_IOC_INTM_ADDR);
67
68 (void)jmr3927_ioc_reg_in(JMR3927_IOC_REV_ADDR);
69}
70
71static int jmr3927_ioc_irqroute(void)
72{
73 unsigned char istat = jmr3927_ioc_reg_in(JMR3927_IOC_INTS2_ADDR);
74 int i;
75
76 for (i = 0; i < JMR3927_NR_IRQ_IOC; i++) {
77 if (istat & (1 << i))
78 return JMR3927_IRQ_IOC + i;
79 }
80 return -1;
81}
82
83static int jmr3927_irq_dispatch(int pending)
84{
85 int irq;
86
87 if ((pending & CAUSEF_IP7) == 0)
88 return -1;
89 irq = (pending >> CAUSEB_IP2) & 0x0f;
90 irq += JMR3927_IRQ_IRC;
91 if (irq == JMR3927_IRQ_IOCINT)
92 irq = jmr3927_ioc_irqroute();
93 return irq;
94}
95
96static struct irq_chip jmr3927_irq_ioc = {
97 .name = "jmr3927_ioc",
98 .irq_mask = mask_irq_ioc,
99 .irq_unmask = unmask_irq_ioc,
100};
101
102void __init jmr3927_irq_setup(void)
103{
104 int i;
105
106 txx9_irq_dispatch = jmr3927_irq_dispatch;
107
108
109
110
111
112 jmr3927_ioc_reg_out(0, JMR3927_IOC_INTM_ADDR);
113
114 jmr3927_ioc_reg_out(JMR3927_IOC_INTF_SOFT, JMR3927_IOC_INTP_ADDR);
115
116
117 jmr3927_ioc_reg_out(0, JMR3927_IOC_INTS1_ADDR);
118
119 jmr3927_ioc_reg_out(0, JMR3927_IOC_RESET_ADDR);
120
121 tx3927_irq_init();
122 for (i = JMR3927_IRQ_IOC; i < JMR3927_IRQ_IOC + JMR3927_NR_IRQ_IOC; i++)
123 irq_set_chip_and_handler(i, &jmr3927_irq_ioc,
124 handle_level_irq);
125
126
127 irq_set_chained_handler(JMR3927_IRQ_IOCINT, handle_simple_irq);
128}
129