From a80fd21e52cc09ff1e4d36de5781173a5b87b2dc Mon Sep 17 00:00:00 2001 From: Paul Mundt Date: Wed, 27 Sep 2006 14:26:53 +0900 Subject: [PATCH] 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 --- arch/sh/kernel/early_printk.c | 110 +++++++++++++++++++++++++--------- arch/sh/kernel/setup.c | 22 +++++-- include/asm-sh/setup.h | 2 + 3 files changed, 102 insertions(+), 32 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 @@ * * 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 +#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) -{ -#ifdef CONFIG_EARLY_SCIF_CONSOLE - scif_sercon_init(115200); +/* + * 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 - register_console(&early_console); -} + ; -void disable_early_printk(void) +static int __initdata keep_early; + +int __init setup_early_printk(char *opt) { - unregister_console(&early_console); -} + 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 + + if (likely(early_console)) + register_console(early_console); + + return 1; +} +__setup("earlyprintk=", setup_early_printk); + +void __init disable_early_printk(void) +{ + if (!keep_early) { + printk("disabling early console\n"); + unregister_console(early_console); + } else + printk("keeping early console\n"); +} 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], 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 diff --git a/include/asm-sh/setup.h b/include/asm-sh/setup.h index d19de7c8df4e..34ca8a7f06ba 100644 --- a/include/asm-sh/setup.h +++ b/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__ */