diff options
Diffstat (limited to 'arch/microblaze/kernel/early_printk.c')
-rw-r--r-- | arch/microblaze/kernel/early_printk.c | 107 |
1 files changed, 107 insertions, 0 deletions
diff --git a/arch/microblaze/kernel/early_printk.c b/arch/microblaze/kernel/early_printk.c new file mode 100644 index 000000000000..62cc78993f44 --- /dev/null +++ b/arch/microblaze/kernel/early_printk.c | |||
@@ -0,0 +1,107 @@ | |||
1 | /* | ||
2 | * Early printk support for Microblaze. | ||
3 | * | ||
4 | * Copyright (C) 2007-2009 Michal Simek <monstr@monstr.eu> | ||
5 | * Copyright (C) 2007-2009 PetaLogix | ||
6 | * Copyright (C) 2003-2006 Yasushi SHOJI <yashi@atmark-techno.com> | ||
7 | * | ||
8 | * This file is subject to the terms and conditions of the GNU General Public | ||
9 | * License. See the file "COPYING" in the main directory of this archive | ||
10 | * for more details. | ||
11 | */ | ||
12 | |||
13 | #include <linux/console.h> | ||
14 | #include <linux/kernel.h> | ||
15 | #include <linux/init.h> | ||
16 | #include <linux/string.h> | ||
17 | #include <linux/tty.h> | ||
18 | #include <linux/io.h> | ||
19 | #include <asm/processor.h> | ||
20 | #include <linux/fcntl.h> | ||
21 | #include <asm/setup.h> | ||
22 | #include <asm/prom.h> | ||
23 | |||
24 | static u32 early_console_initialized; | ||
25 | static u32 base_addr; | ||
26 | |||
27 | static void early_printk_putc(char c) | ||
28 | { | ||
29 | /* | ||
30 | * Limit how many times we'll spin waiting for TX FIFO status. | ||
31 | * This will prevent lockups if the base address is incorrectly | ||
32 | * set, or any other issue on the UARTLITE. | ||
33 | * This limit is pretty arbitrary, unless we are at about 10 baud | ||
34 | * we'll never timeout on a working UART. | ||
35 | */ | ||
36 | |||
37 | unsigned retries = 10000; | ||
38 | /* read status bit - 0x8 offset */ | ||
39 | while (retries-- && (in_be32(base_addr + 8) & (1 << 3))) | ||
40 | ; | ||
41 | |||
42 | /* Only attempt the iowrite if we didn't timeout */ | ||
43 | /* write to TX_FIFO - 0x4 offset */ | ||
44 | if (retries) | ||
45 | out_be32(base_addr + 4, c & 0xff); | ||
46 | } | ||
47 | |||
48 | static void early_printk_write(struct console *unused, | ||
49 | const char *s, unsigned n) | ||
50 | { | ||
51 | while (*s && n-- > 0) { | ||
52 | early_printk_putc(*s); | ||
53 | if (*s == '\n') | ||
54 | early_printk_putc('\r'); | ||
55 | s++; | ||
56 | } | ||
57 | } | ||
58 | |||
59 | static struct console early_serial_console = { | ||
60 | .name = "earlyser", | ||
61 | .write = early_printk_write, | ||
62 | .flags = CON_PRINTBUFFER, | ||
63 | .index = -1, | ||
64 | }; | ||
65 | |||
66 | static struct console *early_console = &early_serial_console; | ||
67 | |||
68 | void early_printk(const char *fmt, ...) | ||
69 | { | ||
70 | char buf[512]; | ||
71 | int n; | ||
72 | va_list ap; | ||
73 | |||
74 | if (early_console_initialized) { | ||
75 | va_start(ap, fmt); | ||
76 | n = vscnprintf(buf, 512, fmt, ap); | ||
77 | early_console->write(early_console, buf, n); | ||
78 | va_end(ap); | ||
79 | } | ||
80 | } | ||
81 | |||
82 | int __init setup_early_printk(char *opt) | ||
83 | { | ||
84 | if (early_console_initialized) | ||
85 | return 1; | ||
86 | |||
87 | base_addr = early_uartlite_console(); | ||
88 | if (base_addr) { | ||
89 | early_console_initialized = 1; | ||
90 | early_printk("early_printk_console is enabled at 0x%08x\n", | ||
91 | base_addr); | ||
92 | |||
93 | /* register_console(early_console); */ | ||
94 | |||
95 | return 0; | ||
96 | } else | ||
97 | return 1; | ||
98 | } | ||
99 | |||
100 | void __init disable_early_printk(void) | ||
101 | { | ||
102 | if (!early_console_initialized || !early_console) | ||
103 | return; | ||
104 | printk(KERN_WARNING "disabling early console\n"); | ||
105 | unregister_console(early_console); | ||
106 | early_console_initialized = 0; | ||
107 | } | ||