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: 1429611 Return-Path: X-Original-To: patchwork-linux-arm@patchwork.kernel.org Delivered-To: patchwork-process-083081@patchwork2.kernel.org Received: from merlin.infradead.org (merlin.infradead.org [205.233.59.134]) by patchwork2.kernel.org (Postfix) with ESMTP id 4C59DDF28C for ; Mon, 10 Sep 2012 04:20:04 +0000 (UTC) Received: from localhost ([::1] helo=merlin.infradead.org) by merlin.infradead.org with esmtp (Exim 4.76 #1 (Red Hat Linux)) id 1TAvQM-0002Lg-Qj; Mon, 10 Sep 2012 04:16:41 +0000 Received: from mail-pb0-f49.google.com ([209.85.160.49]) by merlin.infradead.org with esmtps (Exim 4.76 #1 (Red Hat Linux)) id 1TAvQ4-0001qa-Jr for linux-arm-kernel@lists.infradead.org; Mon, 10 Sep 2012 04:16:22 +0000 Received: by mail-pb0-f49.google.com with SMTP id rq8so2004197pbb.36 for ; Sun, 09 Sep 2012 21:16:20 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20120113; h=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=om/m6DJqO4f94jTmo/GDdz6PqDDYsIIrvNf5dP8BoVpMZYOGHaCEb+ioAe9Bimd45m HotGeciStka3QvDWNXjSgIdyW6s3LPZKQ15B5tDRm8XJZe93ettWd17tVqQ1wR55BB9X EklOJPnOF9yIopfmgCBHDz7rVfQr1OLRVBoGzcUF/ZJ52fGnMEdzphlaBjPORbrDnAtC RElPBgyyYalkwtGQvKCyzusbZmMTmeLiMvus0KBg4oxlCwRaHypX9qGztsWT2p7tATCK NjZXbFwb/44WUvU+n7oeYiqhBWTPBYUpec56YNU3wz2yC2hSXPtPrxPCEwRcEQnaLQ5y 1FUg== 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 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: ALoCoQn/SZjCZu2HmZcB40ZGGdWgOE6WTV45PBO8+t2AsWWv7lgU8jDIAP7F1YO5+fzbbcQj9+dR X-Spam-Note: CRM114 invocation failed X-Spam-Score: -2.6 (--) X-Spam-Report: SpamAssassin version 3.3.2 on merlin.infradead.org summary: Content analysis details: (-2.6 points) pts rule name description ---- ---------------------- -------------------------------------------------- -0.7 RCVD_IN_DNSWL_LOW RBL: Sender listed at http://www.dnswl.org/, low trust [209.85.160.49 listed in list.dnswl.org] -1.9 BAYES_00 BODY: Bayes spam probability is 0 to 1% [score: 0.0000] Cc: linaro-kernel@lists.linaro.org, patches@linaro.org, Brian Swetland , linux-kernel@vger.kernel.org, Arve =?utf-8?B?SGrDuG5uZXbDpWc=?= , John Stultz , linux-serial@vger.kernel.org, Colin Cross , kgdb-bugreport@lists.sourceforge.net, kernel-team@android.com, linux-arm-kernel@lists.infradead.org X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.14 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: linux-arm-kernel-bounces@lists.infradead.org Errors-To: linux-arm-kernel-bounces+patchwork-linux-arm=patchwork.kernel.org@lists.infradead.org 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