1 1.111 thorpej /* $NetBSD: fdt_machdep.c,v 1.111 2025/09/06 22:53:48 thorpej Exp $ */ 2 1.1 jmcneill 3 1.1 jmcneill /*- 4 1.1 jmcneill * Copyright (c) 2015-2017 Jared McNeill <jmcneill (at) invisible.ca> 5 1.1 jmcneill * All rights reserved. 6 1.1 jmcneill * 7 1.1 jmcneill * Redistribution and use in source and binary forms, with or without 8 1.1 jmcneill * modification, are permitted provided that the following conditions 9 1.1 jmcneill * are met: 10 1.1 jmcneill * 1. Redistributions of source code must retain the above copyright 11 1.1 jmcneill * notice, this list of conditions and the following disclaimer. 12 1.1 jmcneill * 2. Redistributions in binary form must reproduce the above copyright 13 1.1 jmcneill * notice, this list of conditions and the following disclaimer in the 14 1.1 jmcneill * documentation and/or other materials provided with the distribution. 15 1.1 jmcneill * 16 1.1 jmcneill * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 17 1.1 jmcneill * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 18 1.1 jmcneill * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 19 1.1 jmcneill * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 20 1.1 jmcneill * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 21 1.1 jmcneill * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 22 1.1 jmcneill * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 23 1.1 jmcneill * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 24 1.1 jmcneill * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 25 1.1 jmcneill * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 26 1.1 jmcneill * SUCH DAMAGE. 27 1.1 jmcneill */ 28 1.1 jmcneill 29 1.1 jmcneill #include <sys/cdefs.h> 30 1.111 thorpej __KERNEL_RCSID(0, "$NetBSD: fdt_machdep.c,v 1.111 2025/09/06 22:53:48 thorpej Exp $"); 31 1.1 jmcneill 32 1.84 skrll #include "opt_arm_debug.h" 33 1.21 ryo #include "opt_bootconfig.h" 34 1.84 skrll #include "opt_cpuoptions.h" 35 1.1 jmcneill #include "opt_ddb.h" 36 1.84 skrll #include "opt_efi.h" 37 1.84 skrll #include "opt_machdep.h" 38 1.1 jmcneill #include "opt_multiprocessor.h" 39 1.1 jmcneill 40 1.75 jmcneill #include "genfb.h" 41 1.109 jmcneill #include "pci.h" 42 1.14 jmcneill #include "ukbd.h" 43 1.39 bouyer #include "wsdisplay.h" 44 1.14 jmcneill 45 1.1 jmcneill #include <sys/param.h> 46 1.93 skrll #include <sys/types.h> 47 1.93 skrll 48 1.93 skrll #include <sys/atomic.h> 49 1.93 skrll #include <sys/bootblock.h> 50 1.1 jmcneill #include <sys/bus.h> 51 1.93 skrll #include <sys/conf.h> 52 1.1 jmcneill #include <sys/cpu.h> 53 1.1 jmcneill #include <sys/device.h> 54 1.93 skrll #include <sys/disk.h> 55 1.93 skrll #include <sys/disklabel.h> 56 1.76 rin #include <sys/endian.h> 57 1.1 jmcneill #include <sys/exec.h> 58 1.93 skrll #include <sys/fcntl.h> 59 1.93 skrll #include <sys/kauth.h> 60 1.1 jmcneill #include <sys/kernel.h> 61 1.1 jmcneill #include <sys/kmem.h> 62 1.1 jmcneill #include <sys/ksyms.h> 63 1.93 skrll #include <sys/md5.h> 64 1.1 jmcneill #include <sys/msgbuf.h> 65 1.1 jmcneill #include <sys/proc.h> 66 1.93 skrll #include <sys/pserialize.h> 67 1.1 jmcneill #include <sys/reboot.h> 68 1.93 skrll #include <sys/systm.h> 69 1.1 jmcneill #include <sys/termios.h> 70 1.34 jmcneill #include <sys/vnode.h> 71 1.53 jmcneill #include <sys/uuid.h> 72 1.55 jmcneill 73 1.55 jmcneill #include <net/if.h> 74 1.55 jmcneill #include <net/if_dl.h> 75 1.1 jmcneill 76 1.23 ryo #include <dev/cons.h> 77 1.1 jmcneill #include <uvm/uvm_extern.h> 78 1.1 jmcneill 79 1.1 jmcneill #include <machine/db_machdep.h> 80 1.1 jmcneill #include <ddb/db_sym.h> 81 1.1 jmcneill #include <ddb/db_extern.h> 82 1.1 jmcneill 83 1.1 jmcneill #include <machine/bootconfig.h> 84 1.1 jmcneill #include <arm/armreg.h> 85 1.1 jmcneill 86 1.21 ryo #include <arm/cpufunc.h> 87 1.1 jmcneill 88 1.1 jmcneill #include <evbarm/include/autoconf.h> 89 1.30 skrll #include <evbarm/fdt/machdep.h> 90 1.1 jmcneill #include <evbarm/fdt/platform.h> 91 1.1 jmcneill 92 1.1 jmcneill #include <arm/fdt/arm_fdtvar.h> 93 1.102 skrll 94 1.102 skrll #include <dev/fdt/fdtvar.h> 95 1.103 skrll #include <dev/fdt/fdt_boot.h> 96 1.111 thorpej #include <dev/fdt/fdt_console.h> 97 1.68 skrll #include <dev/fdt/fdt_private.h> 98 1.83 skrll #include <dev/fdt/fdt_memory.h> 99 1.110 thorpej #include <dev/fdt/fdt_platform.h> 100 1.1 jmcneill 101 1.46 jmcneill #ifdef EFI_RUNTIME 102 1.46 jmcneill #include <arm/arm/efi_runtime.h> 103 1.46 jmcneill #endif 104 1.46 jmcneill 105 1.75 jmcneill #if NWSDISPLAY > 0 && NGENFB > 0 106 1.75 jmcneill #include <arm/fdt/arm_simplefb.h> 107 1.75 jmcneill #endif 108 1.75 jmcneill 109 1.14 jmcneill #if NUKBD > 0 110 1.14 jmcneill #include <dev/usb/ukbdvar.h> 111 1.14 jmcneill #endif 112 1.39 bouyer #if NWSDISPLAY > 0 113 1.39 bouyer #include <dev/wscons/wsdisplayvar.h> 114 1.39 bouyer #endif 115 1.14 jmcneill 116 1.109 jmcneill #if NPCI > 0 117 1.109 jmcneill #include <dev/pci/pcireg.h> 118 1.109 jmcneill #include <dev/pci/pcivar.h> 119 1.109 jmcneill #endif 120 1.109 jmcneill 121 1.1 jmcneill BootConfig bootconfig; 122 1.1 jmcneill char *boot_args = NULL; 123 1.26 christos 124 1.26 christos /* filled in before cleaning bss. keep in .data */ 125 1.27 christos u_long uboot_args[4] __attribute__((__section__(".data"))); 126 1.28 skrll const uint8_t *fdt_addr_r __attribute__((__section__(".data"))); 127 1.1 jmcneill 128 1.1 jmcneill #include <libfdt.h> 129 1.1 jmcneill #include <dev/fdt/fdtvar.h> 130 1.40 jmcneill #define FDT_BUF_SIZE (512*1024) 131 1.1 jmcneill static uint8_t fdt_data[FDT_BUF_SIZE]; 132 1.1 jmcneill 133 1.1 jmcneill extern char KERNEL_BASE_phys[]; 134 1.1 jmcneill #define KERNEL_BASE_PHYS ((paddr_t)KERNEL_BASE_phys) 135 1.1 jmcneill 136 1.1 jmcneill static void fdt_device_register(device_t, void *); 137 1.39 bouyer static void fdt_device_register_post_config(device_t, void *); 138 1.1 jmcneill static void fdt_reset(void); 139 1.1 jmcneill static void fdt_powerdown(void); 140 1.1 jmcneill 141 1.76 rin #if BYTE_ORDER == BIG_ENDIAN 142 1.76 rin static void fdt_update_fb_format(void); 143 1.76 rin #endif 144 1.76 rin 145 1.1 jmcneill static void 146 1.23 ryo earlyconsputc(dev_t dev, int c) 147 1.1 jmcneill { 148 1.48 skrll uartputc(c); 149 1.1 jmcneill } 150 1.1 jmcneill 151 1.23 ryo static int 152 1.23 ryo earlyconsgetc(dev_t dev) 153 1.1 jmcneill { 154 1.87 jmcneill return -1; 155 1.23 ryo } 156 1.1 jmcneill 157 1.54 skrll static struct consdev earlycons = { 158 1.54 skrll .cn_putc = earlyconsputc, 159 1.54 skrll .cn_getc = earlyconsgetc, 160 1.54 skrll .cn_pollc = nullcnpollc, 161 1.54 skrll }; 162 1.54 skrll 163 1.23 ryo #ifdef VERBOSE_INIT_ARM 164 1.29 skrll #define VPRINTF(...) printf(__VA_ARGS__) 165 1.1 jmcneill #else 166 1.43 skrll #define VPRINTF(...) __nothing 167 1.1 jmcneill #endif 168 1.1 jmcneill 169 1.49 jmcneill static void 170 1.49 jmcneill fdt_add_dram_blocks(const struct fdt_memory *m, void *arg) 171 1.49 jmcneill { 172 1.49 jmcneill BootConfig *bc = arg; 173 1.49 jmcneill 174 1.52 jmcneill VPRINTF(" %" PRIx64 " - %" PRIx64 "\n", m->start, m->end - 1); 175 1.49 jmcneill bc->dram[bc->dramblocks].address = m->start; 176 1.49 jmcneill bc->dram[bc->dramblocks].pages = 177 1.49 jmcneill (m->end - m->start) / PAGE_SIZE; 178 1.49 jmcneill bc->dramblocks++; 179 1.49 jmcneill } 180 1.49 jmcneill 181 1.49 jmcneill static int nfdt_physmem = 0; 182 1.99 jmcneill static struct boot_physmem fdt_physmem[FDT_MEMORY_RANGES]; 183 1.49 jmcneill 184 1.49 jmcneill static void 185 1.49 jmcneill fdt_add_boot_physmem(const struct fdt_memory *m, void *arg) 186 1.49 jmcneill { 187 1.62 skrll const paddr_t saddr = round_page(m->start); 188 1.62 skrll const paddr_t eaddr = trunc_page(m->end); 189 1.62 skrll 190 1.62 skrll VPRINTF(" %" PRIx64 " - %" PRIx64, m->start, m->end - 1); 191 1.62 skrll if (saddr >= eaddr) { 192 1.62 skrll VPRINTF(" skipped\n"); 193 1.62 skrll return; 194 1.62 skrll } 195 1.62 skrll VPRINTF("\n"); 196 1.62 skrll 197 1.49 jmcneill struct boot_physmem *bp = &fdt_physmem[nfdt_physmem++]; 198 1.49 jmcneill 199 1.99 jmcneill KASSERT(nfdt_physmem <= FDT_MEMORY_RANGES); 200 1.49 jmcneill 201 1.62 skrll bp->bp_start = atop(saddr); 202 1.62 skrll bp->bp_pages = atop(eaddr) - bp->bp_start; 203 1.49 jmcneill bp->bp_freelist = VM_FREELIST_DEFAULT; 204 1.49 jmcneill 205 1.49 jmcneill #ifdef PMAP_NEED_ALLOC_POOLPAGE 206 1.49 jmcneill const uint64_t memory_size = *(uint64_t *)arg; 207 1.49 jmcneill if (atop(memory_size) > bp->bp_pages) { 208 1.49 jmcneill arm_poolpage_vmfreelist = VM_FREELIST_DIRECTMAP; 209 1.49 jmcneill bp->bp_freelist = VM_FREELIST_DIRECTMAP; 210 1.49 jmcneill } 211 1.49 jmcneill #endif 212 1.49 jmcneill } 213 1.49 jmcneill 214 1.83 skrll 215 1.83 skrll static void 216 1.83 skrll fdt_print_memory(const struct fdt_memory *m, void *arg) 217 1.83 skrll { 218 1.83 skrll 219 1.83 skrll VPRINTF("FDT /memory @ 0x%" PRIx64 " size 0x%" PRIx64 "\n", 220 1.83 skrll m->start, m->end - m->start); 221 1.83 skrll } 222 1.83 skrll 223 1.83 skrll 224 1.8 jmcneill /* 225 1.8 jmcneill * Define usable memory regions. 226 1.8 jmcneill */ 227 1.8 jmcneill static void 228 1.21 ryo fdt_build_bootconfig(uint64_t mem_start, uint64_t mem_end) 229 1.8 jmcneill { 230 1.8 jmcneill BootConfig *bc = &bootconfig; 231 1.83 skrll 232 1.8 jmcneill uint64_t addr, size; 233 1.49 jmcneill int index; 234 1.8 jmcneill 235 1.104 rin /* Reserve pages for ramdisk, rndseed, and firmware's RNG */ 236 1.104 rin fdt_reserve_initrd(); 237 1.104 rin fdt_reserve_rndseed(); 238 1.104 rin fdt_reserve_efirng(); 239 1.69 riastrad 240 1.47 jmcneill const int framebuffer = OF_finddevice("/chosen/framebuffer"); 241 1.47 jmcneill if (framebuffer >= 0) { 242 1.47 jmcneill for (index = 0; 243 1.47 jmcneill fdtbus_get_reg64(framebuffer, index, &addr, &size) == 0; 244 1.47 jmcneill index++) { 245 1.83 skrll fdt_memory_remove_range(addr, size); 246 1.47 jmcneill } 247 1.47 jmcneill } 248 1.47 jmcneill 249 1.29 skrll VPRINTF("Usable memory:\n"); 250 1.8 jmcneill bc->dramblocks = 0; 251 1.49 jmcneill fdt_memory_foreach(fdt_add_dram_blocks, bc); 252 1.8 jmcneill } 253 1.8 jmcneill 254 1.46 jmcneill 255 1.64 skrll vaddr_t 256 1.1 jmcneill initarm(void *arg) 257 1.1 jmcneill { 258 1.102 skrll const struct fdt_platform *plat; 259 1.21 ryo uint64_t memory_start, memory_end; 260 1.1 jmcneill 261 1.23 ryo /* set temporally to work printf()/panic() even before consinit() */ 262 1.23 ryo cn_tab = &earlycons; 263 1.23 ryo 264 1.1 jmcneill /* Load FDT */ 265 1.1 jmcneill int error = fdt_check_header(fdt_addr_r); 266 1.79 skrll if (error != 0) 267 1.1 jmcneill panic("fdt_check_header failed: %s", fdt_strerror(error)); 268 1.79 skrll 269 1.79 skrll /* If the DTB is too big, try to pack it in place first. */ 270 1.79 skrll if (fdt_totalsize(fdt_addr_r) > sizeof(fdt_data)) 271 1.79 skrll (void)fdt_pack(__UNCONST(fdt_addr_r)); 272 1.83 skrll 273 1.79 skrll error = fdt_open_into(fdt_addr_r, fdt_data, sizeof(fdt_data)); 274 1.79 skrll if (error != 0) 275 1.79 skrll panic("fdt_move failed: %s", fdt_strerror(error)); 276 1.79 skrll 277 1.79 skrll fdtbus_init(fdt_data); 278 1.1 jmcneill 279 1.1 jmcneill /* Lookup platform specific backend */ 280 1.102 skrll plat = fdt_platform_find(); 281 1.1 jmcneill if (plat == NULL) 282 1.1 jmcneill panic("Kernel does not support this device"); 283 1.1 jmcneill 284 1.1 jmcneill /* Early console may be available, announce ourselves. */ 285 1.29 skrll VPRINTF("FDT<%p>\n", fdt_addr_r); 286 1.1 jmcneill 287 1.105 rin boot_args = fdt_get_bootargs(); 288 1.6 jmcneill 289 1.1 jmcneill /* Heads up ... Setup the CPU / MMU / TLB functions. */ 290 1.29 skrll VPRINTF("cpufunc\n"); 291 1.1 jmcneill if (set_cpufuncs()) 292 1.1 jmcneill panic("cpu not recognized!"); 293 1.1 jmcneill 294 1.44 skrll /* 295 1.44 skrll * Memory is still identity/flat mapped this point so using ttbr for 296 1.44 skrll * l1pt VA is fine 297 1.44 skrll */ 298 1.44 skrll 299 1.102 skrll VPRINTF("devmap %p\n", plat->fp_devmap()); 300 1.44 skrll extern char ARM_BOOTSTRAP_LxPT[]; 301 1.102 skrll pmap_devmap_bootstrap((vaddr_t)ARM_BOOTSTRAP_LxPT, plat->fp_devmap()); 302 1.44 skrll 303 1.29 skrll VPRINTF("bootstrap\n"); 304 1.102 skrll plat->fp_bootstrap(); 305 1.16 skrll 306 1.5 jmcneill /* 307 1.5 jmcneill * If stdout-path is specified on the command line, override the 308 1.5 jmcneill * value in /chosen/stdout-path before initializing console. 309 1.5 jmcneill */ 310 1.44 skrll VPRINTF("stdout\n"); 311 1.103 skrll fdt_update_stdout_path(fdt_data, boot_args); 312 1.5 jmcneill 313 1.76 rin #if BYTE_ORDER == BIG_ENDIAN 314 1.76 rin /* 315 1.92 skrll * Most boards are configured to little-endian mode initially, and 316 1.76 rin * switched to big-endian mode after kernel is loaded. In this case, 317 1.76 rin * framebuffer seems byte-swapped to CPU. Override FDT to let 318 1.76 rin * drivers know. 319 1.76 rin */ 320 1.76 rin VPRINTF("fb_format\n"); 321 1.76 rin fdt_update_fb_format(); 322 1.76 rin #endif 323 1.76 rin 324 1.38 jmcneill /* 325 1.38 jmcneill * Done making changes to the FDT. 326 1.38 jmcneill */ 327 1.38 jmcneill fdt_pack(fdt_data); 328 1.38 jmcneill 329 1.29 skrll VPRINTF("consinit "); 330 1.1 jmcneill consinit(); 331 1.29 skrll VPRINTF("ok\n"); 332 1.1 jmcneill 333 1.29 skrll VPRINTF("uboot: args %#lx, %#lx, %#lx, %#lx\n", 334 1.1 jmcneill uboot_args[0], uboot_args[1], uboot_args[2], uboot_args[3]); 335 1.1 jmcneill 336 1.1 jmcneill cpu_reset_address = fdt_reset; 337 1.1 jmcneill cpu_powerdown_address = fdt_powerdown; 338 1.1 jmcneill evbarm_device_register = fdt_device_register; 339 1.39 bouyer evbarm_device_register_post_config = fdt_device_register_post_config; 340 1.34 jmcneill evbarm_cpu_rootconf = fdt_cpu_rootconf; 341 1.1 jmcneill 342 1.1 jmcneill /* Talk to the user */ 343 1.45 skrll printf("NetBSD/evbarm (fdt) booting ...\n"); 344 1.1 jmcneill 345 1.1 jmcneill #ifdef BOOT_ARGS 346 1.1 jmcneill char mi_bootargs[] = BOOT_ARGS; 347 1.1 jmcneill parse_mi_bootargs(mi_bootargs); 348 1.1 jmcneill #endif 349 1.1 jmcneill 350 1.83 skrll fdt_memory_get(&memory_start, &memory_end); 351 1.83 skrll 352 1.83 skrll fdt_memory_foreach(fdt_print_memory, NULL); 353 1.1 jmcneill 354 1.1 jmcneill #if !defined(_LP64) 355 1.81 skrll /* Cannot map memory above 4GB (remove last page as well) */ 356 1.81 skrll const uint64_t memory_limit = 0x100000000ULL - PAGE_SIZE; 357 1.83 skrll if (memory_end > memory_limit) { 358 1.83 skrll fdt_memory_remove_range(memory_limit , memory_end); 359 1.81 skrll memory_end = memory_limit; 360 1.83 skrll } 361 1.31 skrll #endif 362 1.21 ryo uint64_t memory_size = memory_end - memory_start; 363 1.1 jmcneill 364 1.44 skrll VPRINTF("%s: memory start %" PRIx64 " end %" PRIx64 " (len %" 365 1.44 skrll PRIx64 ")\n", __func__, memory_start, memory_end, memory_size); 366 1.44 skrll 367 1.8 jmcneill /* Parse ramdisk info */ 368 1.104 rin fdt_probe_initrd(); 369 1.8 jmcneill 370 1.69 riastrad /* Parse our on-disk rndseed and the firmware's RNG from EFI */ 371 1.104 rin fdt_probe_rndseed(); 372 1.104 rin fdt_probe_efirng(); 373 1.65 riastrad 374 1.98 skrll fdt_memory_remove_reserved(memory_start, memory_end); 375 1.96 skrll 376 1.16 skrll /* 377 1.80 skrll * Populate bootconfig structure for the benefit of dodumpsys 378 1.16 skrll */ 379 1.44 skrll VPRINTF("%s: fdt_build_bootconfig\n", __func__); 380 1.21 ryo fdt_build_bootconfig(memory_start, memory_end); 381 1.21 ryo 382 1.31 skrll /* Perform PT build and VM init */ 383 1.31 skrll cpu_kernel_vm_init(memory_start, memory_size); 384 1.1 jmcneill 385 1.105 rin VPRINTF("bootargs: %s\n", boot_args); 386 1.1 jmcneill 387 1.1 jmcneill parse_mi_bootargs(boot_args); 388 1.1 jmcneill 389 1.49 jmcneill VPRINTF("Memory regions:\n"); 390 1.86 skrll 391 1.86 skrll /* Populate fdt_physmem / nfdt_physmem for initarm_common */ 392 1.49 jmcneill fdt_memory_foreach(fdt_add_boot_physmem, &memory_size); 393 1.1 jmcneill 394 1.64 skrll vaddr_t sp = initarm_common(KERNEL_VM_BASE, KERNEL_VM_SIZE, fdt_physmem, 395 1.16 skrll nfdt_physmem); 396 1.44 skrll 397 1.59 skrll /* 398 1.60 skrll * initarm_common flushes cache if required before AP start 399 1.59 skrll */ 400 1.58 skrll error = 0; 401 1.56 ryo if ((boothowto & RB_MD1) == 0) { 402 1.56 ryo VPRINTF("mpstart\n"); 403 1.102 skrll if (plat->fp_mpstart) 404 1.102 skrll error = plat->fp_mpstart(); 405 1.56 ryo } 406 1.44 skrll 407 1.58 skrll if (error) 408 1.58 skrll return sp; 409 1.74 skrll 410 1.44 skrll /* 411 1.44 skrll * Now we have APs started the pages used for stacks and L1PT can 412 1.44 skrll * be given to uvm 413 1.44 skrll */ 414 1.57 skrll extern char const __start__init_memory[]; 415 1.57 skrll extern char const __stop__init_memory[] __weak; 416 1.57 skrll 417 1.106 mrg if (&__start__init_memory[0] != &__stop__init_memory[0]) { 418 1.44 skrll const paddr_t spa = KERN_VTOPHYS((vaddr_t)__start__init_memory); 419 1.44 skrll const paddr_t epa = KERN_VTOPHYS((vaddr_t)__stop__init_memory); 420 1.44 skrll const paddr_t spg = atop(spa); 421 1.44 skrll const paddr_t epg = atop(epa); 422 1.44 skrll 423 1.63 skrll VPRINTF(" start %08lx end %08lx... " 424 1.63 skrll "loading in freelist %d\n", spa, epa, VM_FREELIST_DEFAULT); 425 1.63 skrll 426 1.44 skrll uvm_page_physload(spg, epg, spg, epg, VM_FREELIST_DEFAULT); 427 1.44 skrll } 428 1.44 skrll 429 1.44 skrll return sp; 430 1.1 jmcneill } 431 1.1 jmcneill 432 1.1 jmcneill void 433 1.1 jmcneill consinit(void) 434 1.1 jmcneill { 435 1.1 jmcneill static bool initialized = false; 436 1.102 skrll const struct fdt_platform *plat = fdt_platform_find(); 437 1.1 jmcneill const struct fdt_console *cons = fdtbus_get_console(); 438 1.1 jmcneill struct fdt_attach_args faa; 439 1.4 jmcneill u_int uart_freq = 0; 440 1.1 jmcneill 441 1.1 jmcneill if (initialized || cons == NULL) 442 1.1 jmcneill return; 443 1.1 jmcneill 444 1.102 skrll plat->fp_init_attach_args(&faa); 445 1.1 jmcneill faa.faa_phandle = fdtbus_get_stdout_phandle(); 446 1.1 jmcneill 447 1.102 skrll if (plat->fp_uart_freq != NULL) 448 1.102 skrll uart_freq = plat->fp_uart_freq(); 449 1.4 jmcneill 450 1.4 jmcneill cons->consinit(&faa, uart_freq); 451 1.1 jmcneill 452 1.1 jmcneill initialized = true; 453 1.1 jmcneill } 454 1.1 jmcneill 455 1.3 jmcneill void 456 1.65 riastrad cpu_startup_hook(void) 457 1.65 riastrad { 458 1.91 skrll #ifdef EFI_RUNTIME 459 1.91 skrll fdt_map_efi_runtime("netbsd,uefi-runtime-code", ARM_EFIRT_MEM_CODE); 460 1.91 skrll fdt_map_efi_runtime("netbsd,uefi-runtime-data", ARM_EFIRT_MEM_DATA); 461 1.91 skrll fdt_map_efi_runtime("netbsd,uefi-runtime-mmio", ARM_EFIRT_MEM_MMIO); 462 1.91 skrll #endif 463 1.65 riastrad 464 1.68 skrll fdtbus_intr_init(); 465 1.68 skrll 466 1.65 riastrad fdt_setup_rndseed(); 467 1.69 riastrad fdt_setup_efirng(); 468 1.65 riastrad } 469 1.65 riastrad 470 1.65 riastrad void 471 1.3 jmcneill delay(u_int us) 472 1.3 jmcneill { 473 1.102 skrll const struct fdt_platform *plat = fdt_platform_find(); 474 1.3 jmcneill 475 1.102 skrll plat->fp_delay(us); 476 1.3 jmcneill } 477 1.34 jmcneill static void 478 1.1 jmcneill fdt_device_register(device_t self, void *aux) 479 1.1 jmcneill { 480 1.102 skrll const struct fdt_platform *plat = fdt_platform_find(); 481 1.1 jmcneill 482 1.75 jmcneill if (device_is_a(self, "armfdt")) { 483 1.8 jmcneill fdt_setup_initrd(); 484 1.8 jmcneill 485 1.75 jmcneill #if NWSDISPLAY > 0 && NGENFB > 0 486 1.75 jmcneill /* 487 1.75 jmcneill * Setup framebuffer console, if present. 488 1.75 jmcneill */ 489 1.75 jmcneill arm_simplefb_preattach(); 490 1.75 jmcneill #endif 491 1.75 jmcneill } 492 1.75 jmcneill 493 1.77 jmcneill #if NWSDISPLAY > 0 && NGENFB > 0 494 1.77 jmcneill if (device_is_a(self, "genfb")) { 495 1.77 jmcneill prop_dictionary_t dict = device_properties(self); 496 1.77 jmcneill prop_dictionary_set_uint64(dict, 497 1.77 jmcneill "simplefb-physaddr", arm_simplefb_physaddr()); 498 1.77 jmcneill } 499 1.109 jmcneill 500 1.109 jmcneill #if NPCI > 0 501 1.109 jmcneill /* 502 1.109 jmcneill * Gross hack to allow handoff of console from genfb to a PCI DRM 503 1.109 jmcneill * display driver. Will match the first device that attaches, which 504 1.109 jmcneill * is not ideal, but better than nothing for now. Similar to how 505 1.109 jmcneill * this is handled on x86. 506 1.109 jmcneill */ 507 1.109 jmcneill if (device_parent(self) != NULL && 508 1.109 jmcneill device_is_a(device_parent(self), "pci")) { 509 1.109 jmcneill static bool found_pci_console = false; 510 1.109 jmcneill struct pci_attach_args *pa = aux; 511 1.109 jmcneill 512 1.109 jmcneill if (PCI_CLASS(pa->pa_class) == PCI_CLASS_DISPLAY && 513 1.109 jmcneill !found_pci_console) { 514 1.109 jmcneill prop_dictionary_t dict = device_properties(self); 515 1.109 jmcneill prop_dictionary_set_bool(dict, "is_console", true); 516 1.109 jmcneill found_pci_console = true; 517 1.109 jmcneill } 518 1.109 jmcneill } 519 1.109 jmcneill #endif 520 1.77 jmcneill #endif 521 1.77 jmcneill 522 1.102 skrll if (plat && plat->fp_device_register) 523 1.102 skrll plat->fp_device_register(self, aux); 524 1.1 jmcneill } 525 1.1 jmcneill 526 1.1 jmcneill static void 527 1.39 bouyer fdt_device_register_post_config(device_t self, void *aux) 528 1.39 bouyer { 529 1.108 jmcneill const struct fdt_platform *plat = fdt_platform_find(); 530 1.108 jmcneill 531 1.108 jmcneill if (plat && plat->fp_device_register_post_config) 532 1.108 jmcneill plat->fp_device_register_post_config(self, aux); 533 1.108 jmcneill 534 1.39 bouyer #if NUKBD > 0 && NWSDISPLAY > 0 535 1.39 bouyer if (device_is_a(self, "wsdisplay")) { 536 1.39 bouyer struct wsdisplay_softc *sc = device_private(self); 537 1.39 bouyer if (wsdisplay_isconsole(sc)) 538 1.39 bouyer ukbd_cnattach(); 539 1.39 bouyer } 540 1.39 bouyer #endif 541 1.39 bouyer } 542 1.39 bouyer 543 1.39 bouyer static void 544 1.1 jmcneill fdt_reset(void) 545 1.1 jmcneill { 546 1.102 skrll const struct fdt_platform *plat = fdt_platform_find(); 547 1.1 jmcneill 548 1.1 jmcneill fdtbus_power_reset(); 549 1.1 jmcneill 550 1.102 skrll if (plat && plat->fp_reset) 551 1.102 skrll plat->fp_reset(); 552 1.1 jmcneill } 553 1.1 jmcneill 554 1.1 jmcneill static void 555 1.1 jmcneill fdt_powerdown(void) 556 1.1 jmcneill { 557 1.1 jmcneill fdtbus_power_poweroff(); 558 1.1 jmcneill } 559 1.76 rin 560 1.76 rin #if BYTE_ORDER == BIG_ENDIAN 561 1.76 rin static void 562 1.76 rin fdt_update_fb_format(void) 563 1.76 rin { 564 1.76 rin int off, len; 565 1.76 rin const char *format, *replace; 566 1.76 rin 567 1.76 rin off = fdt_path_offset(fdt_data, "/chosen"); 568 1.76 rin if (off < 0) 569 1.76 rin return; 570 1.76 rin 571 1.76 rin for (;;) { 572 1.76 rin off = fdt_node_offset_by_compatible(fdt_data, off, 573 1.76 rin "simple-framebuffer"); 574 1.76 rin if (off < 0) 575 1.76 rin return; 576 1.76 rin 577 1.76 rin format = fdt_getprop(fdt_data, off, "format", &len); 578 1.76 rin if (format == NULL) 579 1.76 rin continue; 580 1.76 rin 581 1.76 rin replace = NULL; 582 1.76 rin if (strcmp(format, "a8b8g8r8") == 0) 583 1.76 rin replace = "r8g8b8a8"; 584 1.76 rin else if (strcmp(format, "x8r8g8b8") == 0) 585 1.76 rin replace = "b8g8r8x8"; 586 1.76 rin if (replace != NULL) 587 1.76 rin fdt_setprop(fdt_data, off, "format", replace, 588 1.76 rin strlen(replace) + 1); 589 1.76 rin } 590 1.76 rin } 591 1.76 rin #endif 592