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