4 * Copyright (C) 2012 ARM Ltd.
5 * Author: Catalin Marinas <catalin.marinas@arm.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 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program. If not, see <http://www.gnu.org/licenses/>.
19 #include <linux/kernel.h>
20 #include <linux/console.h>
21 #include <linux/init.h>
22 #include <linux/string.h>
26 #include <linux/amba/serial.h>
27 #include <linux/serial_reg.h>
29 static void __iomem
*early_base
;
30 static void (*printch
)(char ch
);
33 * PL011 single character TX.
35 static void pl011_printch(char ch
)
37 while (readl_relaxed(early_base
+ UART01x_FR
) & UART01x_FR_TXFF
)
39 writeb_relaxed(ch
, early_base
+ UART01x_DR
);
40 while (readl_relaxed(early_base
+ UART01x_FR
) & UART01x_FR_BUSY
)
45 * Semihosting-based debug console
47 static void smh_printch(char ch
)
49 asm volatile("mov x1, %0\n"
52 : : "r" (&ch
) : "x0", "x1", "memory");
56 * 8250/16550 (8-bit aligned registers) single character TX.
58 static void uart8250_8bit_printch(char ch
)
60 while (!(readb_relaxed(early_base
+ UART_LSR
) & UART_LSR_THRE
))
62 writeb_relaxed(ch
, early_base
+ UART_TX
);
66 * 8250/16550 (32-bit aligned registers) single character TX.
68 static void uart8250_32bit_printch(char ch
)
70 while (!(readl_relaxed(early_base
+ (UART_LSR
<< 2)) & UART_LSR_THRE
))
72 writel_relaxed(ch
, early_base
+ (UART_TX
<< 2));
75 struct earlycon_match
{
77 void (*printch
)(char ch
);
80 static const struct earlycon_match earlycon_match
[] __initconst
= {
81 { .name
= "pl011", .printch
= pl011_printch
, },
82 { .name
= "smh", .printch
= smh_printch
, },
83 { .name
= "uart8250-8bit", .printch
= uart8250_8bit_printch
, },
84 { .name
= "uart8250-32bit", .printch
= uart8250_32bit_printch
, },
88 static void early_write(struct console
*con
, const char *s
, unsigned n
)
98 static struct console early_console_dev
= {
100 .write
= early_write
,
101 .flags
= CON_PRINTBUFFER
| CON_BOOT
,
106 * Parse earlyprintk=... parameter in the format:
108 * <name>[,<addr>][,<options>]
110 * and register the early console. It is assumed that the UART has been
111 * initialised by the bootloader already.
113 static int __init
setup_early_printk(char *buf
)
115 const struct earlycon_match
*match
= earlycon_match
;
116 phys_addr_t paddr
= 0;
119 pr_warning("No earlyprintk arguments passed.\n");
123 while (match
->name
) {
124 size_t len
= strlen(match
->name
);
125 if (!strncmp(buf
, match
->name
, len
)) {
132 pr_warning("Unknown earlyprintk arguments: %s\n", buf
);
137 if (!strncmp(buf
, ",0x", 3)) {
139 paddr
= simple_strtoul(buf
+ 1, &e
, 16);
142 /* no options parsing yet */
145 early_base
= early_io_map(paddr
, EARLYCON_IOBASE
);
147 printch
= match
->printch
;
148 early_console
= &early_console_dev
;
149 register_console(&early_console_dev
);
154 early_param("earlyprintk", setup_early_printk
);