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
This commit is contained in:
Benno Rice 2008-05-30 01:57:13 +00:00
parent 1b3418b2dc
commit 0aefb0a63c
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=179420

View File

@ -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);