1
2
3
4
5
6
7
8
9
10
11
12#include <linux/kernel.h>
13#include <linux/types.h>
14#include <linux/mm.h>
15#include <linux/sched.h>
16#include <linux/pci.h>
17#include <linux/init.h>
18
19#include <asm/ptrace.h>
20#include <asm/dma.h>
21#include <asm/irq.h>
22#include <asm/mmu_context.h>
23#include <asm/io.h>
24#include <asm/pgtable.h>
25#include <asm/core_mcpcia.h>
26#include <asm/tlbflush.h>
27
28#include "proto.h"
29#include "irq_impl.h"
30#include "pci_impl.h"
31#include "machvec_impl.h"
32
33
34
35
36
37
38
39
40
41static unsigned int hose_irq_masks[4] = {
42 0xff0000, 0xfe0000, 0xff0000, 0xff0000
43};
44static unsigned int cached_irq_masks[4];
45DEFINE_SPINLOCK(rawhide_irq_lock);
46
47static inline void
48rawhide_update_irq_hw(int hose, int mask)
49{
50 *(vuip)MCPCIA_INT_MASK0(MCPCIA_HOSE2MID(hose)) = mask;
51 mb();
52 *(vuip)MCPCIA_INT_MASK0(MCPCIA_HOSE2MID(hose));
53}
54
55#define hose_exists(h) \
56 (((h) < MCPCIA_MAX_HOSES) && (cached_irq_masks[(h)] != 0))
57
58static inline void
59rawhide_enable_irq(struct irq_data *d)
60{
61 unsigned int mask, hose;
62 unsigned int irq = d->irq;
63
64 irq -= 16;
65 hose = irq / 24;
66 if (!hose_exists(hose))
67 return;
68
69 irq -= hose * 24;
70 mask = 1 << irq;
71
72 spin_lock(&rawhide_irq_lock);
73 mask |= cached_irq_masks[hose];
74 cached_irq_masks[hose] = mask;
75 rawhide_update_irq_hw(hose, mask);
76 spin_unlock(&rawhide_irq_lock);
77}
78
79static void
80rawhide_disable_irq(struct irq_data *d)
81{
82 unsigned int mask, hose;
83 unsigned int irq = d->irq;
84
85 irq -= 16;
86 hose = irq / 24;
87 if (!hose_exists(hose))
88 return;
89
90 irq -= hose * 24;
91 mask = ~(1 << irq) | hose_irq_masks[hose];
92
93 spin_lock(&rawhide_irq_lock);
94 mask &= cached_irq_masks[hose];
95 cached_irq_masks[hose] = mask;
96 rawhide_update_irq_hw(hose, mask);
97 spin_unlock(&rawhide_irq_lock);
98}
99
100static void
101rawhide_mask_and_ack_irq(struct irq_data *d)
102{
103 unsigned int mask, mask1, hose;
104 unsigned int irq = d->irq;
105
106 irq -= 16;
107 hose = irq / 24;
108 if (!hose_exists(hose))
109 return;
110
111 irq -= hose * 24;
112 mask1 = 1 << irq;
113 mask = ~mask1 | hose_irq_masks[hose];
114
115 spin_lock(&rawhide_irq_lock);
116
117 mask &= cached_irq_masks[hose];
118 cached_irq_masks[hose] = mask;
119 rawhide_update_irq_hw(hose, mask);
120
121
122 *(vuip)MCPCIA_INT_REQ(MCPCIA_HOSE2MID(hose)) = mask1;
123
124 spin_unlock(&rawhide_irq_lock);
125}
126
127static struct irq_chip rawhide_irq_type = {
128 .name = "RAWHIDE",
129 .irq_unmask = rawhide_enable_irq,
130 .irq_mask = rawhide_disable_irq,
131 .irq_mask_ack = rawhide_mask_and_ack_irq,
132};
133
134static void
135rawhide_srm_device_interrupt(unsigned long vector)
136{
137 int irq;
138
139 irq = (vector - 0x800) >> 4;
140
141
142
143
144
145
146
147
148
149
150
151 if (irq == 52) {
152
153 irq = 72;
154 }
155
156
157 irq -= ((irq + 16) >> 2) & 0x38;
158
159 handle_irq(irq);
160}
161
162static void __init
163rawhide_init_irq(void)
164{
165 struct pci_controller *hose;
166 long i;
167
168 mcpcia_init_hoses();
169
170
171 for (i = 0; i < MCPCIA_MAX_HOSES; i++) cached_irq_masks[i] = 0;
172
173 for (hose = hose_head; hose; hose = hose->next) {
174 unsigned int h = hose->index;
175 unsigned int mask = hose_irq_masks[h];
176
177 cached_irq_masks[h] = mask;
178 *(vuip)MCPCIA_INT_MASK0(MCPCIA_HOSE2MID(h)) = mask;
179 *(vuip)MCPCIA_INT_MASK1(MCPCIA_HOSE2MID(h)) = 0;
180 }
181
182 for (i = 16; i < 128; ++i) {
183 irq_set_chip_and_handler(i, &rawhide_irq_type,
184 handle_level_irq);
185 irq_set_status_flags(i, IRQ_LEVEL);
186 }
187
188 init_i8259a_irqs();
189 common_init_isa_dma();
190}
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225static int
226rawhide_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
227{
228 static char irq_tab[5][5] = {
229
230 { 16+16, 16+16, 16+16, 16+16, 16+16},
231 { 16+ 0, 16+ 0, 16+ 1, 16+ 2, 16+ 3},
232 { 16+ 4, 16+ 4, 16+ 5, 16+ 6, 16+ 7},
233 { 16+ 8, 16+ 8, 16+ 9, 16+10, 16+11},
234 { 16+12, 16+12, 16+13, 16+14, 16+15}
235 };
236 const long min_idsel = 1, max_idsel = 5, irqs_per_slot = 5;
237
238 struct pci_controller *hose = dev->sysdata;
239 int irq = COMMON_TABLE_LOOKUP;
240 if (irq >= 0)
241 irq += 24 * hose->index;
242 return irq;
243}
244
245
246
247
248
249
250struct alpha_machine_vector rawhide_mv __initmv = {
251 .vector_name = "Rawhide",
252 DO_EV5_MMU,
253 DO_DEFAULT_RTC,
254 DO_MCPCIA_IO,
255 .machine_check = mcpcia_machine_check,
256 .max_isa_dma_address = ALPHA_MAX_ISA_DMA_ADDRESS,
257 .min_io_address = DEFAULT_IO_BASE,
258 .min_mem_address = MCPCIA_DEFAULT_MEM_BASE,
259 .pci_dac_offset = MCPCIA_DAC_OFFSET,
260
261 .nr_irqs = 128,
262 .device_interrupt = rawhide_srm_device_interrupt,
263
264 .init_arch = mcpcia_init_arch,
265 .init_irq = rawhide_init_irq,
266 .init_rtc = common_init_rtc,
267 .init_pci = common_init_pci,
268 .kill_arch = NULL,
269 .pci_map_irq = rawhide_map_irq,
270 .pci_swizzle = common_swizzle,
271};
272ALIAS_MV(rawhide)
273