Import 2.1.116pre2
[davej-history.git] / arch / m68k / mac / via6522.c
blobc867bc96d70cf1d4e26f17f73db12854663b5663
1 /*
2 * 6522 Versatile Interface Adapter (VIA)
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 */
8 #include <linux/types.h>
9 #include <linux/kernel.h>
10 #include <linux/mm.h>
12 #include <asm/macintosh.h>
13 #include <asm/macints.h>
14 #include "via6522.h"
15 #include "psc.h"
17 volatile unsigned char *via1=(unsigned char *)VIABASE;
18 volatile unsigned char *via2=(unsigned char *)VIABASE2;
19 volatile unsigned char *psc=(unsigned char *)PSCBASE;
21 unsigned char via1_clock, via1_datab;
23 static int rbv=0;
24 static int oss=0;
26 extern void adb_interrupt(int slot, void *via, struct pt_regs *regs);
29 * hardware reset vector
31 static void (*rom_reset)(void);
34 * Timer defs.
36 #define MAC_CLOCK_TICK (783300/HZ) /* ticks per HZ */
37 #define MAC_CLOCK_LOW (MAC_CLOCK_TICK&0xFF)
38 #define MAC_CLOCK_HIGH (MAC_CLOCK_TICK>>8)
41 void via_init_clock(void (*func)(int, void *, struct pt_regs *))
43 unsigned char c;
45 switch(macintosh_config->via_type)
48 * CI, SI, VX, LC
50 case MAC_VIA_IIci:
51 via1=(void *)0x50F00000;
52 via2=(void *)0x50F26000;
53 rbv=1;
54 if (macintosh_config->ident == MAC_MODEL_IIFX) {
55 via2=(void *)0x50F1A000;
56 oss=1;
58 break;
60 * Quadra and early MacIIs agree on the VIA locations
62 case MAC_VIA_QUADRA:
63 case MAC_VIA_II:
64 via1=(void *)0x50F00000;
65 via2=(void *)0x50F02000;
66 break;
67 default:
69 via1_clock=via_read(via1, vACR);
70 via1_datab=via_read(via1, vBufB);
73 * Tell what MacOS left us with
76 printk("via_init: boot via1 acr=%X pcr=%X buf_a=%X dir_a=%X buf_b=%X dir_b=%X \n",
77 (int)via1_clock, (int)via_read(via1, vPCR),
78 (int)via_read(via1, vBufA), (int)via_read(via1, vDirA),
79 (int)via_read(via1, vBufB), (int)via_read(via1, vDirB));
81 if (rbv == 0)
82 printk("via_init: boot via2 acr=%X pcr=%X buf_a=%X dir_a=%X buf_b=%X dir_b=%X \n",
83 (int)via_read(via2, vACR), (int)via_read(via2, vPCR),
84 (int)via_read(via2, vBufA), (int)via_read(via2, vDirA),
85 (int)via_read(via2, vBufB), (int)via_read(via2, vDirB));
88 * Shut it down
91 via_write(via1,vIER, 0x7F);
94 * Kill the timers
97 via_write(via1,vT1LL,0);
98 via_write(via1,vT1LH,0);
99 via_write(via1,vT1CL,0);
100 via_write(via1,vT1CH,0);
101 via_write(via1,vT2CL,0);
102 via_write(via1,vT2CH,0);
105 * Now do via2
108 if(rbv==0)
110 via_write(via2,vT1LL,0);
111 via_write(via2,vT1LH,0);
112 via_write(via2,vT1CL,0);
113 via_write(via2,vT1CH,0);
114 via_write(via2,vT2CL,0);
115 via_write(via2,vT2CH,0);
116 via_write(via2,vIER, 0x7F);
118 else if (oss==0)
121 * Init the RBV chip a bit
124 via_write(via2, rIER,0x7F);
128 * Disable the timer latches
131 c=via_read(via1,vACR);
132 via_write(via1,vACR,c&0x3F);
134 if(rbv==0)
136 c=via_read(via2,vACR);
137 via_write(via2,vACR,c&0x3F);
141 * Now start the clock - we want 100Hz
144 via_write(via1,vACR,via_read(via1,vACR)|0x40);
146 via_write(via1,vT1LL, MAC_CLOCK_LOW);
147 via_write(via1,vT1LH, MAC_CLOCK_HIGH);
148 via_write(via1,vT1CL, MAC_CLOCK_LOW);
149 via_write(via1,vT1CH, MAC_CLOCK_HIGH);
152 * And enable its interrupt
155 request_irq(IRQ_MAC_TIMER_1, func, IRQ_FLG_LOCK, "timer", func);
158 * SE/30: disable video int.
159 * XXX: testing for SE/30 VBL
162 if (macintosh_config->ident == MAC_MODEL_SE30) {
163 c = via_read(via1, vBufB);
164 via_write(via1, vBufB, c|(0x40));
165 c = via_read(via1, vDirB);
166 via_write(via1, vDirB, c|(0x40));
169 #if 0 /* gone to mac_init_IRQ */
171 * Set vPCR for SCSI interrupts.
173 * That is: CA1 negative edge int., CA2 indep., positive edge int.;
174 * CB1 negative edge int., CB2 indep., positive edge int..
176 via_write(via2,vPCR, 0x66);
177 #endif
182 * get time offset between scheduling timer ticks
183 * Code stolen from arch/m68k/atari/time.c; underflow check probably
184 * wrong.
186 #define TICK_SIZE 10000
188 /* This is always executed with interrupts disabled. */
189 unsigned long mac_gettimeoffset (void)
191 unsigned long ticks, offset = 0;
193 /* read VIA1 timer 2 current value */
194 ticks = via_read(via1, vT1CL) + (via_read(via1, vT1CH)<<8);
195 /* The probability of underflow is less than 2% */
196 if (ticks > MAC_CLOCK_TICK - MAC_CLOCK_TICK / 50)
197 /* Check for pending timer interrupt in VIA1 IFR */
198 if (via_read(via1, vIFR) & 0x40)
199 offset = TICK_SIZE;
201 ticks = MAC_CLOCK_TICK - ticks;
202 ticks = ticks * 10000L / MAC_CLOCK_TICK;
204 return ticks + offset;
208 * PSC (AV Macs; level 3-6): initialize interrupt enable registers
211 void psc_init(void)
213 via_write(psc, pIER3, 0x01);
214 via_write(psc, pIER4, 0x09);
215 via_write(psc, pIER4, 0x86);
216 via_write(psc, pIER5, 0x03);
217 via_write(psc, pIER6, 0x07);
221 * The power switch - yes its software!
224 void mac_poweroff(void)
226 #if 0
228 * Powerdown, for the Macs that support it
230 if(rbv) {
231 via_write(via2, rBufB, via_read(via2, rBufB)&~0x04);
232 } else {
233 /* Direction of vDirB is output */
234 via_write(via2,vDirB,via_read(via2,vDirB)|0x04);
235 /* Send a value of 0 on that line */
236 via_write(via2,vBufB,via_read(via2,vBufB)&~0x04);
238 #endif
239 /* We should never make it this far... */
240 /* XXX - delay do we need to spin here ? */
241 while(1); /* Just in case .. */
245 * Not all Macs support software power down; for the rest, just
246 * try the ROM reset vector ...
248 void mac_reset(void)
250 unsigned long flags;
251 unsigned long *reset_hook;
253 save_flags(flags);
254 cli();
256 #if 0 /* need ROMBASE in booter */
257 #if 0 /* works on some */
258 rom_reset = (boot_info.bi_mac.rombase + 0xa);
259 #else /* testing, doesn't work on SE/30 either */
260 reset_hook = (unsigned long *) (boot_info.bi_mac.rombase + 0x4);
261 printk("ROM reset hook: %p\n", *reset_hook);
262 rom_reset = *reset_hook;
263 #endif
264 rom_reset();
265 #endif
266 restore_flags(flags);
268 /* We never make it this far... */
269 printk(" reboot failed, reboot manually!\n");
270 /* XXX - delay do we need to spin here ? */
271 while(1); /* Just in case .. */
275 * Set up the keyboard
278 void via_setup_keyboard(void)
280 #if 0 /* moved to adb */
281 via1_func_tab.vector[2]=adb_interrupt;
282 #else
283 request_irq(IRQ_MAC_ADB, adb_interrupt, IRQ_FLG_LOCK, "adb interrupt",
284 adb_interrupt);
285 #endif
289 * Floppy hook
292 void via1_set_head(int head)
294 if(head==0)
295 via_write(via1, vBufA, via_read(via1, vBufA)&~0x20);
296 else
297 via_write(via1, vBufA, via_read(via1, vBufA)|0x20);
300 void nubus_init_via(void)
302 if (rbv) {
303 if (oss==0) {
304 via_write(via2, rBufB, via_read(via2, rBufB)|0x02);
305 via_write(via2, rIER, 0x82); /* Interrupts on */
307 } else {
308 /* Assert the nubus active */
309 via_write(via2, vDirB, via_read(via2, vDirB)|0x02);
310 via_write(via2, vBufB, via_read(via2, vBufB)|0x02);
311 /* Make the nubus interrupt source register all output (disable) */
312 /* via_write(via2, vDirA, 0xFF); */
313 via_write(via2, vIER, 0x82); /* Interrupts on */
316 printk("nubus_init_via: via1 acr=%X datab=%X pcr=%X\n",
317 (int)via_read(via1, vACR), (int)via_read(via1, vBufB),
318 (int)via_read(via1, vPCR));
320 if (rbv==0)
321 printk("nubus_init_via: via2 acr=%X datab=%X pcr=%X\n",
322 (int)via_read(via2, vACR), (int)via_read(via2, vBufB),
323 (int)via_read(via2, vPCR));