1 /* $NetBSD: pcctwo_68k.c,v 1.3 2002/10/02 05:28:14 thorpej Exp $ */ 2 3 /*- 4 * Copyright (c) 1999, 2002 The NetBSD Foundation, Inc. 5 * All rights reserved. 6 * 7 * This code is derived from software contributed to The NetBSD Foundation 8 * by Steve C. Woodford. 9 * 10 * Redistribution and use in source and binary forms, with or without 11 * modification, are permitted provided that the following conditions 12 * are met: 13 * 1. Redistributions of source code must retain the above copyright 14 * notice, this list of conditions and the following disclaimer. 15 * 2. Redistributions in binary form must reproduce the above copyright 16 * notice, this list of conditions and the following disclaimer in the 17 * documentation and/or other materials provided with the distribution. 18 * 3. All advertising materials mentioning features or use of this software 19 * must display the following acknowledgement: 20 * This product includes software developed by the NetBSD 21 * Foundation, Inc. and its contributors. 22 * 4. Neither the name of The NetBSD Foundation nor the names of its 23 * contributors may be used to endorse or promote products derived 24 * from this software without specific prior written permission. 25 * 26 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 27 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 28 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 29 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 30 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 31 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 32 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 33 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 34 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 35 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 36 * POSSIBILITY OF SUCH DAMAGE. 37 */ 38 39 /* 40 * PCCchip2 and MCchip Mvme68k Front End Driver 41 */ 42 43 #include <sys/param.h> 44 #include <sys/kernel.h> 45 #include <sys/systm.h> 46 #include <sys/device.h> 47 48 #include <machine/cpu.h> 49 #include <machine/bus.h> 50 51 #include <mvme68k/dev/mainbus.h> 52 #include <mvme68k/mvme68k/isr.h> 53 54 #include <dev/mvme/pcctworeg.h> 55 #include <dev/mvme/pcctwovar.h> 56 57 /* 58 * Autoconfiguration stuff. 59 */ 60 void pcctwoattach(struct device *, struct device *, void *); 61 int pcctwomatch(struct device *, struct cfdata *, void *); 62 63 CFATTACH_DECL(pcctwo, sizeof(struct pcctwo_softc), 64 pcctwomatch, pcctwoattach, NULL, NULL); 65 66 extern struct cfdriver pcctwo_cd; 67 68 69 #if defined(MVME167) || defined(MVME177) 70 /* 71 * Devices that live on the PCCchip2, attached in this order. 72 */ 73 static struct pcctwo_device pcctwo_devices[] = { 74 {"clock", 0}, 75 {"clmpcc", PCCTWO_SCC_OFF}, 76 {"ie", PCCTWO_IE_OFF}, 77 {"osiop", PCCTWO_NCRSC_OFF}, 78 {"lpt", PCCTWO_LPT_OFF}, 79 {NULL, 0} 80 }; 81 82 static int pcctwo_vec2icsr_1x7[] = { 83 VEC2ICSR(PCC2REG_PRT_BUSY_ICSR, PCCTWO_ICR_EDGE | PCCTWO_ICR_ICLR), 84 VEC2ICSR(PCC2REG_PRT_PE_ICSR, PCCTWO_ICR_EDGE | PCCTWO_ICR_ICLR), 85 VEC2ICSR(PCC2REG_PRT_SEL_ICSR, PCCTWO_ICR_EDGE | PCCTWO_ICR_ICLR), 86 VEC2ICSR(PCC2REG_PRT_FAULT_ICSR, PCCTWO_ICR_EDGE | PCCTWO_ICR_ICLR), 87 VEC2ICSR(PCC2REG_PRT_ACK_ICSR, PCCTWO_ICR_EDGE | PCCTWO_ICR_ICLR), 88 VEC2ICSR(PCC2REG_SCSI_ICSR, 0), 89 VEC2ICSR(PCC2REG_ETH_ICSR, PCCTWO_ICR_EDGE | PCCTWO_ICR_ICLR), 90 VEC2ICSR(PCC2REG_ETH_ICSR, PCCTWO_ICR_EDGE | PCCTWO_ICR_ICLR), 91 VEC2ICSR(PCC2REG_TIMER2_ICSR, PCCTWO_ICR_ICLR), 92 VEC2ICSR(PCC2REG_TIMER1_ICSR, PCCTWO_ICR_ICLR), 93 VEC2ICSR(PCC2REG_GPIO_ICSR, PCCTWO_ICR_EDGE | PCCTWO_ICR_ICLR), 94 -1, 95 VEC2ICSR(PCC2REG_SCC_RX_ICSR, 0), 96 VEC2ICSR(PCC2REG_SCC_MODEM_ICSR, 0), 97 VEC2ICSR(PCC2REG_SCC_TX_ICSR, 0), 98 VEC2ICSR(PCC2REG_SCC_RX_ICSR, 0) 99 }; 100 #endif 101 102 #if defined(MVME162) || defined(MVME172) 103 /* 104 * Devices that live on the MCchip, attached in this order. 105 */ 106 static struct pcctwo_device mcchip_devices[] = { 107 {"clock", 0}, 108 {"zsc", MCCHIP_ZS0_OFF}, 109 {"zsc", MCCHIP_ZS1_OFF}, 110 {"ie", PCCTWO_IE_OFF}, 111 {"osiop", PCCTWO_NCRSC_OFF}, 112 {NULL, 0} 113 }; 114 115 static int pcctwo_vec2icsr_1x2[] = { 116 -1, 117 -1, 118 -1, 119 VEC2ICSR(MCCHIPREG_TIMER4_ICSR, PCCTWO_ICR_ICLR), 120 VEC2ICSR(MCCHIPREG_TIMER3_ICSR, PCCTWO_ICR_ICLR), 121 VEC2ICSR(PCC2REG_SCSI_ICSR, 0), 122 VEC2ICSR(PCC2REG_ETH_ICSR, PCCTWO_ICR_EDGE | PCCTWO_ICR_ICLR), 123 VEC2ICSR(PCC2REG_ETH_ICSR, PCCTWO_ICR_EDGE | PCCTWO_ICR_ICLR), 124 VEC2ICSR(PCC2REG_TIMER2_ICSR, PCCTWO_ICR_ICLR), 125 VEC2ICSR(PCC2REG_TIMER1_ICSR, PCCTWO_ICR_ICLR), 126 -1, 127 VEC2ICSR(MCCHIPREG_PARERR_ICSR, PCCTWO_ICR_ICLR), 128 VEC2ICSR(MCCHIPREG_SCC_ICSR, 0), 129 VEC2ICSR(MCCHIPREG_SCC_ICSR, 0), 130 VEC2ICSR(MCCHIPREG_ABORT_ICSR, PCCTWO_ICR_ICLR), 131 -1 132 }; 133 134 static int pcctwoabortintr(void *); 135 void pcctwosoftintrinit(void); 136 static int pcctwosoftintr(void *); 137 static void pcctwosoftintrassert(void); 138 #endif 139 140 static void pcctwoisrlink(void *, int (*)(void *), void *, 141 int, int, struct evcnt *); 142 static void pcctwoisrunlink(void *, int); 143 static struct evcnt *pcctwoisrevcnt(void *, int); 144 145 146 /* ARGSUSED */ 147 int 148 pcctwomatch(parent, cf, args) 149 struct device *parent; 150 struct cfdata *cf; 151 void *args; 152 { 153 struct mainbus_attach_args *ma; 154 bus_space_handle_t bh; 155 u_int8_t cid; 156 157 ma = args; 158 159 /* There can be only one. */ 160 if (sys_pcctwo || strcmp(ma->ma_name, pcctwo_cd.cd_name)) 161 return (0); 162 163 /* 164 * Grab the Chip's ID 165 */ 166 bus_space_map(ma->ma_bust, PCCTWO_REG_OFF + ma->ma_offset, 167 PCC2REG_SIZE, 0, &bh); 168 cid = bus_space_read_1(ma->ma_bust, bh, PCC2REG_CHIP_ID); 169 bus_space_unmap(ma->ma_bust, bh, PCC2REG_SIZE); 170 171 #if defined(MVME167) || defined(MVME177) 172 if ((machineid == MVME_167 || machineid == MVME_177) && 173 cid == PCCTWO_CHIP_ID_PCC2) 174 return (1); 175 #endif 176 #if defined(MVME162) || defined(MVME172) 177 if ((machineid == MVME_162 || machineid == MVME_172) && 178 cid == PCCTWO_CHIP_ID_MCCHIP) 179 return (1); 180 #endif 181 182 return (0); 183 } 184 185 /* ARGSUSED */ 186 void 187 pcctwoattach(parent, self, args) 188 struct device *parent; 189 struct device *self; 190 void *args; 191 { 192 struct mainbus_attach_args *ma; 193 struct pcctwo_softc *sc; 194 struct pcctwo_device *pd = NULL; 195 u_int8_t cid; 196 197 ma = args; 198 sc = sys_pcctwo = (struct pcctwo_softc *) self; 199 200 /* Get a handle to the PCCChip2's registers */ 201 sc->sc_bust = ma->ma_bust; 202 sc->sc_dmat = ma->ma_dmat; 203 bus_space_map(sc->sc_bust, PCCTWO_REG_OFF + ma->ma_offset, 204 PCC2REG_SIZE, 0, &sc->sc_bush); 205 206 sc->sc_vecbase = PCCTWO_VECBASE; 207 sc->sc_isrlink = pcctwoisrlink; 208 sc->sc_isrevcnt = pcctwoisrevcnt; 209 sc->sc_isrunlink = pcctwoisrunlink; 210 211 cid = pcc2_reg_read(sc, PCC2REG_CHIP_ID); 212 213 #if defined(MVME167) || defined(MVME177) 214 if (cid == PCCTWO_CHIP_ID_PCC2) { 215 pd = pcctwo_devices; 216 sc->sc_vec2icsr = pcctwo_vec2icsr_1x7; 217 } 218 #endif 219 #if defined(MVME162) || defined(MVME172) 220 if (cid == PCCTWO_CHIP_ID_MCCHIP) { 221 pd = mcchip_devices; 222 sc->sc_vec2icsr = pcctwo_vec2icsr_1x2; 223 } 224 #endif 225 226 /* Finish initialisation in common code */ 227 pcctwo_init(sc, pd, ma->ma_offset); 228 229 #if defined(MVME162) || defined(MVME172) 230 if (cid == PCCTWO_CHIP_ID_MCCHIP) { 231 evcnt_attach_dynamic(&sc->sc_evcnt, EVCNT_TYPE_INTR, 232 isrlink_evcnt(7), "nmi", "abort sw"); 233 pcctwointr_establish(MCCHIPV_ABORT, pcctwoabortintr, 7, NULL, 234 &sc->sc_evcnt); 235 } 236 #endif 237 } 238 239 /* ARGSUSED */ 240 static void 241 pcctwoisrlink(cookie, fn, arg, ipl, vec, evcnt) 242 void *cookie; 243 int (*fn)(void *); 244 void *arg; 245 int ipl, vec; 246 struct evcnt *evcnt; 247 { 248 249 isrlink_vectored(fn, arg, ipl, vec, evcnt); 250 } 251 252 /* ARGSUSED */ 253 static void 254 pcctwoisrunlink(cookie, vec) 255 void *cookie; 256 int vec; 257 { 258 259 isrunlink_vectored(vec); 260 } 261 262 /* ARGSUSED */ 263 static struct evcnt * 264 pcctwoisrevcnt(cookie, ipl) 265 void *cookie; 266 int ipl; 267 { 268 269 return (isrlink_evcnt(ipl)); 270 } 271 272 #if defined(MVME162) || defined(MVME172) 273 static int 274 pcctwoabortintr(void *frame) 275 { 276 277 pcc2_reg_write(sys_pcctwo, MCCHIPREG_ABORT_ICSR, PCCTWO_ICR_ICLR | 278 pcc2_reg_read(sys_pcctwo, MCCHIPREG_ABORT_ICSR)); 279 280 return (nmihand(frame)); 281 } 282 283 void 284 pcctwosoftintrinit(void) 285 { 286 287 /* 288 * Since the VMEChip2 is normally used to generate 289 * software interrupts to the CPU, we have to deal 290 * with 162/172 boards which have the "No VMEChip2" 291 * build option. 292 * 293 * When such a board is found, the VMEChip2 probe code 294 * calls this function to implement software interrupts 295 * the hard way; using tick timer 4 ... 296 */ 297 pcctwointr_establish(MCCHIPV_TIMER4, pcctwosoftintr, 298 1, sys_pcctwo, &sys_pcctwo->sc_evcnt); 299 pcc2_reg_write(sys_pcctwo, MCCHIPREG_TIMER4_CTRL, 0); 300 pcc2_reg_write32(sys_pcctwo, MCCHIPREG_TIMER4_COMP, 1); 301 pcc2_reg_write32(sys_pcctwo, MCCHIPREG_TIMER4_CNTR, 0); 302 _softintr_chipset_assert = pcctwosoftintrassert; 303 } 304 305 static int 306 pcctwosoftintr(void *arg) 307 { 308 struct pcctwo_softc *sc = arg; 309 310 pcc2_reg_write32(sc, MCCHIPREG_TIMER4_CNTR, 0); 311 pcc2_reg_write(sc, MCCHIPREG_TIMER4_CTRL, 0); 312 pcc2_reg_write(sc, MCCHIPREG_TIMER4_ICSR, 313 PCCTWO_ICR_ICLR | PCCTWO_ICR_IEN | 1); 314 315 softintr_dispatch(); 316 317 return (1); 318 } 319 320 static void 321 pcctwosoftintrassert(void) 322 { 323 324 /* 325 * Schedule a timer interrupt to happen in ~1uS. 326 * This is more than adequate on any available m68k platform 327 * for simulating software interrupts. 328 */ 329 pcc2_reg_write(sys_pcctwo, MCCHIPREG_TIMER4_CTRL, PCCTWO_TT_CTRL_CEN); 330 } 331 #endif 332