summaryrefslogtreecommitdiffstats
path: root/drivers/tty/serial/imx.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/tty/serial/imx.c')
-rw-r--r--drivers/tty/serial/imx.c47
1 files changed, 44 insertions, 3 deletions
diff --git a/drivers/tty/serial/imx.c b/drivers/tty/serial/imx.c
index 8cdfbd36589..415cec62073 100644
--- a/drivers/tty/serial/imx.c
+++ b/drivers/tty/serial/imx.c
@@ -201,6 +201,7 @@ struct imx_port {
unsigned int old_status;
int txirq, rxirq, rtsirq;
unsigned int have_rtscts:1;
+ unsigned int dte_mode:1;
unsigned int use_irda:1;
unsigned int irda_inv_rx:1;
unsigned int irda_inv_tx:1;
@@ -271,6 +272,7 @@ static inline int is_imx21_uart(struct imx_port *sport)
/*
* Save and restore functions for UCR1, UCR2 and UCR3 registers
*/
+#if defined(CONFIG_CONSOLE_POLL) || defined(CONFIG_SERIAL_IMX_CONSOLE)
static void imx_port_ucrs_save(struct uart_port *port,
struct imx_port_ucrs *ucr)
{
@@ -288,6 +290,7 @@ static void imx_port_ucrs_restore(struct uart_port *port,
writel(ucr->ucr2, port->membase + UCR2);
writel(ucr->ucr3, port->membase + UCR3);
}
+#endif
/*
* Handle any change of modem status signal since we were last called.
@@ -449,6 +452,13 @@ static void imx_start_tx(struct uart_port *port)
temp &= ~(UCR1_RRDYEN);
writel(temp, sport->port.membase + UCR1);
}
+ /* Clear any pending ORE flag before enabling interrupt */
+ temp = readl(sport->port.membase + USR2);
+ writel(temp | USR2_ORE, sport->port.membase + USR2);
+
+ temp = readl(sport->port.membase + UCR4);
+ temp |= UCR4_OREN;
+ writel(temp, sport->port.membase + UCR4);
temp = readl(sport->port.membase + UCR1);
writel(temp | UCR1_TXMPTYEN, sport->port.membase + UCR1);
@@ -582,6 +592,7 @@ static irqreturn_t imx_int(int irq, void *dev_id)
{
struct imx_port *sport = dev_id;
unsigned int sts;
+ unsigned int sts2;
sts = readl(sport->port.membase + USR1);
@@ -598,6 +609,13 @@ static irqreturn_t imx_int(int irq, void *dev_id)
if (sts & USR1_AWAKE)
writel(USR1_AWAKE, sport->port.membase + USR1);
+ sts2 = readl(sport->port.membase + USR2);
+ if (sts2 & USR2_ORE) {
+ dev_err(sport->port.dev, "Rx FIFO overrun\n");
+ sport->port.icount.overrun++;
+ writel(sts2 | USR2_ORE, sport->port.membase + USR2);
+ }
+
return IRQ_HANDLED;
}
@@ -684,6 +702,17 @@ static int imx_startup(struct uart_port *port)
int retval;
unsigned long flags, temp;
+ if (!uart_console(port)) {
+ retval = clk_prepare_enable(sport->clk_per);
+ if (retval)
+ goto error_out1;
+ retval = clk_prepare_enable(sport->clk_ipg);
+ if (retval) {
+ clk_disable_unprepare(sport->clk_per);
+ goto error_out1;
+ }
+ }
+
imx_setup_ufcr(sport, 0);
/* disable the DREN bit (Data Ready interrupt enable) before
@@ -871,6 +900,11 @@ static void imx_shutdown(struct uart_port *port)
writel(temp, sport->port.membase + UCR1);
spin_unlock_irqrestore(&sport->port.lock, flags);
+
+ if (!uart_console(&sport->port)) {
+ clk_disable_unprepare(sport->clk_per);
+ clk_disable_unprepare(sport->clk_ipg);
+ }
}
static void
@@ -1007,6 +1041,8 @@ imx_set_termios(struct uart_port *port, struct ktermios *termios,
ufcr = readl(sport->port.membase + UFCR);
ufcr = (ufcr & (~UFCR_RFDIV)) | UFCR_RFDIV_REG(div);
+ if (sport->dte_mode)
+ ufcr |= UFCR_DCEDTE;
writel(ufcr, sport->port.membase + UFCR);
writel(num, sport->port.membase + UBIR);
@@ -1431,6 +1467,9 @@ static int serial_imx_probe_dt(struct imx_port *sport,
if (of_get_property(np, "fsl,irda-mode", NULL))
sport->use_irda = 1;
+ if (of_get_property(np, "fsl,dte-mode", NULL))
+ sport->dte_mode = 1;
+
sport->devdata = of_id->data;
return 0;
@@ -1544,6 +1583,11 @@ static int serial_imx_probe(struct platform_device *pdev)
goto deinit;
platform_set_drvdata(pdev, sport);
+ if (!uart_console(&sport->port)) {
+ clk_disable_unprepare(sport->clk_per);
+ clk_disable_unprepare(sport->clk_ipg);
+ }
+
return 0;
deinit:
if (pdata && pdata->exit)
@@ -1565,9 +1609,6 @@ static int serial_imx_remove(struct platform_device *pdev)
uart_remove_one_port(&imx_reg, &sport->port);
- clk_disable_unprepare(sport->clk_per);
- clk_disable_unprepare(sport->clk_ipg);
-
if (pdata && pdata->exit)
pdata->exit(pdev);