Merge /spare/repo/linux-2.6/
[linux-2.6] / arch / sh / kernel / early_printk.c
1 /*
2  * arch/sh/kernel/early_printk.c
3  *
4  *  Copyright (C) 1999, 2000  Niibe Yutaka
5  *  Copyright (C) 2002  M. R. Brown
6  *  Copyright (C) 2004  Paul Mundt
7  *
8  * This file is subject to the terms and conditions of the GNU General Public
9  * License.  See the file "COPYING" in the main directory of this archive
10  * for more details.
11  */
12 #include <linux/console.h>
13 #include <linux/tty.h>
14 #include <linux/init.h>
15 #include <asm/io.h>
16
17 #ifdef CONFIG_SH_STANDARD_BIOS
18 #include <asm/sh_bios.h>
19
20 /*
21  *      Print a string through the BIOS
22  */
23 static void sh_console_write(struct console *co, const char *s,
24                                  unsigned count)
25 {
26         sh_bios_console_write(s, count);
27 }
28
29 /*
30  *      Setup initial baud/bits/parity. We do two things here:
31  *      - construct a cflag setting for the first rs_open()
32  *      - initialize the serial port
33  *      Return non-zero if we didn't find a serial port.
34  */
35 static int __init sh_console_setup(struct console *co, char *options)
36 {
37         int     cflag = CREAD | HUPCL | CLOCAL;
38
39         /*
40          *      Now construct a cflag setting.
41          *      TODO: this is a totally bogus cflag, as we have
42          *      no idea what serial settings the BIOS is using, or
43          *      even if its using the serial port at all.
44          */
45         cflag |= B115200 | CS8 | /*no parity*/0;
46
47         co->cflag = cflag;
48
49         return 0;
50 }
51
52 static struct console early_console = {
53         .name           = "bios",
54         .write          = sh_console_write,
55         .setup          = sh_console_setup,
56         .flags          = CON_PRINTBUFFER,
57         .index          = -1,
58 };
59 #endif
60
61 #ifdef CONFIG_EARLY_SCIF_CONSOLE
62 #define SCIF_REG        0xffe80000
63
64 static void scif_sercon_putc(int c)
65 {
66         while (!(ctrl_inw(SCIF_REG + 0x10) & 0x20)) ;
67
68         ctrl_outb(c, SCIF_REG + 12);
69         ctrl_outw((ctrl_inw(SCIF_REG + 0x10) & 0x9f), SCIF_REG + 0x10);
70
71         if (c == '\n')
72                 scif_sercon_putc('\r');
73 }
74
75 static void scif_sercon_flush(void)
76 {
77         ctrl_outw((ctrl_inw(SCIF_REG + 0x10) & 0xbf), SCIF_REG + 0x10);
78
79         while (!(ctrl_inw(SCIF_REG + 0x10) & 0x40)) ;
80
81         ctrl_outw((ctrl_inw(SCIF_REG + 0x10) & 0xbf), SCIF_REG + 0x10);
82 }
83
84 static void scif_sercon_write(struct console *con, const char *s, unsigned count)
85 {
86         while (count-- > 0)
87                 scif_sercon_putc(*s++);
88
89         scif_sercon_flush();
90 }
91
92 static int __init scif_sercon_setup(struct console *con, char *options)
93 {
94         con->cflag = CREAD | HUPCL | CLOCAL | B115200 | CS8;
95
96         return 0;
97 }
98
99 static struct console early_console = {
100         .name           = "sercon",
101         .write          = scif_sercon_write,
102         .setup          = scif_sercon_setup,
103         .flags          = CON_PRINTBUFFER,
104         .index          = -1,
105 };
106
107 void scif_sercon_init(int baud)
108 {
109         ctrl_outw(0, SCIF_REG + 8);
110         ctrl_outw(0, SCIF_REG);
111
112         /* Set baud rate */
113         ctrl_outb((CONFIG_SH_PCLK_FREQ + 16 * baud) /
114                   (32 * baud) - 1, SCIF_REG + 4);
115
116         ctrl_outw(12, SCIF_REG + 24);
117         ctrl_outw(8, SCIF_REG + 24);
118         ctrl_outw(0, SCIF_REG + 32);
119         ctrl_outw(0x60, SCIF_REG + 16);
120         ctrl_outw(0, SCIF_REG + 36);
121         ctrl_outw(0x30, SCIF_REG + 8);
122 }
123 #endif
124
125 void __init enable_early_printk(void)
126 {
127 #ifdef CONFIG_EARLY_SCIF_CONSOLE
128         scif_sercon_init(115200);
129 #endif
130         register_console(&early_console);
131 }
132
133 void disable_early_printk(void)
134 {
135         unregister_console(&early_console);
136 }
137