Add support for A10 uart.
A10 uart is derived from Synopsys DesignWare uart and requires to read Uart Status Register when IIR_BUSY has detected. Also this change includes FDT check, where it checks device specific properties defined in dts and sets the busy_detect variable. broken_txfifo is also needed to be set in order to make it work for A10 uart case. Reviewed by: marcel@ Approved by: gonzo@
This commit is contained in:
parent
4cf5de800c
commit
ac4adddf04
@ -182,6 +182,7 @@
|
||||
#define com_xoff1 6 /* XOFF 1 character (R/W) */
|
||||
#define com_xoff2 7 /* XOFF 2 character (R/W) */
|
||||
|
||||
#define DW_REG_USR 31 /* DesignWare derived Uart Status Reg */
|
||||
#define com_usr 39 /* Octeon 16750/16550 Uart Status Reg */
|
||||
#define REG_USR com_usr
|
||||
#define USR_TXFIFO_NOTFULL 2 /* Uart TX FIFO Not full */
|
||||
|
@ -24,6 +24,8 @@
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "opt_platform.h"
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__FBSDID("$FreeBSD$");
|
||||
|
||||
@ -35,6 +37,12 @@ __FBSDID("$FreeBSD$");
|
||||
#include <sys/sysctl.h>
|
||||
#include <machine/bus.h>
|
||||
|
||||
#ifdef FDT
|
||||
#include <dev/fdt/fdt_common.h>
|
||||
#include <dev/ofw/ofw_bus.h>
|
||||
#include <dev/ofw/ofw_bus_subr.h>
|
||||
#endif
|
||||
|
||||
#include <dev/uart/uart.h>
|
||||
#include <dev/uart/uart_cpu.h>
|
||||
#include <dev/uart/uart_bus.h>
|
||||
@ -45,6 +53,11 @@ __FBSDID("$FreeBSD$");
|
||||
|
||||
#define DEFAULT_RCLK 1843200
|
||||
|
||||
static int broken_txfifo = 0;
|
||||
SYSCTL_INT(_hw, OID_AUTO, broken_txfifo, CTLFLAG_RW | CTLFLAG_TUN,
|
||||
&broken_txfifo, 0, "UART FIFO has QEMU emulation bug");
|
||||
TUNABLE_INT("hw.broken_txfifo", &broken_txfifo);
|
||||
|
||||
/*
|
||||
* Clear pending interrupts. THRE is cleared by reading IIR. Data
|
||||
* that may have been received gets lost here.
|
||||
@ -350,6 +363,7 @@ struct ns8250_softc {
|
||||
|
||||
uint8_t ier_mask;
|
||||
uint8_t ier_rxbits;
|
||||
uint8_t busy_detect;
|
||||
};
|
||||
|
||||
static int ns8250_bus_attach(struct uart_softc *);
|
||||
@ -401,6 +415,24 @@ ns8250_bus_attach(struct uart_softc *sc)
|
||||
struct ns8250_softc *ns8250 = (struct ns8250_softc*)sc;
|
||||
struct uart_bas *bas;
|
||||
unsigned int ivar;
|
||||
#ifdef FDT
|
||||
phandle_t node;
|
||||
pcell_t cell;
|
||||
#endif
|
||||
|
||||
ns8250->busy_detect = 0;
|
||||
|
||||
#ifdef FDT
|
||||
/*
|
||||
* Check whether uart requires to read USR reg when IIR_BUSY and
|
||||
* has broken txfifo.
|
||||
*/
|
||||
node = ofw_bus_get_node(sc->sc_dev);
|
||||
if ((OF_getprop(node, "busy-detect", &cell, sizeof(cell))) > 0)
|
||||
ns8250->busy_detect = 1;
|
||||
if ((OF_getprop(node, "broken-txfifo", &cell, sizeof(cell))) > 0)
|
||||
broken_txfifo = 1;
|
||||
#endif
|
||||
|
||||
bas = &sc->sc_bas;
|
||||
|
||||
@ -592,6 +624,12 @@ ns8250_bus_ipend(struct uart_softc *sc)
|
||||
bas = &sc->sc_bas;
|
||||
uart_lock(sc->sc_hwmtx);
|
||||
iir = uart_getreg(bas, REG_IIR);
|
||||
|
||||
if (ns8250->busy_detect && (iir & IIR_BUSY) == IIR_BUSY) {
|
||||
(void)uart_getreg(bas, DW_REG_USR);
|
||||
uart_unlock(sc->sc_hwmtx);
|
||||
return (0);
|
||||
}
|
||||
if (iir & IIR_NOPEND) {
|
||||
uart_unlock(sc->sc_hwmtx);
|
||||
return (0);
|
||||
@ -847,11 +885,6 @@ ns8250_bus_setsig(struct uart_softc *sc, int sig)
|
||||
return (0);
|
||||
}
|
||||
|
||||
static int broken_txfifo = 0;
|
||||
SYSCTL_INT(_hw, OID_AUTO, broken_txfifo, CTLFLAG_RW | CTLFLAG_TUN,
|
||||
&broken_txfifo, 0, "UART FIFO has QEMU emulation bug");
|
||||
TUNABLE_INT("hw.broken_txfifo", &broken_txfifo);
|
||||
|
||||
static int
|
||||
ns8250_bus_transmit(struct uart_softc *sc)
|
||||
{
|
||||
|
Loading…
Reference in New Issue
Block a user