File: /usr/src/linux/arch/m68k/mac/via.c

1     /*
2      *	6522 Versatile Interface Adapter (VIA)
3      *
4      *	There are two of these on the Mac II. Some IRQ's are vectored
5      *	via them as are assorted bits and bobs - eg RTC, ADB.
6      *
7      * CSA: Motorola seems to have removed documentation on the 6522 from
8      * their web site; try
9      *     http://nerini.drf.com/vectrex/other/text/chips/6522/
10      *     http://www.zymurgy.net/classic/vic20/vicdet1.htm
11      * and
12      *     http://193.23.168.87/mikro_laborversuche/via_iobaustein/via6522_1.html
13      * for info.  A full-text web search on 6522 AND VIA will probably also
14      * net some usefulness. <cananian@alumni.princeton.edu> 20apr1999
15      *
16      * 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)
18      *
19      */
20     
21     #include <linux/types.h>
22     #include <linux/kernel.h>
23     #include <linux/mm.h>
24     #include <linux/delay.h>
25     #include <linux/init.h>
26     
27     #include <linux/ide.h>
28     
29     #include <asm/traps.h>
30     #include <asm/bootinfo.h> 
31     #include <asm/macintosh.h> 
32     #include <asm/macints.h>
33     #include <asm/machw.h> 
34     #include <asm/mac_via.h>
35     #include <asm/mac_psc.h>
36     
37     volatile __u8 *via1, *via2;
38     #if 0
39     /* See note in mac_via.h about how this is possibly not useful */
40     volatile long *via_memory_bogon=(long *)&via_memory_bogon;
41     #endif
42     int  rbv_present,via_alt_mapping;
43     __u8 rbv_clear;
44     
45     /*
46      * Globals for accessing the VIA chip registers without having to
47      * check if we're hitting a real VIA or an RBV. Normally you could
48      * just hit the combined register (ie, vIER|rIER) but that seems to
49      * break on AV Macs...probably because they actually decode more than
50      * eight address bits. Why can't Apple engineers at least be
51      * _consistantly_ lazy?                          - 1999-05-21 (jmt)
52      */
53     
54     static int gIER,gIFR,gBufA,gBufB;
55     
56     /*
57      * Timer defs.
58      */
59     
60     #define TICK_SIZE		10000
61     #define MAC_CLOCK_TICK		(783300/HZ)		/* ticks per HZ */
62     #define MAC_CLOCK_LOW		(MAC_CLOCK_TICK&0xFF)
63     #define MAC_CLOCK_HIGH		(MAC_CLOCK_TICK>>8)
64     
65     static int  nubus_active = 0;
66     
67     void via_debug_dump(void);
68     void via1_irq(int, void *, struct pt_regs *);
69     void via2_irq(int, void *, struct pt_regs *);
70     void via_nubus_irq(int, void *, struct pt_regs *);
71     void via_irq_enable(int irq);
72     void via_irq_disable(int irq);
73     void via_irq_clear(int irq);
74     
75     extern void mac_bang(int, void *, struct pt_regs *);
76     extern void mac_scc_dispatch(int, void *, struct pt_regs *);
77     extern int oss_present;
78     
79     /*
80      * Initialize the VIAs
81      *
82      * First we figure out where they actually _are_ as well as what type of
83      * VIA we have for VIA2 (it could be a real VIA or an RBV or even an OSS.)
84      * Then we pretty much clear them out and disable all IRQ sources.
85      *
86      * Note: the OSS is actually "detected" here and not in oss_init(). It just
87      *	 seems more logical to do it here since via_init() needs to know
88      *	 these things anyways.
89      */
90     
91     void __init via_init(void)
92     {
93     	switch(macintosh_config->via_type) {
94     
95     		/* IIci, IIsi, IIvx, IIvi (P6xx), LC series */
96     
97     		case MAC_VIA_IIci:	
98     			via1 = (void *) VIA1_BASE;
99     			if (macintosh_config->ident == MAC_MODEL_IIFX) {
100     				via2 = NULL;
101     				rbv_present = 0;
102     				oss_present = 1;
103     			} else {
104     				via2 = (void *) RBV_BASE;
105     				rbv_present = 1;
106     				oss_present = 0;
107     			}
108     			if (macintosh_config->ident == MAC_MODEL_LCIII) {
109     				rbv_clear = 0x00;
110     			} else {
111     				/* on most RBVs (& unlike the VIAs), you   */
112     				/* need to set bit 7 when you write to IFR */
113     				/* in order for your clear to occur.       */
114     				rbv_clear = 0x80;
115     			}
116     			gIER = rIER;
117     			gIFR = rIFR;
118     			gBufA = rSIFR;
119     			gBufB = rBufB;
120     			break;
121     
122     		/* Quadra and early MacIIs agree on the VIA locations */
123     
124     		case MAC_VIA_QUADRA:
125     		case MAC_VIA_II:
126     			via1 = (void *) VIA1_BASE;
127     			via2 = (void *) VIA2_BASE;
128     			rbv_present = 0;
129     			oss_present = 0;
130     			rbv_clear = 0x00;
131     			gIER = vIER;
132     			gIFR = vIFR;
133     			gBufA = vBufA;
134     			gBufB = vBufB;
135     			break;
136     		default:
137     			panic("UNKNOWN VIA TYPE");
138     	}
139     
140     	printk("VIA1 at %p is a 6522 or clone\n", via1);
141     
142     	printk("VIA2 at %p is ", via2);
143     	if (rbv_present) {
144     		printk("an RBV\n");
145     	} else if (oss_present) {
146     		printk("an OSS\n");
147     	} else {
148     		printk("a 6522 or clone\n");
149     	}
150     
151     #ifdef DEBUG_VIA
152     	via_debug_dump();
153     #endif
154     
155     	/*
156     	 * Shut down all IRQ sources, reset the timers, and
157     	 * kill the timer latch on VIA1.
158     	 */
159     
160     	via1[vIER] = 0x7F;
161     	via1[vIFR] = 0x7F;
162     	via1[vT1LL] = 0;
163     	via1[vT1LH] = 0;
164     	via1[vT1CL] = 0;
165     	via1[vT1CH] = 0;
166     	via1[vT2CL] = 0;
167     	via1[vT2CH] = 0;
168     	via1[vACR] &= 0x3F;
169     
170     	/* 
171     	 * SE/30: disable video IRQ
172     	 * XXX: testing for SE/30 VBL
173     	 */
174     
175     	if (macintosh_config->ident == MAC_MODEL_SE30) {
176     		via1[vDirB] |= 0x40;
177     		via1[vBufB] |= 0x40;
178     	} 
179     	
180     	/*
181     	 * Set the RTC bits to a known state: all lines to outputs and
182     	 * RTC disabled (yes that's 0 to enable and 1 to disable).
183     	 */
184     
185     	via1[vDirB] |= (VIA1B_vRTCEnb | VIA1B_vRTCClk | VIA1B_vRTCData);
186     	via1[vBufB] |= (VIA1B_vRTCEnb | VIA1B_vRTCClk);
187     
188     	/* Everything below this point is VIA2/RBV only... */
189     
190     	if (oss_present) return;
191     
192     #if 1
193     	/* Some machines support an alternate IRQ mapping that spreads  */
194     	/* Ethernet and Sound out to their own autolevel IRQs and moves */
195     	/* VIA1 to level 6. A/UX uses this mapping and we do too.  Note */
196     	/* that the IIfx emulates this alternate mapping using the OSS. */
197     
198     	switch(macintosh_config->ident) {
199     		case MAC_MODEL_C610:
200     		case MAC_MODEL_Q610:
201     		case MAC_MODEL_C650:
202     		case MAC_MODEL_Q650:
203     		case MAC_MODEL_Q700:
204     		case MAC_MODEL_Q800:
205     		case MAC_MODEL_Q900:
206     		case MAC_MODEL_Q950:
207     			via_alt_mapping = 1;
208     			via1[vDirB] |= 0x40;
209     			via1[vBufB] &= ~0x40;
210     			break;
211     		default:
212     			via_alt_mapping = 0;
213     			break;
214     	}
215     #else
216     	/* The alernate IRQ mapping seems to just not work. Anyone with a   */
217     	/* supported machine is welcome to take a stab at fixing it. It     */
218     	/* _should_ work on the following Quadras: 610,650,700,800,900,950  */
219     	/*                                               - 1999-06-12 (jmt) */
220     
221     	via_alt_mapping = 0;
222     #endif
223     
224     	/*
225     	 * Now initialize VIA2. For RBV we just kill all interrupts;
226     	 * for a regular VIA we also reset the timers and stuff.
227     	 */
228     
229     	via2[gIER] = 0x7F;
230     	via2[gIFR] = 0x7F | rbv_clear;
231     	if (!rbv_present) {
232     		via2[vT1LL] = 0;
233     		via2[vT1LH] = 0;
234     		via2[vT1CL] = 0;
235     		via2[vT1CH] = 0;
236     		via2[vT2CL] = 0;
237     		via2[vT2CH] = 0;
238     		via2[vACR] &= 0x3F;
239     	}
240     }
241     
242     /*
243      * Start the 100 Hz clock
244      */
245     
246     void __init via_init_clock(void (*func)(int, void *, struct pt_regs *))
247     {	
248     	via1[vACR] |= 0x40;
249     	via1[vT1LL] = MAC_CLOCK_LOW;
250     	via1[vT1LH] = MAC_CLOCK_HIGH;
251     	via1[vT1CL] = MAC_CLOCK_LOW;
252     	via1[vT1CH] = MAC_CLOCK_HIGH;
253     
254     	request_irq(IRQ_MAC_TIMER_1, func, IRQ_FLG_LOCK, "timer", func);
255     }
256     
257     /*
258      * Register the interrupt dispatchers for VIA or RBV machines only.
259      */
260     
261     void __init via_register_interrupts(void)
262     {
263     	if (via_alt_mapping) {
264     		sys_request_irq(IRQ_AUTO_1, via1_irq, IRQ_FLG_LOCK|IRQ_FLG_FAST,
265     				"software", (void *) via1);
266     		sys_request_irq(IRQ_AUTO_6, via1_irq, IRQ_FLG_LOCK|IRQ_FLG_FAST,
267     				"via1", (void *) via1);
268     	} else {
269     		sys_request_irq(IRQ_AUTO_1, via1_irq, IRQ_FLG_LOCK|IRQ_FLG_FAST,
270     				"via1", (void *) via1);
271     #if 0 /* interferes with serial on some machines */
272     		if (!psc_present) {
273     			sys_request_irq(IRQ_AUTO_6, mac_bang, IRQ_FLG_LOCK,
274     					"Off Switch", mac_bang);
275     		}
276     #endif
277     	}
278     	sys_request_irq(IRQ_AUTO_2, via2_irq, IRQ_FLG_LOCK|IRQ_FLG_FAST,
279     			"via2", (void *) via2);
280     	if (!psc_present) {
281     		sys_request_irq(IRQ_AUTO_4, mac_scc_dispatch, IRQ_FLG_LOCK,
282     				"scc", mac_scc_dispatch);
283     	}
284     	request_irq(IRQ_MAC_NUBUS, via_nubus_irq, IRQ_FLG_LOCK|IRQ_FLG_FAST,
285     			"nubus", (void *) via2);
286     }
287     
288     /*
289      * Debugging dump, used in various places to see what's going on.
290      */
291     
292     void via_debug_dump(void)
293     {
294     	printk("VIA1: DDRA = 0x%02X DDRB = 0x%02X ACR = 0x%02X\n",
295     		(uint) via1[vDirA], (uint) via1[vDirB], (uint) via1[vACR]);
296     	printk("         PCR = 0x%02X  IFR = 0x%02X IER = 0x%02X\n",
297     		(uint) via1[vPCR], (uint) via1[vIFR], (uint) via1[vIER]);
298     	if (oss_present) {
299     		printk("VIA2: <OSS>\n");
300     	} else if (rbv_present) {
301     		printk("VIA2:  IFR = 0x%02X  IER = 0x%02X\n",
302     			(uint) via2[rIFR], (uint) via2[rIER]);
303     		printk("      SIFR = 0x%02X SIER = 0x%02X\n",
304     			(uint) via2[rSIFR], (uint) via2[rSIER]);
305     	} else {
306     		printk("VIA2: DDRA = 0x%02X DDRB = 0x%02X ACR = 0x%02X\n",
307     			(uint) via2[vDirA], (uint) via2[vDirB],
308     			(uint) via2[vACR]);
309     		printk("         PCR = 0x%02X  IFR = 0x%02X IER = 0x%02X\n",
310     			(uint) via2[vPCR],
311     			(uint) via2[vIFR], (uint) via2[vIER]);
312     	}
313     }
314     
315     /*
316      * This is always executed with interrupts disabled.
317      *
318      * TBI: get time offset between scheduling timer ticks
319      */
320     
321     unsigned long mac_gettimeoffset (void)
322     {
323     	unsigned long ticks, offset = 0;
324     
325     	/* read VIA1 timer 2 current value */
326     	ticks = via1[vT1CL] | (via1[vT1CH] << 8);
327     	/* The probability of underflow is less than 2% */
328     	if (ticks > MAC_CLOCK_TICK - MAC_CLOCK_TICK / 50)
329     		/* Check for pending timer interrupt in VIA1 IFR */
330     		if (via1[vIFR] & 0x40) offset = TICK_SIZE;
331     
332     	ticks = MAC_CLOCK_TICK - ticks;
333     	ticks = ticks * 10000L / MAC_CLOCK_TICK;
334     
335     	return ticks + offset;
336     }
337     
338     /*
339      * Flush the L2 cache on Macs that have it by flipping
340      * the system into 24-bit mode for an instant.
341      */
342     
343     void via_flush_cache(void)
344     {
345     	via2[gBufB] &= ~VIA2B_vMode32;
346     	via2[gBufB] |= VIA2B_vMode32;
347     }
348     
349     /*
350      * Return the status of the L2 cache on a IIci
351      */
352     
353     int via_get_cache_disable(void)
354     {
355     	/* Safeguard against being called accidentally */
356     	if (!via2) {
357     		printk(KERN_ERR "via_get_cache_disable called on a non-VIA machine!\n");
358     		return 1;
359     	}
360     
361     	return (int) via2[gBufB] & VIA2B_vCDis;
362     }
363     
364     /*
365      * Initialize VIA2 for Nubus access
366      */
367     
368     void __init via_nubus_init(void)
369     {
370     	/* don't set nubus_active = 0 here, it kills the Baboon */
371     	/* interrupt that we've already registered.		*/
372     
373     	/* unlock nubus transactions */
374     
375     	if (!rbv_present) {
376     		/* set the line to be an output on non-RBV machines */
377     		via2[vDirB] |= 0x02;
378     	}
379     
380     	/* this seems to be an ADB bit on PMU machines */
381     	/* according to MkLinux.  -- jmt               */
382     
383     	if ((macintosh_config->adb_type != MAC_ADB_PB1) &&
384     	    (macintosh_config->adb_type != MAC_ADB_PB2)) {
385     		via2[gBufB] |= 0x02;
386     	}
387     
388     	/* disable nubus slot interrupts. */
389     	if (rbv_present) {
390     		via2[rSIER] = 0x7F;
391     		via2[rSIER] = nubus_active | 0x80;
392     	} else {
393     		via2[vBufA] = 0xFF;
394     		via2[vDirA] = ~nubus_active;
395     	}
396     }
397     
398     /*
399      * The generic VIA interrupt routines (shamelessly stolen from Alan Cox's
400      * via6522.c :-), disable/pending masks added.
401      *
402      * The new interrupt architecture in macints.c takes care of a lot of the
403      * gruntwork for us, including tallying the interrupts and calling the
404      * handlers on the linked list. All we need to do here is basically generate
405      * the machspec interrupt number after clearing the interrupt.
406      */
407     
408     void via1_irq(int irq, void *dev_id, struct pt_regs *regs)
409     {
410     	int irq_bit, i;
411     	unsigned char events, mask;
412     
413     	mask = via1[vIER] & 0x7F;
414     	if (!(events = via1[vIFR] & mask)) return;
415     
416     	for (i = 0, irq_bit = 1 ; i < 7 ; i++, irq_bit <<= 1)
417     		if (events & irq_bit) {
418     			via1[vIER] = irq_bit;
419     			mac_do_irq_list(VIA1_SOURCE_BASE + i, regs);
420     			via1[vIFR] = irq_bit;
421     			via1[vIER] = irq_bit | 0x80;
422     		}
423     
424     #if 0 /* freakin' pmu is doing weird stuff */
425     	if (!oss_present) {
426     		/* This (still) seems to be necessary to get IDE
427     		   working.  However, if you enable VBL interrupts,
428     		   you're screwed... */
429     		/* FIXME: should we check the SLOTIRQ bit before
430                        pulling this stunt? */
431     		/* No, it won't be set. that's why we're doing this. */
432     		via_irq_disable(IRQ_MAC_NUBUS);
433     		via_irq_clear(IRQ_MAC_NUBUS);
434     		mac_do_irq_list(IRQ_MAC_NUBUS, regs);
435     		via_irq_enable(IRQ_MAC_NUBUS);
436     	}
437     #endif
438     }
439     
440     void via2_irq(int irq, void *dev_id, struct pt_regs *regs)
441     {
442     	int irq_bit, i;
443     	unsigned char events, mask;
444     
445     	mask = via2[gIER] & 0x7F;
446     	if (!(events = via2[gIFR] & mask)) return;
447     
448     	for (i = 0, irq_bit = 1 ; i < 7 ; i++, irq_bit <<= 1)
449     		if (events & irq_bit) {
450     			via2[gIER] = irq_bit;
451     			mac_do_irq_list(VIA2_SOURCE_BASE + i, regs);
452     			via2[gIFR] = irq_bit | rbv_clear;
453     			via2[gIER] = irq_bit | 0x80;
454     		}
455     }
456     
457     /*
458      * Dispatch Nubus interrupts. We are called as a secondary dispatch by the
459      * VIA2 dispatcher as a fast interrupt handler.
460      */
461     
462     void via_nubus_irq(int irq, void *dev_id, struct pt_regs *regs)
463     {
464     	int irq_bit, i;
465     	unsigned char events;
466     
467     	if (!(events = ~via2[gBufA] & nubus_active)) return;
468     
469     	for (i = 0, irq_bit = 1 ; i < 7 ; i++, irq_bit <<= 1) {
470     		if (events & irq_bit) {
471     			via_irq_disable(NUBUS_SOURCE_BASE + i);
472     			mac_do_irq_list(NUBUS_SOURCE_BASE + i, regs);
473     			via_irq_enable(NUBUS_SOURCE_BASE + i);
474     		}
475     	}
476     }
477     
478     void via_irq_enable(int irq) {
479     	int irq_src	= IRQ_SRC(irq);
480     	int irq_idx	= IRQ_IDX(irq);
481     	int irq_bit	= 1 << irq_idx;
482     
483     #ifdef DEBUG_IRQUSE
484     	printk("via_irq_enable(%d)\n", irq);
485     #endif
486     
487     	if (irq_src == 1) {
488     		via1[vIER] = irq_bit | 0x80;
489     	} else if (irq_src == 2) {
490     		/*
491     		 * Set vPCR for SCSI interrupts (but not on RBV)
492     		 */
493     		if ((irq_idx == 0) && !rbv_present) {
494     			if (macintosh_config->scsi_type == MAC_SCSI_OLD) {
495     				/* CB2 (IRQ) indep. input, positive edge */
496     				/* CA2 (DRQ) indep. input, positive edge */
497     				via2[vPCR] = 0x66;
498     			} else {
499     				/* CB2 (IRQ) indep. input, negative edge */
500     				/* CA2 (DRQ) indep. input, negative edge */
501     				via2[vPCR] = 0x22;
502     			}
503     		}
504     		via2[gIER] = irq_bit | 0x80;
505     	} else if (irq_src == 7) {
506     		if (rbv_present) {
507     			/* enable the slot interrupt. SIER works like IER. */
508     			via2[rSIER] = IER_SET_BIT(irq_idx);
509     		} else {
510     			/* Make sure the bit is an input, to enable the irq */
511     			via2[vDirA] &= ~irq_bit;
512     		}
513     		nubus_active |= irq_bit;
514     	}
515     }
516     
517     void via_irq_disable(int irq) {
518     	int irq_src	= IRQ_SRC(irq);
519     	int irq_idx	= IRQ_IDX(irq);
520     	int irq_bit	= 1 << irq_idx;
521     
522     #ifdef DEBUG_IRQUSE
523     	printk("via_irq_disable(%d)\n", irq);
524     #endif
525     
526     	if (irq_src == 1) {
527     		via1[vIER] = irq_bit;
528     	} else if (irq_src == 2) {
529     		via2[gIER] = irq_bit;
530     	} else if (irq_src == 7) {
531     		if (rbv_present) {
532     			/* disable the slot interrupt.  SIER works like IER. */
533     			via2[rSIER] = IER_CLR_BIT(irq_idx);
534     		} else {
535     			/* disable the nubus irq by changing dir to output */
536     			via2[vDirA] |= irq_bit;
537     		}
538     		nubus_active &= ~irq_bit;
539     	}
540     }
541     
542     void via_irq_clear(int irq) {
543     	int irq_src	= IRQ_SRC(irq);
544     	int irq_idx	= IRQ_IDX(irq);
545     	int irq_bit	= 1 << irq_idx;
546     
547     	if (irq_src == 1) {
548     		via1[vIFR] = irq_bit;
549     	} else if (irq_src == 2) {
550     		via2[gIFR] = irq_bit | rbv_clear;
551     	} else if (irq_src == 7) {
552     		/* FIXME: hmm.. */
553     	}
554     }
555     
556     /*
557      * Returns nonzero if an interrupt is pending on the given
558      * VIA/IRQ combination.
559      */
560     
561     int via_irq_pending(int irq)
562     {
563     	int irq_src	= IRQ_SRC(irq);
564     	int irq_idx	= IRQ_IDX(irq);
565     	int irq_bit	= 1 << irq_idx;
566     
567     	if (irq_src == 1) {
568     		return via1[vIFR] & irq_bit;
569     	} else if (irq_src == 2) {
570     		return via2[gIFR] & irq_bit;
571     	} else if (irq_src == 7) {
572     		return ~via2[gBufA] & irq_bit;
573     	}
574     	return 0;
575     }
576