From patchwork Mon Sep 10 04:13:46 2012 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Anton Vorontsov X-Patchwork-Id: 11273 Return-Path: X-Original-To: patchwork@peony.canonical.com Delivered-To: patchwork@peony.canonical.com Received: from fiordland.canonical.com (fiordland.canonical.com [91.189.94.145]) by peony.canonical.com (Postfix) with ESMTP id D803E23F26 for ; Mon, 10 Sep 2012 04:16:21 +0000 (UTC) Received: from mail-ie0-f180.google.com (mail-ie0-f180.google.com [209.85.223.180]) by fiordland.canonical.com (Postfix) with ESMTP id 69A61A1831C for ; Mon, 10 Sep 2012 04:16:21 +0000 (UTC) Received: by mail-ie0-f180.google.com with SMTP id k11so2310032iea.11 for ; Sun, 09 Sep 2012 21:16:21 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20120113; h=x-forwarded-to:x-forwarded-for:delivered-to:received-spf:date:from :to:cc:subject:message-id:references:mime-version:content-type :content-disposition:in-reply-to:user-agent:x-gm-message-state; bh=uD55YE9cKprpyuRWLIjQw2LFqGssIsv+AC2N0vS6K8M=; b=JjwAQkPBciE5fM+0x8nLP0m2EPwTbOiADkUn0cwcMDsqg7NRL/oyIr4iBcgfemkchk akB5CttZcMOJ5FQlUV6y99PI9c/ZnRHPqFo5ZGyzM9wiMdJG0aP4Sa1Ya2Z1TS7T89aQ 7lSEUoWgKN2mmD59FJpgmg/HZ1rhVTPJpH2ou7GnFu2XSeVjBlpcZesNa6C8/MBboM+Q mgutgvdZOpBs6MGD4JZc+k7UHmtftUtdS9CRwOX/Co8SInqfycVyE4krBC+FoD0TpD6q OZU0Kzs8erdnAZfU2bPCMgRndWAFSsOjNrGhJtp4VFz2/ABPheFyEpNlcAOs7cq6fpyb 3/xQ== Received: by 10.50.45.162 with SMTP id o2mr9300154igm.0.1347250581189; Sun, 09 Sep 2012 21:16:21 -0700 (PDT) X-Forwarded-To: linaro-patchwork@canonical.com X-Forwarded-For: patch@linaro.org linaro-patchwork@canonical.com Delivered-To: patches@linaro.org Received: by 10.50.184.232 with SMTP id ex8csp72954igc; Sun, 9 Sep 2012 21:16:20 -0700 (PDT) Received: by 10.68.233.230 with SMTP id tz6mr3921607pbc.42.1347250580591; Sun, 09 Sep 2012 21:16:20 -0700 (PDT) Received: from mail-pb0-f50.google.com (mail-pb0-f50.google.com [209.85.160.50]) by mx.google.com with ESMTPS id nr4si12805903pbc.96.2012.09.09.21.16.20 (version=TLSv1/SSLv3 cipher=OTHER); Sun, 09 Sep 2012 21:16:20 -0700 (PDT) Received-SPF: neutral (google.com: 209.85.160.50 is neither permitted nor denied by best guess record for domain of anton.vorontsov@linaro.org) client-ip=209.85.160.50; Authentication-Results: mx.google.com; spf=neutral (google.com: 209.85.160.50 is neither permitted nor denied by best guess record for domain of anton.vorontsov@linaro.org) smtp.mail=anton.vorontsov@linaro.org Received: by mail-pb0-f50.google.com with SMTP id md12so2061699pbc.37 for ; Sun, 09 Sep 2012 21:16:20 -0700 (PDT) Received: by 10.68.237.3 with SMTP id uy3mr3855056pbc.30.1347250580289; Sun, 09 Sep 2012 21:16:20 -0700 (PDT) Received: from localhost (ip-64-134-230-8.public.wayport.net. [64.134.230.8]) by mx.google.com with ESMTPS id to6sm1259892pbc.12.2012.09.09.21.16.19 (version=TLSv1/SSLv3 cipher=OTHER); Sun, 09 Sep 2012 21:16:19 -0700 (PDT) Date: Sun, 9 Sep 2012 21:13:46 -0700 From: Anton Vorontsov To: Andrew Morton , Russell King , Jason Wessel , Greg Kroah-Hartman , Alan Cox Cc: Arve =?utf-8?B?SGrDuG5uZXbDpWc=?= , Colin Cross , Brian Swetland , John Stultz , linux-kernel@vger.kernel.org, linux-arm-kernel@lists.infradead.org, linaro-kernel@lists.linaro.org, patches@linaro.org, kernel-team@android.com, kgdb-bugreport@lists.sourceforge.net, linux-serial@vger.kernel.org Subject: [PATCH 07/14] tty/serial/amba-pl011: Implement poll_init callback Message-ID: <20120910041346.GG29537@lizard> References: <20120910040802.GA1261@lizard> MIME-Version: 1.0 Content-Disposition: inline In-Reply-To: <20120910040802.GA1261@lizard> User-Agent: Mutt/1.5.21 (2010-09-15) X-Gm-Message-State: ALoCoQkkJyoXacfTESfq+3LpHEbaNNFA6yk8iuLgz6NjcQp4eWvUR5+nrOpgW/V7iEOV7EO8cjEy The callback is used to initialize the hardware, nothing else should be done, i.e. we should not request interrupts (but we can and do unmask some of them, as they might be useful for NMI entry). As a side-effect, the patch also fixes a division by zero[1] when booting with kgdboc options specified (e.g. kgdboc=ttyAMA0,115200n8). The issue happens because serial core calls set_termios callback, but the driver doesn't know clock frequency, and thus cannot calculate proper baud rate values. [1] WARNING: at drivers/tty/serial/serial_core.c:400 uart_get_baud_rate+0xe8/0x14c() Modules linked in: [] (unwind_backtrace+0x0/0xf0) from [] (warn_slowpath_common+0x4c/0x64) [] (warn_slowpath_common+0x4c/0x64) from [] (warn_slowpath_null+0x1c/0x24) [] (warn_slowpath_null+0x1c/0x24) from [] (uart_get_baud_rate+0xe8/0x14c) [] (uart_get_baud_rate+0xe8/0x14c) from [] (pl011_set_termios+0x48/0x278) [] (pl011_set_termios+0x48/0x278) from [] (uart_set_options+0xe8/0x114) [] (uart_set_options+0xe8/0x114) from [] (uart_poll_init+0xd4/0xe0) [] (uart_poll_init+0xd4/0xe0) from [] (tty_find_polling_driver+0x100/0x17c) [] (tty_find_polling_driver+0x100/0x17c) from [] (configure_kgdboc+0xc8/0x1b8) [] (configure_kgdboc+0xc8/0x1b8) from [] (do_one_initcall+0x30/0x168) [] (do_one_initcall+0x30/0x168) from [] (do_basic_setup+0x94/0xc8) [] (do_basic_setup+0x94/0xc8) from [] (kernel_init+0x60/0xf4) [] (kernel_init+0x60/0xf4) from [] (kernel_thread_exit+0x0/0x8) ---[ end trace 7d41c9186f342c40 ]--- Division by zero in kernel. [] (unwind_backtrace+0x0/0xf0) from [] (Ldiv0+0x8/0x10) [] (Ldiv0+0x8/0x10) from [] (pl011_set_termios+0x68/0x278) [] (pl011_set_termios+0x68/0x278) from [] (uart_set_options+0xe8/0x114) [] (uart_set_options+0xe8/0x114) from [] (uart_poll_init+0xd4/0xe0) [] (uart_poll_init+0xd4/0xe0) from [] (tty_find_polling_driver+0x100/0x17c) [] (tty_find_polling_driver+0x100/0x17c) from [] (configure_kgdboc+0xc8/0x1b8) [] (configure_kgdboc+0xc8/0x1b8) from [] (do_one_initcall+0x30/0x168) [] (do_one_initcall+0x30/0x168) from [] (do_basic_setup+0x94/0xc8) [] (do_basic_setup+0x94/0xc8) from [] (kernel_init+0x60/0xf4) [] (kernel_init+0x60/0xf4) from [] (kernel_thread_exit+0x0/0x8) Division by zero in kernel. [] (unwind_backtrace+0x0/0xf0) from [] (Ldiv0+0x8/0x10) [] (Ldiv0+0x8/0x10) from [] (uart_update_timeout+0x4c/0x5c) [] (uart_update_timeout+0x4c/0x5c) from [] (pl011_set_termios+0xc8/0x278) [] (pl011_set_termios+0xc8/0x278) from [] (uart_set_options+0xe8/0x114) [] (uart_set_options+0xe8/0x114) from [] (uart_poll_init+0xd4/0xe0) [] (uart_poll_init+0xd4/0xe0) from [] (tty_find_polling_driver+0x100/0x17c) [] (tty_find_polling_driver+0x100/0x17c) from [] (configure_kgdboc+0xc8/0x1b8) [] (configure_kgdboc+0xc8/0x1b8) from [] (do_one_initcall+0x30/0x168) [] (do_one_initcall+0x30/0x168) from [] (do_basic_setup+0x94/0xc8) [] (do_basic_setup+0x94/0xc8) from [] (kernel_init+0x60/0xf4) [] (kernel_init+0x60/0xf4) from [] (kernel_thread_exit+0x0/0x8) Signed-off-by: Anton Vorontsov --- drivers/tty/serial/amba-pl011.c | 44 ++++++++++++++++++++++++++++++----------- 1 file changed, 33 insertions(+), 11 deletions(-) diff --git a/drivers/tty/serial/amba-pl011.c b/drivers/tty/serial/amba-pl011.c index 3322023..88e2df2 100644 --- a/drivers/tty/serial/amba-pl011.c +++ b/drivers/tty/serial/amba-pl011.c @@ -1310,10 +1310,9 @@ static void pl011_put_poll_char(struct uart_port *port, #endif /* CONFIG_CONSOLE_POLL */ -static int pl011_startup(struct uart_port *port) +static int pl011_hwinit(struct uart_port *port) { struct uart_amba_port *uap = (struct uart_amba_port *)port; - unsigned int cr; int retval; /* Optionaly enable pins to be muxed in and configured */ @@ -1338,6 +1337,37 @@ static int pl011_startup(struct uart_port *port) UART011_RTIS | UART011_RXIS, uap->port.membase + UART011_ICR); /* + * Save interrupts enable mask, and enable RX interrupts in case if + * the interrupt is used for NMI entry. + */ + uap->im = readw(uap->port.membase + UART011_IMSC); + writew(UART011_RTIM | UART011_RXIM, uap->port.membase + UART011_IMSC); + + if (uap->port.dev->platform_data) { + struct amba_pl011_data *plat; + + plat = uap->port.dev->platform_data; + if (plat->init) + plat->init(); + } + return 0; + out: + return retval; +} + +static int pl011_startup(struct uart_port *port) +{ + struct uart_amba_port *uap = (struct uart_amba_port *)port; + unsigned int cr; + int retval; + + retval = pl011_hwinit(port); + if (retval) + goto clk_dis; + + writew(uap->im, uap->port.membase + UART011_IMSC); + + /* * Allocate the IRQ */ retval = request_irq(uap->port.irq, pl011_int, 0, "uart-pl011", uap); @@ -1396,19 +1426,10 @@ static int pl011_startup(struct uart_port *port) writew(uap->im, uap->port.membase + UART011_IMSC); spin_unlock_irq(&uap->port.lock); - if (uap->port.dev->platform_data) { - struct amba_pl011_data *plat; - - plat = uap->port.dev->platform_data; - if (plat->init) - plat->init(); - } - return 0; clk_dis: clk_disable_unprepare(uap->clk); - out: return retval; } @@ -1689,6 +1710,7 @@ static struct uart_ops amba_pl011_pops = { .config_port = pl011_config_port, .verify_port = pl011_verify_port, #ifdef CONFIG_CONSOLE_POLL + .poll_init = pl011_hwinit, .poll_get_char = pl011_get_poll_char, .poll_put_char = pl011_put_poll_char, #endif