Path: blob/main/sys/arm/broadcom/bcm2835/bcm2835_vcbus.c
39566 views
/*-1* SPDX-License-Identifier: BSD-2-Clause2*3* Copyright (c) 2019 Kyle Evans <[email protected]>4*5* Redistribution and use in source and binary forms, with or without6* modification, are permitted provided that the following conditions7* are met:8* 1. Redistributions of source code must retain the above copyright9* notice, this list of conditions and the following disclaimer.10* 2. Redistributions in binary form must reproduce the above copyright11* notice, this list of conditions and the following disclaimer in the12* documentation and/or other materials provided with the distribution.13*14* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND15* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE16* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE17* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE18* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL19* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS20* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)21* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT22* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY23* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF24* SUCH DAMAGE.25*/2627#include <sys/cdefs.h>28/*29* This file contains facilities for runtime determination of address space30* mappings for use in DMA/mailbox interactions. This is only used for the31* arm64 SoC because the 32-bit SoC used the same mappings.32*/3334#include <sys/types.h>35#include <sys/systm.h>3637#include <dev/ofw/openfirm.h>38#include <dev/ofw/ofw_bus.h>39#include <dev/ofw/ofw_bus_subr.h>4041#include <machine/bus.h>4243#include <arm/broadcom/bcm2835/bcm2835_vcbus.h>4445/*46* This structure describes mappings that need to take place when transforming47* ARM core addresses into vcbus addresses for use with the DMA/mailbox48* interfaces. Currently, we only deal with peripheral/SDRAM address spaces49* here.50*51* The SDRAM address space is consistently mapped starting at 0 and extends to52* the size of the installed SDRAM.53*54* Peripherals are mapped further up at spots that vary per-SOC.55*/56struct bcm283x_memory_mapping {57vm_paddr_t armc_start;58vm_paddr_t armc_size;59vm_paddr_t vcbus_start;60};6162static struct bcm283x_memory_mapping bcm2835_memmap[] = {63{64/* SDRAM */65.armc_start = 0x00000000,66.armc_size = BCM2835_ARM_IO_BASE,67.vcbus_start = BCM2835_VCBUS_SDRAM_BASE,68},69{70/* Peripherals */71.armc_start = BCM2835_ARM_IO_BASE,72.armc_size = BCM28XX_ARM_IO_SIZE,73.vcbus_start = BCM2835_VCBUS_IO_BASE,74},75{ 0, 0, 0 },76};7778static struct bcm283x_memory_mapping bcm2836_memmap[] = {79{80/* SDRAM */81.armc_start = 0x00000000,82.armc_size = BCM2836_ARM_IO_BASE,83.vcbus_start = BCM2836_VCBUS_SDRAM_BASE,84},85{86/* Peripherals */87.armc_start = BCM2836_ARM_IO_BASE,88.armc_size = BCM28XX_ARM_IO_SIZE,89.vcbus_start = BCM2836_VCBUS_IO_BASE,90},91{ 0, 0, 0 },92};9394static struct bcm283x_memory_mapping bcm2837_memmap[] = {95{96/* SDRAM */97.armc_start = 0x00000000,98.armc_size = BCM2837_ARM_IO_BASE,99.vcbus_start = BCM2837_VCBUS_SDRAM_BASE,100},101{102/* Peripherals */103.armc_start = BCM2837_ARM_IO_BASE,104.armc_size = BCM28XX_ARM_IO_SIZE,105.vcbus_start = BCM2837_VCBUS_IO_BASE,106},107{ 0, 0, 0 },108};109110/*111* The BCM2838 supports up to 4GB of SDRAM, but unfortunately we can still only112* map the first 1GB into the "legacy master view" (vcbus) address space. Thus,113* peripherals can still only access the lower end of SDRAM. For this reason,114* we also capture the main-peripheral busdma restriction below.115*/116static struct bcm283x_memory_mapping bcm2838_memmap[] = {117{118/* SDRAM */119.armc_start = 0x00000000,120.armc_size = 0x40000000,121.vcbus_start = BCM2838_VCBUS_SDRAM_BASE,122},123{124/* Main peripherals */125.armc_start = BCM2838_ARM_IO_BASE,126.armc_size = BCM28XX_ARM_IO_SIZE,127.vcbus_start = BCM2838_VCBUS_IO_BASE,128},129{ 0, 0, 0 },130};131132static struct bcm283x_memory_soc_cfg {133struct bcm283x_memory_mapping *memmap;134const char *soc_compat;135bus_addr_t busdma_lowaddr;136} bcm283x_memory_configs[] = {137/* Legacy */138{139.memmap = bcm2835_memmap,140.soc_compat = "raspberrypi,model-b",141.busdma_lowaddr = BUS_SPACE_MAXADDR_32BIT,142},143/* Modern */144{145.memmap = bcm2835_memmap,146.soc_compat = "brcm,bcm2835",147.busdma_lowaddr = BUS_SPACE_MAXADDR_32BIT,148},149/* Legacy */150{151.memmap = bcm2836_memmap,152.soc_compat = "brcm,bcm2709",153.busdma_lowaddr = BUS_SPACE_MAXADDR_32BIT,154},155/* Modern */156{157.memmap = bcm2836_memmap,158.soc_compat = "brcm,bcm2836",159.busdma_lowaddr = BUS_SPACE_MAXADDR_32BIT,160},161{162.memmap = bcm2837_memmap,163.soc_compat = "brcm,bcm2837",164.busdma_lowaddr = BUS_SPACE_MAXADDR_32BIT,165},166{167.memmap = bcm2838_memmap,168.soc_compat = "brcm,bcm2711",169.busdma_lowaddr = BCM2838_PERIPH_MAXADDR,170},171{172.memmap = bcm2838_memmap,173.soc_compat = "brcm,bcm2838",174.busdma_lowaddr = BCM2838_PERIPH_MAXADDR,175},176};177178static struct bcm283x_memory_soc_cfg *booted_soc_memcfg;179180static struct bcm283x_memory_soc_cfg *181bcm283x_get_current_memcfg(void)182{183phandle_t root;184int i;185186/* We'll cache it once we decide, because it won't change per-boot. */187if (booted_soc_memcfg != NULL)188return (booted_soc_memcfg);189190KASSERT(nitems(bcm283x_memory_configs) != 0,191("No SOC memory configurations enabled!"));192193root = OF_finddevice("/");194for (i = 0; i < nitems(bcm283x_memory_configs); ++i) {195booted_soc_memcfg = &bcm283x_memory_configs[i];196if (bootverbose)197printf("Checking root against %s\n",198booted_soc_memcfg->soc_compat);199if (ofw_bus_node_is_compatible(root,200booted_soc_memcfg->soc_compat))201return (booted_soc_memcfg);202}203204/*205* The kernel doesn't fit the board; we can't really make a reasonable206* guess, as these SOC are different enough that something will blow up207* later.208*/209panic("No suitable SOC memory configuration found.");210}211212#define BCM283X_MEMMAP_ISTERM(ent) \213((ent)->armc_start == 0 && (ent)->armc_size == 0 && \214(ent)->vcbus_start == 0)215216vm_paddr_t217bcm283x_armc_to_vcbus(vm_paddr_t pa)218{219struct bcm283x_memory_soc_cfg *cfg;220struct bcm283x_memory_mapping *map, *ment;221222/* Guaranteed not NULL if we haven't panicked yet. */223cfg = bcm283x_get_current_memcfg();224map = cfg->memmap;225for (ment = map; !BCM283X_MEMMAP_ISTERM(ment); ++ment) {226if (pa >= ment->armc_start &&227pa < ment->armc_start + ment->armc_size) {228return (pa - ment->armc_start) + ment->vcbus_start;229}230}231232/*233* Assume 1:1 mapping for anything else, but complain about it on234* verbose boots.235*/236if (bootverbose)237printf("bcm283x_vcbus: No armc -> vcbus mapping found: %jx\n",238(uintmax_t)pa);239return (pa);240}241242vm_paddr_t243bcm283x_vcbus_to_armc(vm_paddr_t vca)244{245struct bcm283x_memory_soc_cfg *cfg;246struct bcm283x_memory_mapping *map, *ment;247248/* Guaranteed not NULL if we haven't panicked yet. */249cfg = bcm283x_get_current_memcfg();250map = cfg->memmap;251for (ment = map; !BCM283X_MEMMAP_ISTERM(ment); ++ment) {252if (vca >= ment->vcbus_start &&253vca < ment->vcbus_start + ment->armc_size) {254return (vca - ment->vcbus_start) + ment->armc_start;255}256}257258/*259* Assume 1:1 mapping for anything else, but complain about it on260* verbose boots.261*/262if (bootverbose)263printf("bcm283x_vcbus: No vcbus -> armc mapping found: %jx\n",264(uintmax_t)vca);265return (vca);266}267268bus_addr_t269bcm283x_dmabus_peripheral_lowaddr(void)270{271struct bcm283x_memory_soc_cfg *cfg;272273cfg = bcm283x_get_current_memcfg();274return (cfg->busdma_lowaddr);275}276277278