linux/arch/blackfin/kernel/early_printk.c
<<
>>
Prefs
   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