aboutsummaryrefslogtreecommitdiffstats
path: root/arch/blackfin/kernel/shadow_console.c
diff options
context:
space:
mode:
authorRobin Getz <robin.getz@analog.com>2009-07-07 16:17:09 -0400
committerMike Frysinger <vapier@gentoo.org>2009-09-16 21:31:44 -0400
commit837ec2d56c41640d1f1238e52c350b2a516d29ba (patch)
tree1732468388385c411853c67cb2b288c2f8d17cc7 /arch/blackfin/kernel/shadow_console.c
parent3f871feaf3390c6d6e578818f867917c2e4738a2 (diff)
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.c51
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 @@
24 24
25static __initdata char *shadow_console_buffer = (char *)SHADOW_CONSOLE_START; 25static __initdata char *shadow_console_buffer = (char *)SHADOW_CONSOLE_START;
26 26
27static __init void early_shadow_write(struct console *con, const char *s, 27__init void early_shadow_write(struct console *con, const char *s,
28 unsigned int n) 28 unsigned int n)
29{ 29{
30 unsigned int i;
30 /* 31 /*
31 * save 2 bytes for the double null at the end 32 * save 2 bytes for the double null at the end
32 * once we fail on a long line, make sure we don't write a short line afterwards 33 * once we fail on a long line, make sure we don't write a short line afterwards
33 */ 34 */
34 if ((shadow_console_buffer + n) <= (char *)(SHADOW_CONSOLE_END - 2)) { 35 if ((shadow_console_buffer + n) <= (char *)(SHADOW_CONSOLE_END - 2)) {
35 memcpy(shadow_console_buffer, s, n); 36 /* can't use memcpy - it may not be relocated yet */
37 for (i = 0; i <= n; i++)
38 shadow_console_buffer[i] = s[i];
36 shadow_console_buffer += n; 39 shadow_console_buffer += n;
37 shadow_console_buffer[0] = 0; 40 shadow_console_buffer[0] = 0;
38 shadow_console_buffer[1] = 0; 41 shadow_console_buffer[1] = 0;
@@ -48,16 +51,24 @@ static __initdata struct console early_shadow_console = {
48 .device = 0, 51 .device = 0,
49}; 52};
50 53
51__init void enable_shadow_console(void) 54__init int shadow_console_enabled(void)
55{
56 return early_shadow_console.flags & CON_ENABLED;
57}
58
59__init void mark_shadow_error(void)
52{ 60{
53 int *loc = (int *)SHADOW_CONSOLE_MAGIC_LOC; 61 int *loc = (int *)SHADOW_CONSOLE_MAGIC_LOC;
62 loc[0] = SHADOW_CONSOLE_MAGIC;
63 loc[1] = SHADOW_CONSOLE_START;
64}
54 65
55 if (!(early_shadow_console.flags & CON_ENABLED)) { 66__init void enable_shadow_console(void)
67{
68 if (!shadow_console_enabled()) {
56 register_console(&early_shadow_console); 69 register_console(&early_shadow_console);
57 /* for now, assume things are going to fail */ 70 /* for now, assume things are going to fail */
58 *loc = SHADOW_CONSOLE_MAGIC; 71 mark_shadow_error();
59 loc++;
60 *loc = SHADOW_CONSOLE_START;
61 } 72 }
62} 73}
63 74
@@ -71,8 +82,32 @@ static __init int disable_shadow_console(void)
71 */ 82 */
72 int *loc = (int *)SHADOW_CONSOLE_MAGIC_LOC; 83 int *loc = (int *)SHADOW_CONSOLE_MAGIC_LOC;
73 84
74 *loc = 0; 85 loc[0] = 0;
75 86
76 return 0; 87 return 0;
77} 88}
78pure_initcall(disable_shadow_console); 89pure_initcall(disable_shadow_console);
90
91/*
92 * since we can't use printk, dump numbers (as hex), n = # bits
93 */
94__init void early_shadow_reg(unsigned long reg, unsigned int n)
95{
96 /*
97 * can't use any "normal" kernel features, since thay
98 * may not be relocated to their execute address yet
99 */
100 int i;
101 char ascii[11] = " 0x";
102
103 n = n / 4;
104 reg = reg << ((8 - n) * 4);
105 n += 3;
106
107 for (i = 3; i <= n ; i++) {
108 ascii[i] = hex_asc_lo(reg >> 28);
109 reg <<= 4;
110 }
111 early_shadow_write(NULL, ascii, n);
112
113}