diff options
author | Robin Getz <robin.getz@analog.com> | 2009-07-07 20:17:09 +0000 |
---|---|---|
committer | Mike Frysinger <vapier@gentoo.org> | 2009-09-16 21:31:44 -0400 |
commit | 837ec2d56c41640d1f1238e52c350b2a516d29ba (patch) | |
tree | 1732468388385c411853c67cb2b288c2f8d17cc7 /arch/blackfin/kernel/shadow_console.c | |
parent | 3f871feaf3390c6d6e578818f867917c2e4738a2 (diff) | |
download | blackbird-op-linux-837ec2d56c41640d1f1238e52c350b2a516d29ba.tar.gz blackbird-op-linux-837ec2d56c41640d1f1238e52c350b2a516d29ba.zip |
Blackfin: catch hardware errors earlier during booting
Allow hardware errors to be caught during early portions of booting, and
leave something in the shadow console that people can use to debug their
system with (to be printed out by the bootloader on next reset).
This enables the hardare error interrupts in head.S, allowing us to find
hardware errors when they happen (well, as much as you can with a hardware
error) and prints out the trace if it is enabled. This will catch errors
(like booting the wrong image on a 533) which previously resulted in a
infinite loop/hang, as well as random hardware errors before before
setup_arch().
To disable this debug only feature - turn off EARLY_PRINTK.
Signed-off-by: Robin Getz <robin.getz@analog.com>
Signed-off-by: Mike Frysinger <vapier@gentoo.org>
Diffstat (limited to 'arch/blackfin/kernel/shadow_console.c')
-rw-r--r-- | arch/blackfin/kernel/shadow_console.c | 51 |
1 files changed, 43 insertions, 8 deletions
diff --git a/arch/blackfin/kernel/shadow_console.c b/arch/blackfin/kernel/shadow_console.c index 15819ff10573..8b8c7107a162 100644 --- a/arch/blackfin/kernel/shadow_console.c +++ b/arch/blackfin/kernel/shadow_console.c @@ -24,15 +24,18 @@ static __initdata char *shadow_console_buffer = (char *)SHADOW_CONSOLE_START; -static __init void early_shadow_write(struct console *con, const char *s, +__init void early_shadow_write(struct console *con, const char *s, unsigned int n) { + unsigned int i; /* * save 2 bytes for the double null at the end * once we fail on a long line, make sure we don't write a short line afterwards */ if ((shadow_console_buffer + n) <= (char *)(SHADOW_CONSOLE_END - 2)) { - memcpy(shadow_console_buffer, s, n); + /* can't use memcpy - it may not be relocated yet */ + for (i = 0; i <= n; i++) + shadow_console_buffer[i] = s[i]; shadow_console_buffer += n; shadow_console_buffer[0] = 0; shadow_console_buffer[1] = 0; @@ -48,16 +51,24 @@ static __initdata struct console early_shadow_console = { .device = 0, }; -__init void enable_shadow_console(void) +__init int shadow_console_enabled(void) +{ + return early_shadow_console.flags & CON_ENABLED; +} + +__init void mark_shadow_error(void) { int *loc = (int *)SHADOW_CONSOLE_MAGIC_LOC; + loc[0] = SHADOW_CONSOLE_MAGIC; + loc[1] = SHADOW_CONSOLE_START; +} - if (!(early_shadow_console.flags & CON_ENABLED)) { +__init void enable_shadow_console(void) +{ + if (!shadow_console_enabled()) { register_console(&early_shadow_console); /* for now, assume things are going to fail */ - *loc = SHADOW_CONSOLE_MAGIC; - loc++; - *loc = SHADOW_CONSOLE_START; + mark_shadow_error(); } } @@ -71,8 +82,32 @@ static __init int disable_shadow_console(void) */ int *loc = (int *)SHADOW_CONSOLE_MAGIC_LOC; - *loc = 0; + loc[0] = 0; return 0; } pure_initcall(disable_shadow_console); + +/* + * since we can't use printk, dump numbers (as hex), n = # bits + */ +__init void early_shadow_reg(unsigned long reg, unsigned int n) +{ + /* + * can't use any "normal" kernel features, since thay + * may not be relocated to their execute address yet + */ + int i; + char ascii[11] = " 0x"; + + n = n / 4; + reg = reg << ((8 - n) * 4); + n += 3; + + for (i = 3; i <= n ; i++) { + ascii[i] = hex_asc_lo(reg >> 28); + reg <<= 4; + } + early_shadow_write(NULL, ascii, n); + +} |