2005-04-17 02:20:36 +04:00
/*
* arch / sh / kernel / early_printk . c
*
* Copyright ( C ) 1999 , 2000 Niibe Yutaka
* Copyright ( C ) 2002 M . R . Brown
2006-09-27 09:26:53 +04:00
* Copyright ( C ) 2004 - 2006 Paul Mundt
2005-04-17 02:20:36 +04: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 06:10:23 +03:00
# include <linux/io.h>
2005-04-17 02:20:36 +04: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 09:26:53 +04:00
static struct console bios_console = {
2005-04-17 02:20:36 +04: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 09:26:53 +04:00
# include <linux/serial_core.h>
# include "../../../drivers/serial/sh-sci.h"
static struct uart_port scif_port = {
2006-11-27 06:10:23 +03:00
. mapbase = CONFIG_EARLY_SCIF_CONSOLE_PORT ,
. membase = ( char __iomem * ) CONFIG_EARLY_SCIF_CONSOLE_PORT ,
2006-09-27 09:26:53 +04:00
} ;
2005-04-17 02:20:36 +04:00
static void scif_sercon_putc ( int c )
{
2006-09-27 09:26:53 +04:00
while ( ( ( sci_in ( & scif_port , SCFDR ) & 0x1f00 > > 8 ) = = 16 ) )
;
2005-04-17 02:20:36 +04:00
2006-09-27 09:26:53 +04: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-17 02:20:36 +04:00
if ( c = = ' \n ' )
scif_sercon_putc ( ' \r ' ) ;
}
2006-09-27 09:26:53 +04:00
static void scif_sercon_write ( struct console * con , const char * s ,
unsigned count )
2005-04-17 02:20:36 +04: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 09:26:53 +04:00
static struct console scif_console = {
2005-04-17 02:20:36 +04:00
. name = " sercon " ,
. write = scif_sercon_write ,
. setup = scif_sercon_setup ,
. flags = CON_PRINTBUFFER ,
. index = - 1 ,
} ;
2006-11-27 06:10:23 +03:00
# if defined(CONFIG_CPU_SH4) && !defined(CONFIG_SH_STANDARD_BIOS)
2006-12-19 06:16:06 +03:00
# define DEFAULT_BAUD 115200
2006-11-27 06:10:23 +03:00
/*
* Simple SCIF init , primarily aimed at SH7750 and other similar SH - 4
* devices that aren ' t using sh - ipl + g .
*/
2006-12-19 06:16:06 +03:00
static void scif_sercon_init ( char * s )
2005-04-17 02:20:36 +04:00
{
2006-12-19 06:16:06 +03:00
unsigned baud = DEFAULT_BAUD ;
char * e ;
if ( * s = = ' , ' )
+ + s ;
if ( * s ) {
/* ignore ioport/device name */
s + = strcspn ( s , " , " ) ;
if ( * s = = ' , ' )
s + + ;
}
if ( * s ) {
baud = simple_strtoul ( s , & e , 0 ) ;
if ( baud = = 0 | | s = = e )
baud = DEFAULT_BAUD ;
}
2006-11-27 06:10:23 +03:00
ctrl_outw ( 0 , scif_port . mapbase + 8 ) ;
ctrl_outw ( 0 , scif_port . mapbase ) ;
2005-04-17 02:20:36 +04:00
/* Set baud rate */
ctrl_outb ( ( CONFIG_SH_PCLK_FREQ + 16 * baud ) /
2006-11-27 06:10:23 +03: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-17 02:20:36 +04:00
}
2006-11-27 06:10:23 +03:00
# endif /* CONFIG_CPU_SH4 && !CONFIG_SH_STANDARD_BIOS */
# endif /* CONFIG_EARLY_SCIF_CONSOLE */
2005-04-17 02:20:36 +04:00
2006-09-27 09:26:53 +04: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 03:00:47 +03:00
static int early_console_initialized ;
2006-09-27 09:26:53 +04:00
2006-12-12 03:00:47 +03:00
int __init setup_early_printk ( char * buf )
2005-04-17 02:20:36 +04:00
{
2006-12-12 03:00:47 +03:00
if ( ! buf )
return 0 ;
2006-09-27 09:26:53 +04:00
2006-12-12 03:00:47 +03:00
if ( early_console_initialized )
return 0 ;
early_console_initialized = 1 ;
2006-09-27 09:26:53 +04: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 06:10:23 +03:00
# if defined(CONFIG_CPU_SH4) && !defined(CONFIG_SH_STANDARD_BIOS)
2006-12-19 06:16:06 +03:00
scif_sercon_init ( buf + 6 ) ;
2006-09-27 09:26:53 +04:00
# endif
}
2005-04-17 02:20:36 +04:00
# endif
2006-09-27 09:26:53 +04:00
2007-05-08 11:26:49 +04:00
if ( likely ( early_console ) ) {
if ( keep_early )
early_console - > flags & = ~ CON_BOOT ;
else
early_console - > flags | = CON_BOOT ;
2006-09-27 09:26:53 +04:00
register_console ( early_console ) ;
2007-05-08 11:26:49 +04:00
}
2006-09-27 09:26:53 +04:00
2006-12-12 03:00:47 +03:00
return 0 ;
2005-04-17 02:20:36 +04:00
}
2006-12-12 03:00:47 +03:00
early_param ( " earlyprintk " , setup_early_printk ) ;