diff options
author | Mike Frysinger <vapier@gentoo.org> | 2011-05-14 15:59:09 +0000 |
---|---|---|
committer | Mike Frysinger <vapier@gentoo.org> | 2011-05-14 15:59:09 +0000 |
commit | 28fe96b798c2b0a7abd07b2631f6d4abeaf9d4dd (patch) | |
tree | b36e50567ba4c3b69bd47cea4479e37b2d394d35 /sim/bfin | |
parent | ba4a8bdd81e55d45b97cdf9b91eb111a7ac0d3f9 (diff) | |
download | binutils-28fe96b798c2b0a7abd07b2631f6d4abeaf9d4dd.zip binutils-28fe96b798c2b0a7abd07b2631f6d4abeaf9d4dd.tar.gz binutils-28fe96b798c2b0a7abd07b2631f6d4abeaf9d4dd.tar.bz2 |
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>
Diffstat (limited to 'sim/bfin')
-rw-r--r-- | sim/bfin/ChangeLog | 15 | ||||
-rw-r--r-- | sim/bfin/dv-bfin_uart.c | 52 | ||||
-rw-r--r-- | sim/bfin/dv-bfin_uart.h | 14 | ||||
-rw-r--r-- | sim/bfin/dv-bfin_uart2.c | 4 |
4 files changed, 62 insertions, 23 deletions
diff --git a/sim/bfin/ChangeLog b/sim/bfin/ChangeLog index 6785044..a69d6e2 100644 --- a/sim/bfin/ChangeLog +++ b/sim/bfin/ChangeLog @@ -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 diff --git a/sim/bfin/dv-bfin_uart.c b/sim/bfin/dv-bfin_uart.c index f05ee15..697fa96 100644 --- a/sim/bfin/dv-bfin_uart.c +++ b/sim/bfin/dv-bfin_uart.c @@ -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) + { + *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) { - if (uart->saved_count > 0) + 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; diff --git a/sim/bfin/dv-bfin_uart.h b/sim/bfin/dv-bfin_uart.h index ccb7af4..52074f6 100644 --- a/sim/bfin/dv-bfin_uart.h +++ b/sim/bfin/dv-bfin_uart.h @@ -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 diff --git a/sim/bfin/dv-bfin_uart2.c b/sim/bfin/dv-bfin_uart2.c index 179574d..16ede50 100644 --- a/sim/bfin/dv-bfin_uart2.c +++ b/sim/bfin/dv-bfin_uart2.c @@ -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): |