@ -1,72 +1,78 @@
/* GRLIB APBUART Serial controller driver
*
* ( C ) Copyright 2008
* Daniel Hellstrom , Gaisler Research , daniel @ gaisler . com .
* ( C ) Copyright 2008 , 2015
* Daniel Hellstrom , Cobham Gaisler , daniel @ gaisler . com .
*
* SPDX - License - Identifier : GPL - 2.0 +
*/
# include <common.h>
# include <asm/processor.h>
# include <asm/leon.h>
# include <asm/io.h>
# include <serial.h>
# include <linux/compiler .h>
# include <watchdog .h>
DECLARE_GLOBAL_DATA_PTR ;
static unsigned leon2_serial_calc_scaler ( unsigned freq , unsigned baud )
{
return ( ( ( freq * 10 ) / ( baud * 8 ) ) - 5 ) / 10 ;
}
static int leon2_serial_init ( void )
{
LEON2_regs * leon2 = ( LEON2_regs * ) LEON2_PREGS ;
LEON2_regs * leon2 = ( LEON2_regs * ) LEON2_PREGS ;
LEON2_Uart_regs * regs ;
unsigned int tmp ;
/* Init LEON2 UART
*
* Set scaler / baud rate
*
* Receiver & transmitter enable
*/
# if LEON2_CONSOLE_SELECT == LEON_CONSOLE_UART1
regs = ( LEON2_Uart_regs * ) & leon2 - > UART_Channel_1 ;
regs = ( LEON2_Uart_regs * ) & leon2 - > UART_Channel_1 ;
# else
regs = ( LEON2_Uart_regs * ) & leon2 - > UART_Channel_2 ;
regs = ( LEON2_Uart_regs * ) & leon2 - > UART_Channel_2 ;
# endif
regs - > UART_Scaler = CONFIG_SYS_LEON2_UART1_SCALER ;
/* Set scaler / baud rate */
tmp = leon2_serial_calc_scaler ( CONFIG_SYS_CLK_FREQ , CONFIG_BAUDRATE ) ;
writel ( tmp , & regs - > UART_Scaler ) ;
/* Let bit 11 be unchanged (debug bit for GRMON) */
tmp = READ_WORD ( regs - > UART_Control ) ;
tmp = readl ( & regs - > UART_Control ) & LEON2_UART_CTRL_DBG ;
tmp | = ( LEON2_UART1_LOOPBACK_ENABLE < < 7 ) ;
tmp | = ( LEON2_UART1_FLOWCTRL_ENABLE < < 6 ) ;
tmp | = ( LEON2_UART1_PARITY_ENABLE < < 5 ) ;
tmp | = ( LEON2_UART1_ODDPAR_ENABLE < < 4 ) ;
/* Receiver & transmitter enable */
tmp | = ( LEON2_UART_CTRL_RE | LEON2_UART_CTRL_TE ) ;
writel ( tmp , & regs - > UART_Control ) ;
gd - > arch . uart = regs ;
return 0 ;
}
regs - > UART_Control = ( ( tmp & LEON2_UART_CTRL_DBG ) |
( LEON2_UART1_LOOPBACK_ENABLE < < 7 ) |
( LEON2_UART1_FLOWCTRL_ENABLE < < 6 ) |
( LEON2_UART1_PARITY_ENABLE < < 5 ) |
( LEON2_UART1_ODDPAR_ENABLE < < 4 ) |
LEON2_UART_CTRL_RE | LEON2_UART_CTRL_TE ) ;
static inline LEON2_Uart_regs * leon2_get_uart_regs ( void )
{
LEON2_Uart_regs * uart = gd - > arch . uart ;
return 0 ;
return uart ;
}
static void leon2_serial_putc_raw ( const char c )
{
LEON2_regs * leon2 = ( LEON2_regs * ) LEON2_PREGS ;
LEON2_Uart_regs * regs ;
LEON2_Uart_regs * uart = leon2_get_uart_regs ( ) ;
# if LEON2_CONSOLE_SELECT == LEON_CONSOLE_UART1
regs = ( LEON2_Uart_regs * ) & leon2 - > UART_Channel_1 ;
# else
regs = ( LEON2_Uart_regs * ) & leon2 - > UART_Channel_2 ;
# endif
if ( ! uart )
return ;
/* Wait for last character to go. */
while ( ! ( READ_WORD ( regs - > UART_Status ) & LEON2_UART_STAT_THE ) ) ;
while ( ! ( readl ( & uart - > UART_Status ) & LEON2_UART_STAT_THE ) )
WATCHDOG_RESET ( ) ;
/* Send data */
regs - > UART_Channel = c ;
writel ( c , & uart - > UART_Channel ) ;
# ifdef LEON_DEBUG
/* Wait for data to be sent */
while ( ! ( READ_WORD ( regs - > UART_Status ) & LEON2_UART_STAT_TSE ) ) ;
while ( ! ( readl ( & uart - > UART_Status ) & LEON2_UART_STAT_TSE ) )
WATCHDOG_RESET ( ) ;
# endif
}
@ -80,56 +86,43 @@ static void leon2_serial_putc(const char c)
static int leon2_serial_getc ( void )
{
LEON2_regs * leon2 = ( LEON2_regs * ) LEON2_PREGS ;
LEON2_Uart_regs * regs ;
LEON2_Uart_regs * uart = leon2_get_uart_regs ( ) ;
# if LEON2_CONSOLE_SELECT == LEON_CONSOLE_UART1
regs = ( LEON2_Uart_regs * ) & leon2 - > UART_Channel_1 ;
# else
regs = ( LEON2_Uart_regs * ) & leon2 - > UART_Channel_2 ;
# endif
if ( ! uart )
return 0 ;
/* Wait for a character to arrive. */
while ( ! ( READ_WORD ( regs - > UART_Status ) & LEON2_UART_STAT_DR ) ) ;
while ( ! ( readl ( & uart - > UART_Status ) & LEON2_UART_STAT_DR ) )
WATCHDOG_RESET ( ) ;
/* read data */
return READ_WORD ( regs - > UART_Channel ) ;
/* Read character data */
return readl ( & uart - > UART_Channel ) ;
}
static int leon2_serial_tstc ( void )
{
LEON2_regs * leon2 = ( LEON2_regs * ) LEON2_PREGS ;
LEON2_Uart_regs * regs ;
LEON2_Uart_regs * uart = leon2_get_uart_regs ( ) ;
# if LEON2_CONSOLE_SELECT == LEON_CONSOLE_UART1
regs = ( LEON2_Uart_regs * ) & leon2 - > UART_Channel_1 ;
# else
regs = ( LEON2_Uart_regs * ) & leon2 - > UART_Channel_2 ;
# endif
if ( ! uart )
return 0 ;
return ( READ_WORD ( regs - > UART_Status ) & LEON2_UART_STAT_DR ) ;
return readl ( & uart - > UART_Status ) & LEON2_UART_STAT_DR ;
}
/* set baud rate for uart */
static void leon2_serial_setbrg ( void )
{
/* update baud rate settings, read it from gd->baudrate */
LEON2_Uart_regs * uart = leon2_get_uart_regs ( ) ;
unsigned int scaler ;
LEON2_regs * leon2 = ( LEON2_regs * ) LEON2_PREGS ;
LEON2_Uart_regs * regs ;
# if LEON2_CONSOLE_SELECT == LEON_CONSOLE_UART1
regs = ( LEON2_Uart_regs * ) & leon2 - > UART_Channel_1 ;
# else
regs = ( LEON2_Uart_regs * ) & leon2 - > UART_Channel_2 ;
# endif
if ( ! uart )
return ;
if ( ! gd - > baudrate )
gd - > baudrate = CONFIG_BAUDRATE ;
scaler = leon2_serial_calc_scaler ( CONFIG_SYS_CLK_FREQ , CONFIG_BAUDRATE ) ;
if ( gd - > baudrate > 0 ) {
scaler =
( ( ( CONFIG_SYS_CLK_FREQ * 10 ) / ( gd - > baudrate * 8 ) ) -
5 ) / 10 ;
regs - > UART_Scaler = scaler ;
}
writel ( scaler , & uart - > UART_Scaler ) ;
}
static struct serial_device leon2_serial_drv = {