diff options
| author | Thor Thayer <tthayer@opensource.altera.com> | 2016-09-22 15:56:16 -0400 |
|---|---|---|
| committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2016-09-27 06:55:50 -0400 |
| commit | 8e5470c9839caff94fe334e67ff7e7ace587282a (patch) | |
| tree | d96d839061310f9c2e94f7fc24fc906d338f4d01 /drivers/tty/serial | |
| parent | ffea043965e4634617485b4d313d6c0099d817f0 (diff) | |
serial: 8250: Set Altera 16550 TX FIFO Threshold
The Altera 16550 soft IP UART requires 2 additional registers for
TX FIFO threshold support. These 2 registers enable the TX FIFO
Low Watermark and set the TX FIFO Low Watermark.
Set the TX FIFO threshold to the FIFO size - tx_loadsz.
Signed-off-by: Thor Thayer <tthayer@opensource.altera.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'drivers/tty/serial')
| -rw-r--r-- | drivers/tty/serial/8250/8250_port.c | 43 |
1 files changed, 43 insertions, 0 deletions
diff --git a/drivers/tty/serial/8250/8250_port.c b/drivers/tty/serial/8250/8250_port.c index 28d29fac1973..1bfb6fdbaa20 100644 --- a/drivers/tty/serial/8250/8250_port.c +++ b/drivers/tty/serial/8250/8250_port.c | |||
| @@ -1870,6 +1870,30 @@ static int exar_handle_irq(struct uart_port *port) | |||
| 1870 | return ret; | 1870 | return ret; |
| 1871 | } | 1871 | } |
| 1872 | 1872 | ||
| 1873 | /* | ||
| 1874 | * Newer 16550 compatible parts such as the SC16C650 & Altera 16550 Soft IP | ||
| 1875 | * have a programmable TX threshold that triggers the THRE interrupt in | ||
| 1876 | * the IIR register. In this case, the THRE interrupt indicates the FIFO | ||
| 1877 | * has space available. Load it up with tx_loadsz bytes. | ||
| 1878 | */ | ||
| 1879 | static int serial8250_tx_threshold_handle_irq(struct uart_port *port) | ||
| 1880 | { | ||
| 1881 | unsigned long flags; | ||
| 1882 | unsigned int iir = serial_port_in(port, UART_IIR); | ||
| 1883 | |||
| 1884 | /* TX Threshold IRQ triggered so load up FIFO */ | ||
| 1885 | if ((iir & UART_IIR_ID) == UART_IIR_THRI) { | ||
| 1886 | struct uart_8250_port *up = up_to_u8250p(port); | ||
| 1887 | |||
| 1888 | spin_lock_irqsave(&port->lock, flags); | ||
| 1889 | serial8250_tx_chars(up); | ||
| 1890 | spin_unlock_irqrestore(&port->lock, flags); | ||
| 1891 | } | ||
| 1892 | |||
| 1893 | iir = serial_port_in(port, UART_IIR); | ||
| 1894 | return serial8250_handle_irq(port, iir); | ||
| 1895 | } | ||
| 1896 | |||
| 1873 | static unsigned int serial8250_tx_empty(struct uart_port *port) | 1897 | static unsigned int serial8250_tx_empty(struct uart_port *port) |
| 1874 | { | 1898 | { |
| 1875 | struct uart_8250_port *up = up_to_u8250p(port); | 1899 | struct uart_8250_port *up = up_to_u8250p(port); |
| @@ -2159,6 +2183,25 @@ int serial8250_do_startup(struct uart_port *port) | |||
| 2159 | serial_port_out(port, UART_LCR, 0); | 2183 | serial_port_out(port, UART_LCR, 0); |
| 2160 | } | 2184 | } |
| 2161 | 2185 | ||
| 2186 | /* | ||
| 2187 | * For the Altera 16550 variants, set TX threshold trigger level. | ||
| 2188 | */ | ||
| 2189 | if (((port->type == PORT_ALTR_16550_F32) || | ||
| 2190 | (port->type == PORT_ALTR_16550_F64) || | ||
| 2191 | (port->type == PORT_ALTR_16550_F128)) && (port->fifosize > 1)) { | ||
| 2192 | /* Bounds checking of TX threshold (valid 0 to fifosize-2) */ | ||
| 2193 | if ((up->tx_loadsz < 2) || (up->tx_loadsz > port->fifosize)) { | ||
| 2194 | pr_err("ttyS%d TX FIFO Threshold errors, skipping\n", | ||
| 2195 | serial_index(port)); | ||
| 2196 | } else { | ||
| 2197 | serial_port_out(port, UART_ALTR_AFR, | ||
| 2198 | UART_ALTR_EN_TXFIFO_LW); | ||
| 2199 | serial_port_out(port, UART_ALTR_TX_LOW, | ||
| 2200 | port->fifosize - up->tx_loadsz); | ||
| 2201 | port->handle_irq = serial8250_tx_threshold_handle_irq; | ||
| 2202 | } | ||
| 2203 | } | ||
| 2204 | |||
| 2162 | if (port->irq) { | 2205 | if (port->irq) { |
| 2163 | unsigned char iir1; | 2206 | unsigned char iir1; |
| 2164 | /* | 2207 | /* |
