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