forked from Minki/linux
703404ea44
This allows the baud rate for earlyprintk for sh4 without the standard BIOS to be set via the command line. This uses the same format as i386 and x86_64, which is: earlyprintk=serial,ttySC1,38400 The second parameter (ttySC1 above) is usually the console device name or the io address of the serial port. I allow that to be specified but ignore it in order to keep the format the same as i386/x86_64. Signed-off-by: Jamie Lenehan <lenehan@twibble.org> Signed-off-by: Paul Mundt <lethal@linux-sh.org>
212 lines
4.6 KiB
C
212 lines
4.6 KiB
C
/*
|
|
* arch/sh/kernel/early_printk.c
|
|
*
|
|
* Copyright (C) 1999, 2000 Niibe Yutaka
|
|
* Copyright (C) 2002 M. R. Brown
|
|
* 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
|
|
* for more details.
|
|
*/
|
|
#include <linux/console.h>
|
|
#include <linux/tty.h>
|
|
#include <linux/init.h>
|
|
#include <linux/io.h>
|
|
|
|
#ifdef CONFIG_SH_STANDARD_BIOS
|
|
#include <asm/sh_bios.h>
|
|
|
|
/*
|
|
* Print a string through the BIOS
|
|
*/
|
|
static void sh_console_write(struct console *co, const char *s,
|
|
unsigned count)
|
|
{
|
|
sh_bios_console_write(s, count);
|
|
}
|
|
|
|
/*
|
|
* Setup initial baud/bits/parity. We do two things here:
|
|
* - construct a cflag setting for the first rs_open()
|
|
* - initialize the serial port
|
|
* Return non-zero if we didn't find a serial port.
|
|
*/
|
|
static int __init sh_console_setup(struct console *co, char *options)
|
|
{
|
|
int cflag = CREAD | HUPCL | CLOCAL;
|
|
|
|
/*
|
|
* Now construct a cflag setting.
|
|
* TODO: this is a totally bogus cflag, as we have
|
|
* no idea what serial settings the BIOS is using, or
|
|
* even if its using the serial port at all.
|
|
*/
|
|
cflag |= B115200 | CS8 | /*no parity*/0;
|
|
|
|
co->cflag = cflag;
|
|
|
|
return 0;
|
|
}
|
|
|
|
static struct console bios_console = {
|
|
.name = "bios",
|
|
.write = sh_console_write,
|
|
.setup = sh_console_setup,
|
|
.flags = CON_PRINTBUFFER,
|
|
.index = -1,
|
|
};
|
|
#endif
|
|
|
|
#ifdef CONFIG_EARLY_SCIF_CONSOLE
|
|
#include <linux/serial_core.h>
|
|
#include "../../../drivers/serial/sh-sci.h"
|
|
|
|
static struct uart_port scif_port = {
|
|
.mapbase = CONFIG_EARLY_SCIF_CONSOLE_PORT,
|
|
.membase = (char __iomem *)CONFIG_EARLY_SCIF_CONSOLE_PORT,
|
|
};
|
|
|
|
static void scif_sercon_putc(int c)
|
|
{
|
|
while (((sci_in(&scif_port, SCFDR) & 0x1f00 >> 8) == 16))
|
|
;
|
|
|
|
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_write(struct console *con, const char *s,
|
|
unsigned count)
|
|
{
|
|
while (count-- > 0)
|
|
scif_sercon_putc(*s++);
|
|
}
|
|
|
|
static int __init scif_sercon_setup(struct console *con, char *options)
|
|
{
|
|
con->cflag = CREAD | HUPCL | CLOCAL | B115200 | CS8;
|
|
|
|
return 0;
|
|
}
|
|
|
|
static struct console scif_console = {
|
|
.name = "sercon",
|
|
.write = scif_sercon_write,
|
|
.setup = scif_sercon_setup,
|
|
.flags = CON_PRINTBUFFER,
|
|
.index = -1,
|
|
};
|
|
|
|
#if defined(CONFIG_CPU_SH4) && !defined(CONFIG_SH_STANDARD_BIOS)
|
|
#define DEFAULT_BAUD 115200
|
|
/*
|
|
* Simple SCIF init, primarily aimed at SH7750 and other similar SH-4
|
|
* devices that aren't using sh-ipl+g.
|
|
*/
|
|
static void scif_sercon_init(char *s)
|
|
{
|
|
unsigned baud = DEFAULT_BAUD;
|
|
char *e;
|
|
|
|
if (*s == ',')
|
|
++s;
|
|
|
|
if (*s) {
|
|
/* ignore ioport/device name */
|
|
s += strcspn(s, ",");
|
|
if (*s == ',')
|
|
s++;
|
|
}
|
|
|
|
if (*s) {
|
|
baud = simple_strtoul(s, &e, 0);
|
|
if (baud == 0 || s == e)
|
|
baud = DEFAULT_BAUD;
|
|
}
|
|
|
|
ctrl_outw(0, scif_port.mapbase + 8);
|
|
ctrl_outw(0, scif_port.mapbase);
|
|
|
|
/* Set baud rate */
|
|
ctrl_outb((CONFIG_SH_PCLK_FREQ + 16 * baud) /
|
|
(32 * baud) - 1, scif_port.mapbase + 4);
|
|
|
|
ctrl_outw(12, scif_port.mapbase + 24);
|
|
ctrl_outw(8, scif_port.mapbase + 24);
|
|
ctrl_outw(0, scif_port.mapbase + 32);
|
|
ctrl_outw(0x60, scif_port.mapbase + 16);
|
|
ctrl_outw(0, scif_port.mapbase + 36);
|
|
ctrl_outw(0x30, scif_port.mapbase + 8);
|
|
}
|
|
#endif /* CONFIG_CPU_SH4 && !CONFIG_SH_STANDARD_BIOS */
|
|
#endif /* CONFIG_EARLY_SCIF_CONSOLE */
|
|
|
|
/*
|
|
* 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;
|
|
static int early_console_initialized;
|
|
|
|
int __init setup_early_printk(char *buf)
|
|
{
|
|
if (!buf)
|
|
return 0;
|
|
|
|
if (early_console_initialized)
|
|
return 0;
|
|
early_console_initialized = 1;
|
|
|
|
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;
|
|
|
|
#if defined(CONFIG_CPU_SH4) && !defined(CONFIG_SH_STANDARD_BIOS)
|
|
scif_sercon_init(buf + 6);
|
|
#endif
|
|
}
|
|
#endif
|
|
|
|
if (likely(early_console))
|
|
register_console(early_console);
|
|
|
|
return 0;
|
|
}
|
|
early_param("earlyprintk", setup_early_printk);
|
|
|
|
void __init disable_early_printk(void)
|
|
{
|
|
if (!early_console_initialized || !early_console)
|
|
return;
|
|
if (!keep_early) {
|
|
printk("disabling early console\n");
|
|
unregister_console(early_console);
|
|
} else
|
|
printk("keeping early console\n");
|
|
}
|