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/mips/broadcom/bcm_machdep.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  * Copyright (c) 2007 Bruce M. Simpson.
    3  * Copyright (c) 2016 Michael Zhilin <mizhka@gmail.com>
    4  * Copyright (c) 2016 Landon Fuller <landonf@FreeBSD.org>
    5  * Copyright (c) 2017 The FreeBSD Foundation
    6  * All rights reserved.
    7  *
    8  * Portions of this software were developed by Landon Fuller
    9  * under sponsorship from the FreeBSD Foundation.
   10  *
   11  * Redistribution and use in source and binary forms, with or without
   12  * modification, are permitted provided that the following conditions
   13  * are met:
   14  * 1. Redistributions of source code must retain the above copyright
   15  *    notice, this list of conditions and the following disclaimer.
   16  * 2. Redistributions in binary form must reproduce the above copyright
   17  *    notice, this list of conditions and the following disclaimer in the
   18  *    documentation and/or other materials provided with the distribution.
   19  *
   20  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
   21  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   22  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   23  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
   24  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   25  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   26  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   27  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   28  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   29  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   30  * SUCH DAMAGE.
   31  */
   32 
   33 #include <sys/cdefs.h>
   34 __FBSDID("$FreeBSD$");
   35 
   36 #include "opt_ddb.h"
   37 
   38 #include <sys/param.h>
   39 #include <sys/conf.h>
   40 #include <sys/kernel.h>
   41 #include <sys/systm.h>
   42 #include <sys/imgact.h>
   43 #include <sys/bio.h>
   44 #include <sys/buf.h>
   45 #include <sys/bus.h>
   46 #include <sys/cpu.h>
   47 #include <sys/cons.h>
   48 #include <sys/exec.h>
   49 #include <sys/ucontext.h>
   50 #include <sys/proc.h>
   51 #include <sys/kdb.h>
   52 #include <sys/ptrace.h>
   53 #include <sys/reboot.h>
   54 #include <sys/signalvar.h>
   55 #include <sys/sysent.h>
   56 #include <sys/sysproto.h>
   57 #include <sys/user.h>
   58 
   59 #include <vm/vm.h>
   60 #include <vm/vm_param.h>
   61 #include <vm/vm_object.h>
   62 #include <vm/vm_page.h>
   63 #include <vm/vm_phys.h>
   64 #include <vm/vm_dumpset.h>
   65 
   66 #include <machine/cache.h>
   67 #include <machine/clock.h>
   68 #include <machine/cpu.h>
   69 #include <machine/cpuinfo.h>
   70 #include <machine/cpufunc.h>
   71 #include <machine/cpuregs.h>
   72 #include <machine/hwfunc.h>
   73 #include <machine/intr_machdep.h>
   74 #include <machine/locore.h>
   75 #include <machine/md_var.h>
   76 #include <machine/pte.h>
   77 #include <machine/sigframe.h>
   78 #include <machine/trap.h>
   79 
   80 #include <dev/bhnd/bhnd.h>
   81 #include <dev/bhnd/bhndreg.h>
   82 #include <dev/bhnd/bhnd_eromvar.h>
   83 
   84 #include <dev/bhnd/bcma/bcma_eromvar.h>
   85 
   86 #include <dev/bhnd/siba/sibareg.h>
   87 #include <dev/bhnd/siba/sibavar.h>
   88 
   89 #include <dev/bhnd/cores/chipc/chipcreg.h>
   90 #include <dev/bhnd/cores/pmu/bhnd_pmureg.h>
   91 
   92 #include "bcm_machdep.h"
   93 #include "bcm_bmips_exts.h"
   94 
   95 #ifdef CFE
   96 #include <dev/cfe/cfe_api.h>
   97 #include <dev/cfe/cfe_error.h>
   98 #endif
   99 
  100 #if 0
  101 #define BCM_TRACE(_fmt, ...)    printf(_fmt, ##__VA_ARGS__)
  102 #else
  103 #define BCM_TRACE(_fmt, ...)
  104 #endif
  105 
  106 static int      bcm_init_platform_data(struct bcm_platform *bp);
  107 
  108 static int      bcm_find_core(struct bcm_platform *bp,
  109                     const struct bhnd_core_match *descs, size_t num_descs,
  110                     struct bhnd_core_info *info, uintptr_t *addr);
  111 
  112 static int      bcm_erom_probe_and_attach(bhnd_erom_class_t **erom_cls,
  113                     kobj_ops_t erom_ops, bhnd_erom_t *erom, size_t esize,
  114                     struct bhnd_erom_io *eio, struct bhnd_chipid *cid);
  115 
  116 extern int      *edata;
  117 extern int      *end;
  118 
  119 static struct bcm_platform       bcm_platform_data;
  120 static bool                      bcm_platform_data_avail = false;
  121 
  122 #ifdef CFE
  123 static struct bcm_nvram_iocfe    bcm_cfe_nvram;
  124 #endif
  125 
  126 static const struct bhnd_core_match bcm_chipc_cores[] = {
  127         { BHND_MATCH_CORE(BHND_MFGID_BCM,       BHND_COREID_CC)         },
  128         { BHND_MATCH_CORE(BHND_MFGID_BCM,       BHND_COREID_4706_CC)    },
  129 };
  130 
  131 static const struct bhnd_core_match bcm_cpu0_cores[] = {
  132         {
  133                 BHND_MATCH_CORE_CLASS(BHND_DEVCLASS_CPU),
  134                 BHND_MATCH_CORE_UNIT(0)
  135         }
  136 };
  137 
  138 static const struct bhnd_core_match bcm_pmu_cores[] = {
  139         { BHND_MATCH_CORE(BHND_MFGID_BCM,       BHND_COREID_PMU)        },
  140 };
  141 
  142 struct bcm_platform *
  143 bcm_get_platform(void)
  144 {
  145         if (!bcm_platform_data_avail)
  146                 panic("platform data not available");
  147 
  148         return (&bcm_platform_data);
  149 }
  150 
  151 static bus_addr_t
  152 bcm_get_bus_addr(void)
  153 {
  154         long maddr;
  155 
  156         if (resource_long_value("bhnd", 0, "maddr", &maddr) == 0)
  157                 return ((u_long)maddr);
  158 
  159         return (BHND_DEFAULT_CHIPC_ADDR);
  160 }
  161 
  162 static bus_size_t
  163 bcm_get_bus_size(void)
  164 {
  165         long msize;
  166 
  167         if (resource_long_value("bhnd", 0, "msize", &msize) == 0)
  168                 return ((u_long)msize);
  169 
  170         return (BHND_DEFAULT_ENUM_SIZE);
  171 }
  172 
  173 /**
  174  * Search the device enumeration table for a core matching @p descs,
  175  * 
  176  * @param       bp              Platform state containing a valid EROM parser.
  177  * @param       descs           The core match descriptor table.
  178  * @param       num_descs       The number of match descriptors in @p descs.
  179  * @param[out]  info            If non-NULL, will be populated with the core
  180  *                              info.
  181  * @param[out]  addr            If non-NULL, will be populated with the core's
  182  *                              physical register address.
  183  */
  184 static int
  185 bcm_find_core(struct bcm_platform *bp, const struct bhnd_core_match *descs,
  186     size_t num_descs, struct bhnd_core_info *info, uintptr_t *addr)
  187 {
  188         bhnd_addr_t             b_addr;
  189         bhnd_size_t             b_size;
  190         int                     error;
  191 
  192         /* Fetch core info */
  193         for (size_t i = 0; i < num_descs; i++) {
  194                 error = bhnd_erom_lookup_core_addr(&bp->erom.obj, &descs[i],
  195                     BHND_PORT_DEVICE, 0, 0, info, &b_addr, &b_size);
  196 
  197                 /* Terminate search on first match */
  198                 if (error == 0)
  199                         break;
  200 
  201                 /* Terminate on first error (other than core not found) */
  202                 if (error != ENOENT)
  203                         return (error);
  204 
  205                 /* Continue search ... */
  206         }
  207 
  208         /* Provide the core's base address */
  209         if (addr != NULL && b_addr > UINTPTR_MAX) {
  210                 BCM_ERR("core address %#jx overflows native address width\n",
  211                     (uintmax_t)b_addr);
  212                 return (ERANGE);
  213         }
  214 
  215         if (addr != NULL)
  216                 *addr = b_addr;
  217 
  218         return (0);
  219 }
  220 
  221 /**
  222  * Read a variable directly from NVRAM, decoding as @p type.
  223  *
  224  * @param               bp      Platform state.
  225  * @param               name    The raw name of the variable to be fetched,
  226  *                              including any device path (/pci/1/1/varname) or
  227  *                              alias prefix (0:varname).
  228  * @param[out]          buf     On success, the requested value will be written
  229  *                              to this buffer. This argment may be NULL if
  230  *                              the value is not desired.
  231  * @param[in,out]       len     The capacity of @p buf. On success, will be set
  232  *                              to the actual size of the requested value.
  233  * @param               type    The data type to be written to @p buf.
  234  *
  235  * @retval 0            success
  236  * @retval ENOMEM       If @p buf is non-NULL and a buffer of @p len is too
  237  *                      small to hold the requested value.
  238  * @retval ENOENT       If @p name is not found.
  239  * @retval EFTYPE       If the variable data cannot be coerced to @p type.
  240  * @retval ERANGE       If value coercion would overflow @p type.
  241  * @retval non-zero     If parsing NVRAM otherwise fails, a regular unix error
  242  *                      code will be returned.
  243  */
  244 int
  245 bcm_get_nvram(struct bcm_platform *bp, const char *name, void *buf, size_t *len,
  246     bhnd_nvram_type type)
  247 {
  248         if (bp->nvram_io == NULL || bp->nvram_cls == NULL)
  249                 return (ENOENT);
  250 
  251         return (bhnd_nvram_data_getvar_direct(bp->nvram_cls, bp->nvram_io, name,
  252             buf, len, type));
  253 }
  254 
  255 /**
  256  * Probe and attach a bhnd_erom parser instance for the bhnd bus.
  257  * 
  258  * @param[out]  erom_cls        The probed EROM class.
  259  * @param[out]  erom_ops        The storage to be used when compiling
  260  *                              @p erom_cls.
  261  * @param[out]  erom            The storage to be used when initializing the
  262  *                              static instance of @p erom_cls.
  263  * @param       esize           The total available number of bytes allocated
  264  *                              for @p erom. If this is less than is required
  265  *                              by @p erom_cls ENOMEM will be returned.
  266  * @param       eio             EROM I/O callbacks to be used.
  267  * @param[out]  cid             On success, the probed chip identification.
  268  */
  269 static int
  270 bcm_erom_probe_and_attach(bhnd_erom_class_t **erom_cls, kobj_ops_t erom_ops,
  271     bhnd_erom_t *erom, size_t esize, struct bhnd_erom_io *eio,
  272     struct bhnd_chipid *cid)
  273 {
  274         bhnd_erom_class_t       **clsp;
  275         bus_addr_t                bus_addr;
  276         int                       error, prio, result;
  277 
  278         *erom_cls = NULL;
  279         prio = 0;
  280 
  281         /* Map our first bus core for the erom probe */
  282         bus_addr = bcm_get_bus_addr();
  283         if ((error = bhnd_erom_io_map(eio, bus_addr, BHND_DEFAULT_CORE_SIZE))) {
  284                 BCM_ERR("failed to map first core at %#jx+%#jx: %d\n",
  285                     (uintmax_t)bus_addr, (uintmax_t)BHND_DEFAULT_CORE_SIZE,
  286                     error);
  287 
  288                 return (error);
  289         }
  290 
  291         SET_FOREACH(clsp, bhnd_erom_class_set) {
  292                 struct bhnd_chipid       pcid;
  293                 bhnd_erom_class_t       *cls;
  294                 struct kobj_ops          kops;
  295 
  296                 cls = *clsp;
  297 
  298                 /* Compile the class' ops table */
  299                 kobj_class_compile_static(cls, &kops);
  300 
  301                 /* Probe the bus address */
  302                 result = bhnd_erom_probe(cls, eio, NULL, &pcid);
  303 
  304                 /* Drop pointer to stack allocated ops table */
  305                 cls->ops = NULL;
  306 
  307                 /* The parser did not match if an error was returned */
  308                 if (result > 0)
  309                         continue;
  310 
  311                 /* Check for a new highest priority match */
  312                 if (*erom_cls == NULL || result > prio) {
  313                         prio = result;
  314 
  315                         *cid = pcid;
  316                         *erom_cls = cls;
  317                 }
  318 
  319                 /* Terminate immediately on BUS_PROBE_SPECIFIC */
  320                 if (result == BUS_PROBE_SPECIFIC)
  321                         break;
  322         }
  323 
  324         /* Valid EROM class probed? */
  325         if (*erom_cls == NULL) {
  326                 BCM_ERR("no erom parser found for root bus at %#jx\n", 
  327                     (uintmax_t)bus_addr);
  328 
  329                 return (ENOENT);
  330         }
  331 
  332         /* Using the provided storage, recompile the erom class ... */
  333         kobj_class_compile_static(*erom_cls, erom_ops);
  334 
  335         /* ... and initialize the erom parser instance */
  336         error = bhnd_erom_init_static(*erom_cls, erom, esize, cid, eio);
  337 
  338         return (error);
  339 }
  340 
  341 /**
  342  * Populate platform configuration data.
  343  */
  344 static int
  345 bcm_init_platform_data(struct bcm_platform *bp)
  346 {
  347         bus_addr_t              bus_addr, bus_size;
  348         bus_space_tag_t         erom_bst;
  349         bus_space_handle_t      erom_bsh;
  350         bool                    aob, pmu;
  351         int                     error;
  352 
  353         bus_addr = bcm_get_bus_addr();
  354         bus_size = bcm_get_bus_size();
  355 
  356 #ifdef CFE
  357         /* Fetch CFE console handle (if any). Must be initialized before
  358          * any calls to printf/early_putc. */
  359         if ((bp->cfe_console = cfe_getstdhandle(CFE_STDHANDLE_CONSOLE)) < 0)
  360                 bp->cfe_console = -1;
  361 
  362         /* Probe CFE NVRAM sources */
  363         bp->nvram_io = &bcm_cfe_nvram.io;
  364         error = bcm_nvram_find_cfedev(&bcm_cfe_nvram, &bp->nvram_cls);
  365         if (error) {
  366                 bp->nvram_io = NULL;
  367                 bp->nvram_cls = NULL;
  368         }
  369 #endif /* CFE */
  370 
  371         /* Probe and attach device table provider, populating our
  372          * chip identification */
  373         erom_bst = mips_bus_space_generic;
  374         erom_bsh = BCM_SOC_BSH(bus_addr, 0);
  375 
  376         error = bhnd_erom_iobus_init(&bp->erom_io, bus_addr, bus_size, erom_bst,
  377             erom_bsh);
  378         if (error) {
  379                 BCM_ERR("failed to initialize erom I/O callbacks: %d\n", error);
  380                 return (error);
  381         }
  382 
  383         error = bcm_erom_probe_and_attach(&bp->erom_impl, &bp->erom_ops,
  384             &bp->erom.obj, sizeof(bp->erom), &bp->erom_io.eio, &bp->cid);
  385         if (error) {
  386                 BCM_ERR("error attaching erom parser: %d\n", error);
  387                 bhnd_erom_io_fini(&bp->erom_io.eio);
  388                 return (error);
  389         }
  390 
  391         if (bootverbose)
  392                 bhnd_erom_dump(&bp->erom.obj);
  393 
  394         /* Fetch chipcommon core info */
  395         error = bcm_find_core(bp, bcm_chipc_cores, nitems(bcm_chipc_cores),
  396             &bp->cc_id, &bp->cc_addr);
  397         if (error) {
  398                 BCM_ERR("error locating chipc core: %d\n", error);
  399                 return (error);
  400         }
  401 
  402         /* Fetch chipc capability flags */
  403         bp->cc_caps = BCM_SOC_READ_4(bp->cc_addr, CHIPC_CAPABILITIES);
  404         bp->cc_caps_ext = 0x0;  
  405 
  406         if (CHIPC_HWREV_HAS_CAP_EXT(bp->cc_id.hwrev))
  407                 bp->cc_caps_ext = BCM_CHIPC_READ_4(bp, CHIPC_CAPABILITIES_EXT);
  408 
  409         /* Fetch PMU info */
  410         pmu = CHIPC_GET_FLAG(bp->cc_caps, CHIPC_CAP_PMU);
  411         aob = CHIPC_GET_FLAG(bp->cc_caps_ext, CHIPC_CAP2_AOB);
  412 
  413         if (pmu && aob) {
  414                 /* PMU block mapped to a PMU core on the Always-on-Bus (aob) */
  415                 error = bcm_find_core(bp, bcm_pmu_cores, nitems(bcm_pmu_cores),
  416                     &bp->pmu_id,  &bp->pmu_addr);
  417                 if (error) {
  418                         BCM_ERR("error locating pmu core: %d\n", error);
  419                         return (error);
  420                 }
  421         } else if (pmu) {
  422                 /* PMU block mapped to chipc */
  423                 bp->pmu_addr = bp->cc_addr;
  424                 bp->pmu_id = bp->cc_id;
  425         } else {
  426                 /* No PMU */
  427                 bp->pmu_addr = 0x0;
  428                 memset(&bp->pmu_id, 0, sizeof(bp->pmu_id));
  429         }
  430 
  431         /* Initialize PMU query state */
  432         if (pmu) {
  433                 error = bhnd_pmu_query_init(&bp->pmu, NULL, bp->cid,
  434                     &bcm_pmu_soc_io, bp);
  435                 if (error) {
  436                         BCM_ERR("bhnd_pmu_query_init() failed: %d\n", error);
  437                         return (error);
  438                 }
  439         }
  440 
  441         /* Find CPU core info */
  442         error = bcm_find_core(bp, bcm_cpu0_cores, nitems(bcm_cpu0_cores),
  443             &bp->cpu_id,  &bp->cpu_addr);
  444         if (error) {
  445                 BCM_ERR("error locating CPU core: %d\n", error);
  446                 return (error);
  447         }
  448 
  449         /* Initialize our platform service registry */
  450         if ((error = bhnd_service_registry_init(&bp->services))) {
  451                 BCM_ERR("error initializing service registry: %d\n", error);
  452                 return (error);
  453         }
  454 
  455         bcm_platform_data_avail = true;
  456         return (0);
  457 }
  458 
  459 void
  460 platform_cpu_init()
  461 {
  462         /* Nothing special */
  463 }
  464 
  465 static void
  466 mips_init(void)
  467 {
  468         int i, j;
  469 
  470         printf("entry: mips_init()\n");
  471 
  472 #ifdef CFE
  473         /*
  474          * Query DRAM memory map from CFE.
  475          */
  476         physmem = 0;
  477         for (i = 0; i < 10; i += 2) {
  478                 int result;
  479                 uint64_t addr, len, type;
  480 
  481                 result = cfe_enummem(i / 2, 0, &addr, &len, &type);
  482                 if (result < 0) {
  483                         BCM_TRACE("There is no phys memory for: %d\n", i);
  484                         phys_avail[i] = phys_avail[i + 1] = 0;
  485                         break;
  486                 }
  487                 if (type != CFE_MI_AVAILABLE) {
  488                         BCM_TRACE("phys memory is not available: %d\n", i);
  489                         continue;
  490                 }
  491 
  492                 phys_avail[i] = addr;
  493                 if (i == 0 && addr == 0) {
  494                         /*
  495                          * If this is the first physical memory segment probed
  496                          * from CFE, omit the region at the start of physical
  497                          * memory where the kernel has been loaded.
  498                          */
  499                         phys_avail[i] += MIPS_KSEG0_TO_PHYS(kernel_kseg0_end);
  500                 }
  501                 
  502                 BCM_TRACE("phys memory is available for: %d\n", i);
  503                 BCM_TRACE(" => addr =  %jx\n", addr);
  504                 BCM_TRACE(" => len =  %jd\n", len);
  505 
  506                 phys_avail[i + 1] = addr + len;
  507                 physmem += len;
  508         }
  509 
  510         BCM_TRACE("Total phys memory is : %ld\n", physmem);
  511         realmem = btoc(physmem);
  512 #endif
  513 
  514         for (j = 0; j < i; j++)
  515                 dump_avail[j] = phys_avail[j];
  516 
  517         physmem = realmem;
  518 
  519         init_param1();
  520         init_param2(physmem);
  521         mips_cpu_init();
  522         pmap_bootstrap();
  523         mips_proc0_init();
  524         mutex_init();
  525         kdb_init();
  526 #ifdef KDB
  527         if (boothowto & RB_KDB)
  528                 kdb_enter(KDB_WHY_BOOTFLAGS, "Boot flags requested debugger");
  529 #endif
  530 }
  531 
  532 void
  533 platform_reset(void)
  534 {
  535         struct bcm_platform     *bp;
  536         bool                     bcm4785war;
  537 
  538         printf("bcm::platform_reset()\n");
  539         intr_disable();
  540 
  541 #ifdef CFE
  542         /* Fall back on CFE if reset requested during platform
  543          * data initialization */
  544         if (!bcm_platform_data_avail) {
  545                 cfe_exit(0, 0);
  546                 while (1);
  547         }
  548 #endif
  549 
  550         bp = bcm_get_platform();
  551         bcm4785war = false;
  552 
  553         /* Handle BCM4785-specific behavior */
  554         if (bp->cid.chip_id == BHND_CHIPID_BCM4785) {
  555                 bcm4785war = true;
  556 
  557                 /* Switch to async mode */
  558                 bcm_bmips_wr_pllcfg3(BMIPS_BCMCFG_PLLCFG3_SM);
  559         }
  560 
  561         /* Set watchdog (PMU or ChipCommon) */
  562         if (bp->pmu_addr != 0x0) {
  563                 BCM_PMU_WRITE_4(bp, BHND_PMU_WATCHDOG, 1);
  564         } else
  565                 BCM_CHIPC_WRITE_4(bp, CHIPC_WATCHDOG, 1);
  566 
  567         /* BCM4785 */
  568         if (bcm4785war) {
  569                 mips_sync();
  570                 __asm __volatile("wait");
  571         }
  572 
  573         while (1);
  574 }
  575 
  576 void
  577 platform_start(__register_t a0, __register_t a1, __register_t a2,
  578                __register_t a3)
  579 {
  580         vm_offset_t              kernend;
  581         uint64_t                 platform_counter_freq;
  582         int                      error;
  583 
  584         /* clear the BSS and SBSS segments */
  585         kernend = (vm_offset_t)&end;
  586         memset(&edata, 0, kernend - (vm_offset_t)(&edata));
  587 
  588         mips_postboot_fixup();
  589 
  590         /* Initialize pcpu stuff */
  591         mips_pcpu0_init();
  592 
  593 #ifdef CFE
  594         /*
  595          * Initialize CFE firmware trampolines. This must be done
  596          * before any CFE APIs are called, including writing
  597          * to the CFE console.
  598          *
  599          * CFE passes the following values in registers:
  600          * a0: firmware handle
  601          * a2: firmware entry point
  602          * a3: entry point seal
  603          */
  604         if (a3 == CFE_EPTSEAL)
  605                 cfe_init(a0, a2);
  606 #endif
  607 
  608         /* Init BCM platform data */
  609         if ((error = bcm_init_platform_data(&bcm_platform_data)))
  610                 panic("bcm_init_platform_data() failed: %d", error);
  611 
  612         platform_counter_freq = bcm_get_cpufreq(bcm_get_platform());
  613 
  614         /* CP0 ticks every two cycles */
  615         mips_timer_early_init(platform_counter_freq / 2);
  616 
  617         cninit();
  618 
  619         mips_init();
  620 
  621         mips_timer_init_params(platform_counter_freq, 1);
  622 }
  623 
  624 /*
  625  * CFE-based EARLY_PRINTF support. To use, add the following to the kernel
  626  * config:
  627  *      option EARLY_PRINTF
  628  *      option CFE
  629  *      device cfe
  630  */
  631 #if defined(EARLY_PRINTF) && defined(CFE)
  632 static void
  633 bcm_cfe_eputc(int c)
  634 {
  635         unsigned char   ch;
  636         int             handle;
  637 
  638         ch = (unsigned char) c;
  639 
  640         /* bcm_get_platform() cannot be used here, as we may be called
  641          * from bcm_init_platform_data(). */
  642         if ((handle = bcm_platform_data.cfe_console) < 0)
  643                 return;
  644 
  645         if (ch == '\n')
  646                 early_putc('\r');
  647 
  648         while ((cfe_write(handle, &ch, 1)) == 0)
  649                 continue;
  650 }
  651 
  652 early_putc_t *early_putc = bcm_cfe_eputc;
  653 #endif /* EARLY_PRINTF */

Cache object: 19dcfea0c161e75f64e0f6e785ac5858


[ 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.