Import 2.3.13pre1
[davej-history.git] / arch / alpha / kernel / sys_ruffian.c
bloba1a009cb305f4e95455236823e27ec482b1a93f8
1 /*
2 * linux/arch/alpha/kernel/sys_ruffian.c
4 * Copyright (C) 1995 David A Rusling
5 * Copyright (C) 1996 Jay A Estabrook
6 * Copyright (C) 1998 Richard Henderson
8 * Code supporting the RUFFIAN.
9 */
11 #include <linux/kernel.h>
12 #include <linux/types.h>
13 #include <linux/mm.h>
14 #include <linux/sched.h>
15 #include <linux/pci.h>
16 #include <linux/ioport.h>
17 #include <linux/init.h>
19 #include <asm/ptrace.h>
20 #include <asm/system.h>
21 #include <asm/dma.h>
22 #include <asm/irq.h>
23 #include <asm/mmu_context.h>
24 #include <asm/io.h>
25 #include <asm/pgtable.h>
26 #include <asm/core_pyxis.h>
28 #include "proto.h"
29 #include "irq.h"
30 #include "bios32.h"
31 #include "machvec.h"
33 static void
34 ruffian_update_irq_hw(unsigned long irq, unsigned long mask, int unmask_p)
36 if (irq >= 16) {
37 /* Note inverted sense of mask bits: */
38 /* Make CERTAIN none of the bogus ints get enabled... */
39 *(vulp)PYXIS_INT_MASK =
40 ~((long)mask >> 16) & 0x00000000ffffffbfUL;
41 mb();
42 /* ... and read it back to make sure it got written. */
43 *(vulp)PYXIS_INT_MASK;
45 else if (irq >= 8)
46 outb(mask >> 8, 0xA1); /* ISA PIC2 */
47 else
48 outb(mask, 0x21); /* ISA PIC1 */
51 static void
52 ruffian_ack_irq(unsigned long irq)
54 if (irq < 16) {
55 /* Ack PYXIS ISA interrupt. */
56 *(vulp)PYXIS_INT_REQ = 1L << 7; mb();
57 /* ... and read it back to make sure it got written. */
58 *(vulp)PYXIS_INT_REQ;
59 if (irq > 7) {
60 outb(0x20, 0xa0);
62 outb(0x20, 0x20);
63 } else {
64 /* Ack PYXIS PCI interrupt. */
65 *(vulp)PYXIS_INT_REQ = (1UL << (irq - 16)); mb();
66 /* ... and read it back to make sure it got written. */
67 *(vulp)PYXIS_INT_REQ;
71 static void
72 ruffian_device_interrupt(unsigned long vector, struct pt_regs *regs)
74 unsigned long pld;
75 unsigned int i;
77 /* Read the interrupt summary register of PYXIS */
78 pld = *(vulp)PYXIS_INT_REQ;
80 /* For now, AND off any bits we are not interested in:
81 * HALT (2), timer (6), ISA Bridge (7), 21142 (8)
82 * then all the PCI slots/INTXs (12-31)
83 * flash(5) :DWH:
85 pld &= 0x00000000ffffff9fUL; /* was ffff7f */
88 * Now for every possible bit set, work through them and call
89 * the appropriate interrupt handler.
91 while (pld) {
92 i = ffz(~pld);
93 pld &= pld - 1; /* clear least bit set */
94 if (i == 7) { /* if ISA int */
95 /* Ruffian does not have the RTC connected to
96 the CPU timer interrupt. Instead, it uses the
97 PIT connected to IRQ 0. So we must detect that
98 and route that specifically to where we expected
99 to find the timer interrupt come in. */
101 /* Copy this code from isa_device_interrupt because
102 we need to hook into int 0 for the timer. I
103 refuse to soil device_interrupt with ifdefs. */
105 /* Generate a PCI interrupt acknowledge cycle.
106 The PIC will respond with the interrupt
107 vector of the highest priority interrupt
108 that is pending. The PALcode sets up the
109 interrupts vectors such that irq level L
110 generates vector L. */
112 unsigned int j = *(vuip)PYXIS_IACK_SC & 0xff;
113 if (j == 7 && !(inb(0x20) & 0x80)) {
114 /* It's only a passive release... */
115 } else if (j == 0) {
116 handle_irq(TIMER_IRQ, -1, regs);
117 ruffian_ack_irq(0);
118 } else {
119 handle_irq(j, j, regs);
121 } else { /* if not an ISA int */
122 handle_irq(16 + i, 16 + i, regs);
125 *(vulp)PYXIS_INT_REQ = 1UL << i; mb();
126 *(vulp)PYXIS_INT_REQ; /* read to force the write */
130 static void __init
131 ruffian_init_irq(void)
133 STANDARD_INIT_IRQ_PROLOG;
135 /* Invert 6&7 for i82371 */
136 *(vulp)PYXIS_INT_HILO = 0x000000c0UL; mb();
137 *(vulp)PYXIS_INT_CNFG = 0x00002064UL; mb(); /* all clear */
138 *(vulp)PYXIS_INT_MASK = 0x00000000UL; mb();
139 *(vulp)PYXIS_INT_REQ = 0xffffffffUL; mb();
141 outb(0x11,0xA0);
142 outb(0x08,0xA1);
143 outb(0x02,0xA1);
144 outb(0x01,0xA1);
145 outb(0xFF,0xA1);
147 outb(0x11,0x20);
148 outb(0x00,0x21);
149 outb(0x04,0x21);
150 outb(0x01,0x21);
151 outb(0xFF,0x21);
153 /* Send -INTA pulses to clear any pending interrupts ...*/
154 *(vuip) PYXIS_IACK_SC;
156 /* Finish writing the 82C59A PIC Operation Control Words */
157 outb(0x20,0xA0);
158 outb(0x20,0x20);
160 /* Turn on the interrupt controller, the timer interrupt */
161 enable_irq(16 + 7); /* enable ISA PIC cascade */
162 enable_irq(0); /* enable timer */
163 enable_irq(2); /* enable 2nd PIC cascade */
168 * For RUFFIAN, we do not want to make any modifications to the PCI
169 * setup. But we may need to do some kind of init.
172 static void __init
173 ruffian_pci_fixup(void)
175 /* layout_all_busses(DEFAULT_IO_BASE, DEFAULT_MEM_BASE); */
179 #ifdef BUILDING_FOR_MILO
181 * The DeskStation Ruffian motherboard firmware does not place
182 * the memory size in the PALimpure area. Therefore, we use
183 * the Bank Configuration Registers in PYXIS to obtain the size.
185 static unsigned long __init
186 ruffian_get_bank_size(unsigned long offset)
188 unsigned long bank_addr, bank, ret = 0;
190 /* Valid offsets are: 0x800, 0x840 and 0x880
191 since Ruffian only uses three banks. */
192 bank_addr = (unsigned long)PYXIS_MCR + offset;
193 bank = *(vulp)bank_addr;
195 /* Check BANK_ENABLE */
196 if (bank & 0x01) {
197 static unsigned long size[] __initlocaldata = {
198 0x40000000UL, /* 0x00, 1G */
199 0x20000000UL, /* 0x02, 512M */
200 0x10000000UL, /* 0x04, 256M */
201 0x08000000UL, /* 0x06, 128M */
202 0x04000000UL, /* 0x08, 64M */
203 0x02000000UL, /* 0x0a, 32M */
204 0x01000000UL, /* 0x0c, 16M */
205 0x00800000UL, /* 0x0e, 8M */
206 0x80000000UL, /* 0x10, 2G */
209 bank = (bank & 0x1e) >> 1;
210 if (bank < sizeof(size)/sizeof(*size))
211 ret = size[bank];
214 return ret;
216 #endif /* BUILDING_FOR_MILO */
218 static void __init
219 ruffian_init_arch(unsigned long *mem_start, unsigned long *mem_end)
221 /* FIXME: What do we do with ruffian_get_bank_size above? */
223 #if 1
224 pyxis_init_arch();
225 #else
226 pyxis_enable_errors();
227 if (!pyxis_srm_window_setup()) {
228 printk("ruffian_init_arch: Skipping window register rewrites."
229 "\n... Trust DeskStation firmware!\n");
231 pyxis_finish_init_arch();
232 #endif
235 static void
236 ruffian_init_pit (void)
238 /* Ruffian depends on the system timer established in MILO! */
239 timer_resource.start = 0x70;
240 timer_resource.end = 0x70 + 0x10;
241 request_resource(&ioport_resource, &timer_resource);
243 outb(0xb6, 0x43); /* pit counter 2: speaker */
244 outb(0x31, 0x42);
245 outb(0x13, 0x42);
248 static void
249 ruffian_kill_arch (int mode, char *reboot_cmd)
251 #if 0
252 /* this only causes re-entry to ARCSBIOS */
253 /* Perhaps this works for other PYXIS as well? */
254 *(vuip) PYXIS_RESET = 0x0000dead;
255 mb();
256 #endif
257 generic_kill_arch(mode, reboot_cmd);
262 * The System Vector
265 struct alpha_machine_vector ruffian_mv __initmv = {
266 vector_name: "Ruffian",
267 DO_EV5_MMU,
268 DO_DEFAULT_RTC,
269 /* For the moment, do not use BWIO on RUFFIAN. */
270 IO(PYXIS,pyxis,pyxis),
271 DO_PYXIS_BUS,
272 machine_check: pyxis_machine_check,
273 max_dma_address: ALPHA_RUFFIAN_MAX_DMA_ADDRESS,
275 nr_irqs: 48,
276 irq_probe_mask: RUFFIAN_PROBE_MASK,
277 update_irq_hw: ruffian_update_irq_hw,
278 ack_irq: ruffian_ack_irq,
279 device_interrupt: ruffian_device_interrupt,
281 init_arch: ruffian_init_arch,
282 init_irq: ruffian_init_irq,
283 init_pit: ruffian_init_pit,
284 pci_fixup: ruffian_pci_fixup,
285 kill_arch: ruffian_kill_arch,
287 ALIAS_MV(ruffian)