isa_shark_machdep.c revision 1.4 1 1.4 lukem /* $NetBSD: isa_shark_machdep.c,v 1.4 2003/07/15 03:36:01 lukem Exp $ */
2 1.1 thorpej
3 1.1 thorpej /*
4 1.1 thorpej * Copyright 1997
5 1.1 thorpej * Digital Equipment Corporation. All rights reserved.
6 1.1 thorpej *
7 1.1 thorpej * This software is furnished under license and may be used and
8 1.1 thorpej * copied only in accordance with the following terms and conditions.
9 1.1 thorpej * Subject to these conditions, you may download, copy, install,
10 1.1 thorpej * use, modify and distribute this software in source and/or binary
11 1.1 thorpej * form. No title or ownership is transferred hereby.
12 1.1 thorpej *
13 1.1 thorpej * 1) Any source code used, modified or distributed must reproduce
14 1.1 thorpej * and retain this copyright notice and list of conditions as
15 1.1 thorpej * they appear in the source file.
16 1.1 thorpej *
17 1.1 thorpej * 2) No right is granted to use any trade name, trademark, or logo of
18 1.1 thorpej * Digital Equipment Corporation. Neither the "Digital Equipment
19 1.1 thorpej * Corporation" name nor any trademark or logo of Digital Equipment
20 1.1 thorpej * Corporation may be used to endorse or promote products derived
21 1.1 thorpej * from this software without the prior written permission of
22 1.1 thorpej * Digital Equipment Corporation.
23 1.1 thorpej *
24 1.1 thorpej * 3) This software is provided "AS-IS" and any express or implied
25 1.1 thorpej * warranties, including but not limited to, any implied warranties
26 1.1 thorpej * of merchantability, fitness for a particular purpose, or
27 1.1 thorpej * non-infringement are disclaimed. In no event shall DIGITAL be
28 1.1 thorpej * liable for any damages whatsoever, and in particular, DIGITAL
29 1.1 thorpej * shall not be liable for special, indirect, consequential, or
30 1.1 thorpej * incidental damages or damages for lost profits, loss of
31 1.1 thorpej * revenue or loss of use, whether such damages arise in contract,
32 1.1 thorpej * negligence, tort, under statute, in equity, at law or otherwise,
33 1.1 thorpej * even if advised of the possibility of such damage.
34 1.1 thorpej */
35 1.4 lukem
36 1.4 lukem #include <sys/cdefs.h>
37 1.4 lukem __KERNEL_RCSID(0, "$NetBSD: isa_shark_machdep.c,v 1.4 2003/07/15 03:36:01 lukem Exp $");
38 1.1 thorpej
39 1.1 thorpej #include <sys/param.h>
40 1.1 thorpej #include <sys/systm.h>
41 1.1 thorpej #include <sys/kernel.h>
42 1.1 thorpej #include <sys/syslog.h>
43 1.1 thorpej #include <sys/device.h>
44 1.1 thorpej #include <sys/malloc.h>
45 1.1 thorpej
46 1.1 thorpej #include <machine/intr.h>
47 1.1 thorpej #include <machine/pio.h>
48 1.1 thorpej
49 1.1 thorpej #include <dev/isa/isareg.h>
50 1.1 thorpej #include <dev/isa/isavar.h>
51 1.1 thorpej #include <dev/isa/isadmavar.h>
52 1.1 thorpej #include <shark/isa/icu.h>
53 1.1 thorpej
54 1.1 thorpej #include <machine/ofw.h>
55 1.1 thorpej
56 1.1 thorpej struct arm32_isa_chipset isa_chipset_tag;
57 1.1 thorpej
58 1.1 thorpej unsigned i8259_mask;
59 1.1 thorpej
60 1.3 chs void isa_init8259s(void);
61 1.3 chs
62 1.1 thorpej /* Notes on the interaction of StrongARM and ISA. A lot of the nastiness
63 1.1 thorpej is caused by consciously prostituting shark to a low bill of materials.
64 1.1 thorpej
65 1.1 thorpej It takes on the order of 700ns (about 150 instruction cycles at
66 1.1 thorpej 233 MHz) to access the ISA bus, so it is important to minimize the number
67 1.1 thorpej of ISA accesses, in particular to the 8259 interrupt controllers.
68 1.1 thorpej
69 1.1 thorpej To reduce the number of accesses, the 8259's are NOT run in the
70 1.1 thorpej same mode as on a typical Intel (IBM AT) system, which requires
71 1.1 thorpej an interrupt acknowledge sequence (INTA) for every interrupt.
72 1.1 thorpej Instead, the 8259's are used as big OR gates with interrupt masks
73 1.1 thorpej on the front. The code in irq.S takes particular care to cache
74 1.1 thorpej the state of the interrupt masks and only update them when absolutely
75 1.1 thorpej necessary.
76 1.1 thorpej
77 1.1 thorpej Unfortunately, resetting the 8259 edge detectors without a real
78 1.1 thorpej INTA sequence is problematic at best. To complicate matters further,
79 1.1 thorpej (unlike EISA components) the 8259s on the Sequoia core logic do
80 1.1 thorpej not allow configuration of edge vs. level on an IRQ-by-IRQ basis.
81 1.1 thorpej Thus, all interrupts must be either edge-triggered or level-triggered.
82 1.1 thorpej To preserve the sanity of the system, this code chooses the
83 1.1 thorpej level-triggered configuration.
84 1.1 thorpej
85 1.1 thorpej None of the possible operation modes of the 8254 interval timers can
86 1.1 thorpej be used to generate a periodic, level-triggered, clearable clock
87 1.1 thorpej interrupt. This restriction means that TIMER0 -- hardwired to IRQ0 --
88 1.1 thorpej may not be used as the heartbeat timer, as it is on Intel-based PCs.
89 1.1 thorpej Instead, the real-time clock (RTC) interrupt -- connected to
90 1.1 thorpej IRQ8 -- has the right properties and is used for the heartbeat interrupt.
91 1.1 thorpej TIMER0 may still be used to implement a microsecond timer.
92 1.1 thorpej See clock.c for details.
93 1.1 thorpej
94 1.1 thorpej As on most PC systems, 8254 TIMER1 is used for the ISA refresh signal.
95 1.1 thorpej
96 1.1 thorpej Unlike most PC systems, 8254 TIMER2 is not used for cheap tone
97 1.1 thorpej generation. Instead, it is used to create a high-availability interrupt
98 1.1 thorpej for bit-bashing functions (e.g. for SmartCard access). TIMER2 output,
99 1.1 thorpej called "SPKR" on Sequoia 2, is routed back into the SWTCH input on
100 1.1 thorpej Sequoia 1. This input eventually reemerges from Sequoia 1 on the SMI pin,
101 1.1 thorpej which is then converted into the StrongARM FIQ (fast interrupt request).
102 1.1 thorpej To clear this interrupt, the StrongARM clears the SMI.
103 1.1 thorpej See .../shark/fiq.S for details.
104 1.1 thorpej
105 1.1 thorpej One more complication: ISA devices can be rather nasty with respect
106 1.1 thorpej to ISA bus usage. For example, the CS8900 ethernet chip will occupy
107 1.1 thorpej the bus for very long DMA streams. It is possible to configure the
108 1.1 thorpej chip so it relinquishes the ISA bus every 28 usec or so
109 1.1 thorpej (about every 6500 instructions). This causes problems when trying
110 1.1 thorpej to run the TIMER2/SMI/FIQ at 50 kHz, which is required to detect the
111 1.1 thorpej baud rate of the SmartCard. A modification to .../dev/isa/isadma.c
112 1.1 thorpej allows the processor to freeze DMA during critial periods of time.
113 1.1 thorpej This is a working -- but not very satisfactory -- solution to the problem.
114 1.1 thorpej */
115 1.1 thorpej
116 1.1 thorpej /*
117 1.1 thorpej * Initialize the interrupt controllers.
118 1.1 thorpej */
119 1.1 thorpej void
120 1.3 chs isa_init8259s(void)
121 1.1 thorpej {
122 1.1 thorpej /* initialize 8259's */
123 1.1 thorpej outb(IO_ICU1, 0x19); /* reset; four bytes, level triggered */
124 1.1 thorpej outb(IO_ICU1+1, ICU_OFFSET); /* int base: not used */
125 1.1 thorpej outb(IO_ICU1+1, 1 << IRQ_SLAVE); /* slave on line 2 */
126 1.1 thorpej outb(IO_ICU1+1, 2 | 1); /* auto EOI, 8086 mode */
127 1.1 thorpej outb(IO_ICU1+1, 0xff); /* disable all interrupts */
128 1.1 thorpej outb(IO_ICU1, 0x68); /* special mask mode (if available) */
129 1.1 thorpej outb(IO_ICU1, 0x0a); /* Read IRR, not ISR */
130 1.1 thorpej
131 1.1 thorpej outb(IO_ICU2, 0x19); /* reset; four bytes, level triggered */
132 1.1 thorpej outb(IO_ICU2+1, ICU_OFFSET+8); /* int base + offset for master: not used */
133 1.1 thorpej outb(IO_ICU2+1, IRQ_SLAVE); /* who ami i? */
134 1.1 thorpej outb(IO_ICU2+1, 2 | 1); /* auto EOI, 8086 mode */
135 1.1 thorpej outb(IO_ICU2+1, 0xff); /* disable all interrupts */
136 1.1 thorpej outb(IO_ICU2, 0x68); /* special mask mode (if available) */
137 1.1 thorpej outb(IO_ICU2, 0x0a); /* Read IRR by default. */
138 1.1 thorpej
139 1.1 thorpej i8259_mask = 0x0000ffff; /* everything disabled */
140 1.1 thorpej }
141 1.1 thorpej
142 1.1 thorpej #define LEGAL_IRQ(x) ((x) >= 0 && (x) < ICU_LEN && (x) != 2)
143 1.1 thorpej
144 1.1 thorpej const struct evcnt *
145 1.1 thorpej isa_intr_evcnt(isa_chipset_tag_t ic, int irq)
146 1.1 thorpej {
147 1.1 thorpej
148 1.1 thorpej /* XXX for now, no evcnt parent reported */
149 1.1 thorpej return NULL;
150 1.1 thorpej }
151 1.1 thorpej
152 1.1 thorpej /*
153 1.1 thorpej * Set up an interrupt handler to start being called.
154 1.1 thorpej */
155 1.2 cgd static const char * const isa_intr_names[16] = {
156 1.2 cgd "isa intr 0", "isa intr 1", "isa intr 2", "isa intr 3",
157 1.2 cgd "isa intr 4", "isa intr 5", "isa intr 6", "isa intr 7",
158 1.2 cgd "isa intr 8", "isa intr 9", "isa intr 10", "isa intr 11",
159 1.2 cgd "isa intr 12", "isa intr 13", "isa intr 14", "isa intr 15"
160 1.2 cgd };
161 1.2 cgd
162 1.1 thorpej void *
163 1.1 thorpej isa_intr_establish(ic, irq, type, level, ih_fun, ih_arg)
164 1.1 thorpej isa_chipset_tag_t ic;
165 1.1 thorpej int irq;
166 1.1 thorpej int type;
167 1.1 thorpej int level;
168 1.1 thorpej int (*ih_fun) __P((void *));
169 1.1 thorpej void *ih_arg;
170 1.1 thorpej {
171 1.1 thorpej irqhandler_t *ih;
172 1.1 thorpej
173 1.1 thorpej /* no point in sleeping unless someone can free memory. */
174 1.1 thorpej ih = malloc(sizeof *ih, M_DEVBUF, cold ? M_NOWAIT : M_WAITOK);
175 1.1 thorpej if (ih == NULL)
176 1.1 thorpej panic("isa_intr_establish: can't malloc handler info");
177 1.1 thorpej
178 1.1 thorpej if (!LEGAL_IRQ(irq) || type == IST_NONE)
179 1.1 thorpej panic("intr_establish: bogus irq or type");
180 1.1 thorpej
181 1.1 thorpej /* Note: sequoia doesn't allow configuration of edge vs. level
182 1.1 thorpej on an IRQ-by-IRQ basis. */
183 1.1 thorpej if (type != IST_LEVEL)
184 1.1 thorpej printf("WARNING: irq %d not level triggered\n", irq);
185 1.1 thorpej
186 1.1 thorpej memset(ih, 0, sizeof *ih);
187 1.1 thorpej ih->ih_func = ih_fun;
188 1.1 thorpej ih->ih_arg = ih_arg;
189 1.1 thorpej ih->ih_level = level;
190 1.2 cgd if (irq >= 0 &&
191 1.2 cgd irq < (sizeof isa_intr_names / sizeof isa_intr_names[0]))
192 1.2 cgd ih->ih_name = isa_intr_names[irq];
193 1.2 cgd else
194 1.2 cgd ih->ih_name = "isa intr";
195 1.1 thorpej
196 1.1 thorpej if (irq_claim(irq, ih) == -1)
197 1.1 thorpej panic("isa_intr_establish: can't install handler");
198 1.1 thorpej
199 1.1 thorpej return (ih);
200 1.1 thorpej }
201 1.1 thorpej
202 1.1 thorpej
203 1.1 thorpej /*
204 1.1 thorpej * Deregister an interrupt handler.
205 1.1 thorpej */
206 1.1 thorpej void
207 1.1 thorpej isa_intr_disestablish(ic, arg)
208 1.1 thorpej isa_chipset_tag_t ic;
209 1.1 thorpej void *arg;
210 1.1 thorpej {
211 1.1 thorpej panic("isa_intr_disestablish");
212 1.1 thorpej }
213 1.1 thorpej
214 1.1 thorpej /* isa_init() might eventually become the ISA attach routine */
215 1.1 thorpej void
216 1.1 thorpej isa_init(vm_offset_t isa_io_addr, vm_offset_t isa_mem_addr)
217 1.1 thorpej {
218 1.1 thorpej /* initialize the bus space functions */
219 1.1 thorpej isa_io_init(isa_io_addr, isa_mem_addr);
220 1.1 thorpej
221 1.1 thorpej /* Clear the IRQ/FIQ masks */
222 1.1 thorpej isa_init8259s();
223 1.1 thorpej
224 1.1 thorpej /* Initialize the ISA interrupt handling code */
225 1.1 thorpej irq_init();
226 1.1 thorpej }
227 1.1 thorpej
228 1.1 thorpej void
229 1.1 thorpej isa_attach_hook(parent, self, iba)
230 1.1 thorpej struct device *parent, *self;
231 1.1 thorpej struct isabus_attach_args *iba;
232 1.1 thorpej {
233 1.1 thorpej
234 1.1 thorpej /*
235 1.1 thorpej * Since we can only have one ISA bus, we just use a single
236 1.1 thorpej * statically allocated ISA chipset structure. Pass it up
237 1.1 thorpej * now.
238 1.1 thorpej */
239 1.1 thorpej iba->iba_ic = &isa_chipset_tag;
240 1.1 thorpej }
241