Annotation of sys/arch/mvme88k/mvme88k/m8820x.c, Revision 1.1
1.1 ! nbrk 1: /* $OpenBSD: m8820x.c,v 1.47 2006/11/18 22:53:11 miod Exp $ */
! 2: /*
! 3: * Copyright (c) 2004, Miodrag Vallat.
! 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 THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
! 15: * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
! 16: * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
! 17: * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
! 18: * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
! 19: * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
! 20: * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
! 21: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
! 22: * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
! 23: * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
! 24: * POSSIBILITY OF SUCH DAMAGE.
! 25: */
! 26:
! 27: #include <sys/param.h>
! 28: #include <sys/systm.h>
! 29:
! 30: #include <uvm/uvm_extern.h>
! 31:
! 32: #include <machine/asm_macro.h>
! 33: #include <machine/cpu.h>
! 34:
! 35: #include <machine/cmmu.h>
! 36: #include <machine/m8820x.h>
! 37: #ifdef MVME187
! 38: #include <machine/mvme187.h>
! 39: #endif
! 40: #ifdef MVME188
! 41: #include <machine/mvme188.h>
! 42: #endif
! 43:
! 44: #ifdef MVME188
! 45: /*
! 46: * There are 6 possible MVME188 HYPERmodule configurations:
! 47: * - config 0: 4 CPUs, 8 CMMUs
! 48: * - config 1: 2 CPUs, 8 CMMUs
! 49: * - config 2: 1 CPUs, 8 CMMUs
! 50: * - config 5: 2 CPUs, 4 CMMUs
! 51: * - config 6: 1 CPU, 4 CMMUs
! 52: * - config A: 1 CPU, 2 CMMUs (similar in operation to MVME187)
! 53: * which can exist either with MC88200 or MC88204 CMMUs.
! 54: */
! 55: const struct board_config {
! 56: int ncpus;
! 57: int ncmmus;
! 58: u_int32_t *pfsr;
! 59: } bd_config[16] = {
! 60: { 4, 8, pfsr_save_188_straight }, /* 4P128 - 4P512 */
! 61: { 2, 8, pfsr_save_188_double }, /* 2P128 - 2P512 */
! 62: { 1, 8, pfsr_save_188_quad }, /* 1P128 - 1P512 */
! 63: { 0, 0, NULL },
! 64: { 0, 0, NULL },
! 65: { 2, 4, pfsr_save_188_straight }, /* 2P64 - 2P256 */
! 66: { 1, 4, pfsr_save_188_double }, /* 1P64 - 1P256 */
! 67: { 0, 0, NULL },
! 68: { 0, 0, NULL },
! 69: { 0, 0, NULL },
! 70: { 1, 2, pfsr_save_188_straight }, /* 1P32 - 1P128 */
! 71: { 0, 0, NULL },
! 72: { 0, 0, NULL },
! 73: { 0, 0, NULL },
! 74: { 0, 0, NULL },
! 75: { 0, 0, NULL }
! 76: };
! 77: #endif
! 78:
! 79: /*
! 80: * This routine sets up the CPU/CMMU configuration.
! 81: */
! 82: void
! 83: m8820x_setup_board_config()
! 84: {
! 85: extern u_int32_t pfsr_save[];
! 86: struct m8820x_cmmu *cmmu;
! 87: int num, cmmu_num;
! 88: int vme188_config;
! 89: u_int32_t *m8820x_pfsr;
! 90: #ifdef MVME188
! 91: u_int32_t whoami;
! 92: #endif
! 93:
! 94: switch (brdtyp) {
! 95: #ifdef MVME187
! 96: case BRD_187:
! 97: case BRD_8120:
! 98: /* There is no WHOAMI reg on MVME187 - fake it... */
! 99: vme188_config = 0x0a;
! 100: m8820x_cmmu[0].cmmu_regs = (void *)SBC_CMMU_I;
! 101: m8820x_cmmu[1].cmmu_regs = (void *)SBC_CMMU_D;
! 102: max_cpus = 1;
! 103: max_cmmus = 2;
! 104: cmmu_shift = 1;
! 105: m8820x_pfsr = pfsr_save_187;
! 106: break;
! 107: #endif /* MVME187 */
! 108: #ifdef MVME188
! 109: case BRD_188:
! 110: whoami = *(volatile u_int32_t *)MVME188_WHOAMI;
! 111: vme188_config = (whoami & 0xf0) >> 4;
! 112: m8820x_cmmu[0].cmmu_regs = (void *)VME_CMMU_I0;
! 113: m8820x_cmmu[1].cmmu_regs = (void *)VME_CMMU_D0;
! 114: m8820x_cmmu[2].cmmu_regs = (void *)VME_CMMU_I1;
! 115: m8820x_cmmu[3].cmmu_regs = (void *)VME_CMMU_D1;
! 116: m8820x_cmmu[4].cmmu_regs = (void *)VME_CMMU_I2;
! 117: m8820x_cmmu[5].cmmu_regs = (void *)VME_CMMU_D2;
! 118: m8820x_cmmu[6].cmmu_regs = (void *)VME_CMMU_I3;
! 119: m8820x_cmmu[7].cmmu_regs = (void *)VME_CMMU_D3;
! 120: max_cpus = bd_config[vme188_config].ncpus;
! 121: max_cmmus = bd_config[vme188_config].ncmmus;
! 122: m8820x_pfsr = bd_config[vme188_config].pfsr;
! 123: cmmu_shift = ff1(max_cmmus / max_cpus);
! 124: break;
! 125: #endif /* MVME188 */
! 126: }
! 127:
! 128: #ifdef MVME188
! 129: if (bd_config[vme188_config].ncpus != 0) {
! 130: /* 187 has a fixed configuration, no need to print it */
! 131: if (brdtyp == BRD_188) {
! 132: printf("MVME188 board configuration #%X "
! 133: "(%d CPUs %d CMMUs)\n",
! 134: vme188_config, max_cpus, max_cmmus);
! 135: }
! 136: } else {
! 137: panic("unrecognized MVME%x board configuration #%X",
! 138: brdtyp, vme188_config);
! 139: }
! 140: #endif
! 141:
! 142: /*
! 143: * Patch the exception handling code to invoke the correct pfsr
! 144: * analysis chunk.
! 145: */
! 146: pfsr_save[0] = 0xc4000000 |
! 147: (((vaddr_t)m8820x_pfsr + 4 - (vaddr_t)pfsr_save) >> 2);
! 148: pfsr_save[1] = m8820x_pfsr[0];
! 149:
! 150: #ifdef DEBUG
! 151: /*
! 152: * Check CMMU type
! 153: */
! 154: for (cmmu_num = 0; cmmu_num < max_cmmus; cmmu_num++) {
! 155: volatile unsigned *cr = m8820x_cmmu[cmmu_num].cmmu_regs;
! 156: if (badaddr((vaddr_t)cr, 4) == 0) {
! 157: int type;
! 158:
! 159: type = CMMU_TYPE(cr[CMMU_IDR]);
! 160: if (type != M88200_ID && type != M88204_ID) {
! 161: printf("WARNING: non M8820x circuit found "
! 162: "at CMMU address %p\n", cr);
! 163: continue; /* will probably die quickly */
! 164: }
! 165: }
! 166: }
! 167: #endif
! 168:
! 169: /*
! 170: * Now that we know which CMMUs are there, report every association
! 171: */
! 172: for (num = 0; num < max_cpus; num++) {
! 173: int type;
! 174:
! 175: type = CMMU_TYPE(m8820x_cmmu[num << cmmu_shift].
! 176: cmmu_regs[CMMU_IDR]);
! 177:
! 178: printf("CPU%d is associated to %d MC8820%c CMMUs\n",
! 179: num, 1 << cmmu_shift, type == M88204_ID ? '4' : '0');
! 180: }
! 181:
! 182:
! 183: #ifdef MVME188
! 184: /*
! 185: * Systems with more than 2 CMMUs per CPU use programmable split
! 186: * schemes, through PCNFA (for code CMMUs) and PCNFB (for data CMMUs)
! 187: * configuration registers.
! 188: *
! 189: * The following schemes are available:
! 190: * - split on A12 address bit (A14 for 88204)
! 191: * - split on supervisor/user access
! 192: * - split on SRAM/non-SRAM addresses, with either supervisor-only or
! 193: * all access to SRAM.
! 194: *
! 195: * Configuration 6, with 4 CMMUs par CPU, also allows a split on A14
! 196: * address bit (A16 for 88204).
! 197: *
! 198: * Setup the default A12/A14 scheme here. We should theoretically only
! 199: * set the PCNFA and PCNFB on configurations 1, 2 and 6, since the
! 200: * other ones do not have P bus decoders.
! 201: * However, is it safe to write them anyways - the values will be
! 202: * discarded. Just don't do this on a 187...
! 203: */
! 204: if (brdtyp == BRD_188) {
! 205: *(volatile unsigned long *)MVME188_PCNFA = 0;
! 206: *(volatile unsigned long *)MVME188_PCNFB = 0;
! 207: }
! 208:
! 209: /*
! 210: * Now set up addressing limits
! 211: */
! 212: for (cmmu_num = 0, cmmu = m8820x_cmmu; cmmu_num < max_cmmus;
! 213: cmmu_num++, cmmu++) {
! 214: num = cmmu_num >> 1; /* CPU view of the CMMU */
! 215:
! 216: switch (cmmu_shift) {
! 217: case 3:
! 218: /*
! 219: * A14 split (configuration 2 only).
! 220: * CMMU numbers 0 and 1 match on A14 set,
! 221: * 2 and 3 on A14 clear
! 222: */
! 223: cmmu->cmmu_addr |= (num < 2 ? CMMU_A14_MASK : 0);
! 224: cmmu->cmmu_addr_mask |= CMMU_A14_MASK;
! 225: /* FALLTHROUGH */
! 226:
! 227: case 2:
! 228: /*
! 229: * A12 split.
! 230: * CMMU numbers 0 and 2 match on A12 set,
! 231: * 1 and 3 on A12 clear.
! 232: */
! 233: cmmu->cmmu_addr |= (num & 1 ? 0 : CMMU_A12_MASK);
! 234: cmmu->cmmu_addr_mask |= CMMU_A12_MASK;
! 235: break;
! 236:
! 237: case 1:
! 238: /*
! 239: * We don't need to set up anything for the hardwired
! 240: * configurations.
! 241: */
! 242: cmmu->cmmu_addr = 0;
! 243: cmmu->cmmu_addr_mask = 0;
! 244: break;
! 245: }
! 246:
! 247: /*
! 248: * If these CMMUs are 88204, these splitting address lines
! 249: * need to be shifted two bits.
! 250: */
! 251: if (CMMU_TYPE(cmmu->cmmu_regs[CMMU_IDR]) == M88204_ID) {
! 252: cmmu->cmmu_addr <<= 2;
! 253: cmmu->cmmu_addr_mask <<= 2;
! 254: }
! 255: }
! 256: #endif
! 257: }
! 258:
! 259: /*
! 260: * Find out the CPU number from accessing CMMU.
! 261: * On MVME187, there is only one CPU, so this is trivial.
! 262: * On MVME188, we access the WHOAMI register, which is in data space;
! 263: * its value will let us know which data CMMU has been used to perform
! 264: * the read, and we can reliably compute the CPU number from it.
! 265: */
! 266: cpuid_t
! 267: m8820x_cpu_number()
! 268: {
! 269: #ifdef MVME188
! 270: u_int32_t whoami;
! 271: cpuid_t cpu;
! 272: #endif
! 273:
! 274: #ifdef MVME187
! 275: if (brdtyp != BRD_188)
! 276: return 0;
! 277: #endif
! 278:
! 279: #ifdef MVME188
! 280: whoami = *(volatile u_int32_t *)MVME188_WHOAMI;
! 281: switch ((whoami & 0xf0) >> 4) {
! 282: /* 2 CMMU per CPU multiprocessor modules */
! 283: case 0:
! 284: case 5:
! 285: for (cpu = 0; cpu < 4; cpu++)
! 286: if (whoami & (1 << cpu))
! 287: return cpu;
! 288: break;
! 289: /* 4 CMMU per CPU dual processor modules */
! 290: case 1:
! 291: for (cpu = 0; cpu < 4; cpu++)
! 292: if (whoami & (1 << cpu))
! 293: return cpu >> 1;
! 294: break;
! 295: /* single processor modules */
! 296: case 2:
! 297: case 6:
! 298: case 0x0a:
! 299: return 0;
! 300: }
! 301: panic("can't figure out cpu number from whoami register %x", whoami);
! 302: #endif
! 303: }
CVSweb