aboutsummaryrefslogtreecommitdiff
path: root/sim/bfin
diff options
context:
space:
mode:
authorMike Frysinger <vapier@gentoo.org>2011-05-14 15:59:09 +0000
committerMike Frysinger <vapier@gentoo.org>2011-05-14 15:59:09 +0000
commit28fe96b798c2b0a7abd07b2631f6d4abeaf9d4dd (patch)
treeb36e50567ba4c3b69bd47cea4479e37b2d394d35 /sim/bfin
parentba4a8bdd81e55d45b97cdf9b91eb111a7ac0d3f9 (diff)
downloadbinutils-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/ChangeLog15
-rw-r--r--sim/bfin/dv-bfin_uart.c52
-rw-r--r--sim/bfin/dv-bfin_uart.h14
-rw-r--r--sim/bfin/dv-bfin_uart2.c4
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):