1 /* $NetBSD: pcctwo_68k.c,v 1.1 2002/02/12 20:38:25 scw 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 struct cfattach pcctwo_ca = { 64 sizeof(struct pcctwo_softc), pcctwomatch, pcctwoattach 65 }; 66 67 extern struct cfdriver pcctwo_cd; 68 69 70 #if defined(MVME167) || defined(MVME177) 71 /* 72 * Devices that live on the PCCchip2, attached in this order. 73 */ 74 static struct pcctwo_device pcctwo_devices[] = { 75 {"clock", 0}, 76 {"clmpcc", PCCTWO_SCC_OFF}, 77 {"ie", PCCTWO_IE_OFF}, 78 {"osiop", PCCTWO_NCRSC_OFF}, 79 {"lpt", PCCTWO_LPT_OFF}, 80 {NULL, 0} 81 }; 82 83 static int pcctwo_vec2icsr_1x7[] = { 84 VEC2ICSR(PCC2REG_PRT_BUSY_ICSR, PCCTWO_ICR_EDGE | PCCTWO_ICR_ICLR), 85 VEC2ICSR(PCC2REG_PRT_PE_ICSR, PCCTWO_ICR_EDGE | PCCTWO_ICR_ICLR), 86 VEC2ICSR(PCC2REG_PRT_SEL_ICSR, PCCTWO_ICR_EDGE | PCCTWO_ICR_ICLR), 87 VEC2ICSR(PCC2REG_PRT_FAULT_ICSR, PCCTWO_ICR_EDGE | PCCTWO_ICR_ICLR), 88 VEC2ICSR(PCC2REG_PRT_ACK_ICSR, PCCTWO_ICR_EDGE | PCCTWO_ICR_ICLR), 89 VEC2ICSR(PCC2REG_SCSI_ICSR, 0), 90 VEC2ICSR(PCC2REG_ETH_ICSR, PCCTWO_ICR_EDGE | PCCTWO_ICR_ICLR), 91 VEC2ICSR(PCC2REG_ETH_ICSR, PCCTWO_ICR_EDGE | PCCTWO_ICR_ICLR), 92 VEC2ICSR(PCC2REG_TIMER2_ICSR, PCCTWO_ICR_ICLR), 93 VEC2ICSR(PCC2REG_TIMER1_ICSR, PCCTWO_ICR_ICLR), 94 VEC2ICSR(PCC2REG_GPIO_ICSR, PCCTWO_ICR_EDGE | PCCTWO_ICR_ICLR), 95 -1, 96 VEC2ICSR(PCC2REG_SCC_RX_ICSR, 0), 97 VEC2ICSR(PCC2REG_SCC_MODEM_ICSR, 0), 98 VEC2ICSR(PCC2REG_SCC_TX_ICSR, 0), 99 VEC2ICSR(PCC2REG_SCC_RX_ICSR, 0) 100 }; 101 #endif 102 103 #if defined(MVME162) || defined(MVME172) 104 /* 105 * Devices that live on the MCchip, attached in this order. 106 */ 107 static struct pcctwo_device mcchip_devices[] = { 108 {"clock", 0}, 109 {"zsc", MCCHIP_ZS0_OFF}, 110 {"zsc", MCCHIP_ZS1_OFF}, 111 {"ie", PCCTWO_IE_OFF}, 112 {"osiop", PCCTWO_NCRSC_OFF}, 113 {NULL, 0} 114 }; 115 116 static int pcctwo_vec2icsr_1x2[] = { 117 -1, 118 -1, 119 -1, 120 VEC2ICSR(MCCHIPREG_TIMER4_ICSR, PCCTWO_ICR_ICLR), 121 VEC2ICSR(MCCHIPREG_TIMER3_ICSR, PCCTWO_ICR_ICLR), 122 VEC2ICSR(PCC2REG_SCSI_ICSR, 0), 123 VEC2ICSR(PCC2REG_ETH_ICSR, PCCTWO_ICR_EDGE | PCCTWO_ICR_ICLR), 124 VEC2ICSR(PCC2REG_ETH_ICSR, PCCTWO_ICR_EDGE | PCCTWO_ICR_ICLR), 125 VEC2ICSR(PCC2REG_TIMER2_ICSR, PCCTWO_ICR_ICLR), 126 VEC2ICSR(PCC2REG_TIMER1_ICSR, PCCTWO_ICR_ICLR), 127 -1, 128 VEC2ICSR(MCCHIPREG_PARERR_ICSR, PCCTWO_ICR_ICLR), 129 VEC2ICSR(MCCHIPREG_SCC_ICSR, 0), 130 VEC2ICSR(MCCHIPREG_SCC_ICSR, 0), 131 VEC2ICSR(MCCHIPREG_ABORT_ICSR, PCCTWO_ICR_ICLR), 132 -1 133 }; 134 135 static int pcctwoabortintr(void *); 136 void pcctwosoftintrinit(void); 137 static int pcctwosoftintr(void *); 138 static void pcctwosoftintrassert(void); 139 #endif 140 141 static void pcctwoisrlink(void *, int (*)(void *), void *, 142 int, int, struct evcnt *); 143 static void pcctwoisrunlink(void *, int); 144 static struct evcnt *pcctwoisrevcnt(void *, int); 145 146 147 /* ARGSUSED */ 148 int 149 pcctwomatch(parent, cf, args) 150 struct device *parent; 151 struct cfdata *cf; 152 void *args; 153 { 154 struct mainbus_attach_args *ma; 155 bus_space_handle_t bh; 156 u_int8_t cid; 157 158 ma = args; 159 160 /* There can be only one. */ 161 if (sys_pcctwo || strcmp(ma->ma_name, pcctwo_cd.cd_name)) 162 return (0); 163 164 /* 165 * Grab the Chip's ID 166 */ 167 bus_space_map(ma->ma_bust, PCCTWO_REG_OFF + ma->ma_offset, 168 PCC2REG_SIZE, 0, &bh); 169 cid = bus_space_read_1(ma->ma_bust, bh, PCC2REG_CHIP_ID); 170 bus_space_unmap(ma->ma_bust, bh, PCC2REG_SIZE); 171 172 #if defined(MVME167) || defined(MVME177) 173 if ((machineid == MVME_167 || machineid == MVME_177) && 174 cid == PCCTWO_CHIP_ID_PCC2) 175 return (1); 176 #endif 177 #if defined(MVME162) || defined(MVME172) 178 if ((machineid == MVME_162 || machineid == MVME_172) && 179 cid == PCCTWO_CHIP_ID_MCCHIP) 180 return (1); 181 #endif 182 183 return (0); 184 } 185 186 /* ARGSUSED */ 187 void 188 pcctwoattach(parent, self, args) 189 struct device *parent; 190 struct device *self; 191 void *args; 192 { 193 struct mainbus_attach_args *ma; 194 struct pcctwo_softc *sc; 195 struct pcctwo_device *pd = NULL; 196 u_int8_t cid; 197 198 ma = args; 199 sc = sys_pcctwo = (struct pcctwo_softc *) self; 200 201 /* Get a handle to the PCCChip2's registers */ 202 sc->sc_bust = ma->ma_bust; 203 sc->sc_dmat = ma->ma_dmat; 204 bus_space_map(sc->sc_bust, PCCTWO_REG_OFF + ma->ma_offset, 205 PCC2REG_SIZE, 0, &sc->sc_bush); 206 207 sc->sc_vecbase = PCCTWO_VECBASE; 208 sc->sc_isrlink = pcctwoisrlink; 209 sc->sc_isrevcnt = pcctwoisrevcnt; 210 sc->sc_isrunlink = pcctwoisrunlink; 211 212 cid = pcc2_reg_read(sc, PCC2REG_CHIP_ID); 213 214 #if defined(MVME167) || defined(MVME177) 215 if (cid == PCCTWO_CHIP_ID_PCC2) { 216 pd = pcctwo_devices; 217 sc->sc_vec2icsr = pcctwo_vec2icsr_1x7; 218 } 219 #endif 220 #if defined(MVME162) || defined(MVME172) 221 if (cid == PCCTWO_CHIP_ID_MCCHIP) { 222 pd = mcchip_devices; 223 sc->sc_vec2icsr = pcctwo_vec2icsr_1x2; 224 } 225 #endif 226 227 /* Finish initialisation in common code */ 228 pcctwo_init(sc, pd, ma->ma_offset); 229 230 #if defined(MVME162) || defined(MVME172) 231 if (cid == PCCTWO_CHIP_ID_MCCHIP) { 232 evcnt_attach_dynamic(&sc->sc_evcnt, EVCNT_TYPE_INTR, 233 isrlink_evcnt(7), "nmi", "abort sw"); 234 pcctwointr_establish(MCCHIPV_ABORT, pcctwoabortintr, 7, NULL, 235 &sc->sc_evcnt); 236 } 237 #endif 238 } 239 240 /* ARGSUSED */ 241 static void 242 pcctwoisrlink(cookie, fn, arg, ipl, vec, evcnt) 243 void *cookie; 244 int (*fn)(void *); 245 void *arg; 246 int ipl, vec; 247 struct evcnt *evcnt; 248 { 249 250 isrlink_vectored(fn, arg, ipl, vec, evcnt); 251 } 252 253 /* ARGSUSED */ 254 static void 255 pcctwoisrunlink(cookie, vec) 256 void *cookie; 257 int vec; 258 { 259 260 isrunlink_vectored(vec); 261 } 262 263 /* ARGSUSED */ 264 static struct evcnt * 265 pcctwoisrevcnt(cookie, ipl) 266 void *cookie; 267 int ipl; 268 { 269 270 return (isrlink_evcnt(ipl)); 271 } 272 273 #if defined(MVME162) || defined(MVME172) 274 static int 275 pcctwoabortintr(void *frame) 276 { 277 278 pcc2_reg_write(sys_pcctwo, MCCHIPREG_ABORT_ICSR, PCCTWO_ICR_ICLR | 279 pcc2_reg_read(sys_pcctwo, MCCHIPREG_ABORT_ICSR)); 280 281 return (nmihand(frame)); 282 } 283 284 void 285 pcctwosoftintrinit(void) 286 { 287 288 /* 289 * Since the VMEChip2 is normally used to generate 290 * software interrupts to the CPU, we have to deal 291 * with 162/172 boards which have the "No VMEChip2" 292 * build option. 293 * 294 * When such a board is found, the VMEChip2 probe code 295 * calls this function to implement software interrupts 296 * the hard way; using tick timer 4 ... 297 */ 298 pcctwointr_establish(MCCHIPV_TIMER4, pcctwosoftintr, 299 1, sys_pcctwo, &sys_pcctwo->sc_evcnt); 300 pcc2_reg_write(sys_pcctwo, MCCHIPREG_TIMER4_CTRL, 0); 301 pcc2_reg_write32(sys_pcctwo, MCCHIPREG_TIMER4_COMP, 1); 302 pcc2_reg_write32(sys_pcctwo, MCCHIPREG_TIMER4_CNTR, 0); 303 _softintr_chipset_assert = pcctwosoftintrassert; 304 } 305 306 static int 307 pcctwosoftintr(void *arg) 308 { 309 struct pcctwo_softc *sc = arg; 310 311 pcc2_reg_write32(sc, MCCHIPREG_TIMER4_CNTR, 0); 312 pcc2_reg_write(sc, MCCHIPREG_TIMER4_CTRL, 0); 313 pcc2_reg_write(sc, MCCHIPREG_TIMER4_ICSR, 314 PCCTWO_ICR_ICLR | PCCTWO_ICR_IEN | 1); 315 316 softintr_dispatch(); 317 318 return (1); 319 } 320 321 static void 322 pcctwosoftintrassert(void) 323 { 324 325 /* 326 * Schedule a timer interrupt to happen in ~1uS. 327 * This is more than adequate on any available m68k platform 328 * for simulating software interrupts. 329 */ 330 pcc2_reg_write(sys_pcctwo, MCCHIPREG_TIMER4_CTRL, PCCTWO_TT_CTRL_CEN); 331 } 332 #endif 333