]> git.proxmox.com Git - mirror_ubuntu-zesty-kernel.git/blame - drivers/staging/vme/bridges/vme_ca91cx42.c
Staging: vme: add Universe I/II bridge driver
[mirror_ubuntu-zesty-kernel.git] / drivers / staging / vme / bridges / vme_ca91cx42.c
CommitLineData
60479690
MW
1/*
2 * Support for the Tundra Universe I/II VME-PCI Bridge Chips
3 *
4 * Author: Martyn Welch <martyn.welch@gefanuc.com>
5 * Copyright 2008 GE Fanuc Intelligent Platforms Embedded Systems, Inc.
6 *
7 * Based on work by Tom Armistead and Ajit Prem
8 * Copyright 2004 Motorola Inc.
9 *
10 * Derived from ca91c042.c by Michael Wyrick
11 *
12 * This program is free software; you can redistribute it and/or modify it
13 * under the terms of the GNU General Public License as published by the
14 * Free Software Foundation; either version 2 of the License, or (at your
15 * option) any later version.
16 */
17
18#include <linux/version.h>
19#include <linux/module.h>
20#include <linux/mm.h>
21#include <linux/types.h>
22#include <linux/errno.h>
23#include <linux/proc_fs.h>
24#include <linux/pci.h>
25#include <linux/dma-mapping.h>
26#include <linux/poll.h>
27#include <linux/interrupt.h>
28#include <linux/spinlock.h>
29#include <asm/time.h>
30#include <asm/io.h>
31#include <asm/uaccess.h>
32
33#include "../vme.h"
34#include "../vme_bridge.h"
35#include "vme_ca91cx42.h"
36
37extern struct vmeSharedData *vmechip_interboard_data;
38extern dma_addr_t vmechip_interboard_datap;
39extern const int vmechip_revision;
40extern const int vmechip_devid;
41extern const int vmechip_irq;
42extern int vmechip_irq_overhead_ticks;
43extern char *vmechip_baseaddr;
44extern const int vme_slotnum;
45extern int vme_syscon;
46extern unsigned int out_image_va[];
47extern unsigned int vme_irqlog[8][0x100];
48
49static int outCTL[] = { LSI0_CTL, LSI1_CTL, LSI2_CTL, LSI3_CTL,
50 LSI4_CTL, LSI5_CTL, LSI6_CTL, LSI7_CTL
51};
52
53static int outBS[] = { LSI0_BS, LSI1_BS, LSI2_BS, LSI3_BS,
54 LSI4_BS, LSI5_BS, LSI6_BS, LSI7_BS
55};
56
57static int outBD[] = { LSI0_BD, LSI1_BD, LSI2_BD, LSI3_BD,
58 LSI4_BD, LSI5_BD, LSI6_BD, LSI7_BD
59};
60
61static int outTO[] = { LSI0_TO, LSI1_TO, LSI2_TO, LSI3_TO,
62 LSI4_TO, LSI5_TO, LSI6_TO, LSI7_TO
63};
64
65static int inCTL[] = { VSI0_CTL, VSI1_CTL, VSI2_CTL, VSI3_CTL,
66 VSI4_CTL, VSI5_CTL, VSI6_CTL, VSI7_CTL
67};
68
69static int inBS[] = { VSI0_BS, VSI1_BS, VSI2_BS, VSI3_BS,
70 VSI4_BS, VSI5_BS, VSI6_BS, VSI7_BS
71};
72
73static int inBD[] = { VSI0_BD, VSI1_BD, VSI2_BD, VSI3_BD,
74 VSI4_BD, VSI5_BD, VSI6_BD, VSI7_BD
75};
76
77static int inTO[] = { VSI0_TO, VSI1_TO, VSI2_TO, VSI3_TO,
78 VSI4_TO, VSI5_TO, VSI6_TO, VSI7_TO
79};
80static int vmevec[7] = { V1_STATID, V2_STATID, V3_STATID, V4_STATID,
81 V5_STATID, V6_STATID, V7_STATID
82};
83
84struct interrupt_counters {
85 unsigned int acfail;
86 unsigned int sysfail;
87 unsigned int sw_int;
88 unsigned int sw_iack;
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};
97
98extern wait_queue_head_t dma_queue[];
99extern wait_queue_head_t lm_queue;
100extern wait_queue_head_t mbox_queue;
101
102extern int tb_speed;
103
104unsigned int uni_irq_time;
105unsigned int uni_dma_irq_time;
106unsigned int uni_lm_event;
107
108static spinlock_t lm_lock = SPIN_LOCK_UNLOCKED;
109
110static 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
122int uni_procinfo(char *buf)
123{
124 char *p;
125
126 p = buf;
127
128 p += sprintf(p, "\n");
129 {
130 unsigned long misc_ctl;
131
132 misc_ctl = read_register(MISC_CTL);
133 p += sprintf(p, "MISC_CTL:\t\t\t0x%08lx\n", misc_ctl);
134 p += sprintf(p, "VME Bus Time Out:\t\t");
135 switch ((misc_ctl & UNIV_BM_MISC_CTL_VBTO) >>
136 UNIV_OF_MISC_CTL_VBTO) {
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 }
247 p += sprintf(p, "\n");
248 }
249 {
250 unsigned int mast_ctl;
251
252 mast_ctl = read_register(MAST_CTL);
253 p += sprintf(p, "MAST_CTL:\t\t\t0x%08x\n", mast_ctl);
254 {
255 int retries;
256
257 retries = ((mast_ctl & UNIV_BM_MAST_CTL_MAXRTRY)
258 >> UNIV_OF_MAST_CTL_MAXRTRY) * 64;
259 p += sprintf(p, "Max PCI Master Retries:\t\t");
260 if (retries)
261 p += sprintf(p, "%d\n", retries);
262 else
263 p += sprintf(p, "Forever\n");
264 }
265
266 p += sprintf(p, "Posted Write Transfer Count:\t");
267 switch ((mast_ctl & UNIV_BM_MAST_CTL_PWON) >>
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
291 p += sprintf(p, "VMEbus Request Level:\t\t");
292 switch ((mast_ctl & UNIV_BM_MAST_CTL_VRL) >>
293 UNIV_OF_MAST_CTL_VRL) {
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
487 return p - buf;
488}
489
490//----------------------------------------------------------------------------
491// uni_bus_error_chk()
492//----------------------------------------------------------------------------
493int uni_bus_error_chk(int clrflag)
494{
495 int tmp;
496 tmp = readl(vmechip_baseaddr + PCI_COMMAND);
497 if (tmp & 0x08000000) { // S_TA is Set
498 if (clrflag)
499 writel(tmp | 0x08000000,
500 vmechip_baseaddr + PCI_COMMAND);
501 return (1);
502 }
503 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//-----------------------------------------------------------------------------
512static void DMA_uni_irqhandler(void)
513{
514 uni_dma_irq_time = uni_irq_time;
515 wake_up(&dma_queue[0]);
516}
517
518//-----------------------------------------------------------------------------
519// Function : LERR_uni_irqhandler
520// Inputs : void
521// Outputs : void
522// Description:
523//-----------------------------------------------------------------------------
524static void LERR_uni_irqhandler(void)
525{
526 int val;
527
528 val = readl(vmechip_baseaddr + DGCS);
529
530 if (!(val & 0x00000800)) {
531 printk(KERN_ERR
532 "ca91c042: LERR_uni_irqhandler DMA Read Error DGCS=%08X\n",
533 val);
534
535 }
536}
537
538//-----------------------------------------------------------------------------
539// Function : VERR_uni_irqhandler
540// Inputs : void
541// Outputs : void
542// Description:
543//-----------------------------------------------------------------------------
544static void VERR_uni_irqhandler(void)
545{
546 int val;
547
548 val = readl(vmechip_baseaddr + DGCS);
549
550 if (!(val & 0x00000800)) {
551 printk(KERN_ERR
552 "ca91c042: VERR_uni_irqhandler DMA Read Error DGCS=%08X\n",
553 val);
554 }
555
556}
557
558//-----------------------------------------------------------------------------
559// Function : MB_uni_irqhandler
560// Inputs : void
561// Outputs : void
562// Description:
563//-----------------------------------------------------------------------------
564static void MB_uni_irqhandler(int mbox_mask)
565{
566 if (vmechip_irq_overhead_ticks != 0) {
567 wake_up(&mbox_queue);
568 }
569}
570
571//-----------------------------------------------------------------------------
572// Function : LM_uni_irqhandler
573// Inputs : void
574// Outputs : void
575// Description:
576//-----------------------------------------------------------------------------
577static void LM_uni_irqhandler(int lm_mask)
578{
579 uni_lm_event = lm_mask;
580 wake_up(&lm_queue);
581}
582
583//-----------------------------------------------------------------------------
584// Function : VIRQ_uni_irqhandler
585// Inputs : void
586// Outputs : void
587// Description:
588//-----------------------------------------------------------------------------
589static void VIRQ_uni_irqhandler(int virq_mask)
590{
591 int iackvec, i;
592
593 for (i = 7; i > 0; i--) {
594 if (virq_mask & (1 << i)) {
595 Interrupt_counters.virq[i - 1]++;
596 iackvec = readl(vmechip_baseaddr + vmevec[i - 1]);
597 vme_irqlog[i][iackvec]++;
598 }
599 }
600}
601
602//-----------------------------------------------------------------------------
603// Function : uni_irqhandler
604// Inputs : int irq, void *dev_id, struct pt_regs *regs
605// Outputs : void
606// Description:
607//-----------------------------------------------------------------------------
608static irqreturn_t uni_irqhandler(int irq, void *dev_id)
609{
610 long stat, enable;
611
612 if (dev_id != vmechip_baseaddr)
613 return IRQ_NONE;
614
615 uni_irq_time = get_tbl();
616
617 stat = readl(vmechip_baseaddr + LINT_STAT);
618 writel(stat, vmechip_baseaddr + LINT_STAT); // Clear all pending ints
619 enable = readl(vmechip_baseaddr + LINT_EN);
620 stat = stat & enable;
621 if (stat & 0x0100) {
622 Interrupt_counters.dma++;
623 DMA_uni_irqhandler();
624 }
625 if (stat & 0x0200) {
626 Interrupt_counters.lerr++;
627 LERR_uni_irqhandler();
628 }
629 if (stat & 0x0400) {
630 Interrupt_counters.verr++;
631 VERR_uni_irqhandler();
632 }
633 if (stat & 0xF0000) {
634 Interrupt_counters.mbox++;
635 MB_uni_irqhandler((stat & 0xF0000) >> 16);
636 }
637 if (stat & 0xF00000) {
638 Interrupt_counters.lm++;
639 LM_uni_irqhandler((stat & 0xF00000) >> 20);
640 }
641 if (stat & 0x0000FE) {
642 VIRQ_uni_irqhandler(stat & 0x0000FE);
643 }
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
660 return IRQ_HANDLED;
661}
662
663//-----------------------------------------------------------------------------
664// Function : uni_generate_irq
665// Description:
666//-----------------------------------------------------------------------------
667int uni_generate_irq(virqInfo_t * vmeIrq)
668{
669 int timeout;
670 int looptimeout;
671
672 timeout = vmeIrq->waitTime;
673 if (timeout == 0) {
674 timeout++; // Wait at least 1 tick...
675 }
676 looptimeout = HZ / 20; // try for 1/20 second
677
678 vmeIrq->timeOutFlag = 0;
679
680 // Validate & setup vector register.
681 if (vmeIrq->vector & 1) { // Universe can only generate even vectors
682 return (-EINVAL);
683 }
684 writel(vmeIrq->vector << 24, vmechip_baseaddr + STATID);
685
686 // Assert VMEbus IRQ
687 writel(1 << (vmeIrq->level + 24), vmechip_baseaddr + VINT_EN);
688
689 // Wait for syscon to do iack
690 while (readl(vmechip_baseaddr + VINT_STAT) &
691 (1 << (vmeIrq->level + 24))) {
692 set_current_state(TASK_INTERRUPTIBLE);
693 schedule_timeout(looptimeout);
694 timeout = timeout - looptimeout;
695 if (timeout <= 0) {
696 vmeIrq->timeOutFlag = 1;
697 break;
698 }
699 }
700
701 // Clear VMEbus IRQ bit
702 writel(0, vmechip_baseaddr + VINT_EN);
703
704 return (0);
705}
706
707//-----------------------------------------------------------------------------
708// Function : uni_set_arbiter
709// Description:
710//-----------------------------------------------------------------------------
711int uni_set_arbiter(vmeArbiterCfg_t * vmeArb)
712{
713 int temp_ctl = 0;
714 int vbto = 0;
715
716 temp_ctl = readl(vmechip_baseaddr + MISC_CTL);
717 temp_ctl &= 0x00FFFFFF;
718
719 if (vmeArb->globalTimeoutTimer == 0xFFFFFFFF) {
720 vbto = 7;
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
733 if (vmeArb->arbiterMode == VME_PRIORITY_MODE) {
734 temp_ctl |= 1 << 26;
735 }
736
737 if (vmeArb->arbiterTimeoutFlag) {
738 temp_ctl |= 2 << 24;
739 }
740
741 writel(temp_ctl, vmechip_baseaddr + MISC_CTL);
742 return (0);
743}
744
745//-----------------------------------------------------------------------------
746// Function : uni_get_arbiter
747// Description:
748//-----------------------------------------------------------------------------
749int uni_get_arbiter(vmeArbiterCfg_t * vmeArb)
750{
751 int temp_ctl = 0;
752 int vbto = 0;
753
754 temp_ctl = readl(vmechip_baseaddr + MISC_CTL);
755
756 vbto = (temp_ctl >> 28) & 0xF;
757 if (vbto != 0) {
758 vmeArb->globalTimeoutTimer = (16 * (1 << (vbto - 1)));
759 }
760
761 if (temp_ctl & (1 << 26)) {
762 vmeArb->arbiterMode = VME_PRIORITY_MODE;
763 } else {
764 vmeArb->arbiterMode = VME_R_ROBIN_MODE;
765 }
766
767 if (temp_ctl & (3 << 24)) {
768 vmeArb->arbiterTimeoutFlag = 1;
769 }
770 return (0);
771}
772
773//-----------------------------------------------------------------------------
774// Function : uni_set_requestor
775// Description:
776//-----------------------------------------------------------------------------
777int uni_set_requestor(vmeRequesterCfg_t * vmeReq)
778{
779 int temp_ctl = 0;
780
781 temp_ctl = readl(vmechip_baseaddr + MAST_CTL);
782 temp_ctl &= 0xFF0FFFFF;
783
784 if (vmeReq->releaseMode == 1) {
785 temp_ctl |= (1 << 20);
786 }
787
788 if (vmeReq->fairMode == 1) {
789 temp_ctl |= (1 << 21);
790 }
791
792 temp_ctl |= (vmeReq->requestLevel << 22);
793
794 writel(temp_ctl, vmechip_baseaddr + MAST_CTL);
795 return (0);
796}
797
798//-----------------------------------------------------------------------------
799// Function : uni_get_requestor
800// Description:
801//-----------------------------------------------------------------------------
802int uni_get_requestor(vmeRequesterCfg_t * vmeReq)
803{
804 int temp_ctl = 0;
805
806 temp_ctl = readl(vmechip_baseaddr + MAST_CTL);
807
808 if (temp_ctl & (1 << 20)) {
809 vmeReq->releaseMode = 1;
810 }
811
812 if (temp_ctl & (1 << 21)) {
813 vmeReq->fairMode = 1;
814 }
815
816 vmeReq->requestLevel = (temp_ctl & 0xC00000) >> 22;
817
818 return (0);
819}
820
821//-----------------------------------------------------------------------------
822// Function : uni_set_in_bound
823// Description:
824//-----------------------------------------------------------------------------
825int uni_set_in_bound(vmeInWindowCfg_t * vmeIn)
826{
827 int temp_ctl = 0;
828
829 // Verify input data
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
841 if (vmeIn->bcastRespond2esst) {
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:
851 temp_ctl |= 0x00000;
852 break;
853 case VME_A24:
854 temp_ctl |= 0x10000;
855 break;
856 case VME_A32:
857 temp_ctl |= 0x20000;
858 break;
859 case VME_USER1:
860 temp_ctl |= 0x60000;
861 break;
862 case VME_USER2:
863 temp_ctl |= 0x70000;
864 break;
865 }
866
867 // Disable while we are mucking around
868 writel(0x00000000, vmechip_baseaddr + inCTL[vmeIn->windowNbr]);
869 writel(vmeIn->vmeAddrL, vmechip_baseaddr + inBS[vmeIn->windowNbr]);
870 writel(vmeIn->vmeAddrL + vmeIn->windowSizeL,
871 vmechip_baseaddr + inBD[vmeIn->windowNbr]);
872 writel(vmeIn->pciAddrL - vmeIn->vmeAddrL,
873 vmechip_baseaddr + inTO[vmeIn->windowNbr]);
874
875 // Setup CTL register.
876 if (vmeIn->wrPostEnable)
877 temp_ctl |= 0x40000000;
878 if (vmeIn->prefetchEnable)
879 temp_ctl |= 0x20000000;
880 if (vmeIn->rmwLock)
881 temp_ctl |= 0x00000040;
882 if (vmeIn->data64BitCapable)
883 temp_ctl |= 0x00000080;
884 if (vmeIn->userAccessType & VME_USER)
885 temp_ctl |= 0x00100000;
886 if (vmeIn->userAccessType & VME_SUPER)
887 temp_ctl |= 0x00200000;
888 if (vmeIn->dataAccessType & VME_DATA)
889 temp_ctl |= 0x00400000;
890 if (vmeIn->dataAccessType & VME_PROG)
891 temp_ctl |= 0x00800000;
892
893 // Write ctl reg without enable
894 writel(temp_ctl, vmechip_baseaddr + inCTL[vmeIn->windowNbr]);
895
896 if (vmeIn->windowEnable)
897 temp_ctl |= 0x80000000;
898
899 writel(temp_ctl, vmechip_baseaddr + inCTL[vmeIn->windowNbr]);
900 return (0);
901}
902
903//-----------------------------------------------------------------------------
904// Function : uni_get_in_bound
905// Description:
906//-----------------------------------------------------------------------------
907int uni_get_in_bound(vmeInWindowCfg_t * vmeIn)
908{
909 int temp_ctl = 0;
910
911 // Verify input data
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
962 return (0);
963}
964
965//-----------------------------------------------------------------------------
966// Function : uni_set_out_bound
967// Description:
968//-----------------------------------------------------------------------------
969int uni_set_out_bound(vmeOutWindowCfg_t * vmeOut)
970{
971 int temp_ctl = 0;
972
973 // Verify input data
974 if (vmeOut->windowNbr > 7) {
975 return (-EINVAL);
976 }
977 if ((vmeOut->xlatedAddrU) || (vmeOut->windowSizeU)
978 || (vmeOut->pciBusAddrU)) {
979 return (-EINVAL);
980 }
981 if ((vmeOut->xlatedAddrL & 0xFFF) ||
982 (vmeOut->windowSizeL & 0xFFF) || (vmeOut->pciBusAddrL & 0xFFF)) {
983 return (-EINVAL);
984 }
985 if (vmeOut->bcastSelect2esst) {
986 return (-EINVAL);
987 }
988 switch (vmeOut->addrSpace) {
989 case VME_A64:
990 case VME_USER3:
991 case VME_USER4:
992 return (-EINVAL);
993 case VME_A16:
994 temp_ctl |= 0x00000;
995 break;
996 case VME_A24:
997 temp_ctl |= 0x10000;
998 break;
999 case VME_A32:
1000 temp_ctl |= 0x20000;
1001 break;
1002 case VME_CRCSR:
1003 temp_ctl |= 0x50000;
1004 break;
1005 case VME_USER1:
1006 temp_ctl |= 0x60000;
1007 break;
1008 case VME_USER2:
1009 temp_ctl |= 0x70000;
1010 break;
1011 }
1012
1013 // Disable while we are mucking around
1014 writel(0x00000000, vmechip_baseaddr + outCTL[vmeOut->windowNbr]);
1015 writel(vmeOut->pciBusAddrL,
1016 vmechip_baseaddr + outBS[vmeOut->windowNbr]);
1017 writel(vmeOut->pciBusAddrL + vmeOut->windowSizeL,
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
1062 // Write ctl reg without enable
1063 writel(temp_ctl, vmechip_baseaddr + outCTL[vmeOut->windowNbr]);
1064
1065 if (vmeOut->windowEnable)
1066 temp_ctl |= 0x80000000;
1067
1068 writel(temp_ctl, vmechip_baseaddr + outCTL[vmeOut->windowNbr]);
1069 return (0);
1070}
1071
1072//-----------------------------------------------------------------------------
1073// Function : uni_get_out_bound
1074// Description:
1075//-----------------------------------------------------------------------------
1076int uni_get_out_bound(vmeOutWindowCfg_t * vmeOut)
1077{
1078 int temp_ctl = 0;
1079
1080 // Verify input data
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
1094 temp_ctl = readl(vmechip_baseaddr + outCTL[vmeOut->windowNbr]);
1095
1096 // Get Control & BUS attributes
1097 if (temp_ctl & 0x40000000)
1098 vmeOut->wrPostEnable = 1;
1099 if (temp_ctl & 0x001000)
1100 vmeOut->userAccessType = VME_SUPER;
1101 else
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
1110 switch ((temp_ctl & 0x00C00000) >> 22) {
1111 case 0:
1112 vmeOut->maxDataWidth = VME_D8;
1113 break;
1114 case 1:
1115 vmeOut->maxDataWidth = VME_D16;
1116 break;
1117 case 2:
1118 vmeOut->maxDataWidth = VME_D32;
1119 break;
1120 case 3:
1121 vmeOut->maxDataWidth = VME_D64;
1122 break;
1123 }
1124 if (temp_ctl & 0x00000100)
1125 vmeOut->xferProtocol = VME_BLT;
1126 else
1127 vmeOut->xferProtocol = VME_SCT;
1128
1129 switch ((temp_ctl & 0x70000) >> 16) {
1130 case 0x0:
1131 vmeOut->addrSpace = VME_A16;
1132 break;
1133 case 0x1:
1134 vmeOut->addrSpace = VME_A24;
1135 break;
1136 case 0x2:
1137 vmeOut->addrSpace = VME_A32;
1138 break;
1139 case 0x5:
1140 vmeOut->addrSpace = VME_CRCSR;
1141 break;
1142 case 0x6:
1143 vmeOut->addrSpace = VME_USER1;
1144 break;
1145 case 0x7:
1146 vmeOut->addrSpace = VME_USER2;
1147 break;
1148 }
1149
1150 return (0);
1151}
1152
1153//-----------------------------------------------------------------------------
1154// Function : uni_setup_lm
1155// Description:
1156//-----------------------------------------------------------------------------
1157int uni_setup_lm(vmeLmCfg_t * vmeLm)
1158{
1159 int temp_ctl = 0;
1160
1161 if (vmeLm->addrU) {
1162 return (-EINVAL);
1163 }
1164 switch (vmeLm->addrSpace) {
1165 case VME_A64:
1166 case VME_USER3:
1167 case VME_USER4:
1168 return (-EINVAL);
1169 case VME_A16:
1170 temp_ctl |= 0x00000;
1171 break;
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 }
1188
1189 // Disable while we are mucking around
1190 writel(0x00000000, vmechip_baseaddr + LM_CTL);
1191
1192 writel(vmeLm->addr, vmechip_baseaddr + LM_BS);
1193
1194 // Setup CTL register.
1195 if (vmeLm->userAccessType & VME_SUPER)
1196 temp_ctl |= 0x00200000;
1197 if (vmeLm->userAccessType & VME_USER)
1198 temp_ctl |= 0x00100000;
1199 if (vmeLm->dataAccessType & VME_PROG)
1200 temp_ctl |= 0x00800000;
1201 if (vmeLm->dataAccessType & VME_DATA)
1202 temp_ctl |= 0x00400000;
1203
1204 uni_lm_event = 0;
1205
1206 // Write ctl reg and enable
1207 writel(0x80000000 | temp_ctl, vmechip_baseaddr + LM_CTL);
1208 temp_ctl = readl(vmechip_baseaddr + LM_CTL);
1209
1210 return (0);
1211}
1212
1213//-----------------------------------------------------------------------------
1214// Function : uni_wait_lm
1215// Description:
1216//-----------------------------------------------------------------------------
1217int uni_wait_lm(vmeLmCfg_t * vmeLm)
1218{
1219 unsigned long flags;
1220 unsigned int tmp;
1221
1222 spin_lock_irqsave(&lm_lock, flags);
1223 tmp = uni_lm_event;
1224 spin_unlock_irqrestore(&lm_lock, flags);
1225 if (tmp == 0) {
1226 if (vmeLm->lmWait < 10)
1227 vmeLm->lmWait = 10;
1228 interruptible_sleep_on_timeout(&lm_queue, vmeLm->lmWait);
1229 }
1230 writel(0x00000000, vmechip_baseaddr + LM_CTL);
1231 vmeLm->lmEvents = uni_lm_event;
1232
1233 return (0);
1234}
1235
1236#define SWIZZLE(X) ( ((X & 0xFF000000) >> 24) | ((X & 0x00FF0000) >> 8) | ((X & 0x0000FF00) << 8) | ((X & 0x000000FF) << 24))
1237
1238//-----------------------------------------------------------------------------
1239// Function : uni_do_rmw
1240// Description:
1241//-----------------------------------------------------------------------------
1242int uni_do_rmw(vmeRmwCfg_t * vmeRmw)
1243{
1244 int temp_ctl = 0;
1245 int tempBS = 0;
1246 int tempBD = 0;
1247 int tempTO = 0;
1248 int vmeBS = 0;
1249 int vmeBD = 0;
1250 int *rmw_pci_data_ptr = NULL;
1251 int *vaDataPtr = NULL;
1252 int i;
1253 vmeOutWindowCfg_t vmeOut;
1254 if (vmeRmw->maxAttempts < 1) {
1255 return (-EINVAL);
1256 }
1257 if (vmeRmw->targetAddrU) {
1258 return (-EINVAL);
1259 }
1260 // Find the PCI address that maps to the desired VME address
1261 for (i = 0; i < 8; i++) {
1262 temp_ctl = readl(vmechip_baseaddr + outCTL[i]);
1263 if ((temp_ctl & 0x80000000) == 0) {
1264 continue;
1265 }
1266 memset(&vmeOut, 0, sizeof(vmeOut));
1267 vmeOut.windowNbr = i;
1268 uni_get_out_bound(&vmeOut);
1269 if (vmeOut.addrSpace != vmeRmw->addrSpace) {
1270 continue;
1271 }
1272 tempBS = readl(vmechip_baseaddr + outBS[i]);
1273 tempBD = readl(vmechip_baseaddr + outBD[i]);
1274 tempTO = readl(vmechip_baseaddr + outTO[i]);
1275 vmeBS = tempBS + tempTO;
1276 vmeBD = tempBD + tempTO;
1277 if ((vmeRmw->targetAddr >= vmeBS) &&
1278 (vmeRmw->targetAddr < vmeBD)) {
1279 rmw_pci_data_ptr =
1280 (int *)(tempBS + (vmeRmw->targetAddr - vmeBS));
1281 vaDataPtr =
1282 (int *)(out_image_va[i] +
1283 (vmeRmw->targetAddr - vmeBS));
1284 break;
1285 }
1286 }
1287
1288 // If no window - fail.
1289 if (rmw_pci_data_ptr == NULL) {
1290 return (-EINVAL);
1291 }
1292 // Setup the RMW registers.
1293 writel(0, vmechip_baseaddr + SCYC_CTL);
1294 writel(SWIZZLE(vmeRmw->enableMask), vmechip_baseaddr + SCYC_EN);
1295 writel(SWIZZLE(vmeRmw->compareData), vmechip_baseaddr + SCYC_CMP);
1296 writel(SWIZZLE(vmeRmw->swapData), vmechip_baseaddr + SCYC_SWP);
1297 writel((int)rmw_pci_data_ptr, vmechip_baseaddr + SCYC_ADDR);
1298 writel(1, vmechip_baseaddr + SCYC_CTL);
1299
1300 // Run the RMW cycle until either success or max attempts.
1301 vmeRmw->numAttempts = 1;
1302 while (vmeRmw->numAttempts <= vmeRmw->maxAttempts) {
1303
1304 if ((readl(vaDataPtr) & vmeRmw->enableMask) ==
1305 (vmeRmw->swapData & vmeRmw->enableMask)) {
1306
1307 writel(0, vmechip_baseaddr + SCYC_CTL);
1308 break;
1309
1310 }
1311 vmeRmw->numAttempts++;
1312 }
1313
1314 // If no success, set num Attempts to be greater than max attempts
1315 if (vmeRmw->numAttempts > vmeRmw->maxAttempts) {
1316 vmeRmw->numAttempts = vmeRmw->maxAttempts + 1;
1317 }
1318
1319 return (0);
1320}
1321
1322//-----------------------------------------------------------------------------
1323// Function : uniSetupDctlReg
1324// Description:
1325//-----------------------------------------------------------------------------
1326int uniSetupDctlReg(vmeDmaPacket_t * vmeDma, int *dctlregreturn)
1327{
1328 unsigned int dctlreg = 0x80;
1329 struct vmeAttr *vmeAttr;
1330
1331 if (vmeDma->srcBus == VME_DMA_VME) {
1332 dctlreg = 0;
1333 vmeAttr = &vmeDma->srcVmeAttr;
1334 } else {
1335 dctlreg = 0x80000000;
1336 vmeAttr = &vmeDma->dstVmeAttr;
1337 }
1338
1339 switch (vmeAttr->maxDataWidth) {
1340 case VME_D8:
1341 break;
1342 case VME_D16:
1343 dctlreg |= 0x00400000;
1344 break;
1345 case VME_D32:
1346 dctlreg |= 0x00800000;
1347 break;
1348 case VME_D64:
1349 dctlreg |= 0x00C00000;
1350 break;
1351 }
1352
1353 switch (vmeAttr->addrSpace) {
1354 case VME_A16:
1355 break;
1356 case VME_A24:
1357 dctlreg |= 0x00010000;
1358 break;
1359 case VME_A32:
1360 dctlreg |= 0x00020000;
1361 break;
1362 case VME_USER1:
1363 dctlreg |= 0x00060000;
1364 break;
1365 case VME_USER2:
1366 dctlreg |= 0x00070000;
1367 break;
1368
1369 case VME_A64: // not supported in Universe DMA
1370 case VME_CRCSR:
1371 case VME_USER3:
1372 case VME_USER4:
1373 return (-EINVAL);
1374 break;
1375 }
1376 if (vmeAttr->userAccessType == VME_PROG) {
1377 dctlreg |= 0x00004000;
1378 }
1379 if (vmeAttr->dataAccessType == VME_SUPER) {
1380 dctlreg |= 0x00001000;
1381 }
1382 if (vmeAttr->xferProtocol != VME_SCT) {
1383 dctlreg |= 0x00000100;
1384 }
1385 *dctlregreturn = dctlreg;
1386 return (0);
1387}
1388
1389//-----------------------------------------------------------------------------
1390// Function : uni_start_dma
1391// Description:
1392//-----------------------------------------------------------------------------
1393unsigned int
1394uni_start_dma(int channel, unsigned int dgcsreg, TDMA_Cmd_Packet * vmeLL)
1395{
1396 unsigned int val;
1397
1398 // Setup registers as needed for direct or chained.
1399 if (dgcsreg & 0x8000000) {
1400 writel(0, vmechip_baseaddr + DTBC);
1401 writel((unsigned int)vmeLL, vmechip_baseaddr + DCPP);
1402 } else {
1403#if 0
1404 printk("Starting: DGCS = %08x\n", dgcsreg);
1405 printk("Starting: DVA = %08x\n", readl(&vmeLL->dva));
1406 printk("Starting: DLV = %08x\n", readl(&vmeLL->dlv));
1407 printk("Starting: DTBC = %08x\n", readl(&vmeLL->dtbc));
1408 printk("Starting: DCTL = %08x\n", readl(&vmeLL->dctl));
1409#endif
1410 // Write registers
1411 writel(readl(&vmeLL->dva), vmechip_baseaddr + DVA);
1412 writel(readl(&vmeLL->dlv), vmechip_baseaddr + DLA);
1413 writel(readl(&vmeLL->dtbc), vmechip_baseaddr + DTBC);
1414 writel(readl(&vmeLL->dctl), vmechip_baseaddr + DCTL);
1415 writel(0, vmechip_baseaddr + DCPP);
1416 }
1417
1418 // Start the operation
1419 writel(dgcsreg, vmechip_baseaddr + DGCS);
1420 val = get_tbl();
1421 writel(dgcsreg | 0x8000000F, vmechip_baseaddr + DGCS);
1422 return (val);
1423}
1424
1425//-----------------------------------------------------------------------------
1426// Function : uni_setup_dma
1427// Description:
1428//-----------------------------------------------------------------------------
1429TDMA_Cmd_Packet *uni_setup_dma(vmeDmaPacket_t * vmeDma)
1430{
1431 vmeDmaPacket_t *vmeCur;
1432 int maxPerPage;
1433 int currentLLcount;
1434 TDMA_Cmd_Packet *startLL;
1435 TDMA_Cmd_Packet *currentLL;
1436 TDMA_Cmd_Packet *nextLL;
1437 unsigned int dctlreg = 0;
1438
1439 maxPerPage = PAGESIZE / sizeof(TDMA_Cmd_Packet) - 1;
1440 startLL = (TDMA_Cmd_Packet *) __get_free_pages(GFP_KERNEL, 0);
1441 if (startLL == 0) {
1442 return (startLL);
1443 }
1444 // First allocate pages for descriptors and create linked list
1445 vmeCur = vmeDma;
1446 currentLL = startLL;
1447 currentLLcount = 0;
1448 while (vmeCur != 0) {
1449 if (vmeCur->pNextPacket != 0) {
1450 currentLL->dcpp = (unsigned int)(currentLL + 1);
1451 currentLLcount++;
1452 if (currentLLcount >= maxPerPage) {
1453 currentLL->dcpp =
1454 __get_free_pages(GFP_KERNEL, 0);
1455 currentLLcount = 0;
1456 }
1457 currentLL = (TDMA_Cmd_Packet *) currentLL->dcpp;
1458 } else {
1459 currentLL->dcpp = (unsigned int)0;
1460 }
1461 vmeCur = vmeCur->pNextPacket;
1462 }
1463
1464 // Next fill in information for each descriptor
1465 vmeCur = vmeDma;
1466 currentLL = startLL;
1467 while (vmeCur != 0) {
1468 if (vmeCur->srcBus == VME_DMA_VME) {
1469 writel(vmeCur->srcAddr, &currentLL->dva);
1470 writel(vmeCur->dstAddr, &currentLL->dlv);
1471 } else {
1472 writel(vmeCur->srcAddr, &currentLL->dlv);
1473 writel(vmeCur->dstAddr, &currentLL->dva);
1474 }
1475 uniSetupDctlReg(vmeCur, &dctlreg);
1476 writel(dctlreg, &currentLL->dctl);
1477 writel(vmeCur->byteCount, &currentLL->dtbc);
1478
1479 currentLL = (TDMA_Cmd_Packet *) currentLL->dcpp;
1480 vmeCur = vmeCur->pNextPacket;
1481 }
1482
1483 // Convert Links to PCI addresses.
1484 currentLL = startLL;
1485 while (currentLL != 0) {
1486 nextLL = (TDMA_Cmd_Packet *) currentLL->dcpp;
1487 if (nextLL == 0) {
1488 writel(1, &currentLL->dcpp);
1489 } else {
1490 writel((unsigned int)virt_to_bus(nextLL),
1491 &currentLL->dcpp);
1492 }
1493 currentLL = nextLL;
1494 }
1495
1496 // Return pointer to descriptors list
1497 return (startLL);
1498}
1499
1500//-----------------------------------------------------------------------------
1501// Function : uni_free_dma
1502// Description:
1503//-----------------------------------------------------------------------------
1504int uni_free_dma(TDMA_Cmd_Packet * startLL)
1505{
1506 TDMA_Cmd_Packet *currentLL;
1507 TDMA_Cmd_Packet *prevLL;
1508 TDMA_Cmd_Packet *nextLL;
1509 unsigned int dcppreg;
1510
1511 // Convert Links to virtual addresses.
1512 currentLL = startLL;
1513 while (currentLL != 0) {
1514 dcppreg = readl(&currentLL->dcpp);
1515 dcppreg &= ~6;
1516 if (dcppreg & 1) {
1517 currentLL->dcpp = 0;
1518 } else {
1519 currentLL->dcpp = (unsigned int)bus_to_virt(dcppreg);
1520 }
1521 currentLL = (TDMA_Cmd_Packet *) currentLL->dcpp;
1522 }
1523
1524 // Free all pages associated with the descriptors.
1525 currentLL = startLL;
1526 prevLL = currentLL;
1527 while (currentLL != 0) {
1528 nextLL = (TDMA_Cmd_Packet *) currentLL->dcpp;
1529 if (currentLL + 1 != nextLL) {
1530 free_pages((int)prevLL, 0);
1531 prevLL = nextLL;
1532 }
1533 currentLL = nextLL;
1534 }
1535
1536 // Return pointer to descriptors list
1537 return (0);
1538}
1539
1540//-----------------------------------------------------------------------------
1541// Function : uni_do_dma
1542// Description:
1543//-----------------------------------------------------------------------------
1544int uni_do_dma(vmeDmaPacket_t * vmeDma)
1545{
1546 unsigned int dgcsreg = 0;
1547 unsigned int dctlreg = 0;
1548 int val;
1549 int channel, x;
1550 vmeDmaPacket_t *curDma;
1551 TDMA_Cmd_Packet *dmaLL;
1552
1553 // Sanity check the VME chain.
1554 channel = vmeDma->channel_number;
1555 if (channel > 0) {
1556 return (-EINVAL);
1557 }
1558 curDma = vmeDma;
1559 while (curDma != 0) {
1560 if (curDma->byteCount == 0) {
1561 return (-EINVAL);
1562 }
1563 if (curDma->byteCount >= 0x1000000) {
1564 return (-EINVAL);
1565 }
1566 if ((curDma->srcAddr & 7) != (curDma->dstAddr & 7)) {
1567 return (-EINVAL);
1568 }
1569 switch (curDma->srcBus) {
1570 case VME_DMA_PCI:
1571 if (curDma->dstBus != VME_DMA_VME) {
1572 return (-EINVAL);
1573 }
1574 break;
1575 case VME_DMA_VME:
1576 if (curDma->dstBus != VME_DMA_PCI) {
1577 return (-EINVAL);
1578 }
1579 break;
1580 default:
1581 return (-EINVAL);
1582 break;
1583 }
1584 if (uniSetupDctlReg(curDma, &dctlreg) < 0) {
1585 return (-EINVAL);
1586 }
1587
1588 curDma = curDma->pNextPacket;
1589 if (curDma == vmeDma) { // Endless Loop!
1590 return (-EINVAL);
1591 }
1592 }
1593
1594 // calculate control register
1595 if (vmeDma->pNextPacket != 0) {
1596 dgcsreg = 0x8000000;
1597 } else {
1598 dgcsreg = 0;
1599 }
1600
1601 for (x = 0; x < 8; x++) { // vme block size
1602 if ((256 << x) >= vmeDma->maxVmeBlockSize) {
1603 break;
1604 }
1605 }
1606 if (x == 8)
1607 x = 7;
1608 dgcsreg |= (x << 20);
1609
1610 if (vmeDma->vmeBackOffTimer) {
1611 for (x = 1; x < 8; x++) { // vme timer
1612 if ((16 << (x - 1)) >= vmeDma->vmeBackOffTimer) {
1613 break;
1614 }
1615 }
1616 if (x == 8)
1617 x = 7;
1618 dgcsreg |= (x << 16);
1619 }
1620 // Setup the dma chain
1621 dmaLL = uni_setup_dma(vmeDma);
1622
1623 // Start the DMA
1624 if (dgcsreg & 0x8000000) {
1625 vmeDma->vmeDmaStartTick =
1626 uni_start_dma(channel, dgcsreg,
1627 (TDMA_Cmd_Packet *) virt_to_phys(dmaLL));
1628 } else {
1629 vmeDma->vmeDmaStartTick =
1630 uni_start_dma(channel, dgcsreg, dmaLL);
1631 }
1632
1633 wait_event_interruptible(dma_queue[0],
1634 readl(vmechip_baseaddr + DGCS) & 0x800);
1635
1636 val = readl(vmechip_baseaddr + DGCS);
1637 writel(val | 0xF00, vmechip_baseaddr + DGCS);
1638
1639 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
1652 if (!(val & 0x00000800)) {
1653 vmeDma->vmeDmaStatus = val & 0x700;
1654 printk(KERN_ERR
1655 "ca91c042: DMA Error in DMA_uni_irqhandler DGCS=%08X\n",
1656 val);
1657 val = readl(vmechip_baseaddr + DCPP);
1658 printk(KERN_ERR "ca91c042: DCPP=%08X\n", val);
1659 val = readl(vmechip_baseaddr + DCTL);
1660 printk(KERN_ERR "ca91c042: DCTL=%08X\n", val);
1661 val = readl(vmechip_baseaddr + DTBC);
1662 printk(KERN_ERR "ca91c042: DTBC=%08X\n", val);
1663 val = readl(vmechip_baseaddr + DLA);
1664 printk(KERN_ERR "ca91c042: DLA=%08X\n", val);
1665 val = readl(vmechip_baseaddr + DVA);
1666 printk(KERN_ERR "ca91c042: DVA=%08X\n", val);
1667
1668 }
1669 // Free the dma chain
1670 uni_free_dma(dmaLL);
1671
1672 return (0);
1673}
1674
1675//-----------------------------------------------------------------------------
1676// Function : uni_shutdown
1677// Description: Put VME bridge in quiescent state.
1678//-----------------------------------------------------------------------------
1679void uni_shutdown(void)
1680{
1681 writel(0, vmechip_baseaddr + LINT_EN); // Turn off Ints
1682
1683 // Turn off the windows
1684 writel(0x00800000, vmechip_baseaddr + LSI0_CTL);
1685 writel(0x00800000, vmechip_baseaddr + LSI1_CTL);
1686 writel(0x00800000, vmechip_baseaddr + LSI2_CTL);
1687 writel(0x00800000, vmechip_baseaddr + LSI3_CTL);
1688 writel(0x00F00000, vmechip_baseaddr + VSI0_CTL);
1689 writel(0x00F00000, vmechip_baseaddr + VSI1_CTL);
1690 writel(0x00F00000, vmechip_baseaddr + VSI2_CTL);
1691 writel(0x00F00000, vmechip_baseaddr + VSI3_CTL);
1692 if (vmechip_revision >= 2) {
1693 writel(0x00800000, vmechip_baseaddr + LSI4_CTL);
1694 writel(0x00800000, vmechip_baseaddr + LSI5_CTL);
1695 writel(0x00800000, vmechip_baseaddr + LSI6_CTL);
1696 writel(0x00800000, vmechip_baseaddr + LSI7_CTL);
1697 writel(0x00F00000, vmechip_baseaddr + VSI4_CTL);
1698 writel(0x00F00000, vmechip_baseaddr + VSI5_CTL);
1699 writel(0x00F00000, vmechip_baseaddr + VSI6_CTL);
1700 writel(0x00F00000, vmechip_baseaddr + VSI7_CTL);
1701 }
1702}
1703
1704//-----------------------------------------------------------------------------
1705// Function : uni_init()
1706// Description:
1707//-----------------------------------------------------------------------------
1708int uni_init(void)
1709{
1710 int result;
1711 unsigned int tmp;
1712 unsigned int crcsr_addr;
1713 unsigned int irqOverHeadStart;
1714 int overHeadTicks;
1715
1716 uni_shutdown();
1717
1718 // Write to Misc Register
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 }
1766
1767 // Enable DMA, mailbox, VIRQ & LM Interrupts
1768 if (vme_syscon)
1769 tmp = 0x00FF07FE;
1770 else
1771 tmp = 0x00FF0700;
1772 writel(tmp, vmechip_baseaddr + LINT_EN);
1773
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
1792 // do a mail box interrupt to calibrate the interrupt overhead.
1793
1794 irqOverHeadStart = get_tbl();
1795 writel(0, vmechip_baseaddr + MBOX1);
1796 for (tmp = 0; tmp < 10; tmp++) {
1797 }
1798
1799 irqOverHeadStart = get_tbl();
1800 writel(0, vmechip_baseaddr + MBOX1);
1801 for (tmp = 0; tmp < 10; tmp++) {
1802 }
1803
1804 overHeadTicks = uni_irq_time - irqOverHeadStart;
1805 if (overHeadTicks > 0) {
1806 vmechip_irq_overhead_ticks = overHeadTicks;
1807 } else {
1808 vmechip_irq_overhead_ticks = 1;
1809 }
1810 return (1);
1811}