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
This commit is contained in:
benno 2006-05-23 00:41:12 +00:00
parent 713caab1d6
commit 30977bc35b
2 changed files with 18 additions and 25 deletions

View File

@ -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) */

View File

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