Bläddra i källkod

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>
Paul Mundt 18 år sedan
förälder
incheckning
a80fd21e52
3 ändrade filer med 100 tillägg och 30 borttagningar
  1. 80 26
      arch/sh/kernel/early_printk.c
  2. 18 4
      arch/sh/kernel/setup.c
  3. 2 0
      include/asm-sh/setup.h

+ 80 - 26
arch/sh/kernel/early_printk.c

@@ -3,7 +3,7 @@
  *
  *  Copyright (C) 1999, 2000  Niibe Yutaka
  *  Copyright (C) 2002  M. R. Brown
- *  Copyright (C) 2004  Paul Mundt
+ *  Copyright (C) 2004 - 2006  Paul Mundt
  *
  * This file is subject to the terms and conditions of the GNU General Public
  * 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)
 	return 0;
 }
 
-static struct console early_console = {
+static struct console bios_console = {
 	.name		= "bios",
 	.write		= sh_console_write,
 	.setup		= sh_console_setup,
@@ -59,34 +59,43 @@ static struct console early_console = {
 #endif
 
 #ifdef CONFIG_EARLY_SCIF_CONSOLE
+#include <linux/serial_core.h>
+#include "../../../drivers/serial/sh-sci.h"
+
+#ifdef CONFIG_CPU_SH4
 #define SCIF_REG	0xffe80000
+#elif defined(CONFIG_CPU_SUBTYPE_SH72060)
+#define SCIF_REG	0xfffe9800
+#else
+#error "Undefined SCIF for this subtype"
+#endif
+
+static struct uart_port scif_port = {
+	.mapbase	= SCIF_REG,
+	.membase	= (char __iomem *)SCIF_REG,
+};
 
 static void scif_sercon_putc(int c)
 {
-	while (!(ctrl_inw(SCIF_REG + 0x10) & 0x20)) ;
+	while (((sci_in(&scif_port, SCFDR) & 0x1f00 >> 8) == 16))
+		;
 
-	ctrl_outb(c, SCIF_REG + 12);
-	ctrl_outw((ctrl_inw(SCIF_REG + 0x10) & 0x9f), SCIF_REG + 0x10);
+	sci_out(&scif_port, SCxTDR, c);
+	sci_in(&scif_port, SCxSR);
+	sci_out(&scif_port, SCxSR, 0xf3 & ~(0x20 | 0x40));
+
+	while ((sci_in(&scif_port, SCxSR) & 0x40) == 0);
+		;
 
 	if (c == '\n')
 		scif_sercon_putc('\r');
 }
 
-static void scif_sercon_flush(void)
-{
-	ctrl_outw((ctrl_inw(SCIF_REG + 0x10) & 0xbf), SCIF_REG + 0x10);
-
-	while (!(ctrl_inw(SCIF_REG + 0x10) & 0x40)) ;
-
-	ctrl_outw((ctrl_inw(SCIF_REG + 0x10) & 0xbf), SCIF_REG + 0x10);
-}
-
-static void scif_sercon_write(struct console *con, const char *s, unsigned count)
+static void scif_sercon_write(struct console *con, const char *s,
+			      unsigned count)
 {
 	while (count-- > 0)
 		scif_sercon_putc(*s++);
-
-	scif_sercon_flush();
 }
 
 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)
 	return 0;
 }
 
-static struct console early_console = {
+static struct console scif_console = {
 	.name		= "sercon",
 	.write		= scif_sercon_write,
 	.setup		= scif_sercon_setup,
@@ -104,7 +113,7 @@ static struct console early_console = {
 	.index		= -1,
 };
 
-void scif_sercon_init(int baud)
+static void scif_sercon_init(int baud)
 {
 	ctrl_outw(0, SCIF_REG + 8);
 	ctrl_outw(0, SCIF_REG);
@@ -122,16 +131,61 @@ void scif_sercon_init(int baud)
 }
 #endif
 
-void __init enable_early_printk(void)
+/*
+ * Setup a default console, if more than one is compiled in, rely on the
+ * earlyprintk= parsing to give priority.
+ */
+static struct console *early_console =
+#ifdef CONFIG_SH_STANDARD_BIOS
+	&bios_console
+#elif defined(CONFIG_EARLY_SCIF_CONSOLE)
+	&scif_console
+#else
+	NULL
+#endif
+	;
+
+static int __initdata keep_early;
+
+int __init setup_early_printk(char *opt)
 {
-#ifdef CONFIG_EARLY_SCIF_CONSOLE
-	scif_sercon_init(115200);
+	char *space;
+	char buf[256];
+
+	strlcpy(buf, opt, sizeof(buf));
+	space = strchr(buf, ' ');
+	if (space)
+		*space = 0;
+
+	if (strstr(buf, "keep"))
+		keep_early = 1;
+
+#ifdef CONFIG_SH_STANDARD_BIOS
+	if (!strncmp(buf, "bios", 4))
+		early_console = &bios_console;
+#endif
+#if defined(CONFIG_EARLY_SCIF_CONSOLE)
+	if (!strncmp(buf, "serial", 6)) {
+		early_console = &scif_console;
+
+#ifdef CONFIG_CPU_SH4
+		scif_sercon_init(115200);
+#endif
+	}
 #endif
-	register_console(&early_console);
+
+	if (likely(early_console))
+		register_console(early_console);
+
+	return 1;
 }
+__setup("earlyprintk=", setup_early_printk);
 
-void disable_early_printk(void)
+void __init disable_early_printk(void)
 {
-	unregister_console(&early_console);
+	if (!keep_early) {
+		printk("disabling early console\n");
+		unregister_console(early_console);
+	} else
+		printk("keeping early console\n");
 }
-

+ 18 - 4
arch/sh/kernel/setup.c

@@ -145,6 +145,24 @@ static inline void parse_cmdline (char ** cmdline_p, char mv_name[MV_NAME_SIZE],
 				memory_end = memory_start + mem_size;
 			}
 		}
+
+#ifdef CONFIG_EARLY_PRINTK
+		if (c == ' ' && !memcmp(from, "earlyprintk=", 12)) {
+			char *ep_end;
+
+			if (to != command_line)
+				to--;
+
+			from += 12;
+			ep_end = strchr(from, ' ');
+
+			setup_early_printk(from);
+			printk("early console enabled\n");
+
+			from = ep_end;
+		}
+#endif
+
 		if (c == ' ' && !memcmp(from, "sh_mv=", 6)) {
 			char* mv_end;
 			char* mv_comma;
@@ -245,11 +263,7 @@ void __init setup_arch(char **cmdline_p)
 	unsigned long bootmap_size;
 	unsigned long start_pfn, max_pfn, max_low_pfn;
 
-#ifdef CONFIG_EARLY_PRINTK
-	extern void enable_early_printk(void);
 
-	enable_early_printk();
-#endif
 #ifdef CONFIG_CMDLINE_BOOL
         strcpy(COMMAND_LINE, CONFIG_CMDLINE);
 #endif

+ 2 - 0
include/asm-sh/setup.h

@@ -4,5 +4,7 @@
 
 #define COMMAND_LINE_SIZE 256
 
+int setup_early_printk(char *);
+
 #endif /* _SH_SETUP_H */
 #endif /* __KERNEL__ */