summaryrefslogtreecommitdiffstats
path: root/sys/dev/uart
diff options
context:
space:
mode:
authorian <ian@FreeBSD.org>2015-05-23 20:01:20 +0000
committerian <ian@FreeBSD.org>2015-05-23 20:01:20 +0000
commit142829f4c84994fedf96baad0c9a95317ffd241c (patch)
treec8089e7c7bef2668f6b90d723abb9238348b591b /sys/dev/uart
parent446930c903da0e661ec3358fe3105c9d0b3a9ab0 (diff)
downloadFreeBSD-src-142829f4c84994fedf96baad0c9a95317ffd241c.zip
FreeBSD-src-142829f4c84994fedf96baad0c9a95317ffd241c.tar.gz
MFC r279239:
Enable 'receive timeout' interrupt allowing us to not loose 'rx buffer full' event.
Diffstat (limited to 'sys/dev/uart')
-rw-r--r--sys/dev/uart/uart_dev_pl011.c35
1 files changed, 25 insertions, 10 deletions
diff --git a/sys/dev/uart/uart_dev_pl011.c b/sys/dev/uart/uart_dev_pl011.c
index 2e5ac8c..1d17286 100644
--- a/sys/dev/uart/uart_dev_pl011.c
+++ b/sys/dev/uart/uart_dev_pl011.c
@@ -78,6 +78,7 @@ __FBSDID("$FreeBSD$");
#define UART_RIS 0x0f /* Raw interrupt status register */
#define UART_RXREADY (1 << 4) /* RX buffer full */
#define UART_TXEMPTY (1 << 5) /* TX buffer empty */
+#define RIS_RTIM (1 << 6) /* Receive timeout */
#define RIS_FE (1 << 7) /* Framing error interrupt status */
#define RIS_PE (1 << 8) /* Parity error interrupt status */
#define RIS_BE (1 << 9) /* Break error interrupt status */
@@ -278,11 +279,15 @@ static int
uart_pl011_bus_attach(struct uart_softc *sc)
{
struct uart_bas *bas;
+ int reg;
bas = &sc->sc_bas;
- /* Enable RX & TX interrupts */
- __uart_setreg(bas, UART_IMSC, (UART_RXREADY | UART_TXEMPTY));
- /* Clear RX & TX interrupts */
+
+ /* Enable interrupts */
+ reg = (UART_RXREADY | RIS_RTIM | UART_TXEMPTY);
+ __uart_setreg(bas, UART_IMSC, reg);
+
+ /* Clear interrupts */
__uart_setreg(bas, UART_ICR, IMSC_MASK_ALL);
return (0);
@@ -337,15 +342,16 @@ static int
uart_pl011_bus_ipend(struct uart_softc *sc)
{
struct uart_bas *bas;
- int ipend;
uint32_t ints;
+ int ipend;
+ int reg;
bas = &sc->sc_bas;
uart_lock(sc->sc_hwmtx);
ints = __uart_getreg(bas, UART_MIS);
ipend = 0;
- if (ints & UART_RXREADY)
+ if (ints & (UART_RXREADY | RIS_RTIM))
ipend |= SER_INT_RXREADY;
if (ints & RIS_BE)
ipend |= SER_INT_BREAK;
@@ -355,7 +361,10 @@ uart_pl011_bus_ipend(struct uart_softc *sc)
if (sc->sc_txbusy)
ipend |= SER_INT_TXIDLE;
- __uart_setreg(bas, UART_IMSC, UART_RXREADY);
+ /* Disable TX interrupt */
+ reg = __uart_getreg(bas, UART_IMSC);
+ reg &= ~(UART_TXEMPTY);
+ __uart_setreg(bas, UART_IMSC, reg);
}
uart_unlock(sc->sc_hwmtx);
@@ -391,14 +400,14 @@ static int
uart_pl011_bus_receive(struct uart_softc *sc)
{
struct uart_bas *bas;
- int rx;
uint32_t ints, xc;
+ int rx;
bas = &sc->sc_bas;
uart_lock(sc->sc_hwmtx);
ints = __uart_getreg(bas, UART_MIS);
- while (ints & UART_RXREADY) {
+ while (ints & (UART_RXREADY | RIS_RTIM)) {
if (uart_rx_full(sc)) {
sc->sc_rxbuf[sc->sc_rxput] = UART_STAT_OVERRUN;
break;
@@ -411,7 +420,7 @@ uart_pl011_bus_receive(struct uart_softc *sc)
if (xc & DR_PE)
rx |= UART_STAT_PARERR;
- __uart_setreg(bas, UART_ICR, UART_RXREADY);
+ __uart_setreg(bas, UART_ICR, (UART_RXREADY | RIS_RTIM));
uart_rx_put(sc, rx);
ints = __uart_getreg(bas, UART_MIS);
@@ -433,6 +442,7 @@ static int
uart_pl011_bus_transmit(struct uart_softc *sc)
{
struct uart_bas *bas;
+ int reg;
int i;
bas = &sc->sc_bas;
@@ -443,7 +453,12 @@ uart_pl011_bus_transmit(struct uart_softc *sc)
uart_barrier(bas);
}
sc->sc_txbusy = 1;
- __uart_setreg(bas, UART_IMSC, (UART_RXREADY | UART_TXEMPTY));
+
+ /* Enable TX interrupt */
+ reg = __uart_getreg(bas, UART_IMSC);
+ reg |= (UART_TXEMPTY);
+ __uart_setreg(bas, UART_IMSC, reg);
+
uart_unlock(sc->sc_hwmtx);
return (0);
OpenPOWER on IntegriCloud