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