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:
parent
713caab1d6
commit
30977bc35b
@ -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) */
|
||||
|
@ -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);
|
||||
|
Loading…
Reference in New Issue
Block a user