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 21static 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 37static 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 65static 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 73static 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 \ 85selected 86#endif 87 88static struct console early_console_prom = { 89 .name = "early", 90 .write = early_console_write, 91 .flags = CON_PRINTBUFFER | CON_BOOT, 92 .index = -1 93}; 94 95void __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} 119