diff options
author | benno <benno@FreeBSD.org> | 2006-05-23 00:41:12 +0000 |
---|---|---|
committer | benno <benno@FreeBSD.org> | 2006-05-23 00:41:12 +0000 |
commit | 30977bc35b2c6606b2b36368fa48f92b5f7dab3a (patch) | |
tree | f537b7c6f68a60e25b048f527b1dfed0b95789f5 /sys/dev/uart | |
parent | 713caab1d6be4eba0130d3c24e75ddd38e45e980 (diff) | |
download | FreeBSD-src-30977bc35b2c6606b2b36368fa48f92b5f7dab3a.zip FreeBSD-src-30977bc35b2c6606b2b36368fa48f92b5f7dab3a.tar.gz |
Allow uart(4)'s ns8250 driver to work with devices whose regshift is > 0.
- Rename REG_DL to REG_DLL and REG_DLH.
- Always treat DLL and DLH as two separate 8-bit registers instead of one
16-bit register.
Additionally, remove the probe for the high 4 bits of IER being 0 and don't
assume we can always read/write 0 to/from those bits.
These changes allow uart(4) to drive the UARTs on the Intel XScale PXA255.
Reviewed by: marcel
Diffstat (limited to 'sys/dev/uart')
-rw-r--r-- | sys/dev/uart/uart_dev_ns8250.c | 40 |
1 files changed, 16 insertions, 24 deletions
diff --git a/sys/dev/uart/uart_dev_ns8250.c b/sys/dev/uart/uart_dev_ns8250.c index 6c5af19..85cfaec 100644 --- a/sys/dev/uart/uart_dev_ns8250.c +++ b/sys/dev/uart/uart_dev_ns8250.c @@ -75,7 +75,7 @@ ns8250_delay(struct uart_bas *bas) lcr = uart_getreg(bas, REG_LCR); uart_setreg(bas, REG_LCR, lcr | LCR_DLAB); uart_barrier(bas); - divisor = uart_getdreg(bas, REG_DL); + divisor = uart_getreg(bas, REG_DLL) | (uart_getreg(bas, REG_DLH) << 8); uart_barrier(bas); uart_setreg(bas, REG_LCR, lcr); uart_barrier(bas); @@ -199,7 +199,8 @@ ns8250_param(struct uart_bas *bas, int baudrate, int databits, int stopbits, return (EINVAL); uart_setreg(bas, REG_LCR, lcr | LCR_DLAB); uart_barrier(bas); - uart_setdreg(bas, REG_DL, divisor); + uart_setreg(bas, REG_DLL, divisor & 0xff); + uart_setreg(bas, REG_DLH, (divisor >> 8) & 0xff); uart_barrier(bas); } @@ -241,36 +242,22 @@ ns8250_probe(struct uart_bas *bas) if (val & 0xe0) return (ENXIO); - lcr = uart_getreg(bas, REG_LCR); - uart_setreg(bas, REG_LCR, lcr & ~LCR_DLAB); - uart_barrier(bas); - - /* Check known 0 bits that depend on !DLAB. */ - val = uart_getreg(bas, REG_IER); - if (val & 0xf0) - goto fail; - - uart_setreg(bas, REG_LCR, lcr); - uart_barrier(bas); return (0); - - fail: - uart_setreg(bas, REG_LCR, lcr); - uart_barrier(bas); - return (ENXIO); } static void ns8250_init(struct uart_bas *bas, int baudrate, int databits, int stopbits, int parity) { + u_char ier; if (bas->rclk == 0) bas->rclk = DEFAULT_RCLK; ns8250_param(bas, baudrate, databits, stopbits, parity); /* Disable all interrupt sources. */ - uart_setreg(bas, REG_IER, 0); + ier = uart_getreg(bas, REG_IER) & 0xf0; + uart_setreg(bas, REG_IER, ier); uart_barrier(bas); /* Disable the FIFO (if present). */ @@ -416,7 +403,8 @@ ns8250_bus_attach(struct uart_softc *sc) ns8250_bus_getsig(sc); ns8250_clrint(bas); - ns8250->ier = IER_EMSC | IER_ERLS | IER_ERXRDY; + ns8250->ier = uart_getreg(bas, REG_IER) & 0xf0; + ns8250->ier |= IER_EMSC | IER_ERLS | IER_ERXRDY; uart_setreg(bas, REG_IER, ns8250->ier); uart_barrier(bas); return (0); @@ -426,9 +414,11 @@ static int ns8250_bus_detach(struct uart_softc *sc) { struct uart_bas *bas; + u_char ier; bas = &sc->sc_bas; - uart_setreg(bas, REG_IER, 0); + ier = uart_getreg(bas, REG_IER) & 0xf0; + uart_setreg(bas, REG_IER, ier); uart_barrier(bas); ns8250_clrint(bas); return (0); @@ -529,7 +519,8 @@ ns8250_bus_ioctl(struct uart_softc *sc, int request, intptr_t data) lcr = uart_getreg(bas, REG_LCR); uart_setreg(bas, REG_LCR, lcr | LCR_DLAB); uart_barrier(bas); - divisor = uart_getdreg(bas, REG_DL); + divisor = uart_getreg(bas, REG_DLL) | + (uart_getreg(bas, REG_DLH) << 8); uart_barrier(bas); uart_setreg(bas, REG_LCR, lcr); uart_barrier(bas); @@ -600,7 +591,7 @@ ns8250_bus_probe(struct uart_softc *sc) { struct uart_bas *bas; int count, delay, error, limit; - uint8_t lsr, mcr; + uint8_t lsr, mcr, ier; bas = &sc->sc_bas; @@ -684,7 +675,8 @@ ns8250_bus_probe(struct uart_softc *sc) --limit) DELAY(delay); if (limit == 0) { - uart_setreg(bas, REG_IER, 0); + ier = uart_getreg(bas, REG_IER) & 0xf0; + uart_setreg(bas, REG_IER, ier); uart_setreg(bas, REG_MCR, mcr); uart_setreg(bas, REG_FCR, 0); uart_barrier(bas); |