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_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 104static int bcm_init_platform_data(struct bcm_platform *bp); 105 106static 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 110static 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 114extern int *edata; 115extern int *end; 116 117static struct bcm_platform bcm_platform_data; 118static bool bcm_platform_data_avail = false; 119 120#ifdef CFE 121static struct bcm_nvram_iocfe bcm_cfe_nvram; 122#endif 123 124static 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 129static 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 136static const struct bhnd_core_match bcm_pmu_cores[] = { 137 { BHND_MATCH_CORE(BHND_MFGID_BCM, BHND_COREID_PMU) }, 138}; 139 140struct bcm_platform * 141bcm_get_platform(void) 142{ 143 if (!bcm_platform_data_avail) 144 panic("platform data not available"); 145 146 return (&bcm_platform_data); 147} 148 149static bus_addr_t 150bcm_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 160static bus_size_t 161bcm_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 */ 182static int 183bcm_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 */ 242int 243bcm_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 */ 267static int 268bcm_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 */ 342static int 343bcm_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 457void 458platform_cpu_init() 459{ 460 /* Nothing special */ 461} 462 463static void 464mips_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 530void 531platform_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 574void 575platform_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) 630static void 631bcm_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 650early_putc_t *early_putc = bcm_cfe_eputc; 651#endif /* EARLY_PRINTF */ 652