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