1
2
3
4
5
6
7
8
9#include <linux/init.h>
10#include <linux/irq.h>
11#include <linux/io.h>
12#include <linux/interrupt.h>
13#include <mach-se/mach/se7206.h>
14
15#define INTSTS0 0x31800000
16#define INTSTS1 0x31800002
17#define INTMSK0 0x31800004
18#define INTMSK1 0x31800006
19#define INTSEL 0x31800008
20
21#define IRQ0_IRQ 64
22#define IRQ1_IRQ 65
23#define IRQ3_IRQ 67
24
25#define INTC_IPR01 0xfffe0818
26#define INTC_ICR1 0xfffe0802
27
28static void disable_se7206_irq(struct irq_data *data)
29{
30 unsigned int irq = data->irq;
31 unsigned short val;
32 unsigned short mask = 0xffff ^ (0x0f << 4 * (3 - (IRQ0_IRQ - irq)));
33 unsigned short msk0,msk1;
34
35
36 val = __raw_readw(INTC_IPR01);
37 val &= mask;
38 __raw_writew(val, INTC_IPR01);
39
40 msk0 = __raw_readw(INTMSK0);
41 msk1 = __raw_readw(INTMSK1);
42
43 switch (irq) {
44 case IRQ0_IRQ:
45 msk0 |= 0x0010;
46 break;
47 case IRQ1_IRQ:
48 msk0 |= 0x000f;
49 break;
50 case IRQ3_IRQ:
51 msk0 |= 0x0f00;
52 msk1 |= 0x00ff;
53 break;
54 }
55 __raw_writew(msk0, INTMSK0);
56 __raw_writew(msk1, INTMSK1);
57}
58
59static void enable_se7206_irq(struct irq_data *data)
60{
61 unsigned int irq = data->irq;
62 unsigned short val;
63 unsigned short value = (0x0001 << 4 * (3 - (IRQ0_IRQ - irq)));
64 unsigned short msk0,msk1;
65
66
67 val = __raw_readw(INTC_IPR01);
68 val |= value;
69 __raw_writew(val, INTC_IPR01);
70
71
72 msk0 = __raw_readw(INTMSK0);
73 msk1 = __raw_readw(INTMSK1);
74
75 switch (irq) {
76 case IRQ0_IRQ:
77 msk0 &= ~0x0010;
78 break;
79 case IRQ1_IRQ:
80 msk0 &= ~0x000f;
81 break;
82 case IRQ3_IRQ:
83 msk0 &= ~0x0f00;
84 msk1 &= ~0x00ff;
85 break;
86 }
87 __raw_writew(msk0, INTMSK0);
88 __raw_writew(msk1, INTMSK1);
89}
90
91static void eoi_se7206_irq(struct irq_data *data)
92{
93 unsigned short sts0,sts1;
94 unsigned int irq = data->irq;
95
96 if (!irqd_irq_disabled(data) && !irqd_irq_inprogress(data))
97 enable_se7206_irq(data);
98
99 sts0 = __raw_readw(INTSTS0);
100 sts1 = __raw_readw(INTSTS1);
101
102 switch (irq) {
103 case IRQ0_IRQ:
104 sts0 &= ~0x0010;
105 break;
106 case IRQ1_IRQ:
107 sts0 &= ~0x000f;
108 break;
109 case IRQ3_IRQ:
110 sts0 &= ~0x0f00;
111 sts1 &= ~0x00ff;
112 break;
113 }
114 __raw_writew(sts0, INTSTS0);
115 __raw_writew(sts1, INTSTS1);
116}
117
118static struct irq_chip se7206_irq_chip __read_mostly = {
119 .name = "SE7206-FPGA",
120 .irq_mask = disable_se7206_irq,
121 .irq_unmask = enable_se7206_irq,
122 .irq_eoi = eoi_se7206_irq,
123};
124
125static void make_se7206_irq(unsigned int irq)
126{
127 disable_irq_nosync(irq);
128 irq_set_chip_and_handler_name(irq, &se7206_irq_chip,
129 handle_level_irq, "level");
130 disable_se7206_irq(irq_get_irq_data(irq));
131}
132
133
134
135
136void __init init_se7206_IRQ(void)
137{
138 make_se7206_irq(IRQ0_IRQ);
139 make_se7206_irq(IRQ1_IRQ);
140 make_se7206_irq(IRQ3_IRQ);
141
142 __raw_writew(__raw_readw(INTC_ICR1) | 0x000b, INTC_ICR1);
143
144
145 __raw_writew(0x0000,INTSTS0);
146 __raw_writew(0x0000,INTSTS1);
147
148
149 __raw_writew(0x0001,INTSEL);
150}
151