| /* |
| * Early printk for Nios2. |
| * |
| * Copyright (C) 2015, Altera Corporation |
| * Copyright (C) 2010, Tobias Klauser <tklauser@distanz.ch> |
| * Copyright (C) 2009, Wind River Systems Inc |
| * Implemented by fredrik.markstrom@gmail.com and ivarholmqvist@gmail.com |
| * |
| * This file is subject to the terms and conditions of the GNU General Public |
| * License. See the file "COPYING" in the main directory of this archive |
| * for more details. |
| */ |
| |
| #include <linux/console.h> |
| #include <linux/init.h> |
| #include <linux/kernel.h> |
| #include <linux/io.h> |
| |
| #include <asm/prom.h> |
| |
| static unsigned long base_addr; |
| |
| #if defined(CONFIG_SERIAL_ALTERA_JTAGUART_CONSOLE) |
| |
| #define ALTERA_JTAGUART_DATA_REG 0 |
| #define ALTERA_JTAGUART_CONTROL_REG 4 |
| #define ALTERA_JTAGUART_CONTROL_WSPACE_MSK 0xFFFF0000 |
| #define ALTERA_JTAGUART_CONTROL_AC_MSK 0x00000400 |
| |
| #define JUART_GET_CR() \ |
| __builtin_ldwio((void *)(base_addr + ALTERA_JTAGUART_CONTROL_REG)) |
| #define JUART_SET_CR(v) \ |
| __builtin_stwio((void *)(base_addr + ALTERA_JTAGUART_CONTROL_REG), v) |
| #define JUART_SET_TX(v) \ |
| __builtin_stwio((void *)(base_addr + ALTERA_JTAGUART_DATA_REG), v) |
| |
| static void early_console_write(struct console *con, const char *s, unsigned n) |
| { |
| unsigned long status; |
| |
| while (n-- && *s) { |
| while (((status = JUART_GET_CR()) |
| & ALTERA_JTAGUART_CONTROL_WSPACE_MSK) == 0) { |
| #if defined(CONFIG_SERIAL_ALTERA_JTAGUART_CONSOLE_BYPASS) |
| if ((status & ALTERA_JTAGUART_CONTROL_AC_MSK) == 0) |
| return; /* no connection activity */ |
| #endif |
| } |
| JUART_SET_TX(*s); |
| s++; |
| } |
| } |
| |
| #elif defined(CONFIG_SERIAL_ALTERA_UART_CONSOLE) |
| |
| #define ALTERA_UART_TXDATA_REG 4 |
| #define ALTERA_UART_STATUS_REG 8 |
| #define ALTERA_UART_STATUS_TRDY 0x0040 |
| |
| #define UART_GET_SR() \ |
| __builtin_ldwio((void *)(base_addr + ALTERA_UART_STATUS_REG)) |
| #define UART_SET_TX(v) \ |
| __builtin_stwio((void *)(base_addr + ALTERA_UART_TXDATA_REG), v) |
| |
| static void early_console_putc(char c) |
| { |
| while (!(UART_GET_SR() & ALTERA_UART_STATUS_TRDY)) |
| ; |
| |
| UART_SET_TX(c); |
| } |
| |
| static void early_console_write(struct console *con, const char *s, unsigned n) |
| { |
| while (n-- && *s) { |
| early_console_putc(*s); |
| if (*s == '\n') |
| early_console_putc('\r'); |
| s++; |
| } |
| } |
| |
| #else |
| # error Neither SERIAL_ALTERA_JTAGUART_CONSOLE nor SERIAL_ALTERA_UART_CONSOLE \ |
| selected |
| #endif |
| |
| static struct console early_console_prom = { |
| .name = "early", |
| .write = early_console_write, |
| .flags = CON_PRINTBUFFER | CON_BOOT, |
| .index = -1 |
| }; |
| |
| void __init setup_early_printk(void) |
| { |
| #if defined(CONFIG_SERIAL_ALTERA_JTAGUART_CONSOLE) || \ |
| defined(CONFIG_SERIAL_ALTERA_UART_CONSOLE) |
| base_addr = of_early_console(); |
| #else |
| base_addr = 0; |
| #endif |
| |
| if (!base_addr) |
| return; |
| |
| #if defined(CONFIG_SERIAL_ALTERA_JTAGUART_CONSOLE_BYPASS) |
| /* Clear activity bit so BYPASS doesn't stall if we've used JTAG for |
| * downloading the kernel. This might cause early data to be lost even |
| * if the JTAG terminal is running. |
| */ |
| JUART_SET_CR(JUART_GET_CR() | ALTERA_JTAGUART_CONTROL_AC_MSK); |
| #endif |
| |
| early_console = &early_console_prom; |
| register_console(early_console); |
| pr_info("early_console initialized at 0x%08lx\n", base_addr); |
| } |