@ -6,6 +6,7 @@
# include <common.h>
# include <dm.h>
# include <fsl_lpuart.h>
# include <watchdog.h>
# include <asm/io.h>
# include <serial.h>
@ -48,14 +49,56 @@
DECLARE_GLOBAL_DATA_PTR ;
# define LPUART_FLAG_REGMAP_32BIT_REG BIT(0)
# define LPUART_FLAG_REGMAP_ENDIAN_BIG BIT(1)
struct lpuart_serial_platdata {
struct lpuart_fsl * reg ;
void * reg ;
ulong flags ;
} ;
# ifndef CONFIG_LPUART_32B_REG
static void _lpuart_serial_setbrg ( struct lpuart_fsl * base , int baudrate )
static void lpuart_read32 ( u32 flags , u32 * addr , u32 * val )
{
if ( flags & LPUART_FLAG_REGMAP_32BIT_REG ) {
if ( flags & LPUART_FLAG_REGMAP_ENDIAN_BIG )
* ( u32 * ) val = in_be32 ( addr ) ;
else
* ( u32 * ) val = in_le32 ( addr ) ;
}
}
static void lpuart_write32 ( u32 flags , u32 * addr , u32 val )
{
if ( flags & LPUART_FLAG_REGMAP_32BIT_REG ) {
if ( flags & LPUART_FLAG_REGMAP_ENDIAN_BIG )
out_be32 ( addr , val ) ;
else
out_le32 ( addr , val ) ;
}
}
# ifndef CONFIG_SYS_CLK_FREQ
# define CONFIG_SYS_CLK_FREQ 0
# endif
u32 __weak get_lpuart_clk ( void )
{
u32 clk = mxc_get_clock ( MXC_UART_CLK ) ;
return CONFIG_SYS_CLK_FREQ ;
}
static bool is_lpuart32 ( struct udevice * dev )
{
struct lpuart_serial_platdata * plat = dev - > platdata ;
return plat - > flags & LPUART_FLAG_REGMAP_32BIT_REG ;
}
static void _lpuart_serial_setbrg ( struct lpuart_serial_platdata * plat ,
int baudrate )
{
struct lpuart_fsl * base = plat - > reg ;
u32 clk = get_lpuart_clk ( ) ;
u16 sbr ;
sbr = ( u16 ) ( clk / ( 16 * baudrate ) ) ;
@ -65,8 +108,9 @@ static void _lpuart_serial_setbrg(struct lpuart_fsl *base, int baudrate)
__raw_writeb ( sbr & 0xff , & base - > ubdl ) ;
}
static int _lpuart_serial_getc ( struct lpuart_fsl * base )
static int _lpuart_serial_getc ( struct lpuart_serial_platdata * plat )
{
struct lpuart_fsl * base = plat - > reg ;
while ( ! ( __raw_readb ( & base - > us1 ) & ( US1_RDRF | US1_OR ) ) )
WATCHDOG_RESET ( ) ;
@ -75,8 +119,11 @@ static int _lpuart_serial_getc(struct lpuart_fsl *base)
return __raw_readb ( & base - > ud ) ;
}
static void _lpuart_serial_putc ( struct lpuart_fsl * base , const char c )
static void _lpuart_serial_putc ( struct lpuart_serial_platdata * plat ,
const char c )
{
struct lpuart_fsl * base = plat - > reg ;
while ( ! ( __raw_readb ( & base - > us1 ) & US1_TDRE ) )
WATCHDOG_RESET ( ) ;
@ -84,8 +131,10 @@ static void _lpuart_serial_putc(struct lpuart_fsl *base, const char c)
}
/* Test whether a character is in the RX buffer */
static int _lpuart_serial_tstc ( struct lpuart_fsl * base )
static int _lpuart_serial_tstc ( struct lpuart_serial_platdata * plat )
{
struct lpuart_fsl * base = plat - > reg ;
if ( __raw_readb ( & base - > urcfifo ) = = 0 )
return 0 ;
@ -96,8 +145,9 @@ static int _lpuart_serial_tstc(struct lpuart_fsl *base)
* Initialise the serial port with the given baudrate . The settings
* are always 8 data bits , no parity , 1 stop bit , no start bits .
*/
static int _lpuart_serial_init ( struct lpuart_fsl * base )
static int _lpuart_serial_init ( struct lpuart_serial_platdata * plat )
{
struct lpuart_fsl * base = ( struct lpuart_fsl * ) plat - > reg ;
u8 ctrl ;
ctrl = __raw_readb ( & base - > uc2 ) ;
@ -115,101 +165,71 @@ static int _lpuart_serial_init(struct lpuart_fsl *base)
__raw_writeb ( CFIFO_TXFLUSH | CFIFO_RXFLUSH , & base - > ucfifo ) ;
/* provide data bits, parity, stop bit, etc */
_lpuart_serial_setbrg ( base , gd - > baudrate ) ;
_lpuart_serial_setbrg ( plat , gd - > baudrate ) ;
__raw_writeb ( UC2_RE | UC2_TE , & base - > uc2 ) ;
return 0 ;
}
static int lpuart_serial_setbrg ( struct udevice * dev , int baudrate )
{
struct lpuart_serial_platdata * plat = dev - > platdata ;
struct lpuart_fsl * reg = plat - > reg ;
_lpuart_serial_setbrg ( reg , baudrate ) ;
return 0 ;
}
static int lpuart_serial_getc ( struct udevice * dev )
{
struct lpuart_serial_platdata * plat = dev - > platdata ;
struct lpuart_fsl * reg = plat - > reg ;
return _lpuart_serial_getc ( reg ) ;
}
static int lpuart_serial_putc ( struct udevice * dev , const char c )
{
struct lpuart_serial_platdata * plat = dev - > platdata ;
struct lpuart_fsl * reg = plat - > reg ;
_lpuart_serial_putc ( reg , c ) ;
return 0 ;
}
static int lpuart_serial_pending ( struct udevice * dev , bool input )
{
struct lpuart_serial_platdata * plat = dev - > platdata ;
struct lpuart_fsl * reg = plat - > reg ;
if ( input )
return _lpuart_serial_tstc ( reg ) ;
else
return __raw_readb ( & reg - > us1 ) & US1_TDRE ? 0 : 1 ;
}
static int lpuart_serial_probe ( struct udevice * dev )
{
struct lpuart_serial_platdata * plat = dev - > platdata ;
struct lpuart_fsl * reg = plat - > reg ;
return _lpuart_serial_init ( reg ) ;
}
# else
u32 __weak get_lpuart_clk ( void )
{
return CONFIG_SYS_CLK_FREQ ;
}
static void _lpuart32_serial_setbrg ( struct lpuart_fsl * base , int baudrate )
static void _lpuart32_serial_setbrg ( struct lpuart_serial_platdata * plat ,
int baudrate )
{
struct lpuart_fsl_reg32 * base = plat - > reg ;
u32 clk = get_lpuart_clk ( ) ;
u32 sbr ;
sbr = ( clk / ( 16 * baudrate ) ) ;
/* place adjustment later - n/32 BRFA */
out_be32 ( & base - > baud , sbr ) ;
lpuart_write32 ( plat - > flags , & base - > baud , sbr ) ;
}
static int _lpuart32_serial_getc ( struct lpuart_fsl * base )
static int _lpuart32_serial_getc ( struct lpuart_serial_platdata * plat )
{
struct lpuart_fsl_reg32 * base = plat - > reg ;
u32 stat ;
while ( ( ( stat = in_be32 ( & base - > stat ) ) & STAT_RDRF ) = = 0 ) {
out_be32 ( & base - > stat , STAT_FLAGS ) ;
lpuart_read32 ( plat - > flags , & base - > stat , & stat ) ;
while ( ( stat & STAT_RDRF ) = = 0 ) {
lpuart_write32 ( plat - > flags , & base - > stat , STAT_FLAGS ) ;
WATCHDOG_RESET ( ) ;
lpuart_read32 ( plat - > flags , & base - > stat , & stat ) ;
}
return in_be32 ( & base - > data ) & 0x3ff ;
/* Reuse stat */
lpuart_read32 ( plat - > flags , & base - > data , & stat ) ;
return stat & 0x3ff ;
}
static void _lpuart32_serial_putc ( struct lpuart_fsl * base , const char c )
static void _lpuart32_serial_putc ( struct lpuart_serial_platdata * plat ,
const char c )
{
while ( ! ( in_be32 ( & base - > stat ) & STAT_TDRE ) )
struct lpuart_fsl_reg32 * base = plat - > reg ;
u32 stat ;
while ( true ) {
lpuart_read32 ( plat - > flags , & base - > stat , & stat ) ;
if ( ( stat & STAT_TDRE ) )
break ;
WATCHDOG_RESET ( ) ;
}
out_be32 ( & base - > data , c ) ;
lpuart_write32 ( plat - > flags , & base - > data , c ) ;
}
/* Test whether a character is in the RX buffer */
static int _lpuart32_serial_tstc ( struct lpuart_fsl * base )
static int _lpuart32_serial_tstc ( struct lpuart_serial_platdata * plat )
{
if ( ( in_be32 ( & base - > water ) > > 24 ) = = 0 )
struct lpuart_fsl_reg32 * base = plat - > reg ;
u32 water ;
lpuart_read32 ( plat - > flags , & base - > water , & water ) ;
if ( ( water > > 24 ) = = 0 )
return 0 ;
return 1 ;
@ -219,75 +239,94 @@ static int _lpuart32_serial_tstc(struct lpuart_fsl *base)
* Initialise the serial port with the given baudrate . The settings
* are always 8 data bits , no parity , 1 stop bit , no start bits .
*/
static int _lpuart32_serial_init ( struct lpuart_fsl * base )
static int _lpuart32_serial_init ( struct lpuart_serial_platdata * plat )
{
u8 ctrl ;
struct lpuart_fsl_reg32 * base = ( struct lpuart_fsl_reg32 * ) plat - > reg ;
u32 ctrl ;
ctrl = in_be32 ( & base - > ctrl ) ;
lpuart_read32 ( plat - > flags , & base - > ctrl , & ctrl ) ;
ctrl & = ~ CTRL_RE ;
ctrl & = ~ CTRL_TE ;
out_be32 ( & base - > ctrl , ctrl ) ;
lpuart_write32 ( plat - > flags , & base - > ctrl , ctrl ) ;
out_be32 ( & base - > modir , 0 ) ;
out_be32 ( & base - > fifo , ~ ( FIFO_TXFE | FIFO_RXFE ) ) ;
lpuart_write32 ( plat - > flags , & base - > modir , 0 ) ;
lpuart_write32 ( plat - > flags , & base - > fifo , ~ ( FIFO_TXFE | FIFO_RXFE ) ) ;
out_be32 ( & base - > match , 0 ) ;
lpuart_write32 ( plat - > flags , & base - > match , 0 ) ;
/* provide data bits, parity, stop bit, etc */
_lpuart32_serial_setbrg ( base , gd - > baudrate ) ;
_lpuart32_serial_setbrg ( plat , gd - > baudrate ) ;
out_be32 ( & base - > ctrl , CTRL_RE | CTRL_TE ) ;
lpuart_write32 ( plat - > flags , & base - > ctrl , CTRL_RE | CTRL_TE ) ;
return 0 ;
}
static int lpuart32 _serial_setbrg ( struct udevice * dev , int baudrate )
static int lpuart_serial_setbrg ( struct udevice * dev , int baudrate )
{
struct lpuart_serial_platdata * plat = dev - > platdata ;
struct lpuart_fsl * reg = plat - > reg ;
_lpuart32_serial_setbrg ( reg , baudrate ) ;
if ( is_lpuart32 ( dev ) )
_lpuart32_serial_setbrg ( plat , baudrate ) ;
else
_lpuart_serial_setbrg ( plat , baudrate ) ;
return 0 ;
}
static int lpuart32 _serial_getc ( struct udevice * dev )
static int lpuart_serial_getc ( struct udevice * dev )
{
struct lpuart_serial_platdata * plat = dev - > platdata ;
struct lpuart_fsl * reg = plat - > reg ;
return _lpuart32_serial_getc ( reg ) ;
if ( is_lpuart32 ( dev ) )
return _lpuart32_serial_getc ( plat ) ;
return _lpuart_serial_getc ( plat ) ;
}
static int lpuart32_serial_putc ( struct udevice * dev , const char c )
static int lpuart_serial_putc ( struct udevice * dev , const char c )
{
struct lpuart_serial_platdata * plat = dev - > platdata ;
struct lpuart_fsl * reg = plat - > reg ;
_lpuart32_serial_putc ( reg , c ) ;
if ( is_lpuart32 ( dev ) )
_lpuart32_serial_putc ( plat , c ) ;
else
_lpuart_serial_putc ( plat , c ) ;
return 0 ;
}
static int lpuart32 _serial_pending ( struct udevice * dev , bool input )
static int lpuart_serial_pending ( struct udevice * dev , bool input )
{
struct lpuart_serial_platdata * plat = dev - > platdata ;
struct lpuart_fsl * reg = plat - > reg ;
struct lpuart_fsl_reg32 * reg32 = plat - > reg ;
u32 stat ;
if ( is_lpuart32 ( dev ) ) {
if ( input ) {
return _lpuart32_serial_tstc ( plat ) ;
} else {
lpuart_read32 ( plat - > flags , & reg32 - > stat , & stat ) ;
return stat & STAT_TDRE ? 0 : 1 ;
}
}
if ( input )
return _lpuart32_serial_tstc ( reg ) ;
return _lpuart_serial_tstc ( plat ) ;
else
return in_be32 ( & reg - > stat ) & STAT_TDRE ? 0 : 1 ;
return __raw_readb ( & reg - > us1 ) & US1 _TDRE ? 0 : 1 ;
}
static int lpuart32_serial_probe ( struct udevice * dev )
static int lpuart_serial_probe ( struct udevice * dev )
{
struct lpuart_serial_platdata * plat = dev - > platdata ;
struct lpuart_fsl * reg = plat - > reg ;
return _lpuart32_serial_init ( reg ) ;
if ( is_lpuart32 ( dev ) )
return _lpuart32_serial_init ( plat ) ;
else
return _lpuart_serial_init ( plat ) ;
}
# endif /* CONFIG_LPUART_32B_REG */
static int lpuart_serial_ofdata_to_platdata ( struct udevice * dev )
{
@ -298,12 +337,12 @@ static int lpuart_serial_ofdata_to_platdata(struct udevice *dev)
if ( addr = = FDT_ADDR_T_NONE )
return - EINVAL ;
plat - > reg = ( struct lpuart_fsl * ) addr ;
plat - > reg = ( void * ) addr ;
plat - > flags = dev_get_driver_data ( dev ) ;
return 0 ;
}
# ifndef CONFIG_LPUART_32B_REG
static const struct dm_serial_ops lpuart_serial_ops = {
. putc = lpuart_serial_putc ,
. pending = lpuart_serial_pending ,
@ -312,7 +351,9 @@ static const struct dm_serial_ops lpuart_serial_ops = {
} ;
static const struct udevice_id lpuart_serial_ids [ ] = {
{ . compatible = " fsl,vf610-lpuart " } ,
{ . compatible = " fsl,ls1021a-lpuart " , . data =
LPUART_FLAG_REGMAP_32BIT_REG | LPUART_FLAG_REGMAP_ENDIAN_BIG } ,
{ . compatible = " fsl,vf610-lpuart " } ,
{ }
} ;
@ -326,27 +367,3 @@ U_BOOT_DRIVER(serial_lpuart) = {
. ops = & lpuart_serial_ops ,
. flags = DM_FLAG_PRE_RELOC ,
} ;
# else /* CONFIG_LPUART_32B_REG */
static const struct dm_serial_ops lpuart32_serial_ops = {
. putc = lpuart32_serial_putc ,
. pending = lpuart32_serial_pending ,
. getc = lpuart32_serial_getc ,
. setbrg = lpuart32_serial_setbrg ,
} ;
static const struct udevice_id lpuart32_serial_ids [ ] = {
{ . compatible = " fsl,ls1021a-lpuart " } ,
{ }
} ;
U_BOOT_DRIVER ( serial_lpuart32 ) = {
. name = " serial_lpuart32 " ,
. id = UCLASS_SERIAL ,
. of_match = lpuart32_serial_ids ,
. ofdata_to_platdata = lpuart_serial_ofdata_to_platdata ,
. platdata_auto_alloc_size = sizeof ( struct lpuart_serial_platdata ) ,
. probe = lpuart32_serial_probe ,
. ops = & lpuart32_serial_ops ,
. flags = DM_FLAG_PRE_RELOC ,
} ;
# endif /* CONFIG_LPUART_32B_REG */