Merge master.kernel.org:/pub/scm/linux/kernel/git/lethal/sh-2.6
[pandora-kernel.git] / 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 - 2006  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 bios_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 #include <linux/serial_core.h>
63 #include "../../../drivers/serial/sh-sci.h"
64
65 #ifdef CONFIG_CPU_SH4
66 #define SCIF_REG        0xffe80000
67 #elif defined(CONFIG_CPU_SUBTYPE_SH72060)
68 #define SCIF_REG        0xfffe9800
69 #else
70 #error "Undefined SCIF for this subtype"
71 #endif
72
73 static struct uart_port scif_port = {
74         .mapbase        = SCIF_REG,
75         .membase        = (char __iomem *)SCIF_REG,
76 };
77
78 static void scif_sercon_putc(int c)
79 {
80         while (((sci_in(&scif_port, SCFDR) & 0x1f00 >> 8) == 16))
81                 ;
82
83         sci_out(&scif_port, SCxTDR, c);
84         sci_in(&scif_port, SCxSR);
85         sci_out(&scif_port, SCxSR, 0xf3 & ~(0x20 | 0x40));
86
87         while ((sci_in(&scif_port, SCxSR) & 0x40) == 0);
88                 ;
89
90         if (c == '\n')
91                 scif_sercon_putc('\r');
92 }
93
94 static void scif_sercon_write(struct console *con, const char *s,
95                               unsigned count)
96 {
97         while (count-- > 0)
98                 scif_sercon_putc(*s++);
99 }
100
101 static int __init scif_sercon_setup(struct console *con, char *options)
102 {
103         con->cflag = CREAD | HUPCL | CLOCAL | B115200 | CS8;
104
105         return 0;
106 }
107
108 static struct console scif_console = {
109         .name           = "sercon",
110         .write          = scif_sercon_write,
111         .setup          = scif_sercon_setup,
112         .flags          = CON_PRINTBUFFER,
113         .index          = -1,
114 };
115
116 static void scif_sercon_init(int baud)
117 {
118         ctrl_outw(0, SCIF_REG + 8);
119         ctrl_outw(0, SCIF_REG);
120
121         /* Set baud rate */
122         ctrl_outb((CONFIG_SH_PCLK_FREQ + 16 * baud) /
123                   (32 * baud) - 1, SCIF_REG + 4);
124
125         ctrl_outw(12, SCIF_REG + 24);
126         ctrl_outw(8, SCIF_REG + 24);
127         ctrl_outw(0, SCIF_REG + 32);
128         ctrl_outw(0x60, SCIF_REG + 16);
129         ctrl_outw(0, SCIF_REG + 36);
130         ctrl_outw(0x30, SCIF_REG + 8);
131 }
132 #endif
133
134 /*
135  * Setup a default console, if more than one is compiled in, rely on the
136  * earlyprintk= parsing to give priority.
137  */
138 static struct console *early_console =
139 #ifdef CONFIG_SH_STANDARD_BIOS
140         &bios_console
141 #elif defined(CONFIG_EARLY_SCIF_CONSOLE)
142         &scif_console
143 #else
144         NULL
145 #endif
146         ;
147
148 static int __initdata keep_early;
149
150 int __init setup_early_printk(char *opt)
151 {
152         char *space;
153         char buf[256];
154
155         strlcpy(buf, opt, sizeof(buf));
156         space = strchr(buf, ' ');
157         if (space)
158                 *space = 0;
159
160         if (strstr(buf, "keep"))
161                 keep_early = 1;
162
163 #ifdef CONFIG_SH_STANDARD_BIOS
164         if (!strncmp(buf, "bios", 4))
165                 early_console = &bios_console;
166 #endif
167 #if defined(CONFIG_EARLY_SCIF_CONSOLE)
168         if (!strncmp(buf, "serial", 6)) {
169                 early_console = &scif_console;
170
171 #ifdef CONFIG_CPU_SH4
172                 scif_sercon_init(115200);
173 #endif
174         }
175 #endif
176
177         if (likely(early_console))
178                 register_console(early_console);
179
180         return 1;
181 }
182 __setup("earlyprintk=", setup_early_printk);
183
184 void __init disable_early_printk(void)
185 {
186         if (!keep_early) {
187                 printk("disabling early console\n");
188                 unregister_console(early_console);
189         } else
190                 printk("keeping early console\n");
191 }