Path: blob/master/arch/blackfin/kernel/early_printk.c
10817 views
/*1* allow a console to be used for early printk2* derived from arch/x86/kernel/early_printk.c3*4* Copyright 2007-2009 Analog Devices Inc.5*6* Licensed under the GPL-27*/89#include <linux/kernel.h>10#include <linux/init.h>11#include <linux/serial_core.h>12#include <linux/console.h>13#include <linux/string.h>14#include <linux/reboot.h>15#include <asm/blackfin.h>16#include <asm/irq_handler.h>17#include <asm/early_printk.h>1819#ifdef CONFIG_SERIAL_BFIN20extern struct console *bfin_earlyserial_init(unsigned int port,21unsigned int cflag);22#endif23#ifdef CONFIG_BFIN_JTAG_COMM24extern struct console *bfin_jc_early_init(void);25#endif2627static struct console *early_console;2829/* Default console */30#define DEFAULT_PORT 031#define DEFAULT_CFLAG CS8|B576003233/* Default console for early crashes */34#define DEFAULT_EARLY_PORT "serial,uart0,57600"3536#ifdef CONFIG_SERIAL_CORE37/* What should get here is "0,57600" */38static struct console * __init earlyserial_init(char *buf)39{40int baud, bit;41char parity;42unsigned int serial_port = DEFAULT_PORT;43unsigned int cflag = DEFAULT_CFLAG;4445serial_port = simple_strtoul(buf, &buf, 10);46buf++;4748cflag = 0;49baud = simple_strtoul(buf, &buf, 10);50switch (baud) {51case 1200:52cflag |= B1200;53break;54case 2400:55cflag |= B2400;56break;57case 4800:58cflag |= B4800;59break;60case 9600:61cflag |= B9600;62break;63case 19200:64cflag |= B19200;65break;66case 38400:67cflag |= B38400;68break;69case 115200:70cflag |= B115200;71break;72default:73cflag |= B57600;74}7576parity = buf[0];77buf++;78switch (parity) {79case 'e':80cflag |= PARENB;81break;82case 'o':83cflag |= PARODD;84break;85}8687bit = simple_strtoul(buf, &buf, 10);88switch (bit) {89case 5:90cflag |= CS5;91break;92case 6:93cflag |= CS6;94break;95case 7:96cflag |= CS7;97break;98default:99cflag |= CS8;100}101102#ifdef CONFIG_SERIAL_BFIN103return bfin_earlyserial_init(serial_port, cflag);104#else105return NULL;106#endif107108}109#endif110111int __init setup_early_printk(char *buf)112{113114/* Crashing in here would be really bad, so check both the var115and the pointer before we start using it116*/117if (!buf)118return 0;119120if (!*buf)121return 0;122123if (early_console != NULL)124return 0;125126#ifdef CONFIG_SERIAL_BFIN127/* Check for Blackfin Serial */128if (!strncmp(buf, "serial,uart", 11)) {129buf += 11;130early_console = earlyserial_init(buf);131}132#endif133134#ifdef CONFIG_BFIN_JTAG_COMM135/* Check for Blackfin JTAG */136if (!strncmp(buf, "jtag", 4)) {137buf += 4;138early_console = bfin_jc_early_init();139}140#endif141142#ifdef CONFIG_FB143/* TODO: add framebuffer console support */144#endif145146if (likely(early_console)) {147early_console->flags |= CON_BOOT;148149register_console(early_console);150printk(KERN_INFO "early printk enabled on %s%d\n",151early_console->name,152early_console->index);153}154155return 0;156}157158/*159* Set up a temporary Event Vector Table, so if something bad happens before160* the kernel is fully started, it doesn't vector off into somewhere we don't161* know162*/163164asmlinkage void __init init_early_exception_vectors(void)165{166u32 evt;167SSYNC();168169/*170* This starts up the shadow buffer, incase anything crashes before171* setup arch172*/173mark_shadow_error();174early_shadow_puts(linux_banner);175early_shadow_stamp();176177if (CPUID != bfin_cpuid()) {178early_shadow_puts("Running on wrong machine type, expected");179early_shadow_reg(CPUID, 16);180early_shadow_puts(", but running on");181early_shadow_reg(bfin_cpuid(), 16);182early_shadow_puts("\n");183}184185/* cannot program in software:186* evt0 - emulation (jtag)187* evt1 - reset188*/189for (evt = EVT2; evt <= EVT15; evt += 4)190bfin_write32(evt, early_trap);191CSYNC();192193/* Set all the return from interrupt, exception, NMI to a known place194* so if we do a RETI, RETX or RETN by mistake - we go somewhere known195* Note - don't change RETS - we are in a subroutine, or196* RETE - since it might screw up if emulator is attached197*/198asm("\tRETI = %0; RETX = %0; RETN = %0;\n"199: : "p"(early_trap));200201}202203__attribute__((__noreturn__))204asmlinkage void __init early_trap_c(struct pt_regs *fp, void *retaddr)205{206/* This can happen before the uart is initialized, so initialize207* the UART now (but only if we are running on the processor we think208* we are compiled for - otherwise we write to MMRs that don't exist,209* and cause other problems. Nothing comes out the UART, but it does210* end up in the __buf_log.211*/212if (likely(early_console == NULL) && CPUID == bfin_cpuid())213setup_early_printk(DEFAULT_EARLY_PORT);214215if (!shadow_console_enabled()) {216/* crap - we crashed before setup_arch() */217early_shadow_puts("panic before setup_arch\n");218early_shadow_puts("IPEND:");219early_shadow_reg(fp->ipend, 16);220if (fp->seqstat & SEQSTAT_EXCAUSE) {221early_shadow_puts("\nEXCAUSE:");222early_shadow_reg(fp->seqstat & SEQSTAT_EXCAUSE, 8);223}224if (fp->seqstat & SEQSTAT_HWERRCAUSE) {225early_shadow_puts("\nHWERRCAUSE:");226early_shadow_reg(227(fp->seqstat & SEQSTAT_HWERRCAUSE) >> 14, 8);228}229early_shadow_puts("\nErr @");230if (fp->ipend & EVT_EVX)231early_shadow_reg(fp->retx, 32);232else233early_shadow_reg(fp->pc, 32);234#ifdef CONFIG_DEBUG_BFIN_HWTRACE_ON235early_shadow_puts("\nTrace:");236if (likely(bfin_read_TBUFSTAT() & TBUFCNT)) {237while (bfin_read_TBUFSTAT() & TBUFCNT) {238early_shadow_puts("\nT :");239early_shadow_reg(bfin_read_TBUF(), 32);240early_shadow_puts("\n S :");241early_shadow_reg(bfin_read_TBUF(), 32);242}243}244#endif245early_shadow_puts("\nUse bfin-elf-addr2line to determine "246"function names\n");247/*248* We should panic(), but we can't - since panic calls printk,249* and printk uses memcpy.250* we want to reboot, but if the machine type is different,251* can't due to machine specific reboot sequences252*/253if (CPUID == bfin_cpuid()) {254early_shadow_puts("Trying to restart\n");255machine_restart("");256}257258early_shadow_puts("Halting, since it is not safe to restart\n");259while (1)260asm volatile ("EMUEXCPT; IDLE;\n");261262} else {263printk(KERN_EMERG "Early panic\n");264show_regs(fp);265dump_bfin_trace_buffer();266}267268panic("Died early");269}270271early_param("earlyprintk", setup_early_printk);272273274