diff options
author | Paul Mundt <lethal@linux-sh.org> | 2006-09-27 01:26:53 -0400 |
---|---|---|
committer | Paul Mundt <lethal@linux-sh.org> | 2006-09-27 01:26:53 -0400 |
commit | a80fd21e52cc09ff1e4d36de5781173a5b87b2dc (patch) | |
tree | 9e4ee0efc4809209f5bb9c9a288a6a1cf43c060e /arch | |
parent | e86d6b66f5b38680746b2cb71186d90af17f150f (diff) |
sh: earlyprintk= support and cleanups.
Allow multiple early printk consoles via earlyprintk=.
With this change earlyprintk is no longer enabled by default,
it must be specified on the kernel command line. Optionally
with ,keep to prevent unreg by tty_io.
Signed-off-by: Paul Mundt <lethal@linux-sh.org>
Diffstat (limited to 'arch')
-rw-r--r-- | arch/sh/kernel/early_printk.c | 106 | ||||
-rw-r--r-- | arch/sh/kernel/setup.c | 22 |
2 files changed, 98 insertions, 30 deletions
diff --git a/arch/sh/kernel/early_printk.c b/arch/sh/kernel/early_printk.c index 1378db375e17..a00022722e9e 100644 --- a/arch/sh/kernel/early_printk.c +++ b/arch/sh/kernel/early_printk.c | |||
@@ -3,7 +3,7 @@ | |||
3 | * | 3 | * |
4 | * Copyright (C) 1999, 2000 Niibe Yutaka | 4 | * Copyright (C) 1999, 2000 Niibe Yutaka |
5 | * Copyright (C) 2002 M. R. Brown | 5 | * Copyright (C) 2002 M. R. Brown |
6 | * Copyright (C) 2004 Paul Mundt | 6 | * Copyright (C) 2004 - 2006 Paul Mundt |
7 | * | 7 | * |
8 | * This file is subject to the terms and conditions of the GNU General Public | 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 | 9 | * License. See the file "COPYING" in the main directory of this archive |
@@ -49,7 +49,7 @@ static int __init sh_console_setup(struct console *co, char *options) | |||
49 | return 0; | 49 | return 0; |
50 | } | 50 | } |
51 | 51 | ||
52 | static struct console early_console = { | 52 | static struct console bios_console = { |
53 | .name = "bios", | 53 | .name = "bios", |
54 | .write = sh_console_write, | 54 | .write = sh_console_write, |
55 | .setup = sh_console_setup, | 55 | .setup = sh_console_setup, |
@@ -59,34 +59,43 @@ static struct console early_console = { | |||
59 | #endif | 59 | #endif |
60 | 60 | ||
61 | #ifdef CONFIG_EARLY_SCIF_CONSOLE | 61 | #ifdef CONFIG_EARLY_SCIF_CONSOLE |
62 | #include <linux/serial_core.h> | ||
63 | #include "../../../drivers/serial/sh-sci.h" | ||
64 | |||
65 | #ifdef CONFIG_CPU_SH4 | ||
62 | #define SCIF_REG 0xffe80000 | 66 | #define SCIF_REG 0xffe80000 |
67 | #elif defined(CONFIG_CPU_SUBTYPE_SH72060) | ||
68 | #define SCIF_REG 0xfffe9800 | ||
69 | #else | ||
70 | #error "Undefined SCIF for this subtype" | ||
71 | #endif | ||
72 | |||
73 | static struct uart_port scif_port = { | ||
74 | .mapbase = SCIF_REG, | ||
75 | .membase = (char __iomem *)SCIF_REG, | ||
76 | }; | ||
63 | 77 | ||
64 | static void scif_sercon_putc(int c) | 78 | static void scif_sercon_putc(int c) |
65 | { | 79 | { |
66 | while (!(ctrl_inw(SCIF_REG + 0x10) & 0x20)) ; | 80 | while (((sci_in(&scif_port, SCFDR) & 0x1f00 >> 8) == 16)) |
81 | ; | ||
67 | 82 | ||
68 | ctrl_outb(c, SCIF_REG + 12); | 83 | sci_out(&scif_port, SCxTDR, c); |
69 | ctrl_outw((ctrl_inw(SCIF_REG + 0x10) & 0x9f), SCIF_REG + 0x10); | 84 | sci_in(&scif_port, SCxSR); |
85 | sci_out(&scif_port, SCxSR, 0xf3 & ~(0x20 | 0x40)); | ||
86 | |||
87 | while ((sci_in(&scif_port, SCxSR) & 0x40) == 0); | ||
88 | ; | ||
70 | 89 | ||
71 | if (c == '\n') | 90 | if (c == '\n') |
72 | scif_sercon_putc('\r'); | 91 | scif_sercon_putc('\r'); |
73 | } | 92 | } |
74 | 93 | ||
75 | static void scif_sercon_flush(void) | 94 | static void scif_sercon_write(struct console *con, const char *s, |
76 | { | 95 | unsigned count) |
77 | ctrl_outw((ctrl_inw(SCIF_REG + 0x10) & 0xbf), SCIF_REG + 0x10); | ||
78 | |||
79 | while (!(ctrl_inw(SCIF_REG + 0x10) & 0x40)) ; | ||
80 | |||
81 | ctrl_outw((ctrl_inw(SCIF_REG + 0x10) & 0xbf), SCIF_REG + 0x10); | ||
82 | } | ||
83 | |||
84 | static void scif_sercon_write(struct console *con, const char *s, unsigned count) | ||
85 | { | 96 | { |
86 | while (count-- > 0) | 97 | while (count-- > 0) |
87 | scif_sercon_putc(*s++); | 98 | scif_sercon_putc(*s++); |
88 | |||
89 | scif_sercon_flush(); | ||
90 | } | 99 | } |
91 | 100 | ||
92 | static int __init scif_sercon_setup(struct console *con, char *options) | 101 | static int __init scif_sercon_setup(struct console *con, char *options) |
@@ -96,7 +105,7 @@ static int __init scif_sercon_setup(struct console *con, char *options) | |||
96 | return 0; | 105 | return 0; |
97 | } | 106 | } |
98 | 107 | ||
99 | static struct console early_console = { | 108 | static struct console scif_console = { |
100 | .name = "sercon", | 109 | .name = "sercon", |
101 | .write = scif_sercon_write, | 110 | .write = scif_sercon_write, |
102 | .setup = scif_sercon_setup, | 111 | .setup = scif_sercon_setup, |
@@ -104,7 +113,7 @@ static struct console early_console = { | |||
104 | .index = -1, | 113 | .index = -1, |
105 | }; | 114 | }; |
106 | 115 | ||
107 | void scif_sercon_init(int baud) | 116 | static void scif_sercon_init(int baud) |
108 | { | 117 | { |
109 | ctrl_outw(0, SCIF_REG + 8); | 118 | ctrl_outw(0, SCIF_REG + 8); |
110 | ctrl_outw(0, SCIF_REG); | 119 | ctrl_outw(0, SCIF_REG); |
@@ -122,16 +131,61 @@ void scif_sercon_init(int baud) | |||
122 | } | 131 | } |
123 | #endif | 132 | #endif |
124 | 133 | ||
125 | void __init enable_early_printk(void) | 134 | /* |
135 | * Setup a default console, if more than one is compiled in, rely on the | ||
136 | * earlyprintk= parsing to give priority. | ||
137 | */ | ||
138 | static struct console *early_console = | ||
139 | #ifdef CONFIG_SH_STANDARD_BIOS | ||
140 | &bios_console | ||
141 | #elif defined(CONFIG_EARLY_SCIF_CONSOLE) | ||
142 | &scif_console | ||
143 | #else | ||
144 | NULL | ||
145 | #endif | ||
146 | ; | ||
147 | |||
148 | static int __initdata keep_early; | ||
149 | |||
150 | int __init setup_early_printk(char *opt) | ||
126 | { | 151 | { |
127 | #ifdef CONFIG_EARLY_SCIF_CONSOLE | 152 | char *space; |
128 | scif_sercon_init(115200); | 153 | char buf[256]; |
154 | |||
155 | strlcpy(buf, opt, sizeof(buf)); | ||
156 | space = strchr(buf, ' '); | ||
157 | if (space) | ||
158 | *space = 0; | ||
159 | |||
160 | if (strstr(buf, "keep")) | ||
161 | keep_early = 1; | ||
162 | |||
163 | #ifdef CONFIG_SH_STANDARD_BIOS | ||
164 | if (!strncmp(buf, "bios", 4)) | ||
165 | early_console = &bios_console; | ||
166 | #endif | ||
167 | #if defined(CONFIG_EARLY_SCIF_CONSOLE) | ||
168 | if (!strncmp(buf, "serial", 6)) { | ||
169 | early_console = &scif_console; | ||
170 | |||
171 | #ifdef CONFIG_CPU_SH4 | ||
172 | scif_sercon_init(115200); | ||
173 | #endif | ||
174 | } | ||
129 | #endif | 175 | #endif |
130 | register_console(&early_console); | 176 | |
177 | if (likely(early_console)) | ||
178 | register_console(early_console); | ||
179 | |||
180 | return 1; | ||
131 | } | 181 | } |
182 | __setup("earlyprintk=", setup_early_printk); | ||
132 | 183 | ||
133 | void disable_early_printk(void) | 184 | void __init disable_early_printk(void) |
134 | { | 185 | { |
135 | unregister_console(&early_console); | 186 | if (!keep_early) { |
187 | printk("disabling early console\n"); | ||
188 | unregister_console(early_console); | ||
189 | } else | ||
190 | printk("keeping early console\n"); | ||
136 | } | 191 | } |
137 | |||
diff --git a/arch/sh/kernel/setup.c b/arch/sh/kernel/setup.c index e75189cb1db7..cff8d36f91b0 100644 --- a/arch/sh/kernel/setup.c +++ b/arch/sh/kernel/setup.c | |||
@@ -145,6 +145,24 @@ static inline void parse_cmdline (char ** cmdline_p, char mv_name[MV_NAME_SIZE], | |||
145 | memory_end = memory_start + mem_size; | 145 | memory_end = memory_start + mem_size; |
146 | } | 146 | } |
147 | } | 147 | } |
148 | |||
149 | #ifdef CONFIG_EARLY_PRINTK | ||
150 | if (c == ' ' && !memcmp(from, "earlyprintk=", 12)) { | ||
151 | char *ep_end; | ||
152 | |||
153 | if (to != command_line) | ||
154 | to--; | ||
155 | |||
156 | from += 12; | ||
157 | ep_end = strchr(from, ' '); | ||
158 | |||
159 | setup_early_printk(from); | ||
160 | printk("early console enabled\n"); | ||
161 | |||
162 | from = ep_end; | ||
163 | } | ||
164 | #endif | ||
165 | |||
148 | if (c == ' ' && !memcmp(from, "sh_mv=", 6)) { | 166 | if (c == ' ' && !memcmp(from, "sh_mv=", 6)) { |
149 | char* mv_end; | 167 | char* mv_end; |
150 | char* mv_comma; | 168 | char* mv_comma; |
@@ -245,11 +263,7 @@ void __init setup_arch(char **cmdline_p) | |||
245 | unsigned long bootmap_size; | 263 | unsigned long bootmap_size; |
246 | unsigned long start_pfn, max_pfn, max_low_pfn; | 264 | unsigned long start_pfn, max_pfn, max_low_pfn; |
247 | 265 | ||
248 | #ifdef CONFIG_EARLY_PRINTK | ||
249 | extern void enable_early_printk(void); | ||
250 | 266 | ||
251 | enable_early_printk(); | ||
252 | #endif | ||
253 | #ifdef CONFIG_CMDLINE_BOOL | 267 | #ifdef CONFIG_CMDLINE_BOOL |
254 | strcpy(COMMAND_LINE, CONFIG_CMDLINE); | 268 | strcpy(COMMAND_LINE, CONFIG_CMDLINE); |
255 | #endif | 269 | #endif |