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

Cache object: aeae6c5d05b02cc1a8877161c1f3a800


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