summaryrefslogtreecommitdiffstats
path: root/sys/dev/uart/uart_dev_ns8250.c
diff options
context:
space:
mode:
authorbenno <benno@FreeBSD.org>2008-05-30 01:57:13 +0000
committerbenno <benno@FreeBSD.org>2008-05-30 01:57:13 +0000
commitc358527cf765804a28fbb6f9754035a12b2a6671 (patch)
treeae2c95ba117f04cf20dce9430343bbb759cb702a /sys/dev/uart/uart_dev_ns8250.c
parent8951bcd14cbf45e5917c52c16236bfa5515c6d1b (diff)
downloadFreeBSD-src-c358527cf765804a28fbb6f9754035a12b2a6671.zip
FreeBSD-src-c358527cf765804a28fbb6f9754035a12b2a6671.tar.gz
The XScale PXA255 has three generally ns16x50 compatible UARTs. One of the
variations from normal 16x50 behaviour however is the the use of a normally unused bit of IER to control RX timeout interrupts independently of the generally used RXRDY bit. If this bit is not enabled, we only ever get interrupts when the FIFO is full, never before. This is not very useful when the UART is being used as a console. In order to support this without causing potential problems on more "normal" 16x50 variants, this change introduces two hints for the uart device, ier_mask and ier_rxbits. These can be used to override which bits get set and cleared when we're enabling and disabling RX interrupts. Reviewed by: marcel
Diffstat (limited to 'sys/dev/uart/uart_dev_ns8250.c')
-rw-r--r--sys/dev/uart/uart_dev_ns8250.c36
1 files changed, 31 insertions, 5 deletions
diff --git a/sys/dev/uart/uart_dev_ns8250.c b/sys/dev/uart/uart_dev_ns8250.c
index d2a3dcf..81642b2 100644
--- a/sys/dev/uart/uart_dev_ns8250.c
+++ b/sys/dev/uart/uart_dev_ns8250.c
@@ -258,7 +258,12 @@ ns8250_init(struct uart_bas *bas, int baudrate, int databits, int stopbits,
ns8250_param(bas, baudrate, databits, stopbits, parity);
/* Disable all interrupt sources. */
- ier = uart_getreg(bas, REG_IER) & 0xf0;
+ /*
+ * We use 0xe0 instead of 0xf0 as the mask because the XScale PXA
+ * UARTs split the receive time-out interrupt bit out separately as
+ * 0x10. This gets handled by ier_mask and ier_rxbits below.
+ */
+ ier = uart_getreg(bas, REG_IER) & 0xe0;
uart_setreg(bas, REG_IER, ier);
uart_barrier(bas);
@@ -332,6 +337,9 @@ struct ns8250_softc {
uint8_t fcr;
uint8_t ier;
uint8_t mcr;
+
+ uint8_t ier_mask;
+ uint8_t ier_rxbits;
};
static int ns8250_bus_attach(struct uart_softc *);
@@ -400,6 +408,19 @@ ns8250_bus_attach(struct uart_softc *sc)
ns8250->fcr |= FCR_RX_MEDH;
} else
ns8250->fcr |= FCR_RX_MEDH;
+
+ /* Get IER mask */
+ ivar = 0xf0;
+ resource_int_value("uart", device_get_unit(sc->sc_dev), "ier_mask",
+ &ivar);
+ ns8250->ier_mask = (uint8_t)(ivar & 0xff);
+
+ /* Get IER RX interrupt bits */
+ ivar = IER_EMSC | IER_ERLS | IER_ERXRDY;
+ resource_int_value("uart", device_get_unit(sc->sc_dev), "ier_rxbits",
+ &ivar);
+ ns8250->ier_rxbits = (uint8_t)(ivar & 0xff);
+
uart_setreg(bas, REG_FCR, ns8250->fcr);
uart_barrier(bas);
ns8250_bus_flush(sc, UART_FLUSH_RECEIVER|UART_FLUSH_TRANSMITTER);
@@ -411,21 +432,24 @@ ns8250_bus_attach(struct uart_softc *sc)
ns8250_bus_getsig(sc);
ns8250_clrint(bas);
- ns8250->ier = uart_getreg(bas, REG_IER) & 0xf0;
- ns8250->ier |= IER_EMSC | IER_ERLS | IER_ERXRDY;
+ ns8250->ier = uart_getreg(bas, REG_IER) & ns8250->ier_mask;
+ ns8250->ier |= ns8250->ier_rxbits;
uart_setreg(bas, REG_IER, ns8250->ier);
uart_barrier(bas);
+
return (0);
}
static int
ns8250_bus_detach(struct uart_softc *sc)
{
+ struct ns8250_softc *ns8250;
struct uart_bas *bas;
u_char ier;
+ ns8250 = (struct ns8250_softc *)sc;
bas = &sc->sc_bas;
- ier = uart_getreg(bas, REG_IER) & 0xf0;
+ ier = uart_getreg(bas, REG_IER) & ns8250->ier_mask;
uart_setreg(bas, REG_IER, ier);
uart_barrier(bas);
ns8250_clrint(bas);
@@ -597,10 +621,12 @@ ns8250_bus_param(struct uart_softc *sc, int baudrate, int databits,
static int
ns8250_bus_probe(struct uart_softc *sc)
{
+ struct ns8250_softc *ns8250;
struct uart_bas *bas;
int count, delay, error, limit;
uint8_t lsr, mcr, ier;
+ ns8250 = (struct ns8250_softc *)sc;
bas = &sc->sc_bas;
error = ns8250_probe(bas);
@@ -683,7 +709,7 @@ ns8250_bus_probe(struct uart_softc *sc)
--limit)
DELAY(delay);
if (limit == 0) {
- ier = uart_getreg(bas, REG_IER) & 0xf0;
+ ier = uart_getreg(bas, REG_IER) & ns8250->ier_mask;
uart_setreg(bas, REG_IER, ier);
uart_setreg(bas, REG_MCR, mcr);
uart_setreg(bas, REG_FCR, 0);
OpenPOWER on IntegriCloud