1 /* $NetBSD: cats_machdep.c,v 1.96 2024/10/21 13:37:07 skrll Exp $ */ 2 3 /* 4 * Copyright (c) 1997,1998 Mark Brinicombe. 5 * Copyright (c) 1997,1998 Causality Limited. 6 * All rights reserved. 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 by Mark Brinicombe 19 * for the NetBSD Project. 20 * 4. The name of the company nor the name of the author may be used to 21 * endorse or promote products derived from this software without specific 22 * prior written permission. 23 * 24 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED 25 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 26 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 27 * IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, 28 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 29 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 30 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 31 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 32 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 33 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 34 * SUCH DAMAGE. 35 * 36 * Machine dependent functions for kernel setup for EBSA285 core architecture 37 * using cyclone firmware 38 * 39 * Created : 24/11/97 40 */ 41 42 #include <sys/cdefs.h> 43 __KERNEL_RCSID(0, "$NetBSD: cats_machdep.c,v 1.96 2024/10/21 13:37:07 skrll Exp $"); 44 45 #include "opt_arm_debug.h" 46 #include "opt_cats.h" 47 #include "opt_ddb.h" 48 #include "opt_modular.h" 49 50 #include "isadma.h" 51 52 #include <sys/param.h> 53 #include <sys/device.h> 54 #include <sys/systm.h> 55 #include <sys/kernel.h> 56 #include <sys/exec.h> 57 #include <sys/proc.h> 58 #include <sys/msgbuf.h> 59 #include <sys/reboot.h> 60 #include <sys/termios.h> 61 #include <sys/ksyms.h> 62 #include <sys/cpu.h> 63 #include <sys/intr.h> 64 65 #include <dev/cons.h> 66 67 #include <machine/db_machdep.h> 68 #include <ddb/db_sym.h> 69 #include <ddb/db_extern.h> 70 71 #include <machine/bootconfig.h> 72 #define _ARM32_BUS_DMA_PRIVATE 73 #include <sys/bus.h> 74 #include <arm/locore.h> 75 #include <arm/undefined.h> 76 #include <arm/arm32/machdep.h> 77 78 #include <machine/cyclone_boot.h> 79 #include <arm/footbridge/dc21285mem.h> 80 #include <arm/footbridge/dc21285reg.h> 81 82 #include "ksyms.h" 83 #include "opt_ableelf.h" 84 85 #include "isa.h" 86 #if NISA > 0 87 #include <dev/isa/isareg.h> 88 #include <dev/isa/isavar.h> 89 #endif 90 91 #ifdef VERBOSE_INIT_ARM 92 #define VPRINTF(...) printf(__VA_ARGS__) 93 #else 94 #define VPRINTF(...) __nothing 95 #endif 96 97 /* Kernel text starts at the base of the kernel address space. */ 98 #define KERNEL_TEXT_BASE (KERNEL_BASE + 0x00000000) 99 #define KERNEL_VM_BASE (KERNEL_BASE + 0x01000000) 100 101 /* 102 * The range 0xf1000000 - 0xfcffffff is available for kernel VM space 103 * Footbridge registers and I/O mappings occupy 0xfd000000 - 0xffffffff 104 */ 105 106 /* 107 * Size of available KVM space, note that growkernel will grow into this. 108 */ 109 #define KERNEL_VM_SIZE 0x0c000000 110 111 /* 112 * Address to call from cpu_reset() to reset the machine. 113 * This is machine architecture dependent as it varies depending 114 * on where the ROM appears when you turn the MMU off. 115 */ 116 117 u_int dc21285_fclk = FCLK; 118 119 struct ebsaboot ebsabootinfo; 120 BootConfig bootconfig; /* Boot config storage */ 121 static char bootargs[MAX_BOOT_STRING + 1]; 122 char *boot_args = NULL; 123 char *boot_file = NULL; 124 125 /* Prototypes */ 126 127 void consinit(void); 128 129 int fcomcnattach(u_int iobase, int rate, tcflag_t cflag); 130 int fcomcndetach(void); 131 132 static void process_kernel_args(const char *); 133 extern void configure(void); 134 135 /* A load of console goo. */ 136 #include "vga.h" 137 #if (NVGA > 0) 138 #include <dev/ic/mc6845reg.h> 139 #include <dev/ic/pcdisplayvar.h> 140 #include <dev/ic/vgareg.h> 141 #include <dev/ic/vgavar.h> 142 #endif 143 144 #include "pckbc.h" 145 #if (NPCKBC > 0) 146 #include <dev/ic/i8042reg.h> 147 #include <dev/ic/pckbcvar.h> 148 #endif 149 150 #include "com.h" 151 #if (NCOM > 0) 152 #include <dev/ic/comreg.h> 153 #include <dev/ic/comvar.h> 154 #ifndef CONCOMADDR 155 #define CONCOMADDR 0x3f8 156 #endif 157 #endif 158 159 #ifndef CONSDEVNAME 160 #define CONSDEVNAME "vga" 161 #endif 162 163 #define CONSPEED B38400 164 #ifndef CONSPEED 165 #define CONSPEED B9600 /* TTYDEF_SPEED */ 166 #endif 167 #ifndef CONMODE 168 #define CONMODE ((TTYDEF_CFLAG & ~(CSIZE | CSTOPB | PARENB)) | CS8) /* 8N1 */ 169 #endif 170 171 int comcnspeed = CONSPEED; 172 int comcnmode = CONMODE; 173 174 static const struct pmap_devmap cats_devmap[] = { 175 /* Map 1MB for CSR space */ 176 DEVMAP_ENTRY(DC21285_ARMCSR_VBASE, 177 DC21285_ARMCSR_BASE, 178 DC21285_ARMCSR_VSIZE), 179 180 /* Map 1MB for fast cache cleaning space */ 181 DEVMAP_ENTRY(DC21285_CACHE_FLUSH_VBASE, 182 DC21285_SA_CACHE_FLUSH_BASE, 183 DC21285_CACHE_FLUSH_VSIZE), 184 185 /* Map 1MB for PCI IO space */ 186 DEVMAP_ENTRY(DC21285_PCI_IO_VBASE, 187 DC21285_PCI_IO_BASE, 188 DC21285_PCI_IO_VSIZE), 189 190 /* Map 1MB for PCI IACK space */ 191 DEVMAP_ENTRY(DC21285_PCI_IACK_VBASE, 192 DC21285_PCI_IACK_SPECIAL, 193 DC21285_PCI_IACK_VSIZE), 194 195 /* Map 16MB of type 1 PCI config access */ 196 DEVMAP_ENTRY(DC21285_PCI_TYPE_1_CONFIG_VBASE, 197 DC21285_PCI_TYPE_1_CONFIG, 198 DC21285_PCI_TYPE_1_CONFIG_VSIZE), 199 200 /* Map 16MB of type 0 PCI config access */ 201 DEVMAP_ENTRY(DC21285_PCI_TYPE_0_CONFIG_VBASE, 202 DC21285_PCI_TYPE_0_CONFIG, 203 DC21285_PCI_TYPE_0_CONFIG_VSIZE), 204 205 /* Map 1MB of 32 bit PCI address space for ISA MEM accesses via PCI */ 206 DEVMAP_ENTRY(DC21285_PCI_ISA_MEM_VBASE, 207 DC21285_PCI_MEM_BASE, 208 DC21285_PCI_ISA_MEM_VSIZE), 209 210 DEVMAP_ENTRY_END 211 }; 212 213 #define MAX_PHYSMEM 4 214 static struct boot_physmem cats_physmem[MAX_PHYSMEM]; 215 int ncats_physmem = 0; 216 217 extern struct bus_space footbridge_pci_io_bs_tag; 218 extern struct bus_space footbridge_pci_mem_bs_tag; 219 void footbridge_pci_bs_tag_init(void); 220 221 /* 222 * vaddr_t initarm(struct ebsaboot *bootinfo) 223 * 224 * Initial entry point on startup. This gets called before main() is 225 * entered. 226 * It should be responsible for setting up everything that must be 227 * in place when main is called. 228 * This includes 229 * Taking a copy of the boot configuration structure. 230 * Initialising the physical console so characters can be printed. 231 * Setting up page tables for the kernel 232 * Relocating the kernel to the bottom of physical memory 233 */ 234 235 vaddr_t 236 initarm(void *arm_bootargs) 237 { 238 struct ebsaboot *bootinfo = arm_bootargs; 239 extern u_int cpu_get_control(void); 240 241 /* 242 * Heads up ... Setup the CPU / MMU / TLB functions 243 */ 244 set_cpufuncs(); 245 246 /* Copy the boot configuration structure */ 247 ebsabootinfo = *bootinfo; 248 249 if (ebsabootinfo.bt_fclk >= 50000000 250 && ebsabootinfo.bt_fclk <= 66000000) 251 dc21285_fclk = ebsabootinfo.bt_fclk; 252 253 /* Fake bootconfig structure for the benefit of pmap.c */ 254 /* XXX must make the memory description h/w independent */ 255 bootconfig.dramblocks = 1; 256 bootconfig.dram[0].address = ebsabootinfo.bt_memstart; 257 bootconfig.dram[0].pages = (ebsabootinfo.bt_memend 258 - ebsabootinfo.bt_memstart) / PAGE_SIZE; 259 260 /* 261 * Initialise the diagnostic serial console 262 * This allows a means of generating output during initarm(). 263 * Once all the memory map changes are complete we can call consinit() 264 * and not have to worry about things moving. 265 */ 266 pmap_devmap_bootstrap((vaddr_t)ebsabootinfo.bt_l1, cats_devmap); 267 268 #ifdef FCOM_INIT_ARM 269 fcomcnattach(DC21285_ARMCSR_VBASE, comcnspeed, comcnmode); 270 #endif 271 272 /* Talk to the user */ 273 printf("NetBSD/cats booting ...\n"); 274 275 if (ebsabootinfo.bt_magic != BT_MAGIC_NUMBER_EBSA 276 && ebsabootinfo.bt_magic != BT_MAGIC_NUMBER_CATS) 277 panic("Incompatible magic number %#x passed in boot args", 278 ebsabootinfo.bt_magic); 279 280 /* output the incoming bootinfo */ 281 VPRINTF("bootinfo @ %p\n", arm_bootargs); 282 VPRINTF("bt_magic = 0x%08x\n", ebsabootinfo.bt_magic); 283 VPRINTF("bt_vargp = 0x%08x\n", ebsabootinfo.bt_vargp); 284 VPRINTF("bt_pargp = 0x%08x\n", ebsabootinfo.bt_pargp); 285 VPRINTF("bt_args @ %p, contents = \"%s\"\n", ebsabootinfo.bt_args, ebsabootinfo.bt_args); 286 VPRINTF("bt_l1 = %p\n", ebsabootinfo.bt_l1); 287 288 VPRINTF("bt_memstart = 0x%08x\n", ebsabootinfo.bt_memstart); 289 VPRINTF("bt_memend = 0x%08x\n", ebsabootinfo.bt_memend); 290 VPRINTF("bt_memavail = 0x%08x\n", ebsabootinfo.bt_memavail); 291 VPRINTF("bt_fclk = 0x%08x\n", ebsabootinfo.bt_fclk); 292 VPRINTF("bt_pciclk = 0x%08x\n", ebsabootinfo.bt_pciclk); 293 VPRINTF("bt_vers = 0x%08x\n", ebsabootinfo.bt_vers); 294 VPRINTF("bt_features = 0x%08x\n", ebsabootinfo.bt_features); 295 296 /* 297 * Examine the boot args string for options we need to know about 298 * now. 299 */ 300 process_kernel_args(ebsabootinfo.bt_args); 301 302 psize_t ram_size = ebsabootinfo.bt_memend - ebsabootinfo.bt_memstart; 303 /* 304 * If MEMSIZE specified less than what we really have, limit ourselves 305 * to that. 306 */ 307 #ifdef MEMSIZE 308 if (ram_size == 0 || ram_size > (unsigned)MEMSIZE * 1024 * 1024) 309 ram_size = (unsigned)MEMSIZE * 1024 * 1024; 310 VPRINTF("ram_size = 0x%x\n", (int)ram_size); 311 #else 312 KASSERTMSG(ram_size > 0, "RAM size unknown and MEMSIZE undefined"); 313 #endif 314 315 #ifdef __HAVE_MM_MD_DIRECT_MAPPED_PHYS 316 const bool mapallmem_p = true; 317 318 if (ram_size > KERNEL_VM_BASE - KERNEL_BASE) { 319 printf("%s: dropping RAM size from %luMB to %uMB\n", 320 __func__, (unsigned long) (ram_size >> 20), 321 (KERNEL_VM_BASE - KERNEL_BASE) >> 20); 322 ram_size = KERNEL_VM_BASE - KERNEL_BASE; 323 } 324 #else 325 const bool mapallmem_p = false; 326 #endif 327 328 printf("ram_size = 0x%08lx\n", ram_size); 329 330 arm32_bootmem_init(ebsabootinfo.bt_memstart, ram_size, 331 ebsabootinfo.bt_memstart); 332 333 /* 334 * The free block after the kernel from arm32_bootmem_init doesn't 335 * account for bt_memavail. Adjust for this. 336 */ 337 extern struct bootmem_info bootmem_info; 338 struct bootmem_info * const bmi = &bootmem_info; 339 340 pv_addr_t *pv0 = &bmi->bmi_freeblocks[0]; 341 KASSERTMSG(pv0->pv_pa == bmi->bmi_kernelend, 342 "pv_pa %#lx kernelend %#lx", pv0->pv_pa, bmi->bmi_kernelend); 343 344 pv0->pv_pa = ebsabootinfo.bt_memavail; 345 pv0->pv_va = KERN_PHYSTOV(pv0->pv_pa); 346 pv0->pv_size = bmi->bmi_end - pv0->pv_pa; 347 348 printf("First freeblock adjusted to: %lx -> %lx\n", pv0->pv_pa, 349 pv0->pv_pa + pv0->pv_size - 1); 350 351 arm32_kernel_vm_init(KERNEL_VM_BASE, ARM_VECTORS_LOW, 0, cats_devmap, 352 mapallmem_p); 353 354 printf("init subsystems: patch "); 355 356 /* 357 * PATCH PATCH ... 358 * 359 * Fixup the first word of the kernel to be the instruction 360 * add pc, pc, #0x41000000 361 * 362 * This traps the case where the CPU core resets due to bus contention 363 * on a prototype CATS system and will reboot into the firmware. 364 */ 365 *((u_int *)KERNEL_TEXT_BASE) = 0xe28ff441; 366 367 #if NISA > 0 368 /* Initialise the ISA subsystem early ... */ 369 isa_footbridge_init(DC21285_PCI_IO_VBASE, DC21285_PCI_ISA_MEM_VBASE); 370 #endif 371 372 footbridge_pci_bs_tag_init(); 373 374 printf("busses done.\n"); 375 376 /* Map the boot arguments page */ 377 if (ebsabootinfo.bt_vargp != vector_page) { 378 pmap_map_entry(kernel_l1pt.pv_va, ebsabootinfo.bt_vargp, 379 ebsabootinfo.bt_pargp, VM_PROT_READ, PTE_CACHE); 380 } 381 382 printf("Doing freeblocks: %d\n", bmi->bmi_nfreeblocks); 383 384 for (size_t i = 0; i < bmi->bmi_nfreeblocks; i++) { 385 pv_addr_t * const pv = &bmi->bmi_freeblocks[i]; 386 paddr_t start = pv->pv_pa; 387 paddr_t end = pv->pv_pa + pv->pv_size; 388 struct boot_physmem *bp; 389 #if NISADMA > 0 390 paddr_t istart, isize; 391 extern struct arm32_dma_range *footbridge_isa_dma_ranges; 392 extern int footbridge_isa_dma_nranges; 393 #endif 394 395 VPRINTF("%zu: 0x08%lx -> 0x08%lx\n", i, start, end - 1); 396 397 #if NISADMA > 0 398 if (arm32_dma_range_intersect(footbridge_isa_dma_ranges, 399 footbridge_isa_dma_nranges, start, end - start, 400 &istart, &isize)) { 401 /* 402 * Place the pages that intersect with the 403 * ISA DMA range onto the ISA DMA free list. 404 */ 405 VPRINTF(" ISADMA 0x08%lx -> 0x%08lx\n", istart, 406 istart + isize - 1); 407 bp = &cats_physmem[ncats_physmem++]; 408 KASSERT(ncats_physmem < MAX_PHYSMEM); 409 bp->bp_start = atop(istart); 410 bp->bp_pages = atop(isize); 411 bp->bp_freelist = VM_FREELIST_ISADMA; 412 413 /* 414 * Load the pieces that come before the 415 * intersection onto the default free list. 416 */ 417 if (start < istart) { 418 VPRINTF(" BEFORE 0x08%lx -> 0x08%lx\n", 419 start, istart - 1); 420 bp = &cats_physmem[ncats_physmem++]; 421 KASSERT(ncats_physmem < MAX_PHYSMEM); 422 bp->bp_start = atop(start); 423 bp->bp_pages = atop(istart - start); 424 bp->bp_freelist = VM_FREELIST_DEFAULT; 425 } 426 427 /* 428 * Load the pieces that come after the 429 * intersection onto the default free list. 430 */ 431 if ((istart + isize) < end) { 432 VPRINTF(" AFTER 0x%08lx -> 0x%08lx\n", 433 (istart + isize), end - 1); 434 bp = &cats_physmem[ncats_physmem++]; 435 KASSERT(ncats_physmem < MAX_PHYSMEM); 436 bp->bp_start = atop(istart + isize); 437 bp->bp_pages = atop(end - (istart + isize)); 438 bp->bp_freelist = VM_FREELIST_DEFAULT; 439 } 440 } else { 441 bp = &cats_physmem[ncats_physmem++]; 442 KASSERT(ncats_physmem < MAX_PHYSMEM); 443 bp->bp_start = atop(start); 444 bp->bp_pages = atop(end - start); 445 bp->bp_freelist = VM_FREELIST_DEFAULT; 446 } 447 #else /* NISADMA > 0 */ 448 bp = &cats_physmem[ncats_physmem++]; 449 KASSERT(ncats_physmem < MAX_PHYSMEM); 450 bp->bp_start = atop(start); 451 bp->bp_pages = atop(end - start); 452 bp->bp_freelist = VM_FREELIST_DEFAULT; 453 #endif /* NISADMA > 0 */ 454 } 455 456 cpu_reset_address_paddr = DC21285_ROM_BASE; 457 458 /* initarm_common returns the new stack pointer address */ 459 vaddr_t sp; 460 sp = initarm_common(KERNEL_VM_BASE, KERNEL_VM_SIZE, cats_physmem, 461 ncats_physmem); 462 463 /* Setup the IRQ system */ 464 printf("init subsystems: irq "); 465 footbridge_intr_init(); 466 467 printf("done.\n"); 468 469 #ifdef FCOM_INIT_ARM 470 fcomcndetach(); 471 #endif 472 473 #ifdef DDB 474 if (boothowto & RB_KDB) 475 Debugger(); 476 #endif 477 478 /* 479 * XXX this should only be done in main() but it useful to 480 * have output earlier ... 481 */ 482 consinit(); 483 484 return sp; 485 } 486 487 static void 488 process_kernel_args(const char *loader_args) 489 { 490 char *args; 491 boothowto = 0; 492 493 /* Make a local copy of the bootargs */ 494 strncpy(bootargs, loader_args, MAX_BOOT_STRING); 495 496 args = bootargs; 497 boot_file = bootargs; 498 499 /* Skip the kernel image filename */ 500 while (*args != ' ' && *args != 0) 501 ++args; 502 503 if (*args != 0) 504 *args++ = 0; 505 506 while (*args == ' ') 507 ++args; 508 509 boot_args = args; 510 511 printf("bootfile: %s\n", boot_file); 512 printf("bootargs: %s\n", boot_args); 513 514 parse_mi_bootargs(boot_args); 515 } 516 517 void 518 consinit(void) 519 { 520 static int consinit_called = 0; 521 const char *console = CONSDEVNAME; 522 523 if (consinit_called != 0) 524 return; 525 526 consinit_called = 1; 527 528 get_bootconf_option(boot_args, "console", BOOTOPT_TYPE_STRING, 529 &console); 530 531 if (strncmp(console, "fcom", 4) == 0 532 || strncmp(console, "diag", 4) == 0) 533 fcomcnattach(DC21285_ARMCSR_VBASE, comcnspeed, comcnmode); 534 #if (NVGA > 0) 535 else if (strncmp(console, "vga", 3) == 0) { 536 vga_cnattach(&footbridge_pci_io_bs_tag, 537 &footbridge_pci_mem_bs_tag, - 1, 0); 538 #if (NPCKBC > 0) 539 pckbc_cnattach(&isa_io_bs_tag, IO_KBD, KBCMDP, PCKBC_KBD_SLOT, 540 0); 541 #endif /* NPCKBC */ 542 } 543 #endif /* NVGA */ 544 #if (NCOM > 0) 545 else if (strncmp(console, "com", 3) == 0) { 546 if (comcnattach(&isa_io_bs_tag, CONCOMADDR, comcnspeed, 547 COM_FREQ, COM_TYPE_NORMAL, comcnmode)) 548 panic("can't init serial console @%x", CONCOMADDR); 549 } 550 #endif 551 /* Don't know what console was requested so use the fall back. */ 552 else 553 fcomcnattach(DC21285_ARMCSR_VBASE, comcnspeed, comcnmode); 554 } 555 556 /* End of cats_machdep.c */ 557