[BACK]Return to m8820x.c CVS log [TXT][DIR] Up to [local] / sys / arch / mvme88k / mvme88k

Annotation of sys/arch/mvme88k/mvme88k/m8820x.c, Revision 1.1.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