The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/arm/broadcom/bcm2835/bcm2835_vcbus.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 /*-
    2  * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
    3  *
    4  * Copyright (c) 2019 Kyle Evans <kevans@FreeBSD.org>
    5  *
    6  * Redistribution and use in source and binary forms, with or without
    7  * modification, are permitted provided that the following conditions
    8  * are met:
    9  * 1. Redistributions of source code must retain the above copyright
   10  *    notice, this list of conditions and the following disclaimer.
   11  * 2. Redistributions in binary form must reproduce the above copyright
   12  *    notice, this list of conditions and the following disclaimer in the
   13  *    documentation and/or other materials provided with the distribution.
   14  *
   15  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
   16  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   17  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   18  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
   19  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   20  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   21  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   22  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   23  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   24  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   25  * SUCH DAMAGE.
   26  *
   27  * $FreeBSD$
   28  */
   29 
   30 #include <sys/cdefs.h>
   31 __FBSDID("$FreeBSD$");
   32 
   33 /*
   34  * This file contains facilities for runtime determination of address space
   35  * mappings for use in DMA/mailbox interactions.  This is only used for the
   36  * arm64 SoC because the 32-bit SoC used the same mappings.
   37  */
   38 
   39 #include <sys/types.h>
   40 #include <sys/systm.h>
   41 
   42 #include <dev/ofw/openfirm.h>
   43 #include <dev/ofw/ofw_bus.h>
   44 #include <dev/ofw/ofw_bus_subr.h>
   45 
   46 #include <machine/bus.h>
   47 
   48 #include <arm/broadcom/bcm2835/bcm2835_vcbus.h>
   49 
   50 /*
   51  * This structure describes mappings that need to take place when transforming
   52  * ARM core addresses into vcbus addresses for use with the DMA/mailbox
   53  * interfaces.  Currently, we only deal with peripheral/SDRAM address spaces
   54  * here.
   55  *
   56  * The SDRAM address space is consistently mapped starting at 0 and extends to
   57  * the size of the installed SDRAM.
   58  *
   59  * Peripherals are mapped further up at spots that vary per-SOC.
   60  */
   61 struct bcm283x_memory_mapping {
   62         vm_paddr_t      armc_start;
   63         vm_paddr_t      armc_size;
   64         vm_paddr_t      vcbus_start;
   65 };
   66 
   67 static struct bcm283x_memory_mapping bcm2835_memmap[] = {
   68         {
   69                 /* SDRAM */
   70                 .armc_start = 0x00000000,
   71                 .armc_size = BCM2835_ARM_IO_BASE,
   72                 .vcbus_start = BCM2835_VCBUS_SDRAM_BASE,
   73         },
   74         {
   75                 /* Peripherals */
   76                 .armc_start = BCM2835_ARM_IO_BASE,
   77                 .armc_size  = BCM28XX_ARM_IO_SIZE,
   78                 .vcbus_start = BCM2835_VCBUS_IO_BASE,
   79         },
   80         { 0, 0, 0 },
   81 };
   82 
   83 static struct bcm283x_memory_mapping bcm2836_memmap[] = {
   84         {
   85                 /* SDRAM */
   86                 .armc_start = 0x00000000,
   87                 .armc_size = BCM2836_ARM_IO_BASE,
   88                 .vcbus_start = BCM2836_VCBUS_SDRAM_BASE,
   89         },
   90         {
   91                 /* Peripherals */
   92                 .armc_start = BCM2836_ARM_IO_BASE,
   93                 .armc_size  = BCM28XX_ARM_IO_SIZE,
   94                 .vcbus_start = BCM2836_VCBUS_IO_BASE,
   95         },
   96         { 0, 0, 0 },
   97 };
   98 
   99 static struct bcm283x_memory_mapping bcm2837_memmap[] = {
  100         {
  101                 /* SDRAM */
  102                 .armc_start = 0x00000000,
  103                 .armc_size = BCM2837_ARM_IO_BASE,
  104                 .vcbus_start = BCM2837_VCBUS_SDRAM_BASE,
  105         },
  106         {
  107                 /* Peripherals */
  108                 .armc_start = BCM2837_ARM_IO_BASE,
  109                 .armc_size  = BCM28XX_ARM_IO_SIZE,
  110                 .vcbus_start = BCM2837_VCBUS_IO_BASE,
  111         },
  112         { 0, 0, 0 },
  113 };
  114 
  115 /*
  116  * The BCM2838 supports up to 4GB of SDRAM, but unfortunately we can still only
  117  * map the first 1GB into the "legacy master view" (vcbus) address space.  Thus,
  118  * peripherals can still only access the lower end of SDRAM.  For this reason,
  119  * we also capture the main-peripheral busdma restriction below.
  120  */
  121 static struct bcm283x_memory_mapping bcm2838_memmap[] = {
  122         {
  123                 /* SDRAM */
  124                 .armc_start = 0x00000000,
  125                 .armc_size = 0x40000000,
  126                 .vcbus_start = BCM2838_VCBUS_SDRAM_BASE,
  127         },
  128         {
  129                 /* Main peripherals */
  130                 .armc_start = BCM2838_ARM_IO_BASE,
  131                 .armc_size = BCM28XX_ARM_IO_SIZE,
  132                 .vcbus_start = BCM2838_VCBUS_IO_BASE,
  133         },
  134         { 0, 0, 0 },
  135 };
  136 
  137 static struct bcm283x_memory_soc_cfg {
  138         struct bcm283x_memory_mapping   *memmap;
  139         const char                      *soc_compat;
  140         bus_addr_t                       busdma_lowaddr;
  141 } bcm283x_memory_configs[] = {
  142         /* Legacy */
  143         {
  144                 .memmap = bcm2835_memmap,
  145                 .soc_compat = "raspberrypi,model-b",
  146                 .busdma_lowaddr = BUS_SPACE_MAXADDR_32BIT,
  147         },
  148         /* Modern */
  149         {
  150                 .memmap = bcm2835_memmap,
  151                 .soc_compat = "brcm,bcm2835",
  152                 .busdma_lowaddr = BUS_SPACE_MAXADDR_32BIT,
  153         },
  154         /* Legacy */
  155         {
  156                 .memmap = bcm2836_memmap,
  157                 .soc_compat = "brcm,bcm2709",
  158                 .busdma_lowaddr = BUS_SPACE_MAXADDR_32BIT,
  159         },
  160         /* Modern */
  161         {
  162                 .memmap = bcm2836_memmap,
  163                 .soc_compat = "brcm,bcm2836",
  164                 .busdma_lowaddr = BUS_SPACE_MAXADDR_32BIT,
  165         },
  166         {
  167                 .memmap = bcm2837_memmap,
  168                 .soc_compat = "brcm,bcm2837",
  169                 .busdma_lowaddr = BUS_SPACE_MAXADDR_32BIT,
  170         },
  171         {
  172                 .memmap = bcm2838_memmap,
  173                 .soc_compat = "brcm,bcm2711",
  174                 .busdma_lowaddr = BCM2838_PERIPH_MAXADDR,
  175         },
  176         {
  177                 .memmap = bcm2838_memmap,
  178                 .soc_compat = "brcm,bcm2838",
  179                 .busdma_lowaddr = BCM2838_PERIPH_MAXADDR,
  180         },
  181 };
  182 
  183 static struct bcm283x_memory_soc_cfg *booted_soc_memcfg;
  184 
  185 static struct bcm283x_memory_soc_cfg *
  186 bcm283x_get_current_memcfg(void)
  187 {
  188         phandle_t root;
  189         int i;
  190 
  191         /* We'll cache it once we decide, because it won't change per-boot. */
  192         if (booted_soc_memcfg != NULL)
  193                 return (booted_soc_memcfg);
  194 
  195         KASSERT(nitems(bcm283x_memory_configs) != 0,
  196             ("No SOC memory configurations enabled!"));
  197 
  198         root = OF_finddevice("/");
  199         for (i = 0; i < nitems(bcm283x_memory_configs); ++i) {
  200                 booted_soc_memcfg = &bcm283x_memory_configs[i];
  201                 if (bootverbose)
  202                         printf("Checking root against %s\n",
  203                             booted_soc_memcfg->soc_compat);
  204                 if (ofw_bus_node_is_compatible(root,
  205                     booted_soc_memcfg->soc_compat))
  206                         return (booted_soc_memcfg);
  207         }
  208 
  209         /*
  210          * The kernel doesn't fit the board; we can't really make a reasonable
  211          * guess, as these SOC are different enough that something will blow up
  212          * later.
  213          */
  214         panic("No suitable SOC memory configuration found.");
  215 }
  216 
  217 #define BCM283X_MEMMAP_ISTERM(ent)      \
  218     ((ent)->armc_start == 0 && (ent)->armc_size == 0 && \
  219     (ent)->vcbus_start == 0)
  220 
  221 vm_paddr_t
  222 bcm283x_armc_to_vcbus(vm_paddr_t pa)
  223 {
  224         struct bcm283x_memory_soc_cfg *cfg;
  225         struct bcm283x_memory_mapping *map, *ment;
  226 
  227         /* Guaranteed not NULL if we haven't panicked yet. */
  228         cfg = bcm283x_get_current_memcfg();
  229         map = cfg->memmap;
  230         for (ment = map; !BCM283X_MEMMAP_ISTERM(ment); ++ment) {
  231                 if (pa >= ment->armc_start &&
  232                     pa < ment->armc_start + ment->armc_size) {
  233                         return (pa - ment->armc_start) + ment->vcbus_start;
  234                 }
  235         }
  236 
  237         /*
  238          * Assume 1:1 mapping for anything else, but complain about it on
  239          * verbose boots.
  240          */
  241         if (bootverbose)
  242                 printf("bcm283x_vcbus: No armc -> vcbus mapping found: %jx\n",
  243                     (uintmax_t)pa);
  244         return (pa);
  245 }
  246 
  247 vm_paddr_t
  248 bcm283x_vcbus_to_armc(vm_paddr_t vca)
  249 {
  250         struct bcm283x_memory_soc_cfg *cfg;
  251         struct bcm283x_memory_mapping *map, *ment;
  252 
  253         /* Guaranteed not NULL if we haven't panicked yet. */
  254         cfg = bcm283x_get_current_memcfg();
  255         map = cfg->memmap;
  256         for (ment = map; !BCM283X_MEMMAP_ISTERM(ment); ++ment) {
  257                 if (vca >= ment->vcbus_start &&
  258                     vca < ment->vcbus_start + ment->armc_size) {
  259                         return (vca - ment->vcbus_start) + ment->armc_start;
  260                 }
  261         }
  262 
  263         /*
  264          * Assume 1:1 mapping for anything else, but complain about it on
  265          * verbose boots.
  266          */
  267         if (bootverbose)
  268                 printf("bcm283x_vcbus: No vcbus -> armc mapping found: %jx\n",
  269                     (uintmax_t)vca);
  270         return (vca);
  271 }
  272 
  273 bus_addr_t
  274 bcm283x_dmabus_peripheral_lowaddr(void)
  275 {
  276         struct bcm283x_memory_soc_cfg *cfg;
  277 
  278         cfg = bcm283x_get_current_memcfg();
  279         return (cfg->busdma_lowaddr);
  280 }

Cache object: c0c0e85add6c9a704fded757db7563ab


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.