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