sh: earlyprintk= support and cleanups.
authorPaul Mundt <lethal@linux-sh.org>
Wed, 27 Sep 2006 05:26:53 +0000 (14:26 +0900)
committerPaul Mundt <lethal@linux-sh.org>
Wed, 27 Sep 2006 05:26:53 +0000 (14:26 +0900)
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>
arch/sh/kernel/early_printk.c
arch/sh/kernel/setup.c
include/asm-sh/setup.h

index 1378db3..a000227 100644 (file)
@@ -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");
 }
-
index e75189c..cff8d36 100644 (file)
@@ -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
index d19de7c..34ca8a7 100644 (file)
@@ -4,5 +4,7 @@
 
 #define COMMAND_LINE_SIZE 256
 
+int setup_early_printk(char *);
+
 #endif /* _SH_SETUP_H */
 #endif /* __KERNEL__ */