1 /*- 2 * Copyright (C) 2002 Benno Rice. 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 14 * THIS SOFTWARE IS PROVIDED BY Benno Rice ``AS IS'' AND ANY EXPRESS OR 15 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 16 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 17 * IN NO EVENT SHALL TOOLS GMBH BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 18 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 19 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 20 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 21 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 22 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 23 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24 * 25 * $FreeBSD$ 26 */ 27 28 #include <sys/param.h> 29 #include <sys/systm.h> 30 #include <sys/bus.h> 31 #include <sys/conf.h> 32 #include <sys/kernel.h> 33 #include <sys/rman.h> 34 35 #include <machine/bus.h> 36 #include <machine/intr.h> 37 #include <machine/intr_machdep.h> 38 #include <machine/md_var.h> 39 #include <machine/pio.h> 40 #include <machine/resource.h> 41 42 #include <vm/vm.h> 43 #include <vm/pmap.h> 44 45 #include <machine/openpicreg.h> 46 #include <machine/openpicvar.h> 47 48 #include "pic_if.h" 49 50 devclass_t openpic_devclass; 51 52 /* 53 * Local routines 54 */ 55 56 static __inline uint32_t 57 openpic_read(struct openpic_softc *sc, u_int reg) 58 { 59 return (bus_space_read_4(sc->sc_bt, sc->sc_bh, reg)); 60 } 61 62 static __inline void 63 openpic_write(struct openpic_softc *sc, u_int reg, uint32_t val) 64 { 65 bus_space_write_4(sc->sc_bt, sc->sc_bh, reg, val); 66 } 67 68 static __inline void 69 openpic_set_priority(struct openpic_softc *sc, int cpu, int pri) 70 { 71 uint32_t x; 72 73 x = openpic_read(sc, OPENPIC_CPU_PRIORITY(cpu)); 74 x &= ~OPENPIC_CPU_PRIORITY_MASK; 75 x |= pri; 76 openpic_write(sc, OPENPIC_CPU_PRIORITY(cpu), x); 77 } 78 79 int 80 openpic_attach(device_t dev) 81 { 82 struct openpic_softc *sc; 83 u_int irq; 84 u_int32_t x; 85 86 sc = device_get_softc(dev); 87 sc->sc_dev = dev; 88 89 sc->sc_rid = 0; 90 sc->sc_memr = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &sc->sc_rid, 91 RF_ACTIVE); 92 93 if (sc->sc_memr == NULL) { 94 device_printf(dev, "Could not alloc mem resource!\n"); 95 return (ENXIO); 96 } 97 98 sc->sc_bt = rman_get_bustag(sc->sc_memr); 99 sc->sc_bh = rman_get_bushandle(sc->sc_memr); 100 101 x = openpic_read(sc, OPENPIC_FEATURE); 102 switch (x & OPENPIC_FEATURE_VERSION_MASK) { 103 case 1: 104 sc->sc_version = "1.0"; 105 break; 106 case 2: 107 sc->sc_version = "1.2"; 108 break; 109 case 3: 110 sc->sc_version = "1.3"; 111 break; 112 default: 113 sc->sc_version = "unknown"; 114 break; 115 } 116 117 sc->sc_ncpu = ((x & OPENPIC_FEATURE_LAST_CPU_MASK) >> 118 OPENPIC_FEATURE_LAST_CPU_SHIFT) + 1; 119 sc->sc_nirq = ((x & OPENPIC_FEATURE_LAST_IRQ_MASK) >> 120 OPENPIC_FEATURE_LAST_IRQ_SHIFT) + 1; 121 122 /* 123 * PSIM seems to report 1 too many IRQs 124 */ 125 if (sc->sc_psim) 126 sc->sc_nirq--; 127 128 if (bootverbose) 129 device_printf(dev, 130 "Version %s, supports %d CPUs and %d irqs\n", 131 sc->sc_version, sc->sc_ncpu, sc->sc_nirq); 132 133 /* disable all interrupts */ 134 for (irq = 0; irq < sc->sc_nirq; irq++) 135 openpic_write(sc, OPENPIC_SRC_VECTOR(irq), OPENPIC_IMASK); 136 137 openpic_set_priority(sc, 0, 15); 138 139 /* we don't need 8259 passthrough mode */ 140 x = openpic_read(sc, OPENPIC_CONFIG); 141 x |= OPENPIC_CONFIG_8259_PASSTHRU_DISABLE; 142 openpic_write(sc, OPENPIC_CONFIG, x); 143 144 /* send all interrupts to cpu 0 */ 145 for (irq = 0; irq < sc->sc_nirq; irq++) 146 openpic_write(sc, OPENPIC_IDEST(irq), 1 << 0); 147 148 for (irq = 0; irq < sc->sc_nirq; irq++) { 149 x = irq; /* irq == vector. */ 150 x |= OPENPIC_IMASK; 151 x |= OPENPIC_POLARITY_POSITIVE; 152 x |= OPENPIC_SENSE_LEVEL; 153 x |= 8 << OPENPIC_PRIORITY_SHIFT; 154 openpic_write(sc, OPENPIC_SRC_VECTOR(irq), x); 155 } 156 157 /* XXX IPI */ 158 /* XXX set spurious intr vector */ 159 160 openpic_set_priority(sc, 0, 0); 161 162 /* clear all pending interrupts */ 163 for (irq = 0; irq < sc->sc_nirq; irq++) { 164 (void)openpic_read(sc, OPENPIC_IACK(0)); 165 openpic_write(sc, OPENPIC_EOI(0), 0); 166 } 167 168 powerpc_register_pic(dev); 169 170 return (0); 171 } 172 173 /* 174 * PIC I/F methods 175 */ 176 177 void 178 openpic_dispatch(device_t dev, struct trapframe *tf) 179 { 180 struct openpic_softc *sc; 181 u_int vector; 182 183 sc = device_get_softc(dev); 184 while (1) { 185 vector = openpic_read(sc, OPENPIC_IACK(0)); 186 vector &= OPENPIC_VECTOR_MASK; 187 if (vector == 255) 188 break; 189 powerpc_dispatch_intr(vector, tf); 190 } 191 } 192 193 void 194 openpic_enable(device_t dev, u_int irq, u_int vector) 195 { 196 struct openpic_softc *sc; 197 uint32_t x; 198 199 sc = device_get_softc(dev); 200 x = openpic_read(sc, OPENPIC_SRC_VECTOR(irq)); 201 x &= ~(OPENPIC_IMASK | OPENPIC_VECTOR_MASK); 202 x |= vector; 203 openpic_write(sc, OPENPIC_SRC_VECTOR(irq), x); 204 } 205 206 void 207 openpic_eoi(device_t dev, u_int irq __unused) 208 { 209 struct openpic_softc *sc; 210 211 sc = device_get_softc(dev); 212 openpic_write(sc, OPENPIC_EOI(0), 0); 213 } 214 215 void 216 openpic_mask(device_t dev, u_int irq) 217 { 218 struct openpic_softc *sc; 219 uint32_t x; 220 221 sc = device_get_softc(dev); 222 x = openpic_read(sc, OPENPIC_SRC_VECTOR(irq)); 223 x |= OPENPIC_IMASK; 224 openpic_write(sc, OPENPIC_SRC_VECTOR(irq), x); 225 openpic_write(sc, OPENPIC_EOI(0), 0); 226 } 227 228 void 229 openpic_unmask(device_t dev, u_int irq) 230 { 231 struct openpic_softc *sc; 232 uint32_t x; 233 234 sc = device_get_softc(dev); 235 x = openpic_read(sc, OPENPIC_SRC_VECTOR(irq)); 236 x &= ~OPENPIC_IMASK; 237 openpic_write(sc, OPENPIC_SRC_VECTOR(irq), x); 238 } 239