Changeset View
Changeset View
Standalone View
Standalone View
head/sys/dev/uart/uart_dev_pl011.c
Show First 20 Lines • Show All 55 Lines • ▼ Show 20 Lines | |||||
/* PL011 UART registers and masks*/ | /* PL011 UART registers and masks*/ | ||||
#define UART_DR 0x00 /* Data register */ | #define UART_DR 0x00 /* Data register */ | ||||
#define DR_FE (1 << 8) /* Framing error */ | #define DR_FE (1 << 8) /* Framing error */ | ||||
#define DR_PE (1 << 9) /* Parity error */ | #define DR_PE (1 << 9) /* Parity error */ | ||||
#define DR_BE (1 << 10) /* Break error */ | #define DR_BE (1 << 10) /* Break error */ | ||||
#define DR_OE (1 << 11) /* Overrun error */ | #define DR_OE (1 << 11) /* Overrun error */ | ||||
#define UART_FR 0x06 /* Flag register */ | #define UART_FR 0x06 /* Flag register */ | ||||
#define FR_RXFE (1 << 4) /* Receive FIFO/reg empty */ | |||||
#define FR_TXFF (1 << 5) /* Transmit FIFO/reg full */ | #define FR_TXFF (1 << 5) /* Transmit FIFO/reg full */ | ||||
#define FR_RXFF (1 << 6) /* Receive FIFO/reg full */ | #define FR_RXFF (1 << 6) /* Receive FIFO/reg full */ | ||||
#define FR_TXFE (1 << 7) /* Transmit FIFO/reg empty */ | #define FR_TXFE (1 << 7) /* Transmit FIFO/reg empty */ | ||||
#define UART_IBRD 0x09 /* Integer baud rate register */ | #define UART_IBRD 0x09 /* Integer baud rate register */ | ||||
#define IBRD_BDIVINT 0xffff /* Significant part of int. divisor value */ | #define IBRD_BDIVINT 0xffff /* Significant part of int. divisor value */ | ||||
#define UART_FBRD 0x0a /* Fractional baud rate register */ | #define UART_FBRD 0x0a /* Fractional baud rate register */ | ||||
▲ Show 20 Lines • Show All 94 Lines • ▼ Show 20 Lines | if (stopbits == 2) | ||||
line |= LCR_H_STP2; | line |= LCR_H_STP2; | ||||
else | else | ||||
line &= ~LCR_H_STP2; | line &= ~LCR_H_STP2; | ||||
if (parity) | if (parity) | ||||
line |= LCR_H_PEN; | line |= LCR_H_PEN; | ||||
else | else | ||||
line &= ~LCR_H_PEN; | line &= ~LCR_H_PEN; | ||||
line |= LCR_H_FEN; | |||||
/* Configure the rest */ | /* Configure the rest */ | ||||
line &= ~LCR_H_FEN; | |||||
ctrl |= (CR_RXE | CR_TXE | CR_UARTEN); | ctrl |= (CR_RXE | CR_TXE | CR_UARTEN); | ||||
if (bas->rclk != 0 && baudrate != 0) { | if (bas->rclk != 0 && baudrate != 0) { | ||||
baud = bas->rclk * 4 / baudrate; | baud = bas->rclk * 4 / baudrate; | ||||
__uart_setreg(bas, UART_IBRD, ((uint32_t)(baud >> 6)) & IBRD_BDIVINT); | __uart_setreg(bas, UART_IBRD, ((uint32_t)(baud >> 6)) & IBRD_BDIVINT); | ||||
__uart_setreg(bas, UART_FBRD, (uint32_t)(baud & 0x3F) & FBRD_BDIVFRAC); | __uart_setreg(bas, UART_FBRD, (uint32_t)(baud & 0x3F) & FBRD_BDIVFRAC); | ||||
} | } | ||||
Show All 29 Lines | while (__uart_getreg(bas, UART_FR) & FR_TXFF) | ||||
; | ; | ||||
__uart_setreg(bas, UART_DR, c & 0xff); | __uart_setreg(bas, UART_DR, c & 0xff); | ||||
} | } | ||||
static int | static int | ||||
uart_pl011_rxready(struct uart_bas *bas) | uart_pl011_rxready(struct uart_bas *bas) | ||||
{ | { | ||||
return (__uart_getreg(bas, UART_FR) & FR_RXFF); | return !(__uart_getreg(bas, UART_FR) & FR_RXFE); | ||||
} | } | ||||
static int | static int | ||||
uart_pl011_getc(struct uart_bas *bas, struct mtx *hwmtx) | uart_pl011_getc(struct uart_bas *bas, struct mtx *hwmtx) | ||||
{ | { | ||||
int c; | int c; | ||||
while (!uart_pl011_rxready(bas)) | while (!uart_pl011_rxready(bas)) | ||||
▲ Show 20 Lines • Show All 181 Lines • ▼ Show 20 Lines | |||||
} | } | ||||
static int | static int | ||||
uart_pl011_bus_probe(struct uart_softc *sc) | uart_pl011_bus_probe(struct uart_softc *sc) | ||||
{ | { | ||||
device_set_desc(sc->sc_dev, "PrimeCell UART (PL011)"); | device_set_desc(sc->sc_dev, "PrimeCell UART (PL011)"); | ||||
sc->sc_rxfifosz = 1; | sc->sc_rxfifosz = 16; | ||||
sc->sc_txfifosz = 1; | sc->sc_txfifosz = 16; | ||||
return (0); | return (0); | ||||
} | } | ||||
static int | static int | ||||
uart_pl011_bus_receive(struct uart_softc *sc) | uart_pl011_bus_receive(struct uart_softc *sc) | ||||
{ | { | ||||
struct uart_bas *bas; | struct uart_bas *bas; | ||||
uint32_t ints, xc; | uint32_t ints, xc; | ||||
int rx; | int rx; | ||||
bas = &sc->sc_bas; | bas = &sc->sc_bas; | ||||
uart_lock(sc->sc_hwmtx); | uart_lock(sc->sc_hwmtx); | ||||
ints = __uart_getreg(bas, UART_MIS); | ints = __uart_getreg(bas, UART_MIS); | ||||
while (ints & (UART_RXREADY | RIS_RTIM)) { | while (ints & (UART_RXREADY | RIS_RTIM)) { | ||||
if (uart_rx_full(sc)) { | if (uart_rx_full(sc)) { | ||||
sc->sc_rxbuf[sc->sc_rxput] = UART_STAT_OVERRUN; | sc->sc_rxbuf[sc->sc_rxput] = UART_STAT_OVERRUN; | ||||
break; | break; | ||||
} | } | ||||
__uart_setreg(bas, UART_ICR, (UART_RXREADY | RIS_RTIM)); | |||||
xc = __uart_getreg(bas, UART_DR); | xc = __uart_getreg(bas, UART_DR); | ||||
rx = xc & 0xff; | rx = xc & 0xff; | ||||
if (xc & DR_FE) | if (xc & DR_FE) | ||||
rx |= UART_STAT_FRAMERR; | rx |= UART_STAT_FRAMERR; | ||||
if (xc & DR_PE) | if (xc & DR_PE) | ||||
rx |= UART_STAT_PARERR; | rx |= UART_STAT_PARERR; | ||||
Show All 24 Lines | uart_pl011_bus_transmit(struct uart_softc *sc) | ||||
bas = &sc->sc_bas; | bas = &sc->sc_bas; | ||||
uart_lock(sc->sc_hwmtx); | uart_lock(sc->sc_hwmtx); | ||||
for (i = 0; i < sc->sc_txdatasz; i++) { | for (i = 0; i < sc->sc_txdatasz; i++) { | ||||
__uart_setreg(bas, UART_DR, sc->sc_txbuf[i]); | __uart_setreg(bas, UART_DR, sc->sc_txbuf[i]); | ||||
uart_barrier(bas); | uart_barrier(bas); | ||||
} | } | ||||
/* If not empty wait until it is */ | /* Mark busy and enable TX interrupt */ | ||||
if ((__uart_getreg(bas, UART_FR) & FR_TXFE) != FR_TXFE) { | |||||
sc->sc_txbusy = 1; | sc->sc_txbusy = 1; | ||||
/* Enable TX interrupt */ | |||||
__uart_setreg(bas, UART_IMSC, psc->imsc); | __uart_setreg(bas, UART_IMSC, psc->imsc); | ||||
} | |||||
uart_unlock(sc->sc_hwmtx); | uart_unlock(sc->sc_hwmtx); | ||||
/* No interrupt expected, schedule the next fifo write */ | |||||
if (!sc->sc_txbusy) | |||||
uart_sched_softih(sc, SER_INT_TXIDLE); | |||||
return (0); | return (0); | ||||
} | } | ||||
static void | static void | ||||
uart_pl011_bus_grab(struct uart_softc *sc) | uart_pl011_bus_grab(struct uart_softc *sc) | ||||
{ | { | ||||
struct uart_pl011_softc *psc; | struct uart_pl011_softc *psc; | ||||
Show All 25 Lines |