2009-03-27 16:25:22 +03:00
/*
* Early printk support for Microblaze .
*
* Copyright ( C ) 2007 - 2009 Michal Simek < monstr @ monstr . eu >
* Copyright ( C ) 2007 - 2009 PetaLogix
* Copyright ( C ) 2003 - 2006 Yasushi SHOJI < yashi @ atmark - techno . 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/kernel.h>
# include <linux/init.h>
# include <linux/string.h>
# include <linux/tty.h>
# include <linux/io.h>
# include <asm/processor.h>
# include <linux/fcntl.h>
# include <asm/setup.h>
# include <asm/prom.h>
static u32 early_console_initialized ;
static u32 base_addr ;
2010-09-28 10:40:00 +04:00
# ifdef CONFIG_SERIAL_UARTLITE_CONSOLE
2010-09-28 10:33:53 +04:00
static void early_printk_uartlite_putc ( char c )
2009-03-27 16:25:22 +03:00
{
/*
* Limit how many times we ' ll spin waiting for TX FIFO status .
* This will prevent lockups if the base address is incorrectly
* set , or any other issue on the UARTLITE .
* This limit is pretty arbitrary , unless we are at about 10 baud
* we ' ll never timeout on a working UART .
*/
2011-04-06 15:06:45 +04:00
unsigned retries = 1000000 ;
2009-03-27 16:25:22 +03:00
/* read status bit - 0x8 offset */
2009-04-17 00:49:17 +04:00
while ( - - retries & & ( in_be32 ( base_addr + 8 ) & ( 1 < < 3 ) ) )
2009-03-27 16:25:22 +03:00
;
/* Only attempt the iowrite if we didn't timeout */
/* write to TX_FIFO - 0x4 offset */
if ( retries )
out_be32 ( base_addr + 4 , c & 0xff ) ;
}
2010-09-28 10:33:53 +04:00
static void early_printk_uartlite_write ( struct console * unused ,
2009-03-27 16:25:22 +03:00
const char * s , unsigned n )
{
while ( * s & & n - - > 0 ) {
if ( * s = = ' \n ' )
2010-09-28 10:33:53 +04:00
early_printk_uartlite_putc ( ' \r ' ) ;
2011-11-10 16:40:08 +04:00
early_printk_uartlite_putc ( * s ) ;
2009-03-27 16:25:22 +03:00
s + + ;
}
}
2010-09-28 10:33:53 +04:00
static struct console early_serial_uartlite_console = {
2009-03-27 16:25:22 +03:00
. name = " earlyser " ,
2010-09-28 10:33:53 +04:00
. write = early_printk_uartlite_write ,
2011-04-04 17:45:06 +04:00
. flags = CON_PRINTBUFFER | CON_BOOT ,
2009-03-27 16:25:22 +03:00
. index = - 1 ,
} ;
2010-09-28 10:40:00 +04:00
# endif /* CONFIG_SERIAL_UARTLITE_CONSOLE */
2009-03-27 16:25:22 +03:00
2010-09-28 10:17:03 +04:00
# ifdef CONFIG_SERIAL_8250_CONSOLE
static void early_printk_uart16550_putc ( char c )
{
/*
* Limit how many times we ' ll spin waiting for TX FIFO status .
* This will prevent lockups if the base address is incorrectly
* set , or any other issue on the UARTLITE .
* This limit is pretty arbitrary , unless we are at about 10 baud
* we ' ll never timeout on a working UART .
*/
# define UART_LSR_TEMT 0x40 /* Transmitter empty */
# define UART_LSR_THRE 0x20 /* Transmit-hold-register empty */
# define BOTH_EMPTY (UART_LSR_TEMT | UART_LSR_THRE)
unsigned retries = 10000 ;
while ( - - retries & &
! ( ( in_be32 ( base_addr + 0x14 ) & BOTH_EMPTY ) = = BOTH_EMPTY ) )
;
if ( retries )
out_be32 ( base_addr , c & 0xff ) ;
}
static void early_printk_uart16550_write ( struct console * unused ,
const char * s , unsigned n )
{
while ( * s & & n - - > 0 ) {
if ( * s = = ' \n ' )
early_printk_uart16550_putc ( ' \r ' ) ;
2011-11-10 16:40:08 +04:00
early_printk_uart16550_putc ( * s ) ;
2010-09-28 10:17:03 +04:00
s + + ;
}
}
static struct console early_serial_uart16550_console = {
. name = " earlyser " ,
. write = early_printk_uart16550_write ,
2011-04-04 17:45:06 +04:00
. flags = CON_PRINTBUFFER | CON_BOOT ,
2010-09-28 10:17:03 +04:00
. index = - 1 ,
} ;
# endif /* CONFIG_SERIAL_8250_CONSOLE */
2010-09-28 10:38:28 +04:00
static struct console * early_console ;
2009-03-27 16:25:22 +03:00
void early_printk ( const char * fmt , . . . )
{
char buf [ 512 ] ;
int n ;
va_list ap ;
if ( early_console_initialized ) {
va_start ( ap , fmt ) ;
n = vscnprintf ( buf , 512 , fmt , ap ) ;
early_console - > write ( early_console , buf , n ) ;
va_end ( ap ) ;
}
}
int __init setup_early_printk ( char * opt )
{
2011-04-14 13:48:43 +04:00
int version = 0 ;
2009-03-27 16:25:22 +03:00
if ( early_console_initialized )
return 1 ;
2011-04-14 13:48:43 +04:00
base_addr = of_early_console ( & version ) ;
2009-03-27 16:25:22 +03:00
if ( base_addr ) {
2009-05-26 18:30:10 +04:00
# ifdef CONFIG_MMU
early_console_reg_tlb_alloc ( base_addr ) ;
# endif
2011-04-14 13:48:43 +04:00
switch ( version ) {
# ifdef CONFIG_SERIAL_UARTLITE_CONSOLE
case UARTLITE :
printk ( KERN_INFO " Early console on uartlite "
" at 0x%08x \n " , base_addr ) ;
early_console = & early_serial_uartlite_console ;
break ;
# endif
2010-09-28 10:17:03 +04:00
# ifdef CONFIG_SERIAL_8250_CONSOLE
2011-04-14 13:48:43 +04:00
case UART16550 :
printk ( KERN_INFO " Early console on uart16650 "
" at 0x%08x \n " , base_addr ) ;
early_console = & early_serial_uart16550_console ;
break ;
2010-09-28 10:17:03 +04:00
# endif
2011-04-14 13:48:43 +04:00
default :
printk ( KERN_INFO " Unsupported early console %d \n " ,
version ) ;
return 1 ;
}
2010-09-28 10:17:03 +04:00
2011-04-04 17:45:06 +04:00
register_console ( early_console ) ;
2011-04-14 13:48:43 +04:00
early_console_initialized = 1 ;
2010-09-28 10:17:03 +04:00
return 0 ;
}
2010-09-28 10:40:00 +04:00
return 1 ;
2009-03-27 16:25:22 +03:00
}
2011-04-04 17:45:06 +04:00
/* Remap early console to virtual address and do not allocate one TLB
* only for early console because of performance degression */
void __init remap_early_printk ( void )
{
if ( ! early_console_initialized | | ! early_console )
return ;
printk ( KERN_INFO " early_printk_console remaping from 0x%x to " ,
base_addr ) ;
base_addr = ( u32 ) ioremap ( base_addr , PAGE_SIZE ) ;
printk ( KERN_CONT " 0x%x \n " , base_addr ) ;
}
2009-03-27 16:25:22 +03:00
void __init disable_early_printk ( void )
{
if ( ! early_console_initialized | | ! early_console )
return ;
printk ( KERN_WARNING " disabling early console \n " ) ;
unregister_console ( early_console ) ;
early_console_initialized = 0 ;
}