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.
11 #include <linux/kernel.h>
12 #include <linux/types.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>
23 #include <asm/mmu_context.h>
25 #include <asm/pgtable.h>
26 #include <asm/core_pyxis.h>
34 ruffian_update_irq_hw(unsigned long irq
, unsigned long mask
, int unmask_p
)
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
;
42 /* ... and read it back to make sure it got written. */
43 *(vulp
)PYXIS_INT_MASK
;
46 outb(mask
>> 8, 0xA1); /* ISA PIC2 */
48 outb(mask
, 0x21); /* ISA PIC1 */
52 ruffian_ack_irq(unsigned long irq
)
55 /* Ack PYXIS ISA interrupt. */
56 *(vulp
)PYXIS_INT_REQ
= 1L << 7; mb();
57 /* ... and read it back to make sure it got written. */
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. */
72 ruffian_device_interrupt(unsigned long vector
, struct pt_regs
*regs
)
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)
85 pld
&= 0x00000000ffffff9fUL
; /* was ffff7f */
88 * Now for every possible bit set, work through them and call
89 * the appropriate interrupt handler.
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... */
116 handle_irq(TIMER_IRQ
, -1, regs
);
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 */
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();
153 /* Send -INTA pulses to clear any pending interrupts ...*/
154 *(vuip
) PYXIS_IACK_SC
;
156 /* Finish writing the 82C59A PIC Operation Control Words */
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.
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 */
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
))
216 #endif /* BUILDING_FOR_MILO */
219 ruffian_init_arch(unsigned long *mem_start
, unsigned long *mem_end
)
221 /* FIXME: What do we do with ruffian_get_bank_size above? */
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();
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 */
249 ruffian_kill_arch (int mode
, char *reboot_cmd
)
252 /* this only causes re-entry to ARCSBIOS */
253 /* Perhaps this works for other PYXIS as well? */
254 *(vuip
) PYXIS_RESET
= 0x0000dead;
257 generic_kill_arch(mode
, reboot_cmd
);
265 struct alpha_machine_vector ruffian_mv __initmv
= {
266 vector_name
: "Ruffian",
269 /* For the moment, do not use BWIO on RUFFIAN. */
270 IO(PYXIS
,pyxis
,pyxis
),
272 machine_check
: pyxis_machine_check
,
273 max_dma_address
: ALPHA_RUFFIAN_MAX_DMA_ADDRESS
,
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
,