aboutsummaryrefslogtreecommitdiffstats
path: root/arch
diff options
context:
space:
mode:
authorPaul Mundt <lethal@linux-sh.org>2006-09-27 01:26:53 -0400
committerPaul Mundt <lethal@linux-sh.org>2006-09-27 01:26:53 -0400
commita80fd21e52cc09ff1e4d36de5781173a5b87b2dc (patch)
tree9e4ee0efc4809209f5bb9c9a288a6a1cf43c060e /arch
parente86d6b66f5b38680746b2cb71186d90af17f150f (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.c106
-rw-r--r--arch/sh/kernel/setup.c22
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
52static struct console early_console = { 52static 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
73static struct uart_port scif_port = {
74 .mapbase = SCIF_REG,
75 .membase = (char __iomem *)SCIF_REG,
76};
63 77
64static void scif_sercon_putc(int c) 78static 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
75static void scif_sercon_flush(void) 94static 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
84static 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
92static int __init scif_sercon_setup(struct console *con, char *options) 101static 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
99static struct console early_console = { 108static 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
107void scif_sercon_init(int baud) 116static 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
125void __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 */
138static 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
148static int __initdata keep_early;
149
150int __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
133void disable_early_printk(void) 184void __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