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