I've made a couple of changes to uart(4)'s support for ns8250/ns16550-alikes to support some work I'm doing on porting FreeBSD to Intel's XScale PXA255. The changes are:

- Stop using uart_{get,set}dreg to handle the DL register. The DL register is 16 bits wide, but when the register offset is anything other than 0, it's true nature as two individual 8-bit registers is revealed and bus_space_{read,write}_2 won't work anymore. Instead, treat it as two single 8-bit registers.

- The PXA255 uses the upper four bits of the IER to handle some of it's own configuration for the UART, including the bit that turns the UART on and off. Therefore we can't assume that those bits will be 0, or that writing 0 to them is safe. Instead, always read the IER, make the changes and write it back out again.

A patch is attached which contains these changes. I've already run these past marcel and he's ok with them. If anyone using uart(4) to drive one of these parts could test this and let me know if they run into any problems, that'd rock.

Many thanks!

--
Benno Rice
[EMAIL PROTECTED]
Index: sys/dev/ic/ns16550.h
===================================================================
RCS file: /home/ncvs/src/sys/dev/ic/ns16550.h,v
retrieving revision 1.16
diff -u -r1.16 ns16550.h
--- sys/dev/ic/ns16550.h        20 Nov 2004 23:19:42 -0000      1.16
+++ sys/dev/ic/ns16550.h        11 May 2006 03:09:35 -0000
@@ -127,7 +127,8 @@
 #define        com_dlbl        com_dll
 #define        com_dlm         1       /* divisor latch high (R/W) */
 #define        com_dlbh        com_dlm
-#define        REG_DL          com_dll
+#define        REG_DLL         com_dll
+#define        REG_DLH         com_dlm
 
 /* 16450 register #7.  Not multiplexed. */
 #define        com_scr         7       /* scratch register (R/W) */
Index: sys/dev/uart/uart_dev_ns8250.c
===================================================================
RCS file: /home/ncvs/src/sys/dev/uart/uart_dev_ns8250.c,v
retrieving revision 1.21
diff -u -r1.21 uart_dev_ns8250.c
--- sys/dev/uart/uart_dev_ns8250.c      27 Apr 2006 05:43:10 -0000      1.21
+++ sys/dev/uart/uart_dev_ns8250.c      11 May 2006 03:09:49 -0000
@@ -75,7 +75,7 @@
        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 @@
                        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);
        }
 
@@ -245,32 +246,22 @@
        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 +407,8 @@
        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 +418,11 @@
 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 +523,8 @@
                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 +595,7 @@
 {
        struct uart_bas *bas;
        int count, delay, error, limit;
-       uint8_t lsr, mcr;
+       uint8_t lsr, mcr, ier;
 
        bas = &sc->sc_bas;
 
@@ -684,7 +679,8 @@
                    --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);
_______________________________________________
freebsd-hackers@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/freebsd-hackers
To unsubscribe, send any mail to "[EMAIL PROTECTED]"

Reply via email to