1320572Sdim/* $NetBSD: machdep.c,v 1.16 2024/03/05 14:15:31 thorpej Exp $ */ 2317017Sdim 3353358Sdim/* 4353358Sdim * Copyright (c) 2002 The NetBSD Foundation, Inc. 5353358Sdim * All rights reserved. 6317017Sdim * 7317017Sdim * This code is derived from software contributed to The NetBSD Foundation 8317017Sdim * by Lennart Augustsson (lennart@augustsson.net) at Sandburst Corp. 9317017Sdim * 10320572Sdim * Redistribution and use in source and binary forms, with or without 11321238Sdim * modification, are permitted provided that the following conditions 12320572Sdim * are met: 13320572Sdim * 1. Redistributions of source code must retain the above copyright 14320572Sdim * notice, this list of conditions and the following disclaimer. 15317017Sdim * 2. Redistributions in binary form must reproduce the above copyright 16317017Sdim * notice, this list of conditions and the following disclaimer in the 17317017Sdim * documentation and/or other materials provided with the distribution. 18317017Sdim * 19317017Sdim * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 20317017Sdim * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 21317017Sdim * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 22317017Sdim * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 23317017Sdim * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24317017Sdim * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 25317017Sdim * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26320572Sdim * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27317017Sdim * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 28317017Sdim * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29317017Sdim * POSSIBILITY OF SUCH DAMAGE. 30317017Sdim */ 31317017Sdim 32317017Sdim/* 33317017Sdim * Copyright (C) 1995, 1996 Wolfgang Solfrank. 34317017Sdim * Copyright (C) 1995, 1996 TooLs GmbH. 35317017Sdim * All rights reserved. 36317017Sdim * 37317017Sdim * Redistribution and use in source and binary forms, with or without 38317017Sdim * modification, are permitted provided that the following conditions 39317017Sdim * are met: 40317017Sdim * 1. Redistributions of source code must retain the above copyright 41317017Sdim * notice, this list of conditions and the following disclaimer. 42321238Sdim * 2. Redistributions in binary form must reproduce the above copyright 43321238Sdim * notice, this list of conditions and the following disclaimer in the 44321238Sdim * documentation and/or other materials provided with the distribution. 45321238Sdim * 3. All advertising materials mentioning features or use of this software 46321238Sdim * must display the following acknowledgement: 47321238Sdim * This product includes software developed by TooLs GmbH. 48 * 4. The name of TooLs GmbH may not be used to endorse or promote products 49 * derived from this software without specific prior written permission. 50 * 51 * THIS SOFTWARE IS PROVIDED BY TOOLS GMBH ``AS IS'' AND ANY EXPRESS OR 52 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 53 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 54 * IN NO EVENT SHALL TOOLS GMBH BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 55 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 56 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 57 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 58 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 59 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 60 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 61 */ 62 63#include <sys/cdefs.h> 64__KERNEL_RCSID(0, "$NetBSD: machdep.c,v 1.16 2024/03/05 14:15:31 thorpej Exp $"); 65 66#include "opt_compat_netbsd.h" 67#include "opt_ddb.h" 68#include "opt_ddbparam.h" 69#include "opt_inet.h" 70#include "opt_ccitt.h" 71#include "opt_ns.h" 72 73#include <sys/param.h> 74#include <sys/buf.h> 75#include <sys/bus.h> 76#include <sys/conf.h> 77#include <sys/device.h> 78#include <sys/exec.h> 79#include <sys/extent.h> 80#include <sys/intr.h> 81#include <sys/kernel.h> 82#include <sys/kgdb.h> 83#include <sys/ksyms.h> 84#include <sys/mbuf.h> 85#include <sys/mount.h> 86#include <sys/msgbuf.h> 87#include <sys/proc.h> 88#include <sys/reboot.h> 89#include <sys/syscallargs.h> 90#include <sys/sysctl.h> 91#include <sys/syslog.h> 92#include <sys/systm.h> 93 94#include <uvm/uvm_extern.h> 95 96#include <machine/powerpc.h> 97#include <machine/pmppc.h> 98 99#include <powerpc/db_machdep.h> 100#include <powerpc/pio.h> 101#include <powerpc/pmap.h> 102#include <powerpc/trap.h> 103 104#include <powerpc/oea/bat.h> 105#include <powerpc/pic/picvar.h> 106 107#include <ddb/db_extern.h> 108 109#include <dev/cons.h> 110 111#include <dev/ic/cpc700reg.h> 112#include <dev/ic/cpc700uic.h> 113 114#include "com.h" 115#if (NCOM > 0) 116#include <sys/termios.h> 117#include <dev/ic/comreg.h> 118#include <dev/ic/comvar.h> 119#endif 120 121#include "ksyms.h" 122 123struct powerpc_bus_space pmppc_mem_tag = { 124 _BUS_SPACE_LITTLE_ENDIAN|_BUS_SPACE_MEM_TYPE, 125 0, 0, 0xffffffff, 126 NULL, 127}; 128struct powerpc_bus_space pmppc_pci_io_tag = { 129 _BUS_SPACE_LITTLE_ENDIAN|_BUS_SPACE_MEM_TYPE, 130 0, CPC_PCI_IO_BASE, 0xffffffff, 131 NULL, 132}; 133 134static char ex_storage[1][EXTENT_FIXED_STORAGE_SIZE(8)] 135 __attribute__((aligned(8))); 136 137 138#ifdef KGDB 139char kgdb_devname[] = KGDB_DEVNAME; 140int comkgdbaddr = KGDB_DEVADDR; 141int comkgdbrate = KGDB_DEVRATE; 142 143#ifndef KGDB_DEVMODE 144#define KGDB_DEVMODE ((TTYDEF_CFLAG & ~(CSIZE | CSTOPB | PARENB)) | CS8) /* 8N1 */ 145#endif 146int comkgdbmode = KGDB_DEVMODE; 147 148void kgdb_port_init(void); 149#endif /* KGDB */ 150 151/* 152 * Global variables used here and there 153 */ 154struct mem_region physmemr[2], availmemr[2]; 155 156struct a_config a_config; 157 158void initppc(u_int, u_int, u_int, void *); /* Called from locore */ 159void pmppc_setup(void); 160void setleds(int leds); 161 162void 163initppc(u_int startkernel, u_int endkernel, u_int args, void *btinfo) 164{ 165 extern void consinit(void); 166 extern u_long ticks_per_sec; 167 extern unsigned char edata[], end[]; 168 169 memset(&edata, 0, end - edata); /* clear BSS */ 170 171 pmppc_setup(); 172 173 physmemr[0].start = 0; 174 physmemr[0].size = a_config.a_mem_size; 175 physmemr[1].size = 0; 176 availmemr[0].start = (endkernel + PGOFSET) & ~PGOFSET; 177 availmemr[0].size = a_config.a_mem_size - availmemr[0].start; 178 availmemr[1].size = 0; 179 180#ifdef BOOTHOWTO 181 /* 182 * boothowto 183 */ 184 boothowto = BOOTHOWTO; 185#endif 186 187 if (bus_space_init(&pmppc_mem_tag, "iomem", 188 ex_storage[0], sizeof(ex_storage[0]))) 189 panic("bus_space_init failed"); 190 191 /* 192 * Initialize the BAT registers 193 */ 194 oea_batinit( 195 PMPPC_FLASH_BASE, BAT_BL_256M, /* flash (etc) memory 256M area */ 196 CPC_PCI_MEM_BASE, BAT_BL_256M, /* PCI memory 256M area */ 197 CPC_PCI_IO_BASE, BAT_BL_128M, /* PCI I/O 128M area */ 198 0); 199 200 /* 201 * Set up trap vectors 202 */ 203 oea_init(NULL); 204 205 /* 206 * Get CPU clock 207 */ 208 ticks_per_sec = a_config.a_bus_freq; 209 ticks_per_sec /= 4; /* 4 cycles per DEC tick */ 210 cpu_timebase = ticks_per_sec; 211 212 /* 213 * Set up console. 214 */ 215 consinit(); /* XXX should not be here */ 216 217 printf("console set up\n"); 218 219 uvm_md_init(); 220 221 /* 222 * Initialize pmap module. 223 */ 224 pmap_bootstrap(startkernel, endkernel); 225 226#ifdef KGDB 227 kgdb_port_init(); 228 if (boothowto & RB_KDB) { 229 kgdb_debug_init = 1; 230 kgdb_connect(1); 231 } 232#endif 233} 234 235void 236mem_regions(struct mem_region **mem, struct mem_region **avail) 237{ 238 *mem = physmemr; 239 *avail = availmemr; 240} 241 242/* 243 * Machine dependent startup code. 244 */ 245void 246cpu_startup(void) 247{ 248 249 oea_startup(NULL); 250 251 /* 252 * Now that we have VM, malloc()s are OK in bus_space. 253 */ 254 bus_space_mallocok(); 255 256 /* Set up the PCI bus tag. */ 257 if (bus_space_init(&pmppc_pci_io_tag, "pcimem", NULL, 0)) 258 panic("bus_space_init pci failed"); 259 260 /* Set up interrupt controller */ 261 cpc700_init_intr(&pmppc_mem_tag, CPC_UIC_BASE, 262 CPC_INTR_MASK(PMPPC_I_ETH_INT), 0); 263 264 pic_init(); 265 (void)setup_cpc700(); 266 oea_install_extint(pic_ext_intr); 267 268#if 0 269/* XXX doesn't seem to be needed anymore */ 270 /* 271 * Now allow hardware interrupts. 272 */ 273 __asm volatile ("mfmsr %0; ori %0,%0,%1; mtmsr %0" 274 : "=r"(msr) : "K"(PSL_EE)); 275#endif 276} 277 278/* 279 * consinit 280 * Initialize system console. 281 */ 282void 283consinit(void) 284{ 285 static int initted; 286#if (NCOM > 0) 287 bus_space_tag_t tag; 288#endif 289 290 if (initted) 291 return; 292 initted = 1; 293 294#if (NCOM > 0) 295 tag = &pmppc_mem_tag; 296 297 if(comcnattach(tag, CPC_COM0, 9600, CPC_COM_SPEED(a_config.a_bus_freq), 298 COM_TYPE_NORMAL, 299 ((TTYDEF_CFLAG & ~(CSIZE | CSTOPB | PARENB)) | CS8))) 300 panic("can't init serial console"); 301 else 302 return; 303#endif 304 305 panic("console device missing -- serial console not in kernel"); 306 /* Of course, this is moot if there is no console... */ 307} 308 309#ifdef KGDB 310void 311kgdb_port_init(void) 312{ 313#if (NCOM > 0) 314 if(!strcmp(kgdb_devname, "com")) { 315 bus_space_tag_t tag = &pmppc_mem_tag; 316 com_kgdb_attach(tag, comkgdbaddr, comkgdbrate, 317 CPC_COM_SPEED(a_config.a_bus_freq), 318 COM_TYPE_NORMAL, comkgdbmode); 319 } 320#endif 321} 322#endif 323 324/* 325 * Halt or reboot the machine after syncing/dumping according to howto. 326 */ 327void 328cpu_reboot(int howto, char *what) 329{ 330 static int syncing; 331 static char str[256]; 332 char *ap = str, *ap1 = ap; 333 extern void disable_intr(void); 334 335 boothowto = howto; 336 if (!cold && !(howto & RB_NOSYNC) && !syncing) { 337 syncing = 1; 338 vfs_shutdown(); /* sync */ 339 } 340 splhigh(); 341 if (howto & RB_HALT) { 342 doshutdownhooks(); 343 pmf_system_shutdown(boothowto); 344 printf("halted\n\n"); 345 while(1); 346 } 347 if (!cold && (howto & RB_DUMP)) 348 oea_dumpsys(); 349 doshutdownhooks(); 350 351 pmf_system_shutdown(boothowto); 352 printf("rebooting\n\n"); 353 if (what && *what) { 354 if (strlen(what) > sizeof str - 5) 355 printf("boot string too large, ignored\n"); 356 else { 357 strcpy(str, what); 358 ap1 = ap = str + strlen(str); 359 *ap++ = ' '; 360 } 361 } 362 *ap++ = '-'; 363 if (howto & RB_SINGLE) 364 *ap++ = 's'; 365 if (howto & RB_KDB) 366 *ap++ = 'd'; 367 *ap++ = 0; 368 if (ap[-2] == '-') 369 *ap1 = 0; 370 371 disable_intr(); 372 373 /* Write the two byte reset sequence to the reset register. */ 374 out8(PMPPC_RESET, PMPPC_RESET_SEQ_STEP1); 375 out8(PMPPC_RESET, PMPPC_RESET_SEQ_STEP2); 376 377 while (1); 378} 379 380void 381setleds(int leds) 382{ 383 out8(PMPPC_LEDS, leds); 384} 385 386void 387pmppc_setup(void) 388{ 389 uint config0, config1; 390 391 config0 = in8(PMPPC_CONFIG0); 392 config1 = in8(PMPPC_CONFIG1); 393 394 /* from page 2-8 in the Artesyn User's manual */ 395 a_config.a_boot_device = config1 & 0x80 ? A_BOOT_FLASH : A_BOOT_ROM; 396 a_config.a_has_ecc = (config1 & 0x40) != 0; 397 switch (config1 & 0x30) { 398 case 0x00: a_config.a_mem_size = 32 * 1024 * 1024; break; 399 case 0x10: a_config.a_mem_size = 64 * 1024 * 1024; break; 400 case 0x20: a_config.a_mem_size = 128 * 1024 * 1024; break; 401 case 0x30: a_config.a_mem_size = 256 * 1024 * 1024; break; 402 } 403 a_config.a_l2_cache = (config1 >> 2) & 3; 404 switch (config1 & 0x03) { 405 case 0x00: a_config.a_bus_freq = 66666666; break; 406 case 0x01: a_config.a_bus_freq = 83333333; break; 407 case 0x02: a_config.a_bus_freq = 100000000; break; 408 case 0x03: a_config.a_bus_freq = 0; break; /* XXX */ 409 } 410 a_config.a_is_monarch = (config0 & 0x80) == 0; 411 a_config.a_has_eth = (config0 & 0x20) != 0; 412 a_config.a_has_rtc = (config0 & 0x10) == 0; 413 switch (config0 & 0x0c) { 414 case 0x00: a_config.a_flash_size = 256 * 1024 * 1024; break; 415 case 0x04: a_config.a_flash_size = 128 * 1024 * 1024; break; 416 case 0x08: a_config.a_flash_size = 64 * 1024 * 1024; break; 417 case 0x0c: a_config.a_flash_size = 32 * 1024 * 1024; break; 418 } 419 switch (config0 & 0x03) { 420 case 0x00: a_config.a_flash_width = 64; break; 421 case 0x01: a_config.a_flash_width = 32; break; 422 case 0x02: a_config.a_flash_width = 16; break; 423 case 0x03: a_config.a_flash_width = 0; break; 424 } 425} 426