Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/ieee1394...
[pandora-kernel.git] / arch / blackfin / kernel / shadow_console.c
1 /*
2  * manage a small early shadow of the log buffer which we can pass between the
3  * bootloader so early crash messages are communicated properly and easily
4  *
5  * Copyright 2009 Analog Devices Inc.
6  *
7  * Licensed under the GPL-2 or later.
8  */
9
10 #include <linux/kernel.h>
11 #include <linux/init.h>
12 #include <linux/console.h>
13 #include <linux/string.h>
14 #include <asm/blackfin.h>
15 #include <asm/irq_handler.h>
16 #include <asm/early_printk.h>
17
18 #define SHADOW_CONSOLE_START            (0x500)
19 #define SHADOW_CONSOLE_END              (0x1000)
20 #define SHADOW_CONSOLE_MAGIC_LOC        (0x4F0)
21 #define SHADOW_CONSOLE_MAGIC            (0xDEADBEEF)
22
23 static __initdata char *shadow_console_buffer = (char *)SHADOW_CONSOLE_START;
24
25 __init void early_shadow_write(struct console *con, const char *s,
26                                 unsigned int n)
27 {
28         unsigned int i;
29         /*
30          * save 2 bytes for the double null at the end
31          * once we fail on a long line, make sure we don't write a short line afterwards
32          */
33         if ((shadow_console_buffer + n) <= (char *)(SHADOW_CONSOLE_END - 2)) {
34                 /* can't use memcpy - it may not be relocated yet */
35                 for (i = 0; i <= n; i++)
36                         shadow_console_buffer[i] = s[i];
37                 shadow_console_buffer += n;
38                 shadow_console_buffer[0] = 0;
39                 shadow_console_buffer[1] = 0;
40         } else
41                 shadow_console_buffer = (char *)SHADOW_CONSOLE_END;
42 }
43
44 static __initdata struct console early_shadow_console = {
45         .name = "early_shadow",
46         .write = early_shadow_write,
47         .flags = CON_BOOT | CON_PRINTBUFFER,
48         .index = -1,
49         .device = 0,
50 };
51
52 __init int shadow_console_enabled(void)
53 {
54         return early_shadow_console.flags & CON_ENABLED;
55 }
56
57 __init void mark_shadow_error(void)
58 {
59         int *loc = (int *)SHADOW_CONSOLE_MAGIC_LOC;
60         loc[0] = SHADOW_CONSOLE_MAGIC;
61         loc[1] = SHADOW_CONSOLE_START;
62 }
63
64 __init void enable_shadow_console(void)
65 {
66         if (!shadow_console_enabled()) {
67                 register_console(&early_shadow_console);
68                 /* for now, assume things are going to fail */
69                 mark_shadow_error();
70         }
71 }
72
73 static __init int disable_shadow_console(void)
74 {
75         /*
76          * by the time pure_initcall runs, the standard console is enabled,
77          * and the early_console is off, so unset the magic numbers
78          * unregistering the console is taken care of in common code (See
79          * ./kernel/printk:disable_boot_consoles() )
80          */
81         int *loc = (int *)SHADOW_CONSOLE_MAGIC_LOC;
82
83         loc[0] = 0;
84
85         return 0;
86 }
87 pure_initcall(disable_shadow_console);
88
89 /*
90  * since we can't use printk, dump numbers (as hex), n = # bits
91  */
92 __init void early_shadow_reg(unsigned long reg, unsigned int n)
93 {
94         /*
95          * can't use any "normal" kernel features, since thay
96          * may not be relocated to their execute address yet
97          */
98         int i;
99         char ascii[11] = " 0x";
100
101         n = n / 4;
102         reg = reg << ((8 - n) * 4);
103         n += 3;
104
105         for (i = 3; i <= n ; i++) {
106                 ascii[i] = hex_asc_lo(reg >> 28);
107                 reg <<= 4;
108         }
109         early_shadow_write(NULL, ascii, n);
110
111 }