early_printk.c 5.2 KB
Newer Older
L
Linus Torvalds 已提交
1 2 3 4 5
/*
 * arch/sh/kernel/early_printk.c
 *
 *  Copyright (C) 1999, 2000  Niibe Yutaka
 *  Copyright (C) 2002  M. R. Brown
P
Paul Mundt 已提交
6
 *  Copyright (C) 2004 - 2007  Paul Mundt
L
Linus Torvalds 已提交
7 8 9 10 11 12 13 14
 *
 * 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>
15
#include <linux/io.h>
M
Markus Brunner 已提交
16
#include <linux/delay.h>
L
Linus Torvalds 已提交
17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52

#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;
}

53
static struct console bios_console = {
L
Linus Torvalds 已提交
54 55 56 57 58 59 60 61 62
	.name		= "bios",
	.write		= sh_console_write,
	.setup		= sh_console_setup,
	.flags		= CON_PRINTBUFFER,
	.index		= -1,
};
#endif

#ifdef CONFIG_EARLY_SCIF_CONSOLE
63 64 65
#include <linux/serial_core.h>
#include "../../../drivers/serial/sh-sci.h"

M
Markus Brunner 已提交
66 67 68 69 70 71 72 73 74 75
#if defined(CONFIG_CPU_SUBTYPE_SH7720)
#define EPK_SCSMR_VALUE 0x000
#define EPK_SCBRR_VALUE 0x00C
#define EPK_FIFO_SIZE 64
#define EPK_FIFO_BITS (0x7f00 >> 8)
#else
#define EPK_FIFO_SIZE 16
#define EPK_FIFO_BITS (0x1f00 >> 8)
#endif

76
static struct uart_port scif_port = {
77 78
	.mapbase	= CONFIG_EARLY_SCIF_CONSOLE_PORT,
	.membase	= (char __iomem *)CONFIG_EARLY_SCIF_CONSOLE_PORT,
79
};
L
Linus Torvalds 已提交
80 81 82

static void scif_sercon_putc(int c)
{
M
Markus Brunner 已提交
83
	while (((sci_in(&scif_port, SCFDR) & EPK_FIFO_BITS) >= EPK_FIFO_SIZE))
84
		;
L
Linus Torvalds 已提交
85

86 87 88 89
	sci_out(&scif_port, SCxTDR, c);
	sci_in(&scif_port, SCxSR);
	sci_out(&scif_port, SCxSR, 0xf3 & ~(0x20 | 0x40));

90
	while ((sci_in(&scif_port, SCxSR) & 0x40) == 0)
91
		;
L
Linus Torvalds 已提交
92 93 94 95 96

	if (c == '\n')
		scif_sercon_putc('\r');
}

97 98
static void scif_sercon_write(struct console *con, const char *s,
			      unsigned count)
L
Linus Torvalds 已提交
99 100 101 102 103 104 105 106 107 108 109 110
{
	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;
}

111
static struct console scif_console = {
L
Linus Torvalds 已提交
112 113 114 115 116 117 118
	.name		= "sercon",
	.write		= scif_sercon_write,
	.setup		= scif_sercon_setup,
	.flags		= CON_PRINTBUFFER,
	.index		= -1,
};

M
Markus Brunner 已提交
119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134
#if !defined(CONFIG_SH_STANDARD_BIOS)
#if defined(CONFIG_CPU_SUBTYPE_SH7720)
static void scif_sercon_init(char *s)
{
	sci_out(&scif_port, SCSCR, 0x0000);	/* clear TE and RE */
	sci_out(&scif_port, SCFCR, 0x4006);	/* reset */
	sci_out(&scif_port, SCSCR, 0x0000);	/* select internal clock */
	sci_out(&scif_port, SCSMR, EPK_SCSMR_VALUE);
	sci_out(&scif_port, SCBRR, EPK_SCBRR_VALUE);

	mdelay(1);	/* wait 1-bit time */

	sci_out(&scif_port, SCFCR, 0x0030);	/* TTRG=b'11 */
	sci_out(&scif_port, SCSCR, 0x0030);	/* TE, RE */
}
#elif defined(CONFIG_CPU_SH4)
135
#define DEFAULT_BAUD 115200
136 137 138 139
/*
 * Simple SCIF init, primarily aimed at SH7750 and other similar SH-4
 * devices that aren't using sh-ipl+g.
 */
140
static void scif_sercon_init(char *s)
L
Linus Torvalds 已提交
141
{
142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160
	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;
	}

161 162
	ctrl_outw(0, scif_port.mapbase + 8);
	ctrl_outw(0, scif_port.mapbase);
L
Linus Torvalds 已提交
163 164 165

	/* Set baud rate */
	ctrl_outb((CONFIG_SH_PCLK_FREQ + 16 * baud) /
166 167 168 169 170 171 172 173
		  (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);
L
Linus Torvalds 已提交
174
}
M
Markus Brunner 已提交
175 176
#endif /* defined(CONFIG_CPU_SUBTYPE_SH7720) */
#endif /* !defined(CONFIG_SH_STANDARD_BIOS) */
177
#endif /* CONFIG_EARLY_SCIF_CONSOLE */
L
Linus Torvalds 已提交
178

179 180 181 182 183 184 185 186 187 188 189 190 191 192
/*
 * 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
	;

P
Paul Mundt 已提交
193
static int __init setup_early_printk(char *buf)
L
Linus Torvalds 已提交
194
{
P
Paul Mundt 已提交
195
	int keep_early = 0;
196

P
Paul Mundt 已提交
197
	if (!buf)
198
		return 0;
199 200 201 202 203 204 205 206 207 208 209 210

	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;

M
Markus Brunner 已提交
211 212
#if (defined(CONFIG_CPU_SH4) || defined(CONFIG_CPU_SUBTYPE_SH7720)) && \
    !defined(CONFIG_SH_STANDARD_BIOS)
213
		scif_sercon_init(buf + 6);
214 215
#endif
	}
L
Linus Torvalds 已提交
216
#endif
217

218 219 220 221 222
	if (likely(early_console)) {
		if (keep_early)
			early_console->flags &= ~CON_BOOT;
		else
			early_console->flags |= CON_BOOT;
223
		register_console(early_console);
224
	}
225

226
	return 0;
L
Linus Torvalds 已提交
227
}
228
early_param("earlyprintk", setup_early_printk);