1/* 2 * allow a console to be used for early printk 3 * derived from arch/x86/kernel/early_printk.c 4 * 5 * Copyright 2007-2009 Analog Devices Inc. 6 * 7 * Licensed under the GPL-2 8 */ 9 10#include <linux/kernel.h> 11#include <linux/init.h> 12#include <linux/serial_core.h> 13#include <linux/console.h> 14#include <linux/string.h> 15#include <linux/reboot.h> 16#include <asm/blackfin.h> 17#include <asm/irq_handler.h> 18#include <asm/early_printk.h> 19 20#ifdef CONFIG_SERIAL_BFIN 21extern struct console *bfin_earlyserial_init(unsigned int port, 22 unsigned int cflag); 23#endif 24#ifdef CONFIG_BFIN_JTAG_COMM 25extern struct console *bfin_jc_early_init(void); 26#endif 27 28/* Default console */ 29#define DEFAULT_PORT 0 30#define DEFAULT_CFLAG CS8|B57600 31 32/* Default console for early crashes */ 33#define DEFAULT_EARLY_PORT "serial,uart0,57600" 34 35#ifdef CONFIG_SERIAL_CORE 36/* What should get here is "0,57600" */ 37static struct console * __init earlyserial_init(char *buf) 38{ 39 int baud, bit; 40 char parity; 41 unsigned int serial_port = DEFAULT_PORT; 42 unsigned int cflag = DEFAULT_CFLAG; 43 44 serial_port = simple_strtoul(buf, &buf, 10); 45 buf++; 46 47 cflag = 0; 48 baud = simple_strtoul(buf, &buf, 10); 49 switch (baud) { 50 case 1200: 51 cflag |= B1200; 52 break; 53 case 2400: 54 cflag |= B2400; 55 break; 56 case 4800: 57 cflag |= B4800; 58 break; 59 case 9600: 60 cflag |= B9600; 61 break; 62 case 19200: 63 cflag |= B19200; 64 break; 65 case 38400: 66 cflag |= B38400; 67 break; 68 case 115200: 69 cflag |= B115200; 70 break; 71 default: 72 cflag |= B57600; 73 } 74 75 parity = buf[0]; 76 buf++; 77 switch (parity) { 78 case 'e': 79 cflag |= PARENB; 80 break; 81 case 'o': 82 cflag |= PARODD; 83 break; 84 } 85 86 bit = simple_strtoul(buf, &buf, 10); 87 switch (bit) { 88 case 5: 89 cflag |= CS5; 90 break; 91 case 6: 92 cflag |= CS6; 93 break; 94 case 7: 95 cflag |= CS7; 96 break; 97 default: 98 cflag |= CS8; 99 } 100 101#ifdef CONFIG_SERIAL_BFIN 102 return bfin_earlyserial_init(serial_port, cflag); 103#else 104 return NULL; 105#endif 106 107} 108#endif 109 110int __init setup_early_printk(char *buf) 111{ 112 113 /* Crashing in here would be really bad, so check both the var 114 and the pointer before we start using it 115 */ 116 if (!buf) 117 return 0; 118 119 if (!*buf) 120 return 0; 121 122 if (early_console != NULL) 123 return 0; 124 125#ifdef CONFIG_SERIAL_BFIN 126 /* Check for Blackfin Serial */ 127 if (!strncmp(buf, "serial,uart", 11)) { 128 buf += 11; 129 early_console = earlyserial_init(buf); 130 } 131#endif 132 133#ifdef CONFIG_BFIN_JTAG_COMM 134 /* Check for Blackfin JTAG */ 135 if (!strncmp(buf, "jtag", 4)) { 136 buf += 4; 137 early_console = bfin_jc_early_init(); 138 } 139#endif 140 141#ifdef CONFIG_FB 142 /* TODO: add framebuffer console support */ 143#endif 144 145 if (likely(early_console)) { 146 early_console->flags |= CON_BOOT; 147 148 register_console(early_console); 149 printk(KERN_INFO "early printk enabled on %s%d\n", 150 early_console->name, 151 early_console->index); 152 } 153 154 return 0; 155} 156 157/* 158 * Set up a temporary Event Vector Table, so if something bad happens before 159 * the kernel is fully started, it doesn't vector off into somewhere we don't 160 * know 161 */ 162 163asmlinkage void __init init_early_exception_vectors(void) 164{ 165 u32 evt; 166 SSYNC(); 167 168 /* 169 * This starts up the shadow buffer, incase anything crashes before 170 * setup arch 171 */ 172 mark_shadow_error(); 173 early_shadow_puts(linux_banner); 174 early_shadow_stamp(); 175 176 if (CPUID != bfin_cpuid()) { 177 early_shadow_puts("Running on wrong machine type, expected"); 178 early_shadow_reg(CPUID, 16); 179 early_shadow_puts(", but running on"); 180 early_shadow_reg(bfin_cpuid(), 16); 181 early_shadow_puts("\n"); 182 } 183 184 /* cannot program in software: 185 * evt0 - emulation (jtag) 186 * evt1 - reset 187 */ 188 for (evt = EVT2; evt <= EVT15; evt += 4) 189 bfin_write32(evt, early_trap); 190 CSYNC(); 191 192 /* Set all the return from interrupt, exception, NMI to a known place 193 * so if we do a RETI, RETX or RETN by mistake - we go somewhere known 194 * Note - don't change RETS - we are in a subroutine, or 195 * RETE - since it might screw up if emulator is attached 196 */ 197 asm("\tRETI = %0; RETX = %0; RETN = %0;\n" 198 : : "p"(early_trap)); 199 200} 201 202__attribute__((__noreturn__)) 203asmlinkage void __init early_trap_c(struct pt_regs *fp, void *retaddr) 204{ 205 /* This can happen before the uart is initialized, so initialize 206 * the UART now (but only if we are running on the processor we think 207 * we are compiled for - otherwise we write to MMRs that don't exist, 208 * and cause other problems. Nothing comes out the UART, but it does 209 * end up in the __buf_log. 210 */ 211 if (likely(early_console == NULL) && CPUID == bfin_cpuid()) 212 setup_early_printk(DEFAULT_EARLY_PORT); 213 214 if (!shadow_console_enabled()) { 215 /* crap - we crashed before setup_arch() */ 216 early_shadow_puts("panic before setup_arch\n"); 217 early_shadow_puts("IPEND:"); 218 early_shadow_reg(fp->ipend, 16); 219 if (fp->seqstat & SEQSTAT_EXCAUSE) { 220 early_shadow_puts("\nEXCAUSE:"); 221 early_shadow_reg(fp->seqstat & SEQSTAT_EXCAUSE, 8); 222 } 223 if (fp->seqstat & SEQSTAT_HWERRCAUSE) { 224 early_shadow_puts("\nHWERRCAUSE:"); 225 early_shadow_reg( 226 (fp->seqstat & SEQSTAT_HWERRCAUSE) >> 14, 8); 227 } 228 early_shadow_puts("\nErr @"); 229 if (fp->ipend & EVT_EVX) 230 early_shadow_reg(fp->retx, 32); 231 else 232 early_shadow_reg(fp->pc, 32); 233#ifdef CONFIG_DEBUG_BFIN_HWTRACE_ON 234 early_shadow_puts("\nTrace:"); 235 if (likely(bfin_read_TBUFSTAT() & TBUFCNT)) { 236 while (bfin_read_TBUFSTAT() & TBUFCNT) { 237 early_shadow_puts("\nT :"); 238 early_shadow_reg(bfin_read_TBUF(), 32); 239 early_shadow_puts("\n S :"); 240 early_shadow_reg(bfin_read_TBUF(), 32); 241 } 242 } 243#endif 244 early_shadow_puts("\nUse bfin-elf-addr2line to determine " 245 "function names\n"); 246 /* 247 * We should panic(), but we can't - since panic calls printk, 248 * and printk uses memcpy. 249 * we want to reboot, but if the machine type is different, 250 * can't due to machine specific reboot sequences 251 */ 252 if (CPUID == bfin_cpuid()) { 253 early_shadow_puts("Trying to restart\n"); 254 machine_restart(""); 255 } 256 257 early_shadow_puts("Halting, since it is not safe to restart\n"); 258 while (1) 259 asm volatile ("EMUEXCPT; IDLE;\n"); 260 261 } else { 262 printk(KERN_EMERG "Early panic\n"); 263 show_regs(fp); 264 dump_bfin_trace_buffer(); 265 } 266 267 panic("Died early"); 268} 269 270early_param("earlyprintk", setup_early_printk); 271