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.
8 #include <linux/types.h>
9 #include <linux/kernel.h>
12 #include <asm/macintosh.h>
13 #include <asm/macints.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
;
26 extern void adb_interrupt(int slot
, void *via
, struct pt_regs
*regs
);
29 * hardware reset vector
31 static void (*rom_reset
)(void);
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
*))
45 switch(macintosh_config
->via_type
)
51 via1
=(void *)0x50F00000;
52 via2
=(void *)0x50F26000;
54 if (macintosh_config
->ident
== MAC_MODEL_IIFX
) {
55 via2
=(void *)0x50F1A000;
60 * Quadra and early MacIIs agree on the VIA locations
64 via1
=(void *)0x50F00000;
65 via2
=(void *)0x50F02000;
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
));
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
));
91 via_write(via1
,vIER
, 0x7F);
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);
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);
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);
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);
182 * get time offset between scheduling timer ticks
183 * Code stolen from arch/m68k/atari/time.c; underflow check probably
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)
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
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)
228 * Powerdown, for the Macs that support it
231 via_write(via2
, rBufB
, via_read(via2
, rBufB
)&~0x04);
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);
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 ...
251 unsigned long *reset_hook
;
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
;
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
;
283 request_irq(IRQ_MAC_ADB
, adb_interrupt
, IRQ_FLG_LOCK
, "adb interrupt",
292 void via1_set_head(int head
)
295 via_write(via1
, vBufA
, via_read(via1
, vBufA
)&~0x20);
297 via_write(via1
, vBufA
, via_read(via1
, vBufA
)|0x20);
300 void nubus_init_via(void)
304 via_write(via2
, rBufB
, via_read(via2
, rBufB
)|0x02);
305 via_write(via2
, rIER
, 0x82); /* Interrupts on */
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
));
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
));