[PATCH V2] tty: serial: imx.c: Reset UART before activating interrupts

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



If the UART has been in use before this driver was loaded, IRQs might be
active and get fired as soon as we set the handler, which will crash
in the spin_lock_irqsave(&sport->port.lock, flags) because port.lock is
not initialized until the port is added at the end of probe.

Signed-off-by: David Jander <david@xxxxxxxxxxx>
---

Changes from V1:
 - Enable peripheral clock before attempting reset.

 drivers/tty/serial/imx.c | 36 +++++++++++++++++++++++++++---------
 1 file changed, 27 insertions(+), 9 deletions(-)

diff --git a/drivers/tty/serial/imx.c b/drivers/tty/serial/imx.c
index 54fdc78..fae0243 100644
--- a/drivers/tty/serial/imx.c
+++ b/drivers/tty/serial/imx.c
@@ -1093,10 +1093,23 @@ static void imx_disable_dma(struct imx_port *sport)
 /* half the RX buffer size */
 #define CTSTL 16
 
+static inline void imx_reset(struct imx_port *sport)
+{
+	int i = 100;
+	unsigned long temp;
+
+	temp = readl(sport->port.membase + UCR2);
+	temp &= ~UCR2_SRST;
+	writel(temp, sport->port.membase + UCR2);
+
+	while (!(readl(sport->port.membase + UCR2) & UCR2_SRST) && (--i > 0))
+		udelay(1);
+}
+
 static int imx_startup(struct uart_port *port)
 {
 	struct imx_port *sport = (struct imx_port *)port;
-	int retval, i;
+	int retval;
 	unsigned long flags, temp;
 
 	retval = clk_prepare_enable(sport->clk_per);
@@ -1123,14 +1136,7 @@ static int imx_startup(struct uart_port *port)
 
 	spin_lock_irqsave(&sport->port.lock, flags);
 	/* Reset fifo's and state machines */
-	i = 100;
-
-	temp = readl(sport->port.membase + UCR2);
-	temp &= ~UCR2_SRST;
-	writel(temp, sport->port.membase + UCR2);
-
-	while (!(readl(sport->port.membase + UCR2) & UCR2_SRST) && (--i > 0))
-		udelay(1);
+	imx_reset(sport);
 
 	/*
 	 * Finally, clear and enable interrupts
@@ -1957,6 +1963,18 @@ static int serial_imx_probe(struct platform_device *pdev)
 	sport->port.uartclk = clk_get_rate(sport->clk_per);
 
 	/*
+	 * Perform a complete reset of the UART device. Needed if we don't
+	 * come straight out of reset.
+	 */
+	ret = clk_prepare_enable(sport->clk_per);
+	if (ret)
+		return ret;
+	writel(0, sport->port.membase + UCR2);
+	writel(0, sport->port.membase + UCR1);
+	imx_reset(sport);
+	clk_disable_unprepare(sport->clk_per);
+
+	/*
 	 * Allocate the IRQ(s) i.MX1 has three interrupts whereas later
 	 * chips only have one interrupt.
 	 */
-- 
2.1.4

--
To unsubscribe from this list: send the line "unsubscribe linux-serial" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html



[Index of Archives]     [Kernel Newbies]     [Security]     [Netfilter]     [Bugtraq]     [Linux PPP]     [Linux FS]     [Yosemite News]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Samba]     [Video 4 Linux]     [Linmodem]     [Device Mapper]     [Linux Kernel for ARM]

  Powered by Linux