diff options
author | Martyn Welch <martyn.welch@gefanuc.com> | 2009-08-27 12:00:40 -0400 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@suse.de> | 2009-09-15 15:02:11 -0400 |
commit | 3d0f8bc7517718a4846de6f538ad67a4f7f83239 (patch) | |
tree | 5e3b48acbb646729a0d7972c0d59bb711ba560c5 /drivers/staging/vme/bridges/vme_ca91cx42.c | |
parent | 42fb503122d8cd428b5b1078bd473847ca2b206c (diff) |
Staging: vme: Update support for the Universe II VME driver
This patch starts the reworking of the vme_ca91cx42.c for the VME core. The
driver seems to have only supported the Universe II for a long time, I have no
hardware to check to see if it would work on the Universe I.
This patch is compile tested with minimal run-time testing. It enables basic
support for slave and master windows and interrupts. The master windows have
undergone basic run testing.
Signed-off-by: Martyn Welch <martyn.welch@gefanuc.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Diffstat (limited to 'drivers/staging/vme/bridges/vme_ca91cx42.c')
-rw-r--r-- | drivers/staging/vme/bridges/vme_ca91cx42.c | 2646 |
1 files changed, 1384 insertions, 1262 deletions
diff --git a/drivers/staging/vme/bridges/vme_ca91cx42.c b/drivers/staging/vme/bridges/vme_ca91cx42.c index 37487d6df51..3d2a84c4582 100644 --- a/drivers/staging/vme/bridges/vme_ca91cx42.c +++ b/drivers/staging/vme/bridges/vme_ca91cx42.c | |||
@@ -20,7 +20,6 @@ | |||
20 | #include <linux/mm.h> | 20 | #include <linux/mm.h> |
21 | #include <linux/types.h> | 21 | #include <linux/types.h> |
22 | #include <linux/errno.h> | 22 | #include <linux/errno.h> |
23 | #include <linux/proc_fs.h> | ||
24 | #include <linux/pci.h> | 23 | #include <linux/pci.h> |
25 | #include <linux/dma-mapping.h> | 24 | #include <linux/dma-mapping.h> |
26 | #include <linux/poll.h> | 25 | #include <linux/poll.h> |
@@ -34,1212 +33,1333 @@ | |||
34 | #include "../vme_bridge.h" | 33 | #include "../vme_bridge.h" |
35 | #include "vme_ca91cx42.h" | 34 | #include "vme_ca91cx42.h" |
36 | 35 | ||
37 | extern struct vmeSharedData *vmechip_interboard_data; | 36 | static int __init ca91cx42_init(void); |
38 | extern dma_addr_t vmechip_interboard_datap; | 37 | static int ca91cx42_probe(struct pci_dev *, const struct pci_device_id *); |
39 | extern const int vmechip_revision; | 38 | static void ca91cx42_remove(struct pci_dev *); |
40 | extern const int vmechip_devid; | 39 | static void __exit ca91cx42_exit(void); |
41 | extern const int vmechip_irq; | ||
42 | extern int vmechip_irq_overhead_ticks; | ||
43 | extern char *vmechip_baseaddr; | ||
44 | extern const int vme_slotnum; | ||
45 | extern int vme_syscon; | ||
46 | extern unsigned int out_image_va[]; | ||
47 | extern unsigned int vme_irqlog[8][0x100]; | ||
48 | |||
49 | static int outCTL[] = { LSI0_CTL, LSI1_CTL, LSI2_CTL, LSI3_CTL, | ||
50 | LSI4_CTL, LSI5_CTL, LSI6_CTL, LSI7_CTL | ||
51 | }; | ||
52 | 40 | ||
53 | static int outBS[] = { LSI0_BS, LSI1_BS, LSI2_BS, LSI3_BS, | 41 | struct vme_bridge *ca91cx42_bridge; |
54 | LSI4_BS, LSI5_BS, LSI6_BS, LSI7_BS | 42 | wait_queue_head_t dma_queue; |
55 | }; | 43 | wait_queue_head_t iack_queue; |
44 | wait_queue_head_t lm_queue; | ||
45 | wait_queue_head_t mbox_queue; | ||
56 | 46 | ||
57 | static int outBD[] = { LSI0_BD, LSI1_BD, LSI2_BD, LSI3_BD, | 47 | void (*lm_callback[4])(int); /* Called in interrupt handler, be careful! */ |
58 | LSI4_BD, LSI5_BD, LSI6_BD, LSI7_BD | 48 | void *crcsr_kernel; |
59 | }; | 49 | dma_addr_t crcsr_bus; |
60 | 50 | ||
61 | static int outTO[] = { LSI0_TO, LSI1_TO, LSI2_TO, LSI3_TO, | 51 | struct mutex vme_rmw; /* Only one RMW cycle at a time */ |
62 | LSI4_TO, LSI5_TO, LSI6_TO, LSI7_TO | 52 | struct mutex vme_int; /* |
63 | }; | 53 | * Only one VME interrupt can be |
54 | * generated at a time, provide locking | ||
55 | */ | ||
56 | struct mutex vme_irq; /* Locking for VME irq callback configuration */ | ||
64 | 57 | ||
65 | static int inCTL[] = { VSI0_CTL, VSI1_CTL, VSI2_CTL, VSI3_CTL, | ||
66 | VSI4_CTL, VSI5_CTL, VSI6_CTL, VSI7_CTL | ||
67 | }; | ||
68 | 58 | ||
69 | static int inBS[] = { VSI0_BS, VSI1_BS, VSI2_BS, VSI3_BS, | ||
70 | VSI4_BS, VSI5_BS, VSI6_BS, VSI7_BS | ||
71 | }; | ||
72 | 59 | ||
73 | static int inBD[] = { VSI0_BD, VSI1_BD, VSI2_BD, VSI3_BD, | 60 | static char driver_name[] = "vme_ca91cx42"; |
74 | VSI4_BD, VSI5_BD, VSI6_BD, VSI7_BD | ||
75 | }; | ||
76 | 61 | ||
77 | static int inTO[] = { VSI0_TO, VSI1_TO, VSI2_TO, VSI3_TO, | 62 | static struct pci_device_id ca91cx42_ids[] = { |
78 | VSI4_TO, VSI5_TO, VSI6_TO, VSI7_TO | 63 | { PCI_DEVICE(PCI_VENDOR_ID_TUNDRA, PCI_DEVICE_ID_TUNDRA_CA91C142) }, |
79 | }; | 64 | { }, |
80 | static int vmevec[7] = { V1_STATID, V2_STATID, V3_STATID, V4_STATID, | ||
81 | V5_STATID, V6_STATID, V7_STATID | ||
82 | }; | 65 | }; |
83 | 66 | ||
84 | struct interrupt_counters { | 67 | static struct pci_driver ca91cx42_driver = { |
85 | unsigned int acfail; | 68 | .name = driver_name, |
86 | unsigned int sysfail; | 69 | .id_table = ca91cx42_ids, |
87 | unsigned int sw_int; | 70 | .probe = ca91cx42_probe, |
88 | unsigned int sw_iack; | 71 | .remove = ca91cx42_remove, |
89 | unsigned int verr; | ||
90 | unsigned int lerr; | ||
91 | unsigned int lm; | ||
92 | unsigned int mbox; | ||
93 | unsigned int dma; | ||
94 | unsigned int virq[7]; | ||
95 | unsigned int vown; | ||
96 | }; | 72 | }; |
97 | 73 | ||
98 | extern wait_queue_head_t dma_queue[]; | 74 | static u32 ca91cx42_DMA_irqhandler(void) |
99 | extern wait_queue_head_t lm_queue; | ||
100 | extern wait_queue_head_t mbox_queue; | ||
101 | |||
102 | extern int tb_speed; | ||
103 | |||
104 | unsigned int uni_irq_time; | ||
105 | unsigned int uni_dma_irq_time; | ||
106 | unsigned int uni_lm_event; | ||
107 | |||
108 | static spinlock_t lm_lock = SPIN_LOCK_UNLOCKED; | ||
109 | |||
110 | static struct interrupt_counters Interrupt_counters = { 0, 0, | ||
111 | 0, 0, 0, 0, | ||
112 | 0, 0, 0, | ||
113 | {0, 0, 0, 0, 0, 0, 0}, | ||
114 | 0 | ||
115 | }; | ||
116 | |||
117 | #define read_register(offset) readl(vmechip_baseaddr + offset) | ||
118 | #define write_register(value,offset) writel(value, vmechip_baseaddr + offset) | ||
119 | #define read_register_word(offset) readw(vmechip_baseaddr + offset) | ||
120 | #define write_register_word(value,offset) writew(value, vmechip_baseaddr + offset) | ||
121 | |||
122 | int uni_procinfo(char *buf) | ||
123 | { | 75 | { |
124 | char *p; | 76 | wake_up(&dma_queue); |
125 | 77 | ||
126 | p = buf; | 78 | return CA91CX42_LINT_DMA; |
79 | } | ||
127 | 80 | ||
128 | p += sprintf(p, "\n"); | 81 | static u32 ca91cx42_LM_irqhandler(u32 stat) |
129 | { | 82 | { |
130 | unsigned long misc_ctl; | 83 | int i; |
84 | u32 serviced = 0; | ||
131 | 85 | ||
132 | misc_ctl = read_register(MISC_CTL); | 86 | for (i = 0; i < 4; i++) { |
133 | p += sprintf(p, "MISC_CTL:\t\t\t0x%08lx\n", misc_ctl); | 87 | if (stat & CA91CX42_LINT_LM[i]) { |
134 | p += sprintf(p, "VME Bus Time Out:\t\t"); | 88 | /* We only enable interrupts if the callback is set */ |
135 | switch ((misc_ctl & UNIV_BM_MISC_CTL_VBTO) >> | 89 | lm_callback[i](i); |
136 | UNIV_OF_MISC_CTL_VBTO) { | 90 | serviced |= CA91CX42_LINT_LM[i]; |
137 | case 0x0: | ||
138 | p += sprintf(p, "Disabled\n"); | ||
139 | break; | ||
140 | case 0x1: | ||
141 | p += sprintf(p, "16 us\n"); | ||
142 | break; | ||
143 | case 0x2: | ||
144 | p += sprintf(p, "32 us\n"); | ||
145 | break; | ||
146 | case 0x3: | ||
147 | p += sprintf(p, "64 us\n"); | ||
148 | break; | ||
149 | case 0x4: | ||
150 | p += sprintf(p, "128 us\n"); | ||
151 | break; | ||
152 | case 0x5: | ||
153 | p += sprintf(p, "256 us\n"); | ||
154 | break; | ||
155 | case 0x6: | ||
156 | p += sprintf(p, "512 us\n"); | ||
157 | break; | ||
158 | case 0x7: | ||
159 | p += sprintf(p, "1024 us\n"); | ||
160 | break; | ||
161 | default: | ||
162 | p += sprintf(p, "Reserved Value, Undefined\n"); | ||
163 | } | ||
164 | p += sprintf(p, "VME Arbitration Time Out:\t"); | ||
165 | switch ((misc_ctl & UNIV_BM_MISC_CTL_VARBTO) >> | ||
166 | UNIV_OF_MISC_CTL_VARBTO) { | ||
167 | case 0x0: | ||
168 | p += sprintf(p, "Disabled"); | ||
169 | break; | ||
170 | case 0x1: | ||
171 | p += sprintf(p, "16 us"); | ||
172 | break; | ||
173 | case 0x2: | ||
174 | p += sprintf(p, "256 us"); | ||
175 | break; | ||
176 | default: | ||
177 | p += sprintf(p, "Reserved Value, Undefined"); | ||
178 | } | ||
179 | if (misc_ctl & UNIV_BM_MISC_CTL_VARB) | ||
180 | p += sprintf(p, ", Priority Arbitration\n"); | ||
181 | else | ||
182 | p += sprintf(p, ", Round Robin Arbitration\n"); | ||
183 | p += sprintf(p, "\n"); | ||
184 | } | ||
185 | |||
186 | { | ||
187 | unsigned int lmisc; | ||
188 | unsigned int crt; | ||
189 | unsigned int cwt; | ||
190 | |||
191 | lmisc = read_register(LMISC); | ||
192 | p += sprintf(p, "LMISC:\t\t\t\t0x%08x\n", lmisc); | ||
193 | crt = (lmisc & UNIV_BM_LMISC_CRT) >> UNIV_OF_LMISC_CRT; | ||
194 | cwt = (lmisc & UNIV_BM_LMISC_CWT) >> UNIV_OF_LMISC_CWT; | ||
195 | p += sprintf(p, "Coupled Request Timer:\t\t"); | ||
196 | switch (crt) { | ||
197 | case 0x0: | ||
198 | p += sprintf(p, "Disabled\n"); | ||
199 | break; | ||
200 | case 0x1: | ||
201 | p += sprintf(p, "128 us\n"); | ||
202 | break; | ||
203 | case 0x2: | ||
204 | p += sprintf(p, "256 us\n"); | ||
205 | break; | ||
206 | case 0x3: | ||
207 | p += sprintf(p, "512 us\n"); | ||
208 | break; | ||
209 | case 0x4: | ||
210 | p += sprintf(p, "1024 us\n"); | ||
211 | break; | ||
212 | case 0x5: | ||
213 | p += sprintf(p, "2048 us\n"); | ||
214 | break; | ||
215 | case 0x6: | ||
216 | p += sprintf(p, "4096 us\n"); | ||
217 | break; | ||
218 | default: | ||
219 | p += sprintf(p, "Reserved\n"); | ||
220 | } | ||
221 | p += sprintf(p, "Coupled Window Timer:\t\t"); | ||
222 | switch (cwt) { | ||
223 | case 0x0: | ||
224 | p += sprintf(p, "Disabled\n"); | ||
225 | break; | ||
226 | case 0x1: | ||
227 | p += sprintf(p, "16 PCI Clocks\n"); | ||
228 | break; | ||
229 | case 0x2: | ||
230 | p += sprintf(p, "32 PCI Clocks\n"); | ||
231 | break; | ||
232 | case 0x3: | ||
233 | p += sprintf(p, "64 PCI Clocks\n"); | ||
234 | break; | ||
235 | case 0x4: | ||
236 | p += sprintf(p, "128 PCI Clocks\n"); | ||
237 | break; | ||
238 | case 0x5: | ||
239 | p += sprintf(p, "256 PCI Clocks\n"); | ||
240 | break; | ||
241 | case 0x6: | ||
242 | p += sprintf(p, "512 PCI Clocks\n"); | ||
243 | break; | ||
244 | default: | ||
245 | p += sprintf(p, "Reserved\n"); | ||
246 | } | 91 | } |
247 | p += sprintf(p, "\n"); | ||
248 | } | 92 | } |
249 | { | ||
250 | unsigned int mast_ctl; | ||
251 | 93 | ||
252 | mast_ctl = read_register(MAST_CTL); | 94 | return serviced; |
253 | p += sprintf(p, "MAST_CTL:\t\t\t0x%08x\n", mast_ctl); | 95 | } |
254 | { | ||
255 | int retries; | ||
256 | 96 | ||
257 | retries = ((mast_ctl & UNIV_BM_MAST_CTL_MAXRTRY) | 97 | /* XXX This needs to be split into 4 queues */ |
258 | >> UNIV_OF_MAST_CTL_MAXRTRY) * 64; | 98 | static u32 ca91cx42_MB_irqhandler(int mbox_mask) |
259 | p += sprintf(p, "Max PCI Master Retries:\t\t"); | 99 | { |
260 | if (retries) | 100 | wake_up(&mbox_queue); |
261 | p += sprintf(p, "%d\n", retries); | ||
262 | else | ||
263 | p += sprintf(p, "Forever\n"); | ||
264 | } | ||
265 | 101 | ||
266 | p += sprintf(p, "Posted Write Transfer Count:\t"); | 102 | return CA91CX42_LINT_MBOX; |
267 | switch ((mast_ctl & UNIV_BM_MAST_CTL_PWON) >> | 103 | } |
268 | UNIV_OF_MAST_CTL_PWON) { | ||
269 | case 0x0: | ||
270 | p += sprintf(p, "128 Bytes\n"); | ||
271 | break; | ||
272 | case 0x1: | ||
273 | p += sprintf(p, "256 Bytes\n"); | ||
274 | break; | ||
275 | case 0x2: | ||
276 | p += sprintf(p, "512 Bytes\n"); | ||
277 | break; | ||
278 | case 0x3: | ||
279 | p += sprintf(p, "1024 Bytes\n"); | ||
280 | break; | ||
281 | case 0x4: | ||
282 | p += sprintf(p, "2048 Bytes\n"); | ||
283 | break; | ||
284 | case 0x5: | ||
285 | p += sprintf(p, "4096 Bytes\n"); | ||
286 | break; | ||
287 | default: | ||
288 | p += sprintf(p, "Undefined\n"); | ||
289 | } | ||
290 | 104 | ||
291 | p += sprintf(p, "VMEbus Request Level:\t\t"); | 105 | static u32 ca91cx42_IACK_irqhandler(void) |
292 | switch ((mast_ctl & UNIV_BM_MAST_CTL_VRL) >> | 106 | { |
293 | UNIV_OF_MAST_CTL_VRL) { | 107 | wake_up(&iack_queue); |
294 | case 0x0: | ||
295 | p += sprintf(p, "Level 0\n"); | ||
296 | case 0x1: | ||
297 | p += sprintf(p, "Level 1\n"); | ||
298 | case 0x2: | ||
299 | p += sprintf(p, "Level 2\n"); | ||
300 | case 0x3: | ||
301 | p += sprintf(p, "Level 3\n"); | ||
302 | } | ||
303 | p += sprintf(p, "VMEbus Request Mode:\t\t"); | ||
304 | if (mast_ctl & UNIV_BM_MAST_CTL_VRM) | ||
305 | p += sprintf(p, "Fair Request Mode\n"); | ||
306 | else | ||
307 | p += sprintf(p, "Demand Request Mode\n"); | ||
308 | p += sprintf(p, "VMEbus Release Mode:\t\t"); | ||
309 | if (mast_ctl & UNIV_BM_MAST_CTL_VREL) | ||
310 | p += sprintf(p, "Release on Request\n"); | ||
311 | else | ||
312 | p += sprintf(p, "Release when Done\n"); | ||
313 | p += sprintf(p, "VMEbus Ownership Bit:\t\t"); | ||
314 | if (mast_ctl & UNIV_BM_MAST_CTL_VOWN) | ||
315 | p += sprintf(p, "Acquire and hold VMEbus\n"); | ||
316 | else | ||
317 | p += sprintf(p, "Release VMEbus\n"); | ||
318 | p += sprintf(p, "VMEbus Ownership Bit Ack:\t"); | ||
319 | if (mast_ctl & UNIV_BM_MAST_CTL_VOWN_ACK) | ||
320 | p += sprintf(p, "Owning VMEbus\n"); | ||
321 | else | ||
322 | p += sprintf(p, "Not Owning VMEbus\n"); | ||
323 | p += sprintf(p, "\n"); | ||
324 | } | ||
325 | { | ||
326 | unsigned int misc_stat; | ||
327 | |||
328 | misc_stat = read_register(MISC_STAT); | ||
329 | p += sprintf(p, "MISC_STAT:\t\t\t0x%08x\n", misc_stat); | ||
330 | p += sprintf(p, "Universe BBSY:\t\t\t"); | ||
331 | if (misc_stat & UNIV_BM_MISC_STAT_MYBBSY) | ||
332 | p += sprintf(p, "Negated\n"); | ||
333 | else | ||
334 | p += sprintf(p, "Asserted\n"); | ||
335 | p += sprintf(p, "Transmit FIFO:\t\t\t"); | ||
336 | if (misc_stat & UNIV_BM_MISC_STAT_TXFE) | ||
337 | p += sprintf(p, "Empty\n"); | ||
338 | else | ||
339 | p += sprintf(p, "Not empty\n"); | ||
340 | p += sprintf(p, "Receive FIFO:\t\t\t"); | ||
341 | if (misc_stat & UNIV_BM_MISC_STAT_RXFE) | ||
342 | p += sprintf(p, "Empty\n"); | ||
343 | else | ||
344 | p += sprintf(p, "Not Empty\n"); | ||
345 | p += sprintf(p, "\n"); | ||
346 | } | ||
347 | |||
348 | p += sprintf(p, "Latency Timer:\t\t\t%02d Clocks\n\n", | ||
349 | (read_register(UNIV_PCI_MISC0) & | ||
350 | UNIV_BM_PCI_MISC0_LTIMER) >> UNIV_OF_PCI_MISC0_LTIMER); | ||
351 | |||
352 | { | ||
353 | unsigned int lint_en; | ||
354 | unsigned int lint_stat; | ||
355 | |||
356 | lint_en = read_register(LINT_EN); | ||
357 | lint_stat = read_register(LINT_STAT); | ||
358 | |||
359 | #define REPORT_IRQ(name,field) \ | ||
360 | p += sprintf(p, (lint_en & UNIV_BM_LINT_##name) ? "Enabled" : "Masked"); \ | ||
361 | p += sprintf(p, ", triggered %d times", Interrupt_counters.field); \ | ||
362 | p += sprintf(p, (lint_stat & UNIV_BM_LINT_##name) ? ", irq now active\n" : "\n"); | ||
363 | p += sprintf(p, "ACFAIL Interrupt:\t\t"); | ||
364 | REPORT_IRQ(ACFAIL, acfail); | ||
365 | p += sprintf(p, "SYSFAIL Interrupt:\t\t"); | ||
366 | REPORT_IRQ(SYSFAIL, sysfail); | ||
367 | p += sprintf(p, "SW_INT Interrupt:\t\t"); | ||
368 | REPORT_IRQ(SW_INT, sw_int); | ||
369 | p += sprintf(p, "SW_IACK Interrupt:\t\t"); | ||
370 | REPORT_IRQ(SW_IACK, sw_iack); | ||
371 | p += sprintf(p, "VERR Interrupt:\t\t\t"); | ||
372 | REPORT_IRQ(VERR, verr); | ||
373 | p += sprintf(p, "LERR Interrupt:\t\t\t"); | ||
374 | REPORT_IRQ(LERR, lerr); | ||
375 | p += sprintf(p, "LM Interrupt:\t\t\t"); | ||
376 | REPORT_IRQ(LM, lm); | ||
377 | p += sprintf(p, "MBOX Interrupt:\t\t\t"); | ||
378 | REPORT_IRQ(MBOX, mbox); | ||
379 | p += sprintf(p, "DMA Interrupt:\t\t\t"); | ||
380 | REPORT_IRQ(DMA, dma); | ||
381 | p += sprintf(p, "VIRQ7 Interrupt:\t\t"); | ||
382 | REPORT_IRQ(VIRQ7, virq[7 - 1]); | ||
383 | p += sprintf(p, "VIRQ6 Interrupt:\t\t"); | ||
384 | REPORT_IRQ(VIRQ6, virq[6 - 1]); | ||
385 | p += sprintf(p, "VIRQ5 Interrupt:\t\t"); | ||
386 | REPORT_IRQ(VIRQ5, virq[5 - 1]); | ||
387 | p += sprintf(p, "VIRQ4 Interrupt:\t\t"); | ||
388 | REPORT_IRQ(VIRQ4, virq[4 - 1]); | ||
389 | p += sprintf(p, "VIRQ3 Interrupt:\t\t"); | ||
390 | REPORT_IRQ(VIRQ3, virq[3 - 1]); | ||
391 | p += sprintf(p, "VIRQ2 Interrupt:\t\t"); | ||
392 | REPORT_IRQ(VIRQ2, virq[2 - 1]); | ||
393 | p += sprintf(p, "VIRQ1 Interrupt:\t\t"); | ||
394 | REPORT_IRQ(VIRQ1, virq[1 - 1]); | ||
395 | p += sprintf(p, "VOWN Interrupt:\t\t\t"); | ||
396 | REPORT_IRQ(VOWN, vown); | ||
397 | p += sprintf(p, "\n"); | ||
398 | #undef REPORT_IRQ | ||
399 | } | ||
400 | { | ||
401 | unsigned long vrai_ctl; | ||
402 | |||
403 | vrai_ctl = read_register(VRAI_CTL); | ||
404 | if (vrai_ctl & UNIV_BM_VRAI_CTL_EN) { | ||
405 | unsigned int vrai_bs; | ||
406 | |||
407 | vrai_bs = read_register(VRAI_BS); | ||
408 | p += sprintf(p, | ||
409 | "VME Register Image:\t\tEnabled at VME-Address 0x%x\n", | ||
410 | vrai_bs); | ||
411 | } else | ||
412 | p += sprintf(p, "VME Register Image:\t\tDisabled\n"); | ||
413 | } | ||
414 | { | ||
415 | unsigned int slsi; | ||
416 | |||
417 | slsi = read_register(SLSI); | ||
418 | if (slsi & UNIV_BM_SLSI_EN) { | ||
419 | /* Not implemented */ | ||
420 | } else { | ||
421 | p += sprintf(p, "Special PCI Slave Image:\tDisabled\n"); | ||
422 | } | ||
423 | } | ||
424 | { | ||
425 | int i; | ||
426 | |||
427 | for (i = 0; i < (vmechip_revision > 0 ? 8 : 4); i++) { | ||
428 | unsigned int ctl, bs, bd, to, vstart, vend; | ||
429 | |||
430 | ctl = readl(vmechip_baseaddr + outCTL[i]); | ||
431 | bs = readl(vmechip_baseaddr + outBS[i]); | ||
432 | bd = readl(vmechip_baseaddr + outBD[i]); | ||
433 | to = readl(vmechip_baseaddr + outTO[i]); | ||
434 | |||
435 | vstart = bs + to; | ||
436 | vend = bd + to; | ||
437 | |||
438 | p += sprintf(p, "PCI Slave Image %d:\t\t", i); | ||
439 | if (ctl & UNIV_BM_LSI_CTL_EN) { | ||
440 | p += sprintf(p, "Enabled"); | ||
441 | if (ctl & UNIV_BM_LSI_CTL_PWEN) | ||
442 | p += sprintf(p, | ||
443 | ", Posted Write Enabled\n"); | ||
444 | else | ||
445 | p += sprintf(p, "\n"); | ||
446 | p += sprintf(p, | ||
447 | "\t\t\t\tPCI Addresses from 0x%x to 0x%x\n", | ||
448 | bs, bd); | ||
449 | p += sprintf(p, | ||
450 | "\t\t\t\tVME Addresses from 0x%x to 0x%x\n", | ||
451 | vstart, vend); | ||
452 | } else | ||
453 | p += sprintf(p, "Disabled\n"); | ||
454 | } | ||
455 | p += sprintf(p, "\n"); | ||
456 | } | ||
457 | { | ||
458 | int i; | ||
459 | for (i = 0; i < (vmechip_revision > 0 ? 8 : 4); i++) { | ||
460 | unsigned int ctl, bs, bd, to, vstart, vend; | ||
461 | |||
462 | ctl = readl(vmechip_baseaddr + inCTL[i]); | ||
463 | bs = readl(vmechip_baseaddr + inBS[i]); | ||
464 | bd = readl(vmechip_baseaddr + inBD[i]); | ||
465 | to = readl(vmechip_baseaddr + inTO[i]); | ||
466 | vstart = bs + to; | ||
467 | vend = bd + to; | ||
468 | p += sprintf(p, "VME Slave Image %d:\t\t", i); | ||
469 | if (ctl & UNIV_BM_LSI_CTL_EN) { | ||
470 | p += sprintf(p, "Enabled"); | ||
471 | if (ctl & UNIV_BM_LSI_CTL_PWEN) | ||
472 | p += sprintf(p, | ||
473 | ", Posted Write Enabled\n"); | ||
474 | else | ||
475 | p += sprintf(p, "\n"); | ||
476 | p += sprintf(p, | ||
477 | "\t\t\t\tVME Addresses from 0x%x to 0x%x\n", | ||
478 | bs, bd); | ||
479 | p += sprintf(p, | ||
480 | "\t\t\t\tPCI Addresses from 0x%x to 0x%x\n", | ||
481 | vstart, vend); | ||
482 | } else | ||
483 | p += sprintf(p, "Disabled\n"); | ||
484 | } | ||
485 | } | ||
486 | 108 | ||
487 | return p - buf; | 109 | return CA91CX42_LINT_SW_IACK; |
488 | } | 110 | } |
489 | 111 | ||
490 | //---------------------------------------------------------------------------- | 112 | #if 0 |
491 | // uni_bus_error_chk() | 113 | int ca91cx42_bus_error_chk(int clrflag) |
492 | //---------------------------------------------------------------------------- | ||
493 | int uni_bus_error_chk(int clrflag) | ||
494 | { | 114 | { |
495 | int tmp; | 115 | int tmp; |
496 | tmp = readl(vmechip_baseaddr + PCI_COMMAND); | 116 | tmp = ioread32(ca91cx42_bridge->base + PCI_COMMAND); |
497 | if (tmp & 0x08000000) { // S_TA is Set | 117 | if (tmp & 0x08000000) { /* S_TA is Set */ |
498 | if (clrflag) | 118 | if (clrflag) |
499 | writel(tmp | 0x08000000, | 119 | iowrite32(tmp | 0x08000000, |
500 | vmechip_baseaddr + PCI_COMMAND); | 120 | ca91cx42_bridge->base + PCI_COMMAND); |
501 | return (1); | 121 | return 1; |
502 | } | 122 | } |
503 | return (0); | 123 | return 0; |
504 | } | ||
505 | |||
506 | //----------------------------------------------------------------------------- | ||
507 | // Function : DMA_uni_irqhandler | ||
508 | // Inputs : void | ||
509 | // Outputs : void | ||
510 | // Description: Saves DMA completion timestamp and then wakes up DMA queue | ||
511 | //----------------------------------------------------------------------------- | ||
512 | static void DMA_uni_irqhandler(void) | ||
513 | { | ||
514 | uni_dma_irq_time = uni_irq_time; | ||
515 | wake_up(&dma_queue[0]); | ||
516 | } | 124 | } |
125 | #endif | ||
517 | 126 | ||
518 | //----------------------------------------------------------------------------- | 127 | static u32 ca91cx42_VERR_irqhandler(void) |
519 | // Function : LERR_uni_irqhandler | ||
520 | // Inputs : void | ||
521 | // Outputs : void | ||
522 | // Description: | ||
523 | //----------------------------------------------------------------------------- | ||
524 | static void LERR_uni_irqhandler(void) | ||
525 | { | 128 | { |
526 | int val; | 129 | int val; |
527 | 130 | ||
528 | val = readl(vmechip_baseaddr + DGCS); | 131 | val = ioread32(ca91cx42_bridge->base + DGCS); |
529 | 132 | ||
530 | if (!(val & 0x00000800)) { | 133 | if (!(val & 0x00000800)) { |
531 | printk(KERN_ERR | 134 | printk(KERN_ERR "ca91c042: ca91cx42_VERR_irqhandler DMA Read " |
532 | "ca91c042: LERR_uni_irqhandler DMA Read Error DGCS=%08X\n", | 135 | "Error DGCS=%08X\n", val); |
533 | val); | ||
534 | |||
535 | } | 136 | } |
137 | |||
138 | return CA91CX42_LINT_VERR; | ||
536 | } | 139 | } |
537 | 140 | ||
538 | //----------------------------------------------------------------------------- | 141 | static u32 ca91cx42_LERR_irqhandler(void) |
539 | // Function : VERR_uni_irqhandler | ||
540 | // Inputs : void | ||
541 | // Outputs : void | ||
542 | // Description: | ||
543 | //----------------------------------------------------------------------------- | ||
544 | static void VERR_uni_irqhandler(void) | ||
545 | { | 142 | { |
546 | int val; | 143 | int val; |
547 | 144 | ||
548 | val = readl(vmechip_baseaddr + DGCS); | 145 | val = ioread32(ca91cx42_bridge->base + DGCS); |
549 | 146 | ||
550 | if (!(val & 0x00000800)) { | 147 | if (!(val & 0x00000800)) { |
551 | printk(KERN_ERR | 148 | printk(KERN_ERR "ca91c042: ca91cx42_LERR_irqhandler DMA Read " |
552 | "ca91c042: VERR_uni_irqhandler DMA Read Error DGCS=%08X\n", | 149 | "Error DGCS=%08X\n", val); |
553 | val); | ||
554 | } | ||
555 | |||
556 | } | ||
557 | 150 | ||
558 | //----------------------------------------------------------------------------- | ||
559 | // Function : MB_uni_irqhandler | ||
560 | // Inputs : void | ||
561 | // Outputs : void | ||
562 | // Description: | ||
563 | //----------------------------------------------------------------------------- | ||
564 | static void MB_uni_irqhandler(int mbox_mask) | ||
565 | { | ||
566 | if (vmechip_irq_overhead_ticks != 0) { | ||
567 | wake_up(&mbox_queue); | ||
568 | } | 151 | } |
569 | } | ||
570 | 152 | ||
571 | //----------------------------------------------------------------------------- | 153 | return CA91CX42_LINT_LERR; |
572 | // Function : LM_uni_irqhandler | ||
573 | // Inputs : void | ||
574 | // Outputs : void | ||
575 | // Description: | ||
576 | //----------------------------------------------------------------------------- | ||
577 | static void LM_uni_irqhandler(int lm_mask) | ||
578 | { | ||
579 | uni_lm_event = lm_mask; | ||
580 | wake_up(&lm_queue); | ||
581 | } | 154 | } |
582 | 155 | ||
583 | //----------------------------------------------------------------------------- | 156 | |
584 | // Function : VIRQ_uni_irqhandler | 157 | static u32 ca91cx42_VIRQ_irqhandler(int stat) |
585 | // Inputs : void | ||
586 | // Outputs : void | ||
587 | // Description: | ||
588 | //----------------------------------------------------------------------------- | ||
589 | static void VIRQ_uni_irqhandler(int virq_mask) | ||
590 | { | 158 | { |
591 | int iackvec, i; | 159 | int vec, i, serviced = 0; |
160 | void (*call)(int, int, void *); | ||
161 | void *priv_data; | ||
592 | 162 | ||
593 | for (i = 7; i > 0; i--) { | 163 | for (i = 7; i > 0; i--) { |
594 | if (virq_mask & (1 << i)) { | 164 | if (stat & (1 << i)) { |
595 | Interrupt_counters.virq[i - 1]++; | 165 | vec = ioread32(ca91cx42_bridge->base + |
596 | iackvec = readl(vmechip_baseaddr + vmevec[i - 1]); | 166 | CA91CX42_V_STATID[i]) & 0xff; |
597 | vme_irqlog[i][iackvec]++; | 167 | |
168 | call = ca91cx42_bridge->irq[i - 1].callback[vec].func; | ||
169 | priv_data = | ||
170 | ca91cx42_bridge->irq[i - 1].callback[vec].priv_data; | ||
171 | |||
172 | if (call != NULL) | ||
173 | call(i, vec, priv_data); | ||
174 | else | ||
175 | printk("Spurilous VME interrupt, level:%x, " | ||
176 | "vector:%x\n", i, vec); | ||
177 | |||
178 | serviced |= (1 << i); | ||
598 | } | 179 | } |
599 | } | 180 | } |
181 | |||
182 | return serviced; | ||
600 | } | 183 | } |
601 | 184 | ||
602 | //----------------------------------------------------------------------------- | 185 | static irqreturn_t ca91cx42_irqhandler(int irq, void *dev_id) |
603 | // Function : uni_irqhandler | ||
604 | // Inputs : int irq, void *dev_id, struct pt_regs *regs | ||
605 | // Outputs : void | ||
606 | // Description: | ||
607 | //----------------------------------------------------------------------------- | ||
608 | static irqreturn_t uni_irqhandler(int irq, void *dev_id) | ||
609 | { | 186 | { |
610 | long stat, enable; | 187 | u32 stat, enable, serviced = 0; |
611 | 188 | ||
612 | if (dev_id != vmechip_baseaddr) | 189 | if (dev_id != ca91cx42_bridge->base) |
613 | return IRQ_NONE; | 190 | return IRQ_NONE; |
614 | 191 | ||
615 | uni_irq_time = get_tbl(); | 192 | enable = ioread32(ca91cx42_bridge->base + LINT_EN); |
193 | stat = ioread32(ca91cx42_bridge->base + LINT_STAT); | ||
616 | 194 | ||
617 | stat = readl(vmechip_baseaddr + LINT_STAT); | 195 | /* Only look at unmasked interrupts */ |
618 | writel(stat, vmechip_baseaddr + LINT_STAT); // Clear all pending ints | 196 | stat &= enable; |
619 | enable = readl(vmechip_baseaddr + LINT_EN); | 197 | |
620 | stat = stat & enable; | 198 | if (unlikely(!stat)) |
621 | if (stat & 0x0100) { | 199 | return IRQ_NONE; |
622 | Interrupt_counters.dma++; | 200 | |
623 | DMA_uni_irqhandler(); | 201 | if (stat & CA91CX42_LINT_DMA) |
624 | } | 202 | serviced |= ca91cx42_DMA_irqhandler(); |
625 | if (stat & 0x0200) { | 203 | if (stat & (CA91CX42_LINT_LM0 | CA91CX42_LINT_LM1 | CA91CX42_LINT_LM2 | |
626 | Interrupt_counters.lerr++; | 204 | CA91CX42_LINT_LM3)) |
627 | LERR_uni_irqhandler(); | 205 | serviced |= ca91cx42_LM_irqhandler(stat); |
628 | } | 206 | if (stat & CA91CX42_LINT_MBOX) |
629 | if (stat & 0x0400) { | 207 | serviced |= ca91cx42_MB_irqhandler(stat); |
630 | Interrupt_counters.verr++; | 208 | if (stat & CA91CX42_LINT_SW_IACK) |
631 | VERR_uni_irqhandler(); | 209 | serviced |= ca91cx42_IACK_irqhandler(); |
632 | } | 210 | if (stat & CA91CX42_LINT_VERR) |
633 | if (stat & 0xF0000) { | 211 | serviced |= ca91cx42_VERR_irqhandler(); |
634 | Interrupt_counters.mbox++; | 212 | if (stat & CA91CX42_LINT_LERR) |
635 | MB_uni_irqhandler((stat & 0xF0000) >> 16); | 213 | serviced |= ca91cx42_LERR_irqhandler(); |
636 | } | 214 | if (stat & (CA91CX42_LINT_VIRQ1 | CA91CX42_LINT_VIRQ2 | |
637 | if (stat & 0xF00000) { | 215 | CA91CX42_LINT_VIRQ3 | CA91CX42_LINT_VIRQ4 | |
638 | Interrupt_counters.lm++; | 216 | CA91CX42_LINT_VIRQ5 | CA91CX42_LINT_VIRQ6 | |
639 | LM_uni_irqhandler((stat & 0xF00000) >> 20); | 217 | CA91CX42_LINT_VIRQ7)) |
640 | } | 218 | serviced |= ca91cx42_VIRQ_irqhandler(stat); |
641 | if (stat & 0x0000FE) { | 219 | |
642 | VIRQ_uni_irqhandler(stat & 0x0000FE); | 220 | /* Clear serviced interrupts */ |
643 | } | 221 | iowrite32(stat, ca91cx42_bridge->base + LINT_STAT); |
644 | if (stat & UNIV_BM_LINT_ACFAIL) { | ||
645 | Interrupt_counters.acfail++; | ||
646 | } | ||
647 | if (stat & UNIV_BM_LINT_SYSFAIL) { | ||
648 | Interrupt_counters.sysfail++; | ||
649 | } | ||
650 | if (stat & UNIV_BM_LINT_SW_INT) { | ||
651 | Interrupt_counters.sw_int++; | ||
652 | } | ||
653 | if (stat & UNIV_BM_LINT_SW_IACK) { | ||
654 | Interrupt_counters.sw_iack++; | ||
655 | } | ||
656 | if (stat & UNIV_BM_LINT_VOWN) { | ||
657 | Interrupt_counters.vown++; | ||
658 | } | ||
659 | 222 | ||
660 | return IRQ_HANDLED; | 223 | return IRQ_HANDLED; |
661 | } | 224 | } |
662 | 225 | ||
663 | //----------------------------------------------------------------------------- | 226 | static int ca91cx42_irq_init(struct vme_bridge *bridge) |
664 | // Function : uni_generate_irq | ||
665 | // Description: | ||
666 | //----------------------------------------------------------------------------- | ||
667 | int uni_generate_irq(virqInfo_t * vmeIrq) | ||
668 | { | 227 | { |
669 | int timeout; | 228 | int result, tmp; |
670 | int looptimeout; | 229 | struct pci_dev *pdev; |
671 | 230 | ||
672 | timeout = vmeIrq->waitTime; | 231 | /* Need pdev */ |
673 | if (timeout == 0) { | 232 | pdev = container_of(bridge->parent, struct pci_dev, dev); |
674 | timeout++; // Wait at least 1 tick... | ||
675 | } | ||
676 | looptimeout = HZ / 20; // try for 1/20 second | ||
677 | 233 | ||
678 | vmeIrq->timeOutFlag = 0; | 234 | /* Initialise list for VME bus errors */ |
235 | INIT_LIST_HEAD(&(bridge->vme_errors)); | ||
679 | 236 | ||
680 | // Validate & setup vector register. | 237 | /* Disable interrupts from PCI to VME */ |
681 | if (vmeIrq->vector & 1) { // Universe can only generate even vectors | 238 | iowrite32(0, bridge->base + VINT_EN); |
682 | return (-EINVAL); | ||
683 | } | ||
684 | writel(vmeIrq->vector << 24, vmechip_baseaddr + STATID); | ||
685 | 239 | ||
686 | // Assert VMEbus IRQ | 240 | /* Disable PCI interrupts */ |
687 | writel(1 << (vmeIrq->level + 24), vmechip_baseaddr + VINT_EN); | 241 | iowrite32(0, bridge->base + LINT_EN); |
242 | /* Clear Any Pending PCI Interrupts */ | ||
243 | iowrite32(0x00FFFFFF, bridge->base + LINT_STAT); | ||
688 | 244 | ||
689 | // Wait for syscon to do iack | 245 | result = request_irq(pdev->irq, ca91cx42_irqhandler, IRQF_SHARED, |
690 | while (readl(vmechip_baseaddr + VINT_STAT) & | 246 | driver_name, pdev); |
691 | (1 << (vmeIrq->level + 24))) { | 247 | if (result) { |
692 | set_current_state(TASK_INTERRUPTIBLE); | 248 | dev_err(&pdev->dev, "Can't get assigned pci irq vector %02X\n", |
693 | schedule_timeout(looptimeout); | 249 | pdev->irq); |
694 | timeout = timeout - looptimeout; | 250 | return result; |
695 | if (timeout <= 0) { | ||
696 | vmeIrq->timeOutFlag = 1; | ||
697 | break; | ||
698 | } | ||
699 | } | 251 | } |
700 | 252 | ||
701 | // Clear VMEbus IRQ bit | 253 | /* Ensure all interrupts are mapped to PCI Interrupt 0 */ |
702 | writel(0, vmechip_baseaddr + VINT_EN); | 254 | iowrite32(0, bridge->base + LINT_MAP0); |
703 | 255 | iowrite32(0, bridge->base + LINT_MAP1); | |
704 | return (0); | 256 | iowrite32(0, bridge->base + LINT_MAP2); |
705 | } | ||
706 | 257 | ||
707 | //----------------------------------------------------------------------------- | 258 | /* Enable DMA, mailbox & LM Interrupts */ |
708 | // Function : uni_set_arbiter | 259 | tmp = CA91CX42_LINT_MBOX3 | CA91CX42_LINT_MBOX2 | CA91CX42_LINT_MBOX1 | |
709 | // Description: | 260 | CA91CX42_LINT_MBOX0 | CA91CX42_LINT_SW_IACK | |
710 | //----------------------------------------------------------------------------- | 261 | CA91CX42_LINT_VERR | CA91CX42_LINT_LERR | CA91CX42_LINT_DMA; |
711 | int uni_set_arbiter(vmeArbiterCfg_t * vmeArb) | ||
712 | { | ||
713 | int temp_ctl = 0; | ||
714 | int vbto = 0; | ||
715 | 262 | ||
716 | temp_ctl = readl(vmechip_baseaddr + MISC_CTL); | 263 | iowrite32(tmp, bridge->base + LINT_EN); |
717 | temp_ctl &= 0x00FFFFFF; | ||
718 | 264 | ||
719 | if (vmeArb->globalTimeoutTimer == 0xFFFFFFFF) { | 265 | return 0; |
720 | vbto = 7; | 266 | } |
721 | } else if (vmeArb->globalTimeoutTimer > 1024) { | ||
722 | return (-EINVAL); | ||
723 | } else if (vmeArb->globalTimeoutTimer == 0) { | ||
724 | vbto = 0; | ||
725 | } else { | ||
726 | vbto = 1; | ||
727 | while ((16 * (1 << (vbto - 1))) < vmeArb->globalTimeoutTimer) { | ||
728 | vbto += 1; | ||
729 | } | ||
730 | } | ||
731 | temp_ctl |= (vbto << 28); | ||
732 | 267 | ||
733 | if (vmeArb->arbiterMode == VME_PRIORITY_MODE) { | 268 | static void ca91cx42_irq_exit(struct pci_dev *pdev) |
734 | temp_ctl |= 1 << 26; | 269 | { |
735 | } | 270 | /* Disable interrupts from PCI to VME */ |
271 | iowrite32(0, ca91cx42_bridge->base + VINT_EN); | ||
736 | 272 | ||
737 | if (vmeArb->arbiterTimeoutFlag) { | 273 | /* Disable PCI interrupts */ |
738 | temp_ctl |= 2 << 24; | 274 | iowrite32(0, ca91cx42_bridge->base + LINT_EN); |
739 | } | 275 | /* Clear Any Pending PCI Interrupts */ |
276 | iowrite32(0x00FFFFFF, ca91cx42_bridge->base + LINT_STAT); | ||
740 | 277 | ||
741 | writel(temp_ctl, vmechip_baseaddr + MISC_CTL); | 278 | free_irq(pdev->irq, pdev); |
742 | return (0); | ||
743 | } | 279 | } |
744 | 280 | ||
745 | //----------------------------------------------------------------------------- | 281 | /* |
746 | // Function : uni_get_arbiter | 282 | * Set up an VME interrupt |
747 | // Description: | 283 | */ |
748 | //----------------------------------------------------------------------------- | 284 | int ca91cx42_request_irq(int level, int statid, |
749 | int uni_get_arbiter(vmeArbiterCfg_t * vmeArb) | 285 | void (*callback)(int level, int vector, void *priv_data), |
286 | void *priv_data) | ||
750 | { | 287 | { |
751 | int temp_ctl = 0; | 288 | u32 tmp; |
752 | int vbto = 0; | ||
753 | 289 | ||
754 | temp_ctl = readl(vmechip_baseaddr + MISC_CTL); | 290 | mutex_lock(&(vme_irq)); |
755 | 291 | ||
756 | vbto = (temp_ctl >> 28) & 0xF; | 292 | if (ca91cx42_bridge->irq[level - 1].callback[statid].func) { |
757 | if (vbto != 0) { | 293 | mutex_unlock(&(vme_irq)); |
758 | vmeArb->globalTimeoutTimer = (16 * (1 << (vbto - 1))); | 294 | printk("VME Interrupt already taken\n"); |
295 | return -EBUSY; | ||
759 | } | 296 | } |
760 | 297 | ||
761 | if (temp_ctl & (1 << 26)) { | ||
762 | vmeArb->arbiterMode = VME_PRIORITY_MODE; | ||
763 | } else { | ||
764 | vmeArb->arbiterMode = VME_R_ROBIN_MODE; | ||
765 | } | ||
766 | 298 | ||
767 | if (temp_ctl & (3 << 24)) { | 299 | ca91cx42_bridge->irq[level - 1].count++; |
768 | vmeArb->arbiterTimeoutFlag = 1; | 300 | ca91cx42_bridge->irq[level - 1].callback[statid].priv_data = priv_data; |
769 | } | 301 | ca91cx42_bridge->irq[level - 1].callback[statid].func = callback; |
770 | return (0); | 302 | |
303 | /* Enable IRQ level */ | ||
304 | tmp = ioread32(ca91cx42_bridge->base + LINT_EN); | ||
305 | tmp |= CA91CX42_LINT_VIRQ[level]; | ||
306 | iowrite32(tmp, ca91cx42_bridge->base + LINT_EN); | ||
307 | |||
308 | mutex_unlock(&(vme_irq)); | ||
309 | |||
310 | return 0; | ||
771 | } | 311 | } |
772 | 312 | ||
773 | //----------------------------------------------------------------------------- | 313 | /* |
774 | // Function : uni_set_requestor | 314 | * Free VME interrupt |
775 | // Description: | 315 | */ |
776 | //----------------------------------------------------------------------------- | 316 | void ca91cx42_free_irq(int level, int statid) |
777 | int uni_set_requestor(vmeRequesterCfg_t * vmeReq) | ||
778 | { | 317 | { |
779 | int temp_ctl = 0; | 318 | u32 tmp; |
319 | struct pci_dev *pdev; | ||
780 | 320 | ||
781 | temp_ctl = readl(vmechip_baseaddr + MAST_CTL); | 321 | mutex_lock(&(vme_irq)); |
782 | temp_ctl &= 0xFF0FFFFF; | ||
783 | 322 | ||
784 | if (vmeReq->releaseMode == 1) { | 323 | ca91cx42_bridge->irq[level - 1].count--; |
785 | temp_ctl |= (1 << 20); | ||
786 | } | ||
787 | 324 | ||
788 | if (vmeReq->fairMode == 1) { | 325 | /* Disable IRQ level if no more interrupts attached at this level*/ |
789 | temp_ctl |= (1 << 21); | 326 | if (ca91cx42_bridge->irq[level - 1].count == 0) { |
327 | tmp = ioread32(ca91cx42_bridge->base + LINT_EN); | ||
328 | tmp &= ~CA91CX42_LINT_VIRQ[level]; | ||
329 | iowrite32(tmp, ca91cx42_bridge->base + LINT_EN); | ||
330 | |||
331 | pdev = container_of(ca91cx42_bridge->parent, struct pci_dev, | ||
332 | dev); | ||
333 | |||
334 | synchronize_irq(pdev->irq); | ||
790 | } | 335 | } |
791 | 336 | ||
792 | temp_ctl |= (vmeReq->requestLevel << 22); | 337 | ca91cx42_bridge->irq[level - 1].callback[statid].func = NULL; |
338 | ca91cx42_bridge->irq[level - 1].callback[statid].priv_data = NULL; | ||
793 | 339 | ||
794 | writel(temp_ctl, vmechip_baseaddr + MAST_CTL); | 340 | mutex_unlock(&(vme_irq)); |
795 | return (0); | ||
796 | } | 341 | } |
797 | 342 | ||
798 | //----------------------------------------------------------------------------- | 343 | int ca91cx42_generate_irq(int level, int statid) |
799 | // Function : uni_get_requestor | ||
800 | // Description: | ||
801 | //----------------------------------------------------------------------------- | ||
802 | int uni_get_requestor(vmeRequesterCfg_t * vmeReq) | ||
803 | { | 344 | { |
804 | int temp_ctl = 0; | 345 | u32 tmp; |
805 | 346 | ||
806 | temp_ctl = readl(vmechip_baseaddr + MAST_CTL); | 347 | /* Universe can only generate even vectors */ |
348 | if (statid & 1) | ||
349 | return -EINVAL; | ||
807 | 350 | ||
808 | if (temp_ctl & (1 << 20)) { | 351 | mutex_lock(&(vme_int)); |
809 | vmeReq->releaseMode = 1; | ||
810 | } | ||
811 | 352 | ||
812 | if (temp_ctl & (1 << 21)) { | 353 | tmp = ioread32(ca91cx42_bridge->base + VINT_EN); |
813 | vmeReq->fairMode = 1; | ||
814 | } | ||
815 | 354 | ||
816 | vmeReq->requestLevel = (temp_ctl & 0xC00000) >> 22; | 355 | /* Set Status/ID */ |
356 | iowrite32(statid << 24, ca91cx42_bridge->base + STATID); | ||
357 | |||
358 | /* Assert VMEbus IRQ */ | ||
359 | tmp = tmp | (1 << (level + 24)); | ||
360 | iowrite32(tmp, ca91cx42_bridge->base + VINT_EN); | ||
361 | |||
362 | /* Wait for IACK */ | ||
363 | wait_event_interruptible(iack_queue, 0); | ||
817 | 364 | ||
818 | return (0); | 365 | /* Return interrupt to low state */ |
366 | tmp = ioread32(ca91cx42_bridge->base + VINT_EN); | ||
367 | tmp = tmp & ~(1 << (level + 24)); | ||
368 | iowrite32(tmp, ca91cx42_bridge->base + VINT_EN); | ||
369 | |||
370 | mutex_unlock(&(vme_int)); | ||
371 | |||
372 | return 0; | ||
819 | } | 373 | } |
820 | 374 | ||
821 | //----------------------------------------------------------------------------- | 375 | int ca91cx42_slave_set(struct vme_slave_resource *image, int enabled, |
822 | // Function : uni_set_in_bound | 376 | unsigned long long vme_base, unsigned long long size, |
823 | // Description: | 377 | dma_addr_t pci_base, vme_address_t aspace, vme_cycle_t cycle) |
824 | //----------------------------------------------------------------------------- | ||
825 | int uni_set_in_bound(vmeInWindowCfg_t * vmeIn) | ||
826 | { | 378 | { |
827 | int temp_ctl = 0; | 379 | unsigned int i, addr = 0, granularity = 0; |
380 | unsigned int temp_ctl = 0; | ||
381 | unsigned int vme_bound, pci_offset; | ||
828 | 382 | ||
829 | // Verify input data | 383 | i = image->number; |
830 | if (vmeIn->windowNbr > 7) { | ||
831 | return (-EINVAL); | ||
832 | } | ||
833 | if ((vmeIn->vmeAddrU) || (vmeIn->windowSizeU) || (vmeIn->pciAddrU)) { | ||
834 | return (-EINVAL); | ||
835 | } | ||
836 | if ((vmeIn->vmeAddrL & 0xFFF) || | ||
837 | (vmeIn->windowSizeL & 0xFFF) || (vmeIn->pciAddrL & 0xFFF)) { | ||
838 | return (-EINVAL); | ||
839 | } | ||
840 | 384 | ||
841 | if (vmeIn->bcastRespond2esst) { | 385 | switch (aspace) { |
842 | return (-EINVAL); | ||
843 | } | ||
844 | switch (vmeIn->addrSpace) { | ||
845 | case VME_A64: | ||
846 | case VME_CRCSR: | ||
847 | case VME_USER3: | ||
848 | case VME_USER4: | ||
849 | return (-EINVAL); | ||
850 | case VME_A16: | 386 | case VME_A16: |
851 | temp_ctl |= 0x00000; | 387 | addr |= CA91CX42_VSI_CTL_VAS_A16; |
852 | break; | 388 | break; |
853 | case VME_A24: | 389 | case VME_A24: |
854 | temp_ctl |= 0x10000; | 390 | addr |= CA91CX42_VSI_CTL_VAS_A24; |
855 | break; | 391 | break; |
856 | case VME_A32: | 392 | case VME_A32: |
857 | temp_ctl |= 0x20000; | 393 | addr |= CA91CX42_VSI_CTL_VAS_A32; |
858 | break; | 394 | break; |
859 | case VME_USER1: | 395 | case VME_USER1: |
860 | temp_ctl |= 0x60000; | 396 | addr |= CA91CX42_VSI_CTL_VAS_USER1; |
861 | break; | 397 | break; |
862 | case VME_USER2: | 398 | case VME_USER2: |
863 | temp_ctl |= 0x70000; | 399 | addr |= CA91CX42_VSI_CTL_VAS_USER2; |
864 | break; | 400 | break; |
401 | case VME_A64: | ||
402 | case VME_CRCSR: | ||
403 | case VME_USER3: | ||
404 | case VME_USER4: | ||
405 | default: | ||
406 | printk(KERN_ERR "Invalid address space\n"); | ||
407 | return -EINVAL; | ||
408 | break; | ||
409 | } | ||
410 | |||
411 | /* | ||
412 | * Bound address is a valid address for the window, adjust | ||
413 | * accordingly | ||
414 | */ | ||
415 | vme_bound = vme_base + size - granularity; | ||
416 | pci_offset = pci_base - vme_base; | ||
417 | |||
418 | /* XXX Need to check that vme_base, vme_bound and pci_offset aren't | ||
419 | * too big for registers | ||
420 | */ | ||
421 | |||
422 | if ((i == 0) || (i == 4)) | ||
423 | granularity = 0x1000; | ||
424 | else | ||
425 | granularity = 0x10000; | ||
426 | |||
427 | if (vme_base & (granularity - 1)) { | ||
428 | printk(KERN_ERR "Invalid VME base alignment\n"); | ||
429 | return -EINVAL; | ||
430 | } | ||
431 | if (vme_bound & (granularity - 1)) { | ||
432 | printk(KERN_ERR "Invalid VME bound alignment\n"); | ||
433 | return -EINVAL; | ||
434 | } | ||
435 | if (pci_offset & (granularity - 1)) { | ||
436 | printk(KERN_ERR "Invalid PCI Offset alignment\n"); | ||
437 | return -EINVAL; | ||
865 | } | 438 | } |
866 | 439 | ||
867 | // Disable while we are mucking around | 440 | /* Disable while we are mucking around */ |
868 | writel(0x00000000, vmechip_baseaddr + inCTL[vmeIn->windowNbr]); | 441 | temp_ctl = ioread32(ca91cx42_bridge->base + CA91CX42_VSI_CTL[i]); |
869 | writel(vmeIn->vmeAddrL, vmechip_baseaddr + inBS[vmeIn->windowNbr]); | 442 | temp_ctl &= ~CA91CX42_VSI_CTL_EN; |
870 | writel(vmeIn->vmeAddrL + vmeIn->windowSizeL, | 443 | iowrite32(temp_ctl, ca91cx42_bridge->base + CA91CX42_VSI_CTL[i]); |
871 | vmechip_baseaddr + inBD[vmeIn->windowNbr]); | ||
872 | writel(vmeIn->pciAddrL - vmeIn->vmeAddrL, | ||
873 | vmechip_baseaddr + inTO[vmeIn->windowNbr]); | ||
874 | 444 | ||
875 | // Setup CTL register. | 445 | /* Setup mapping */ |
446 | iowrite32(vme_base, ca91cx42_bridge->base + CA91CX42_VSI_BS[i]); | ||
447 | iowrite32(vme_bound, ca91cx42_bridge->base + CA91CX42_VSI_BD[i]); | ||
448 | iowrite32(pci_offset, ca91cx42_bridge->base + CA91CX42_VSI_TO[i]); | ||
449 | |||
450 | /* XXX Prefetch stuff currently unsupported */ | ||
451 | #if 0 | ||
876 | if (vmeIn->wrPostEnable) | 452 | if (vmeIn->wrPostEnable) |
877 | temp_ctl |= 0x40000000; | 453 | temp_ctl |= CA91CX42_VSI_CTL_PWEN; |
878 | if (vmeIn->prefetchEnable) | 454 | if (vmeIn->prefetchEnable) |
879 | temp_ctl |= 0x20000000; | 455 | temp_ctl |= CA91CX42_VSI_CTL_PREN; |
880 | if (vmeIn->rmwLock) | 456 | if (vmeIn->rmwLock) |
881 | temp_ctl |= 0x00000040; | 457 | temp_ctl |= CA91CX42_VSI_CTL_LLRMW; |
882 | if (vmeIn->data64BitCapable) | 458 | if (vmeIn->data64BitCapable) |
883 | temp_ctl |= 0x00000080; | 459 | temp_ctl |= CA91CX42_VSI_CTL_LD64EN; |
884 | if (vmeIn->userAccessType & VME_USER) | 460 | #endif |
885 | temp_ctl |= 0x00100000; | 461 | |
886 | if (vmeIn->userAccessType & VME_SUPER) | 462 | /* Setup address space */ |
887 | temp_ctl |= 0x00200000; | 463 | temp_ctl &= ~CA91CX42_VSI_CTL_VAS_M; |
888 | if (vmeIn->dataAccessType & VME_DATA) | 464 | temp_ctl |= addr; |
889 | temp_ctl |= 0x00400000; | 465 | |
890 | if (vmeIn->dataAccessType & VME_PROG) | 466 | /* Setup cycle types */ |
891 | temp_ctl |= 0x00800000; | 467 | temp_ctl &= ~(CA91CX42_VSI_CTL_PGM_M | CA91CX42_VSI_CTL_SUPER_M); |
468 | if (cycle & VME_SUPER) | ||
469 | temp_ctl |= CA91CX42_VSI_CTL_SUPER_SUPR; | ||
470 | if (cycle & VME_USER) | ||
471 | temp_ctl |= CA91CX42_VSI_CTL_SUPER_NPRIV; | ||
472 | if (cycle & VME_PROG) | ||
473 | temp_ctl |= CA91CX42_VSI_CTL_PGM_PGM; | ||
474 | if (cycle & VME_DATA) | ||
475 | temp_ctl |= CA91CX42_VSI_CTL_PGM_DATA; | ||
892 | 476 | ||
893 | // Write ctl reg without enable | 477 | /* Write ctl reg without enable */ |
894 | writel(temp_ctl, vmechip_baseaddr + inCTL[vmeIn->windowNbr]); | 478 | iowrite32(temp_ctl, ca91cx42_bridge->base + CA91CX42_VSI_CTL[i]); |
895 | 479 | ||
896 | if (vmeIn->windowEnable) | 480 | if (enabled) |
897 | temp_ctl |= 0x80000000; | 481 | temp_ctl |= CA91CX42_VSI_CTL_EN; |
898 | 482 | ||
899 | writel(temp_ctl, vmechip_baseaddr + inCTL[vmeIn->windowNbr]); | 483 | iowrite32(temp_ctl, ca91cx42_bridge->base + CA91CX42_VSI_CTL[i]); |
900 | return (0); | 484 | |
485 | return 0; | ||
901 | } | 486 | } |
902 | 487 | ||
903 | //----------------------------------------------------------------------------- | 488 | int ca91cx42_slave_get(struct vme_slave_resource *image, int *enabled, |
904 | // Function : uni_get_in_bound | 489 | unsigned long long *vme_base, unsigned long long *size, |
905 | // Description: | 490 | dma_addr_t *pci_base, vme_address_t *aspace, vme_cycle_t *cycle) |
906 | //----------------------------------------------------------------------------- | ||
907 | int uni_get_in_bound(vmeInWindowCfg_t * vmeIn) | ||
908 | { | 491 | { |
909 | int temp_ctl = 0; | 492 | unsigned int i, granularity = 0, ctl = 0; |
493 | unsigned long long vme_bound, pci_offset; | ||
910 | 494 | ||
911 | // Verify input data | 495 | i = image->number; |
912 | if (vmeIn->windowNbr > 7) { | ||
913 | return (-EINVAL); | ||
914 | } | ||
915 | // Get Window mappings. | ||
916 | vmeIn->vmeAddrL = readl(vmechip_baseaddr + inBS[vmeIn->windowNbr]); | ||
917 | vmeIn->pciAddrL = vmeIn->vmeAddrL + | ||
918 | readl(vmechip_baseaddr + inTO[vmeIn->windowNbr]); | ||
919 | vmeIn->windowSizeL = readl(vmechip_baseaddr + inBD[vmeIn->windowNbr]) - | ||
920 | vmeIn->vmeAddrL; | ||
921 | |||
922 | temp_ctl = readl(vmechip_baseaddr + inCTL[vmeIn->windowNbr]); | ||
923 | |||
924 | // Get Control & BUS attributes | ||
925 | if (temp_ctl & 0x40000000) | ||
926 | vmeIn->wrPostEnable = 1; | ||
927 | if (temp_ctl & 0x20000000) | ||
928 | vmeIn->prefetchEnable = 1; | ||
929 | if (temp_ctl & 0x00000040) | ||
930 | vmeIn->rmwLock = 1; | ||
931 | if (temp_ctl & 0x00000080) | ||
932 | vmeIn->data64BitCapable = 1; | ||
933 | if (temp_ctl & 0x00100000) | ||
934 | vmeIn->userAccessType |= VME_USER; | ||
935 | if (temp_ctl & 0x00200000) | ||
936 | vmeIn->userAccessType |= VME_SUPER; | ||
937 | if (temp_ctl & 0x00400000) | ||
938 | vmeIn->dataAccessType |= VME_DATA; | ||
939 | if (temp_ctl & 0x00800000) | ||
940 | vmeIn->dataAccessType |= VME_PROG; | ||
941 | if (temp_ctl & 0x80000000) | ||
942 | vmeIn->windowEnable = 1; | ||
943 | |||
944 | switch ((temp_ctl & 0x70000) >> 16) { | ||
945 | case 0x0: | ||
946 | vmeIn->addrSpace = VME_A16; | ||
947 | break; | ||
948 | case 0x1: | ||
949 | vmeIn->addrSpace = VME_A24; | ||
950 | break; | ||
951 | case 0x2: | ||
952 | vmeIn->addrSpace = VME_A32; | ||
953 | break; | ||
954 | case 0x6: | ||
955 | vmeIn->addrSpace = VME_USER1; | ||
956 | break; | ||
957 | case 0x7: | ||
958 | vmeIn->addrSpace = VME_USER2; | ||
959 | break; | ||
960 | } | ||
961 | 496 | ||
962 | return (0); | 497 | if ((i == 0) || (i == 4)) |
498 | granularity = 0x1000; | ||
499 | else | ||
500 | granularity = 0x10000; | ||
501 | |||
502 | /* Read Registers */ | ||
503 | ctl = ioread32(ca91cx42_bridge->base + CA91CX42_VSI_CTL[i]); | ||
504 | |||
505 | *vme_base = ioread32(ca91cx42_bridge->base + CA91CX42_VSI_BS[i]); | ||
506 | vme_bound = ioread32(ca91cx42_bridge->base + CA91CX42_VSI_BD[i]); | ||
507 | pci_offset = ioread32(ca91cx42_bridge->base + CA91CX42_VSI_TO[i]); | ||
508 | |||
509 | *pci_base = (dma_addr_t)vme_base + pci_offset; | ||
510 | *size = (unsigned long long)((vme_bound - *vme_base) + granularity); | ||
511 | |||
512 | *enabled = 0; | ||
513 | *aspace = 0; | ||
514 | *cycle = 0; | ||
515 | |||
516 | if (ctl & CA91CX42_VSI_CTL_EN) | ||
517 | *enabled = 1; | ||
518 | |||
519 | if ((ctl & CA91CX42_VSI_CTL_VAS_M) == CA91CX42_VSI_CTL_VAS_A16) | ||
520 | *aspace = VME_A16; | ||
521 | if ((ctl & CA91CX42_VSI_CTL_VAS_M) == CA91CX42_VSI_CTL_VAS_A24) | ||
522 | *aspace = VME_A24; | ||
523 | if ((ctl & CA91CX42_VSI_CTL_VAS_M) == CA91CX42_VSI_CTL_VAS_A32) | ||
524 | *aspace = VME_A32; | ||
525 | if ((ctl & CA91CX42_VSI_CTL_VAS_M) == CA91CX42_VSI_CTL_VAS_USER1) | ||
526 | *aspace = VME_USER1; | ||
527 | if ((ctl & CA91CX42_VSI_CTL_VAS_M) == CA91CX42_VSI_CTL_VAS_USER2) | ||
528 | *aspace = VME_USER2; | ||
529 | |||
530 | if (ctl & CA91CX42_VSI_CTL_SUPER_SUPR) | ||
531 | *cycle |= VME_SUPER; | ||
532 | if (ctl & CA91CX42_VSI_CTL_SUPER_NPRIV) | ||
533 | *cycle |= VME_USER; | ||
534 | if (ctl & CA91CX42_VSI_CTL_PGM_PGM) | ||
535 | *cycle |= VME_PROG; | ||
536 | if (ctl & CA91CX42_VSI_CTL_PGM_DATA) | ||
537 | *cycle |= VME_DATA; | ||
538 | |||
539 | return 0; | ||
963 | } | 540 | } |
964 | 541 | ||
965 | //----------------------------------------------------------------------------- | 542 | /* |
966 | // Function : uni_set_out_bound | 543 | * Allocate and map PCI Resource |
967 | // Description: | 544 | */ |
968 | //----------------------------------------------------------------------------- | 545 | static int ca91cx42_alloc_resource(struct vme_master_resource *image, |
969 | int uni_set_out_bound(vmeOutWindowCfg_t * vmeOut) | 546 | unsigned long long size) |
970 | { | 547 | { |
971 | int temp_ctl = 0; | 548 | unsigned long long existing_size; |
972 | 549 | int retval = 0; | |
973 | // Verify input data | 550 | struct pci_dev *pdev; |
974 | if (vmeOut->windowNbr > 7) { | 551 | |
975 | return (-EINVAL); | 552 | /* Find pci_dev container of dev */ |
553 | if (ca91cx42_bridge->parent == NULL) { | ||
554 | printk(KERN_ERR "Dev entry NULL\n"); | ||
555 | return -EINVAL; | ||
556 | } | ||
557 | pdev = container_of(ca91cx42_bridge->parent, struct pci_dev, dev); | ||
558 | |||
559 | existing_size = (unsigned long long)(image->pci_resource.end - | ||
560 | image->pci_resource.start); | ||
561 | |||
562 | /* If the existing size is OK, return */ | ||
563 | if (existing_size == (size - 1)) | ||
564 | return 0; | ||
565 | |||
566 | if (existing_size != 0) { | ||
567 | iounmap(image->kern_base); | ||
568 | image->kern_base = NULL; | ||
569 | if (image->pci_resource.name != NULL) | ||
570 | kfree(image->pci_resource.name); | ||
571 | release_resource(&(image->pci_resource)); | ||
572 | memset(&(image->pci_resource), 0, sizeof(struct resource)); | ||
573 | } | ||
574 | |||
575 | if (image->pci_resource.name == NULL) { | ||
576 | image->pci_resource.name = kmalloc(VMENAMSIZ+3, GFP_KERNEL); | ||
577 | if (image->pci_resource.name == NULL) { | ||
578 | printk(KERN_ERR "Unable to allocate memory for resource" | ||
579 | " name\n"); | ||
580 | retval = -ENOMEM; | ||
581 | goto err_name; | ||
582 | } | ||
976 | } | 583 | } |
977 | if ((vmeOut->xlatedAddrU) || (vmeOut->windowSizeU) | 584 | |
978 | || (vmeOut->pciBusAddrU)) { | 585 | sprintf((char *)image->pci_resource.name, "%s.%d", |
979 | return (-EINVAL); | 586 | ca91cx42_bridge->name, image->number); |
587 | |||
588 | image->pci_resource.start = 0; | ||
589 | image->pci_resource.end = (unsigned long)size; | ||
590 | image->pci_resource.flags = IORESOURCE_MEM; | ||
591 | |||
592 | retval = pci_bus_alloc_resource(pdev->bus, | ||
593 | &(image->pci_resource), size, size, PCIBIOS_MIN_MEM, | ||
594 | 0, NULL, NULL); | ||
595 | if (retval) { | ||
596 | printk(KERN_ERR "Failed to allocate mem resource for " | ||
597 | "window %d size 0x%lx start 0x%lx\n", | ||
598 | image->number, (unsigned long)size, | ||
599 | (unsigned long)image->pci_resource.start); | ||
600 | goto err_resource; | ||
980 | } | 601 | } |
981 | if ((vmeOut->xlatedAddrL & 0xFFF) || | 602 | |
982 | (vmeOut->windowSizeL & 0xFFF) || (vmeOut->pciBusAddrL & 0xFFF)) { | 603 | image->kern_base = ioremap_nocache( |
983 | return (-EINVAL); | 604 | image->pci_resource.start, size); |
605 | if (image->kern_base == NULL) { | ||
606 | printk(KERN_ERR "Failed to remap resource\n"); | ||
607 | retval = -ENOMEM; | ||
608 | goto err_remap; | ||
984 | } | 609 | } |
985 | if (vmeOut->bcastSelect2esst) { | 610 | |
986 | return (-EINVAL); | 611 | return 0; |
612 | |||
613 | iounmap(image->kern_base); | ||
614 | image->kern_base = NULL; | ||
615 | err_remap: | ||
616 | release_resource(&(image->pci_resource)); | ||
617 | err_resource: | ||
618 | kfree(image->pci_resource.name); | ||
619 | memset(&(image->pci_resource), 0, sizeof(struct resource)); | ||
620 | err_name: | ||
621 | return retval; | ||
622 | } | ||
623 | |||
624 | /* | ||
625 | * * Free and unmap PCI Resource | ||
626 | * */ | ||
627 | static void ca91cx42_free_resource(struct vme_master_resource *image) | ||
628 | { | ||
629 | iounmap(image->kern_base); | ||
630 | image->kern_base = NULL; | ||
631 | release_resource(&(image->pci_resource)); | ||
632 | kfree(image->pci_resource.name); | ||
633 | memset(&(image->pci_resource), 0, sizeof(struct resource)); | ||
634 | } | ||
635 | |||
636 | |||
637 | int ca91cx42_master_set(struct vme_master_resource *image, int enabled, | ||
638 | unsigned long long vme_base, unsigned long long size, | ||
639 | vme_address_t aspace, vme_cycle_t cycle, vme_width_t dwidth) | ||
640 | { | ||
641 | int retval = 0; | ||
642 | unsigned int i; | ||
643 | unsigned int temp_ctl = 0; | ||
644 | unsigned long long pci_bound, vme_offset, pci_base; | ||
645 | |||
646 | /* Verify input data */ | ||
647 | if (vme_base & 0xFFF) { | ||
648 | printk(KERN_ERR "Invalid VME Window alignment\n"); | ||
649 | retval = -EINVAL; | ||
650 | goto err_window; | ||
651 | } | ||
652 | if (size & 0xFFF) { | ||
653 | printk(KERN_ERR "Invalid VME Window alignment\n"); | ||
654 | retval = -EINVAL; | ||
655 | goto err_window; | ||
656 | } | ||
657 | |||
658 | spin_lock(&(image->lock)); | ||
659 | |||
660 | /* XXX We should do this much later, so that we can exit without | ||
661 | * needing to redo the mapping... | ||
662 | */ | ||
663 | /* | ||
664 | * Let's allocate the resource here rather than further up the stack as | ||
665 | * it avoids pushing loads of bus dependant stuff up the stack | ||
666 | */ | ||
667 | retval = ca91cx42_alloc_resource(image, size); | ||
668 | if (retval) { | ||
669 | spin_unlock(&(image->lock)); | ||
670 | printk(KERN_ERR "Unable to allocate memory for resource " | ||
671 | "name\n"); | ||
672 | retval = -ENOMEM; | ||
673 | goto err_res; | ||
674 | } | ||
675 | |||
676 | pci_base = (unsigned long long)image->pci_resource.start; | ||
677 | |||
678 | /* | ||
679 | * Bound address is a valid address for the window, adjust | ||
680 | * according to window granularity. | ||
681 | */ | ||
682 | pci_bound = pci_base + (size - 0x1000); | ||
683 | vme_offset = vme_base - pci_base; | ||
684 | |||
685 | i = image->number; | ||
686 | |||
687 | /* Disable while we are mucking around */ | ||
688 | temp_ctl = ioread32(ca91cx42_bridge->base + CA91CX42_LSI_CTL[i]); | ||
689 | temp_ctl &= ~CA91CX42_LSI_CTL_EN; | ||
690 | iowrite32(temp_ctl, ca91cx42_bridge->base + CA91CX42_LSI_CTL[i]); | ||
691 | |||
692 | /* XXX Prefetch stuff currently unsupported */ | ||
693 | #if 0 | ||
694 | if (vmeOut->wrPostEnable) | ||
695 | temp_ctl |= 0x40000000; | ||
696 | #endif | ||
697 | |||
698 | /* Setup cycle types */ | ||
699 | temp_ctl &= ~CA91CX42_LSI_CTL_VCT_M; | ||
700 | if (cycle & VME_BLT) | ||
701 | temp_ctl |= CA91CX42_LSI_CTL_VCT_BLT; | ||
702 | if (cycle & VME_MBLT) | ||
703 | temp_ctl |= CA91CX42_LSI_CTL_VCT_MBLT; | ||
704 | |||
705 | /* Setup data width */ | ||
706 | temp_ctl &= ~CA91CX42_LSI_CTL_VDW_M; | ||
707 | switch (dwidth) { | ||
708 | case VME_D8: | ||
709 | temp_ctl |= CA91CX42_LSI_CTL_VDW_D8; | ||
710 | break; | ||
711 | case VME_D16: | ||
712 | temp_ctl |= CA91CX42_LSI_CTL_VDW_D16; | ||
713 | break; | ||
714 | case VME_D32: | ||
715 | temp_ctl |= CA91CX42_LSI_CTL_VDW_D32; | ||
716 | break; | ||
717 | case VME_D64: | ||
718 | temp_ctl |= CA91CX42_LSI_CTL_VDW_D64; | ||
719 | break; | ||
720 | default: | ||
721 | spin_unlock(&(image->lock)); | ||
722 | printk(KERN_ERR "Invalid data width\n"); | ||
723 | retval = -EINVAL; | ||
724 | goto err_dwidth; | ||
725 | break; | ||
987 | } | 726 | } |
988 | switch (vmeOut->addrSpace) { | 727 | |
989 | case VME_A64: | 728 | /* Setup address space */ |
990 | case VME_USER3: | 729 | temp_ctl &= ~CA91CX42_LSI_CTL_VAS_M; |
991 | case VME_USER4: | 730 | switch (aspace) { |
992 | return (-EINVAL); | ||
993 | case VME_A16: | 731 | case VME_A16: |
994 | temp_ctl |= 0x00000; | 732 | temp_ctl |= CA91CX42_LSI_CTL_VAS_A16; |
995 | break; | 733 | break; |
996 | case VME_A24: | 734 | case VME_A24: |
997 | temp_ctl |= 0x10000; | 735 | temp_ctl |= CA91CX42_LSI_CTL_VAS_A24; |
998 | break; | 736 | break; |
999 | case VME_A32: | 737 | case VME_A32: |
1000 | temp_ctl |= 0x20000; | 738 | temp_ctl |= CA91CX42_LSI_CTL_VAS_A32; |
1001 | break; | 739 | break; |
1002 | case VME_CRCSR: | 740 | case VME_CRCSR: |
1003 | temp_ctl |= 0x50000; | 741 | temp_ctl |= CA91CX42_LSI_CTL_VAS_CRCSR; |
1004 | break; | 742 | break; |
1005 | case VME_USER1: | 743 | case VME_USER1: |
1006 | temp_ctl |= 0x60000; | 744 | temp_ctl |= CA91CX42_LSI_CTL_VAS_USER1; |
1007 | break; | 745 | break; |
1008 | case VME_USER2: | 746 | case VME_USER2: |
1009 | temp_ctl |= 0x70000; | 747 | temp_ctl |= CA91CX42_LSI_CTL_VAS_USER2; |
748 | break; | ||
749 | case VME_A64: | ||
750 | case VME_USER3: | ||
751 | case VME_USER4: | ||
752 | default: | ||
753 | spin_unlock(&(image->lock)); | ||
754 | printk(KERN_ERR "Invalid address space\n"); | ||
755 | retval = -EINVAL; | ||
756 | goto err_aspace; | ||
1010 | break; | 757 | break; |
1011 | } | 758 | } |
1012 | 759 | ||
1013 | // Disable while we are mucking around | 760 | temp_ctl &= ~(CA91CX42_LSI_CTL_PGM_M | CA91CX42_LSI_CTL_SUPER_M); |
1014 | writel(0x00000000, vmechip_baseaddr + outCTL[vmeOut->windowNbr]); | 761 | if (cycle & VME_SUPER) |
1015 | writel(vmeOut->pciBusAddrL, | 762 | temp_ctl |= CA91CX42_LSI_CTL_SUPER_SUPR; |
1016 | vmechip_baseaddr + outBS[vmeOut->windowNbr]); | 763 | if (cycle & VME_PROG) |
1017 | writel(vmeOut->pciBusAddrL + vmeOut->windowSizeL, | 764 | temp_ctl |= CA91CX42_LSI_CTL_PGM_PGM; |
1018 | vmechip_baseaddr + outBD[vmeOut->windowNbr]); | ||
1019 | writel(vmeOut->xlatedAddrL - vmeOut->pciBusAddrL, | ||
1020 | vmechip_baseaddr + outTO[vmeOut->windowNbr]); | ||
1021 | |||
1022 | // Sanity check. | ||
1023 | if (vmeOut->pciBusAddrL != | ||
1024 | readl(vmechip_baseaddr + outBS[vmeOut->windowNbr])) { | ||
1025 | printk(KERN_ERR | ||
1026 | "ca91c042: out window: %x, failed to configure\n", | ||
1027 | vmeOut->windowNbr); | ||
1028 | return (-EINVAL); | ||
1029 | } | ||
1030 | |||
1031 | if (vmeOut->pciBusAddrL + vmeOut->windowSizeL != | ||
1032 | readl(vmechip_baseaddr + outBD[vmeOut->windowNbr])) { | ||
1033 | printk(KERN_ERR | ||
1034 | "ca91c042: out window: %x, failed to configure\n", | ||
1035 | vmeOut->windowNbr); | ||
1036 | return (-EINVAL); | ||
1037 | } | ||
1038 | |||
1039 | if (vmeOut->xlatedAddrL - vmeOut->pciBusAddrL != | ||
1040 | readl(vmechip_baseaddr + outTO[vmeOut->windowNbr])) { | ||
1041 | printk(KERN_ERR | ||
1042 | "ca91c042: out window: %x, failed to configure\n", | ||
1043 | vmeOut->windowNbr); | ||
1044 | return (-EINVAL); | ||
1045 | } | ||
1046 | // Setup CTL register. | ||
1047 | if (vmeOut->wrPostEnable) | ||
1048 | temp_ctl |= 0x40000000; | ||
1049 | if (vmeOut->userAccessType & VME_SUPER) | ||
1050 | temp_ctl |= 0x001000; | ||
1051 | if (vmeOut->dataAccessType & VME_PROG) | ||
1052 | temp_ctl |= 0x004000; | ||
1053 | if (vmeOut->maxDataWidth == VME_D16) | ||
1054 | temp_ctl |= 0x00400000; | ||
1055 | if (vmeOut->maxDataWidth == VME_D32) | ||
1056 | temp_ctl |= 0x00800000; | ||
1057 | if (vmeOut->maxDataWidth == VME_D64) | ||
1058 | temp_ctl |= 0x00C00000; | ||
1059 | if (vmeOut->xferProtocol & (VME_BLT | VME_MBLT)) | ||
1060 | temp_ctl |= 0x00000100; | ||
1061 | 765 | ||
1062 | // Write ctl reg without enable | 766 | /* Setup mapping */ |
1063 | writel(temp_ctl, vmechip_baseaddr + outCTL[vmeOut->windowNbr]); | 767 | iowrite32(pci_base, ca91cx42_bridge->base + CA91CX42_LSI_BS[i]); |
768 | iowrite32(pci_bound, ca91cx42_bridge->base + CA91CX42_LSI_BD[i]); | ||
769 | iowrite32(vme_offset, ca91cx42_bridge->base + CA91CX42_LSI_TO[i]); | ||
1064 | 770 | ||
1065 | if (vmeOut->windowEnable) | 771 | /* Write ctl reg without enable */ |
1066 | temp_ctl |= 0x80000000; | 772 | iowrite32(temp_ctl, ca91cx42_bridge->base + CA91CX42_LSI_CTL[i]); |
1067 | 773 | ||
1068 | writel(temp_ctl, vmechip_baseaddr + outCTL[vmeOut->windowNbr]); | 774 | if (enabled) |
1069 | return (0); | 775 | temp_ctl |= CA91CX42_LSI_CTL_EN; |
776 | |||
777 | iowrite32(temp_ctl, ca91cx42_bridge->base + CA91CX42_LSI_CTL[i]); | ||
778 | |||
779 | spin_unlock(&(image->lock)); | ||
780 | return 0; | ||
781 | |||
782 | err_aspace: | ||
783 | err_dwidth: | ||
784 | ca91cx42_free_resource(image); | ||
785 | err_res: | ||
786 | err_window: | ||
787 | return retval; | ||
1070 | } | 788 | } |
1071 | 789 | ||
1072 | //----------------------------------------------------------------------------- | 790 | int __ca91cx42_master_get(struct vme_master_resource *image, int *enabled, |
1073 | // Function : uni_get_out_bound | 791 | unsigned long long *vme_base, unsigned long long *size, |
1074 | // Description: | 792 | vme_address_t *aspace, vme_cycle_t *cycle, vme_width_t *dwidth) |
1075 | //----------------------------------------------------------------------------- | ||
1076 | int uni_get_out_bound(vmeOutWindowCfg_t * vmeOut) | ||
1077 | { | 793 | { |
1078 | int temp_ctl = 0; | 794 | unsigned int i, ctl; |
795 | unsigned long long pci_base, pci_bound, vme_offset; | ||
1079 | 796 | ||
1080 | // Verify input data | 797 | i = image->number; |
1081 | if (vmeOut->windowNbr > 7) { | ||
1082 | return (-EINVAL); | ||
1083 | } | ||
1084 | // Get Window mappings. | ||
1085 | vmeOut->pciBusAddrL = | ||
1086 | readl(vmechip_baseaddr + outBS[vmeOut->windowNbr]); | ||
1087 | vmeOut->xlatedAddrL = | ||
1088 | vmeOut->pciBusAddrL + readl(vmechip_baseaddr + | ||
1089 | outTO[vmeOut->windowNbr]); | ||
1090 | vmeOut->windowSizeL = | ||
1091 | readl(vmechip_baseaddr + outBD[vmeOut->windowNbr]) - | ||
1092 | vmeOut->pciBusAddrL; | ||
1093 | 798 | ||
1094 | temp_ctl = readl(vmechip_baseaddr + outCTL[vmeOut->windowNbr]); | 799 | ctl = ioread32(ca91cx42_bridge->base + CA91CX42_LSI_CTL[i]); |
1095 | 800 | ||
1096 | // Get Control & BUS attributes | 801 | pci_base = ioread32(ca91cx42_bridge->base + CA91CX42_LSI_BS[i]); |
1097 | if (temp_ctl & 0x40000000) | 802 | vme_offset = ioread32(ca91cx42_bridge->base + CA91CX42_LSI_TO[i]); |
1098 | vmeOut->wrPostEnable = 1; | 803 | pci_bound = ioread32(ca91cx42_bridge->base + CA91CX42_LSI_BD[i]); |
1099 | if (temp_ctl & 0x001000) | 804 | |
1100 | vmeOut->userAccessType = VME_SUPER; | 805 | *vme_base = pci_base + vme_offset; |
1101 | else | 806 | *size = (pci_bound - pci_base) + 0x1000; |
1102 | vmeOut->userAccessType = VME_USER; | ||
1103 | if (temp_ctl & 0x004000) | ||
1104 | vmeOut->dataAccessType = VME_PROG; | ||
1105 | else | ||
1106 | vmeOut->dataAccessType = VME_DATA; | ||
1107 | if (temp_ctl & 0x80000000) | ||
1108 | vmeOut->windowEnable = 1; | ||
1109 | 807 | ||
1110 | switch ((temp_ctl & 0x00C00000) >> 22) { | 808 | *enabled = 0; |
1111 | case 0: | 809 | *aspace = 0; |
1112 | vmeOut->maxDataWidth = VME_D8; | 810 | *cycle = 0; |
811 | *dwidth = 0; | ||
812 | |||
813 | if (ctl & CA91CX42_LSI_CTL_EN) | ||
814 | *enabled = 1; | ||
815 | |||
816 | /* Setup address space */ | ||
817 | switch (ctl & CA91CX42_LSI_CTL_VAS_M) { | ||
818 | case CA91CX42_LSI_CTL_VAS_A16: | ||
819 | *aspace = VME_A16; | ||
820 | break; | ||
821 | case CA91CX42_LSI_CTL_VAS_A24: | ||
822 | *aspace = VME_A24; | ||
823 | break; | ||
824 | case CA91CX42_LSI_CTL_VAS_A32: | ||
825 | *aspace = VME_A32; | ||
1113 | break; | 826 | break; |
1114 | case 1: | 827 | case CA91CX42_LSI_CTL_VAS_CRCSR: |
1115 | vmeOut->maxDataWidth = VME_D16; | 828 | *aspace = VME_CRCSR; |
1116 | break; | 829 | break; |
1117 | case 2: | 830 | case CA91CX42_LSI_CTL_VAS_USER1: |
1118 | vmeOut->maxDataWidth = VME_D32; | 831 | *aspace = VME_USER1; |
1119 | break; | 832 | break; |
1120 | case 3: | 833 | case CA91CX42_LSI_CTL_VAS_USER2: |
1121 | vmeOut->maxDataWidth = VME_D64; | 834 | *aspace = VME_USER2; |
1122 | break; | 835 | break; |
1123 | } | 836 | } |
1124 | if (temp_ctl & 0x00000100) | 837 | |
1125 | vmeOut->xferProtocol = VME_BLT; | 838 | /* XXX Not sure howto check for MBLT */ |
839 | /* Setup cycle types */ | ||
840 | if (ctl & CA91CX42_LSI_CTL_VCT_BLT) | ||
841 | *cycle |= VME_BLT; | ||
1126 | else | 842 | else |
1127 | vmeOut->xferProtocol = VME_SCT; | 843 | *cycle |= VME_SCT; |
1128 | 844 | ||
1129 | switch ((temp_ctl & 0x70000) >> 16) { | 845 | if (ctl & CA91CX42_LSI_CTL_SUPER_SUPR) |
1130 | case 0x0: | 846 | *cycle |= VME_SUPER; |
1131 | vmeOut->addrSpace = VME_A16; | 847 | else |
1132 | break; | 848 | *cycle |= VME_USER; |
1133 | case 0x1: | 849 | |
1134 | vmeOut->addrSpace = VME_A24; | 850 | if (ctl & CA91CX42_LSI_CTL_PGM_PGM) |
1135 | break; | 851 | *cycle = VME_PROG; |
1136 | case 0x2: | 852 | else |
1137 | vmeOut->addrSpace = VME_A32; | 853 | *cycle = VME_DATA; |
854 | |||
855 | /* Setup data width */ | ||
856 | switch (ctl & CA91CX42_LSI_CTL_VDW_M) { | ||
857 | case CA91CX42_LSI_CTL_VDW_D8: | ||
858 | *dwidth = VME_D8; | ||
1138 | break; | 859 | break; |
1139 | case 0x5: | 860 | case CA91CX42_LSI_CTL_VDW_D16: |
1140 | vmeOut->addrSpace = VME_CRCSR; | 861 | *dwidth = VME_D16; |
1141 | break; | 862 | break; |
1142 | case 0x6: | 863 | case CA91CX42_LSI_CTL_VDW_D32: |
1143 | vmeOut->addrSpace = VME_USER1; | 864 | *dwidth = VME_D32; |
1144 | break; | 865 | break; |
1145 | case 0x7: | 866 | case CA91CX42_LSI_CTL_VDW_D64: |
1146 | vmeOut->addrSpace = VME_USER2; | 867 | *dwidth = VME_D64; |
1147 | break; | 868 | break; |
1148 | } | 869 | } |
1149 | 870 | ||
1150 | return (0); | 871 | /* XXX Prefetch stuff currently unsupported */ |
872 | #if 0 | ||
873 | if (ctl & 0x40000000) | ||
874 | vmeOut->wrPostEnable = 1; | ||
875 | #endif | ||
876 | |||
877 | return 0; | ||
1151 | } | 878 | } |
1152 | 879 | ||
1153 | //----------------------------------------------------------------------------- | 880 | int ca91cx42_master_get(struct vme_master_resource *image, int *enabled, |
1154 | // Function : uni_setup_lm | 881 | unsigned long long *vme_base, unsigned long long *size, |
1155 | // Description: | 882 | vme_address_t *aspace, vme_cycle_t *cycle, vme_width_t *dwidth) |
1156 | //----------------------------------------------------------------------------- | ||
1157 | int uni_setup_lm(vmeLmCfg_t * vmeLm) | ||
1158 | { | 883 | { |
1159 | int temp_ctl = 0; | 884 | int retval; |
885 | |||
886 | spin_lock(&(image->lock)); | ||
887 | |||
888 | retval = __ca91cx42_master_get(image, enabled, vme_base, size, aspace, | ||
889 | cycle, dwidth); | ||
890 | |||
891 | spin_unlock(&(image->lock)); | ||
892 | |||
893 | return retval; | ||
894 | } | ||
895 | |||
896 | ssize_t ca91cx42_master_read(struct vme_master_resource *image, void *buf, | ||
897 | size_t count, loff_t offset) | ||
898 | { | ||
899 | int retval; | ||
900 | |||
901 | spin_lock(&(image->lock)); | ||
902 | |||
903 | memcpy_fromio(buf, image->kern_base + offset, (unsigned int)count); | ||
904 | retval = count; | ||
1160 | 905 | ||
1161 | if (vmeLm->addrU) { | 906 | spin_unlock(&(image->lock)); |
1162 | return (-EINVAL); | 907 | |
908 | return retval; | ||
909 | } | ||
910 | |||
911 | ssize_t ca91cx42_master_write(struct vme_master_resource *image, void *buf, | ||
912 | size_t count, loff_t offset) | ||
913 | { | ||
914 | int retval = 0; | ||
915 | |||
916 | spin_lock(&(image->lock)); | ||
917 | |||
918 | memcpy_toio(image->kern_base + offset, buf, (unsigned int)count); | ||
919 | retval = count; | ||
920 | |||
921 | spin_unlock(&(image->lock)); | ||
922 | |||
923 | return retval; | ||
924 | } | ||
925 | |||
926 | int ca91cx42_slot_get(void) | ||
927 | { | ||
928 | u32 slot = 0; | ||
929 | |||
930 | slot = ioread32(ca91cx42_bridge->base + VCSR_BS); | ||
931 | slot = ((slot & CA91CX42_VCSR_BS_SLOT_M) >> 27); | ||
932 | return (int)slot; | ||
933 | |||
934 | } | ||
935 | |||
936 | static int __init ca91cx42_init(void) | ||
937 | { | ||
938 | return pci_register_driver(&ca91cx42_driver); | ||
939 | } | ||
940 | |||
941 | /* | ||
942 | * Configure CR/CSR space | ||
943 | * | ||
944 | * Access to the CR/CSR can be configured at power-up. The location of the | ||
945 | * CR/CSR registers in the CR/CSR address space is determined by the boards | ||
946 | * Auto-ID or Geographic address. This function ensures that the window is | ||
947 | * enabled at an offset consistent with the boards geopgraphic address. | ||
948 | */ | ||
949 | static int ca91cx42_crcsr_init(struct pci_dev *pdev) | ||
950 | { | ||
951 | unsigned int crcsr_addr; | ||
952 | int tmp, slot; | ||
953 | |||
954 | /* XXX We may need to set this somehow as the Universe II does not support | ||
955 | * geographical addressing. | ||
956 | */ | ||
957 | #if 0 | ||
958 | if (vme_slotnum != -1) | ||
959 | iowrite32(vme_slotnum << 27, ca91cx42_bridge->base + VCSR_BS); | ||
960 | #endif | ||
961 | slot = ca91cx42_slot_get(); | ||
962 | dev_info(&pdev->dev, "CR/CSR Offset: %d\n", slot); | ||
963 | if (slot == 0) { | ||
964 | dev_err(&pdev->dev, "Slot number is unset, not configuring " | ||
965 | "CR/CSR space\n"); | ||
966 | return -EINVAL; | ||
1163 | } | 967 | } |
1164 | switch (vmeLm->addrSpace) { | 968 | |
1165 | case VME_A64: | 969 | /* Allocate mem for CR/CSR image */ |
1166 | case VME_USER3: | 970 | crcsr_kernel = pci_alloc_consistent(pdev, VME_CRCSR_BUF_SIZE, |
1167 | case VME_USER4: | 971 | &crcsr_bus); |
1168 | return (-EINVAL); | 972 | if (crcsr_kernel == NULL) { |
1169 | case VME_A16: | 973 | dev_err(&pdev->dev, "Failed to allocate memory for CR/CSR " |
1170 | temp_ctl |= 0x00000; | 974 | "image\n"); |
1171 | break; | 975 | return -ENOMEM; |
1172 | case VME_A24: | ||
1173 | temp_ctl |= 0x10000; | ||
1174 | break; | ||
1175 | case VME_A32: | ||
1176 | temp_ctl |= 0x20000; | ||
1177 | break; | ||
1178 | case VME_CRCSR: | ||
1179 | temp_ctl |= 0x50000; | ||
1180 | break; | ||
1181 | case VME_USER1: | ||
1182 | temp_ctl |= 0x60000; | ||
1183 | break; | ||
1184 | case VME_USER2: | ||
1185 | temp_ctl |= 0x70000; | ||
1186 | break; | ||
1187 | } | 976 | } |
1188 | 977 | ||
1189 | // Disable while we are mucking around | 978 | memset(crcsr_kernel, 0, VME_CRCSR_BUF_SIZE); |
1190 | writel(0x00000000, vmechip_baseaddr + LM_CTL); | ||
1191 | 979 | ||
1192 | writel(vmeLm->addr, vmechip_baseaddr + LM_BS); | 980 | crcsr_addr = slot * (512 * 1024); |
981 | iowrite32(crcsr_bus - crcsr_addr, ca91cx42_bridge->base + VCSR_TO); | ||
1193 | 982 | ||
1194 | // Setup CTL register. | 983 | tmp = ioread32(ca91cx42_bridge->base + VCSR_CTL); |
1195 | if (vmeLm->userAccessType & VME_SUPER) | 984 | tmp |= CA91CX42_VCSR_CTL_EN; |
1196 | temp_ctl |= 0x00200000; | 985 | iowrite32(tmp, ca91cx42_bridge->base + VCSR_CTL); |
1197 | if (vmeLm->userAccessType & VME_USER) | 986 | |
1198 | temp_ctl |= 0x00100000; | 987 | return 0; |
1199 | if (vmeLm->dataAccessType & VME_PROG) | 988 | } |
1200 | temp_ctl |= 0x00800000; | 989 | |
1201 | if (vmeLm->dataAccessType & VME_DATA) | 990 | static void ca91cx42_crcsr_exit(struct pci_dev *pdev) |
1202 | temp_ctl |= 0x00400000; | 991 | { |
992 | u32 tmp; | ||
1203 | 993 | ||
1204 | uni_lm_event = 0; | 994 | /* Turn off CR/CSR space */ |
995 | tmp = ioread32(ca91cx42_bridge->base + VCSR_CTL); | ||
996 | tmp &= ~CA91CX42_VCSR_CTL_EN; | ||
997 | iowrite32(tmp, ca91cx42_bridge->base + VCSR_CTL); | ||
1205 | 998 | ||
1206 | // Write ctl reg and enable | 999 | /* Free image */ |
1207 | writel(0x80000000 | temp_ctl, vmechip_baseaddr + LM_CTL); | 1000 | iowrite32(0, ca91cx42_bridge->base + VCSR_TO); |
1208 | temp_ctl = readl(vmechip_baseaddr + LM_CTL); | ||
1209 | 1001 | ||
1210 | return (0); | 1002 | pci_free_consistent(pdev, VME_CRCSR_BUF_SIZE, crcsr_kernel, crcsr_bus); |
1211 | } | 1003 | } |
1212 | 1004 | ||
1213 | //----------------------------------------------------------------------------- | 1005 | static int ca91cx42_probe(struct pci_dev *pdev, const struct pci_device_id *id) |
1214 | // Function : uni_wait_lm | ||
1215 | // Description: | ||
1216 | //----------------------------------------------------------------------------- | ||
1217 | int uni_wait_lm(vmeLmCfg_t * vmeLm) | ||
1218 | { | 1006 | { |
1219 | unsigned long flags; | 1007 | int retval, i; |
1220 | unsigned int tmp; | 1008 | u32 data; |
1009 | struct list_head *pos = NULL; | ||
1010 | struct vme_master_resource *master_image; | ||
1011 | struct vme_slave_resource *slave_image; | ||
1012 | #if 0 | ||
1013 | struct vme_dma_resource *dma_ctrlr; | ||
1014 | #endif | ||
1015 | struct vme_lm_resource *lm; | ||
1016 | |||
1017 | /* We want to support more than one of each bridge so we need to | ||
1018 | * dynamically allocate the bridge structure | ||
1019 | */ | ||
1020 | ca91cx42_bridge = kmalloc(sizeof(struct vme_bridge), GFP_KERNEL); | ||
1021 | |||
1022 | if (ca91cx42_bridge == NULL) { | ||
1023 | dev_err(&pdev->dev, "Failed to allocate memory for device " | ||
1024 | "structure\n"); | ||
1025 | retval = -ENOMEM; | ||
1026 | goto err_struct; | ||
1027 | } | ||
1028 | |||
1029 | memset(ca91cx42_bridge, 0, sizeof(struct vme_bridge)); | ||
1030 | |||
1031 | /* Enable the device */ | ||
1032 | retval = pci_enable_device(pdev); | ||
1033 | if (retval) { | ||
1034 | dev_err(&pdev->dev, "Unable to enable device\n"); | ||
1035 | goto err_enable; | ||
1036 | } | ||
1037 | |||
1038 | /* Map Registers */ | ||
1039 | retval = pci_request_regions(pdev, driver_name); | ||
1040 | if (retval) { | ||
1041 | dev_err(&pdev->dev, "Unable to reserve resources\n"); | ||
1042 | goto err_resource; | ||
1043 | } | ||
1044 | |||
1045 | /* map registers in BAR 0 */ | ||
1046 | ca91cx42_bridge->base = ioremap_nocache(pci_resource_start(pdev, 0), | ||
1047 | 4096); | ||
1048 | if (!ca91cx42_bridge->base) { | ||
1049 | dev_err(&pdev->dev, "Unable to remap CRG region\n"); | ||
1050 | retval = -EIO; | ||
1051 | goto err_remap; | ||
1052 | } | ||
1053 | |||
1054 | /* Check to see if the mapping worked out */ | ||
1055 | data = ioread32(ca91cx42_bridge->base + CA91CX42_PCI_ID) & 0x0000FFFF; | ||
1056 | if (data != PCI_VENDOR_ID_TUNDRA) { | ||
1057 | dev_err(&pdev->dev, "PCI_ID check failed\n"); | ||
1058 | retval = -EIO; | ||
1059 | goto err_test; | ||
1060 | } | ||
1061 | |||
1062 | /* Initialize wait queues & mutual exclusion flags */ | ||
1063 | /* XXX These need to be moved to the vme_bridge structure */ | ||
1064 | init_waitqueue_head(&dma_queue); | ||
1065 | init_waitqueue_head(&iack_queue); | ||
1066 | mutex_init(&(vme_int)); | ||
1067 | mutex_init(&(vme_irq)); | ||
1068 | mutex_init(&(vme_rmw)); | ||
1069 | |||
1070 | ca91cx42_bridge->parent = &(pdev->dev); | ||
1071 | strcpy(ca91cx42_bridge->name, driver_name); | ||
1072 | |||
1073 | /* Setup IRQ */ | ||
1074 | retval = ca91cx42_irq_init(ca91cx42_bridge); | ||
1075 | if (retval != 0) { | ||
1076 | dev_err(&pdev->dev, "Chip Initialization failed.\n"); | ||
1077 | goto err_irq; | ||
1078 | } | ||
1079 | |||
1080 | /* Add master windows to list */ | ||
1081 | INIT_LIST_HEAD(&(ca91cx42_bridge->master_resources)); | ||
1082 | for (i = 0; i < CA91C142_MAX_MASTER; i++) { | ||
1083 | master_image = kmalloc(sizeof(struct vme_master_resource), | ||
1084 | GFP_KERNEL); | ||
1085 | if (master_image == NULL) { | ||
1086 | dev_err(&pdev->dev, "Failed to allocate memory for " | ||
1087 | "master resource structure\n"); | ||
1088 | retval = -ENOMEM; | ||
1089 | goto err_master; | ||
1090 | } | ||
1091 | master_image->parent = ca91cx42_bridge; | ||
1092 | spin_lock_init(&(master_image->lock)); | ||
1093 | master_image->locked = 0; | ||
1094 | master_image->number = i; | ||
1095 | master_image->address_attr = VME_A16 | VME_A24 | VME_A32 | | ||
1096 | VME_CRCSR | VME_USER1 | VME_USER2; | ||
1097 | master_image->cycle_attr = VME_SCT | VME_BLT | VME_MBLT | | ||
1098 | VME_SUPER | VME_USER | VME_PROG | VME_DATA; | ||
1099 | master_image->width_attr = VME_D8 | VME_D16 | VME_D32 | VME_D64; | ||
1100 | memset(&(master_image->pci_resource), 0, | ||
1101 | sizeof(struct resource)); | ||
1102 | master_image->kern_base = NULL; | ||
1103 | list_add_tail(&(master_image->list), | ||
1104 | &(ca91cx42_bridge->master_resources)); | ||
1105 | } | ||
1106 | |||
1107 | /* Add slave windows to list */ | ||
1108 | INIT_LIST_HEAD(&(ca91cx42_bridge->slave_resources)); | ||
1109 | for (i = 0; i < CA91C142_MAX_SLAVE; i++) { | ||
1110 | slave_image = kmalloc(sizeof(struct vme_slave_resource), | ||
1111 | GFP_KERNEL); | ||
1112 | if (slave_image == NULL) { | ||
1113 | dev_err(&pdev->dev, "Failed to allocate memory for " | ||
1114 | "slave resource structure\n"); | ||
1115 | retval = -ENOMEM; | ||
1116 | goto err_slave; | ||
1117 | } | ||
1118 | slave_image->parent = ca91cx42_bridge; | ||
1119 | mutex_init(&(slave_image->mtx)); | ||
1120 | slave_image->locked = 0; | ||
1121 | slave_image->number = i; | ||
1122 | slave_image->address_attr = VME_A24 | VME_A32 | VME_USER1 | | ||
1123 | VME_USER2; | ||
1124 | |||
1125 | /* Only windows 0 and 4 support A16 */ | ||
1126 | if (i == 0 || i == 4) | ||
1127 | slave_image->address_attr |= VME_A16; | ||
1128 | |||
1129 | slave_image->cycle_attr = VME_SCT | VME_BLT | VME_MBLT | | ||
1130 | VME_SUPER | VME_USER | VME_PROG | VME_DATA; | ||
1131 | list_add_tail(&(slave_image->list), | ||
1132 | &(ca91cx42_bridge->slave_resources)); | ||
1133 | } | ||
1134 | #if 0 | ||
1135 | /* Add dma engines to list */ | ||
1136 | INIT_LIST_HEAD(&(ca91cx42_bridge->dma_resources)); | ||
1137 | for (i = 0; i < CA91C142_MAX_DMA; i++) { | ||
1138 | dma_ctrlr = kmalloc(sizeof(struct vme_dma_resource), | ||
1139 | GFP_KERNEL); | ||
1140 | if (dma_ctrlr == NULL) { | ||
1141 | dev_err(&pdev->dev, "Failed to allocate memory for " | ||
1142 | "dma resource structure\n"); | ||
1143 | retval = -ENOMEM; | ||
1144 | goto err_dma; | ||
1145 | } | ||
1146 | dma_ctrlr->parent = ca91cx42_bridge; | ||
1147 | mutex_init(&(dma_ctrlr->mtx)); | ||
1148 | dma_ctrlr->locked = 0; | ||
1149 | dma_ctrlr->number = i; | ||
1150 | INIT_LIST_HEAD(&(dma_ctrlr->pending)); | ||
1151 | INIT_LIST_HEAD(&(dma_ctrlr->running)); | ||
1152 | list_add_tail(&(dma_ctrlr->list), | ||
1153 | &(ca91cx42_bridge->dma_resources)); | ||
1154 | } | ||
1155 | #endif | ||
1156 | /* Add location monitor to list */ | ||
1157 | INIT_LIST_HEAD(&(ca91cx42_bridge->lm_resources)); | ||
1158 | lm = kmalloc(sizeof(struct vme_lm_resource), GFP_KERNEL); | ||
1159 | if (lm == NULL) { | ||
1160 | dev_err(&pdev->dev, "Failed to allocate memory for " | ||
1161 | "location monitor resource structure\n"); | ||
1162 | retval = -ENOMEM; | ||
1163 | goto err_lm; | ||
1164 | } | ||
1165 | lm->parent = ca91cx42_bridge; | ||
1166 | mutex_init(&(lm->mtx)); | ||
1167 | lm->locked = 0; | ||
1168 | lm->number = 1; | ||
1169 | lm->monitors = 4; | ||
1170 | list_add_tail(&(lm->list), &(ca91cx42_bridge->lm_resources)); | ||
1171 | |||
1172 | ca91cx42_bridge->slave_get = ca91cx42_slave_get; | ||
1173 | ca91cx42_bridge->slave_set = ca91cx42_slave_set; | ||
1174 | ca91cx42_bridge->master_get = ca91cx42_master_get; | ||
1175 | ca91cx42_bridge->master_set = ca91cx42_master_set; | ||
1176 | ca91cx42_bridge->master_read = ca91cx42_master_read; | ||
1177 | ca91cx42_bridge->master_write = ca91cx42_master_write; | ||
1178 | #if 0 | ||
1179 | ca91cx42_bridge->master_rmw = ca91cx42_master_rmw; | ||
1180 | ca91cx42_bridge->dma_list_add = ca91cx42_dma_list_add; | ||
1181 | ca91cx42_bridge->dma_list_exec = ca91cx42_dma_list_exec; | ||
1182 | ca91cx42_bridge->dma_list_empty = ca91cx42_dma_list_empty; | ||
1183 | #endif | ||
1184 | ca91cx42_bridge->request_irq = ca91cx42_request_irq; | ||
1185 | ca91cx42_bridge->free_irq = ca91cx42_free_irq; | ||
1186 | ca91cx42_bridge->generate_irq = ca91cx42_generate_irq; | ||
1187 | #if 0 | ||
1188 | ca91cx42_bridge->lm_set = ca91cx42_lm_set; | ||
1189 | ca91cx42_bridge->lm_get = ca91cx42_lm_get; | ||
1190 | ca91cx42_bridge->lm_attach = ca91cx42_lm_attach; | ||
1191 | ca91cx42_bridge->lm_detach = ca91cx42_lm_detach; | ||
1192 | #endif | ||
1193 | ca91cx42_bridge->slot_get = ca91cx42_slot_get; | ||
1194 | |||
1195 | data = ioread32(ca91cx42_bridge->base + MISC_CTL); | ||
1196 | dev_info(&pdev->dev, "Board is%s the VME system controller\n", | ||
1197 | (data & CA91CX42_MISC_CTL_SYSCON) ? "" : " not"); | ||
1198 | dev_info(&pdev->dev, "Slot ID is %d\n", ca91cx42_slot_get()); | ||
1199 | |||
1200 | if (ca91cx42_crcsr_init(pdev)) { | ||
1201 | dev_err(&pdev->dev, "CR/CSR configuration failed.\n"); | ||
1202 | retval = -EINVAL; | ||
1203 | #if 0 | ||
1204 | goto err_crcsr; | ||
1205 | #endif | ||
1206 | } | ||
1221 | 1207 | ||
1222 | spin_lock_irqsave(&lm_lock, flags); | 1208 | /* Need to save ca91cx42_bridge pointer locally in link list for use in |
1223 | tmp = uni_lm_event; | 1209 | * ca91cx42_remove() |
1224 | spin_unlock_irqrestore(&lm_lock, flags); | 1210 | */ |
1225 | if (tmp == 0) { | 1211 | retval = vme_register_bridge(ca91cx42_bridge); |
1226 | if (vmeLm->lmWait < 10) | 1212 | if (retval != 0) { |
1227 | vmeLm->lmWait = 10; | 1213 | dev_err(&pdev->dev, "Chip Registration failed.\n"); |
1228 | interruptible_sleep_on_timeout(&lm_queue, vmeLm->lmWait); | 1214 | goto err_reg; |
1215 | } | ||
1216 | |||
1217 | return 0; | ||
1218 | |||
1219 | vme_unregister_bridge(ca91cx42_bridge); | ||
1220 | err_reg: | ||
1221 | ca91cx42_crcsr_exit(pdev); | ||
1222 | err_crcsr: | ||
1223 | err_lm: | ||
1224 | /* resources are stored in link list */ | ||
1225 | list_for_each(pos, &(ca91cx42_bridge->lm_resources)) { | ||
1226 | lm = list_entry(pos, struct vme_lm_resource, list); | ||
1227 | list_del(pos); | ||
1228 | kfree(lm); | ||
1229 | } | ||
1230 | #if 0 | ||
1231 | err_dma: | ||
1232 | /* resources are stored in link list */ | ||
1233 | list_for_each(pos, &(ca91cx42_bridge->dma_resources)) { | ||
1234 | dma_ctrlr = list_entry(pos, struct vme_dma_resource, list); | ||
1235 | list_del(pos); | ||
1236 | kfree(dma_ctrlr); | ||
1237 | } | ||
1238 | #endif | ||
1239 | err_slave: | ||
1240 | /* resources are stored in link list */ | ||
1241 | list_for_each(pos, &(ca91cx42_bridge->slave_resources)) { | ||
1242 | slave_image = list_entry(pos, struct vme_slave_resource, list); | ||
1243 | list_del(pos); | ||
1244 | kfree(slave_image); | ||
1245 | } | ||
1246 | err_master: | ||
1247 | /* resources are stored in link list */ | ||
1248 | list_for_each(pos, &(ca91cx42_bridge->master_resources)) { | ||
1249 | master_image = list_entry(pos, struct vme_master_resource, | ||
1250 | list); | ||
1251 | list_del(pos); | ||
1252 | kfree(master_image); | ||
1253 | } | ||
1254 | |||
1255 | ca91cx42_irq_exit(pdev); | ||
1256 | err_irq: | ||
1257 | err_test: | ||
1258 | iounmap(ca91cx42_bridge->base); | ||
1259 | err_remap: | ||
1260 | pci_release_regions(pdev); | ||
1261 | err_resource: | ||
1262 | pci_disable_device(pdev); | ||
1263 | err_enable: | ||
1264 | kfree(ca91cx42_bridge); | ||
1265 | err_struct: | ||
1266 | return retval; | ||
1267 | |||
1268 | } | ||
1269 | |||
1270 | void ca91cx42_remove(struct pci_dev *pdev) | ||
1271 | { | ||
1272 | struct list_head *pos = NULL; | ||
1273 | struct vme_master_resource *master_image; | ||
1274 | struct vme_slave_resource *slave_image; | ||
1275 | struct vme_dma_resource *dma_ctrlr; | ||
1276 | struct vme_lm_resource *lm; | ||
1277 | int i; | ||
1278 | |||
1279 | /* Turn off Ints */ | ||
1280 | iowrite32(0, ca91cx42_bridge->base + LINT_EN); | ||
1281 | |||
1282 | /* Turn off the windows */ | ||
1283 | iowrite32(0x00800000, ca91cx42_bridge->base + LSI0_CTL); | ||
1284 | iowrite32(0x00800000, ca91cx42_bridge->base + LSI1_CTL); | ||
1285 | iowrite32(0x00800000, ca91cx42_bridge->base + LSI2_CTL); | ||
1286 | iowrite32(0x00800000, ca91cx42_bridge->base + LSI3_CTL); | ||
1287 | iowrite32(0x00800000, ca91cx42_bridge->base + LSI4_CTL); | ||
1288 | iowrite32(0x00800000, ca91cx42_bridge->base + LSI5_CTL); | ||
1289 | iowrite32(0x00800000, ca91cx42_bridge->base + LSI6_CTL); | ||
1290 | iowrite32(0x00800000, ca91cx42_bridge->base + LSI7_CTL); | ||
1291 | iowrite32(0x00F00000, ca91cx42_bridge->base + VSI0_CTL); | ||
1292 | iowrite32(0x00F00000, ca91cx42_bridge->base + VSI1_CTL); | ||
1293 | iowrite32(0x00F00000, ca91cx42_bridge->base + VSI2_CTL); | ||
1294 | iowrite32(0x00F00000, ca91cx42_bridge->base + VSI3_CTL); | ||
1295 | iowrite32(0x00F00000, ca91cx42_bridge->base + VSI4_CTL); | ||
1296 | iowrite32(0x00F00000, ca91cx42_bridge->base + VSI5_CTL); | ||
1297 | iowrite32(0x00F00000, ca91cx42_bridge->base + VSI6_CTL); | ||
1298 | iowrite32(0x00F00000, ca91cx42_bridge->base + VSI7_CTL); | ||
1299 | |||
1300 | vme_unregister_bridge(ca91cx42_bridge); | ||
1301 | #if 0 | ||
1302 | ca91cx42_crcsr_exit(pdev); | ||
1303 | #endif | ||
1304 | /* resources are stored in link list */ | ||
1305 | list_for_each(pos, &(ca91cx42_bridge->lm_resources)) { | ||
1306 | lm = list_entry(pos, struct vme_lm_resource, list); | ||
1307 | list_del(pos); | ||
1308 | kfree(lm); | ||
1309 | } | ||
1310 | |||
1311 | /* resources are stored in link list */ | ||
1312 | list_for_each(pos, &(ca91cx42_bridge->dma_resources)) { | ||
1313 | dma_ctrlr = list_entry(pos, struct vme_dma_resource, list); | ||
1314 | list_del(pos); | ||
1315 | kfree(dma_ctrlr); | ||
1229 | } | 1316 | } |
1230 | writel(0x00000000, vmechip_baseaddr + LM_CTL); | ||
1231 | vmeLm->lmEvents = uni_lm_event; | ||
1232 | 1317 | ||
1233 | return (0); | 1318 | /* resources are stored in link list */ |
1319 | list_for_each(pos, &(ca91cx42_bridge->slave_resources)) { | ||
1320 | slave_image = list_entry(pos, struct vme_slave_resource, list); | ||
1321 | list_del(pos); | ||
1322 | kfree(slave_image); | ||
1323 | } | ||
1324 | |||
1325 | /* resources are stored in link list */ | ||
1326 | list_for_each(pos, &(ca91cx42_bridge->master_resources)) { | ||
1327 | master_image = list_entry(pos, struct vme_master_resource, | ||
1328 | list); | ||
1329 | list_del(pos); | ||
1330 | kfree(master_image); | ||
1331 | } | ||
1332 | |||
1333 | ca91cx42_irq_exit(pdev); | ||
1334 | |||
1335 | iounmap(ca91cx42_bridge->base); | ||
1336 | |||
1337 | pci_release_regions(pdev); | ||
1338 | |||
1339 | pci_disable_device(pdev); | ||
1340 | |||
1341 | kfree(ca91cx42_bridge); | ||
1234 | } | 1342 | } |
1235 | 1343 | ||
1344 | static void __exit ca91cx42_exit(void) | ||
1345 | { | ||
1346 | pci_unregister_driver(&ca91cx42_driver); | ||
1347 | } | ||
1348 | |||
1349 | MODULE_DESCRIPTION("VME driver for the Tundra Universe II VME bridge"); | ||
1350 | MODULE_LICENSE("GPL"); | ||
1351 | |||
1352 | module_init(ca91cx42_init); | ||
1353 | module_exit(ca91cx42_exit); | ||
1354 | |||
1355 | /*---------------------------------------------------------------------------- | ||
1356 | * STAGING | ||
1357 | *--------------------------------------------------------------------------*/ | ||
1358 | |||
1359 | #if 0 | ||
1236 | #define SWIZZLE(X) ( ((X & 0xFF000000) >> 24) | ((X & 0x00FF0000) >> 8) | ((X & 0x0000FF00) << 8) | ((X & 0x000000FF) << 24)) | 1360 | #define SWIZZLE(X) ( ((X & 0xFF000000) >> 24) | ((X & 0x00FF0000) >> 8) | ((X & 0x0000FF00) << 8) | ((X & 0x000000FF) << 24)) |
1237 | 1361 | ||
1238 | //----------------------------------------------------------------------------- | 1362 | int ca91cx42_master_rmw(vmeRmwCfg_t *vmeRmw) |
1239 | // Function : uni_do_rmw | ||
1240 | // Description: | ||
1241 | //----------------------------------------------------------------------------- | ||
1242 | int uni_do_rmw(vmeRmwCfg_t * vmeRmw) | ||
1243 | { | 1363 | { |
1244 | int temp_ctl = 0; | 1364 | int temp_ctl = 0; |
1245 | int tempBS = 0; | 1365 | int tempBS = 0; |
@@ -1252,26 +1372,27 @@ int uni_do_rmw(vmeRmwCfg_t * vmeRmw) | |||
1252 | int i; | 1372 | int i; |
1253 | vmeOutWindowCfg_t vmeOut; | 1373 | vmeOutWindowCfg_t vmeOut; |
1254 | if (vmeRmw->maxAttempts < 1) { | 1374 | if (vmeRmw->maxAttempts < 1) { |
1255 | return (-EINVAL); | 1375 | return -EINVAL; |
1256 | } | 1376 | } |
1257 | if (vmeRmw->targetAddrU) { | 1377 | if (vmeRmw->targetAddrU) { |
1258 | return (-EINVAL); | 1378 | return -EINVAL; |
1259 | } | 1379 | } |
1260 | // Find the PCI address that maps to the desired VME address | 1380 | /* Find the PCI address that maps to the desired VME address */ |
1261 | for (i = 0; i < 8; i++) { | 1381 | for (i = 0; i < 8; i++) { |
1262 | temp_ctl = readl(vmechip_baseaddr + outCTL[i]); | 1382 | temp_ctl = ioread32(ca91cx42_bridge->base + |
1383 | CA91CX42_LSI_CTL[i]); | ||
1263 | if ((temp_ctl & 0x80000000) == 0) { | 1384 | if ((temp_ctl & 0x80000000) == 0) { |
1264 | continue; | 1385 | continue; |
1265 | } | 1386 | } |
1266 | memset(&vmeOut, 0, sizeof(vmeOut)); | 1387 | memset(&vmeOut, 0, sizeof(vmeOut)); |
1267 | vmeOut.windowNbr = i; | 1388 | vmeOut.windowNbr = i; |
1268 | uni_get_out_bound(&vmeOut); | 1389 | ca91cx42_get_out_bound(&vmeOut); |
1269 | if (vmeOut.addrSpace != vmeRmw->addrSpace) { | 1390 | if (vmeOut.addrSpace != vmeRmw->addrSpace) { |
1270 | continue; | 1391 | continue; |
1271 | } | 1392 | } |
1272 | tempBS = readl(vmechip_baseaddr + outBS[i]); | 1393 | tempBS = ioread32(ca91cx42_bridge->base + CA91CX42_LSI_BS[i]); |
1273 | tempBD = readl(vmechip_baseaddr + outBD[i]); | 1394 | tempBD = ioread32(ca91cx42_bridge->base + CA91CX42_LSI_BD[i]); |
1274 | tempTO = readl(vmechip_baseaddr + outTO[i]); | 1395 | tempTO = ioread32(ca91cx42_bridge->base + CA91CX42_LSI_TO[i]); |
1275 | vmeBS = tempBS + tempTO; | 1396 | vmeBS = tempBS + tempTO; |
1276 | vmeBD = tempBD + tempTO; | 1397 | vmeBD = tempBD + tempTO; |
1277 | if ((vmeRmw->targetAddr >= vmeBS) && | 1398 | if ((vmeRmw->targetAddr >= vmeBS) && |
@@ -1285,44 +1406,41 @@ int uni_do_rmw(vmeRmwCfg_t * vmeRmw) | |||
1285 | } | 1406 | } |
1286 | } | 1407 | } |
1287 | 1408 | ||
1288 | // If no window - fail. | 1409 | /* If no window - fail. */ |
1289 | if (rmw_pci_data_ptr == NULL) { | 1410 | if (rmw_pci_data_ptr == NULL) { |
1290 | return (-EINVAL); | 1411 | return -EINVAL; |
1291 | } | 1412 | } |
1292 | // Setup the RMW registers. | 1413 | /* Setup the RMW registers. */ |
1293 | writel(0, vmechip_baseaddr + SCYC_CTL); | 1414 | iowrite32(0, ca91cx42_bridge->base + SCYC_CTL); |
1294 | writel(SWIZZLE(vmeRmw->enableMask), vmechip_baseaddr + SCYC_EN); | 1415 | iowrite32(SWIZZLE(vmeRmw->enableMask), ca91cx42_bridge->base + SCYC_EN); |
1295 | writel(SWIZZLE(vmeRmw->compareData), vmechip_baseaddr + SCYC_CMP); | 1416 | iowrite32(SWIZZLE(vmeRmw->compareData), ca91cx42_bridge->base + |
1296 | writel(SWIZZLE(vmeRmw->swapData), vmechip_baseaddr + SCYC_SWP); | 1417 | SCYC_CMP); |
1297 | writel((int)rmw_pci_data_ptr, vmechip_baseaddr + SCYC_ADDR); | 1418 | iowrite32(SWIZZLE(vmeRmw->swapData), ca91cx42_bridge->base + SCYC_SWP); |
1298 | writel(1, vmechip_baseaddr + SCYC_CTL); | 1419 | iowrite32((int)rmw_pci_data_ptr, ca91cx42_bridge->base + SCYC_ADDR); |
1299 | 1420 | iowrite32(1, ca91cx42_bridge->base + SCYC_CTL); | |
1300 | // Run the RMW cycle until either success or max attempts. | 1421 | |
1422 | /* Run the RMW cycle until either success or max attempts. */ | ||
1301 | vmeRmw->numAttempts = 1; | 1423 | vmeRmw->numAttempts = 1; |
1302 | while (vmeRmw->numAttempts <= vmeRmw->maxAttempts) { | 1424 | while (vmeRmw->numAttempts <= vmeRmw->maxAttempts) { |
1303 | 1425 | ||
1304 | if ((readl(vaDataPtr) & vmeRmw->enableMask) == | 1426 | if ((ioread32(vaDataPtr) & vmeRmw->enableMask) == |
1305 | (vmeRmw->swapData & vmeRmw->enableMask)) { | 1427 | (vmeRmw->swapData & vmeRmw->enableMask)) { |
1306 | 1428 | ||
1307 | writel(0, vmechip_baseaddr + SCYC_CTL); | 1429 | iowrite32(0, ca91cx42_bridge->base + SCYC_CTL); |
1308 | break; | 1430 | break; |
1309 | 1431 | ||
1310 | } | 1432 | } |
1311 | vmeRmw->numAttempts++; | 1433 | vmeRmw->numAttempts++; |
1312 | } | 1434 | } |
1313 | 1435 | ||
1314 | // If no success, set num Attempts to be greater than max attempts | 1436 | /* If no success, set num Attempts to be greater than max attempts */ |
1315 | if (vmeRmw->numAttempts > vmeRmw->maxAttempts) { | 1437 | if (vmeRmw->numAttempts > vmeRmw->maxAttempts) { |
1316 | vmeRmw->numAttempts = vmeRmw->maxAttempts + 1; | 1438 | vmeRmw->numAttempts = vmeRmw->maxAttempts + 1; |
1317 | } | 1439 | } |
1318 | 1440 | ||
1319 | return (0); | 1441 | return 0; |
1320 | } | 1442 | } |
1321 | 1443 | ||
1322 | //----------------------------------------------------------------------------- | ||
1323 | // Function : uniSetupDctlReg | ||
1324 | // Description: | ||
1325 | //----------------------------------------------------------------------------- | ||
1326 | int uniSetupDctlReg(vmeDmaPacket_t * vmeDma, int *dctlregreturn) | 1444 | int uniSetupDctlReg(vmeDmaPacket_t * vmeDma, int *dctlregreturn) |
1327 | { | 1445 | { |
1328 | unsigned int dctlreg = 0x80; | 1446 | unsigned int dctlreg = 0x80; |
@@ -1366,11 +1484,11 @@ int uniSetupDctlReg(vmeDmaPacket_t * vmeDma, int *dctlregreturn) | |||
1366 | dctlreg |= 0x00070000; | 1484 | dctlreg |= 0x00070000; |
1367 | break; | 1485 | break; |
1368 | 1486 | ||
1369 | case VME_A64: // not supported in Universe DMA | 1487 | case VME_A64: /* not supported in Universe DMA */ |
1370 | case VME_CRCSR: | 1488 | case VME_CRCSR: |
1371 | case VME_USER3: | 1489 | case VME_USER3: |
1372 | case VME_USER4: | 1490 | case VME_USER4: |
1373 | return (-EINVAL); | 1491 | return -EINVAL; |
1374 | break; | 1492 | break; |
1375 | } | 1493 | } |
1376 | if (vmeAttr->userAccessType == VME_PROG) { | 1494 | if (vmeAttr->userAccessType == VME_PROG) { |
@@ -1383,50 +1501,46 @@ int uniSetupDctlReg(vmeDmaPacket_t * vmeDma, int *dctlregreturn) | |||
1383 | dctlreg |= 0x00000100; | 1501 | dctlreg |= 0x00000100; |
1384 | } | 1502 | } |
1385 | *dctlregreturn = dctlreg; | 1503 | *dctlregreturn = dctlreg; |
1386 | return (0); | 1504 | return 0; |
1387 | } | 1505 | } |
1388 | 1506 | ||
1389 | //----------------------------------------------------------------------------- | ||
1390 | // Function : uni_start_dma | ||
1391 | // Description: | ||
1392 | //----------------------------------------------------------------------------- | ||
1393 | unsigned int | 1507 | unsigned int |
1394 | uni_start_dma(int channel, unsigned int dgcsreg, TDMA_Cmd_Packet * vmeLL) | 1508 | ca91cx42_start_dma(int channel, unsigned int dgcsreg, TDMA_Cmd_Packet *vmeLL) |
1395 | { | 1509 | { |
1396 | unsigned int val; | 1510 | unsigned int val; |
1397 | 1511 | ||
1398 | // Setup registers as needed for direct or chained. | 1512 | /* Setup registers as needed for direct or chained. */ |
1399 | if (dgcsreg & 0x8000000) { | 1513 | if (dgcsreg & 0x8000000) { |
1400 | writel(0, vmechip_baseaddr + DTBC); | 1514 | iowrite32(0, ca91cx42_bridge->base + DTBC); |
1401 | writel((unsigned int)vmeLL, vmechip_baseaddr + DCPP); | 1515 | iowrite32((unsigned int)vmeLL, ca91cx42_bridge->base + DCPP); |
1402 | } else { | 1516 | } else { |
1403 | #if 0 | 1517 | #if 0 |
1404 | printk("Starting: DGCS = %08x\n", dgcsreg); | 1518 | printk(KERN_ERR "Starting: DGCS = %08x\n", dgcsreg); |
1405 | printk("Starting: DVA = %08x\n", readl(&vmeLL->dva)); | 1519 | printk(KERN_ERR "Starting: DVA = %08x\n", |
1406 | printk("Starting: DLV = %08x\n", readl(&vmeLL->dlv)); | 1520 | ioread32(&vmeLL->dva)); |
1407 | printk("Starting: DTBC = %08x\n", readl(&vmeLL->dtbc)); | 1521 | printk(KERN_ERR "Starting: DLV = %08x\n", |
1408 | printk("Starting: DCTL = %08x\n", readl(&vmeLL->dctl)); | 1522 | ioread32(&vmeLL->dlv)); |
1523 | printk(KERN_ERR "Starting: DTBC = %08x\n", | ||
1524 | ioread32(&vmeLL->dtbc)); | ||
1525 | printk(KERN_ERR "Starting: DCTL = %08x\n", | ||
1526 | ioread32(&vmeLL->dctl)); | ||
1409 | #endif | 1527 | #endif |
1410 | // Write registers | 1528 | /* Write registers */ |
1411 | writel(readl(&vmeLL->dva), vmechip_baseaddr + DVA); | 1529 | iowrite32(ioread32(&vmeLL->dva), ca91cx42_bridge->base + DVA); |
1412 | writel(readl(&vmeLL->dlv), vmechip_baseaddr + DLA); | 1530 | iowrite32(ioread32(&vmeLL->dlv), ca91cx42_bridge->base + DLA); |
1413 | writel(readl(&vmeLL->dtbc), vmechip_baseaddr + DTBC); | 1531 | iowrite32(ioread32(&vmeLL->dtbc), ca91cx42_bridge->base + DTBC); |
1414 | writel(readl(&vmeLL->dctl), vmechip_baseaddr + DCTL); | 1532 | iowrite32(ioread32(&vmeLL->dctl), ca91cx42_bridge->base + DCTL); |
1415 | writel(0, vmechip_baseaddr + DCPP); | 1533 | iowrite32(0, ca91cx42_bridge->base + DCPP); |
1416 | } | 1534 | } |
1417 | 1535 | ||
1418 | // Start the operation | 1536 | /* Start the operation */ |
1419 | writel(dgcsreg, vmechip_baseaddr + DGCS); | 1537 | iowrite32(dgcsreg, ca91cx42_bridge->base + DGCS); |
1420 | val = get_tbl(); | 1538 | val = get_tbl(); |
1421 | writel(dgcsreg | 0x8000000F, vmechip_baseaddr + DGCS); | 1539 | iowrite32(dgcsreg | 0x8000000F, ca91cx42_bridge->base + DGCS); |
1422 | return (val); | 1540 | return val; |
1423 | } | 1541 | } |
1424 | 1542 | ||
1425 | //----------------------------------------------------------------------------- | 1543 | TDMA_Cmd_Packet *ca91cx42_setup_dma(vmeDmaPacket_t * vmeDma) |
1426 | // Function : uni_setup_dma | ||
1427 | // Description: | ||
1428 | //----------------------------------------------------------------------------- | ||
1429 | TDMA_Cmd_Packet *uni_setup_dma(vmeDmaPacket_t * vmeDma) | ||
1430 | { | 1544 | { |
1431 | vmeDmaPacket_t *vmeCur; | 1545 | vmeDmaPacket_t *vmeCur; |
1432 | int maxPerPage; | 1546 | int maxPerPage; |
@@ -1439,9 +1553,9 @@ TDMA_Cmd_Packet *uni_setup_dma(vmeDmaPacket_t * vmeDma) | |||
1439 | maxPerPage = PAGESIZE / sizeof(TDMA_Cmd_Packet) - 1; | 1553 | maxPerPage = PAGESIZE / sizeof(TDMA_Cmd_Packet) - 1; |
1440 | startLL = (TDMA_Cmd_Packet *) __get_free_pages(GFP_KERNEL, 0); | 1554 | startLL = (TDMA_Cmd_Packet *) __get_free_pages(GFP_KERNEL, 0); |
1441 | if (startLL == 0) { | 1555 | if (startLL == 0) { |
1442 | return (startLL); | 1556 | return startLL; |
1443 | } | 1557 | } |
1444 | // First allocate pages for descriptors and create linked list | 1558 | /* First allocate pages for descriptors and create linked list */ |
1445 | vmeCur = vmeDma; | 1559 | vmeCur = vmeDma; |
1446 | currentLL = startLL; | 1560 | currentLL = startLL; |
1447 | currentLLcount = 0; | 1561 | currentLLcount = 0; |
@@ -1461,57 +1575,53 @@ TDMA_Cmd_Packet *uni_setup_dma(vmeDmaPacket_t * vmeDma) | |||
1461 | vmeCur = vmeCur->pNextPacket; | 1575 | vmeCur = vmeCur->pNextPacket; |
1462 | } | 1576 | } |
1463 | 1577 | ||
1464 | // Next fill in information for each descriptor | 1578 | /* Next fill in information for each descriptor */ |
1465 | vmeCur = vmeDma; | 1579 | vmeCur = vmeDma; |
1466 | currentLL = startLL; | 1580 | currentLL = startLL; |
1467 | while (vmeCur != 0) { | 1581 | while (vmeCur != 0) { |
1468 | if (vmeCur->srcBus == VME_DMA_VME) { | 1582 | if (vmeCur->srcBus == VME_DMA_VME) { |
1469 | writel(vmeCur->srcAddr, ¤tLL->dva); | 1583 | iowrite32(vmeCur->srcAddr, ¤tLL->dva); |
1470 | writel(vmeCur->dstAddr, ¤tLL->dlv); | 1584 | iowrite32(vmeCur->dstAddr, ¤tLL->dlv); |
1471 | } else { | 1585 | } else { |
1472 | writel(vmeCur->srcAddr, ¤tLL->dlv); | 1586 | iowrite32(vmeCur->srcAddr, ¤tLL->dlv); |
1473 | writel(vmeCur->dstAddr, ¤tLL->dva); | 1587 | iowrite32(vmeCur->dstAddr, ¤tLL->dva); |
1474 | } | 1588 | } |
1475 | uniSetupDctlReg(vmeCur, &dctlreg); | 1589 | uniSetupDctlReg(vmeCur, &dctlreg); |
1476 | writel(dctlreg, ¤tLL->dctl); | 1590 | iowrite32(dctlreg, ¤tLL->dctl); |
1477 | writel(vmeCur->byteCount, ¤tLL->dtbc); | 1591 | iowrite32(vmeCur->byteCount, ¤tLL->dtbc); |
1478 | 1592 | ||
1479 | currentLL = (TDMA_Cmd_Packet *) currentLL->dcpp; | 1593 | currentLL = (TDMA_Cmd_Packet *) currentLL->dcpp; |
1480 | vmeCur = vmeCur->pNextPacket; | 1594 | vmeCur = vmeCur->pNextPacket; |
1481 | } | 1595 | } |
1482 | 1596 | ||
1483 | // Convert Links to PCI addresses. | 1597 | /* Convert Links to PCI addresses. */ |
1484 | currentLL = startLL; | 1598 | currentLL = startLL; |
1485 | while (currentLL != 0) { | 1599 | while (currentLL != 0) { |
1486 | nextLL = (TDMA_Cmd_Packet *) currentLL->dcpp; | 1600 | nextLL = (TDMA_Cmd_Packet *) currentLL->dcpp; |
1487 | if (nextLL == 0) { | 1601 | if (nextLL == 0) { |
1488 | writel(1, ¤tLL->dcpp); | 1602 | iowrite32(1, ¤tLL->dcpp); |
1489 | } else { | 1603 | } else { |
1490 | writel((unsigned int)virt_to_bus(nextLL), | 1604 | iowrite32((unsigned int)virt_to_bus(nextLL), |
1491 | ¤tLL->dcpp); | 1605 | ¤tLL->dcpp); |
1492 | } | 1606 | } |
1493 | currentLL = nextLL; | 1607 | currentLL = nextLL; |
1494 | } | 1608 | } |
1495 | 1609 | ||
1496 | // Return pointer to descriptors list | 1610 | /* Return pointer to descriptors list */ |
1497 | return (startLL); | 1611 | return startLL; |
1498 | } | 1612 | } |
1499 | 1613 | ||
1500 | //----------------------------------------------------------------------------- | 1614 | int ca91cx42_free_dma(TDMA_Cmd_Packet *startLL) |
1501 | // Function : uni_free_dma | ||
1502 | // Description: | ||
1503 | //----------------------------------------------------------------------------- | ||
1504 | int uni_free_dma(TDMA_Cmd_Packet * startLL) | ||
1505 | { | 1615 | { |
1506 | TDMA_Cmd_Packet *currentLL; | 1616 | TDMA_Cmd_Packet *currentLL; |
1507 | TDMA_Cmd_Packet *prevLL; | 1617 | TDMA_Cmd_Packet *prevLL; |
1508 | TDMA_Cmd_Packet *nextLL; | 1618 | TDMA_Cmd_Packet *nextLL; |
1509 | unsigned int dcppreg; | 1619 | unsigned int dcppreg; |
1510 | 1620 | ||
1511 | // Convert Links to virtual addresses. | 1621 | /* Convert Links to virtual addresses. */ |
1512 | currentLL = startLL; | 1622 | currentLL = startLL; |
1513 | while (currentLL != 0) { | 1623 | while (currentLL != 0) { |
1514 | dcppreg = readl(¤tLL->dcpp); | 1624 | dcppreg = ioread32(¤tLL->dcpp); |
1515 | dcppreg &= ~6; | 1625 | dcppreg &= ~6; |
1516 | if (dcppreg & 1) { | 1626 | if (dcppreg & 1) { |
1517 | currentLL->dcpp = 0; | 1627 | currentLL->dcpp = 0; |
@@ -1521,7 +1631,7 @@ int uni_free_dma(TDMA_Cmd_Packet * startLL) | |||
1521 | currentLL = (TDMA_Cmd_Packet *) currentLL->dcpp; | 1631 | currentLL = (TDMA_Cmd_Packet *) currentLL->dcpp; |
1522 | } | 1632 | } |
1523 | 1633 | ||
1524 | // Free all pages associated with the descriptors. | 1634 | /* Free all pages associated with the descriptors. */ |
1525 | currentLL = startLL; | 1635 | currentLL = startLL; |
1526 | prevLL = currentLL; | 1636 | prevLL = currentLL; |
1527 | while (currentLL != 0) { | 1637 | while (currentLL != 0) { |
@@ -1533,15 +1643,11 @@ int uni_free_dma(TDMA_Cmd_Packet * startLL) | |||
1533 | currentLL = nextLL; | 1643 | currentLL = nextLL; |
1534 | } | 1644 | } |
1535 | 1645 | ||
1536 | // Return pointer to descriptors list | 1646 | /* Return pointer to descriptors list */ |
1537 | return (0); | 1647 | return 0; |
1538 | } | 1648 | } |
1539 | 1649 | ||
1540 | //----------------------------------------------------------------------------- | 1650 | int ca91cx42_do_dma(vmeDmaPacket_t *vmeDma) |
1541 | // Function : uni_do_dma | ||
1542 | // Description: | ||
1543 | //----------------------------------------------------------------------------- | ||
1544 | int uni_do_dma(vmeDmaPacket_t * vmeDma) | ||
1545 | { | 1651 | { |
1546 | unsigned int dgcsreg = 0; | 1652 | unsigned int dgcsreg = 0; |
1547 | unsigned int dctlreg = 0; | 1653 | unsigned int dctlreg = 0; |
@@ -1550,55 +1656,55 @@ int uni_do_dma(vmeDmaPacket_t * vmeDma) | |||
1550 | vmeDmaPacket_t *curDma; | 1656 | vmeDmaPacket_t *curDma; |
1551 | TDMA_Cmd_Packet *dmaLL; | 1657 | TDMA_Cmd_Packet *dmaLL; |
1552 | 1658 | ||
1553 | // Sanity check the VME chain. | 1659 | /* Sanity check the VME chain. */ |
1554 | channel = vmeDma->channel_number; | 1660 | channel = vmeDma->channel_number; |
1555 | if (channel > 0) { | 1661 | if (channel > 0) { |
1556 | return (-EINVAL); | 1662 | return -EINVAL; |
1557 | } | 1663 | } |
1558 | curDma = vmeDma; | 1664 | curDma = vmeDma; |
1559 | while (curDma != 0) { | 1665 | while (curDma != 0) { |
1560 | if (curDma->byteCount == 0) { | 1666 | if (curDma->byteCount == 0) { |
1561 | return (-EINVAL); | 1667 | return -EINVAL; |
1562 | } | 1668 | } |
1563 | if (curDma->byteCount >= 0x1000000) { | 1669 | if (curDma->byteCount >= 0x1000000) { |
1564 | return (-EINVAL); | 1670 | return -EINVAL; |
1565 | } | 1671 | } |
1566 | if ((curDma->srcAddr & 7) != (curDma->dstAddr & 7)) { | 1672 | if ((curDma->srcAddr & 7) != (curDma->dstAddr & 7)) { |
1567 | return (-EINVAL); | 1673 | return -EINVAL; |
1568 | } | 1674 | } |
1569 | switch (curDma->srcBus) { | 1675 | switch (curDma->srcBus) { |
1570 | case VME_DMA_PCI: | 1676 | case VME_DMA_PCI: |
1571 | if (curDma->dstBus != VME_DMA_VME) { | 1677 | if (curDma->dstBus != VME_DMA_VME) { |
1572 | return (-EINVAL); | 1678 | return -EINVAL; |
1573 | } | 1679 | } |
1574 | break; | 1680 | break; |
1575 | case VME_DMA_VME: | 1681 | case VME_DMA_VME: |
1576 | if (curDma->dstBus != VME_DMA_PCI) { | 1682 | if (curDma->dstBus != VME_DMA_PCI) { |
1577 | return (-EINVAL); | 1683 | return -EINVAL; |
1578 | } | 1684 | } |
1579 | break; | 1685 | break; |
1580 | default: | 1686 | default: |
1581 | return (-EINVAL); | 1687 | return -EINVAL; |
1582 | break; | 1688 | break; |
1583 | } | 1689 | } |
1584 | if (uniSetupDctlReg(curDma, &dctlreg) < 0) { | 1690 | if (uniSetupDctlReg(curDma, &dctlreg) < 0) { |
1585 | return (-EINVAL); | 1691 | return -EINVAL; |
1586 | } | 1692 | } |
1587 | 1693 | ||
1588 | curDma = curDma->pNextPacket; | 1694 | curDma = curDma->pNextPacket; |
1589 | if (curDma == vmeDma) { // Endless Loop! | 1695 | if (curDma == vmeDma) { /* Endless Loop! */ |
1590 | return (-EINVAL); | 1696 | return -EINVAL; |
1591 | } | 1697 | } |
1592 | } | 1698 | } |
1593 | 1699 | ||
1594 | // calculate control register | 1700 | /* calculate control register */ |
1595 | if (vmeDma->pNextPacket != 0) { | 1701 | if (vmeDma->pNextPacket != 0) { |
1596 | dgcsreg = 0x8000000; | 1702 | dgcsreg = 0x8000000; |
1597 | } else { | 1703 | } else { |
1598 | dgcsreg = 0; | 1704 | dgcsreg = 0; |
1599 | } | 1705 | } |
1600 | 1706 | ||
1601 | for (x = 0; x < 8; x++) { // vme block size | 1707 | for (x = 0; x < 8; x++) { /* vme block size */ |
1602 | if ((256 << x) >= vmeDma->maxVmeBlockSize) { | 1708 | if ((256 << x) >= vmeDma->maxVmeBlockSize) { |
1603 | break; | 1709 | break; |
1604 | } | 1710 | } |
@@ -1608,7 +1714,7 @@ int uni_do_dma(vmeDmaPacket_t * vmeDma) | |||
1608 | dgcsreg |= (x << 20); | 1714 | dgcsreg |= (x << 20); |
1609 | 1715 | ||
1610 | if (vmeDma->vmeBackOffTimer) { | 1716 | if (vmeDma->vmeBackOffTimer) { |
1611 | for (x = 1; x < 8; x++) { // vme timer | 1717 | for (x = 1; x < 8; x++) { /* vme timer */ |
1612 | if ((16 << (x - 1)) >= vmeDma->vmeBackOffTimer) { | 1718 | if ((16 << (x - 1)) >= vmeDma->vmeBackOffTimer) { |
1613 | break; | 1719 | break; |
1614 | } | 1720 | } |
@@ -1617,195 +1723,211 @@ int uni_do_dma(vmeDmaPacket_t * vmeDma) | |||
1617 | x = 7; | 1723 | x = 7; |
1618 | dgcsreg |= (x << 16); | 1724 | dgcsreg |= (x << 16); |
1619 | } | 1725 | } |
1620 | // Setup the dma chain | 1726 | /*` Setup the dma chain */ |
1621 | dmaLL = uni_setup_dma(vmeDma); | 1727 | dmaLL = ca91cx42_setup_dma(vmeDma); |
1622 | 1728 | ||
1623 | // Start the DMA | 1729 | /* Start the DMA */ |
1624 | if (dgcsreg & 0x8000000) { | 1730 | if (dgcsreg & 0x8000000) { |
1625 | vmeDma->vmeDmaStartTick = | 1731 | vmeDma->vmeDmaStartTick = |
1626 | uni_start_dma(channel, dgcsreg, | 1732 | ca91cx42_start_dma(channel, dgcsreg, |
1627 | (TDMA_Cmd_Packet *) virt_to_phys(dmaLL)); | 1733 | (TDMA_Cmd_Packet *) virt_to_phys(dmaLL)); |
1628 | } else { | 1734 | } else { |
1629 | vmeDma->vmeDmaStartTick = | 1735 | vmeDma->vmeDmaStartTick = |
1630 | uni_start_dma(channel, dgcsreg, dmaLL); | 1736 | ca91cx42_start_dma(channel, dgcsreg, dmaLL); |
1631 | } | 1737 | } |
1632 | 1738 | ||
1633 | wait_event_interruptible(dma_queue[0], | 1739 | wait_event_interruptible(dma_queue, |
1634 | readl(vmechip_baseaddr + DGCS) & 0x800); | 1740 | ioread32(ca91cx42_bridge->base + DGCS) & 0x800); |
1635 | 1741 | ||
1636 | val = readl(vmechip_baseaddr + DGCS); | 1742 | val = ioread32(ca91cx42_bridge->base + DGCS); |
1637 | writel(val | 0xF00, vmechip_baseaddr + DGCS); | 1743 | iowrite32(val | 0xF00, ca91cx42_bridge->base + DGCS); |
1638 | 1744 | ||
1639 | vmeDma->vmeDmaStatus = 0; | 1745 | vmeDma->vmeDmaStatus = 0; |
1640 | vmeDma->vmeDmaStopTick = uni_dma_irq_time; | ||
1641 | if (vmeDma->vmeDmaStopTick < vmeDma->vmeDmaStartTick) { | ||
1642 | vmeDma->vmeDmaElapsedTime = | ||
1643 | (0xFFFFFFFF - vmeDma->vmeDmaStartTick) + | ||
1644 | vmeDma->vmeDmaStopTick; | ||
1645 | } else { | ||
1646 | vmeDma->vmeDmaElapsedTime = | ||
1647 | vmeDma->vmeDmaStopTick - vmeDma->vmeDmaStartTick; | ||
1648 | } | ||
1649 | vmeDma->vmeDmaElapsedTime -= vmechip_irq_overhead_ticks; | ||
1650 | vmeDma->vmeDmaElapsedTime /= (tb_speed / 1000000); | ||
1651 | 1746 | ||
1652 | if (!(val & 0x00000800)) { | 1747 | if (!(val & 0x00000800)) { |
1653 | vmeDma->vmeDmaStatus = val & 0x700; | 1748 | vmeDma->vmeDmaStatus = val & 0x700; |
1654 | printk(KERN_ERR | 1749 | printk(KERN_ERR "ca91c042: DMA Error in ca91cx42_DMA_irqhandler" |
1655 | "ca91c042: DMA Error in DMA_uni_irqhandler DGCS=%08X\n", | 1750 | " DGCS=%08X\n", val); |
1656 | val); | 1751 | val = ioread32(ca91cx42_bridge->base + DCPP); |
1657 | val = readl(vmechip_baseaddr + DCPP); | ||
1658 | printk(KERN_ERR "ca91c042: DCPP=%08X\n", val); | 1752 | printk(KERN_ERR "ca91c042: DCPP=%08X\n", val); |
1659 | val = readl(vmechip_baseaddr + DCTL); | 1753 | val = ioread32(ca91cx42_bridge->base + DCTL); |
1660 | printk(KERN_ERR "ca91c042: DCTL=%08X\n", val); | 1754 | printk(KERN_ERR "ca91c042: DCTL=%08X\n", val); |
1661 | val = readl(vmechip_baseaddr + DTBC); | 1755 | val = ioread32(ca91cx42_bridge->base + DTBC); |
1662 | printk(KERN_ERR "ca91c042: DTBC=%08X\n", val); | 1756 | printk(KERN_ERR "ca91c042: DTBC=%08X\n", val); |
1663 | val = readl(vmechip_baseaddr + DLA); | 1757 | val = ioread32(ca91cx42_bridge->base + DLA); |
1664 | printk(KERN_ERR "ca91c042: DLA=%08X\n", val); | 1758 | printk(KERN_ERR "ca91c042: DLA=%08X\n", val); |
1665 | val = readl(vmechip_baseaddr + DVA); | 1759 | val = ioread32(ca91cx42_bridge->base + DVA); |
1666 | printk(KERN_ERR "ca91c042: DVA=%08X\n", val); | 1760 | printk(KERN_ERR "ca91c042: DVA=%08X\n", val); |
1667 | 1761 | ||
1668 | } | 1762 | } |
1669 | // Free the dma chain | 1763 | /* Free the dma chain */ |
1670 | uni_free_dma(dmaLL); | 1764 | ca91cx42_free_dma(dmaLL); |
1671 | 1765 | ||
1672 | return (0); | 1766 | return 0; |
1673 | } | 1767 | } |
1674 | 1768 | ||
1675 | //----------------------------------------------------------------------------- | 1769 | int ca91cx42_lm_set(vmeLmCfg_t *vmeLm) |
1676 | // Function : uni_shutdown | ||
1677 | // Description: Put VME bridge in quiescent state. | ||
1678 | //----------------------------------------------------------------------------- | ||
1679 | void uni_shutdown(void) | ||
1680 | { | 1770 | { |
1681 | writel(0, vmechip_baseaddr + LINT_EN); // Turn off Ints | 1771 | int temp_ctl = 0; |
1682 | 1772 | ||
1683 | // Turn off the windows | 1773 | if (vmeLm->addrU) |
1684 | writel(0x00800000, vmechip_baseaddr + LSI0_CTL); | 1774 | return -EINVAL; |
1685 | writel(0x00800000, vmechip_baseaddr + LSI1_CTL); | 1775 | |
1686 | writel(0x00800000, vmechip_baseaddr + LSI2_CTL); | 1776 | switch (vmeLm->addrSpace) { |
1687 | writel(0x00800000, vmechip_baseaddr + LSI3_CTL); | 1777 | case VME_A64: |
1688 | writel(0x00F00000, vmechip_baseaddr + VSI0_CTL); | 1778 | case VME_USER3: |
1689 | writel(0x00F00000, vmechip_baseaddr + VSI1_CTL); | 1779 | case VME_USER4: |
1690 | writel(0x00F00000, vmechip_baseaddr + VSI2_CTL); | 1780 | return -EINVAL; |
1691 | writel(0x00F00000, vmechip_baseaddr + VSI3_CTL); | 1781 | case VME_A16: |
1692 | if (vmechip_revision >= 2) { | 1782 | temp_ctl |= 0x00000; |
1693 | writel(0x00800000, vmechip_baseaddr + LSI4_CTL); | 1783 | break; |
1694 | writel(0x00800000, vmechip_baseaddr + LSI5_CTL); | 1784 | case VME_A24: |
1695 | writel(0x00800000, vmechip_baseaddr + LSI6_CTL); | 1785 | temp_ctl |= 0x10000; |
1696 | writel(0x00800000, vmechip_baseaddr + LSI7_CTL); | 1786 | break; |
1697 | writel(0x00F00000, vmechip_baseaddr + VSI4_CTL); | 1787 | case VME_A32: |
1698 | writel(0x00F00000, vmechip_baseaddr + VSI5_CTL); | 1788 | temp_ctl |= 0x20000; |
1699 | writel(0x00F00000, vmechip_baseaddr + VSI6_CTL); | 1789 | break; |
1700 | writel(0x00F00000, vmechip_baseaddr + VSI7_CTL); | 1790 | case VME_CRCSR: |
1791 | temp_ctl |= 0x50000; | ||
1792 | break; | ||
1793 | case VME_USER1: | ||
1794 | temp_ctl |= 0x60000; | ||
1795 | break; | ||
1796 | case VME_USER2: | ||
1797 | temp_ctl |= 0x70000; | ||
1798 | break; | ||
1701 | } | 1799 | } |
1800 | |||
1801 | /* Disable while we are mucking around */ | ||
1802 | iowrite32(0x00000000, ca91cx42_bridge->base + LM_CTL); | ||
1803 | |||
1804 | iowrite32(vmeLm->addr, ca91cx42_bridge->base + LM_BS); | ||
1805 | |||
1806 | /* Setup CTL register. */ | ||
1807 | if (vmeLm->userAccessType & VME_SUPER) | ||
1808 | temp_ctl |= 0x00200000; | ||
1809 | if (vmeLm->userAccessType & VME_USER) | ||
1810 | temp_ctl |= 0x00100000; | ||
1811 | if (vmeLm->dataAccessType & VME_PROG) | ||
1812 | temp_ctl |= 0x00800000; | ||
1813 | if (vmeLm->dataAccessType & VME_DATA) | ||
1814 | temp_ctl |= 0x00400000; | ||
1815 | |||
1816 | |||
1817 | /* Write ctl reg and enable */ | ||
1818 | iowrite32(0x80000000 | temp_ctl, ca91cx42_bridge->base + LM_CTL); | ||
1819 | temp_ctl = ioread32(ca91cx42_bridge->base + LM_CTL); | ||
1820 | |||
1821 | return 0; | ||
1702 | } | 1822 | } |
1703 | 1823 | ||
1704 | //----------------------------------------------------------------------------- | 1824 | int ca91cx42_wait_lm(vmeLmCfg_t *vmeLm) |
1705 | // Function : uni_init() | ||
1706 | // Description: | ||
1707 | //----------------------------------------------------------------------------- | ||
1708 | int uni_init(void) | ||
1709 | { | 1825 | { |
1710 | int result; | 1826 | unsigned long flags; |
1711 | unsigned int tmp; | 1827 | unsigned int tmp; |
1712 | unsigned int crcsr_addr; | 1828 | |
1713 | unsigned int irqOverHeadStart; | 1829 | spin_lock_irqsave(&lm_lock, flags); |
1714 | int overHeadTicks; | 1830 | spin_unlock_irqrestore(&lm_lock, flags); |
1715 | 1831 | if (tmp == 0) { | |
1716 | uni_shutdown(); | 1832 | if (vmeLm->lmWait < 10) |
1717 | 1833 | vmeLm->lmWait = 10; | |
1718 | // Write to Misc Register | 1834 | interruptible_sleep_on_timeout(&lm_queue, vmeLm->lmWait); |
1719 | // Set VME Bus Time-out | ||
1720 | // Arbitration Mode | ||
1721 | // DTACK Enable | ||
1722 | tmp = readl(vmechip_baseaddr + MISC_CTL) & 0x0832BFFF; | ||
1723 | tmp |= 0x76040000; | ||
1724 | writel(tmp, vmechip_baseaddr + MISC_CTL); | ||
1725 | if (tmp & 0x20000) { | ||
1726 | vme_syscon = 1; | ||
1727 | } else { | ||
1728 | vme_syscon = 0; | ||
1729 | } | ||
1730 | |||
1731 | // Clear DMA status log | ||
1732 | writel(0x00000F00, vmechip_baseaddr + DGCS); | ||
1733 | // Clear and enable error log | ||
1734 | writel(0x00800000, vmechip_baseaddr + L_CMDERR); | ||
1735 | // Turn off location monitor | ||
1736 | writel(0x00000000, vmechip_baseaddr + LM_CTL); | ||
1737 | |||
1738 | // Initialize crcsr map | ||
1739 | if (vme_slotnum != -1) { | ||
1740 | writel(vme_slotnum << 27, vmechip_baseaddr + VCSR_BS); | ||
1741 | } | ||
1742 | crcsr_addr = readl(vmechip_baseaddr + VCSR_BS) >> 8; | ||
1743 | writel((unsigned int)vmechip_interboard_datap - crcsr_addr, | ||
1744 | vmechip_baseaddr + VCSR_TO); | ||
1745 | if (vme_slotnum != -1) { | ||
1746 | writel(0x80000000, vmechip_baseaddr + VCSR_CTL); | ||
1747 | } | ||
1748 | // Turn off interrupts | ||
1749 | writel(0x00000000, vmechip_baseaddr + LINT_EN); // Disable interrupts in the Universe first | ||
1750 | writel(0x00FFFFFF, vmechip_baseaddr + LINT_STAT); // Clear Any Pending Interrupts | ||
1751 | writel(0x00000000, vmechip_baseaddr + VINT_EN); // Disable interrupts in the Universe first | ||
1752 | |||
1753 | result = | ||
1754 | request_irq(vmechip_irq, uni_irqhandler, IRQF_SHARED | IRQF_DISABLED, | ||
1755 | "VMEBus (ca91c042)", vmechip_baseaddr); | ||
1756 | if (result) { | ||
1757 | printk(KERN_ERR | ||
1758 | "ca91c042: can't get assigned pci irq vector %02X\n", | ||
1759 | vmechip_irq); | ||
1760 | return (0); | ||
1761 | } else { | ||
1762 | writel(0x0000, vmechip_baseaddr + LINT_MAP0); // Map all ints to 0 | ||
1763 | writel(0x0000, vmechip_baseaddr + LINT_MAP1); // Map all ints to 0 | ||
1764 | writel(0x0000, vmechip_baseaddr + LINT_MAP2); // Map all ints to 0 | ||
1765 | } | 1835 | } |
1836 | iowrite32(0x00000000, ca91cx42_bridge->base + LM_CTL); | ||
1766 | 1837 | ||
1767 | // Enable DMA, mailbox, VIRQ & LM Interrupts | 1838 | return 0; |
1768 | if (vme_syscon) | 1839 | } |
1769 | tmp = 0x00FF07FE; | ||
1770 | else | ||
1771 | tmp = 0x00FF0700; | ||
1772 | writel(tmp, vmechip_baseaddr + LINT_EN); | ||
1773 | 1840 | ||
1774 | // Do a quick sanity test of the bridge | ||
1775 | if (readl(vmechip_baseaddr + LINT_EN) != tmp) { | ||
1776 | return (0); | ||
1777 | } | ||
1778 | if (readl(vmechip_baseaddr + PCI_CLASS_REVISION) != 0x06800002) { | ||
1779 | return (0); | ||
1780 | } | ||
1781 | for (tmp = 1; tmp < 0x80000000; tmp = tmp << 1) { | ||
1782 | writel(tmp, vmechip_baseaddr + SCYC_EN); | ||
1783 | writel(~tmp, vmechip_baseaddr + SCYC_CMP); | ||
1784 | if (readl(vmechip_baseaddr + SCYC_EN) != tmp) { | ||
1785 | return (0); | ||
1786 | } | ||
1787 | if (readl(vmechip_baseaddr + SCYC_CMP) != ~tmp) { | ||
1788 | return (0); | ||
1789 | } | ||
1790 | } | ||
1791 | 1841 | ||
1792 | // do a mail box interrupt to calibrate the interrupt overhead. | ||
1793 | 1842 | ||
1794 | irqOverHeadStart = get_tbl(); | 1843 | int ca91cx42_set_arbiter(vmeArbiterCfg_t *vmeArb) |
1795 | writel(0, vmechip_baseaddr + MBOX1); | 1844 | { |
1796 | for (tmp = 0; tmp < 10; tmp++) { | 1845 | int temp_ctl = 0; |
1797 | } | 1846 | int vbto = 0; |
1798 | 1847 | ||
1799 | irqOverHeadStart = get_tbl(); | 1848 | temp_ctl = ioread32(ca91cx42_bridge->base + MISC_CTL); |
1800 | writel(0, vmechip_baseaddr + MBOX1); | 1849 | temp_ctl &= 0x00FFFFFF; |
1801 | for (tmp = 0; tmp < 10; tmp++) { | ||
1802 | } | ||
1803 | 1850 | ||
1804 | overHeadTicks = uni_irq_time - irqOverHeadStart; | 1851 | if (vmeArb->globalTimeoutTimer == 0xFFFFFFFF) { |
1805 | if (overHeadTicks > 0) { | 1852 | vbto = 7; |
1806 | vmechip_irq_overhead_ticks = overHeadTicks; | 1853 | } else if (vmeArb->globalTimeoutTimer > 1024) { |
1854 | return -EINVAL; | ||
1855 | } else if (vmeArb->globalTimeoutTimer == 0) { | ||
1856 | vbto = 0; | ||
1807 | } else { | 1857 | } else { |
1808 | vmechip_irq_overhead_ticks = 1; | 1858 | vbto = 1; |
1859 | while ((16 * (1 << (vbto - 1))) < vmeArb->globalTimeoutTimer) | ||
1860 | vbto += 1; | ||
1809 | } | 1861 | } |
1810 | return (1); | 1862 | temp_ctl |= (vbto << 28); |
1863 | |||
1864 | if (vmeArb->arbiterMode == VME_PRIORITY_MODE) | ||
1865 | temp_ctl |= 1 << 26; | ||
1866 | |||
1867 | if (vmeArb->arbiterTimeoutFlag) | ||
1868 | temp_ctl |= 2 << 24; | ||
1869 | |||
1870 | iowrite32(temp_ctl, ca91cx42_bridge->base + MISC_CTL); | ||
1871 | return 0; | ||
1811 | } | 1872 | } |
1873 | |||
1874 | int ca91cx42_get_arbiter(vmeArbiterCfg_t *vmeArb) | ||
1875 | { | ||
1876 | int temp_ctl = 0; | ||
1877 | int vbto = 0; | ||
1878 | |||
1879 | temp_ctl = ioread32(ca91cx42_bridge->base + MISC_CTL); | ||
1880 | |||
1881 | vbto = (temp_ctl >> 28) & 0xF; | ||
1882 | if (vbto != 0) | ||
1883 | vmeArb->globalTimeoutTimer = (16 * (1 << (vbto - 1))); | ||
1884 | |||
1885 | if (temp_ctl & (1 << 26)) | ||
1886 | vmeArb->arbiterMode = VME_PRIORITY_MODE; | ||
1887 | else | ||
1888 | vmeArb->arbiterMode = VME_R_ROBIN_MODE; | ||
1889 | |||
1890 | if (temp_ctl & (3 << 24)) | ||
1891 | vmeArb->arbiterTimeoutFlag = 1; | ||
1892 | |||
1893 | return 0; | ||
1894 | } | ||
1895 | |||
1896 | int ca91cx42_set_requestor(vmeRequesterCfg_t *vmeReq) | ||
1897 | { | ||
1898 | int temp_ctl = 0; | ||
1899 | |||
1900 | temp_ctl = ioread32(ca91cx42_bridge->base + MAST_CTL); | ||
1901 | temp_ctl &= 0xFF0FFFFF; | ||
1902 | |||
1903 | if (vmeReq->releaseMode == 1) | ||
1904 | temp_ctl |= (1 << 20); | ||
1905 | |||
1906 | if (vmeReq->fairMode == 1) | ||
1907 | temp_ctl |= (1 << 21); | ||
1908 | |||
1909 | temp_ctl |= (vmeReq->requestLevel << 22); | ||
1910 | |||
1911 | iowrite32(temp_ctl, ca91cx42_bridge->base + MAST_CTL); | ||
1912 | return 0; | ||
1913 | } | ||
1914 | |||
1915 | int ca91cx42_get_requestor(vmeRequesterCfg_t *vmeReq) | ||
1916 | { | ||
1917 | int temp_ctl = 0; | ||
1918 | |||
1919 | temp_ctl = ioread32(ca91cx42_bridge->base + MAST_CTL); | ||
1920 | |||
1921 | if (temp_ctl & (1 << 20)) | ||
1922 | vmeReq->releaseMode = 1; | ||
1923 | |||
1924 | if (temp_ctl & (1 << 21)) | ||
1925 | vmeReq->fairMode = 1; | ||
1926 | |||
1927 | vmeReq->requestLevel = (temp_ctl & 0xC00000) >> 22; | ||
1928 | |||
1929 | return 0; | ||
1930 | } | ||
1931 | |||
1932 | |||
1933 | #endif | ||