xref: /linux/arch/m68k/mac/via.c (revision b2d0f5d5dc53532e6f07bc546a476a55ebdfe0f3)
1 // SPDX-License-Identifier: GPL-2.0
2 /*
3  *	6522 Versatile Interface Adapter (VIA)
4  *
5  *	There are two of these on the Mac II. Some IRQs are vectored
6  *	via them as are assorted bits and bobs - eg RTC, ADB.
7  *
8  * CSA: Motorola seems to have removed documentation on the 6522 from
9  * their web site; try
10  *     http://nerini.drf.com/vectrex/other/text/chips/6522/
11  *     http://www.zymurgy.net/classic/vic20/vicdet1.htm
12  * and
13  *     http://193.23.168.87/mikro_laborversuche/via_iobaustein/via6522_1.html
14  * for info.  A full-text web search on 6522 AND VIA will probably also
15  * net some usefulness. <cananian@alumni.princeton.edu> 20apr1999
16  *
17  * Additional data is here (the SY6522 was used in the Mac II etc):
18  *     http://www.6502.org/documents/datasheets/synertek/synertek_sy6522.pdf
19  *     http://www.6502.org/documents/datasheets/synertek/synertek_sy6522_programming_reference.pdf
20  *
21  * PRAM/RTC access algorithms are from the NetBSD RTC toolkit version 1.08b
22  * by Erik Vogan and adapted to Linux by Joshua M. Thompson (funaho@jurai.org)
23  *
24  */
25 
26 #include <linux/types.h>
27 #include <linux/kernel.h>
28 #include <linux/mm.h>
29 #include <linux/delay.h>
30 #include <linux/init.h>
31 #include <linux/module.h>
32 #include <linux/irq.h>
33 
34 #include <asm/macintosh.h>
35 #include <asm/macints.h>
36 #include <asm/mac_via.h>
37 #include <asm/mac_psc.h>
38 #include <asm/mac_oss.h>
39 
40 volatile __u8 *via1, *via2;
41 int rbv_present;
42 int via_alt_mapping;
43 EXPORT_SYMBOL(via_alt_mapping);
44 static __u8 rbv_clear;
45 
46 /*
47  * Globals for accessing the VIA chip registers without having to
48  * check if we're hitting a real VIA or an RBV. Normally you could
49  * just hit the combined register (ie, vIER|rIER) but that seems to
50  * break on AV Macs...probably because they actually decode more than
51  * eight address bits. Why can't Apple engineers at least be
52  * _consistently_ lazy?                          - 1999-05-21 (jmt)
53  */
54 
55 static int gIER,gIFR,gBufA,gBufB;
56 
57 /*
58  * Timer defs.
59  */
60 
61 #define TICK_SIZE		10000
62 #define MAC_CLOCK_TICK		(783300/HZ)		/* ticks per HZ */
63 #define MAC_CLOCK_LOW		(MAC_CLOCK_TICK&0xFF)
64 #define MAC_CLOCK_HIGH		(MAC_CLOCK_TICK>>8)
65 
66 
67 /*
68  * On Macs with a genuine VIA chip there is no way to mask an individual slot
69  * interrupt. This limitation also seems to apply to VIA clone logic cores in
70  * Quadra-like ASICs. (RBV and OSS machines don't have this limitation.)
71  *
72  * We used to fake it by configuring the relevant VIA pin as an output
73  * (to mask the interrupt) or input (to unmask). That scheme did not work on
74  * (at least) the Quadra 700. A NuBus card's /NMRQ signal is an open-collector
75  * circuit (see Designing Cards and Drivers for Macintosh II and Macintosh SE,
76  * p. 10-11 etc) but VIA outputs are not (see datasheet).
77  *
78  * Driving these outputs high must cause the VIA to source current and the
79  * card to sink current when it asserts /NMRQ. Current will flow but the pin
80  * voltage is uncertain and so the /NMRQ condition may still cause a transition
81  * at the VIA2 CA1 input (which explains the lost interrupts). A side effect
82  * is that a disabled slot IRQ can never be tested as pending or not.
83  *
84  * Driving these outputs low doesn't work either. All the slot /NMRQ lines are
85  * (active low) OR'd together to generate the CA1 (aka "SLOTS") interrupt (see
86  * The Guide To Macintosh Family Hardware, 2nd edition p. 167). If we drive a
87  * disabled /NMRQ line low, the falling edge immediately triggers a CA1
88  * interrupt and all slot interrupts after that will generate no transition
89  * and therefore no interrupt, even after being re-enabled.
90  *
91  * So we make the VIA port A I/O lines inputs and use nubus_disabled to keep
92  * track of their states. When any slot IRQ becomes disabled we mask the CA1
93  * umbrella interrupt. Only when all slot IRQs become enabled do we unmask
94  * the CA1 interrupt. It must remain enabled even when cards have no interrupt
95  * handler registered. Drivers must therefore disable a slot interrupt at the
96  * device before they call free_irq (like shared and autovector interrupts).
97  *
98  * There is also a related problem when MacOS is used to boot Linux. A network
99  * card brought up by a MacOS driver may raise an interrupt while Linux boots.
100  * This can be fatal since it can't be handled until the right driver loads
101  * (if such a driver exists at all). Apparently related to this hardware
102  * limitation, "Designing Cards and Drivers", p. 9-8, says that a slot
103  * interrupt with no driver would crash MacOS (the book was written before
104  * the appearance of Macs with RBV or OSS).
105  */
106 
107 static u8 nubus_disabled;
108 
109 void via_debug_dump(void);
110 
111 /*
112  * Initialize the VIAs
113  *
114  * First we figure out where they actually _are_ as well as what type of
115  * VIA we have for VIA2 (it could be a real VIA or an RBV or even an OSS.)
116  * Then we pretty much clear them out and disable all IRQ sources.
117  *
118  * Note: the OSS is actually "detected" here and not in oss_init(). It just
119  *	 seems more logical to do it here since via_init() needs to know
120  *	 these things anyways.
121  */
122 
123 void __init via_init(void)
124 {
125 	switch(macintosh_config->via_type) {
126 
127 		/* IIci, IIsi, IIvx, IIvi (P6xx), LC series */
128 
129 		case MAC_VIA_IICI:
130 			via1 = (void *) VIA1_BASE;
131 			if (macintosh_config->ident == MAC_MODEL_IIFX) {
132 				via2 = NULL;
133 				rbv_present = 0;
134 				oss_present = 1;
135 			} else {
136 				via2 = (void *) RBV_BASE;
137 				rbv_present = 1;
138 				oss_present = 0;
139 			}
140 			if (macintosh_config->ident == MAC_MODEL_LCIII) {
141 				rbv_clear = 0x00;
142 			} else {
143 				/* on most RBVs (& unlike the VIAs), you   */
144 				/* need to set bit 7 when you write to IFR */
145 				/* in order for your clear to occur.       */
146 				rbv_clear = 0x80;
147 			}
148 			gIER = rIER;
149 			gIFR = rIFR;
150 			gBufA = rSIFR;
151 			gBufB = rBufB;
152 			break;
153 
154 		/* Quadra and early MacIIs agree on the VIA locations */
155 
156 		case MAC_VIA_QUADRA:
157 		case MAC_VIA_II:
158 			via1 = (void *) VIA1_BASE;
159 			via2 = (void *) VIA2_BASE;
160 			rbv_present = 0;
161 			oss_present = 0;
162 			rbv_clear = 0x00;
163 			gIER = vIER;
164 			gIFR = vIFR;
165 			gBufA = vBufA;
166 			gBufB = vBufB;
167 			break;
168 		default:
169 			panic("UNKNOWN VIA TYPE");
170 	}
171 
172 	printk(KERN_INFO "VIA1 at %p is a 6522 or clone\n", via1);
173 
174 	printk(KERN_INFO "VIA2 at %p is ", via2);
175 	if (rbv_present) {
176 		printk("an RBV\n");
177 	} else if (oss_present) {
178 		printk("an OSS\n");
179 	} else {
180 		printk("a 6522 or clone\n");
181 	}
182 
183 #ifdef DEBUG_VIA
184 	via_debug_dump();
185 #endif
186 
187 	/*
188 	 * Shut down all IRQ sources, reset the timers, and
189 	 * kill the timer latch on VIA1.
190 	 */
191 
192 	via1[vIER] = 0x7F;
193 	via1[vIFR] = 0x7F;
194 	via1[vT1LL] = 0;
195 	via1[vT1LH] = 0;
196 	via1[vT1CL] = 0;
197 	via1[vT1CH] = 0;
198 	via1[vT2CL] = 0;
199 	via1[vT2CH] = 0;
200 	via1[vACR] &= ~0xC0; /* setup T1 timer with no PB7 output */
201 	via1[vACR] &= ~0x03; /* disable port A & B latches */
202 
203 	/*
204 	 * SE/30: disable video IRQ
205 	 * XXX: testing for SE/30 VBL
206 	 */
207 
208 	if (macintosh_config->ident == MAC_MODEL_SE30) {
209 		via1[vDirB] |= 0x40;
210 		via1[vBufB] |= 0x40;
211 	}
212 
213 	/*
214 	 * Set the RTC bits to a known state: all lines to outputs and
215 	 * RTC disabled (yes that's 0 to enable and 1 to disable).
216 	 */
217 
218 	via1[vDirB] |= (VIA1B_vRTCEnb | VIA1B_vRTCClk | VIA1B_vRTCData);
219 	via1[vBufB] |= (VIA1B_vRTCEnb | VIA1B_vRTCClk);
220 
221 	/* Everything below this point is VIA2/RBV only... */
222 
223 	if (oss_present)
224 		return;
225 
226 	if ((macintosh_config->via_type == MAC_VIA_QUADRA) &&
227 	    (macintosh_config->adb_type != MAC_ADB_PB1) &&
228 	    (macintosh_config->adb_type != MAC_ADB_PB2) &&
229 	    (macintosh_config->ident    != MAC_MODEL_C660) &&
230 	    (macintosh_config->ident    != MAC_MODEL_Q840)) {
231 		via_alt_mapping = 1;
232 		via1[vDirB] |= 0x40;
233 		via1[vBufB] &= ~0x40;
234 	} else {
235 		via_alt_mapping = 0;
236 	}
237 
238 	/*
239 	 * Now initialize VIA2. For RBV we just kill all interrupts;
240 	 * for a regular VIA we also reset the timers and stuff.
241 	 */
242 
243 	via2[gIER] = 0x7F;
244 	via2[gIFR] = 0x7F | rbv_clear;
245 	if (!rbv_present) {
246 		via2[vT1LL] = 0;
247 		via2[vT1LH] = 0;
248 		via2[vT1CL] = 0;
249 		via2[vT1CH] = 0;
250 		via2[vT2CL] = 0;
251 		via2[vT2CH] = 0;
252 		via2[vACR] &= ~0xC0; /* setup T1 timer with no PB7 output */
253 		via2[vACR] &= ~0x03; /* disable port A & B latches */
254 	}
255 
256 	/* Everything below this point is VIA2 only... */
257 
258 	if (rbv_present)
259 		return;
260 
261 	/*
262 	 * Set vPCR for control line interrupts.
263 	 *
264 	 * CA1 (SLOTS IRQ), CB1 (ASC IRQ): negative edge trigger.
265 	 *
266 	 * Macs with ESP SCSI have a negative edge triggered SCSI interrupt.
267 	 * Testing reveals that PowerBooks do too. However, the SE/30
268 	 * schematic diagram shows an active high NCR5380 IRQ line.
269 	 */
270 
271 	pr_debug("VIA2 vPCR is 0x%02X\n", via2[vPCR]);
272 	if (macintosh_config->via_type == MAC_VIA_II) {
273 		/* CA2 (SCSI DRQ), CB2 (SCSI IRQ): indep. input, pos. edge */
274 		via2[vPCR] = 0x66;
275 	} else {
276 		/* CA2 (SCSI DRQ), CB2 (SCSI IRQ): indep. input, neg. edge */
277 		via2[vPCR] = 0x22;
278 	}
279 }
280 
281 /*
282  * Start the 100 Hz clock
283  */
284 
285 void __init via_init_clock(irq_handler_t func)
286 {
287 	via1[vACR] |= 0x40;
288 	via1[vT1LL] = MAC_CLOCK_LOW;
289 	via1[vT1LH] = MAC_CLOCK_HIGH;
290 	via1[vT1CL] = MAC_CLOCK_LOW;
291 	via1[vT1CH] = MAC_CLOCK_HIGH;
292 
293 	if (request_irq(IRQ_MAC_TIMER_1, func, 0, "timer", func))
294 		pr_err("Couldn't register %s interrupt\n", "timer");
295 }
296 
297 /*
298  * Debugging dump, used in various places to see what's going on.
299  */
300 
301 void via_debug_dump(void)
302 {
303 	printk(KERN_DEBUG "VIA1: DDRA = 0x%02X DDRB = 0x%02X ACR = 0x%02X\n",
304 		(uint) via1[vDirA], (uint) via1[vDirB], (uint) via1[vACR]);
305 	printk(KERN_DEBUG "         PCR = 0x%02X  IFR = 0x%02X IER = 0x%02X\n",
306 		(uint) via1[vPCR], (uint) via1[vIFR], (uint) via1[vIER]);
307 	if (oss_present) {
308 		printk(KERN_DEBUG "VIA2: <OSS>\n");
309 	} else if (rbv_present) {
310 		printk(KERN_DEBUG "VIA2:  IFR = 0x%02X  IER = 0x%02X\n",
311 			(uint) via2[rIFR], (uint) via2[rIER]);
312 		printk(KERN_DEBUG "      SIFR = 0x%02X SIER = 0x%02X\n",
313 			(uint) via2[rSIFR], (uint) via2[rSIER]);
314 	} else {
315 		printk(KERN_DEBUG "VIA2: DDRA = 0x%02X DDRB = 0x%02X ACR = 0x%02X\n",
316 			(uint) via2[vDirA], (uint) via2[vDirB],
317 			(uint) via2[vACR]);
318 		printk(KERN_DEBUG "         PCR = 0x%02X  IFR = 0x%02X IER = 0x%02X\n",
319 			(uint) via2[vPCR],
320 			(uint) via2[vIFR], (uint) via2[vIER]);
321 	}
322 }
323 
324 /*
325  * This is always executed with interrupts disabled.
326  *
327  * TBI: get time offset between scheduling timer ticks
328  */
329 
330 u32 mac_gettimeoffset(void)
331 {
332 	unsigned long ticks, offset = 0;
333 
334 	/* read VIA1 timer 2 current value */
335 	ticks = via1[vT1CL] | (via1[vT1CH] << 8);
336 	/* The probability of underflow is less than 2% */
337 	if (ticks > MAC_CLOCK_TICK - MAC_CLOCK_TICK / 50)
338 		/* Check for pending timer interrupt in VIA1 IFR */
339 		if (via1[vIFR] & 0x40) offset = TICK_SIZE;
340 
341 	ticks = MAC_CLOCK_TICK - ticks;
342 	ticks = ticks * 10000L / MAC_CLOCK_TICK;
343 
344 	return (ticks + offset) * 1000;
345 }
346 
347 /*
348  * Flush the L2 cache on Macs that have it by flipping
349  * the system into 24-bit mode for an instant.
350  */
351 
352 void via_flush_cache(void)
353 {
354 	via2[gBufB] &= ~VIA2B_vMode32;
355 	via2[gBufB] |= VIA2B_vMode32;
356 }
357 
358 /*
359  * Return the status of the L2 cache on a IIci
360  */
361 
362 int via_get_cache_disable(void)
363 {
364 	/* Safeguard against being called accidentally */
365 	if (!via2) {
366 		printk(KERN_ERR "via_get_cache_disable called on a non-VIA machine!\n");
367 		return 1;
368 	}
369 
370 	return (int) via2[gBufB] & VIA2B_vCDis;
371 }
372 
373 /*
374  * Initialize VIA2 for Nubus access
375  */
376 
377 void __init via_nubus_init(void)
378 {
379 	/* unlock nubus transactions */
380 
381 	if ((macintosh_config->adb_type != MAC_ADB_PB1) &&
382 	    (macintosh_config->adb_type != MAC_ADB_PB2)) {
383 		/* set the line to be an output on non-RBV machines */
384 		if (!rbv_present)
385 			via2[vDirB] |= 0x02;
386 
387 		/* this seems to be an ADB bit on PMU machines */
388 		/* according to MkLinux.  -- jmt               */
389 		via2[gBufB] |= 0x02;
390 	}
391 
392 	/*
393 	 * Disable the slot interrupts. On some hardware that's not possible.
394 	 * On some hardware it's unclear what all of these I/O lines do.
395 	 */
396 
397 	switch (macintosh_config->via_type) {
398 	case MAC_VIA_II:
399 	case MAC_VIA_QUADRA:
400 		pr_debug("VIA2 vDirA is 0x%02X\n", via2[vDirA]);
401 		break;
402 	case MAC_VIA_IICI:
403 		/* RBV. Disable all the slot interrupts. SIER works like IER. */
404 		via2[rSIER] = 0x7F;
405 		break;
406 	}
407 }
408 
409 void via_nubus_irq_startup(int irq)
410 {
411 	int irq_idx = IRQ_IDX(irq);
412 
413 	switch (macintosh_config->via_type) {
414 	case MAC_VIA_II:
415 	case MAC_VIA_QUADRA:
416 		/* Make the port A line an input. Probably redundant. */
417 		if (macintosh_config->via_type == MAC_VIA_II) {
418 			/* The top two bits are RAM size outputs. */
419 			via2[vDirA] &= 0xC0 | ~(1 << irq_idx);
420 		} else {
421 			/* Allow NuBus slots 9 through F. */
422 			via2[vDirA] &= 0x80 | ~(1 << irq_idx);
423 		}
424 		/* fall through */
425 	case MAC_VIA_IICI:
426 		via_irq_enable(irq);
427 		break;
428 	}
429 }
430 
431 void via_nubus_irq_shutdown(int irq)
432 {
433 	switch (macintosh_config->via_type) {
434 	case MAC_VIA_II:
435 	case MAC_VIA_QUADRA:
436 		/* Ensure that the umbrella CA1 interrupt remains enabled. */
437 		via_irq_enable(irq);
438 		break;
439 	case MAC_VIA_IICI:
440 		via_irq_disable(irq);
441 		break;
442 	}
443 }
444 
445 /*
446  * The generic VIA interrupt routines (shamelessly stolen from Alan Cox's
447  * via6522.c :-), disable/pending masks added.
448  */
449 
450 void via1_irq(struct irq_desc *desc)
451 {
452 	int irq_num;
453 	unsigned char irq_bit, events;
454 
455 	events = via1[vIFR] & via1[vIER] & 0x7F;
456 	if (!events)
457 		return;
458 
459 	irq_num = VIA1_SOURCE_BASE;
460 	irq_bit = 1;
461 	do {
462 		if (events & irq_bit) {
463 			via1[vIFR] = irq_bit;
464 			generic_handle_irq(irq_num);
465 		}
466 		++irq_num;
467 		irq_bit <<= 1;
468 	} while (events >= irq_bit);
469 }
470 
471 static void via2_irq(struct irq_desc *desc)
472 {
473 	int irq_num;
474 	unsigned char irq_bit, events;
475 
476 	events = via2[gIFR] & via2[gIER] & 0x7F;
477 	if (!events)
478 		return;
479 
480 	irq_num = VIA2_SOURCE_BASE;
481 	irq_bit = 1;
482 	do {
483 		if (events & irq_bit) {
484 			via2[gIFR] = irq_bit | rbv_clear;
485 			generic_handle_irq(irq_num);
486 		}
487 		++irq_num;
488 		irq_bit <<= 1;
489 	} while (events >= irq_bit);
490 }
491 
492 /*
493  * Dispatch Nubus interrupts. We are called as a secondary dispatch by the
494  * VIA2 dispatcher as a fast interrupt handler.
495  */
496 
497 static void via_nubus_irq(struct irq_desc *desc)
498 {
499 	int slot_irq;
500 	unsigned char slot_bit, events;
501 
502 	events = ~via2[gBufA] & 0x7F;
503 	if (rbv_present)
504 		events &= via2[rSIER];
505 	else
506 		events &= ~via2[vDirA];
507 	if (!events)
508 		return;
509 
510 	do {
511 		slot_irq = IRQ_NUBUS_F;
512 		slot_bit = 0x40;
513 		do {
514 			if (events & slot_bit) {
515 				events &= ~slot_bit;
516 				generic_handle_irq(slot_irq);
517 			}
518 			--slot_irq;
519 			slot_bit >>= 1;
520 		} while (events);
521 
522  		/* clear the CA1 interrupt and make certain there's no more. */
523 		via2[gIFR] = 0x02 | rbv_clear;
524 		events = ~via2[gBufA] & 0x7F;
525 		if (rbv_present)
526 			events &= via2[rSIER];
527 		else
528 			events &= ~via2[vDirA];
529 	} while (events);
530 }
531 
532 /*
533  * Register the interrupt dispatchers for VIA or RBV machines only.
534  */
535 
536 void __init via_register_interrupts(void)
537 {
538 	if (via_alt_mapping) {
539 		/* software interrupt */
540 		irq_set_chained_handler(IRQ_AUTO_1, via1_irq);
541 		/* via1 interrupt */
542 		irq_set_chained_handler(IRQ_AUTO_6, via1_irq);
543 	} else {
544 		irq_set_chained_handler(IRQ_AUTO_1, via1_irq);
545 	}
546 	irq_set_chained_handler(IRQ_AUTO_2, via2_irq);
547 	irq_set_chained_handler(IRQ_MAC_NUBUS, via_nubus_irq);
548 }
549 
550 void via_irq_enable(int irq) {
551 	int irq_src	= IRQ_SRC(irq);
552 	int irq_idx	= IRQ_IDX(irq);
553 
554 	if (irq_src == 1) {
555 		via1[vIER] = IER_SET_BIT(irq_idx);
556 	} else if (irq_src == 2) {
557 		if (irq != IRQ_MAC_NUBUS || nubus_disabled == 0)
558 			via2[gIER] = IER_SET_BIT(irq_idx);
559 	} else if (irq_src == 7) {
560 		switch (macintosh_config->via_type) {
561 		case MAC_VIA_II:
562 		case MAC_VIA_QUADRA:
563 			nubus_disabled &= ~(1 << irq_idx);
564 			/* Enable the CA1 interrupt when no slot is disabled. */
565 			if (!nubus_disabled)
566 				via2[gIER] = IER_SET_BIT(1);
567 			break;
568 		case MAC_VIA_IICI:
569 			/* On RBV, enable the slot interrupt.
570 			 * SIER works like IER.
571 			 */
572 			via2[rSIER] = IER_SET_BIT(irq_idx);
573 			break;
574 		}
575 	}
576 }
577 
578 void via_irq_disable(int irq) {
579 	int irq_src	= IRQ_SRC(irq);
580 	int irq_idx	= IRQ_IDX(irq);
581 
582 	if (irq_src == 1) {
583 		via1[vIER] = IER_CLR_BIT(irq_idx);
584 	} else if (irq_src == 2) {
585 		via2[gIER] = IER_CLR_BIT(irq_idx);
586 	} else if (irq_src == 7) {
587 		switch (macintosh_config->via_type) {
588 		case MAC_VIA_II:
589 		case MAC_VIA_QUADRA:
590 			nubus_disabled |= 1 << irq_idx;
591 			if (nubus_disabled)
592 				via2[gIER] = IER_CLR_BIT(1);
593 			break;
594 		case MAC_VIA_IICI:
595 			via2[rSIER] = IER_CLR_BIT(irq_idx);
596 			break;
597 		}
598 	}
599 }
600 
601 void via1_set_head(int head)
602 {
603 	if (head == 0)
604 		via1[vBufA] &= ~VIA1A_vHeadSel;
605 	else
606 		via1[vBufA] |= VIA1A_vHeadSel;
607 }
608 EXPORT_SYMBOL(via1_set_head);
609 
610 int via2_scsi_drq_pending(void)
611 {
612 	return via2[gIFR] & (1 << IRQ_IDX(IRQ_MAC_SCSIDRQ));
613 }
614 EXPORT_SYMBOL(via2_scsi_drq_pending);
615