@ -31,45 +31,7 @@
# include "hw/irq.h"
# include "hw/qdev-properties.h"
# undef DEBUG_UART
# undef DEBUG_UART_EXTEND
# undef DEBUG_IRQ
# undef DEBUG_Rx_DATA
# undef DEBUG_Tx_DATA
# define DEBUG_UART 0
# define DEBUG_UART_EXTEND 0
# define DEBUG_IRQ 0
# define DEBUG_Rx_DATA 0
# define DEBUG_Tx_DATA 0
# if DEBUG_UART
# define PRINT_DEBUG(fmt, args...) \
do { \
fprintf ( stderr , " [%s:%d] " fmt , __func__ , __LINE__ , # # args ) ; \
} while ( 0 )
# if DEBUG_UART_EXTEND
# define PRINT_DEBUG_EXTEND(fmt, args...) \
do { \
fprintf ( stderr , " [%s:%d] " fmt , __func__ , __LINE__ , # # args ) ; \
} while ( 0 )
# else
# define PRINT_DEBUG_EXTEND(fmt, args...) \
do { } while ( 0 )
# endif /* EXTEND */
# else
# define PRINT_DEBUG(fmt, args...) \
do { } while ( 0 )
# define PRINT_DEBUG_EXTEND(fmt, args...) \
do { } while ( 0 )
# endif
# define PRINT_ERROR(fmt, args...) \
do { \
fprintf ( stderr , " [%s:%d] " fmt , __func__ , __LINE__ , # # args ) ; \
} while ( 0 )
# include "trace.h"
/*
* Offsets for UART registers relative to SFR base address
@ -193,8 +155,7 @@ typedef struct Exynos4210UartState {
} Exynos4210UartState ;
# if DEBUG_UART
/* Used only for debugging inside PRINT_DEBUG_... macros */
/* Used only for tracing */
static const char * exynos4210_uart_regname ( hwaddr offset )
{
@ -208,7 +169,6 @@ static const char *exynos4210_uart_regname(hwaddr offset)
return NULL ;
}
# endif
static void fifo_store ( Exynos4210UartFIFO * q , uint8_t ch )
@ -271,7 +231,7 @@ static uint32_t exynos4210_uart_Tx_FIFO_trigger_level(const Exynos4210UartState
break ;
default :
level = 0 ;
PRINT_ERROR ( " Wrong UART channel number: %d \n " , s - > channel ) ;
trace_exynos_uart_channel_error ( s - > channel ) ;
}
return level ;
@ -297,14 +257,10 @@ static void exynos4210_uart_update_irq(Exynos4210UartState *s)
if ( s - > reg [ I_ ( UINTP ) ] ) {
qemu_irq_raise ( s - > irq ) ;
# if DEBUG_IRQ
fprintf ( stderr , " UART%d: IRQ has been raised: %08x \n " ,
s - > channel , s - > reg [ I_ ( UINTP ) ] ) ;
# endif
trace_exynos_uart_irq_raised ( s - > channel , s - > reg [ I_ ( UINTP ) ] ) ;
} else {
qemu_irq_lower ( s - > irq ) ;
trace_exynos_uart_irq_lowered ( s - > channel ) ;
}
}
@ -348,7 +304,7 @@ static void exynos4210_uart_update_parameters(Exynos4210UartState *s)
qemu_chr_fe_ioctl ( & s - > chr , CHR_IOCTL_SERIAL_SET_PARAMS , & ssp ) ;
PRINT_DEBUG ( " UART%d: speed: %d, parity: %c, data: %d, stop: %d \n " ,
trace_exynos_uart_update_params (
s - > channel , speed , parity , data_bits , stop_bits ) ;
}
@ -358,8 +314,8 @@ static void exynos4210_uart_write(void *opaque, hwaddr offset,
Exynos4210UartState * s = ( Exynos4210UartState * ) opaque ;
uint8_t ch ;
PRINT_DEBUG_EXTEND ( " UART%d: <0x%04x> %s <- 0x%08llx \n " , s - > channel ,
offset , exynos4210_uart_regname ( offset ) , ( long long unsigned int ) val ) ;
trace_exynos_uart_write ( s - > channel , offset ,
exynos4210_uart_regname ( offset ) , val ) ;
switch ( offset ) {
case ULCON :
@ -373,12 +329,12 @@ static void exynos4210_uart_write(void *opaque, hwaddr offset,
if ( val & UFCON_Rx_FIFO_RESET ) {
fifo_reset ( & s - > rx ) ;
s - > reg [ I_ ( UFCON ) ] & = ~ UFCON_Rx_FIFO_RESET ;
PRINT_DEBUG ( " UART%d: Rx FIFO Reset \n " , s - > channel ) ;
trace_exynos_uart_rx_fifo_reset ( s - > channel ) ;
}
if ( val & UFCON_Tx_FIFO_RESET ) {
fifo_reset ( & s - > tx ) ;
s - > reg [ I_ ( UFCON ) ] & = ~ UFCON_Tx_FIFO_RESET ;
PRINT_DEBUG ( " UART%d: Tx FIFO Reset \n " , s - > channel ) ;
trace_exynos_uart_tx_fifo_reset ( s - > channel ) ;
}
break ;
@ -390,9 +346,7 @@ static void exynos4210_uart_write(void *opaque, hwaddr offset,
/* XXX this blocks entire thread. Rewrite to use
* qemu_chr_fe_write and background I / O callbacks */
qemu_chr_fe_write_all ( & s - > chr , & ch , 1 ) ;
# if DEBUG_Tx_DATA
fprintf ( stderr , " %c " , ch ) ;
# endif
trace_exynos_uart_tx ( s - > channel , ch ) ;
s - > reg [ I_ ( UTRSTAT ) ] | = UTRSTAT_TRANSMITTER_EMPTY |
UTRSTAT_Tx_BUFFER_EMPTY ;
s - > reg [ I_ ( UINTSP ) ] | = UINTSP_TXD ;
@ -403,8 +357,7 @@ static void exynos4210_uart_write(void *opaque, hwaddr offset,
case UINTP :
s - > reg [ I_ ( UINTP ) ] & = ~ val ;
s - > reg [ I_ ( UINTSP ) ] & = ~ val ;
PRINT_DEBUG ( " UART%d: UINTP [%04x] have been cleared: %08x \n " ,
s - > channel , offset , s - > reg [ I_ ( UINTP ) ] ) ;
trace_exynos_uart_intclr ( s - > channel , s - > reg [ I_ ( UINTP ) ] ) ;
exynos4210_uart_update_irq ( s ) ;
break ;
case UTRSTAT :
@ -412,7 +365,7 @@ static void exynos4210_uart_write(void *opaque, hwaddr offset,
case UFSTAT :
case UMSTAT :
case URXH :
PRINT_DEBUG ( " UART%d: Trying to write into RO register: %s [%04x] \n " ,
trace_exynos_uart_ro_write (
s - > channel , exynos4210_uart_regname ( offset ) , offset ) ;
break ;
case UINTSP :
@ -439,6 +392,8 @@ static uint64_t exynos4210_uart_read(void *opaque, hwaddr offset,
case UERSTAT : /* Read Only */
res = s - > reg [ I_ ( UERSTAT ) ] ;
s - > reg [ I_ ( UERSTAT ) ] = 0 ;
trace_exynos_uart_read ( s - > channel , offset ,
exynos4210_uart_regname ( offset ) , res ) ;
return res ;
case UFSTAT : /* Read Only */
s - > reg [ I_ ( UFSTAT ) ] = fifo_elements_number ( & s - > rx ) & 0xff ;
@ -446,20 +401,22 @@ static uint64_t exynos4210_uart_read(void *opaque, hwaddr offset,
s - > reg [ I_ ( UFSTAT ) ] | = UFSTAT_Rx_FIFO_FULL ;
s - > reg [ I_ ( UFSTAT ) ] & = ~ 0xff ;
}
trace_exynos_uart_read ( s - > channel , offset ,
exynos4210_uart_regname ( offset ) ,
s - > reg [ I_ ( UFSTAT ) ] ) ;
return s - > reg [ I_ ( UFSTAT ) ] ;
case URXH :
if ( s - > reg [ I_ ( UFCON ) ] & UFCON_FIFO_ENABLE ) {
if ( fifo_elements_number ( & s - > rx ) ) {
res = fifo_retrieve ( & s - > rx ) ;
# if DEBUG_Rx_DATA
fprintf ( stderr , " %c " , res ) ;
# endif
trace_exynos_uart_rx ( s - > channel , res ) ;
if ( ! fifo_elements_number ( & s - > rx ) ) {
s - > reg [ I_ ( UTRSTAT ) ] & = ~ UTRSTAT_Rx_BUFFER_DATA_READY ;
} else {
s - > reg [ I_ ( UTRSTAT ) ] | = UTRSTAT_Rx_BUFFER_DATA_READY ;
}
} else {
trace_exynos_uart_rx_error ( s - > channel ) ;
s - > reg [ I_ ( UINTSP ) ] | = UINTSP_ERROR ;
exynos4210_uart_update_irq ( s ) ;
res = 0 ;
@ -468,15 +425,22 @@ static uint64_t exynos4210_uart_read(void *opaque, hwaddr offset,
s - > reg [ I_ ( UTRSTAT ) ] & = ~ UTRSTAT_Rx_BUFFER_DATA_READY ;
res = s - > reg [ I_ ( URXH ) ] ;
}
trace_exynos_uart_read ( s - > channel , offset ,
exynos4210_uart_regname ( offset ) , res ) ;
return res ;
case UTXH :
PRINT_DEBUG ( " UART%d: Trying to read from WO register: %s [%04x] \n " ,
s - > channel , exynos4210_uart_regname ( offset ) , offset ) ;
trace_exynos_uart_wo_read ( s - > channel , exynos4210_uart_regname ( offset ) ,
offset ) ;
break ;
default :
trace_exynos_uart_read ( s - > channel , offset ,
exynos4210_uart_regname ( offset ) ,
s - > reg [ I_ ( offset ) ] ) ;
return s - > reg [ I_ ( offset ) ] ;
}
trace_exynos_uart_read ( s - > channel , offset , exynos4210_uart_regname ( offset ) ,
0 ) ;
return 0 ;
}
@ -555,7 +519,7 @@ static void exynos4210_uart_reset(DeviceState *dev)
fifo_reset ( & s - > rx ) ;
fifo_reset ( & s - > tx ) ;
PRINT_DEBUG ( " UART%d: Rx FIFO size: %d \n " , s - > channel , s - > rx . size ) ;
trace_exynos_uart_rxsize ( s - > channel , s - > rx . size ) ;
}
static const VMStateDescription vmstate_exynos4210_uart_fifo = {