Skip to content

Commit

Permalink
tty: serial: imx.c: Reset UART before activating interrupts
Browse files Browse the repository at this point in the history
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@protonic.nl>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
  • Loading branch information
David Jander authored and Greg Kroah-Hartman committed Jul 24, 2015
1 parent e9b5a98 commit e95044b
Showing 1 changed file with 23 additions and 9 deletions.
32 changes: 23 additions & 9 deletions drivers/tty/serial/imx.c
Original file line number Diff line number Diff line change
Expand Up @@ -1098,10 +1098,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);
Expand Down Expand Up @@ -1133,14 +1146,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
Expand Down Expand Up @@ -1975,6 +1981,14 @@ static int serial_imx_probe(struct platform_device *pdev)

clk_disable_unprepare(sport->clk_ipg);

/*
* Perform a complete reset of the UART device. Needed if we don't
* come straight out of reset.
*/
writel(0, sport->port.membase + UCR2);
writel(0, sport->port.membase + UCR1);
imx_reset(sport);

/*
* Allocate the IRQ(s) i.MX1 has three interrupts whereas later
* chips only have one interrupt.
Expand Down

0 comments on commit e95044b

Please sign in to comment.