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