@ -22,6 +22,7 @@
*/
# include <common.h>
# include <fdtdec.h>
# include <linux/compiler.h>
# include <asm/io.h>
# include <asm/arch/uart.h>
@ -34,10 +35,21 @@ DECLARE_GLOBAL_DATA_PTR;
# define RX_FIFO_FULL_MASK (1 << 8)
# define TX_FIFO_FULL_MASK (1 << 24)
/* Information about a serial port */
struct fdt_serial {
u32 base_addr ; /* address of registers in physical memory */
u8 port_id ; /* uart port number */
u8 enabled ; /* 1 if enabled, 0 if disabled */
} config __attribute__ ( ( section ( " .data " ) ) ) ;
static inline struct s5p_uart * s5p_get_base_uart ( int dev_index )
{
# ifdef CONFIG_OF_CONTROL
return ( struct s5p_uart * ) ( config . base_addr ) ;
# else
u32 offset = dev_index * sizeof ( struct s5p_uart ) ;
return ( struct s5p_uart * ) ( samsung_get_base_uart ( ) + offset ) ;
# endif
}
/*
@ -73,6 +85,16 @@ void serial_setbrg_dev(const int dev_index)
u32 baudrate = gd - > baudrate ;
u32 val ;
# if defined(CONFIG_SILENT_CONSOLE) && \
defined ( CONFIG_OF_CONTROL ) & & \
! defined ( CONFIG_SPL_BUILD )
if ( fdtdec_get_config_int ( gd - > fdt_blob , " silent_console " , 0 ) )
gd - > flags | = GD_FLG_SILENT ;
# endif
if ( ! config . enabled )
return ;
val = uclk / baudrate ;
writel ( val / 16 - 1 , & uart - > ubrdiv ) ;
@ -133,6 +155,9 @@ int serial_getc_dev(const int dev_index)
{
struct s5p_uart * const uart = s5p_get_base_uart ( dev_index ) ;
if ( ! config . enabled )
return 0 ;
/* wait for character to arrive */
while ( ! ( readl ( & uart - > ufstat ) & ( RX_FIFO_COUNT_MASK |
RX_FIFO_FULL_MASK ) ) ) {
@ -150,6 +175,9 @@ void serial_putc_dev(const char c, const int dev_index)
{
struct s5p_uart * const uart = s5p_get_base_uart ( dev_index ) ;
if ( ! config . enabled )
return ;
/* wait for room in the tx FIFO */
while ( ( readl ( & uart - > ufstat ) & TX_FIFO_FULL_MASK ) ) {
if ( serial_err_check ( dev_index , 1 ) )
@ -170,6 +198,9 @@ int serial_tstc_dev(const int dev_index)
{
struct s5p_uart * const uart = s5p_get_base_uart ( dev_index ) ;
if ( ! config . enabled )
return 0 ;
return ( int ) ( readl ( & uart - > utrstat ) & 0x1 ) ;
}
@ -212,8 +243,54 @@ DECLARE_S5P_SERIAL_FUNCTIONS(3);
struct serial_device s5p_serial3_device =
INIT_S5P_SERIAL_STRUCTURE ( 3 , " s5pser3 " ) ;
# ifdef CONFIG_OF_CONTROL
int fdtdec_decode_console ( int * index , struct fdt_serial * uart )
{
const void * blob = gd - > fdt_blob ;
int node ;
node = fdt_path_offset ( blob , " console " ) ;
if ( node < 0 )
return node ;
uart - > base_addr = fdtdec_get_addr ( blob , node , " reg " ) ;
if ( uart - > base_addr = = FDT_ADDR_T_NONE )
return - FDT_ERR_NOTFOUND ;
uart - > port_id = fdtdec_get_int ( blob , node , " id " , - 1 ) ;
uart - > enabled = fdtdec_get_is_enabled ( blob , node ) ;
return 0 ;
}
# endif
__weak struct serial_device * default_serial_console ( void )
{
# ifdef CONFIG_OF_CONTROL
int index = 0 ;
if ( ( ! config . base_addr ) & & ( fdtdec_decode_console ( & index , & config ) ) ) {
debug ( " Cannot decode default console node \n " ) ;
return NULL ;
}
switch ( config . port_id ) {
case 0 :
return & s5p_serial0_device ;
case 1 :
return & s5p_serial1_device ;
case 2 :
return & s5p_serial2_device ;
case 3 :
return & s5p_serial3_device ;
default :
debug ( " Unknown config.port_id: %d " , config . port_id ) ;
break ;
}
return NULL ;
# else
config . enabled = 1 ;
# if defined(CONFIG_SERIAL0)
return & s5p_serial0_device ;
# elif defined(CONFIG_SERIAL1)
@ -225,6 +302,7 @@ __weak struct serial_device *default_serial_console(void)
# else
# error "CONFIG_SERIAL? missing."
# endif
# endif
}
void s5p_serial_initialize ( void )