summaryrefslogtreecommitdiffstats
path: root/sys/dev/uart
diff options
context:
space:
mode:
authorbenno <benno@FreeBSD.org>2006-05-23 00:41:12 +0000
committerbenno <benno@FreeBSD.org>2006-05-23 00:41:12 +0000
commit30977bc35b2c6606b2b36368fa48f92b5f7dab3a (patch)
treef537b7c6f68a60e25b048f527b1dfed0b95789f5 /sys/dev/uart
parent713caab1d6be4eba0130d3c24e75ddd38e45e980 (diff)
downloadFreeBSD-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.c40
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);
OpenPOWER on IntegriCloud