1 /* $NetBSD: ka43.c,v 1.35 2010/12/14 23:44:49 matt Exp $ */ 2 /* 3 * Copyright (c) 1996 Ludd, University of Lule}, Sweden. 4 * All rights reserved. 5 * 6 * This code is derived from software contributed to Ludd by Bertram Barth. 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions 10 * are met: 11 * 1. Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer. 13 * 2. Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in the 15 * documentation and/or other materials provided with the distribution. 16 * 3. All advertising materials mentioning features or use of this software 17 * must display the following acknowledgement: 18 * This product includes software developed at Ludd, University of 19 * Lule}, Sweden and its contributors. 20 * 4. The name of the author may not be used to endorse or promote products 21 * derived from this software without specific prior written permission 22 * 23 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 24 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 25 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 26 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 27 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 28 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 29 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 30 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 31 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 32 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 33 */ 34 35 #include <sys/cdefs.h> 36 __KERNEL_RCSID(0, "$NetBSD: ka43.c,v 1.35 2010/12/14 23:44:49 matt Exp $"); 37 38 #include <sys/param.h> 39 #include <sys/systm.h> 40 #include <sys/cpu.h> 41 #include <sys/device.h> 42 #include <sys/kernel.h> 43 44 #include <machine/sid.h> 45 #include <machine/nexus.h> 46 #include <machine/vsbus.h> 47 #include <machine/ka43.h> 48 #include <machine/clock.h> 49 50 static void ka43_conf(void); 51 static void ka43_steal_pages(void); 52 53 static int ka43_mchk(void *); 54 static void ka43_memerr(void); 55 #if 0 56 static void ka43_clear_errors(void); 57 #endif 58 static int ka43_cache_init(void); /* "int mapen" as argument? */ 59 static int ka43_cache_reset(void); 60 static int ka43_cache_enable(void); 61 static int ka43_cache_disable(void); 62 static int ka43_cache_invalidate(void); 63 static void ka43_halt(void); 64 static void ka43_reboot(int); 65 static void ka43_clrf(void); 66 67 static const char * const ka43_devs[] = { "cpu", "vsbus", NULL }; 68 69 const struct cpu_dep ka43_calls = { 70 .cpu_steal_pages = ka43_steal_pages, 71 .cpu_mchk = ka43_mchk, 72 .cpu_memerr = ka43_memerr, 73 .cpu_conf = ka43_conf, 74 .cpu_gettime = chip_gettime, 75 .cpu_settime = chip_settime, 76 .cpu_vups = 7, /* 7.6 VUP */ 77 .cpu_scbsz = 2, /* SCB pages */ 78 .cpu_halt = ka43_halt, 79 .cpu_reboot = ka43_reboot, 80 .cpu_clrf = ka43_clrf, 81 .cpu_devs = ka43_devs, 82 .cpu_flags = CPU_RAISEIPL, 83 }; 84 85 /* 86 * ka43_steal_pages() is called with MMU disabled, after that call MMU gets 87 * enabled. Thus we initialize these four pointers with physical addresses, 88 * but before leving ka43_steal_pages() we reset them to virtual addresses. 89 */ 90 static volatile struct ka43_cpu *ka43_cpu = (void*)KA43_CPU_BASE; 91 static volatile u_int *ka43_creg = (void*)KA43_CH2_CREG; 92 static volatile u_int *ka43_ctag = (void*)KA43_CT2_BASE; 93 94 #define KA43_MC_RESTART 0x00008000 /* Restart possible*/ 95 #define KA43_PSL_FPDONE 0x00010000 /* First Part Done */ 96 97 struct ka43_mcframe { /* Format of RigelMAX machine check frame: */ 98 int mc43_bcnt; /* byte count, always 24 (0x18) */ 99 int mc43_code; /* machine check type code and restart bit */ 100 int mc43_addr; /* most recent (faulting?) virtual address */ 101 int mc43_viba; /* contents of VIBA register */ 102 int mc43_sisr; /* ICCS bit 6 and SISR bits 15:0 */ 103 int mc43_istate; /* internal state */ 104 int mc43_sc; /* shift count register */ 105 int mc43_pc; /* trapped PC */ 106 int mc43_psl; /* trapped PSL */ 107 }; 108 109 static const char * const ka43_mctype[] = { 110 "no error (0)", /* Code 0: No error */ 111 "FPA: protocol error", /* Code 1-5: FPA errors */ 112 "FPA: illegal opcode", 113 "FPA: operand parity error", 114 "FPA: unknown status", 115 "FPA: result parity error", 116 "unused (6)", /* Code 6-7: Unused */ 117 "unused (7)", 118 "MMU error (TLB miss)", /* Code 8-9: MMU errors */ 119 "MMU error (TLB hit)", 120 "HW interrupt at unused IPL", /* Code 10: Interrupt error */ 121 "MOVCx impossible state", /* Code 11-13: Microcode errors */ 122 "undefined trap code (i-box)", 123 "undefined control store address", 124 "unused (14)", /* Code 14-15: Unused */ 125 "unused (15)", 126 "PC tag or data parity error", /* Code 16: Cache error */ 127 "data bus parity error", /* Code 17: Read error */ 128 "data bus error (NXM)", /* Code 18: Write error */ 129 "undefined data bus state", /* Code 19: Bus error */ 130 }; 131 #define MC43_MAX 19 132 133 static int ka43_error_count = 0; 134 135 int 136 ka43_mchk(void *addr) 137 { 138 struct ka43_mcframe *mcf = (void*)addr; 139 140 mtpr(0x00, PR_MCESR); /* Acknowledge the machine check */ 141 printf("machine check %d (0x%x)\n", mcf->mc43_code, mcf->mc43_code); 142 printf("reason: %s\n", ka43_mctype[mcf->mc43_code & 0xff]); 143 if (++ka43_error_count > 10) { 144 printf("error_count exceeded: %d\n", ka43_error_count); 145 return (-1); 146 } 147 148 /* 149 * If either the Restart flag is set or the First-Part-Done flag 150 * is set, and the TRAP2 (double error) bit is not set, then the 151 * error is recoverable. 152 */ 153 if (mfpr(PR_PCSTS) & KA43_PCS_TRAP2) { 154 printf("TRAP2 (double error) in ka43_mchk.\n"); 155 panic("unrecoverable state in ka43_mchk."); 156 return (-1); 157 } 158 if ((mcf->mc43_code & KA43_MC_RESTART) || 159 (mcf->mc43_psl & KA43_PSL_FPDONE)) { 160 printf("ka43_mchk: recovering from machine-check.\n"); 161 ka43_cache_reset(); /* reset caches */ 162 return (0); /* go on; */ 163 } 164 165 /* 166 * Unknown error state, panic/halt the machine! 167 */ 168 printf("ka43_mchk: unknown error state!\n"); 169 return (-1); 170 } 171 172 void 173 ka43_memerr(void) 174 { 175 char sbuf[256]; 176 177 /* 178 * Don\'t know what to do here. So just print some messages 179 * and try to go on... 180 */ 181 182 printf("memory error!\n"); 183 184 snprintb(sbuf, sizeof(sbuf), KA43_PCSTS_BITS, mfpr(PR_PCSTS)); 185 printf("primary cache status: %s\n", sbuf); 186 187 snprintb(sbuf, sizeof(sbuf), KA43_SESR_BITS, *ka43_creg); 188 printf("secondary cache status: %s\n", sbuf); 189 } 190 191 int 192 ka43_cache_init(void) 193 { 194 return (ka43_cache_reset()); 195 } 196 197 #if 0 198 void 199 ka43_clear_errors(void) 200 { 201 int val = *ka43_creg; 202 val |= KA43_SESR_SERR | KA43_SESR_LERR | KA43_SESR_CERR; 203 *ka43_creg = val; 204 } 205 #endif 206 207 int 208 ka43_cache_reset(void) 209 { 210 char sbuf[256]; 211 212 /* 213 * resetting primary and secondary caches is done in three steps: 214 * 1. disable both caches 215 * 2. manually clear secondary cache 216 * 3. enable both caches 217 */ 218 ka43_cache_disable(); 219 ka43_cache_invalidate(); 220 ka43_cache_enable(); 221 222 snprintb(sbuf, sizeof(sbuf), KA43_PCSTS_BITS, mfpr(PR_PCSTS)); 223 printf("primary cache status: %s\n", sbuf); 224 225 snprintb(sbuf, sizeof(sbuf), KA43_SESR_BITS, *ka43_creg); 226 printf("secondary cache status: %s\n", sbuf); 227 228 return (0); 229 } 230 231 int 232 ka43_cache_disable(void) 233 { 234 int val; 235 236 /* 237 * first disable primary cache and clear error flags 238 */ 239 mtpr(KA43_PCS_REFRESH, PR_PCSTS); /* disable primary cache */ 240 val = mfpr(PR_PCSTS); 241 mtpr(val, PR_PCSTS); /* clear error flags */ 242 243 /* 244 * now disable secondary cache and clear error flags 245 */ 246 val = *ka43_creg & ~KA43_SESR_CENB; /* BICL !!! */ 247 *ka43_creg = val; /* disable secondary cache */ 248 val = KA43_SESR_SERR | KA43_SESR_LERR | KA43_SESR_CERR; 249 *ka43_creg = val; /* clear error flags */ 250 251 return (0); 252 } 253 254 int 255 ka43_cache_invalidate(void) 256 { 257 int i, val; 258 259 val = KA43_PCTAG_PARITY; /* clear valid flag, set parity bit */ 260 for (i = 0; i < 256; i++) { /* 256 Quadword entries */ 261 mtpr(i*8, PR_PCIDX); /* write index of tag */ 262 mtpr(val, PR_PCTAG); /* write value into tag */ 263 } 264 val = KA43_PCS_FLUSH | KA43_PCS_REFRESH; 265 mtpr(val, PR_PCSTS); /* flush primary cache */ 266 267 /* 268 * Rigel\'s secondary cache doesn\'t implement a valid-flag. 269 * Thus we initialize all entries with out-of-range/dummy 270 * addresses which will never be referenced (ie. never hit). 271 * After enabling cache we also access 128K of memory starting 272 * at 0x00 so that secondary cache will be filled with these 273 * valid addresses... 274 */ 275 val = 0xff; 276 /* if (memory > 28 MB) val = 0x55; */ 277 for (i = 0; i < KA43_CT2_SIZE; i+= 4) { /* Quadword entries ?? */ 278 ka43_ctag[i/4] = val; /* reset upper and lower */ 279 } 280 281 return (0); 282 } 283 284 285 int 286 ka43_cache_enable(void) 287 { 288 volatile char *membase = (void*)0x80000000; /* physical 0x00 */ 289 int i, val; 290 291 val = KA43_PCS_FLUSH | KA43_PCS_REFRESH; 292 mtpr(val, PR_PCSTS); /* flush primary cache */ 293 294 /* 295 * now we enable secondary cache and access first 128K of memory 296 * so that secondary cache gets really initialized and holds 297 * valid addresses/data... 298 */ 299 *ka43_creg = KA43_SESR_CENB; /* enable secondary cache */ 300 for (i=0; i<128*1024; i++) { 301 val += membase[i]; /* some dummy operation... */ 302 } 303 304 val = KA43_PCS_ENABLE | KA43_PCS_REFRESH; 305 mtpr(val, PR_PCSTS); /* enable primary cache */ 306 307 return (0); 308 } 309 310 void 311 ka43_conf(void) 312 { 313 curcpu()->ci_cpustr = "Rigel, 2KB L1 cache, 128KB L2 cache"; 314 315 ka43_cpu = (void *)vax_map_physmem(VS_REGS, 1); 316 ka43_creg = (void *)vax_map_physmem(KA43_CH2_CREG, 1); 317 ka43_ctag = (void *)vax_map_physmem(KA43_CT2_BASE, 318 (KA43_CT2_SIZE/VAX_NBPG)); 319 320 /* 321 * ka43_conf() gets called with MMU enabled, now it's save to 322 * init/reset the caches. 323 */ 324 ka43_cache_init(); 325 326 clk_adrshift = 1; /* Addressed at long's... */ 327 clk_tweak = 2; /* ...and shift two */ 328 clk_page = (short *)vax_map_physmem(VS_CLOCK, 1); 329 } 330 331 332 /* 333 * The interface for communication with the LANCE ethernet controller 334 * is setup in the xxx_steal_pages() routine. We decrease highest 335 * available address by 64K and use this area as communication buffer. 336 */ 337 338 void 339 ka43_steal_pages(void) 340 { 341 int val; 342 343 344 /* 345 * if LANCE\'s io-buffer is above 16 MB, then the appropriate flag 346 * in the parity control register has to be set (it works as an 347 * additional address bit). In any case, don\'t enable CPEN and 348 * DPEN in the PARCTL register, somewhow they are internally managed 349 * by the RIGEL chip itself!?! 350 */ 351 val = ka43_cpu->parctl & 0x03; /* read the old value */ 352 ka43_cpu->parctl = val; /* and write new value */ 353 } 354 355 void 356 ka43_clrf(void) 357 { 358 volatile struct ka43_clock *clk = (volatile void *)clk_page; 359 360 /* 361 * Clear restart and boot in progress flags in the CPMBX. 362 * The cpmbx is split into two 4-bit fields. 363 * One for the current restart/boot in progress flags, and 364 * one for the permanent halt flag. 365 * The restart/boot in progress flag is also used as the action request 366 * for the CPU at a halt. /BQT 367 */ 368 clk->req = 0; 369 } 370 371 void 372 ka43_halt(void) 373 { 374 volatile struct ka43_clock *clk = (volatile void *)clk_page; 375 clk->req = 3; /* 3 is halt. */ 376 __asm("halt"); 377 } 378 379 void 380 ka43_reboot(int arg) 381 { 382 volatile struct ka43_clock *clk = (volatile void *)clk_page; 383 clk->req = 2; /* 2 is reboot. */ 384 __asm("halt"); 385 } 386