1 /* $NetBSD: machdep.c,v 1.6 2026/06/22 12:34:19 rkujawa Exp $ */ 2 3 /* 4 * Copyright (c) 2012, 2014, 2024, 2026 The NetBSD Foundation, Inc. 5 * All rights reserved. 6 * 7 * This code is derived from software contributed to The NetBSD Foundation 8 * by Radoslaw Kujawa. 9 * 10 * Redistribution and use in source and binary forms, with or without 11 * modification, are permitted provided that the following conditions 12 * are met: 13 * 1. Redistributions of source code must retain the above copyright 14 * notice, this list of conditions and the following disclaimer. 15 * 2. Redistributions in binary form must reproduce the above copyright 16 * notice, this list of conditions and the following disclaimer in the 17 * documentation and/or other materials provided with the distribution. 18 * 19 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 20 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 21 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 22 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 23 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 24 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 25 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 28 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 */ 30 31 /* 32 * Copyright 2001, 2002 Wasabi Systems, Inc. 33 * All rights reserved. 34 * 35 * Written by Eduardo Horvath and Simon Burge for Wasabi Systems, Inc. 36 * 37 * Redistribution and use in source and binary forms, with or without 38 * modification, are permitted provided that the following conditions 39 * are met: 40 * 1. Redistributions of source code must retain the above copyright 41 * notice, this list of conditions and the following disclaimer. 42 * 2. Redistributions in binary form must reproduce the above copyright 43 * notice, this list of conditions and the following disclaimer in the 44 * documentation and/or other materials provided with the distribution. 45 * 3. All advertising materials mentioning features or use of this software 46 * must display the following acknowledgement: 47 * This product includes software developed for the NetBSD Project by 48 * Wasabi Systems, Inc. 49 * 4. The name of Wasabi Systems, Inc. may not be used to endorse 50 * or promote products derived from this software without specific prior 51 * written permission. 52 * 53 * THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, INC. ``AS IS'' AND 54 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 55 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 56 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL WASABI SYSTEMS, INC 57 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 58 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 59 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 60 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 61 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 62 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 63 * POSSIBILITY OF SUCH DAMAGE. 64 */ 65 /* 66 * Copyright (C) 1995, 1996 Wolfgang Solfrank. 67 * Copyright (C) 1995, 1996 TooLs GmbH. 68 * All rights reserved. 69 * 70 * Redistribution and use in source and binary forms, with or without 71 * modification, are permitted provided that the following conditions 72 * are met: 73 * 1. Redistributions of source code must retain the above copyright 74 * notice, this list of conditions and the following disclaimer. 75 * 2. Redistributions in binary form must reproduce the above copyright 76 * notice, this list of conditions and the following disclaimer in the 77 * documentation and/or other materials provided with the distribution. 78 * 3. All advertising materials mentioning features or use of this software 79 * must display the following acknowledgement: 80 * This product includes software developed by TooLs GmbH. 81 * 4. The name of TooLs GmbH may not be used to endorse or promote products 82 * derived from this software without specific prior written permission. 83 * 84 * THIS SOFTWARE IS PROVIDED BY TOOLS GMBH ``AS IS'' AND ANY EXPRESS OR 85 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 86 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 87 * IN NO EVENT SHALL TOOLS GMBH BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 88 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 89 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 90 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 91 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 92 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 93 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 94 */ 95 96 /* 97 * Machine-dependent bootstrap for the ACube Sam460ex (AMCC 460EX). 98 * 99 * Modeled on evbppc/walnut/machdep.c and evbppc/obs405/obs600_machdep.c. 100 */ 101 102 #include <sys/cdefs.h> 103 __KERNEL_RCSID(0, "$NetBSD: machdep.c,v 1.6 2026/06/22 12:34:19 rkujawa Exp $"); 104 105 #include "opt_ddb.h" 106 #include "opt_ppc4xx.h" 107 #include "opt_sam460ex.h" 108 109 #include <sys/param.h> 110 #include <sys/boot_flag.h> 111 #include <sys/bus.h> 112 #include <sys/device.h> 113 #include <sys/kernel.h> 114 #include <sys/reboot.h> 115 #include <sys/sysctl.h> 116 #include <sys/systm.h> 117 118 #include <dev/cons.h> 119 120 #include <prop/proplib.h> 121 122 #include <machine/sam460ex.h> 123 124 #include <powerpc/spr.h> 125 #include <powerpc/ibm4xx/spr.h> 126 127 #include <powerpc/ibm4xx/amcc460ex.h> 128 #include <powerpc/ibm4xx/cpu.h> 129 #include <powerpc/ibm4xx/dcr4xx.h> 130 #include <powerpc/ibm4xx/ibm4xx_460ex_l2.h> 131 #include <powerpc/ibm4xx/tlb.h> 132 133 #include <powerpc/ibm4xx/pci_machdep.h> 134 #include <dev/pci/pciconf.h> 135 #include <dev/pci/pcivar.h> 136 137 #include "com.h" 138 #include "ukbd.h" 139 #if NUKBD > 0 140 #include <dev/usb/ukbdvar.h> 141 #endif 142 #if (NCOM > 0) 143 #include <sys/termios.h> 144 #include <powerpc/ibm4xx/dev/comopbvar.h> 145 #include <dev/ic/comreg.h> 146 147 #ifndef CONADDR 148 #define CONADDR AMCC460EX_UART0_BASE 149 #endif 150 #ifndef CONSPEED 151 #define CONSPEED B115200 152 #endif 153 #ifndef CONMODE 154 /* 8N1 */ 155 #define CONMODE ((TTYDEF_CFLAG & ~(CSIZE | CSTOPB | PARENB)) | CS8) 156 #endif 157 #endif /* NCOM */ 158 159 #ifndef SAM460EX_MEMSIZE 160 #define SAM460EX_MEMSIZE (512 * 1024 * 1024) 161 #endif 162 #ifndef SAM460EX_CPU_FREQ 163 #define SAM460EX_CPU_FREQ (1150 * 1000 * 1000) 164 #endif 165 #ifndef SAM460EX_OPB_FREQ 166 #define SAM460EX_OPB_FREQ (115 * 1000 * 1000) 167 #endif 168 169 #define TLB_PG_SIZE (16 * 1024 * 1024) 170 171 /* Boot loader handoff, for later FDT parsing */ 172 paddr_t sam460ex_fdt_pa; 173 uint32_t sam460ex_epapr_magic; 174 175 void initppc(vaddr_t, vaddr_t, paddr_t, uint32_t); 176 177 /* 178 * Polled early console on UART0. 179 * VA 0xef600300 covered by the locore. 180 */ 181 static void 182 earlycons_putc(dev_t dev, int c) 183 { 184 volatile uint8_t *uart = (volatile uint8_t *)AMCC460EX_UART0_BASE; 185 186 while ((uart[5] & 0x20) == 0) /* LSR.THRE */ 187 ; 188 uart[0] = c; 189 } 190 191 static int 192 earlycons_getc(dev_t dev) 193 { 194 volatile uint8_t *uart = (volatile uint8_t *)AMCC460EX_UART0_BASE; 195 196 while ((uart[5] & 0x01) == 0) /* LSR.DR */ 197 ; 198 return uart[0]; 199 } 200 201 static struct consdev earlycons = { 202 .cn_putc = earlycons_putc, 203 .cn_getc = earlycons_getc, 204 .cn_pollc = nullcnpollc, 205 .cn_dev = NODEV, 206 .cn_pri = CN_INTERNAL, 207 }; 208 209 void 210 initppc(vaddr_t startkernel, vaddr_t endkernel, paddr_t fdt_pa, 211 uint32_t magic) 212 { 213 u_int memsize; 214 vaddr_t va; 215 216 cn_tab = &earlycons; 217 218 sam460ex_fdt_pa = fdt_pa; 219 sam460ex_epapr_magic = magic; 220 221 /* Disable all external interrupts */ 222 mtdcr(DCR_UIC0_BASE + DCR_UIC_ER, 0); 223 mtdcr(DCR_UIC1_BASE + DCR_UIC_ER, 0); 224 mtdcr(DCR_UIC2_BASE + DCR_UIC_ER, 0); 225 mtdcr(DCR_UIC3_BASE + DCR_UIC_ER, 0); 226 227 memsize = SAM460EX_MEMSIZE; 228 #ifdef SAM460EX_FDT 229 if (sam460ex_fdt_parse(fdt_pa)) { 230 if (sam460ex_fdt_info.fi_memsize != 0) 231 memsize = sam460ex_fdt_info.fi_memsize; 232 } else 233 printf("sam460ex: no valid FDT at %#lx, using defaults\n", 234 (u_long)fdt_pa); 235 /* Record the value actually used so cpu_startup() agrees. */ 236 sam460ex_fdt_info.fi_memsize = memsize; 237 #endif 238 239 #ifdef PPC4XX_L2CACHE 240 ibm4xx_460ex_l2cache_enable(memsize); 241 #endif 242 243 /* Slots 0/1 hold the TS=0 identity entries pinned by locore */ 244 ppc44x_tlb_boot_reserved(2); 245 246 /* 247 * locore TS=0 RAM identity entry covers the first 256MB 248 */ 249 for (paddr_t pa = 0x10000000; pa < memsize; pa += 0x10000000) 250 ppc44x_tlb_reserve_ts0(pa); 251 252 /* Linear map kernel memory (TS=1, KERNEL_PID) */ 253 for (va = 0; va < endkernel; va += TLB_PG_SIZE) 254 ppc4xx_tlb_reserve(va, va, TLB_PG_SIZE, TLB_EX); 255 256 /* 257 * Map the on-chip peripherals 258 */ 259 ppc44x_tlb_reserve((uint64_t)AMCC460EX_OPB_PA_HIGH << 32 | 0xef000000, 260 0xef000000, TLB_PG_SIZE, TLB_I | TLB_G); 261 262 /* 263 * PCIX host bridge windows 264 */ 265 for (va = 0; va < AMCC460EX_PCIX0_MEM_SIZE; va += TLB_PG_SIZE) 266 ppc44x_tlb_reserve( 267 (uint64_t)AMCC460EX_PCIX0_MEM_PLBA_H << 32 | 268 (AMCC460EX_PCIX0_MEM_BASE + va), 269 SAM460EX_PCIMEM_VA + va, TLB_PG_SIZE, TLB_I | TLB_G); 270 /* Prefetchable window (POM1): pin the radeonfb framebuffer aperture */ 271 for (va = 0; va < AMCC460EX_PCIX0_PMEM_MAP; va += TLB_PG_SIZE) 272 ppc44x_tlb_reserve( 273 (uint64_t)AMCC460EX_PCIX0_PMEM_PLBA_H << 32 | 274 (AMCC460EX_PCIX0_PMEM_BASE + va), 275 SAM460EX_PCIPREFMEM_VA + va, TLB_PG_SIZE, TLB_I | TLB_G); 276 ppc44x_tlb_reserve((uint64_t)AMCC460EX_PCIX0_IO_PA_HIGH << 32 | 277 AMCC460EX_PCIX0_IO_PLBA, 278 SAM460EX_PCIIO_VA, TLB_PG_SIZE, TLB_I | TLB_G); 279 ppc44x_tlb_reserve((uint64_t)AMCC460EX_PCIX0_CFG_PA_HIGH << 32 | 280 (AMCC460EX_PCIX0_CFG_PLBA & ~(TLB_PG_SIZE - 1)), 281 SAM460EX_PCICFG_VA, TLB_PG_SIZE, TLB_I | TLB_G); 282 283 /* 284 * PCIe root complex windows 285 */ 286 ppc44x_tlb_reserve((uint64_t)AMCC460EX_PCIE_CFG_PA_HIGH << 32 | 287 AMCC460EX_PCIE0_CFG_PLBA, 288 SAM460EX_PCIE0CFG_VA, TLB_PG_SIZE, TLB_I | TLB_G); 289 ppc44x_tlb_reserve((uint64_t)AMCC460EX_PCIE_CFG_PA_HIGH << 32 | 290 AMCC460EX_PCIE1_CFG_PLBA, 291 SAM460EX_PCIE1CFG_VA, TLB_PG_SIZE, TLB_I | TLB_G); 292 /* PCIE1 local config (XCFG): inbound BAR/PIM registers */ 293 ppc44x_tlb_reserve((uint64_t)AMCC460EX_PCIE_CFG_PA_HIGH << 32 | 294 AMCC460EX_PCIE1_XCFG_PLBA, 295 SAM460EX_PCIE1XCFG_VA, TLB_PG_SIZE, TLB_I | TLB_G); 296 ppc44x_tlb_reserve((uint64_t)AMCC460EX_PCIE_MEM_PA_HIGH << 32 | 297 AMCC460EX_PCIE0_MEM_PLBA, 298 SAM460EX_PCIE0MEM_VA, TLB_PG_SIZE, TLB_I | TLB_G); 299 ppc44x_tlb_reserve((uint64_t)AMCC460EX_PCIE_MEM_PA_HIGH << 32 | 300 AMCC460EX_PCIE1_MEM_PLBA, 301 SAM460EX_PCIE1MEM_VA, TLB_PG_SIZE, TLB_I | TLB_G); 302 303 /* 304 * AHB peripherals (USB OTG/OHCI/EHCI) behind the PLB-AHB 305 * bridge. 306 */ 307 ppc44x_tlb_reserve((uint64_t)AMCC460EX_AHB_PA_HIGH << 32 | 308 AMCC460EX_AHB_BASE, 309 SAM460EX_AHB_VA, TLB_PG_SIZE, TLB_I | TLB_G); 310 311 mtspr(SPR_TCR, 0); /* disable all timers */ 312 313 ibm40x_memsize_init(memsize, startkernel); 314 ibm4xx_init(startkernel, endkernel, pic_ext_intr); 315 316 #ifdef DDB 317 if (boothowto & RB_KDB) 318 Debugger(); 319 #endif 320 } 321 322 /* 323 * UART input clock for the console and com devices. 324 */ 325 uint32_t 326 sam460ex_com_freq(void) 327 { 328 329 #ifdef SAM460EX_FDT 330 if (sam460ex_fdt_info.fi_uart_freq != 0) 331 return sam460ex_fdt_info.fi_uart_freq; 332 #endif 333 return AMCC460EX_COM_FREQ; 334 } 335 336 void 337 consinit(void) 338 { 339 340 #if (NCOM > 0) 341 com_opb_cnattach(sam460ex_com_freq(), CONADDR, CONSPEED, CONMODE); 342 #endif 343 } 344 345 /* 346 * Parse /chosen/bootargs. 347 */ 348 static char bootspec_buf[64]; 349 350 /* Console target from the "console=" bootarg (see machine/sam460ex.h). */ 351 enum sam460ex_console sam460ex_console = SAM460EX_CONS_COM; 352 int sam460ex_console_pci_bdf[3] = { -1, -1, -1 }; 353 354 /* 355 * Parse an optional ":bus:dev:func" suffix for "console=pci" 356 */ 357 static void 358 parse_pci_bdf(const char *s) 359 { 360 char *ep; 361 int i; 362 363 for (i = 0; i < 3 && *s == ':'; i++) { 364 sam460ex_console_pci_bdf[i] = (int)strtoul(s + 1, &ep, 0); 365 if (ep == s + 1) { /* no digits consumed */ 366 sam460ex_console_pci_bdf[i] = -1; 367 return; 368 } 369 s = ep; 370 } 371 } 372 373 static void 374 parse_bootargs(const char *args) 375 { 376 const char *cp = args; 377 378 #define BA_DELIM(c) ((c) == ' ' || (c) == '"') 379 while (*cp != '\0') { 380 if (BA_DELIM(*cp)) { 381 cp++; 382 continue; 383 } 384 if (*cp == '-') { 385 for (cp++; *cp != '\0' && !BA_DELIM(*cp); cp++) 386 BOOT_FLAG(*cp, boothowto); 387 } else if (strncmp(cp, "root=", 5) == 0) { 388 char *bp = bootspec_buf; 389 390 for (cp += 5; *cp != '\0' && !BA_DELIM(*cp) && 391 bp < &bootspec_buf[sizeof(bootspec_buf) - 1]; ) 392 *bp++ = *cp++; 393 *bp = '\0'; 394 if (bootspec_buf[0] != '\0') { 395 bootspec = bootspec_buf; 396 booted_method = "bootargs/root"; 397 } 398 } else if (strncmp(cp, "console=", 8) == 0) { 399 char cbuf[24]; 400 char *bp = cbuf; 401 402 for (cp += 8; *cp != '\0' && !BA_DELIM(*cp) && 403 bp < &cbuf[sizeof(cbuf) - 1]; ) 404 *bp++ = *cp++; 405 *bp = '\0'; 406 407 if (strcmp(cbuf, "com0") == 0 || 408 strcmp(cbuf, "serial") == 0) 409 sam460ex_console = SAM460EX_CONS_COM; 410 else if (strcmp(cbuf, "sm502") == 0 || 411 strcmp(cbuf, "fb") == 0) 412 sam460ex_console = SAM460EX_CONS_SM502; 413 else if (strncmp(cbuf, "pci", 3) == 0) { 414 sam460ex_console = SAM460EX_CONS_PCI; 415 parse_pci_bdf(&cbuf[3]); 416 } 417 } else { 418 while (*cp != '\0' && !BA_DELIM(*cp)) 419 cp++; 420 } 421 } 422 #undef BA_DELIM 423 } 424 425 /* 426 * Sanitize EHCI state before the kernel takes over the USB host controller. 427 */ 428 static void 429 sam460ex_usb_host_init(void) 430 { 431 volatile uint32_t *gpio; 432 uint32_t v, srst; 433 const uint32_t pin = 0x00008000; /* GPIO16 = bit 15 in OR/TCR */ 434 435 /* AHB-to-PLB bridge config: 460EX errata for concurrent USB/SATA. */ 436 v = mfsdr(DCR_SDR0_AHB_CFG); 437 v |= SDR0_AHB_CFG_A2P_INCR4; 438 v &= ~SDR0_AHB_CFG_A2P_PROT2; 439 mtsdr(DCR_SDR0_AHB_CFG, v); 440 441 /* USB 2.0 host wrapper config (Sam460ex value). */ 442 v = mfsdr(DCR_SDR0_USB2HOST_CFG); 443 v &= ~0x0000ff00; 444 v |= 0x00004400; 445 mtsdr(DCR_SDR0_USB2HOST_CFG, v); 446 447 gpio = ppc4xx_tlb_mapiodev(AMCC460EX_GPIO0_BASE, 0x40); 448 449 /* 450 * Reset and re-sync the USB 2.0 host and its external ULPI PHY 451 */ 452 srst = mfsdr(DCR_SDR0_SRST1); 453 mtsdr(DCR_SDR0_SRST1, srst | SDR0_SRST1_USBHOST); 454 455 if (gpio != NULL) { 456 /* GPIO16 -> GPIO mode, output low */ 457 gpio[0x04 / 4] &= ~pin; /* TCR: tristate */ 458 gpio[0x0c / 4] &= ~0xc0000000; /* OSRH: select GPIO */ 459 gpio[0x00 / 4] &= ~pin; /* OR: drive low */ 460 gpio[0x04 / 4] |= pin; /* TCR: drive output */ 461 } 462 463 delay(500 * 1000); 464 465 if (gpio != NULL) { 466 /* GPIO16 -> ALT1 (USB2HostStop), output high */ 467 gpio[0x04 / 4] &= ~pin; 468 gpio[0x0c / 4] = (gpio[0x0c / 4] & ~0xc0000000) | 0x40000000; 469 gpio[0x00 / 4] |= pin; 470 gpio[0x04 / 4] |= pin; 471 } 472 473 mtsdr(DCR_SDR0_SRST1, srst & ~SDR0_SRST1_USBHOST); 474 delay(200 * 1000); 475 } 476 477 /* 478 * Machine dependent startup code. 479 */ 480 void 481 cpu_startup(void) 482 { 483 prop_number_t pn; 484 uint32_t cpu_freq = SAM460EX_CPU_FREQ; 485 uint32_t opb_freq = SAM460EX_OPB_FREQ; 486 uint32_t memsize = SAM460EX_MEMSIZE; 487 488 ibm4xx_cpu_startup("ACube Sam460ex (AMCC 460EX)"); 489 490 /* re-init the on-chip USB host so it doesn't depend on firmware state */ 491 sam460ex_usb_host_init(); 492 493 #ifdef SAM460EX_FDT 494 /* 495 * The timebase runs at the CPU clock; "processor-frequency" 496 * feeds delay() and the DEC reload value. 497 */ 498 if (sam460ex_fdt_info.fi_timebase_freq != 0) 499 cpu_freq = sam460ex_fdt_info.fi_timebase_freq; 500 else if (sam460ex_fdt_info.fi_cpu_freq != 0) 501 cpu_freq = sam460ex_fdt_info.fi_cpu_freq; 502 if (sam460ex_fdt_info.fi_opb_freq != 0) 503 opb_freq = sam460ex_fdt_info.fi_opb_freq; 504 if (sam460ex_fdt_info.fi_memsize != 0) 505 memsize = sam460ex_fdt_info.fi_memsize; 506 printf("sam460ex: fdt cpu %u Hz, opb %u Hz, uart %u Hz, mem %u MB\n", 507 cpu_freq, opb_freq, sam460ex_fdt_info.fi_uart_freq, 508 memsize / (1024 * 1024)); 509 if (sam460ex_fdt_info.fi_bootargs != NULL) { 510 printf("bootargs: %s\n", sam460ex_fdt_info.fi_bootargs); 511 parse_bootargs(sam460ex_fdt_info.fi_bootargs); 512 } 513 #endif 514 515 #ifdef PPC4XX_L2CACHE 516 if (ibm4xx_460ex_l2_cfg & L2C_CFG_L2M) 517 printf("sam460ex: 256KB L2 cache enabled, write-through, " 518 "hw snoop (EMAC) + SW inval (USB) (L2C0_CFG %#x)\n", 519 ibm4xx_460ex_l2_cfg); 520 else 521 printf("sam460ex: L2 cache NOT enabled (L2C0_CFG %#x)\n", 522 ibm4xx_460ex_l2_cfg); 523 #endif 524 525 #ifdef DIAGNOSTIC 526 { 527 uint32_t cr = mfdcr(DCR_AHB_CR); 528 printf("sam460ex: AHB bridge rev %#x top %#x bot %#x att %#x " 529 "cr %#x (PUOA %#x -> USB DMA on %s segment)\n", 530 mfdcr(DCR_AHB_REV), mfdcr(DCR_AHB_TOP), mfdcr(DCR_AHB_BOT), 531 mfdcr(DCR_AHB_ATT), cr, 532 (cr & AHB_CR_PUOA_MASK) >> AHB_CR_PUOA_SHIFT, 533 ((cr & AHB_CR_PUOA_MASK) >> AHB_CR_PUOA_SHIFT) < 0x8 ? 534 "low-latency (snooped)" : "high-bandwidth (UNSNOOPED)"); 535 } 536 #endif 537 538 #if NUKBD > 0 539 /* Glass consoles (SM502 or a PCI display) take keyboard input via USB. */ 540 if (sam460ex_console == SAM460EX_CONS_SM502 || 541 sam460ex_console == SAM460EX_CONS_PCI) { 542 ukbd_cnattach(); 543 } 544 #endif 545 546 /* 547 * Set up the board props 548 */ 549 board_info_init(); 550 551 pn = prop_number_create_integer(cpu_freq); 552 KASSERT(pn != NULL); 553 if (prop_dictionary_set(board_properties, "processor-frequency", 554 pn) == false) 555 panic("setting processor-frequency"); 556 prop_object_release(pn); 557 558 pn = prop_number_create_integer(opb_freq); 559 KASSERT(pn != NULL); 560 if (prop_dictionary_set(board_properties, "opb-frequency", pn) == 561 false) 562 panic("setting opb-frequency"); 563 prop_object_release(pn); 564 565 pn = prop_number_create_integer(memsize); 566 KASSERT(pn != NULL); 567 if (prop_dictionary_set(board_properties, "mem-size", pn) == false) 568 panic("setting mem-size"); 569 prop_object_release(pn); 570 571 #ifdef SAM460EX_FDT 572 /* 573 * EMAC MAC addresses from the device tree filled by U-Boot 574 */ 575 for (int i = 0; i < SAM460EX_NEMAC; i++) { 576 char propname[16]; 577 prop_data_t pd; 578 579 if (!sam460ex_fdt_info.fi_enaddr_valid[i]) 580 continue; 581 snprintf(propname, sizeof(propname), "emac%d-mac-addr", i); 582 pd = prop_data_create_data_nocopy( 583 sam460ex_fdt_info.fi_enaddr[i], 6); 584 KASSERT(pd != NULL); 585 if (prop_dictionary_set(board_properties, propname, pd) == 586 false) 587 panic("setting %s", propname); 588 prop_object_release(pd); 589 590 snprintf(propname, sizeof(propname), "emac%d-mii-phy", i); 591 pn = prop_number_create_integer(i); 592 KASSERT(pn != NULL); 593 if (prop_dictionary_set(board_properties, propname, pn) == 594 false) 595 panic("setting %s", propname); 596 prop_object_release(pn); 597 } 598 #endif 599 600 calc_delayconst(); 601 602 /* 603 * Now that we have VM, malloc is OK 604 */ 605 bus_space_mallocok(); 606 fake_mapiodev = 0; 607 } 608 609 /* 610 * PCI interrupt routing and slot policy for the on-chip PLB-PCIX 611 * bridge (see powerpc/ibm4xx/pci/pcix.c). 612 * 613 * XXX: On the Sam460ex every PCI intr pin is wired to UIC1 bit 0? 614 */ 615 int 616 ibm4xx_pci_bus_maxdevs(void *v, int busno) 617 { 618 return 16; 619 } 620 621 /* 622 * Board interrupt routing for the PCI-X slot. Unlike the AMCC Canyonlands 623 * design (where the SoC's external IRQ2 / UIC1 bit 0 is the PCI INT), the 624 * Sam460ex wire-ORs all PCI INTx through its FPGA onto UIC1 bit 3 = irq 35 625 */ 626 #define SAM460EX_PCI_INTR_IRQ 32 /* TEMP, see above; correct value is 35? */ 627 628 int 629 ibm4xx_pci_intr_map(const struct pci_attach_args *pa, pci_intr_handle_t *ihp) 630 { 631 *ihp = SAM460EX_PCI_INTR_IRQ; 632 return 0; 633 } 634 635 void 636 ibm4xx_pci_conf_interrupt(void *v, int bus, int dev, int pin, int swiz, 637 int *iline) 638 { 639 *iline = SAM460EX_PCI_INTR_IRQ; 640 } 641 642 #define UIC_DUMP(n, base) \ 643 blen += snprintf(buf + blen, sizeof(buf) - blen, \ 644 "uic%d SR=%08x MSR=%08x ER=%08x PR=%08x TR=%08x\n", (n), \ 645 (unsigned int)mfdcr((base) + DCR_UIC_SR), \ 646 (unsigned int)mfdcr((base) + DCR_UIC_MSR), \ 647 (unsigned int)mfdcr((base) + DCR_UIC_ER), \ 648 (unsigned int)mfdcr((base) + DCR_UIC_PR), \ 649 (unsigned int)mfdcr((base) + DCR_UIC_TR)) 650 651 static int 652 sysctl_machdep_uicregs(SYSCTLFN_ARGS) 653 { 654 struct sysctlnode node; 655 char buf[400]; 656 int blen = 0; 657 658 UIC_DUMP(0, DCR_UIC0_BASE); 659 UIC_DUMP(1, DCR_UIC1_BASE); 660 UIC_DUMP(2, DCR_UIC2_BASE); 661 UIC_DUMP(3, DCR_UIC3_BASE); 662 663 node = *rnode; 664 node.sysctl_data = buf; 665 node.sysctl_size = strlen(buf) + 1; 666 return sysctl_lookup(SYSCTLFN_CALL(&node)); 667 } 668 #undef UIC_DUMP 669 670 SYSCTL_SETUP(sysctl_machdep_uicregs_setup, "sam460ex UIC register dump") 671 { 672 673 sysctl_createv(clog, 0, NULL, NULL, 674 CTLFLAG_PERMANENT | CTLFLAG_READONLY, 675 CTLTYPE_STRING, "uicregs", 676 SYSCTL_DESCR("UIC0-3 SR/MSR/ER/PR/TR (interrupt debug)"), 677 sysctl_machdep_uicregs, 0, NULL, 0, 678 CTL_MACHDEP, CTL_CREATE, CTL_EOL); 679 } 680 681