From patchwork Fri Jul 31 11:59:13 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: David Jander X-Patchwork-Id: 6910721 Return-Path: X-Original-To: patchwork-linux-arm@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork2.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.29.136]) by patchwork2.web.kernel.org (Postfix) with ESMTP id 7CEABC05AC for ; Fri, 31 Jul 2015 12:02:03 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id 95CB320611 for ; Fri, 31 Jul 2015 12:02:02 +0000 (UTC) Received: from bombadil.infradead.org (bombadil.infradead.org [198.137.202.9]) (using TLSv1.2 with cipher AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id 465B9205B7 for ; Fri, 31 Jul 2015 12:02:01 +0000 (UTC) Received: from localhost ([127.0.0.1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.80.1 #2 (Red Hat Linux)) id 1ZL8ym-0003hr-FB; Fri, 31 Jul 2015 12:00:00 +0000 Received: from protonic.xs4all.nl ([83.163.252.89]) by bombadil.infradead.org with esmtp (Exim 4.80.1 #2 (Red Hat Linux)) id 1ZL8yi-0003Sw-Ay for linux-arm-kernel@lists.infradead.org; Fri, 31 Jul 2015 11:59:58 +0000 Received: from archvile.prtnl (archvile.prtnl [192.168.1.153]) by protonic.xs4all.nl (Postfix) with ESMTP id 09BB32803E; Fri, 31 Jul 2015 13:53:08 +0200 (CEST) From: David Jander To: Sascha Hauer , Greg Kroah-Hartman , Fabio Estevam Subject: [PATCH V3] tty: serial: imx.c: Reset UART before activating interrupts Date: Fri, 31 Jul 2015 13:59:13 +0200 Message-Id: <1438343953-31679-1-git-send-email-david@protonic.nl> X-Mailer: git-send-email 2.1.4 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20150731_045956_700578_9C791B09 X-CRM114-Status: GOOD ( 13.26 ) X-Spam-Score: -1.9 (-) X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.20 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Tyler Baker , linux-arm-kernel@lists.infradead.org, "linux-serial@vger.kernel.org" , David Jander MIME-Version: 1.0 Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+patchwork-linux-arm=patchwork.kernel.org@lists.infradead.org X-Spam-Status: No, score=-5.6 required=5.0 tests=BAYES_00, RCVD_IN_DNSWL_MED, RP_MATCHES_RCVD, UNPARSEABLE_RELAY autolearn=unavailable version=3.3.1 X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on mail.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP 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 Tested-by: Fabio Estevam --- Changes from V2: - Also enable clk_ipg since it is not entirely clear if it is needed or not. Changes from V1: - Enable peripheral clock before attempting reset. drivers/tty/serial/imx.c | 42 +++++++++++++++++++++++++++++++++--------- 1 file changed, 33 insertions(+), 9 deletions(-) diff --git a/drivers/tty/serial/imx.c b/drivers/tty/serial/imx.c index 54fdc78..1eebc44 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,24 @@ 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; + ret = clk_prepare_enable(sport->clk_ipg); + if (ret) { + clk_disable_unprepare(sport->clk_per); + return ret; + } + writel(0, sport->port.membase + UCR2); + writel(0, sport->port.membase + UCR1); + imx_reset(sport); + clk_disable_unprepare(sport->clk_ipg); + clk_disable_unprepare(sport->clk_per); + + /* * Allocate the IRQ(s) i.MX1 has three interrupts whereas later * chips only have one interrupt. */