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
2007-10-02 16:24:50 +09:00
* Copyright ( C ) 2004 - 2007 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>
2007-08-20 08:59:33 +09:00
# include <linux/delay.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"
2007-12-26 11:45:06 +09:00
# if defined(CONFIG_CPU_SUBTYPE_SH7720) || \
defined ( CONFIG_CPU_SUBTYPE_SH7721 )
2007-08-20 08:59:33 +09:00
# define EPK_SCSMR_VALUE 0x000
# define EPK_SCBRR_VALUE 0x00C
# define EPK_FIFO_SIZE 64
# define EPK_FIFO_BITS (0x7f00 >> 8)
# else
# define EPK_FIFO_SIZE 16
# define EPK_FIFO_BITS (0x1f00 >> 8)
# endif
2006-09-27 14:26:53 +09:00
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 )
{
2007-08-20 08:59:33 +09:00
while ( ( ( sci_in ( & scif_port , SCFDR ) & EPK_FIFO_BITS ) > = EPK_FIFO_SIZE ) )
2006-09-27 14:26:53 +09:00
;
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 ) ) ;
2007-08-17 01:25:34 +09:00
while ( ( sci_in ( & scif_port , SCxSR ) & 0x40 ) = = 0 )
2006-09-27 14:26:53 +09:00
;
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 ,
} ;
2007-08-20 08:59:33 +09:00
# if !defined(CONFIG_SH_STANDARD_BIOS)
2007-12-26 11:45:06 +09:00
# if defined(CONFIG_CPU_SUBTYPE_SH7720) || \
defined ( CONFIG_CPU_SUBTYPE_SH7721 )
2007-08-20 08:59:33 +09:00
static void scif_sercon_init ( char * s )
{
sci_out ( & scif_port , SCSCR , 0x0000 ) ; /* clear TE and RE */
sci_out ( & scif_port , SCFCR , 0x4006 ) ; /* reset */
sci_out ( & scif_port , SCSCR , 0x0000 ) ; /* select internal clock */
sci_out ( & scif_port , SCSMR , EPK_SCSMR_VALUE ) ;
sci_out ( & scif_port , SCBRR , EPK_SCBRR_VALUE ) ;
mdelay ( 1 ) ; /* wait 1-bit time */
sci_out ( & scif_port , SCFCR , 0x0030 ) ; /* TTRG=b'11 */
sci_out ( & scif_port , SCSCR , 0x0030 ) ; /* TE, RE */
}
# elif defined(CONFIG_CPU_SH4)
2006-12-19 12:16:06 +09:00
# define DEFAULT_BAUD 115200
2006-11-27 12:10:23 +09:00
/*
* Simple SCIF init , primarily aimed at SH7750 and other similar SH - 4
* devices that aren ' t using sh - ipl + g .
*/
2006-12-19 12:16:06 +09:00
static void scif_sercon_init ( char * s )
2005-04-16 15:20:36 -07:00
{
2006-12-19 12:16:06 +09: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 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
}
2007-08-20 08:59:33 +09:00
# endif /* defined(CONFIG_CPU_SUBTYPE_SH7720) */
# endif /* !defined(CONFIG_SH_STANDARD_BIOS) */
2006-11-27 12:10:23 +09:00
# 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
;
2007-10-02 16:24:50 +09:00
static int __init setup_early_printk ( char * buf )
2005-04-16 15:20:36 -07:00
{
2007-10-02 16:24:50 +09:00
int keep_early = 0 ;
2006-09-27 14:26:53 +09:00
2007-10-02 16:24:50 +09:00
if ( ! buf )
2006-12-12 09:00:47 +09:00
return 0 ;
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 ;
2007-12-26 11:45:06 +09:00
# if !defined(CONFIG_SH_STANDARD_BIOS)
# if defined(CONFIG_CPU_SH4) || defined(CONFIG_CPU_SUBTYPE_SH7720) || \
defined ( CONFIG_CPU_SUBTYPE_SH7721 )
2006-12-19 12:16:06 +09:00
scif_sercon_init ( buf + 6 ) ;
2007-12-26 11:45:06 +09:00
# endif
2006-09-27 14:26:53 +09:00
# endif
}
2005-04-16 15:20:36 -07:00
# endif
2006-09-27 14:26:53 +09:00
2007-05-08 00:26:49 -07:00
if ( likely ( early_console ) ) {
if ( keep_early )
early_console - > flags & = ~ CON_BOOT ;
else
early_console - > flags | = CON_BOOT ;
2006-09-27 14:26:53 +09:00
register_console ( early_console ) ;
2007-05-08 00:26:49 -07:00
}
2006-09-27 14:26:53 +09:00
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 ) ;