diff --git a/sys/arm/arm/machdep.c b/sys/arm/arm/machdep.c --- a/sys/arm/arm/machdep.c +++ b/sys/arm/arm/machdep.c @@ -115,6 +115,7 @@ static struct trapframe proc0_tf; uint32_t cpu_reset_address = 0; int cold = 1; +int early_boot = 1; vm_offset_t vector_page; /* The address at which the kernel was loaded. Set early in initarm(). */ @@ -624,6 +625,7 @@ init_proc0((void *)kernelstack); arm_vector_init(ARM_VECTORS_HIGH, ARM_VEC_ALL); enable_interrupts(PSR_A); + early_boot = 0; pmap_bootstrap(0); /* Exclude the kernel (and all the things we allocated which immediately diff --git a/sys/dev/vt/hw/simplefb/simplefb.c b/sys/dev/vt/hw/simplefb/simplefb.c --- a/sys/dev/vt/hw/simplefb/simplefb.c +++ b/sys/dev/vt/hw/simplefb/simplefb.c @@ -119,26 +119,57 @@ static struct fb_info local_info; VT_DRIVER_DECLARE(vt_simplefb, vt_simplefb_driver); +#ifdef __arm__ +extern int early_boot; +static bool vt_simplefb_preboot_mapped; +#endif + +static bool +vt_simplefb_node_search(phandle_t parent, phandle_t *nodep) +{ + phandle_t node; + + for (node = OF_child(parent); node != 0; node = OF_peer(node)) { + if (ofw_bus_node_status_okay(node) && + ofw_bus_node_is_compatible(node, "simple-framebuffer")) { + if (nodep != NULL) + *nodep = node; + return (true); + } + } + + return (false); +} + static bool vt_simplefb_node(phandle_t *nodep) { - phandle_t chosen, node; + phandle_t chosen, root; chosen = OF_finddevice("/chosen"); - if (chosen == -1) - return (false); + if (chosen != -1 && vt_simplefb_node_search(chosen, nodep)) + return (true); - for (node = OF_child(chosen); node != 0; node = OF_peer(node)) { - if (ofw_bus_node_is_compatible(node, "simple-framebuffer")) - break; - } - if (node == 0) - return (false); + root = OF_finddevice("/"); + if (root != -1 && vt_simplefb_node_search(root, nodep)) + return (true); + + return (false); +} + +static int +vt_simplefb_get_mem(phandle_t node, bus_addr_t *pbase, bus_size_t *size) +{ + phandle_t mem_node; - if (nodep != NULL) - *nodep = node; + if (OF_hasprop(node, "memory-region")) { + if (OF_getencprop(node, "memory-region", &mem_node, + sizeof(mem_node)) != sizeof(mem_node)) + return (ENXIO); + node = OF_node_from_xref(mem_node); + } - return (true); + return (ofw_reg_to_paddr(node, 0, pbase, size, NULL)); } static int @@ -165,6 +196,7 @@ struct fb_info *sc; phandle_t node; bus_size_t size; + bus_addr_t pbase; int error; /* Initialize softc */ @@ -204,7 +236,24 @@ if (error != 0) return (CN_DEAD); - ofw_reg_to_paddr(node, 0, &sc->fb_pbase, &size, NULL); + if (vt_simplefb_get_mem(node, &pbase, &size) != 0) + return (CN_DEAD); + sc->fb_pbase = pbase; +#ifdef __arm__ + if (early_boot) { + vm_offset_t off, va; + vm_size_t map_size; + + off = pbase & PAGE_MASK; + map_size = round_page(size + off); + va = pmap_preboot_reserve_pages(atop(map_size)); + pmap_preboot_map_attr(trunc_page(pbase), va, map_size, + VM_PROT_READ | VM_PROT_WRITE, + VM_MEMATTR_WRITE_COMBINING); + sc->fb_vbase = va + off; + vt_simplefb_preboot_mapped = true; + } else +#endif sc->fb_vbase = (intptr_t)pmap_mapdev_attr(sc->fb_pbase, size, VM_MEMATTR_WRITE_COMBINING); sc->fb_size = size; @@ -221,6 +270,10 @@ sc = softc; vt_fb_fini(vd, softc); +#ifdef __arm__ + if (vt_simplefb_preboot_mapped) + return; +#endif pmap_unmapdev((void *)sc->fb_vbase, sc->fb_size); }