diff options
Diffstat (limited to 'drivers/tty/serial/xilinx_uartps.c')
-rw-r--r-- | drivers/tty/serial/xilinx_uartps.c | 37 |
1 files changed, 21 insertions, 16 deletions
diff --git a/drivers/tty/serial/xilinx_uartps.c b/drivers/tty/serial/xilinx_uartps.c index 605354fd60b1..f145946f659b 100644 --- a/drivers/tty/serial/xilinx_uartps.c +++ b/drivers/tty/serial/xilinx_uartps.c @@ -26,21 +26,23 @@ #include <linux/of.h> #include <linux/module.h> #include <linux/pm_runtime.h> +#include <linux/iopoll.h> #define CDNS_UART_TTY_NAME "ttyPS" #define CDNS_UART_NAME "xuartps" -#define CDNS_UART_MAJOR 0 /* use dynamic node allocation */ #define CDNS_UART_FIFO_SIZE 64 /* FIFO size */ #define CDNS_UART_REGISTER_SPACE 0x1000 +#define TX_TIMEOUT 500000 /* Rx Trigger level */ static int rx_trigger_level = 56; -module_param(rx_trigger_level, uint, S_IRUGO); +static int uartps_major; +module_param(rx_trigger_level, uint, 0444); MODULE_PARM_DESC(rx_trigger_level, "Rx trigger level, 1-63 bytes"); /* Rx Timeout */ static int rx_timeout = 10; -module_param(rx_timeout, uint, S_IRUGO); +module_param(rx_timeout, uint, 0444); MODULE_PARM_DESC(rx_timeout, "Rx timeout, 1-255"); /* Register offsets for the UART. */ @@ -199,7 +201,7 @@ struct cdns_platform_data { u32 quirks; }; #define to_cdns_uart(_nb) container_of(_nb, struct cdns_uart, \ - clk_rate_change_nb); + clk_rate_change_nb) /** * cdns_uart_handle_rx - Handle the received bytes along with Rx errors. @@ -312,15 +314,16 @@ static void cdns_uart_handle_tx(void *dev_id) } else { numbytes = port->fifosize; while (numbytes && !uart_circ_empty(&port->state->xmit) && - !(readl(port->membase + CDNS_UART_SR) & CDNS_UART_SR_TXFULL)) { + !(readl(port->membase + CDNS_UART_SR) & + CDNS_UART_SR_TXFULL)) { /* * Get the data from the UART circular buffer * and write it to the cdns_uart's TX_FIFO * register. */ writel( - port->state->xmit.buf[port->state->xmit. - tail], port->membase + CDNS_UART_FIFO); + port->state->xmit.buf[port->state->xmit.tail], + port->membase + CDNS_UART_FIFO); port->icount.tx++; @@ -684,18 +687,21 @@ static void cdns_uart_set_termios(struct uart_port *port, unsigned int cval = 0; unsigned int baud, minbaud, maxbaud; unsigned long flags; - unsigned int ctrl_reg, mode_reg; - - spin_lock_irqsave(&port->lock, flags); + unsigned int ctrl_reg, mode_reg, val; + int err; /* Wait for the transmit FIFO to empty before making changes */ if (!(readl(port->membase + CDNS_UART_CR) & CDNS_UART_CR_TX_DIS)) { - while (!(readl(port->membase + CDNS_UART_SR) & - CDNS_UART_SR_TXEMPTY)) { - cpu_relax(); + err = readl_poll_timeout(port->membase + CDNS_UART_SR, + val, (val & CDNS_UART_SR_TXEMPTY), + 1000, TX_TIMEOUT); + if (err) { + dev_err(port->dev, "timed out waiting for tx empty"); + return; } } + spin_lock_irqsave(&port->lock, flags); /* Disable the TX and RX to set baud rate */ ctrl_reg = readl(port->membase + CDNS_UART_CR); @@ -1073,8 +1079,6 @@ static void cdns_uart_poll_put_char(struct uart_port *port, unsigned char c) cpu_relax(); spin_unlock_irqrestore(&port->lock, flags); - - return; } #endif @@ -1517,7 +1521,7 @@ static int cdns_uart_probe(struct platform_device *pdev) cdns_uart_uart_driver->owner = THIS_MODULE; cdns_uart_uart_driver->driver_name = driver_name; cdns_uart_uart_driver->dev_name = CDNS_UART_TTY_NAME; - cdns_uart_uart_driver->major = CDNS_UART_MAJOR; + cdns_uart_uart_driver->major = uartps_major; cdns_uart_uart_driver->minor = cdns_uart_data->id; cdns_uart_uart_driver->nr = 1; @@ -1546,6 +1550,7 @@ static int cdns_uart_probe(struct platform_device *pdev) goto err_out_id; } + uartps_major = cdns_uart_uart_driver->tty_driver->major; cdns_uart_data->cdns_uart_driver = cdns_uart_uart_driver; /* |