tty: amba-pl011: define flag register bits for ZTE device
For some reason we do not really understand, ZTE hardware designers choose to define PL011 Flag Register bit positions differently from standard ones as below. Bit Standard ZTE ----------------------------------- CTS 0 1 DSR 1 3 BUSY 3 8 RI 8 0 Let's define these bits into vendor data and get ZTE PL011 supported properly. Signed-off-by: Shawn Guo <shawn.guo@linaro.org> Acked-by: Russell King <rmk+kernel@armlinux.org.uk> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
This commit is contained in:
parent
694d0d0bb2
commit
0e125a5fac
|
@ -93,6 +93,10 @@ static u16 pl011_std_offsets[REG_ARRAY_SIZE] = {
|
|||
struct vendor_data {
|
||||
const u16 *reg_offset;
|
||||
unsigned int ifls;
|
||||
unsigned int fr_busy;
|
||||
unsigned int fr_dsr;
|
||||
unsigned int fr_cts;
|
||||
unsigned int fr_ri;
|
||||
bool access_32b;
|
||||
bool oversampling;
|
||||
bool dma_threshold;
|
||||
|
@ -111,6 +115,10 @@ static unsigned int get_fifosize_arm(struct amba_device *dev)
|
|||
static struct vendor_data vendor_arm = {
|
||||
.reg_offset = pl011_std_offsets,
|
||||
.ifls = UART011_IFLS_RX4_8|UART011_IFLS_TX4_8,
|
||||
.fr_busy = UART01x_FR_BUSY,
|
||||
.fr_dsr = UART01x_FR_DSR,
|
||||
.fr_cts = UART01x_FR_CTS,
|
||||
.fr_ri = UART011_FR_RI,
|
||||
.oversampling = false,
|
||||
.dma_threshold = false,
|
||||
.cts_event_workaround = false,
|
||||
|
@ -121,6 +129,10 @@ static struct vendor_data vendor_arm = {
|
|||
|
||||
static struct vendor_data vendor_sbsa = {
|
||||
.reg_offset = pl011_std_offsets,
|
||||
.fr_busy = UART01x_FR_BUSY,
|
||||
.fr_dsr = UART01x_FR_DSR,
|
||||
.fr_cts = UART01x_FR_CTS,
|
||||
.fr_ri = UART011_FR_RI,
|
||||
.access_32b = true,
|
||||
.oversampling = false,
|
||||
.dma_threshold = false,
|
||||
|
@ -164,6 +176,10 @@ static unsigned int get_fifosize_st(struct amba_device *dev)
|
|||
static struct vendor_data vendor_st = {
|
||||
.reg_offset = pl011_st_offsets,
|
||||
.ifls = UART011_IFLS_RX_HALF|UART011_IFLS_TX_HALF,
|
||||
.fr_busy = UART01x_FR_BUSY,
|
||||
.fr_dsr = UART01x_FR_DSR,
|
||||
.fr_cts = UART01x_FR_CTS,
|
||||
.fr_ri = UART011_FR_RI,
|
||||
.oversampling = true,
|
||||
.dma_threshold = true,
|
||||
.cts_event_workaround = true,
|
||||
|
@ -192,6 +208,10 @@ static struct vendor_data vendor_zte __maybe_unused = {
|
|||
.reg_offset = pl011_zte_offsets,
|
||||
.access_32b = true,
|
||||
.ifls = UART011_IFLS_RX4_8|UART011_IFLS_TX4_8,
|
||||
.fr_busy = ZX_UART01x_FR_BUSY,
|
||||
.fr_dsr = ZX_UART01x_FR_DSR,
|
||||
.fr_cts = ZX_UART01x_FR_CTS,
|
||||
.fr_ri = ZX_UART011_FR_RI,
|
||||
.get_fifosize = get_fifosize_arm,
|
||||
};
|
||||
|
||||
|
@ -1167,7 +1187,7 @@ static void pl011_dma_shutdown(struct uart_amba_port *uap)
|
|||
return;
|
||||
|
||||
/* Disable RX and TX DMA */
|
||||
while (pl011_read(uap, REG_FR) & UART01x_FR_BUSY)
|
||||
while (pl011_read(uap, REG_FR) & uap->vendor->fr_busy)
|
||||
cpu_relax();
|
||||
|
||||
spin_lock_irq(&uap->port.lock);
|
||||
|
@ -1416,11 +1436,12 @@ static void pl011_modem_status(struct uart_amba_port *uap)
|
|||
if (delta & UART01x_FR_DCD)
|
||||
uart_handle_dcd_change(&uap->port, status & UART01x_FR_DCD);
|
||||
|
||||
if (delta & UART01x_FR_DSR)
|
||||
if (delta & uap->vendor->fr_dsr)
|
||||
uap->port.icount.dsr++;
|
||||
|
||||
if (delta & UART01x_FR_CTS)
|
||||
uart_handle_cts_change(&uap->port, status & UART01x_FR_CTS);
|
||||
if (delta & uap->vendor->fr_cts)
|
||||
uart_handle_cts_change(&uap->port,
|
||||
status & uap->vendor->fr_cts);
|
||||
|
||||
wake_up_interruptible(&uap->port.state->port.delta_msr_wait);
|
||||
}
|
||||
|
@ -1493,7 +1514,8 @@ static unsigned int pl011_tx_empty(struct uart_port *port)
|
|||
struct uart_amba_port *uap =
|
||||
container_of(port, struct uart_amba_port, port);
|
||||
unsigned int status = pl011_read(uap, REG_FR);
|
||||
return status & (UART01x_FR_BUSY|UART01x_FR_TXFF) ? 0 : TIOCSER_TEMT;
|
||||
return status & (uap->vendor->fr_busy | UART01x_FR_TXFF) ?
|
||||
0 : TIOCSER_TEMT;
|
||||
}
|
||||
|
||||
static unsigned int pl011_get_mctrl(struct uart_port *port)
|
||||
|
@ -1508,9 +1530,9 @@ static unsigned int pl011_get_mctrl(struct uart_port *port)
|
|||
result |= tiocmbit
|
||||
|
||||
TIOCMBIT(UART01x_FR_DCD, TIOCM_CAR);
|
||||
TIOCMBIT(UART01x_FR_DSR, TIOCM_DSR);
|
||||
TIOCMBIT(UART01x_FR_CTS, TIOCM_CTS);
|
||||
TIOCMBIT(UART011_FR_RI, TIOCM_RNG);
|
||||
TIOCMBIT(uap->vendor->fr_dsr, TIOCM_DSR);
|
||||
TIOCMBIT(uap->vendor->fr_cts, TIOCM_CTS);
|
||||
TIOCMBIT(uap->vendor->fr_ri, TIOCM_RNG);
|
||||
#undef TIOCMBIT
|
||||
return result;
|
||||
}
|
||||
|
@ -2191,7 +2213,7 @@ pl011_console_write(struct console *co, const char *s, unsigned int count)
|
|||
* Finally, wait for transmitter to become empty
|
||||
* and restore the TCR
|
||||
*/
|
||||
while (pl011_read(uap, REG_FR) & UART01x_FR_BUSY)
|
||||
while (pl011_read(uap, REG_FR) & uap->vendor->fr_busy)
|
||||
cpu_relax();
|
||||
if (!uap->vendor->always_enabled)
|
||||
pl011_write(old_cr, uap, REG_CR);
|
||||
|
@ -2303,13 +2325,16 @@ static struct console amba_console = {
|
|||
|
||||
static void pl011_putc(struct uart_port *port, int c)
|
||||
{
|
||||
struct uart_amba_port *uap =
|
||||
container_of(port, struct uart_amba_port, port);
|
||||
|
||||
while (readl(port->membase + UART01x_FR) & UART01x_FR_TXFF)
|
||||
cpu_relax();
|
||||
if (port->iotype == UPIO_MEM32)
|
||||
writel(c, port->membase + UART01x_DR);
|
||||
else
|
||||
writeb(c, port->membase + UART01x_DR);
|
||||
while (readl(port->membase + UART01x_FR) & UART01x_FR_BUSY)
|
||||
while (readl(port->membase + UART01x_FR) & uap->vendor->fr_busy)
|
||||
cpu_relax();
|
||||
}
|
||||
|
||||
|
|
|
@ -104,6 +104,15 @@
|
|||
#define UART01x_FR_CTS 0x001
|
||||
#define UART01x_FR_TMSK (UART01x_FR_TXFF + UART01x_FR_BUSY)
|
||||
|
||||
/*
|
||||
* Some bits of Flag Register on ZTE device have different position from
|
||||
* standard ones.
|
||||
*/
|
||||
#define ZX_UART01x_FR_BUSY 0x100
|
||||
#define ZX_UART01x_FR_DSR 0x008
|
||||
#define ZX_UART01x_FR_CTS 0x002
|
||||
#define ZX_UART011_FR_RI 0x001
|
||||
|
||||
#define UART011_CR_CTSEN 0x8000 /* CTS hardware flow control */
|
||||
#define UART011_CR_RTSEN 0x4000 /* RTS hardware flow control */
|
||||
#define UART011_CR_OUT2 0x2000 /* OUT2 */
|
||||
|
|
Loading…
Reference in a new issue