aboutsummaryrefslogtreecommitdiffstats
path: root/arch/m68k/mac/via.c
diff options
context:
space:
mode:
authorFinn Thain <fthain@telegraphics.com.au>2007-05-01 16:32:56 -0400
committerLinus Torvalds <torvalds@woody.linux-foundation.org>2007-05-04 20:59:07 -0400
commit67dfb153a352e57e71404d550be7eb60d15d7f2d (patch)
tree675db4da976dedeba9c9ffbceb816f56701e9f94 /arch/m68k/mac/via.c
parent647b804c8237aa35e19caf8e11ea8d5565107b0e (diff)
m68k: Mac IRQ prep
Make sure that there are no slot IRQs asserted before leaving the nubus handler. If there are and we don't then the nubus gets wedged because this prevents a CA1 transition, which means no more nubus IRQs. Make the interrupt dispatch loops terminate sooner. Explicitly initialise the VIA latches to make the code more easily understood. Also some cleanups. Signed-off-by: Finn Thain <fthain@telegraphics.com.au> Signed-off-by: Geert Uytterhoeven <geert@linux-m68k.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'arch/m68k/mac/via.c')
-rw-r--r--arch/m68k/mac/via.c141
1 files changed, 87 insertions, 54 deletions
diff --git a/arch/m68k/mac/via.c b/arch/m68k/mac/via.c
index 21b03180d9f4..0c1cc45c570d 100644
--- a/arch/m68k/mac/via.c
+++ b/arch/m68k/mac/via.c
@@ -13,6 +13,10 @@
13 * for info. A full-text web search on 6522 AND VIA will probably also 13 * for info. A full-text web search on 6522 AND VIA will probably also
14 * net some usefulness. <cananian@alumni.princeton.edu> 20apr1999 14 * net some usefulness. <cananian@alumni.princeton.edu> 20apr1999
15 * 15 *
16 * Additional data is here (the SY6522 was used in the Mac II etc):
17 * http://www.6502.org/documents/datasheets/synertek/synertek_sy6522.pdf
18 * http://www.6502.org/documents/datasheets/synertek/synertek_sy6522_programming_reference.pdf
19 *
16 * PRAM/RTC access algorithms are from the NetBSD RTC toolkit version 1.08b 20 * PRAM/RTC access algorithms are from the NetBSD RTC toolkit version 1.08b
17 * by Erik Vogan and adapted to Linux by Joshua M. Thompson (funaho@jurai.org) 21 * by Erik Vogan and adapted to Linux by Joshua M. Thompson (funaho@jurai.org)
18 * 22 *
@@ -37,7 +41,7 @@ volatile __u8 *via1, *via2;
37/* See note in mac_via.h about how this is possibly not useful */ 41/* See note in mac_via.h about how this is possibly not useful */
38volatile long *via_memory_bogon=(long *)&via_memory_bogon; 42volatile long *via_memory_bogon=(long *)&via_memory_bogon;
39#endif 43#endif
40int rbv_present,via_alt_mapping; 44int rbv_present, via_alt_mapping;
41__u8 rbv_clear; 45__u8 rbv_clear;
42 46
43/* 47/*
@@ -138,11 +142,11 @@ void __init via_init(void)
138 142
139 printk(KERN_INFO "VIA2 at %p is ", via2); 143 printk(KERN_INFO "VIA2 at %p is ", via2);
140 if (rbv_present) { 144 if (rbv_present) {
141 printk(KERN_INFO "an RBV\n"); 145 printk("an RBV\n");
142 } else if (oss_present) { 146 } else if (oss_present) {
143 printk(KERN_INFO "an OSS\n"); 147 printk("an OSS\n");
144 } else { 148 } else {
145 printk(KERN_INFO "a 6522 or clone\n"); 149 printk("a 6522 or clone\n");
146 } 150 }
147 151
148#ifdef DEBUG_VIA 152#ifdef DEBUG_VIA
@@ -163,6 +167,7 @@ void __init via_init(void)
163 via1[vT2CL] = 0; 167 via1[vT2CL] = 0;
164 via1[vT2CH] = 0; 168 via1[vT2CH] = 0;
165 via1[vACR] &= 0x3F; 169 via1[vACR] &= 0x3F;
170 via1[vACR] &= ~0x03; /* disable port A & B latches */
166 171
167 /* 172 /*
168 * SE/30: disable video IRQ 173 * SE/30: disable video IRQ
@@ -234,6 +239,22 @@ void __init via_init(void)
234 via2[vT2CL] = 0; 239 via2[vT2CL] = 0;
235 via2[vT2CH] = 0; 240 via2[vT2CH] = 0;
236 via2[vACR] &= 0x3F; 241 via2[vACR] &= 0x3F;
242 via2[vACR] &= ~0x03; /* disable port A & B latches */
243 }
244
245 /*
246 * Set vPCR for SCSI interrupts (but not on RBV)
247 */
248 if (!rbv_present) {
249 if (macintosh_config->scsi_type == MAC_SCSI_OLD) {
250 /* CB2 (IRQ) indep. input, positive edge */
251 /* CA2 (DRQ) indep. input, positive edge */
252 via2[vPCR] = 0x66;
253 } else {
254 /* CB2 (IRQ) indep. input, negative edge */
255 /* CA2 (DRQ) indep. input, negative edge */
256 via2[vPCR] = 0x22;
257 }
237 } 258 }
238} 259}
239 260
@@ -367,19 +388,14 @@ void __init via_nubus_init(void)
367 388
368 /* unlock nubus transactions */ 389 /* unlock nubus transactions */
369 390
370 if (!rbv_present) { 391 if ((macintosh_config->adb_type != MAC_ADB_PB1) &&
392 (macintosh_config->adb_type != MAC_ADB_PB2)) {
371 /* set the line to be an output on non-RBV machines */ 393 /* set the line to be an output on non-RBV machines */
372 if ((macintosh_config->adb_type != MAC_ADB_PB1) && 394 if (!rbv_present)
373 (macintosh_config->adb_type != MAC_ADB_PB2)) {
374 via2[vDirB] |= 0x02; 395 via2[vDirB] |= 0x02;
375 }
376 }
377
378 /* this seems to be an ADB bit on PMU machines */
379 /* according to MkLinux. -- jmt */
380 396
381 if ((macintosh_config->adb_type != MAC_ADB_PB1) && 397 /* this seems to be an ADB bit on PMU machines */
382 (macintosh_config->adb_type != MAC_ADB_PB2)) { 398 /* according to MkLinux. -- jmt */
383 via2[gBufB] |= 0x02; 399 via2[gBufB] |= 0x02;
384 } 400 }
385 401
@@ -420,20 +436,25 @@ void __init via_nubus_init(void)
420 436
421irqreturn_t via1_irq(int irq, void *dev_id) 437irqreturn_t via1_irq(int irq, void *dev_id)
422{ 438{
423 int irq_bit, i; 439 int irq_num;
424 unsigned char events, mask; 440 unsigned char irq_bit, events;
425 441
426 mask = via1[vIER] & 0x7F; 442 events = via1[vIFR] & via1[vIER] & 0x7F;
427 if (!(events = via1[vIFR] & mask)) 443 if (!events)
428 return IRQ_NONE; 444 return IRQ_NONE;
429 445
430 for (i = 0, irq_bit = 1 ; i < 7 ; i++, irq_bit <<= 1) 446 irq_num = VIA1_SOURCE_BASE;
447 irq_bit = 1;
448 do {
431 if (events & irq_bit) { 449 if (events & irq_bit) {
432 via1[vIER] = irq_bit; 450 via1[vIER] = irq_bit;
433 via1[vIFR] = irq_bit; 451 via1[vIFR] = irq_bit;
434 m68k_handle_int(VIA1_SOURCE_BASE + i); 452 m68k_handle_int(irq_num);
435 via1[vIER] = irq_bit | 0x80; 453 via1[vIER] = irq_bit | 0x80;
436 } 454 }
455 ++irq_num;
456 irq_bit <<= 1;
457 } while (events >= irq_bit);
437 458
438#if 0 /* freakin' pmu is doing weird stuff */ 459#if 0 /* freakin' pmu is doing weird stuff */
439 if (!oss_present) { 460 if (!oss_present) {
@@ -454,20 +475,25 @@ irqreturn_t via1_irq(int irq, void *dev_id)
454 475
455irqreturn_t via2_irq(int irq, void *dev_id) 476irqreturn_t via2_irq(int irq, void *dev_id)
456{ 477{
457 int irq_bit, i; 478 int irq_num;
458 unsigned char events, mask; 479 unsigned char irq_bit, events;
459 480
460 mask = via2[gIER] & 0x7F; 481 events = via2[gIFR] & via2[gIER] & 0x7F;
461 if (!(events = via2[gIFR] & mask)) 482 if (!events)
462 return IRQ_NONE; 483 return IRQ_NONE;
463 484
464 for (i = 0, irq_bit = 1 ; i < 7 ; i++, irq_bit <<= 1) 485 irq_num = VIA2_SOURCE_BASE;
486 irq_bit = 1;
487 do {
465 if (events & irq_bit) { 488 if (events & irq_bit) {
466 via2[gIER] = irq_bit; 489 via2[gIER] = irq_bit;
467 via2[gIFR] = irq_bit | rbv_clear; 490 via2[gIFR] = irq_bit | rbv_clear;
468 m68k_handle_int(VIA2_SOURCE_BASE + i); 491 m68k_handle_int(irq_num);
469 via2[gIER] = irq_bit | 0x80; 492 via2[gIER] = irq_bit | 0x80;
470 } 493 }
494 ++irq_num;
495 irq_bit <<= 1;
496 } while (events >= irq_bit);
471 return IRQ_HANDLED; 497 return IRQ_HANDLED;
472} 498}
473 499
@@ -478,19 +504,37 @@ irqreturn_t via2_irq(int irq, void *dev_id)
478 504
479irqreturn_t via_nubus_irq(int irq, void *dev_id) 505irqreturn_t via_nubus_irq(int irq, void *dev_id)
480{ 506{
481 int irq_bit, i; 507 int slot_irq;
482 unsigned char events; 508 unsigned char slot_bit, events;
483 509
484 if (!(events = ~via2[gBufA] & nubus_active)) 510 events = ~via2[gBufA] & 0x7F;
511 if (rbv_present)
512 events &= via2[rSIER];
513 else
514 events &= nubus_active;
515 if (!events)
485 return IRQ_NONE; 516 return IRQ_NONE;
486 517
487 for (i = 0, irq_bit = 1 ; i < 7 ; i++, irq_bit <<= 1) { 518 do {
488 if (events & irq_bit) { 519 slot_irq = IRQ_NUBUS_F;
489 via_irq_disable(NUBUS_SOURCE_BASE + i); 520 slot_bit = 0x40;
490 m68k_handle_int(NUBUS_SOURCE_BASE + i); 521 do {
491 via_irq_enable(NUBUS_SOURCE_BASE + i); 522 if (events & slot_bit) {
492 } 523 events &= ~slot_bit;
493 } 524 m68k_handle_int(slot_irq);
525 }
526 --slot_irq;
527 slot_bit >>= 1;
528 } while (events);
529
530 /* clear the CA1 interrupt and make certain there's no more. */
531 via2[gIFR] = 0x02 | rbv_clear;
532 events = ~via2[gBufA] & 0x7F;
533 if (rbv_present)
534 events &= via2[rSIER];
535 else
536 events &= nubus_active;
537 } while (events);
494 return IRQ_HANDLED; 538 return IRQ_HANDLED;
495} 539}
496 540
@@ -506,20 +550,6 @@ void via_irq_enable(int irq) {
506 if (irq_src == 1) { 550 if (irq_src == 1) {
507 via1[vIER] = irq_bit | 0x80; 551 via1[vIER] = irq_bit | 0x80;
508 } else if (irq_src == 2) { 552 } else if (irq_src == 2) {
509 /*
510 * Set vPCR for SCSI interrupts (but not on RBV)
511 */
512 if ((irq_idx == 0) && !rbv_present) {
513 if (macintosh_config->scsi_type == MAC_SCSI_OLD) {
514 /* CB2 (IRQ) indep. input, positive edge */
515 /* CA2 (DRQ) indep. input, positive edge */
516 via2[vPCR] = 0x66;
517 } else {
518 /* CB2 (IRQ) indep. input, negative edge */
519 /* CA2 (DRQ) indep. input, negative edge */
520 via2[vPCR] = 0x22;
521 }
522 }
523 via2[gIER] = irq_bit | 0x80; 553 via2[gIER] = irq_bit | 0x80;
524 } else if (irq_src == 7) { 554 } else if (irq_src == 7) {
525 nubus_active |= irq_bit; 555 nubus_active |= irq_bit;
@@ -557,9 +587,9 @@ void via_irq_disable(int irq) {
557#endif 587#endif
558 588
559 if (irq_src == 1) { 589 if (irq_src == 1) {
560 via1[vIER] = irq_bit; 590 via1[vIER] = irq_bit & 0x7F;
561 } else if (irq_src == 2) { 591 } else if (irq_src == 2) {
562 via2[gIER] = irq_bit; 592 via2[gIER] = irq_bit & 0x7F;
563 } else if (irq_src == 7) { 593 } else if (irq_src == 7) {
564 if (rbv_present) { 594 if (rbv_present) {
565 /* disable the slot interrupt. SIER works like IER. */ 595 /* disable the slot interrupt. SIER works like IER. */
@@ -586,7 +616,9 @@ void via_irq_clear(int irq) {
586 } else if (irq_src == 2) { 616 } else if (irq_src == 2) {
587 via2[gIFR] = irq_bit | rbv_clear; 617 via2[gIFR] = irq_bit | rbv_clear;
588 } else if (irq_src == 7) { 618 } else if (irq_src == 7) {
589 /* FIXME: hmm.. */ 619 /* FIXME: There is no way to clear an individual nubus slot
620 * IRQ flag, other than getting the device to do it.
621 */
590 } 622 }
591} 623}
592 624
@@ -606,6 +638,7 @@ int via_irq_pending(int irq)
606 } else if (irq_src == 2) { 638 } else if (irq_src == 2) {
607 return via2[gIFR] & irq_bit; 639 return via2[gIFR] & irq_bit;
608 } else if (irq_src == 7) { 640 } else if (irq_src == 7) {
641 /* FIXME: this can't work while a slot irq is disabled! */
609 return ~via2[gBufA] & irq_bit; 642 return ~via2[gBufA] & irq_bit;
610 } 643 }
611 return 0; 644 return 0;