diff options
| author | Ian Lepore <ian@FreeBSD.org> | 2017-03-08 18:53:32 +0000 |
|---|---|---|
| committer | Ian Lepore <ian@FreeBSD.org> | 2017-03-08 18:53:32 +0000 |
| commit | 2cb357c5cd2ba914dcffcd1fa4301beff2356125 (patch) | |
| tree | 94079d80c138c6aa627e60b10676dcfcb5e75ea8 /sys/dev/uart/uart_dev_pl011.c | |
| parent | 696f00b67f7ef6fd26ff34f72eddefad29304637 (diff) | |
Notes
Diffstat (limited to 'sys/dev/uart/uart_dev_pl011.c')
| -rw-r--r-- | sys/dev/uart/uart_dev_pl011.c | 49 |
1 files changed, 39 insertions, 10 deletions
diff --git a/sys/dev/uart/uart_dev_pl011.c b/sys/dev/uart/uart_dev_pl011.c index 25ff57a1e4fd..eb8889976d0e 100644 --- a/sys/dev/uart/uart_dev_pl011.c +++ b/sys/dev/uart/uart_dev_pl011.c @@ -111,16 +111,24 @@ __FBSDID("$FreeBSD$"); #define UART_MIS 0x10 /* Masked interrupt status register */ #define UART_ICR 0x11 /* Interrupt clear register */ +#define UART_PIDREG_0 0x3f8 /* Peripheral ID register 0 */ +#define UART_PIDREG_1 0x3f9 /* Peripheral ID register 1 */ +#define UART_PIDREG_2 0x3fa /* Peripheral ID register 2 */ +#define UART_PIDREG_3 0x3fb /* Peripheral ID register 3 */ + /* - * The hardware FIFOs are 16 bytes each. We configure them to interrupt when - * 3/4 full/empty. For RX we set the size to the full hardware capacity so that - * the uart core allocates enough buffer space to hold a complete fifo full of - * incoming data. For TX, we need to limit the size to the capacity we know - * will be available when the interrupt occurs; uart_core will feed exactly that - * many bytes to uart_pl011_bus_transmit() which must consume them all. + * The hardware FIFOs are 16 bytes each on rev 2 and earlier hardware, 32 bytes + * on rev 3 and later. We configure them to interrupt when 3/4 full/empty. For + * RX we set the size to the full hardware capacity so that the uart core + * allocates enough buffer space to hold a complete fifo full of incoming data. + * For TX, we need to limit the size to the capacity we know will be available + * when the interrupt occurs; uart_core will feed exactly that many bytes to + * uart_pl011_bus_transmit() which must consume them all. */ -#define FIFO_RX_SIZE 16 -#define FIFO_TX_SIZE 12 +#define FIFO_RX_SIZE_R2 16 +#define FIFO_TX_SIZE_R2 12 +#define FIFO_RX_SIZE_R3 32 +#define FIFO_TX_SIZE_R3 24 #define FIFO_IFLS_BITS ((IFLS_LVL_6_8th << IFLS_RX_SHIFT) | (IFLS_LVL_2_8th)) /* @@ -440,11 +448,32 @@ uart_pl011_bus_param(struct uart_softc *sc, int baudrate, int databits, static int uart_pl011_bus_probe(struct uart_softc *sc) { + uint8_t hwrev; + bool is_bcm2835; device_set_desc(sc->sc_dev, "PrimeCell UART (PL011)"); - sc->sc_rxfifosz = FIFO_RX_SIZE; - sc->sc_txfifosz = FIFO_TX_SIZE; + /* + * The FIFO sizes vary depending on hardware; rev 2 and below have 16 + * byte FIFOs, rev 3 and up are 32 byte. We get a bit of drama, as + * always, with the bcm2835 (rpi), which claims to be rev 3, but has 16 + * byte FIFOs. We check for both the old freebsd-historic and the + * proper bindings-defined compatible strings for bcm2835. + */ +#ifdef FDT + is_bcm2835 = ofw_bus_is_compatible(sc->sc_dev, "brcm,bcm2835-pl011") || + ofw_bus_is_compatible(sc->sc_dev, "broadcom,bcm2835-uart"); +#else + is_bcm2835 = false; +#endif + hwrev = __uart_getreg(&sc->sc_bas, UART_PIDREG_2) >> 4; + if (hwrev <= 2 || is_bcm2835) { + sc->sc_rxfifosz = FIFO_RX_SIZE_R2; + sc->sc_txfifosz = FIFO_TX_SIZE_R2; + } else { + sc->sc_rxfifosz = FIFO_RX_SIZE_R3; + sc->sc_txfifosz = FIFO_TX_SIZE_R3; + } return (0); } |
