sim: bfin: implement loop back support in the UARTs
The UART has a LOOP_ENA bit in its MCR register where writes to the THR go to the RBR. Implement support for this mode. Signed-off-by: Mike Frysinger <vapier@gentoo.org>
This commit is contained in:
parent
ba4a8bdd81
commit
28fe96b798
@ -1,3 +1,18 @@
|
||||
2011-05-14 Mike Frysinger <vapier@gentoo.org>
|
||||
|
||||
* dv-bfin_uart.c (bfin_uart_write_byte): Add a mcr arg. Declare a
|
||||
local uart. When LOOP_ENA is set in mcr, write to the saved byte
|
||||
and count fields of the uart.
|
||||
(bfin_uart_io_write_buffer): Pass uart->mcr to bfin_uart_write_byte
|
||||
and bfin_uart_get_next_byte.
|
||||
(bfin_uart_get_next_byte): Add a mcr arg. Move uart->saved_count
|
||||
check first, and skip the remaining code when LOOP_ENA is set in mcr.
|
||||
* dv-bfin_uart.h (bfin_uart_write_byte): Add an mcr argument.
|
||||
(bfin_uart_get_next_byte): Likewise.
|
||||
(XOFF, MRTS, RFIT, RFRT, LOOP_ENA, FCPOL, ARTS, ACTS): Define.
|
||||
* dv-bfin_uart2.c (bfin_uart_io_write_buffer): Padd uart->mcr when
|
||||
calling bfin_uart_write_byte and bfin_uart_get_next_byte.
|
||||
|
||||
2011-05-09 Mike Frysinger <vapier@gentoo.org>
|
||||
|
||||
* dv-bfin_uart2.c (bfin_uart_io_read_buffer): Clear DR/THRE/TEMT bits
|
||||
|
@ -117,10 +117,21 @@ bfin_uart_reschedule (struct hw *me)
|
||||
}
|
||||
|
||||
bu16
|
||||
bfin_uart_write_byte (struct hw *me, bu16 thr)
|
||||
bfin_uart_write_byte (struct hw *me, bu16 thr, bu16 mcr)
|
||||
{
|
||||
struct bfin_uart *uart = hw_data (me);
|
||||
unsigned char ch = thr;
|
||||
|
||||
if (mcr & LOOP_ENA)
|
||||
{
|
||||
/* XXX: This probably doesn't work exactly right with
|
||||
external FIFOs ... */
|
||||
uart->saved_byte = thr;
|
||||
uart->saved_count = 1;
|
||||
}
|
||||
|
||||
bfin_uart_write_buffer (me, &ch, 1);
|
||||
|
||||
return thr;
|
||||
}
|
||||
|
||||
@ -149,7 +160,7 @@ bfin_uart_io_write_buffer (struct hw *me, const void *source,
|
||||
uart->dll = value;
|
||||
else
|
||||
{
|
||||
uart->thr = bfin_uart_write_byte (me, value);
|
||||
uart->thr = bfin_uart_write_byte (me, value, uart->mcr);
|
||||
|
||||
if (uart->ier & ETBEI)
|
||||
hw_port_event (me, DV_PORT_TX, 1);
|
||||
@ -184,7 +195,7 @@ bfin_uart_io_write_buffer (struct hw *me, const void *source,
|
||||
|
||||
/* Switch between socket and stdin on the fly. */
|
||||
bu16
|
||||
bfin_uart_get_next_byte (struct hw *me, bu16 rbr, bool *fresh)
|
||||
bfin_uart_get_next_byte (struct hw *me, bu16 rbr, bu16 mcr, bool *fresh)
|
||||
{
|
||||
SIM_DESC sd = hw_system (me);
|
||||
struct bfin_uart *uart = hw_data (me);
|
||||
@ -197,23 +208,26 @@ bfin_uart_get_next_byte (struct hw *me, bu16 rbr, bool *fresh)
|
||||
fresh = &_fresh;
|
||||
|
||||
*fresh = false;
|
||||
if (status & DV_SOCKSER_DISCONNECTED)
|
||||
|
||||
if (uart->saved_count > 0)
|
||||
{
|
||||
if (uart->saved_count > 0)
|
||||
*fresh = true;
|
||||
rbr = uart->saved_byte;
|
||||
--uart->saved_count;
|
||||
}
|
||||
else if (mcr & LOOP_ENA)
|
||||
{
|
||||
/* RX is disconnected, so only return local data. */
|
||||
}
|
||||
else if (status & DV_SOCKSER_DISCONNECTED)
|
||||
{
|
||||
char byte;
|
||||
int ret = sim_io_poll_read (sd, 0/*STDIN*/, &byte, 1);
|
||||
|
||||
if (ret > 0)
|
||||
{
|
||||
*fresh = true;
|
||||
rbr = uart->saved_byte;
|
||||
--uart->saved_count;
|
||||
}
|
||||
else
|
||||
{
|
||||
char byte;
|
||||
int ret = sim_io_poll_read (sd, 0/*STDIN*/, &byte, 1);
|
||||
if (ret > 0)
|
||||
{
|
||||
*fresh = true;
|
||||
rbr = byte;
|
||||
}
|
||||
rbr = byte;
|
||||
}
|
||||
}
|
||||
else
|
||||
@ -239,7 +253,7 @@ bfin_uart_get_status (struct hw *me)
|
||||
}
|
||||
else
|
||||
lsr |= (status & DV_SOCKSER_INPUT_EMPTY ? 0 : DR) |
|
||||
(status & DV_SOCKSER_OUTPUT_EMPTY ? TEMT | THRE : 0);
|
||||
(status & DV_SOCKSER_OUTPUT_EMPTY ? TEMT | THRE : 0);
|
||||
|
||||
return lsr;
|
||||
}
|
||||
@ -266,7 +280,7 @@ bfin_uart_io_read_buffer (struct hw *me, void *dest,
|
||||
dv_store_2 (dest, uart->dll);
|
||||
else
|
||||
{
|
||||
uart->rbr = bfin_uart_get_next_byte (me, uart->rbr, NULL);
|
||||
uart->rbr = bfin_uart_get_next_byte (me, uart->rbr, uart->mcr, NULL);
|
||||
dv_store_2 (dest, uart->rbr);
|
||||
}
|
||||
break;
|
||||
|
@ -26,8 +26,8 @@
|
||||
#define BFIN_MMR_UART_SIZE 0x30
|
||||
|
||||
struct bfin_uart;
|
||||
bu16 bfin_uart_get_next_byte (struct hw *, bu16, bool *fresh);
|
||||
bu16 bfin_uart_write_byte (struct hw *, bu16);
|
||||
bu16 bfin_uart_get_next_byte (struct hw *, bu16, bu16, bool *fresh);
|
||||
bu16 bfin_uart_write_byte (struct hw *, bu16, bu16);
|
||||
bu16 bfin_uart_get_status (struct hw *);
|
||||
unsigned bfin_uart_write_buffer (struct hw *, const unsigned char *, unsigned);
|
||||
unsigned bfin_uart_read_buffer (struct hw *, unsigned char *, unsigned);
|
||||
@ -51,4 +51,14 @@ void bfin_uart_reschedule (struct hw *);
|
||||
#define ETBEI (1 << 1)
|
||||
#define ELSI (1 << 2)
|
||||
|
||||
/* UART_MCR */
|
||||
#define XOFF (1 << 0)
|
||||
#define MRTS (1 << 1)
|
||||
#define RFIT (1 << 2)
|
||||
#define RFRT (1 << 3)
|
||||
#define LOOP_ENA (1 << 4)
|
||||
#define FCPOL (1 << 5)
|
||||
#define ARTS (1 << 6)
|
||||
#define ACTS (1 << 7)
|
||||
|
||||
#endif
|
||||
|
@ -89,7 +89,7 @@ bfin_uart_io_write_buffer (struct hw *me, const void *source,
|
||||
switch (mmr_off)
|
||||
{
|
||||
case mmr_offset(thr):
|
||||
uart->thr = bfin_uart_write_byte (me, value);
|
||||
uart->thr = bfin_uart_write_byte (me, value, uart->mcr);
|
||||
if (uart->ier & ETBEI)
|
||||
hw_port_event (me, DV_PORT_TX, 1);
|
||||
break;
|
||||
@ -142,7 +142,7 @@ bfin_uart_io_read_buffer (struct hw *me, void *dest,
|
||||
switch (mmr_off)
|
||||
{
|
||||
case mmr_offset(rbr):
|
||||
uart->rbr = bfin_uart_get_next_byte (me, uart->rbr, NULL);
|
||||
uart->rbr = bfin_uart_get_next_byte (me, uart->rbr, uart->mcr, NULL);
|
||||
dv_store_2 (dest, uart->rbr);
|
||||
break;
|
||||
case mmr_offset(ier_set):
|
||||
|
Loading…
Reference in New Issue
Block a user