malta_machdep.c revision 255088
1/*- 2 * Copyright (c) 2006 Wojciech A. Koszek <wkoszek@FreeBSD.org> 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24 * SUCH DAMAGE. 25 * 26 * $FreeBSD: head/sys/mips/malta/malta_machdep.c 255088 2013-08-31 01:24:05Z gonzo $ 27 */ 28#include <sys/cdefs.h> 29__FBSDID("$FreeBSD: head/sys/mips/malta/malta_machdep.c 255088 2013-08-31 01:24:05Z gonzo $"); 30 31#include "opt_ddb.h" 32 33#include <sys/param.h> 34#include <sys/conf.h> 35#include <sys/kernel.h> 36#include <sys/systm.h> 37#include <sys/imgact.h> 38#include <sys/bio.h> 39#include <sys/buf.h> 40#include <sys/bus.h> 41#include <sys/cpu.h> 42#include <sys/cons.h> 43#include <sys/exec.h> 44#include <sys/ucontext.h> 45#include <sys/proc.h> 46#include <sys/kdb.h> 47#include <sys/ptrace.h> 48#include <sys/reboot.h> 49#include <sys/signalvar.h> 50#include <sys/sysent.h> 51#include <sys/sysproto.h> 52#include <sys/user.h> 53 54#include <vm/vm.h> 55#include <vm/vm_object.h> 56#include <vm/vm_page.h> 57 58#include <machine/clock.h> 59#include <machine/cpu.h> 60#include <machine/cpuregs.h> 61#include <machine/hwfunc.h> 62#include <machine/md_var.h> 63#include <machine/pmap.h> 64#include <machine/trap.h> 65 66#ifdef TICK_USE_YAMON_FREQ 67#include <mips/malta/yamon.h> 68#endif 69 70#ifdef TICK_USE_MALTA_RTC 71#include <mips/mips4k/malta/maltareg.h> 72#include <dev/mc146818/mc146818reg.h> 73#include <isa/rtc.h> 74#endif 75 76#include <mips/malta/maltareg.h> 77 78extern int *edata; 79extern int *end; 80 81void lcd_init(void); 82void lcd_puts(char *); 83void malta_reset(void); 84 85/* 86 * Temporary boot environment used at startup. 87 */ 88static char boot1_env[4096]; 89 90/* 91 * Offsets to MALTA LCD characters. 92 */ 93static int malta_lcd_offs[] = { 94 MALTA_ASCIIPOS0, 95 MALTA_ASCIIPOS1, 96 MALTA_ASCIIPOS2, 97 MALTA_ASCIIPOS3, 98 MALTA_ASCIIPOS4, 99 MALTA_ASCIIPOS5, 100 MALTA_ASCIIPOS6, 101 MALTA_ASCIIPOS7 102}; 103 104void 105platform_cpu_init() 106{ 107 /* Nothing special */ 108} 109 110/* 111 * Put character to Malta LCD at given position. 112 */ 113static void 114malta_lcd_putc(int pos, char c) 115{ 116 void *addr; 117 char *ch; 118 119 if (pos < 0 || pos > 7) 120 return; 121 addr = (void *)(MALTA_ASCII_BASE + malta_lcd_offs[pos]); 122 ch = (char *)MIPS_PHYS_TO_KSEG0(addr); 123 *ch = c; 124} 125 126/* 127 * Print given string on LCD. 128 */ 129static void 130malta_lcd_print(char *str) 131{ 132 int i; 133 134 if (str == NULL) 135 return; 136 137 for (i = 0; *str != '\0'; i++, str++) 138 malta_lcd_putc(i, *str); 139} 140 141void 142lcd_init(void) 143{ 144 malta_lcd_print("FreeBSD_"); 145} 146 147void 148lcd_puts(char *s) 149{ 150 malta_lcd_print(s); 151} 152 153#ifdef TICK_USE_MALTA_RTC 154static __inline uint8_t 155rtcin(uint8_t addr) 156{ 157 158 *((volatile uint8_t *) 159 MIPS_PHYS_TO_KSEG1(MALTA_PCI0_ADDR(MALTA_RTCADR))) = addr; 160 return (*((volatile uint8_t *) 161 MIPS_PHYS_TO_KSEG1(MALTA_PCI0_ADDR(MALTA_RTCDAT)))); 162} 163 164static __inline void 165writertc(uint8_t addr, uint8_t val) 166{ 167 168 *((volatile uint8_t *) 169 MIPS_PHYS_TO_KSEG1(MALTA_PCI0_ADDR(MALTA_RTCADR))) = addr; 170 *((volatile uint8_t *) 171 MIPS_PHYS_TO_KSEG1(MALTA_PCI0_ADDR(MALTA_RTCDAT))) = val; 172} 173#endif 174 175static void 176mips_init(void) 177{ 178 int i; 179 180 for (i = 0; i < 10; i++) { 181 phys_avail[i] = 0; 182 } 183 184 /* phys_avail regions are in bytes */ 185 phys_avail[0] = MIPS_KSEG0_TO_PHYS(kernel_kseg0_end); 186 phys_avail[1] = ctob(realmem); 187 188 dump_avail[0] = phys_avail[0]; 189 dump_avail[1] = phys_avail[1]; 190 191 physmem = realmem; 192 193 init_param1(); 194 init_param2(physmem); 195 mips_cpu_init(); 196 pmap_bootstrap(); 197 mips_proc0_init(); 198 mutex_init(); 199 kdb_init(); 200#ifdef KDB 201 if (boothowto & RB_KDB) 202 kdb_enter(KDB_WHY_BOOTFLAGS, "Boot flags requested debugger"); 203#endif 204} 205 206/* 207 * Perform a board-level soft-reset. 208 * Note that this is not emulated by gxemul. 209 */ 210void 211platform_reset(void) 212{ 213 char *c; 214 215 c = (char *)MIPS_PHYS_TO_KSEG0(MALTA_SOFTRES); 216 *c = MALTA_GORESET; 217} 218 219static uint64_t 220malta_cpu_freq(void) 221{ 222 uint64_t platform_counter_freq = 0; 223 224#if defined(TICK_USE_YAMON_FREQ) 225 /* 226 * If we are running on a board which uses YAMON firmware, 227 * then query CPU pipeline clock from the syscon object. 228 * If unsuccessful, use hard-coded default. 229 */ 230 platform_counter_freq = yamon_getcpufreq(); 231 232#elif defined(TICK_USE_MALTA_RTC) 233 /* 234 * If we are running on a board with the MC146818 RTC, 235 * use it to determine CPU pipeline clock frequency. 236 */ 237 u_int64_t counterval[2]; 238 239 /* Set RTC to binary mode. */ 240 writertc(RTC_STATUSB, (rtcin(RTC_STATUSB) | RTCSB_BCD)); 241 242 /* Busy-wait for falling edge of RTC update. */ 243 while (((rtcin(RTC_STATUSA) & RTCSA_TUP) == 0)) 244 ; 245 while (((rtcin(RTC_STATUSA)& RTCSA_TUP) != 0)) 246 ; 247 counterval[0] = mips_rd_count(); 248 249 /* Busy-wait for falling edge of RTC update. */ 250 while (((rtcin(RTC_STATUSA) & RTCSA_TUP) == 0)) 251 ; 252 while (((rtcin(RTC_STATUSA)& RTCSA_TUP) != 0)) 253 ; 254 counterval[1] = mips_rd_count(); 255 256 platform_counter_freq = counterval[1] - counterval[0]; 257#endif 258 259 if (platform_counter_freq == 0) 260 platform_counter_freq = MIPS_DEFAULT_HZ; 261 262 return (platform_counter_freq); 263} 264 265void 266platform_start(__register_t a0, __register_t a1, __register_t a2, 267 __register_t a3) 268{ 269 vm_offset_t kernend; 270 uint64_t platform_counter_freq; 271 int argc = a0; 272 int32_t *argv = (int32_t*)a1; 273 int32_t *envp = (int32_t*)a2; 274 unsigned int memsize = a3; 275 int i; 276 277 /* clear the BSS and SBSS segments */ 278 kernend = (vm_offset_t)&end; 279 memset(&edata, 0, kernend - (vm_offset_t)(&edata)); 280 281 mips_postboot_fixup(); 282 283 mips_pcpu0_init(); 284 platform_counter_freq = malta_cpu_freq(); 285 mips_timer_early_init(platform_counter_freq); 286 init_static_kenv(boot1_env, sizeof(boot1_env)); 287 288 cninit(); 289 printf("entry: platform_start()\n"); 290 291 bootverbose = 1; 292 /* 293 * YAMON uses 32bit pointers to strings so 294 * convert them to proper type manually 295 */ 296 if (bootverbose) { 297 printf("cmd line: "); 298 for (i = 0; i < argc; i++) 299 printf("%s ", (char*)(intptr_t)argv[i]); 300 printf("\n"); 301 302 printf("envp:\n"); 303 for (i = 0; envp[i]; i += 2) 304 printf("\t%s = %s\n", (char*)(intptr_t)envp[i], 305 (char*)(intptr_t)envp[i+1]); 306 307 printf("memsize = %08x\n", memsize); 308 } 309 310 realmem = btoc(memsize); 311 mips_init(); 312 313 mips_timer_init_params(platform_counter_freq, 0); 314} 315