1/* $NetBSD: bcm53xx_machdep.c,v 1.29 2024/02/16 16:28:49 skrll Exp $ */ 2 3/*- 4 * Copyright (c) 2012 The NetBSD Foundation, Inc. 5 * All rights reserved. 6 * 7 * This code is derived from software contributed to The NetBSD Foundation 8 * by Matt Thomas of 3am Software Foundry. 9 * 10 * Redistribution and use in source and binary forms, with or without 11 * modification, are permitted provided that the following conditions 12 * are met: 13 * 1. Redistributions of source code must retain the above copyright 14 * notice, this list of conditions and the following disclaimer. 15 * 2. Redistributions in binary form must reproduce the above copyright 16 * notice, this list of conditions and the following disclaimer in the 17 * documentation and/or other materials provided with the distribution. 18 * 19 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 20 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 21 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 23 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29 * POSSIBILITY OF SUCH DAMAGE. 30 */ 31 32#define CCA_PRIVATE 33#define IDM_PRIVATE 34 35#include <sys/cdefs.h> 36__KERNEL_RCSID(0, "$NetBSD: bcm53xx_machdep.c,v 1.29 2024/02/16 16:28:49 skrll Exp $"); 37 38#include "opt_arm_debug.h" 39#include "opt_console.h" 40#include "opt_evbarm_boardtype.h" 41#include "opt_broadcom.h" 42#include "opt_kgdb.h" 43#include "com.h" 44#include "pci.h" 45#include "bcmrng_ccb.h" 46 47#include <sys/param.h> 48#include <sys/bus.h> 49#include <sys/atomic.h> 50#include <sys/device.h> 51#include <sys/kernel.h> 52#include <sys/reboot.h> 53#include <sys/termios.h> 54 55#include <dev/cons.h> 56 57#include <uvm/uvm_extern.h> 58 59#include <arm/db_machdep.h> 60#include <arm/undefined.h> 61#include <arm/arm32/machdep.h> 62 63#include <machine/autoconf.h> 64#include <machine/bootconfig.h> 65 66#define CCA_PRIVATE 67 68#include <arm/cortex/scu_reg.h> 69#include <arm/broadcom/bcm53xx_var.h> 70 71#include <evbarm/bcm53xx/platform.h> 72 73#if NCOM == 0 74#error missing COM device for console 75#endif 76 77#include <dev/ic/comreg.h> 78#include <dev/ic/comvar.h> 79 80extern int _end[]; 81extern int KERNEL_BASE_phys[]; 82extern int KERNEL_BASE_virt[]; 83 84BootConfig bootconfig; 85static char bootargs[MAX_BOOT_STRING]; 86char *boot_args = NULL; 87 88/* filled in before cleaning bss. keep in .data */ 89u_int uboot_args[4] __attribute__((__section__(".data"))); 90 91static void bcm53xx_system_reset(void); 92 93#ifndef CONADDR 94#define CONADDR (BCM53XX_IOREG_PBASE + CCA_UART0_BASE) 95#endif 96#ifndef CONSPEED 97#define CONSPEED B115200 98#endif 99#ifndef CONMODE 100#define CONMODE ((TTYDEF_CFLAG & ~(CSIZE | CSTOPB | PARENB)) | CS8) /* 8N1 */ 101#endif 102 103void bcm53xx_mpstart(void); 104void bcm53xx_platform_early_putchar(char); 105 106#if (NCOM > 0) 107static const bus_addr_t comcnaddr = (bus_addr_t)CONADDR; 108 109int comcnspeed = CONSPEED; 110int comcnmode = CONMODE | CLOCAL; 111#endif 112 113#ifdef KGDB 114#include <sys/kgdb.h> 115#endif 116 117#ifdef VERBOSE_INIT_ARM 118#define VPRINTF(...) printf(__VA_ARGS__) 119#else 120#define VPRINTF(...) __nothing 121#endif 122 123static void 124earlyconsputc(dev_t dev, int c) 125{ 126 uartputc(c); 127} 128 129static int 130earlyconsgetc(dev_t dev) 131{ 132 return -1; 133} 134 135static struct consdev earlycons = { 136 .cn_putc = earlyconsputc, 137 .cn_getc = earlyconsgetc, 138 .cn_pollc = nullcnpollc, 139}; 140 141/* 142 * Static device mappings. These peripheral registers are mapped at 143 * fixed virtual addresses very early in initarm() so that we can use 144 * them while booting the kernel, and stay at the same address 145 * throughout whole kernel's life time. 146 * 147 * We use this table twice; once with bootstrap page table, and once 148 * with kernel's page table which we build up in initarm(). 149 * 150 * Since we map these registers into the bootstrap page table using 151 * pmap_devmap_bootstrap() which calls pmap_map_chunk(), we map 152 * registers segment-aligned and segment-rounded in order to avoid 153 * using the 2nd page tables. 154 */ 155 156static const struct pmap_devmap devmap[] = { 157 DEVMAP_ENTRY( 158 KERNEL_IO_IOREG_VBASE, 159 BCM53XX_IOREG_PBASE, /* 0x18000000 */ 160 BCM53XX_IOREG_SIZE /* 2MB */ 161 ), 162 DEVMAP_ENTRY( 163 KERNEL_IO_ARMCORE_VBASE, 164 BCM53XX_ARMCORE_PBASE, /* 0x19000000 */ 165 BCM53XX_ARMCORE_SIZE /* 1MB */ 166 ), 167 DEVMAP_ENTRY( 168 KERNEL_IO_ROM_REGION_VBASE, 169 BCM53XX_ROM_REGION_PBASE, /* 0xfff00000 */ 170 BCM53XX_ROM_REGION_SIZE /* 1MB */ 171 ), 172#if NPCI > 0 173 DEVMAP_ENTRY( 174 KERNEL_IO_PCIE0_OWIN_VBASE, 175 BCM53XX_PCIE0_OWIN_PBASE, /* 0x08000000 */ 176 BCM53XX_PCIE0_OWIN_SIZE /* 4MB */ 177 ), 178 DEVMAP_ENTRY( 179 KERNEL_IO_PCIE1_OWIN_VBASE, 180 BCM53XX_PCIE1_OWIN_PBASE, /* 0x40000000 */ 181 BCM53XX_PCIE1_OWIN_SIZE /* 4MB */ 182 ), 183 DEVMAP_ENTRY( 184 KERNEL_IO_PCIE2_OWIN_VBASE, 185 BCM53XX_PCIE2_OWIN_PBASE, /* 0x48000000 */ 186 BCM53XX_PCIE2_OWIN_SIZE /* 4MB */ 187 ), 188#endif /* NPCI > 0 */ 189 DEVMAP_ENTRY_END 190}; 191 192static const struct boot_physmem bp_first256 = { 193 .bp_start = 0x80000000 / NBPG, 194 .bp_pages = 0x10000000 / NBPG, 195 .bp_freelist = VM_FREELIST_ISADMA, 196 .bp_flags = 0, 197}; 198 199#define BCM53xx_ROM_CPU_ENTRY 0xffff0400 200 201void 202bcm53xx_mpstart(void) 203{ 204#ifdef MULTIPROCESSOR 205 /* 206 * Invalidate all SCU cache tags. That is, for all cores (0-3) 207 */ 208 bus_space_write_4(bcm53xx_armcore_bst, bcm53xx_armcore_bsh, 209 ARMCORE_SCU_BASE + SCU_INV_ALL_REG, 0xffff); 210 211 uint32_t diagctl = bus_space_read_4(bcm53xx_armcore_bst, 212 bcm53xx_armcore_bsh, ARMCORE_SCU_BASE + SCU_DIAG_CONTROL); 213 diagctl |= SCU_DIAG_DISABLE_MIGBIT; 214 bus_space_write_4(bcm53xx_armcore_bst, bcm53xx_armcore_bsh, 215 ARMCORE_SCU_BASE + SCU_DIAG_CONTROL, diagctl); 216 217 uint32_t scu_ctl = bus_space_read_4(bcm53xx_armcore_bst, 218 bcm53xx_armcore_bsh, ARMCORE_SCU_BASE + SCU_CTL); 219 scu_ctl |= SCU_CTL_SCU_ENA; 220 bus_space_write_4(bcm53xx_armcore_bst, bcm53xx_armcore_bsh, 221 ARMCORE_SCU_BASE + SCU_CTL, scu_ctl); 222 223 armv7_dcache_wbinv_all(); 224 225 const paddr_t mpstart = KERN_VTOPHYS((vaddr_t)cpu_mpstart); 226 bus_space_tag_t bcm53xx_rom_bst = &bcmgen_bs_tag; 227 bus_space_handle_t bcm53xx_rom_entry_bsh; 228 229 int error = bus_space_map(bcm53xx_rom_bst, BCM53xx_ROM_CPU_ENTRY, 230 4, 0, &bcm53xx_rom_entry_bsh); 231 232 /* 233 * Before we turn on the MMU, let's the other process out of the 234 * SKU ROM but setting the magic LUT address to our own mp_start 235 * routine. 236 */ 237 bus_space_write_4(bcm53xx_rom_bst, bcm53xx_rom_entry_bsh, mpstart); 238 239 dsb(sy); 240 sev(); 241 242 /* Bitmask of CPUs (non-BP) to start */ 243 for (u_int cpuindex = 1; cpuindex < arm_cpu_max; cpuindex++) { 244 u_int i ; 245 for (i = 1500000; i > 0; i--) { 246 if (cpu_hatched_p(cpuindex)) 247 break; 248 } 249 250 if (i == 0) { 251 ret++; 252 aprint_error("cpu%d: WARNING: AP failed to start\n", 253 cpuindex); 254 } 255 } 256#endif /* MULTIPROCESSOR */ 257} 258 259/* 260 * vaddr_t initarm(...) 261 * 262 * Initial entry point on startup. This gets called before main() is 263 * entered. 264 * It should be responsible for setting up everything that must be 265 * in place when main is called. 266 * This includes 267 * Taking a copy of the boot configuration structure. 268 * Initialising the physical console so characters can be printed. 269 * Setting up page tables for the kernel 270 */ 271vaddr_t 272initarm(void *arg) 273{ 274 /* 275 * Heads up ... Setup the CPU / MMU / TLB functions 276 */ 277 if (set_cpufuncs()) // starts PMC counter 278 panic("cpu not recognized!"); 279 280 cn_tab = &earlycons; 281 282 VPRINTF("devmap\n"); 283 extern char ARM_BOOTSTRAP_LxPT[]; 284 pmap_devmap_bootstrap((vaddr_t)ARM_BOOTSTRAP_LxPT, devmap); 285 286 VPRINTF("bootstrap\n"); 287 bcm53xx_bootstrap(KERNEL_IO_IOREG_VBASE); 288 289#ifdef MULTIPROCESSOR 290 uint32_t scu_cfg = bus_space_read_4(bcm53xx_armcore_bst, bcm53xx_armcore_bsh, 291 ARMCORE_SCU_BASE + SCU_CFG); 292 arm_cpu_max = 1 + (scu_cfg & SCU_CFG_CPUMAX); 293 membar_producer(); 294#endif 295 cpu_domains((DOMAIN_CLIENT << (PMAP_DOMAIN_KERNEL*2)) | DOMAIN_CLIENT); 296 297 VPRINTF("consinit "); 298 consinit(); 299 VPRINTF("ok\n"); 300 301 bcm53xx_cpu_softc_init(curcpu()); 302 bcm53xx_print_clocks(); 303 304#if NBCMRNG_CCB > 0 305 /* 306 * Start this early since it takes a while to startup up. 307 */ 308 bcm53xx_rng_start(bcm53xx_ioreg_bst, bcm53xx_ioreg_bsh); 309#endif 310 311 printf("uboot arg = %#x, %#x, %#x, %#x\n", 312 uboot_args[0], uboot_args[1], uboot_args[2], uboot_args[3]); 313 314 /* Talk to the user */ 315 printf("\nNetBSD/evbarm (" ___STRING(EVBARM_BOARDTYPE) ") booting ...\n"); 316 317 bootargs[0] = '\0'; 318 319#if defined(VERBOSE_INIT_ARM) || 1 320 printf("initarm: Configuring system"); 321#ifdef MULTIPROCESSOR 322 printf(" (%u cpu%s, hatched %#x)", 323 arm_cpu_max + 1, arm_cpu_max + 1 ? "s" : "", 324 arm_cpu_hatched); 325#endif 326 printf(", CLIDR=%010o CTR=%#x PMUSERSR=%#x", 327 armreg_clidr_read(), armreg_ctr_read(), armreg_pmuserenr_read()); 328 printf("\n"); 329#endif 330 331 psize_t memsize = bcm53xx_memprobe(); 332#ifdef MEMSIZE 333 if ((memsize >> 20) > MEMSIZE) 334 memsize = MEMSIZE*1024*1024; 335#endif 336 const bool bigmem_p = (memsize >> 20) > 256; 337 338#ifdef __HAVE_MM_MD_DIRECT_MAPPED_PHYS 339 const bool mapallmem_p = true; 340#ifndef PMAP_NEED_ALLOC_POOLPAGE 341 if (memsize > KERNEL_VM_BASE - KERNEL_BASE) { 342 printf("%s: dropping RAM size from %luMB to %uMB\n", 343 __func__, (unsigned long) (ram_size >> 20), 344 (KERNEL_VM_BASE - KERNEL_BASE) >> 20); 345 memsize = KERNEL_VM_BASE - KERNEL_BASE; 346 } 347#endif 348#else 349 const bool mapallmem_p = false; 350#endif 351 KASSERT((armreg_pfr1_read() & ARM_PFR1_SEC_MASK) != 0); 352 arm32_bootmem_init(KERN_VTOPHYS(KERNEL_BASE), memsize, 353 (paddr_t)KERNEL_BASE_phys); 354 355 bcm53xx_dma_bootstrap(memsize); 356 357 /* 358 * This is going to do all the hard work of setting up the first and 359 * and second level page tables. Pages of memory will be allocated 360 * and mapped for other structures that are required for system 361 * operation. When it returns, physical_freestart and free_pages will 362 * have been updated to reflect the allocations that were made. In 363 * addition, kernel_l1pt, kernel_pt_table[], systempage, irqstack, 364 * abtstack, undstack, kernelstack, msgbufphys will be set to point to 365 * the memory that was allocated for them. 366 */ 367 arm32_kernel_vm_init(KERNEL_VM_BASE, ARM_VECTORS_HIGH, 0, devmap, 368 mapallmem_p); 369 370 cpu_reset_address = bcm53xx_system_reset; 371 /* we've a specific device_register routine */ 372 evbarm_device_register = bcm53xx_device_register; 373 if (bigmem_p) { 374 /* 375 * If we have more than 256MB 376 */ 377 arm_poolpage_vmfreelist = bp_first256.bp_freelist; 378 } 379 380 /* 381 * If we have more than 256MB of RAM, set aside the first 256MB for 382 * non-default VM allocations. 383 */ 384 vaddr_t sp = initarm_common(KERNEL_VM_BASE, KERNEL_VM_SIZE, 385 (bigmem_p ? &bp_first256 : NULL), (bigmem_p ? 1 : 0)); 386 387 /* 388 * initarm_common flushes cache if required before AP start 389 */ 390 bcm53xx_mpstart(); 391 392 return sp; 393} 394 395void 396consinit(void) 397{ 398 static bool consinit_called = false; 399 uint32_t v; 400 if (consinit_called) 401 return; 402 403 consinit_called = true; 404 405 /* 406 * Force UART clock to the reference clock 407 */ 408 v = bus_space_read_4(bcm53xx_ioreg_bst, bcm53xx_ioreg_bsh, 409 IDM_BASE + IDM_APBX_BASE + IDM_IO_CONTROL_DIRECT); 410 v &= ~IO_CONTROL_DIRECT_UARTCLKSEL; 411 bus_space_write_4(bcm53xx_ioreg_bst, bcm53xx_ioreg_bsh, 412 IDM_BASE + IDM_APBX_BASE + IDM_IO_CONTROL_DIRECT, v); 413 414 /* 415 * Switch to the reference clock 416 */ 417 v = bus_space_read_4(bcm53xx_ioreg_bst, bcm53xx_ioreg_bsh, 418 CCA_MISC_BASE + MISC_CORECTL); 419 v &= ~CORECTL_UART_CLK_OVERRIDE; 420 bus_space_write_4(bcm53xx_ioreg_bst, bcm53xx_ioreg_bsh, 421 CCA_MISC_BASE + MISC_CORECTL, v); 422 423 if (comcnattach(bcm53xx_ioreg_bst, comcnaddr, comcnspeed, 424 BCM53XX_REF_CLK, COM_TYPE_NORMAL, comcnmode)) 425 panic("Serial console can not be initialized."); 426} 427 428static void 429bcm53xx_system_reset(void) 430{ 431 bus_space_write_4(bcm53xx_ioreg_bst, bcm53xx_ioreg_bsh, 432 MISC_WATCHDOG, 1); 433} 434 435void __noasan 436bcm53xx_platform_early_putchar(char c) 437{ 438#ifdef CONSADDR 439#define CONSADDR_VA (CONSADDR - BCM53XX_IOREG_PBASE + KERNEL_IO_IOREG_VBASE) 440 volatile uint32_t *uartaddr = cpu_earlydevice_va_p() ? 441 (volatile uint32_t *)CONSADDR_VA : 442 (volatile uint32_t *)CONSADDR; 443 444 while ((le32toh(uartaddr[com_lsr]) & LSR_TXRDY) == 0) 445 ; 446 447 uartaddr[com_data] = htole32(c); 448#endif 449} 450 451