1 /* $NetBSD: bcm53xx_machdep.c,v 1.9 2015/07/17 20:29:29 matt Exp $ */ 2 3 /*- 4 * Copyright (c) 2012 The NetBSD Foundation, Inc. 5 * All rights reserved. 6 * 7 * This code is derived from software contributed to The NetBSD Foundation 8 * by Matt Thomas of 3am Software Foundry. 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 NETBSD FOUNDATION, INC. AND CONTRIBUTORS 20 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 21 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 23 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29 * POSSIBILITY OF SUCH DAMAGE. 30 */ 31 32 #define CCA_PRIVATE 33 #define IDM_PRIVATE 34 35 #include <sys/cdefs.h> 36 __KERNEL_RCSID(0, "$NetBSD: bcm53xx_machdep.c,v 1.9 2015/07/17 20:29:29 matt Exp $"); 37 38 #include "opt_evbarm_boardtype.h" 39 #include "opt_broadcom.h" 40 #include "opt_kgdb.h" 41 #include "com.h" 42 #include "pci.h" 43 #include "bcmrng_ccb.h" 44 45 #include <sys/param.h> 46 #include <sys/bus.h> 47 #include <sys/atomic.h> 48 #include <sys/device.h> 49 #include <sys/kernel.h> 50 #include <sys/reboot.h> 51 #include <sys/termios.h> 52 53 #include <dev/cons.h> 54 55 #include <uvm/uvm_extern.h> 56 57 #include <arm/db_machdep.h> 58 #include <arm/undefined.h> 59 #include <arm/arm32/machdep.h> 60 61 #include <machine/autoconf.h> 62 #include <machine/bootconfig.h> 63 64 #define CCA_PRIVATE 65 66 #include <arm/cortex/scu_reg.h> 67 #include <arm/broadcom/bcm53xx_var.h> 68 69 #include <evbarm/bcm53xx/platform.h> 70 71 #if NCOM == 0 72 #error missing COM device for console 73 #endif 74 75 #include <dev/ic/comreg.h> 76 #include <dev/ic/comvar.h> 77 78 extern int _end[]; 79 extern int KERNEL_BASE_phys[]; 80 extern int KERNEL_BASE_virt[]; 81 82 BootConfig bootconfig; 83 static char bootargs[MAX_BOOT_STRING]; 84 char *boot_args = NULL; 85 86 u_int uboot_args[4] = { 0 }; 87 88 static void bcm53xx_system_reset(void); 89 90 /* 91 * Macros to translate between physical and virtual for a subset of the 92 * kernel address space. *Not* for general use. 93 */ 94 #define KERN_VTOPDIFF ((vaddr_t)KERNEL_BASE_phys - (vaddr_t)KERNEL_BASE_virt) 95 #define KERN_VTOPHYS(va) ((paddr_t)((vaddr_t)va + KERN_VTOPDIFF)) 96 #define KERN_PHYSTOV(pa) ((vaddr_t)((paddr_t)pa - KERN_VTOPDIFF)) 97 98 #ifndef CONADDR 99 #define CONADDR (BCM53XX_IOREG_PBASE + CCA_UART0_BASE) 100 #endif 101 #ifndef CONSPEED 102 #define CONSPEED B115200 103 #endif 104 #ifndef CONMODE 105 #define CONMODE ((TTYDEF_CFLAG & ~(CSIZE | CSTOPB | PARENB)) | CS8) /* 8N1 */ 106 #endif 107 108 #if (NCOM > 0) 109 static const bus_addr_t comcnaddr = (bus_addr_t)CONADDR; 110 111 int comcnspeed = CONSPEED; 112 int comcnmode = CONMODE | CLOCAL; 113 #endif 114 115 #ifdef KGDB 116 #include <sys/kgdb.h> 117 #endif 118 119 /* 120 * Static device mappings. These peripheral registers are mapped at 121 * fixed virtual addresses very early in initarm() so that we can use 122 * them while booting the kernel, and stay at the same address 123 * throughout whole kernel's life time. 124 * 125 * We use this table twice; once with bootstrap page table, and once 126 * with kernel's page table which we build up in initarm(). 127 * 128 * Since we map these registers into the bootstrap page table using 129 * pmap_devmap_bootstrap() which calls pmap_map_chunk(), we map 130 * registers segment-aligned and segment-rounded in order to avoid 131 * using the 2nd page tables. 132 */ 133 134 static const struct pmap_devmap devmap[] = { 135 { 136 KERNEL_IO_IOREG_VBASE, 137 BCM53XX_IOREG_PBASE, /* 0x18000000 */ 138 BCM53XX_IOREG_SIZE, /* 2MB */ 139 VM_PROT_READ|VM_PROT_WRITE, 140 PTE_NOCACHE, 141 }, 142 { 143 KERNEL_IO_ARMCORE_VBASE, 144 BCM53XX_ARMCORE_PBASE, /* 0x19000000 */ 145 BCM53XX_ARMCORE_SIZE, /* 1MB */ 146 VM_PROT_READ|VM_PROT_WRITE, 147 PTE_NOCACHE, 148 }, 149 #if NPCI > 0 150 { 151 KERNEL_IO_PCIE0_OWIN_VBASE, 152 BCM53XX_PCIE0_OWIN_PBASE, /* 0x08000000 */ 153 BCM53XX_PCIE0_OWIN_SIZE, /* 4MB */ 154 VM_PROT_READ|VM_PROT_WRITE, 155 PTE_NOCACHE, 156 }, 157 { 158 KERNEL_IO_PCIE1_OWIN_VBASE, 159 BCM53XX_PCIE1_OWIN_PBASE, /* 0x40000000 */ 160 BCM53XX_PCIE1_OWIN_SIZE, /* 4MB */ 161 VM_PROT_READ|VM_PROT_WRITE, 162 PTE_NOCACHE, 163 }, 164 { 165 KERNEL_IO_PCIE2_OWIN_VBASE, 166 BCM53XX_PCIE2_OWIN_PBASE, /* 0x48000000 */ 167 BCM53XX_PCIE2_OWIN_SIZE, /* 4MB */ 168 VM_PROT_READ|VM_PROT_WRITE, 169 PTE_NOCACHE, 170 }, 171 #endif /* NPCI > 0 */ 172 { 0, 0, 0, 0, 0 } 173 }; 174 175 static const struct boot_physmem bp_first256 = { 176 .bp_start = 0x80000000 / NBPG, 177 .bp_pages = 0x10000000 / NBPG, 178 .bp_freelist = VM_FREELIST_ISADMA, 179 .bp_flags = 0, 180 }; 181 182 /* 183 * u_int initarm(...) 184 * 185 * Initial entry point on startup. This gets called before main() is 186 * entered. 187 * It should be responsible for setting up everything that must be 188 * in place when main is called. 189 * This includes 190 * Taking a copy of the boot configuration structure. 191 * Initialising the physical console so characters can be printed. 192 * Setting up page tables for the kernel 193 */ 194 u_int 195 initarm(void *arg) 196 { 197 pmap_devmap_register(devmap); 198 bcm53xx_bootstrap(KERNEL_IO_IOREG_VBASE); 199 200 #ifdef MULTIPROCESSOR 201 uint32_t scu_cfg = bus_space_read_4(bcm53xx_armcore_bst, bcm53xx_armcore_bsh, 202 ARMCORE_SCU_BASE + SCU_CFG); 203 arm_cpu_max = 1 + (scu_cfg & SCU_CFG_CPUMAX); 204 membar_producer(); 205 #endif 206 /* 207 * Heads up ... Setup the CPU / MMU / TLB functions 208 */ 209 if (set_cpufuncs()) // starts PMC counter 210 panic("cpu not recognized!"); 211 212 cpu_domains((DOMAIN_CLIENT << (PMAP_DOMAIN_KERNEL*2)) | DOMAIN_CLIENT); 213 214 consinit(); 215 216 bcm53xx_cpu_softc_init(curcpu()); 217 bcm53xx_print_clocks(); 218 219 #if NBCMRNG_CCB > 0 220 /* 221 * Start this early since it takes a while to startup up. 222 */ 223 bcm53xx_rng_start(bcm53xx_ioreg_bst, bcm53xx_ioreg_bsh); 224 #endif 225 226 printf("uboot arg = %#x, %#x, %#x, %#x\n", 227 uboot_args[0], uboot_args[1], uboot_args[2], uboot_args[3]); 228 229 /* Talk to the user */ 230 printf("\nNetBSD/evbarm (" ___STRING(EVBARM_BOARDTYPE) ") booting ...\n"); 231 232 bootargs[0] = '\0'; 233 234 #if defined(VERBOSE_INIT_ARM) || 1 235 printf("initarm: Configuring system"); 236 #ifdef MULTIPROCESSOR 237 printf(" (%u cpu%s, hatched %#x)", 238 arm_cpu_max + 1, arm_cpu_max + 1 ? "s" : "", 239 arm_cpu_hatched); 240 #endif 241 printf(", CLIDR=%010o CTR=%#x PMUSERSR=%#x", 242 armreg_clidr_read(), armreg_ctr_read(), armreg_pmuserenr_read()); 243 printf("\n"); 244 #endif 245 246 psize_t memsize = bcm53xx_memprobe(); 247 #ifdef MEMSIZE 248 if ((memsize >> 20) > MEMSIZE) 249 memsize = MEMSIZE*1024*1024; 250 #endif 251 const bool bigmem_p = (memsize >> 20) > 256; 252 253 #ifdef __HAVE_MM_MD_DIRECT_MAPPED_PHYS 254 const bool mapallmem_p = true; 255 #ifndef PMAP_NEED_ALLOC_POOLPAGE 256 if (memsize > KERNEL_VM_BASE - KERNEL_BASE) { 257 printf("%s: dropping RAM size from %luMB to %uMB\n", 258 __func__, (unsigned long) (ram_size >> 20), 259 (KERNEL_VM_BASE - KERNEL_BASE) >> 20); 260 memsize = KERNEL_VM_BASE - KERNEL_BASE; 261 } 262 #endif 263 #else 264 const bool mapallmem_p = false; 265 #endif 266 KASSERT((armreg_pfr1_read() & ARM_PFR1_SEC_MASK) != 0); 267 arm32_bootmem_init(KERN_VTOPHYS(KERNEL_BASE), memsize, 268 (paddr_t)KERNEL_BASE_phys); 269 270 bcm53xx_dma_bootstrap(memsize); 271 272 /* 273 * This is going to do all the hard work of setting up the first and 274 * and second level page tables. Pages of memory will be allocated 275 * and mapped for other structures that are required for system 276 * operation. When it returns, physical_freestart and free_pages will 277 * have been updated to reflect the allocations that were made. In 278 * addition, kernel_l1pt, kernel_pt_table[], systempage, irqstack, 279 * abtstack, undstack, kernelstack, msgbufphys will be set to point to 280 * the memory that was allocated for them. 281 */ 282 arm32_kernel_vm_init(KERNEL_VM_BASE, ARM_VECTORS_HIGH, 0, devmap, 283 mapallmem_p); 284 285 cpu_reset_address = bcm53xx_system_reset; 286 /* we've a specific device_register routine */ 287 evbarm_device_register = bcm53xx_device_register; 288 if (bigmem_p) { 289 /* 290 * If we have more than 256MB 291 */ 292 arm_poolpage_vmfreelist = bp_first256.bp_freelist; 293 } 294 295 /* 296 * If we have more than 256MB of RAM, set aside the first 256MB for 297 * non-default VM allocations. 298 */ 299 return initarm_common(KERNEL_VM_BASE, KERNEL_VM_SIZE, 300 (bigmem_p ? &bp_first256 : NULL), (bigmem_p ? 1 : 0)); 301 } 302 303 void 304 consinit(void) 305 { 306 static bool consinit_called = false; 307 uint32_t v; 308 if (consinit_called) 309 return; 310 311 consinit_called = true; 312 313 /* 314 * Force UART clock to the reference clock 315 */ 316 v = bus_space_read_4(bcm53xx_ioreg_bst, bcm53xx_ioreg_bsh, 317 IDM_BASE + IDM_APBX_BASE + IDM_IO_CONTROL_DIRECT); 318 v &= ~IO_CONTROL_DIRECT_UARTCLKSEL; 319 bus_space_write_4(bcm53xx_ioreg_bst, bcm53xx_ioreg_bsh, 320 IDM_BASE + IDM_APBX_BASE + IDM_IO_CONTROL_DIRECT, v); 321 322 /* 323 * Switch to the reference clock 324 */ 325 v = bus_space_read_4(bcm53xx_ioreg_bst, bcm53xx_ioreg_bsh, 326 CCA_MISC_BASE + MISC_CORECTL); 327 v &= ~CORECTL_UART_CLK_OVERRIDE; 328 bus_space_write_4(bcm53xx_ioreg_bst, bcm53xx_ioreg_bsh, 329 CCA_MISC_BASE + MISC_CORECTL, v); 330 331 if (comcnattach(bcm53xx_ioreg_bst, comcnaddr, comcnspeed, 332 BCM53XX_REF_CLK, COM_TYPE_NORMAL, comcnmode)) 333 panic("Serial console can not be initialized."); 334 } 335 336 static void 337 bcm53xx_system_reset(void) 338 { 339 bus_space_write_4(bcm53xx_ioreg_bst, bcm53xx_ioreg_bsh, 340 MISC_WATCHDOG, 1); 341 } 342