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:
Ganbold Tsagaankhuu 2013-03-01 01:42:31 +00:00
parent 4cf5de800c
commit ac4adddf04
2 changed files with 39 additions and 5 deletions

View File

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

View File

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