1/* $NetBSD: cats_machdep.c,v 1.94 2023/04/20 08:28:03 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.94 2023/04/20 08:28:03 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 117u_int dc21285_fclk = FCLK; 118 119struct ebsaboot ebsabootinfo; 120BootConfig bootconfig; /* Boot config storage */ 121static char bootargs[MAX_BOOT_STRING + 1]; 122char *boot_args = NULL; 123char *boot_file = NULL; 124 125/* Prototypes */ 126 127void consinit(void); 128 129int fcomcnattach(u_int iobase, int rate, tcflag_t cflag); 130int fcomcndetach(void); 131 132static void process_kernel_args(const char *); 133extern 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 171int comcnspeed = CONSPEED; 172int comcnmode = CONMODE; 173 174static 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 214static struct boot_physmem cats_physmem[MAX_PHYSMEM]; 215int ncats_physmem = 0; 216 217extern struct bus_space footbridge_pci_io_bs_tag; 218extern struct bus_space footbridge_pci_mem_bs_tag; 219void 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 235vaddr_t 236initarm(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#ifndef PMAP_NEED_ALLOC_POOLPAGE 319 if (ram_size > KERNEL_VM_BASE - KERNEL_BASE) { 320 printf("%s: dropping RAM size from %luMB to %uMB\n", 321 __func__, (unsigned long) (ram_size >> 20), 322 (KERNEL_VM_BASE - KERNEL_BASE) >> 20); 323 ram_size = KERNEL_VM_BASE - KERNEL_BASE; 324 } 325#endif 326#else 327 const bool mapallmem_p = false; 328#endif 329 330 printf("ram_size = 0x%08lx\n", ram_size); 331 332 arm32_bootmem_init(ebsabootinfo.bt_memstart, ram_size, 333 ebsabootinfo.bt_memstart); 334 335 /* 336 * The free block after the kernel from arm32_bootmem_init doesn't 337 * account for bt_memavail. Adjust for this. 338 */ 339 extern struct bootmem_info bootmem_info; 340 struct bootmem_info * const bmi = &bootmem_info; 341 342 pv_addr_t *pv0 = &bmi->bmi_freeblocks[0]; 343 KASSERTMSG(pv0->pv_pa == bmi->bmi_kernelend, 344 "pv_pa %#lx kernelend %#lx", pv0->pv_pa, bmi->bmi_kernelend); 345 346 pv0->pv_pa = ebsabootinfo.bt_memavail; 347 pv0->pv_va = KERN_PHYSTOV(pv0->pv_pa); 348 pv0->pv_size = bmi->bmi_end - pv0->pv_pa; 349 350 printf("First freeblock adjusted to: %lx -> %lx\n", pv0->pv_pa, 351 pv0->pv_pa + pv0->pv_size - 1); 352 353 arm32_kernel_vm_init(KERNEL_VM_BASE, ARM_VECTORS_LOW, 0, cats_devmap, 354 mapallmem_p); 355 356 printf("init subsystems: patch "); 357 358 /* 359 * PATCH PATCH ... 360 * 361 * Fixup the first word of the kernel to be the instruction 362 * add pc, pc, #0x41000000 363 * 364 * This traps the case where the CPU core resets due to bus contention 365 * on a prototype CATS system and will reboot into the firmware. 366 */ 367 *((u_int *)KERNEL_TEXT_BASE) = 0xe28ff441; 368 369#if NISA > 0 370 /* Initialise the ISA subsystem early ... */ 371 isa_footbridge_init(DC21285_PCI_IO_VBASE, DC21285_PCI_ISA_MEM_VBASE); 372#endif 373 374 footbridge_pci_bs_tag_init(); 375 376 printf("busses done.\n"); 377 378 /* Map the boot arguments page */ 379 if (ebsabootinfo.bt_vargp != vector_page) { 380 pmap_map_entry(kernel_l1pt.pv_va, ebsabootinfo.bt_vargp, 381 ebsabootinfo.bt_pargp, VM_PROT_READ, PTE_CACHE); 382 } 383 384 printf("Doing freeblocks: %d\n", bmi->bmi_nfreeblocks); 385 386 for (size_t i = 0; i < bmi->bmi_nfreeblocks; i++) { 387 pv_addr_t * const pv = &bmi->bmi_freeblocks[i]; 388 paddr_t start = pv->pv_pa; 389 paddr_t end = pv->pv_pa + pv->pv_size; 390 struct boot_physmem *bp; 391#if NISADMA > 0 392 paddr_t istart, isize; 393 extern struct arm32_dma_range *footbridge_isa_dma_ranges; 394 extern int footbridge_isa_dma_nranges; 395#endif 396 397 VPRINTF("%zu: 0x08%lx -> 0x08%lx\n", i, start, end - 1); 398 399#if NISADMA > 0 400 if (arm32_dma_range_intersect(footbridge_isa_dma_ranges, 401 footbridge_isa_dma_nranges, start, end - start, 402 &istart, &isize)) { 403 /* 404 * Place the pages that intersect with the 405 * ISA DMA range onto the ISA DMA free list. 406 */ 407 VPRINTF(" ISADMA 0x08%lx -> 0x%08lx\n", istart, 408 istart + isize - 1); 409 bp = &cats_physmem[ncats_physmem++]; 410 KASSERT(ncats_physmem < MAX_PHYSMEM); 411 bp->bp_start = atop(istart); 412 bp->bp_pages = atop(isize); 413 bp->bp_freelist = VM_FREELIST_ISADMA; 414 415 /* 416 * Load the pieces that come before the 417 * intersection onto the default free list. 418 */ 419 if (start < istart) { 420 VPRINTF(" BEFORE 0x08%lx -> 0x08%lx\n", 421 start, istart - 1); 422 bp = &cats_physmem[ncats_physmem++]; 423 KASSERT(ncats_physmem < MAX_PHYSMEM); 424 bp->bp_start = atop(start); 425 bp->bp_pages = atop(istart - start); 426 bp->bp_freelist = VM_FREELIST_DEFAULT; 427 } 428 429 /* 430 * Load the pieces that come after the 431 * intersection onto the default free list. 432 */ 433 if ((istart + isize) < end) { 434 VPRINTF(" AFTER 0x%08lx -> 0x%08lx\n", 435 (istart + isize), end - 1); 436 bp = &cats_physmem[ncats_physmem++]; 437 KASSERT(ncats_physmem < MAX_PHYSMEM); 438 bp->bp_start = atop(istart + isize); 439 bp->bp_pages = atop(end - (istart + isize)); 440 bp->bp_freelist = VM_FREELIST_DEFAULT; 441 } 442 } else { 443 bp = &cats_physmem[ncats_physmem++]; 444 KASSERT(ncats_physmem < MAX_PHYSMEM); 445 bp->bp_start = atop(start); 446 bp->bp_pages = atop(end - start); 447 bp->bp_freelist = VM_FREELIST_DEFAULT; 448 } 449#else /* NISADMA > 0 */ 450 bp = &cats_physmem[ncats_physmem++]; 451 KASSERT(ncats_physmem < MAX_PHYSMEM); 452 bp->bp_start = atop(start); 453 bp->bp_pages = atop(end - start); 454 bp->bp_freelist = VM_FREELIST_DEFAULT; 455#endif /* NISADMA > 0 */ 456 } 457 458 cpu_reset_address_paddr = DC21285_ROM_BASE; 459 460 /* initarm_common returns the new stack pointer address */ 461 vaddr_t sp; 462 sp = initarm_common(KERNEL_VM_BASE, KERNEL_VM_SIZE, cats_physmem, 463 ncats_physmem); 464 465 /* Setup the IRQ system */ 466 printf("init subsystems: irq "); 467 footbridge_intr_init(); 468 469 printf("done.\n"); 470 471#ifdef FCOM_INIT_ARM 472 fcomcndetach(); 473#endif 474 475#ifdef DDB 476 if (boothowto & RB_KDB) 477 Debugger(); 478#endif 479 480 /* 481 * XXX this should only be done in main() but it useful to 482 * have output earlier ... 483 */ 484 consinit(); 485 486 return sp; 487} 488 489static void 490process_kernel_args(const char *loader_args) 491{ 492 char *args; 493 boothowto = 0; 494 495 /* Make a local copy of the bootargs */ 496 strncpy(bootargs, loader_args, MAX_BOOT_STRING); 497 498 args = bootargs; 499 boot_file = bootargs; 500 501 /* Skip the kernel image filename */ 502 while (*args != ' ' && *args != 0) 503 ++args; 504 505 if (*args != 0) 506 *args++ = 0; 507 508 while (*args == ' ') 509 ++args; 510 511 boot_args = args; 512 513 printf("bootfile: %s\n", boot_file); 514 printf("bootargs: %s\n", boot_args); 515 516 parse_mi_bootargs(boot_args); 517} 518 519void 520consinit(void) 521{ 522 static int consinit_called = 0; 523 const char *console = CONSDEVNAME; 524 525 if (consinit_called != 0) 526 return; 527 528 consinit_called = 1; 529 530 get_bootconf_option(boot_args, "console", BOOTOPT_TYPE_STRING, 531 &console); 532 533 if (strncmp(console, "fcom", 4) == 0 534 || strncmp(console, "diag", 4) == 0) 535 fcomcnattach(DC21285_ARMCSR_VBASE, comcnspeed, comcnmode); 536#if (NVGA > 0) 537 else if (strncmp(console, "vga", 3) == 0) { 538 vga_cnattach(&footbridge_pci_io_bs_tag, 539 &footbridge_pci_mem_bs_tag, - 1, 0); 540#if (NPCKBC > 0) 541 pckbc_cnattach(&isa_io_bs_tag, IO_KBD, KBCMDP, PCKBC_KBD_SLOT, 542 0); 543#endif /* NPCKBC */ 544 } 545#endif /* NVGA */ 546#if (NCOM > 0) 547 else if (strncmp(console, "com", 3) == 0) { 548 if (comcnattach(&isa_io_bs_tag, CONCOMADDR, comcnspeed, 549 COM_FREQ, COM_TYPE_NORMAL, comcnmode)) 550 panic("can't init serial console @%x", CONCOMADDR); 551 } 552#endif 553 /* Don't know what console was requested so use the fall back. */ 554 else 555 fcomcnattach(DC21285_ARMCSR_VBASE, comcnspeed, comcnmode); 556} 557 558/* End of cats_machdep.c */ 559