Date: Thu, 11 May 2006 13:12:29 +1000 From: Benno Rice <benno@FreeBSD.org> To: hackers@FreeBSD.org Subject: RFC: Minor changes to uart(4)'s ns8250/ns16550 support. Message-ID: <4462AB9D.4000107@FreeBSD.org>
next in thread | raw e-mail | index | archive | help
This is a multi-part message in MIME format. --------------040608010607010107080407 Content-Type: text/plain; charset=ISO-8859-1; format=flowed Content-Transfer-Encoding: 7bit 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 benno@FreeBSD.org --------------040608010607010107080407 Content-Type: text/plain; x-mac-type="0"; x-mac-creator="0"; name="uart-pxa.diff" Content-Transfer-Encoding: 7bit Content-Disposition: inline; filename="uart-pxa.diff" 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); --------------040608010607010107080407--
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?4462AB9D.4000107>