From patchwork Tue Sep 11 09:34:59 2012 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Anton Vorontsov X-Patchwork-Id: 11295 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 72D1223EFE for ; Tue, 11 Sep 2012 09:38:13 +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 1EA9EA18F23 for ; Tue, 11 Sep 2012 09:38:13 +0000 (UTC) Received: by mail-ie0-f180.google.com with SMTP id k11so513911iea.11 for ; Tue, 11 Sep 2012 02:38:12 -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:from:to:cc :subject:date:message-id:x-mailer:in-reply-to:references :x-gm-message-state; bh=aRw53y2DUQLq/WEZhkmOxrqPdPGN+BPYpiTzzYFcSCE=; b=IWpNjlUS/wpX/wLtlKz4DhKskJlUrfvJPN4elq6otGVg4RvhOsf9op9yKZEN2sjrsG oNSAAiYmryH8afo7K7JJcXf2l8fht2feVm+RJi1/FcQD9P82gO0zSqxQwN6Qz3R1NpvV qq1sSEltf02rcStVmyCCORt2JlQXYloFjUOBEpKMXAwWe6s0/4Md7lo/Lo55se+KzTj4 dAKVD/Qah5P9kRRjCY/4iH0cJY/jTPH1bGHYYDn2K5KSN4raUpSuW3fVUdPAcp0fpyCC HVdUmoNjTbgTRc9sZZFz1qcLW0OS5aYpQ3UIgpQ8nItiT5UbVkOv/ZP3Zw3TkuptJRGn cnrQ== Received: by 10.50.45.162 with SMTP id o2mr16108956igm.0.1347356292852; Tue, 11 Sep 2012 02:38:12 -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 ex8csp4774igc; Tue, 11 Sep 2012 02:38:12 -0700 (PDT) Received: by 10.66.75.228 with SMTP id f4mr26019935paw.52.1347356292200; Tue, 11 Sep 2012 02:38:12 -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 pn6si24191257pbb.160.2012.09.11.02.38.12 (version=TLSv1/SSLv3 cipher=OTHER); Tue, 11 Sep 2012 02:38:12 -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 md12so636245pbc.37 for ; Tue, 11 Sep 2012 02:38:12 -0700 (PDT) Received: by 10.68.234.7 with SMTP id ua7mr10702625pbc.91.1347356291853; Tue, 11 Sep 2012 02:38:11 -0700 (PDT) Received: from localhost (c-71-204-165-222.hsd1.ca.comcast.net. [71.204.165.222]) by mx.google.com with ESMTPS id os1sm3321493pbc.31.2012.09.11.02.38.10 (version=TLSv1/SSLv3 cipher=OTHER); Tue, 11 Sep 2012 02:38:11 -0700 (PDT) From: Anton Vorontsov To: Andrew Morton , Russell King , Jason Wessel , Greg Kroah-Hartman , Alan Cox Cc: =?UTF-8?q?Arve=20Hj=C3=B8nnev=C3=A5g?= , 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 05/12] tty/serial/amba-pl011: Implement poll_init callback Date: Tue, 11 Sep 2012 02:34:59 -0700 Message-Id: <1347356106-25368-5-git-send-email-anton.vorontsov@linaro.org> X-Mailer: git-send-email 1.7.11.5 In-Reply-To: <20120911093042.GA12471@lizard> References: <20120911093042.GA12471@lizard> X-Gm-Message-State: ALoCoQlbv4+iGQRMioQoYRgUm+JoMwrYXcmeVG+Dn9kB/WARLobLURPFRBnEyPTlEQFI7+zkyWaX 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 cede938..45137e4 100644 --- a/drivers/tty/serial/amba-pl011.c +++ b/drivers/tty/serial/amba-pl011.c @@ -1309,10 +1309,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 */ @@ -1337,6 +1336,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); @@ -1395,19 +1425,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; } @@ -1688,6 +1709,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