1/* $NetBSD: machdep.c,v 1.15 2024/03/05 14:15:31 thorpej Exp $ */ 2 3/*- 4 * Copyright (c) 2011 CradlePoint Technology, Inc. 5 * All rights reserved. 6 * 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions 10 * are met: 11 * 1. Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer. 13 * 2. Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in the 15 * documentation and/or other materials provided with the distribution. 16 * 17 * THIS SOFTWARE IS PROVIDED BY CRADLEPOINT TECHNOLOGY, INC. AND CONTRIBUTORS 18 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 19 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 20 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS 21 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 22 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 23 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 24 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 25 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 26 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 27 * POSSIBILITY OF SUCH DAMAGE. 28 */ 29 30#include <sys/cdefs.h> /* RCS ID & Copyright macro defns */ 31__KERNEL_RCSID(0, "$NetBSD: machdep.c,v 1.15 2024/03/05 14:15:31 thorpej Exp $"); 32 33#include <sys/param.h> 34#include <sys/boot_flag.h> 35#include <sys/buf.h> 36#include <sys/cpu.h> 37#include <sys/device.h> 38#include <sys/mount.h> 39#include <sys/kcore.h> 40#include <sys/reboot.h> 41#include <sys/systm.h> 42#include <sys/kernel.h> 43#include <sys/termios.h> 44 45#include <uvm/uvm_extern.h> 46 47#include <dev/cons.h> 48 49#include <mips/cache.h> 50#include <mips/locore.h> 51#include <mips/cpuregs.h> 52 53#include <mips/ralink/ralink_reg.h> 54#include <mips/ralink/ralink_var.h> 55 56/* structures we define/alloc for other files in the kernel */ 57struct vm_map *phys_map = NULL; 58 59int mem_cluster_cnt = 0; 60phys_ram_seg_t mem_clusters[VM_PHYSSEG_MAX]; 61 62void mach_init(void); 63 64static inline uint32_t 65sysctl_read(u_int offset) 66{ 67 return *RA_IOREG_VADDR(RA_SYSCTL_BASE, offset); 68} 69 70static inline void 71sysctl_write(u_int offset, uint32_t val) 72{ 73 *RA_IOREG_VADDR(RA_SYSCTL_BASE, offset) = val; 74} 75 76static void 77cal_timer(void) 78{ 79 uint32_t cntfreq; 80 81 cntfreq = curcpu()->ci_cpu_freq = RA_CLOCK_RATE; 82 83 /* MIPS 4Kc CP0 counts every other clock */ 84 if (mips_options.mips_cpu_flags & CPU_MIPS_DOUBLE_COUNT) 85 cntfreq /= 2; 86 87 curcpu()->ci_cycles_per_hz = (cntfreq + hz / 2) / hz; 88 89 /* Compute number of cycles per 1us (1/MHz). 0.5MHz is for roundup. */ 90 curcpu()->ci_divisor_delay = ((cntfreq + 500000) / 1000000); 91} 92 93void 94mach_init(void) 95{ 96 vaddr_t kernend; 97 psize_t memsize; 98 99 extern char kernel_text[]; 100 extern char edata[], end[]; /* From Linker */ 101 102 /* clear the BSS segment */ 103 kernend = mips_round_page(end); 104 105 memset(edata, 0, kernend - (vaddr_t)edata); 106 107#ifdef RALINK_CONSOLE_EARLY 108 /* 109 * set up early console 110 * cannot printf until sometime (?) in mips_vector_init 111 * meanwhile can use the ra_console_putc primitive if necessary 112 */ 113 ralink_console_early(); 114#endif 115 116 /* set CPU model info for sysctl_hw */ 117 uint32_t tmp1, tmp2; 118 char id1[5], id2[5]; 119 tmp1 = sysctl_read(RA_SYSCTL_ID0); 120 memcpy(id1, &tmp1, sizeof(tmp1)); 121 tmp2 = sysctl_read(RA_SYSCTL_ID1); 122 memcpy(id2, &tmp2, sizeof(tmp2)); 123 id2[4] = id1[4] = '\0'; 124 if (id2[2] == ' ') { 125 id2[2] = '\0'; 126 } else if (id2[3] == ' ') { 127 id2[3] = '\0'; 128 } else { 129 id2[4] = '\0'; 130 } 131 cpu_setmodel("%s%s", id1, id2); 132 133 /* 134 * Set up the exception vectors and CPU-specific function 135 * vectors early on. We need the wbflush() vector set up 136 * before comcnattach() is called (or at least before the 137 * first printf() after that is called). 138 * Sets up mips_cpu_flags that may be queried by other 139 * functions called during startup. 140 * Also clears the I+D caches. 141 */ 142 mips_vector_init(NULL, false); 143 144 /* 145 * Calibrate timers. 146 */ 147 cal_timer(); 148 149 uvm_md_init(); 150 151 /* 152 * Look at arguments passed to us and compute boothowto. 153 */ 154 boothowto = RB_AUTOBOOT; 155#ifdef KADB 156 boothowto |= RB_KDB; 157#endif 158 159 /* 160 * Determine the memory size. 161 */ 162#if defined(MT7620) || defined(MT7628) 163 memsize = 128 << 20; 164#else 165 memsize = *(volatile uint32_t *) 166 MIPS_PHYS_TO_KSEG1(RA_SYSCTL_BASE + RA_SYSCTL_CFG0); 167 memsize = __SHIFTOUT(memsize, SYSCTL_CFG0_DRAM_SIZE); 168 if (__predict_false(memsize == 0)) { 169 memsize = 2 << 20; 170 } else { 171 memsize = 4 << (20 + memsize); 172 } 173#endif 174 175 physmem = btoc(memsize); 176 177 mem_clusters[mem_cluster_cnt].start = 0; 178 mem_clusters[mem_cluster_cnt].size = memsize; 179 mem_cluster_cnt++; 180 181 /* 182 * Load the memory into the VM system 183 */ 184 mips_page_physload((vaddr_t)kernel_text, kernend, 185 mem_clusters, mem_cluster_cnt, 186 NULL, 0); 187 188 /* 189 * Initialize message buffer (at end of core). 190 */ 191 mips_init_msgbuf(); 192 193 /* 194 * Initialize the virtual memory system. 195 */ 196 pmap_bootstrap(); 197 198 /* 199 * Init mapping for u page(s) for proc0. 200 */ 201 mips_init_lwp0_uarea(); 202 203 /* 204 * Initialize busses. 205 */ 206 ra_bus_init(); 207 208#ifdef DDB 209 if (boothowto & RB_KDB) 210 Debugger(); 211#endif 212} 213 214void 215cpu_startup(void) 216{ 217 cpu_startup_common(); 218} 219 220void 221cpu_reboot(int howto, char *bootstr) 222{ 223 static int waittime = -1; 224 225 /* Take a snapshot before clobbering any registers. */ 226 savectx(lwp_getpcb(curlwp)); 227 228 /* If "always halt" was specified as a boot flag, obey. */ 229 if (boothowto & RB_HALT) 230 howto |= RB_HALT; 231 232 boothowto = howto; 233 234 /* If system is cold, just halt. */ 235 if (cold) { 236 boothowto |= RB_HALT; 237 goto haltsys; 238 } 239 240 if ((boothowto & RB_NOSYNC) == 0 && waittime < 0) { 241 waittime = 0; 242 243 /* 244 * Synchronize the disks.... 245 */ 246 vfs_shutdown(); 247 } 248 249 /* Disable interrupts. */ 250 splhigh(); 251 252 if (boothowto & RB_DUMP) 253 dumpsys(); 254 255 haltsys: 256 /* Run any shutdown hooks. */ 257 doshutdownhooks(); 258 259 pmf_system_shutdown(boothowto); 260 261 /* 262 * Firmware may autoboot (depending on settings), and we cannot pass 263 * flags to it (at least I haven't figured out how to yet), so 264 * we "pseudo-halt" now. 265 */ 266 if (boothowto & RB_HALT) { 267 printf("\n"); 268 printf("The operating system has halted.\n"); 269 printf("Please press any key to reboot.\n\n"); 270 cnpollc(1); /* For proper keyboard command handling */ 271 cngetc(); 272 cnpollc(0); 273 } 274 275 printf("resetting board...\n\n"); 276 mips_icache_sync_all(); 277 mips_dcache_wbinv_all(); 278 279 sysctl_write(RA_SYSCTL_RST, 1); /* SoC Reset */ 280 sysctl_write(RA_SYSCTL_RST, 0); 281 282#if 0 283 __asm volatile("jr %0" :: "r"(MIPS_RESET_EXC_VEC)); 284#endif 285 printf("Oops, back from reset\n\nSpinning..."); 286 for (;;) 287 /* spin forever */ ; /* XXX */ 288 /*NOTREACHED*/ 289} 290 291#define NO_SECURITY_MAGIC 0x27051958 292#define SERIAL_MAGIC 0x100000 293int 294ra_check_memo_reg(int key) 295{ 296 uint32_t magic; 297 298 /* 299 * These registers may be overwritten. Keep the value around in case 300 * it is used later. Bitmask 1 == security, 2 = serial 301 */ 302 static int keyvalue; 303 304 switch (key) { 305 case NO_SECURITY: 306 magic = sysctl_read(RA_SYSCTL_MEMO0); 307 if ((NO_SECURITY_MAGIC == magic) || ((keyvalue & 1) != 0)) { 308 keyvalue |= 1; 309 return 1; 310 } 311 return 0; 312 break; 313 314 case SERIAL_CONSOLE: 315 magic = sysctl_read(RA_SYSCTL_MEMO1); 316 if (magic == 0 317 || (SERIAL_MAGIC & magic) != 0 318 || (keyvalue & 2) != 0) { 319 keyvalue |= 2; 320 return 1; 321 } 322 return 0; 323 break; 324 325 default: 326 return 0; 327 } 328 329} 330