2 * Early serial console for 8250/16550 devices
4 * (c) Copyright 2004 Hewlett-Packard Development Company, L.P.
5 * Bjorn Helgaas <bjorn.helgaas@hp.com>
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License version 2 as
9 * published by the Free Software Foundation.
11 * Based on the 8250.c serial driver, Copyright (C) 2001 Russell King,
12 * and on early_printk.c by Andi Kleen.
14 * This is for use before the serial driver has initialized, in
15 * particular, before the UARTs have been discovered and named.
16 * Instead of specifying the console device as, e.g., "ttyS0",
17 * we locate the device directly by its MMIO or I/O port address.
19 * The user can specify the device directly, e.g.,
20 * earlycon=uart8250,io,0x3f8,9600n8
21 * earlycon=uart8250,mmio,0xff5e0000,115200n8
22 * earlycon=uart8250,mmio32,0xff5e0000,115200n8
24 * console=uart8250,io,0x3f8,9600n8
25 * console=uart8250,mmio,0xff5e0000,115200n8
26 * console=uart8250,mmio32,0xff5e0000,115200n8
29 #include <linux/tty.h>
30 #include <linux/init.h>
31 #include <linux/console.h>
32 #include <linux/serial_core.h>
33 #include <linux/serial_reg.h>
34 #include <linux/serial.h>
35 #include <linux/serial_8250.h>
37 #include <asm/serial.h>
38 #ifdef CONFIG_FIX_EARLYCON_MEM
39 #include <asm/pgtable.h>
40 #include <asm/fixmap.h>
43 struct early_serial8250_device
{
44 struct uart_port port
;
45 char options
[16]; /* e.g., 115200n8 */
49 static struct early_serial8250_device early_device
;
51 static unsigned int __init
serial_in(struct uart_port
*port
, int offset
)
53 switch (port
->iotype
) {
55 return readb(port
->membase
+ offset
);
57 return readl(port
->membase
+ (offset
<< 2));
59 return inb(port
->iobase
+ offset
);
65 static void __init
serial_out(struct uart_port
*port
, int offset
, int value
)
67 switch (port
->iotype
) {
69 writeb(value
, port
->membase
+ offset
);
72 writel(value
, port
->membase
+ (offset
<< 2));
75 outb(value
, port
->iobase
+ offset
);
80 #define BOTH_EMPTY (UART_LSR_TEMT | UART_LSR_THRE)
82 static void __init
wait_for_xmitr(struct uart_port
*port
)
87 status
= serial_in(port
, UART_LSR
);
88 if ((status
& BOTH_EMPTY
) == BOTH_EMPTY
)
94 static void __init
serial_putc(struct uart_port
*port
, int c
)
97 serial_out(port
, UART_TX
, c
);
100 static void __init
early_serial8250_write(struct console
*console
,
101 const char *s
, unsigned int count
)
103 struct uart_port
*port
= &early_device
.port
;
106 /* Save the IER and disable interrupts */
107 ier
= serial_in(port
, UART_IER
);
108 serial_out(port
, UART_IER
, 0);
110 uart_console_write(port
, s
, count
, serial_putc
);
112 /* Wait for transmitter to become empty and restore the IER */
113 wait_for_xmitr(port
);
114 serial_out(port
, UART_IER
, ier
);
117 static unsigned int __init
probe_baud(struct uart_port
*port
)
119 unsigned char lcr
, dll
, dlm
;
122 lcr
= serial_in(port
, UART_LCR
);
123 serial_out(port
, UART_LCR
, lcr
| UART_LCR_DLAB
);
124 dll
= serial_in(port
, UART_DLL
);
125 dlm
= serial_in(port
, UART_DLM
);
126 serial_out(port
, UART_LCR
, lcr
);
128 quot
= (dlm
<< 8) | dll
;
129 return (port
->uartclk
/ 16) / quot
;
132 static void __init
init_port(struct early_serial8250_device
*device
)
134 struct uart_port
*port
= &device
->port
;
135 unsigned int divisor
;
138 serial_out(port
, UART_LCR
, 0x3); /* 8n1 */
139 serial_out(port
, UART_IER
, 0); /* no interrupt */
140 serial_out(port
, UART_FCR
, 0); /* no fifo */
141 serial_out(port
, UART_MCR
, 0x3); /* DTR + RTS */
143 divisor
= port
->uartclk
/ (16 * device
->baud
);
144 c
= serial_in(port
, UART_LCR
);
145 serial_out(port
, UART_LCR
, c
| UART_LCR_DLAB
);
146 serial_out(port
, UART_DLL
, divisor
& 0xff);
147 serial_out(port
, UART_DLM
, (divisor
>> 8) & 0xff);
148 serial_out(port
, UART_LCR
, c
& ~UART_LCR_DLAB
);
151 static int __init
parse_options(struct early_serial8250_device
*device
,
154 struct uart_port
*port
= &device
->port
;
155 int mmio
, mmio32
, length
;
160 port
->uartclk
= BASE_BAUD
* 16;
162 mmio
= !strncmp(options
, "mmio,", 5);
163 mmio32
= !strncmp(options
, "mmio32,", 7);
164 if (mmio
|| mmio32
) {
165 port
->iotype
= (mmio
? UPIO_MEM
: UPIO_MEM32
);
166 port
->mapbase
= simple_strtoul(options
+ (mmio
? 5 : 7),
170 #ifdef CONFIG_FIX_EARLYCON_MEM
171 set_fixmap_nocache(FIX_EARLYCON_MEM_BASE
,
172 port
->mapbase
& PAGE_MASK
);
174 (void __iomem
*)__fix_to_virt(FIX_EARLYCON_MEM_BASE
);
175 port
->membase
+= port
->mapbase
& ~PAGE_MASK
;
177 port
->membase
= ioremap_nocache(port
->mapbase
, 64);
178 if (!port
->membase
) {
179 printk(KERN_ERR
"%s: Couldn't ioremap 0x%llx\n",
181 (unsigned long long) port
->mapbase
);
185 } else if (!strncmp(options
, "io,", 3)) {
186 port
->iotype
= UPIO_PORT
;
187 port
->iobase
= simple_strtoul(options
+ 3, &options
, 0);
192 options
= strchr(options
, ',');
195 device
->baud
= simple_strtoul(options
, NULL
, 0);
196 length
= min(strcspn(options
, " "), sizeof(device
->options
));
197 strncpy(device
->options
, options
, length
);
199 device
->baud
= probe_baud(port
);
200 snprintf(device
->options
, sizeof(device
->options
), "%u",
206 "Early serial console at MMIO%s 0x%llx (options '%s')\n",
208 (unsigned long long)port
->mapbase
,
212 "Early serial console at I/O port 0x%lx (options '%s')\n",
219 static struct console early_serial8250_console __initdata
= {
221 .write
= early_serial8250_write
,
222 .flags
= CON_PRINTBUFFER
| CON_BOOT
,
226 static int __init
early_serial8250_setup(char *options
)
228 struct early_serial8250_device
*device
= &early_device
;
231 if (device
->port
.membase
|| device
->port
.iobase
)
234 err
= parse_options(device
, options
);
242 int __init
setup_early_serial8250_console(char *cmdline
)
247 options
= strstr(cmdline
, "uart8250,");
249 options
= strstr(cmdline
, "uart,");
254 options
= strchr(cmdline
, ',') + 1;
255 err
= early_serial8250_setup(options
);
259 register_console(&early_serial8250_console
);
264 int serial8250_find_port_for_earlycon(void)
266 struct early_serial8250_device
*device
= &early_device
;
267 struct uart_port
*port
= &device
->port
;
271 if (!device
->port
.membase
&& !device
->port
.iobase
)
274 line
= serial8250_find_port(port
);
278 ret
= update_console_cmdline("uart", 8250,
279 "ttyS", line
, device
->options
);
281 ret
= update_console_cmdline("uart", 0,
282 "ttyS", line
, device
->options
);
287 early_param("earlycon", setup_early_serial8250_console
);