Commit | Line | Data |
---|---|---|
e8bf5bc7 LFT |
1 | /* |
2 | * Early printk for Nios2. | |
3 | * | |
4 | * Copyright (C) 2015, Altera Corporation | |
5 | * Copyright (C) 2010, Tobias Klauser <tklauser@distanz.ch> | |
6 | * Copyright (C) 2009, Wind River Systems Inc | |
7 | * Implemented by fredrik.markstrom@gmail.com and ivarholmqvist@gmail.com | |
8 | * | |
9 | * This file is subject to the terms and conditions of the GNU General Public | |
10 | * License. See the file "COPYING" in the main directory of this archive | |
11 | * for more details. | |
12 | */ | |
13 | ||
14 | #include <linux/console.h> | |
15 | #include <linux/init.h> | |
16 | #include <linux/kernel.h> | |
17 | #include <linux/io.h> | |
18 | ||
19 | #include <asm/prom.h> | |
20 | ||
21 | static unsigned long base_addr; | |
22 | ||
23 | #if defined(CONFIG_SERIAL_ALTERA_JTAGUART_CONSOLE) | |
24 | ||
25 | #define ALTERA_JTAGUART_DATA_REG 0 | |
26 | #define ALTERA_JTAGUART_CONTROL_REG 4 | |
27 | #define ALTERA_JTAGUART_CONTROL_WSPACE_MSK 0xFFFF0000 | |
28 | #define ALTERA_JTAGUART_CONTROL_AC_MSK 0x00000400 | |
29 | ||
30 | #define JUART_GET_CR() \ | |
31 | __builtin_ldwio((void *)(base_addr + ALTERA_JTAGUART_CONTROL_REG)) | |
32 | #define JUART_SET_CR(v) \ | |
33 | __builtin_stwio((void *)(base_addr + ALTERA_JTAGUART_CONTROL_REG), v) | |
34 | #define JUART_SET_TX(v) \ | |
35 | __builtin_stwio((void *)(base_addr + ALTERA_JTAGUART_DATA_REG), v) | |
36 | ||
37 | static void early_console_write(struct console *con, const char *s, unsigned n) | |
38 | { | |
39 | unsigned long status; | |
40 | ||
41 | while (n-- && *s) { | |
42 | while (((status = JUART_GET_CR()) | |
43 | & ALTERA_JTAGUART_CONTROL_WSPACE_MSK) == 0) { | |
44 | #if defined(CONFIG_SERIAL_ALTERA_JTAGUART_CONSOLE_BYPASS) | |
45 | if ((status & ALTERA_JTAGUART_CONTROL_AC_MSK) == 0) | |
46 | return; /* no connection activity */ | |
47 | #endif | |
48 | } | |
49 | JUART_SET_TX(*s); | |
50 | s++; | |
51 | } | |
52 | } | |
53 | ||
54 | #elif defined(CONFIG_SERIAL_ALTERA_UART_CONSOLE) | |
55 | ||
56 | #define ALTERA_UART_TXDATA_REG 4 | |
57 | #define ALTERA_UART_STATUS_REG 8 | |
58 | #define ALTERA_UART_STATUS_TRDY 0x0040 | |
59 | ||
60 | #define UART_GET_SR() \ | |
61 | __builtin_ldwio((void *)(base_addr + ALTERA_UART_STATUS_REG)) | |
62 | #define UART_SET_TX(v) \ | |
63 | __builtin_stwio((void *)(base_addr + ALTERA_UART_TXDATA_REG), v) | |
64 | ||
65 | static void early_console_putc(char c) | |
66 | { | |
67 | while (!(UART_GET_SR() & ALTERA_UART_STATUS_TRDY)) | |
68 | ; | |
69 | ||
70 | UART_SET_TX(c); | |
71 | } | |
72 | ||
73 | static void early_console_write(struct console *con, const char *s, unsigned n) | |
74 | { | |
75 | while (n-- && *s) { | |
76 | early_console_putc(*s); | |
77 | if (*s == '\n') | |
78 | early_console_putc('\r'); | |
79 | s++; | |
80 | } | |
81 | } | |
82 | ||
83 | #else | |
84 | # error Neither SERIAL_ALTERA_JTAGUART_CONSOLE nor SERIAL_ALTERA_UART_CONSOLE \ | |
85 | selected | |
86 | #endif | |
87 | ||
88 | static struct console early_console_prom = { | |
89 | .name = "early", | |
90 | .write = early_console_write, | |
91 | .flags = CON_PRINTBUFFER | CON_BOOT, | |
92 | .index = -1 | |
93 | }; | |
94 | ||
95 | void __init setup_early_printk(void) | |
96 | { | |
97 | #if defined(CONFIG_SERIAL_ALTERA_JTAGUART_CONSOLE) || \ | |
98 | defined(CONFIG_SERIAL_ALTERA_UART_CONSOLE) | |
99 | base_addr = of_early_console(); | |
100 | #else | |
101 | base_addr = 0; | |
102 | #endif | |
103 | ||
104 | if (!base_addr) | |
105 | return; | |
106 | ||
107 | #if defined(CONFIG_SERIAL_ALTERA_JTAGUART_CONSOLE_BYPASS) | |
108 | /* Clear activity bit so BYPASS doesn't stall if we've used JTAG for | |
109 | * downloading the kernel. This might cause early data to be lost even | |
110 | * if the JTAG terminal is running. | |
111 | */ | |
112 | JUART_SET_CR(JUART_GET_CR() | ALTERA_JTAGUART_CONTROL_AC_MSK); | |
113 | #endif | |
114 | ||
115 | early_console = &early_console_prom; | |
116 | register_console(early_console); | |
117 | pr_info("early_console initialized at 0x%08lx\n", base_addr); | |
118 | } |