| /* | 
 |  * 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); | 
 | } |