blob: 460d82b5bc443c03e7939a293a2c55f50a196304 [file] [log] [blame]
Linus Torvalds1da177e2005-04-16 15:20:36 -07001/*
2 * linux/arch/alpha/kernel/sys_jensen.c
3 *
4 * Copyright (C) 1995 Linus Torvalds
5 * Copyright (C) 1998, 1999 Richard Henderson
6 *
7 * Code supporting the Jensen.
8 */
9
10#include <linux/kernel.h>
11#include <linux/types.h>
12#include <linux/mm.h>
13#include <linux/sched.h>
14#include <linux/pci.h>
15#include <linux/init.h>
16
17#include <asm/ptrace.h>
18#include <asm/system.h>
19
20#define __EXTERN_INLINE inline
21#include <asm/io.h>
22#include <asm/jensen.h>
23#undef __EXTERN_INLINE
24
25#include <asm/dma.h>
26#include <asm/irq.h>
27#include <asm/mmu_context.h>
28#include <asm/pgtable.h>
29#include <asm/tlbflush.h>
30
31#include "proto.h"
32#include "irq_impl.h"
33#include "pci_impl.h"
34#include "machvec_impl.h"
35
36
37/*
38 * Jensen is special: the vector is 0x8X0 for EISA interrupt X, and
39 * 0x9X0 for the local motherboard interrupts.
40 *
41 * Note especially that those local interrupts CANNOT be masked,
42 * which causes much of the pain below...
43 *
44 * 0x660 - NMI
45 *
46 * 0x800 - IRQ0 interval timer (not used, as we use the RTC timer)
47 * 0x810 - IRQ1 line printer (duh..)
48 * 0x860 - IRQ6 floppy disk
49 *
50 * 0x900 - COM1
51 * 0x920 - COM2
52 * 0x980 - keyboard
53 * 0x990 - mouse
54 *
55 * PCI-based systems are more sane: they don't have the local
56 * interrupts at all, and have only normal PCI interrupts from
57 * devices. Happily it's easy enough to do a sane mapping from the
58 * Jensen.
59 *
60 * Note that this means that we may have to do a hardware
61 * "local_op" to a different interrupt than we report to the rest of the
62 * world.
63 */
64
65static unsigned int
66jensen_local_startup(unsigned int irq)
67{
68 /* the parport is really hw IRQ 1, silly Jensen. */
69 if (irq == 7)
70 i8259a_startup_irq(1);
Kyle McMartina891b392010-10-14 22:31:25 -040071
Linus Torvalds1da177e2005-04-16 15:20:36 -070072 return 0;
73}
74
75static void
76jensen_local_shutdown(unsigned int irq)
77{
78 /* the parport is really hw IRQ 1, silly Jensen. */
79 if (irq == 7)
80 i8259a_disable_irq(1);
81}
82
83static void
84jensen_local_enable(unsigned int irq)
85{
86 /* the parport is really hw IRQ 1, silly Jensen. */
87 if (irq == 7)
88 i8259a_enable_irq(1);
89}
90
91static void
92jensen_local_disable(unsigned int irq)
93{
94 /* the parport is really hw IRQ 1, silly Jensen. */
95 if (irq == 7)
96 i8259a_disable_irq(1);
97}
98
99static void
100jensen_local_ack(unsigned int irq)
101{
102 /* the parport is really hw IRQ 1, silly Jensen. */
103 if (irq == 7)
104 i8259a_mask_and_ack_irq(1);
105}
106
107static void
108jensen_local_end(unsigned int irq)
109{
110 /* the parport is really hw IRQ 1, silly Jensen. */
111 if (irq == 7)
112 i8259a_end_irq(1);
113}
114
Thomas Gleixner44377f62009-06-16 15:33:25 -0700115static struct irq_chip jensen_local_irq_type = {
Thomas Gleixner8ab12212009-11-30 22:51:31 -0500116 .name = "LOCAL",
Linus Torvalds1da177e2005-04-16 15:20:36 -0700117 .startup = jensen_local_startup,
118 .shutdown = jensen_local_shutdown,
119 .enable = jensen_local_enable,
120 .disable = jensen_local_disable,
121 .ack = jensen_local_ack,
122 .end = jensen_local_end,
123};
124
125static void
Al Viro7ca56052006-10-08 14:36:08 +0100126jensen_device_interrupt(unsigned long vector)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700127{
128 int irq;
129
130 switch (vector) {
131 case 0x660:
132 printk("Whee.. NMI received. Probable hardware error\n");
133 printk("61=%02x, 461=%02x\n", inb(0x61), inb(0x461));
134 return;
135
136 /* local device interrupts: */
137 case 0x900: irq = 4; break; /* com1 -> irq 4 */
138 case 0x920: irq = 3; break; /* com2 -> irq 3 */
139 case 0x980: irq = 1; break; /* kbd -> irq 1 */
140 case 0x990: irq = 9; break; /* mouse -> irq 9 */
141
142 default:
143 if (vector > 0x900) {
144 printk("Unknown local interrupt %lx\n", vector);
145 return;
146 }
147
148 irq = (vector - 0x800) >> 4;
149 if (irq == 1)
150 irq = 7;
151 break;
152 }
153
154 /* If there is no handler yet... */
Kyle McMartina891b392010-10-14 22:31:25 -0400155 if (!irq_has_action(irq)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700156 /* If it is a local interrupt that cannot be masked... */
157 if (vector >= 0x900)
158 {
159 /* Clear keyboard/mouse state */
160 inb(0x64);
161 inb(0x60);
162 /* Reset serial ports */
163 inb(0x3fa);
164 inb(0x2fa);
165 outb(0x0c, 0x3fc);
166 outb(0x0c, 0x2fc);
167 /* Clear NMI */
168 outb(0,0x61);
169 outb(0,0x461);
170 }
171 }
172
173#if 0
174 /* A useful bit of code to find out if an interrupt is going wild. */
175 {
176 static unsigned int last_msg = 0, last_cc = 0;
177 static int last_irq = -1, count = 0;
178 unsigned int cc;
179
180 __asm __volatile("rpcc %0" : "=r"(cc));
181 ++count;
182#define JENSEN_CYCLES_PER_SEC (150000000)
183 if (cc - last_msg > ((JENSEN_CYCLES_PER_SEC) * 3) ||
184 irq != last_irq) {
185 printk(KERN_CRIT " irq %d count %d cc %u @ %lx\n",
Al Viro7ca56052006-10-08 14:36:08 +0100186 irq, count, cc-last_cc, get_irq_regs()->pc);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700187 count = 0;
188 last_msg = cc;
189 last_irq = irq;
190 }
191 last_cc = cc;
192 }
193#endif
194
Al Viro3dbb8c62006-10-08 14:37:32 +0100195 handle_irq(irq);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700196}
197
198static void __init
199jensen_init_irq(void)
200{
201 init_i8259a_irqs();
202
Kyle McMartind5ccde02010-10-14 22:31:11 -0400203 set_irq_chip_and_handler(1, &jensen_local_irq_type, alpha_do_IRQ);
204 set_irq_chip_and_handler(4, &jensen_local_irq_type, alpha_do_IRQ);
205 set_irq_chip_and_handler(3, &jensen_local_irq_type, alpha_do_IRQ);
206 set_irq_chip_and_handler(7, &jensen_local_irq_type, alpha_do_IRQ);
207 set_irq_chip_and_handler(9, &jensen_local_irq_type, alpha_do_IRQ);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700208
209 common_init_isa_dma();
210}
211
212static void __init
213jensen_init_arch(void)
214{
215 struct pci_controller *hose;
216#ifdef CONFIG_PCI
217 static struct pci_dev fake_isa_bridge = { .dma_mask = 0xffffffffUL, };
218
219 isa_bridge = &fake_isa_bridge;
220#endif
221
222 /* Create a hose so that we can report i/o base addresses to
223 userland. */
224
225 pci_isa_hose = hose = alloc_pci_controller();
226 hose->io_space = &ioport_resource;
227 hose->mem_space = &iomem_resource;
228 hose->index = 0;
229
230 hose->sparse_mem_base = EISA_MEM - IDENT_ADDR;
231 hose->dense_mem_base = 0;
232 hose->sparse_io_base = EISA_IO - IDENT_ADDR;
233 hose->dense_io_base = 0;
234
235 hose->sg_isa = hose->sg_pci = NULL;
236 __direct_map_base = 0;
237 __direct_map_size = 0xffffffff;
238}
239
240static void
Randy Dunlap5f0e3da2009-03-31 15:23:36 -0700241jensen_machine_check(unsigned long vector, unsigned long la)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700242{
243 printk(KERN_CRIT "Machine check\n");
244}
245
Linus Torvalds1da177e2005-04-16 15:20:36 -0700246/*
247 * The System Vector
248 */
249
250struct alpha_machine_vector jensen_mv __initmv = {
251 .vector_name = "Jensen",
252 DO_EV4_MMU,
253 IO_LITE(JENSEN,jensen),
254 .machine_check = jensen_machine_check,
255 .max_isa_dma_address = ALPHA_MAX_ISA_DMA_ADDRESS,
256 .rtc_port = 0x170,
Ivan Kokshaysky5f7dc5d2009-01-15 13:51:19 -0800257 .rtc_get_time = common_get_rtc_time,
258 .rtc_set_time = common_set_rtc_time,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700259
260 .nr_irqs = 16,
261 .device_interrupt = jensen_device_interrupt,
262
263 .init_arch = jensen_init_arch,
264 .init_irq = jensen_init_irq,
265 .init_rtc = common_init_rtc,
266 .init_pci = NULL,
267 .kill_arch = NULL,
268};
269ALIAS_MV(jensen)