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 106static int bcm_init_platform_data(struct bcm_platform *bp); 107 108static 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 112static 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 116extern int *edata; 117extern int *end; 118 119static struct bcm_platform bcm_platform_data; 120static bool bcm_platform_data_avail = false; 121 122#ifdef CFE 123static struct bcm_nvram_iocfe bcm_cfe_nvram; 124#endif 125 126static 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 131static 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 138static const struct bhnd_core_match bcm_pmu_cores[] = { 139 { BHND_MATCH_CORE(BHND_MFGID_BCM, BHND_COREID_PMU) }, 140}; 141 142struct bcm_platform * 143bcm_get_platform(void) 144{ 145 if (!bcm_platform_data_avail) 146 panic("platform data not available"); 147 148 return (&bcm_platform_data); 149} 150 151static bus_addr_t 152bcm_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 162static bus_size_t 163bcm_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 */ 184static int 185bcm_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 */ 244int 245bcm_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 */ 269static int 270bcm_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 */ 344static int 345bcm_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 459void 460platform_cpu_init() 461{ 462 /* Nothing special */ 463} 464 465static void 466mips_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 532void 533platform_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 576void 577platform_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) 632static void 633bcm_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 652early_putc_t *early_putc = bcm_cfe_eputc; 653#endif /* EARLY_PRINTF */ 654