1 /* $NetBSD: machdep.c,v 1.7 2026/09/28 20:41:00 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.7 2026/09/28 20:41:00 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/systm.h> 116 117 #include <dev/cons.h> 118 119 #include <prop/proplib.h> 120 121 #include <machine/sam460ex.h> 122 123 #include <powerpc/spr.h> 124 #include <powerpc/ibm4xx/spr.h> 125 126 #include <powerpc/ibm4xx/amcc460ex.h> 127 #include <powerpc/ibm4xx/cpu.h> 128 #include <powerpc/ibm4xx/dcr4xx.h> 129 #include <powerpc/ibm4xx/tlb.h> 130 131 #include <powerpc/ibm4xx/pci_machdep.h> 132 #include <dev/pci/pciconf.h> 133 #include <dev/pci/pcivar.h> 134 135 #include "com.h" 136 #include "ukbd.h" 137 #if NUKBD > 0 138 #include <dev/usb/ukbdvar.h> 139 #endif 140 #include <dev/ic/comreg.h> 141 #include <powerpc/ibm4xx/dev/gpioreg.h> 142 #if (NCOM > 0) 143 #include <sys/termios.h> 144 #include <powerpc/ibm4xx/dev/comopbvar.h> 145 146 #ifndef CONADDR 147 #define CONADDR AMCC460EX_UART0_BASE 148 #endif 149 #ifndef CONSPEED 150 #define CONSPEED B115200 151 #endif 152 #ifndef CONMODE 153 /* 8N1 */ 154 #define CONMODE ((TTYDEF_CFLAG & ~(CSIZE | CSTOPB | PARENB)) | CS8) 155 #endif 156 #endif /* NCOM */ 157 158 #ifndef SAM460EX_MEMSIZE 159 #define SAM460EX_MEMSIZE (512 * 1024 * 1024) 160 #endif 161 #ifndef SAM460EX_CPU_FREQ 162 #define SAM460EX_CPU_FREQ (1150 * 1000 * 1000) 163 #endif 164 #ifndef SAM460EX_OPB_FREQ 165 #define SAM460EX_OPB_FREQ (115 * 1000 * 1000) 166 #endif 167 168 #define TLB_PG_SIZE (16 * 1024 * 1024) 169 #define TLB_TS0_SIZE (256 * 1024 * 1024) /* locore identity */ 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[com_lsr] & LSR_TXRDY) == 0) 187 ; 188 uart[com_data] = 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[com_lsr] & LSR_RXRDY) == 0) 197 ; 198 return uart[com_data]; 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 /* Slots 0/1 hold the TS=0 identity entries pinned by locore */ 240 ppc44x_tlb_boot_reserved(2); 241 242 /* locore's TS=0 RAM identity entry covers the first TLB_TS0_SIZE */ 243 for (paddr_t pa = TLB_TS0_SIZE; pa < memsize; pa += TLB_TS0_SIZE) 244 ppc44x_tlb_reserve_ts0(pa); 245 246 /* Linear map kernel memory (TS=1, KERNEL_PID) */ 247 for (va = 0; va < endkernel; va += TLB_PG_SIZE) 248 ppc4xx_tlb_reserve(va, va, TLB_PG_SIZE, TLB_EX); 249 250 /* On-chip peripherals */ 251 va = AMCC460EX_OPB_BASE & ~(TLB_PG_SIZE - 1); 252 ppc44x_tlb_reserve((uint64_t)AMCC460EX_OPB_PA_HIGH << 32 | va, 253 va, TLB_PG_SIZE, TLB_I | TLB_G); 254 255 /* 256 * PCIX host bridge windows 257 */ 258 for (va = 0; va < AMCC460EX_PCIX0_MEM_SIZE; va += TLB_PG_SIZE) 259 ppc44x_tlb_reserve( 260 (uint64_t)AMCC460EX_PCIX0_MEM_PLBA_H << 32 | 261 (AMCC460EX_PCIX0_MEM_BASE + va), 262 SAM460EX_PCIMEM_VA + va, TLB_PG_SIZE, TLB_I | TLB_G); 263 /* Prefetchable window (POM1): pin the radeonfb framebuffer aperture */ 264 for (va = 0; va < AMCC460EX_PCIX0_PMEM_MAP; va += TLB_PG_SIZE) 265 ppc44x_tlb_reserve( 266 (uint64_t)AMCC460EX_PCIX0_PMEM_PLBA_H << 32 | 267 (AMCC460EX_PCIX0_PMEM_BASE + va), 268 SAM460EX_PCIPREFMEM_VA + va, TLB_PG_SIZE, TLB_I | TLB_G); 269 ppc44x_tlb_reserve((uint64_t)AMCC460EX_PCIX0_IO_PA_HIGH << 32 | 270 AMCC460EX_PCIX0_IO_PLBA, 271 SAM460EX_PCIIO_VA, TLB_PG_SIZE, TLB_I | TLB_G); 272 ppc44x_tlb_reserve((uint64_t)AMCC460EX_PCIX0_CFG_PA_HIGH << 32 | 273 (AMCC460EX_PCIX0_CFG_PLBA & ~(TLB_PG_SIZE - 1)), 274 SAM460EX_PCICFG_VA, TLB_PG_SIZE, TLB_I | TLB_G); 275 276 /* 277 * PCIe root complex windows 278 */ 279 ppc44x_tlb_reserve((uint64_t)AMCC460EX_PCIE_CFG_PA_HIGH << 32 | 280 AMCC460EX_PCIE0_CFG_PLBA, 281 SAM460EX_PCIE0CFG_VA, TLB_PG_SIZE, TLB_I | TLB_G); 282 ppc44x_tlb_reserve((uint64_t)AMCC460EX_PCIE_CFG_PA_HIGH << 32 | 283 AMCC460EX_PCIE1_CFG_PLBA, 284 SAM460EX_PCIE1CFG_VA, TLB_PG_SIZE, TLB_I | TLB_G); 285 /* XCFG */ 286 ppc44x_tlb_reserve((uint64_t)AMCC460EX_PCIE_CFG_PA_HIGH << 32 | 287 AMCC460EX_PCIE0_XCFG_PLBA, 288 SAM460EX_PCIE0XCFG_VA, TLB_PG_SIZE, TLB_I | TLB_G); 289 ppc44x_tlb_reserve((uint64_t)AMCC460EX_PCIE_CFG_PA_HIGH << 32 | 290 AMCC460EX_PCIE1_XCFG_PLBA, 291 SAM460EX_PCIE1XCFG_VA, TLB_PG_SIZE, TLB_I | TLB_G); 292 for (va = 0; va < AMCC460EX_PCIE_MEM_SIZE; va += TLB_PG_SIZE) { 293 ppc44x_tlb_reserve((uint64_t)AMCC460EX_PCIE_MEM_PA_HIGH << 32 | 294 (AMCC460EX_PCIE0_MEM_PLBA + va), 295 SAM460EX_PCIE0MEM_VA + va, TLB_PG_SIZE, TLB_I | TLB_G); 296 ppc44x_tlb_reserve((uint64_t)AMCC460EX_PCIE_MEM_PA_HIGH << 32 | 297 (AMCC460EX_PCIE1_MEM_PLBA + va), 298 SAM460EX_PCIE1MEM_VA + va, TLB_PG_SIZE, TLB_I | TLB_G); 299 } 300 301 /* 302 * AHB peripherals (USB OTG/OHCI/EHCI) behind the PLB-AHB 303 * bridge. 304 */ 305 ppc44x_tlb_reserve((uint64_t)AMCC460EX_AHB_PA_HIGH << 32 | 306 AMCC460EX_AHB_BASE, 307 SAM460EX_AHB_VA, TLB_PG_SIZE, TLB_I | TLB_G); 308 309 /* FPGA on the EBC */ 310 ppc44x_tlb_reserve((uint64_t)AMCC460EX_EBC_PA_HIGH << 32 | 311 SAM460EX_FPGA_PA, 312 SAM460EX_FPGA_VA, SAM460EX_FPGA_MAP, TLB_I | TLB_G); 313 314 mtspr(SPR_TCR, 0); /* disable all timers */ 315 316 ibm40x_memsize_init(memsize, startkernel); 317 ibm4xx_init(startkernel, endkernel, pic_ext_intr); 318 319 #ifdef DDB 320 if (boothowto & RB_KDB) 321 Debugger(); 322 #endif 323 } 324 325 /* 326 * UART input clock for the console and com devices. 327 */ 328 uint32_t 329 sam460ex_com_freq(void) 330 { 331 332 #ifdef SAM460EX_FDT 333 if (sam460ex_fdt_info.fi_uart_freq != 0) 334 return sam460ex_fdt_info.fi_uart_freq; 335 #endif 336 return AMCC460EX_COM_FREQ; 337 } 338 339 void 340 consinit(void) 341 { 342 343 #if (NCOM > 0) 344 com_opb_cnattach(sam460ex_com_freq(), CONADDR, CONSPEED, CONMODE); 345 #endif 346 } 347 348 /* 349 * Parse /chosen/bootargs. 350 */ 351 static char bootspec_buf[64]; 352 353 /* Console target from the "console=" bootarg (see machine/sam460ex.h). */ 354 enum sam460ex_console sam460ex_console = SAM460EX_CONS_COM; 355 int sam460ex_console_pci_bdf[3] = { -1, -1, -1 }; 356 357 /* 358 * Parse an optional ":bus:dev:func" suffix for "console=pci" 359 */ 360 static void 361 parse_pci_bdf(const char *s) 362 { 363 char *ep; 364 int i; 365 366 for (i = 0; i < __arraycount(sam460ex_console_pci_bdf) && *s == ':'; 367 i++) { 368 sam460ex_console_pci_bdf[i] = (int)strtoul(s + 1, &ep, 0); 369 if (ep == s + 1) { /* no digits consumed */ 370 sam460ex_console_pci_bdf[i] = -1; 371 return; 372 } 373 s = ep; 374 } 375 } 376 377 static void 378 parse_bootargs(const char *args) 379 { 380 const char *cp = args; 381 382 #define BA_DELIM(c) ((c) == ' ' || (c) == '"') 383 #define BA_KEY(cp, key) (strncmp((cp), (key), sizeof(key) - 1) == 0) 384 #define BA_SKIP(cp, key) ((cp) += sizeof(key) - 1) 385 while (*cp != '\0') { 386 if (BA_DELIM(*cp)) { 387 cp++; 388 continue; 389 } 390 if (*cp == '-') { 391 for (cp++; *cp != '\0' && !BA_DELIM(*cp); cp++) 392 BOOT_FLAG(*cp, boothowto); 393 } else if (BA_KEY(cp, "root=")) { 394 char *bp = bootspec_buf; 395 396 for (BA_SKIP(cp, "root="); *cp != '\0' && !BA_DELIM(*cp) && 397 bp < &bootspec_buf[sizeof(bootspec_buf) - 1]; ) 398 *bp++ = *cp++; 399 *bp = '\0'; 400 if (bootspec_buf[0] != '\0') { 401 bootspec = bootspec_buf; 402 booted_method = "bootargs/root"; 403 } 404 } else if (BA_KEY(cp, "console=")) { 405 char cbuf[24]; 406 char *bp = cbuf; 407 408 for (BA_SKIP(cp, "console="); *cp != '\0' && 409 !BA_DELIM(*cp) && 410 bp < &cbuf[sizeof(cbuf) - 1]; ) 411 *bp++ = *cp++; 412 *bp = '\0'; 413 414 if (strcmp(cbuf, "com0") == 0 || 415 strcmp(cbuf, "serial") == 0) 416 sam460ex_console = SAM460EX_CONS_COM; 417 else if (strcmp(cbuf, "sm502") == 0 || 418 strcmp(cbuf, "fb") == 0) 419 sam460ex_console = SAM460EX_CONS_SM502; 420 else if (BA_KEY(cbuf, "pci")) { 421 sam460ex_console = SAM460EX_CONS_PCI; 422 parse_pci_bdf(&cbuf[sizeof("pci") - 1]); 423 } 424 } else { 425 while (*cp != '\0' && !BA_DELIM(*cp)) 426 cp++; 427 } 428 } 429 #undef BA_DELIM 430 #undef BA_KEY 431 #undef BA_SKIP 432 } 433 434 /* 435 * Sanitize EHCI state before the kernel takes over the USB host controller. 436 */ 437 #define SAM460EX_USB_STOP_PIN 16 438 #define SAM460EX_USB2HOST_CFG_MASK 0x0000ff00 439 #define SAM460EX_USB2HOST_CFG 0x00004400 440 441 static void 442 sam460ex_usb_host_init(void) 443 { 444 volatile uint32_t *gpio; 445 uint32_t v, srst; 446 const uint32_t pin = GPIO_PIN_MASK(SAM460EX_USB_STOP_PIN); 447 const uint32_t sel = GPIO_SEL_MASK(SAM460EX_USB_STOP_PIN); 448 const uint32_t alt1 = GPIO_SEL_ALT1(SAM460EX_USB_STOP_PIN); 449 450 /* AHB-to-PLB bridge config: 460EX errata for concurrent USB/SATA. */ 451 v = mfsdr(DCR_SDR0_AHB_CFG); 452 v |= SDR0_AHB_CFG_A2P_INCR4; 453 v &= ~SDR0_AHB_CFG_A2P_PROT2; 454 mtsdr(DCR_SDR0_AHB_CFG, v); 455 456 v = mfsdr(DCR_SDR0_USB2HOST_CFG); 457 v &= ~SAM460EX_USB2HOST_CFG_MASK; 458 v |= SAM460EX_USB2HOST_CFG; 459 mtsdr(DCR_SDR0_USB2HOST_CFG, v); 460 461 gpio = ppc4xx_tlb_mapiodev(AMCC460EX_GPIO0_BASE, GPIO_NREG); 462 463 /* 464 * Reset and re-sync the USB 2.0 host and its external ULPI PHY 465 */ 466 srst = mfsdr(DCR_SDR0_SRST1); 467 mtsdr(DCR_SDR0_SRST1, srst | SDR0_SRST1_USBHOST); 468 469 if (gpio != NULL) { 470 /* GPIO16 -> GPIO mode, output low */ 471 gpio[GPIO_TCR / 4] &= ~pin; 472 gpio[GPIO_OSRH / 4] &= ~sel; 473 gpio[GPIO_OR / 4] &= ~pin; 474 gpio[GPIO_TCR / 4] |= pin; 475 } 476 477 delay(500 * 1000); 478 479 if (gpio != NULL) { 480 /* GPIO16 -> ALT1 (USB2HostStop), output high */ 481 gpio[GPIO_TCR / 4] &= ~pin; 482 gpio[GPIO_OSRH / 4] = (gpio[GPIO_OSRH / 4] & ~sel) | alt1; 483 gpio[GPIO_OR / 4] |= pin; 484 gpio[GPIO_TCR / 4] |= pin; 485 } 486 487 mtsdr(DCR_SDR0_SRST1, srst & ~SDR0_SRST1_USBHOST); 488 delay(200 * 1000); 489 } 490 491 /* 492 * Machine dependent startup code. 493 */ 494 void 495 cpu_startup(void) 496 { 497 prop_number_t pn; 498 uint32_t cpu_freq = SAM460EX_CPU_FREQ; 499 uint32_t opb_freq = SAM460EX_OPB_FREQ; 500 uint32_t memsize = SAM460EX_MEMSIZE; 501 502 ibm4xx_cpu_startup("ACube Sam460ex (AMCC 460EX)"); 503 504 /* re-init the on-chip USB host so it doesn't depend on firmware state */ 505 sam460ex_usb_host_init(); 506 507 #ifdef SAM460EX_FDT 508 /* 509 * The timebase runs at the CPU clock; "processor-frequency" 510 * feeds delay() and the DEC reload value. 511 */ 512 if (sam460ex_fdt_info.fi_timebase_freq != 0) 513 cpu_freq = sam460ex_fdt_info.fi_timebase_freq; 514 else if (sam460ex_fdt_info.fi_cpu_freq != 0) 515 cpu_freq = sam460ex_fdt_info.fi_cpu_freq; 516 if (sam460ex_fdt_info.fi_opb_freq != 0) 517 opb_freq = sam460ex_fdt_info.fi_opb_freq; 518 if (sam460ex_fdt_info.fi_memsize != 0) 519 memsize = sam460ex_fdt_info.fi_memsize; 520 printf("sam460ex: fdt cpu %u Hz, opb %u Hz, uart %u Hz, mem %u MB\n", 521 cpu_freq, opb_freq, sam460ex_fdt_info.fi_uart_freq, 522 memsize / (1024 * 1024)); 523 if (sam460ex_fdt_info.fi_bootargs != NULL) { 524 printf("bootargs: %s\n", sam460ex_fdt_info.fi_bootargs); 525 parse_bootargs(sam460ex_fdt_info.fi_bootargs); 526 } 527 #endif 528 529 #ifdef DIAGNOSTIC 530 { 531 uint32_t cr = mfdcr(DCR_AHB_CR); 532 printf("sam460ex: AHB bridge rev %#x top %#x bot %#x att %#x " 533 "cr %#x (PUOA %#x -> USB DMA on %s segment)\n", 534 mfdcr(DCR_AHB_REV), mfdcr(DCR_AHB_TOP), mfdcr(DCR_AHB_BOT), 535 mfdcr(DCR_AHB_ATT), cr, 536 (cr & AHB_CR_PUOA_MASK) >> AHB_CR_PUOA_SHIFT, 537 ((cr & AHB_CR_PUOA_MASK) >> AHB_CR_PUOA_SHIFT) < 538 AHB_CR_PUOA_HIGHBW ? 539 "low-latency (snooped)" : "high-bandwidth (UNSNOOPED)"); 540 } 541 #endif 542 543 #if NUKBD > 0 544 /* Glass consoles (SM502 or a PCI display) take keyboard input via USB. */ 545 if (sam460ex_console == SAM460EX_CONS_SM502 || 546 sam460ex_console == SAM460EX_CONS_PCI) { 547 ukbd_cnattach(); 548 } 549 #endif 550 551 /* 552 * Set up the board props 553 */ 554 board_info_init(); 555 556 pn = prop_number_create_integer(cpu_freq); 557 KASSERT(pn != NULL); 558 if (prop_dictionary_set(board_properties, "processor-frequency", 559 pn) == false) 560 panic("setting processor-frequency"); 561 prop_object_release(pn); 562 563 pn = prop_number_create_integer(opb_freq); 564 KASSERT(pn != NULL); 565 if (prop_dictionary_set(board_properties, "opb-frequency", pn) == 566 false) 567 panic("setting opb-frequency"); 568 prop_object_release(pn); 569 570 pn = prop_number_create_integer(memsize); 571 KASSERT(pn != NULL); 572 if (prop_dictionary_set(board_properties, "mem-size", pn) == false) 573 panic("setting mem-size"); 574 prop_object_release(pn); 575 576 #ifdef SAM460EX_FDT 577 /* 578 * EMAC MAC addresses from the device tree filled by U-Boot 579 */ 580 for (int i = 0; i < SAM460EX_NEMAC; i++) { 581 char propname[16]; 582 prop_data_t pd; 583 584 if (!sam460ex_fdt_info.fi_enaddr_valid[i]) 585 continue; 586 snprintf(propname, sizeof(propname), "emac%d-mac-addr", i); 587 pd = prop_data_create_data_nocopy( 588 sam460ex_fdt_info.fi_enaddr[i], 6); 589 KASSERT(pd != NULL); 590 if (prop_dictionary_set(board_properties, propname, pd) == 591 false) 592 panic("setting %s", propname); 593 prop_object_release(pd); 594 595 snprintf(propname, sizeof(propname), "emac%d-mii-phy", i); 596 pn = prop_number_create_integer(i); 597 KASSERT(pn != NULL); 598 if (prop_dictionary_set(board_properties, propname, pn) == 599 false) 600 panic("setting %s", propname); 601 prop_object_release(pn); 602 } 603 #endif 604 605 calc_delayconst(); 606 607 /* 608 * Now that we have VM, malloc is OK 609 */ 610 bus_space_mallocok(); 611 fake_mapiodev = 0; 612 } 613 614 /* 615 * PCI interrupt routing and slot policy for the on-chip PLB-PCIX 616 * bridge (see powerpc/ibm4xx/pci/pcix.c). 617 */ 618 int 619 ibm4xx_pci_bus_maxdevs(void *v, int busno) 620 { 621 return 16; 622 } 623 624 /* 625 * It appears that PCI slot's INTA-D are wire-ORed onto UIC1 input 0, as 626 * on the Canyonlands. However, on-board SM502 drives UIC3 input 20. 627 */ 628 #define SAM460EX_SM502_DEV 6 629 630 int 631 ibm4xx_pci_intr_map(const struct pci_attach_args *pa, pci_intr_handle_t *ihp) 632 { 633 *ihp = pa->pa_bus == 0 && pa->pa_device == SAM460EX_SM502_DEV ? 634 SAM460EX_IRQ_SM502 : SAM460EX_IRQ_PCI_INTX; 635 return 0; 636 } 637 638 void 639 ibm4xx_pci_conf_interrupt(void *v, int bus, int dev, int pin, int swiz, 640 int *iline) 641 { 642 *iline = bus == 0 && dev == SAM460EX_SM502_DEV ? 643 SAM460EX_IRQ_SM502 : SAM460EX_IRQ_PCI_INTX; 644 } 645