@ -8,6 +8,7 @@
*/
# include <common.h>
# include <dm.h>
# include <serial.h>
DECLARE_GLOBAL_DATA_PTR ;
@ -23,21 +24,23 @@ struct arc_serial_regs {
unsigned int baudh ;
} ;
struct arc_serial_platdata {
struct arc_serial_regs * reg ;
unsigned int uartclk ;
} ;
/* Bit definitions of STATUS register */
# define UART_RXEMPTY (1 << 5)
# define UART_OVERFLOW_ERR (1 << 1)
# define UART_TXEMPTY (1 << 7)
struct arc_serial_regs * regs = ( struct arc_serial_regs * ) CONFIG_ARC_UART_BASE ;
static void arc_serial_setbrg ( void )
static int arc_serial_setbrg ( struct udevice * dev , int baudrate )
{
int arc_console_baud ;
struct arc_serial_platdata * plat = dev - > platdata ;
struct arc_serial_regs * const regs = plat - > reg ;
int arc_console_baud = gd - > cpu_clk / ( baudrate * 4 ) - 1 ;
if ( ! gd - > baudrate )
gd - > baudrate = CONFIG_BAUDRATE ;
arc_console_baud = gd - > cpu_clk / ( gd - > baudrate * 4 ) - 1 ;
writeb ( arc_console_baud & 0xff , & regs - > baudl ) ;
# ifdef CONFIG_ARC
@ -56,33 +59,49 @@ static void arc_serial_setbrg(void)
# else
writeb ( ( arc_console_baud & 0xff00 ) > > 8 , & regs - > baudh ) ;
# endif
}
static int arc_serial_init ( void )
{
serial_setbrg ( ) ;
return 0 ;
}
static void arc_serial_putc ( const char c )
static int arc_serial_putc ( struct udevice * dev , const char c )
{
struct arc_serial_platdata * plat = dev - > platdata ;
struct arc_serial_regs * const regs = plat - > reg ;
if ( c = = ' \n ' )
arc_serial_putc ( ' \r ' ) ;
arc_serial_putc ( dev , ' \r ' ) ;
while ( ! ( readb ( & regs - > status ) & UART_TXEMPTY ) )
;
writeb ( c , & regs - > data ) ;
return 0 ;
}
static int arc_serial_tstc ( void )
static int arc_serial_tstc ( struct arc_serial_regs * const regs )
{
return ! ( readb ( & regs - > status ) & UART_RXEMPTY ) ;
}
static int arc_serial_getc ( void )
static int arc_serial_pending ( struct udevice * dev , bool input )
{
struct arc_serial_platdata * plat = dev - > platdata ;
struct arc_serial_regs * const regs = plat - > reg ;
uint32_t status = readb ( & regs - > status ) ;
if ( input )
return status & UART_RXEMPTY ? 0 : 1 ;
else
return status & UART_TXEMPTY ? 0 : 1 ;
}
static int arc_serial_getc ( struct udevice * dev )
{
while ( ! arc_serial_tstc ( ) )
struct arc_serial_platdata * plat = dev - > platdata ;
struct arc_serial_regs * const regs = plat - > reg ;
while ( ! arc_serial_tstc ( regs ) )
;
/* Check for overflow errors */
@ -92,23 +111,42 @@ static int arc_serial_getc(void)
return readb ( & regs - > data ) & 0xFF ;
}
static struct serial_device arc_serial_drv = {
. name = " arc_serial " ,
. start = arc_serial_init ,
. stop = NULL ,
. setbrg = arc_serial_setbrg ,
. putc = arc_serial_putc ,
. puts = default_serial_puts ,
. getc = arc_serial_getc ,
. tstc = arc_serial_tstc ,
} ;
void arc_serial_initialize ( void )
static int arc_serial_probe ( struct udevice * dev )
{
serial_register ( & arc_serial_drv ) ;
return 0 ;
}
__weak struct serial_device * default_serial_console ( void )
static const struct dm_serial_ops arc_serial_ops = {
. putc = arc_serial_putc ,
. pending = arc_serial_pending ,
. getc = arc_serial_getc ,
. setbrg = arc_serial_setbrg ,
} ;
static const struct udevice_id arc_serial_ids [ ] = {
{ . compatible = " snps,arc-uart " } ,
{ }
} ;
static int arc_serial_ofdata_to_platdata ( struct udevice * dev )
{
return & arc_serial_drv ;
struct arc_serial_platdata * plat = dev_get_platdata ( dev ) ;
DECLARE_GLOBAL_DATA_PTR ;
plat - > reg = ( struct arc_serial_regs * ) fdtdec_get_addr ( gd - > fdt_blob ,
dev - > of_offset , " reg " ) ;
plat - > uartclk = fdtdec_get_int ( gd - > fdt_blob , dev - > of_offset ,
" clock-frequency " , 0 ) ;
return 0 ;
}
U_BOOT_DRIVER ( serial_arc ) = {
. name = " serial_arc " ,
. id = UCLASS_SERIAL ,
. of_match = arc_serial_ids ,
. ofdata_to_platdata = arc_serial_ofdata_to_platdata ,
. probe = arc_serial_probe ,
. ops = & arc_serial_ops ,
. flags = DM_FLAG_PRE_RELOC ,
} ;