1 /* $NetBSD: vme_two.c,v 1.1 2002/02/12 20:38:50 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 * VME support specific to the VMEchip2 found on all high-end MVME boards 41 */ 42 43 #include "vmetwo.h" 44 45 #include <sys/param.h> 46 #include <sys/kernel.h> 47 #include <sys/systm.h> 48 #include <sys/device.h> 49 50 #include <machine/cpu.h> 51 #include <machine/bus.h> 52 53 #include <dev/vme/vmereg.h> 54 #include <dev/vme/vmevar.h> 55 56 #include <dev/mvme/mvmebus.h> 57 #include <dev/mvme/vme_tworeg.h> 58 #include <dev/mvme/vme_twovar.h> 59 60 void vmetwo_master_range(struct vmetwo_softc *, int, struct mvmebus_range *); 61 void vmetwo_slave_range(struct vmetwo_softc *, int, vme_am_t, 62 struct mvmebus_range *); 63 64 /* ARGSUSED */ 65 void 66 vmetwo_init(sc) 67 struct vmetwo_softc *sc; 68 { 69 u_int32_t reg; 70 int i; 71 72 /* Initialise stuff for the common mvmebus front-end */ 73 sc->sc_mvmebus.sc_chip = sc; 74 sc->sc_mvmebus.sc_nmasters = VME2_NMASTERS; 75 sc->sc_mvmebus.sc_masters = &sc->sc_master[0]; 76 sc->sc_mvmebus.sc_nslaves = VME2_NSLAVES; 77 sc->sc_mvmebus.sc_slaves = &sc->sc_slave[0]; 78 sc->sc_mvmebus.sc_intr_establish = vmetwo_intr_establish; 79 sc->sc_mvmebus.sc_intr_disestablish = vmetwo_intr_disestablish; 80 81 /* Initialise interrupts */ 82 vmetwo_intr_init(sc); 83 84 reg = vme2_lcsr_read(sc, VME2LCSR_BOARD_CONTROL); 85 printf(": Type 2 VMEchip, scon jumper %s\n", 86 (reg & VME2_BOARD_CONTROL_SCON) ? "enabled" : "disabled"); 87 88 /* 89 * Figure out what bits of the VMEbus we can access. 90 * First record the `fixed' maps (if they're enabled) 91 */ 92 reg = vme2_lcsr_read(sc, VME2LCSR_IO_CONTROL); 93 if (reg & VME2_IO_CONTROL_I1EN) { 94 /* This range is fixed to A16, DATA */ 95 sc->sc_master[0].vr_am = VME_AM_A16 | MVMEBUS_AM_CAP_DATA; 96 97 /* However, SUPER/USER is selectable... */ 98 if (reg & VME2_IO_CONTROL_I1SU) 99 sc->sc_master[0].vr_am |= MVMEBUS_AM_CAP_SUPER; 100 else 101 sc->sc_master[0].vr_am |= MVMEBUS_AM_CAP_USER; 102 103 /* As is the datasize */ 104 sc->sc_master[0].vr_datasize = VME_D32 | VME_D16 | VME_D8; 105 if (reg & VME2_IO_CONTROL_I1D16) 106 sc->sc_master[0].vr_datasize &= ~VME_D32; 107 108 sc->sc_master[0].vr_locstart = VME2_IO0_LOCAL_START; 109 sc->sc_master[0].vr_mask = VME2_IO0_MASK; 110 sc->sc_master[0].vr_vmestart = VME2_IO0_VME_START; 111 sc->sc_master[0].vr_vmeend = VME2_IO0_VME_END; 112 } else 113 sc->sc_master[0].vr_am = MVMEBUS_AM_DISABLED; 114 115 if (reg & VME2_IO_CONTROL_I2EN) { 116 /* These two ranges are fixed to A24D16 and A32D16 */ 117 sc->sc_master[1].vr_am = VME_AM_A24; 118 sc->sc_master[1].vr_datasize = VME_D16 | VME_D8; 119 sc->sc_master[2].vr_am = VME_AM_A32; 120 sc->sc_master[2].vr_datasize = VME_D16 | VME_D8; 121 122 /* However, SUPER/USER is selectable */ 123 if (reg & VME2_IO_CONTROL_I2SU) { 124 sc->sc_master[1].vr_am |= MVMEBUS_AM_CAP_SUPER; 125 sc->sc_master[2].vr_am |= MVMEBUS_AM_CAP_SUPER; 126 } else { 127 sc->sc_master[1].vr_am |= MVMEBUS_AM_CAP_USER; 128 sc->sc_master[2].vr_am |= MVMEBUS_AM_CAP_USER; 129 } 130 131 /* As is PROGRAM/DATA */ 132 if (reg & VME2_IO_CONTROL_I2PD) { 133 sc->sc_master[1].vr_am |= MVMEBUS_AM_CAP_PROG; 134 sc->sc_master[2].vr_am |= MVMEBUS_AM_CAP_PROG; 135 } else { 136 sc->sc_master[1].vr_am |= MVMEBUS_AM_CAP_DATA; 137 sc->sc_master[2].vr_am |= MVMEBUS_AM_CAP_DATA; 138 } 139 140 sc->sc_master[1].vr_locstart = VME2_IO1_LOCAL_START; 141 sc->sc_master[1].vr_mask = VME2_IO1_MASK; 142 sc->sc_master[1].vr_vmestart = VME2_IO1_VME_START; 143 sc->sc_master[1].vr_vmeend = VME2_IO1_VME_END; 144 145 sc->sc_master[2].vr_locstart = VME2_IO2_LOCAL_START; 146 sc->sc_master[2].vr_mask = VME2_IO2_MASK; 147 sc->sc_master[2].vr_vmestart = VME2_IO2_VME_START; 148 sc->sc_master[2].vr_vmeend = VME2_IO2_VME_END; 149 } else { 150 sc->sc_master[1].vr_am = MVMEBUS_AM_DISABLED; 151 sc->sc_master[2].vr_am = MVMEBUS_AM_DISABLED; 152 } 153 154 /* 155 * Now read the progammable maps 156 */ 157 for (i = 0; i < VME2_MASTER_WINDOWS; i++) 158 vmetwo_master_range(sc, i, 159 &(sc->sc_master[i + VME2_MASTER_PROG_START])); 160 161 /* XXX: No A16 slave yet :XXX */ 162 sc->sc_slave[VME2_SLAVE_A16].vr_am = MVMEBUS_AM_DISABLED; 163 164 for (i = 0; i < VME2_SLAVE_WINDOWS; i++) { 165 vmetwo_slave_range(sc, i, VME_AM_A32, 166 &sc->sc_slave[i + VME2_SLAVE_PROG_START]); 167 vmetwo_slave_range(sc, i, VME_AM_A24, 168 &sc->sc_slave[i + VME2_SLAVE_PROG_START + 2]); 169 } 170 171 mvmebus_attach(&sc->sc_mvmebus); 172 } 173 174 void 175 vmetwo_master_range(sc, range, vr) 176 struct vmetwo_softc *sc; 177 int range; 178 struct mvmebus_range *vr; 179 { 180 u_int32_t start, end, attr; 181 u_int32_t reg; 182 183 /* 184 * First, check if the range is actually enabled... 185 */ 186 reg = vme2_lcsr_read(sc, VME2LCSR_MASTER_ENABLE); 187 if ((reg & VME2_MASTER_ENABLE(range)) == 0) { 188 vr->vr_am = MVMEBUS_AM_DISABLED; 189 return; 190 } 191 192 /* 193 * Fetch and record the range's attributes 194 */ 195 attr = vme2_lcsr_read(sc, VME2LCSR_MASTER_ATTR); 196 attr >>= VME2_MASTER_ATTR_AM_SHIFT(range); 197 198 /* 199 * Fix up the datasizes available through this range 200 */ 201 vr->vr_datasize = VME_D32 | VME_D16 | VME_D8; 202 if (attr & VME2_MASTER_ATTR_D16) 203 vr->vr_datasize &= ~VME_D32; 204 attr &= VME2_MASTER_ATTR_AM_MASK; 205 206 vr->vr_am = (attr & VME_AM_ADRSIZEMASK) | MVMEBUS_AM2CAP(attr); 207 switch (vr->vr_am & VME_AM_ADRSIZEMASK) { 208 case VME_AM_A32: 209 default: 210 vr->vr_mask = 0xffffffffu; 211 break; 212 213 case VME_AM_A24: 214 vr->vr_mask = 0x00ffffffu; 215 break; 216 217 case VME_AM_A16: 218 vr->vr_mask = 0x0000ffffu; 219 break; 220 } 221 222 /* 223 * XXX 224 * It would be nice if users of the MI VMEbus code could pass down 225 * whether they can tolerate Write-Posting to their device(s). 226 * XXX 227 */ 228 229 /* 230 * Fetch the local-bus start and end addresses for the range 231 */ 232 reg = vme2_lcsr_read(sc, VME2LCSR_MASTER_ADDRESS(range)); 233 start = (reg & VME2_MAST_ADDRESS_START_MASK); 234 start <<= VME2_MAST_ADDRESS_START_SHIFT; 235 end = (reg & VME2_MAST_ADDRESS_END_MASK); 236 end <<= VME2_MAST_ADDRESS_END_SHIFT; 237 238 /* 239 * Local->VMEbus map '4' has optional translation bits, so 240 * the VMEbus start and end addresses may need to be adjusted. 241 */ 242 if (range == 3 && (reg = vme2_lcsr_read(sc, VME2LCSR_MAST4_TRANS))!=0) { 243 uint32_t addr, sel, len = end - start; 244 245 vr->vr_locstart = start; 246 247 reg = vme2_lcsr_read(sc, VME2LCSR_MAST4_TRANS); 248 reg &= VME2_MAST4_TRANS_SELECT_MASK; 249 sel = reg << VME2_MAST4_TRANS_SELECT_SHIFT; 250 251 reg = vme2_lcsr_read(sc, VME2LCSR_MAST4_TRANS); 252 reg &= VME2_MAST4_TRANS_ADDRESS_MASK; 253 addr = reg << VME2_MAST4_TRANS_ADDRESS_SHIFT; 254 255 start = (addr & sel) | (start & (~sel)); 256 end = start + len; 257 vr->vr_mask &= len - 1; 258 } else 259 vr->vr_locstart = 0; 260 261 /* XXX Deal with overlap of onboard RAM address space */ 262 /* XXX Then again, 167-Bug warns about this at setup time ... */ 263 264 /* 265 * Fixup the addresses this range corresponds to 266 */ 267 vr->vr_vmestart = start; 268 vr->vr_vmeend = end - 1; 269 } 270 271 void 272 vmetwo_slave_range(sc, range, am, vr) 273 struct vmetwo_softc *sc; 274 int range; 275 vme_am_t am; 276 struct mvmebus_range *vr; 277 { 278 u_int32_t reg; 279 280 /* 281 * First, check if the range is actually enabled. 282 * Note that bit 1 of `range' is used to indicte if we're 283 * looking for an A24 range (set) or an A32 range (clear). 284 */ 285 reg = vme2_lcsr_read(sc, VME2LCSR_SLAVE_CTRL); 286 287 if (am == VME_AM_A32 && (reg & VME2_SLAVE_AMSEL_A32(range))) { 288 vr->vr_am = VME_AM_A32; 289 vr->vr_mask = 0xffffffffu; 290 } else 291 if (am == VME_AM_A24 && (reg & VME2_SLAVE_AMSEL_A24(range))) { 292 vr->vr_am = VME_AM_A24; 293 vr->vr_mask = 0x00ffffffu; 294 } else { 295 /* The range is not enabled */ 296 vr->vr_am = MVMEBUS_AM_DISABLED; 297 return; 298 } 299 300 if ((reg & VME2_SLAVE_AMSEL_DAT(range)) != 0) 301 vr->vr_am |= MVMEBUS_AM_CAP_DATA; 302 303 if ((reg & VME2_SLAVE_AMSEL_PGM(range)) != 0) 304 vr->vr_am |= MVMEBUS_AM_CAP_PROG; 305 306 if ((reg & VME2_SLAVE_AMSEL_USR(range)) != 0) 307 vr->vr_am |= MVMEBUS_AM_CAP_USER; 308 309 if ((reg & VME2_SLAVE_AMSEL_SUP(range)) != 0) 310 vr->vr_am |= MVMEBUS_AM_CAP_SUPER; 311 312 if ((reg & VME2_SLAVE_AMSEL_BLK(range)) != 0) 313 vr->vr_am |= MVMEBUS_AM_CAP_BLK; 314 315 if ((reg & VME2_SLAVE_AMSEL_BLKD64(range)) != 0) 316 vr->vr_am |= MVMEBUS_AM_CAP_BLKD64; 317 318 vr->vr_datasize = VME_D32 | VME_D16 | VME_D8; 319 320 /* 321 * Record the VMEbus start and end addresses of the slave image 322 */ 323 reg = vme2_lcsr_read(sc, VME2LCSR_SLAVE_ADDRESS(range)); 324 vr->vr_vmestart = reg & VME2_SLAVE_ADDRESS_START_MASK; 325 vr->vr_vmestart <<= VME2_SLAVE_ADDRESS_START_SHIFT; 326 vr->vr_vmestart &= vr->vr_mask; 327 vr->vr_vmeend = reg & VME2_SLAVE_ADDRESS_END_MASK; 328 vr->vr_vmeend <<= VME2_SLAVE_ADDRESS_END_SHIFT; 329 vr->vr_vmeend &= vr->vr_mask; 330 vr->vr_vmeend |= 0xffffu; 331 332 /* 333 * Now figure out the local-bus address 334 */ 335 reg = vme2_lcsr_read(sc, VME2LCSR_SLAVE_CTRL); 336 if ((reg & VME2_SLAVE_CTRL_ADDER(range)) != 0) { 337 reg = vme2_lcsr_read(sc, VME2LCSR_SLAVE_TRANS(range)); 338 reg &= VME2_SLAVE_TRANS_ADDRESS_MASK; 339 reg <<= VME2_SLAVE_TRANS_ADDRESS_SHIFT; 340 vr->vr_locstart = vr->vr_vmestart + reg; 341 } else { 342 u_int32_t sel, addr; 343 344 reg = vme2_lcsr_read(sc, VME2LCSR_SLAVE_TRANS(range)); 345 sel = reg & VME2_SLAVE_TRANS_SELECT_MASK; 346 sel <<= VME2_SLAVE_TRANS_SELECT_SHIFT; 347 addr = reg & VME2_SLAVE_TRANS_ADDRESS_MASK; 348 addr <<= VME2_SLAVE_TRANS_ADDRESS_SHIFT; 349 350 vr->vr_locstart = addr & sel; 351 vr->vr_locstart |= vr->vr_vmestart & (~sel); 352 } 353 } 354