2005-04-16 15:20:36 -07:00
/*
* arch / sh / kernel / early_printk . c
*
* Copyright ( C ) 1999 , 2000 Niibe Yutaka
* Copyright ( C ) 2002 M . R . Brown
2006-09-27 14:26:53 +09:00
* Copyright ( C ) 2004 - 2006 Paul Mundt
2005-04-16 15:20:36 -07:00
*
* 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/tty.h>
# include <linux/init.h>
2006-11-27 12:10:23 +09:00
# include <linux/io.h>
2005-04-16 15:20:36 -07:00
# ifdef CONFIG_SH_STANDARD_BIOS
# include <asm/sh_bios.h>
/*
* Print a string through the BIOS
*/
static void sh_console_write ( struct console * co , const char * s ,
unsigned count )
{
sh_bios_console_write ( s , count ) ;
}
/*
* Setup initial baud / bits / parity . We do two things here :
* - construct a cflag setting for the first rs_open ( )
* - initialize the serial port
* Return non - zero if we didn ' t find a serial port .
*/
static int __init sh_console_setup ( struct console * co , char * options )
{
int cflag = CREAD | HUPCL | CLOCAL ;
/*
* Now construct a cflag setting .
* TODO : this is a totally bogus cflag , as we have
* no idea what serial settings the BIOS is using , or
* even if its using the serial port at all .
*/
cflag | = B115200 | CS8 | /*no parity*/ 0 ;
co - > cflag = cflag ;
return 0 ;
}
2006-09-27 14:26:53 +09:00
static struct console bios_console = {
2005-04-16 15:20:36 -07:00
. name = " bios " ,
. write = sh_console_write ,
. setup = sh_console_setup ,
. flags = CON_PRINTBUFFER ,
. index = - 1 ,
} ;
# endif
# ifdef CONFIG_EARLY_SCIF_CONSOLE
2006-09-27 14:26:53 +09:00
# include <linux/serial_core.h>
# include "../../../drivers/serial/sh-sci.h"
static struct uart_port scif_port = {
2006-11-27 12:10:23 +09:00
. mapbase = CONFIG_EARLY_SCIF_CONSOLE_PORT ,
. membase = ( char __iomem * ) CONFIG_EARLY_SCIF_CONSOLE_PORT ,
2006-09-27 14:26:53 +09:00
} ;
2005-04-16 15:20:36 -07:00
static void scif_sercon_putc ( int c )
{
2006-09-27 14:26:53 +09:00
while ( ( ( sci_in ( & scif_port , SCFDR ) & 0x1f00 > > 8 ) = = 16 ) )
;
2005-04-16 15:20:36 -07:00
2006-09-27 14:26:53 +09:00
sci_out ( & scif_port , SCxTDR , c ) ;
sci_in ( & scif_port , SCxSR ) ;
sci_out ( & scif_port , SCxSR , 0xf3 & ~ ( 0x20 | 0x40 ) ) ;
while ( ( sci_in ( & scif_port , SCxSR ) & 0x40 ) = = 0 ) ;
;
2005-04-16 15:20:36 -07:00
if ( c = = ' \n ' )
scif_sercon_putc ( ' \r ' ) ;
}
2006-09-27 14:26:53 +09:00
static void scif_sercon_write ( struct console * con , const char * s ,
unsigned count )
2005-04-16 15:20:36 -07:00
{
while ( count - - > 0 )
scif_sercon_putc ( * s + + ) ;
}
static int __init scif_sercon_setup ( struct console * con , char * options )
{
con - > cflag = CREAD | HUPCL | CLOCAL | B115200 | CS8 ;
return 0 ;
}
2006-09-27 14:26:53 +09:00
static struct console scif_console = {
2005-04-16 15:20:36 -07:00
. name = " sercon " ,
. write = scif_sercon_write ,
. setup = scif_sercon_setup ,
. flags = CON_PRINTBUFFER ,
. index = - 1 ,
} ;
2006-11-27 12:10:23 +09:00
# if defined(CONFIG_CPU_SH4) && !defined(CONFIG_SH_STANDARD_BIOS)
/*
* Simple SCIF init , primarily aimed at SH7750 and other similar SH - 4
* devices that aren ' t using sh - ipl + g .
*/
2006-09-27 14:26:53 +09:00
static void scif_sercon_init ( int baud )
2005-04-16 15:20:36 -07:00
{
2006-11-27 12:10:23 +09:00
ctrl_outw ( 0 , scif_port . mapbase + 8 ) ;
ctrl_outw ( 0 , scif_port . mapbase ) ;
2005-04-16 15:20:36 -07:00
/* Set baud rate */
ctrl_outb ( ( CONFIG_SH_PCLK_FREQ + 16 * baud ) /
2006-11-27 12:10:23 +09:00
( 32 * baud ) - 1 , scif_port . mapbase + 4 ) ;
ctrl_outw ( 12 , scif_port . mapbase + 24 ) ;
ctrl_outw ( 8 , scif_port . mapbase + 24 ) ;
ctrl_outw ( 0 , scif_port . mapbase + 32 ) ;
ctrl_outw ( 0x60 , scif_port . mapbase + 16 ) ;
ctrl_outw ( 0 , scif_port . mapbase + 36 ) ;
ctrl_outw ( 0x30 , scif_port . mapbase + 8 ) ;
2005-04-16 15:20:36 -07:00
}
2006-11-27 12:10:23 +09:00
# endif /* CONFIG_CPU_SH4 && !CONFIG_SH_STANDARD_BIOS */
# endif /* CONFIG_EARLY_SCIF_CONSOLE */
2005-04-16 15:20:36 -07:00
2006-09-27 14:26:53 +09:00
/*
* Setup a default console , if more than one is compiled in , rely on the
* earlyprintk = parsing to give priority .
*/
static struct console * early_console =
# ifdef CONFIG_SH_STANDARD_BIOS
& bios_console
# elif defined(CONFIG_EARLY_SCIF_CONSOLE)
& scif_console
# else
NULL
# endif
;
static int __initdata keep_early ;
2006-12-12 09:00:47 +09:00
static int early_console_initialized ;
2006-09-27 14:26:53 +09:00
2006-12-12 09:00:47 +09:00
int __init setup_early_printk ( char * buf )
2005-04-16 15:20:36 -07:00
{
2006-12-12 09:00:47 +09:00
if ( ! buf )
return 0 ;
2006-09-27 14:26:53 +09:00
2006-12-12 09:00:47 +09:00
if ( early_console_initialized )
return 0 ;
early_console_initialized = 1 ;
2006-09-27 14:26:53 +09:00
if ( strstr ( buf , " keep " ) )
keep_early = 1 ;
# ifdef CONFIG_SH_STANDARD_BIOS
if ( ! strncmp ( buf , " bios " , 4 ) )
early_console = & bios_console ;
# endif
# if defined(CONFIG_EARLY_SCIF_CONSOLE)
if ( ! strncmp ( buf , " serial " , 6 ) ) {
early_console = & scif_console ;
2006-11-27 12:10:23 +09:00
# if defined(CONFIG_CPU_SH4) && !defined(CONFIG_SH_STANDARD_BIOS)
2006-09-27 14:26:53 +09:00
scif_sercon_init ( 115200 ) ;
# endif
}
2005-04-16 15:20:36 -07:00
# endif
2006-09-27 14:26:53 +09:00
if ( likely ( early_console ) )
register_console ( early_console ) ;
2006-12-12 09:00:47 +09:00
return 0 ;
2005-04-16 15:20:36 -07:00
}
2006-12-12 09:00:47 +09:00
early_param ( " earlyprintk " , setup_early_printk ) ;
2005-04-16 15:20:36 -07:00
2006-09-27 14:26:53 +09:00
void __init disable_early_printk ( void )
2005-04-16 15:20:36 -07:00
{
2006-12-12 09:00:47 +09:00
if ( ! early_console_initialized | | ! early_console )
return ;
2006-09-27 14:26:53 +09:00
if ( ! keep_early ) {
printk ( " disabling early console \n " ) ;
unregister_console ( early_console ) ;
} else
printk ( " keeping early console \n " ) ;
2005-04-16 15:20:36 -07:00
}