From patchwork Tue Jan 27 01:27:09 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Simon Glass X-Patchwork-Id: 433131 X-Patchwork-Delegate: sjg@chromium.org Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from theia.denx.de (theia.denx.de [85.214.87.163]) by ozlabs.org (Postfix) with ESMTP id 006971401DD for ; Tue, 27 Jan 2015 12:27:56 +1100 (AEDT) Received: from localhost (localhost [127.0.0.1]) by theia.denx.de (Postfix) with ESMTP id B8D9F4B632; Tue, 27 Jan 2015 02:27:55 +0100 (CET) Received: from theia.denx.de ([127.0.0.1]) by localhost (theia.denx.de [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id xiaNO7ANHzcK; Tue, 27 Jan 2015 02:27:55 +0100 (CET) Received: from theia.denx.de (localhost [127.0.0.1]) by theia.denx.de (Postfix) with ESMTP id E43FB4B615; Tue, 27 Jan 2015 02:27:54 +0100 (CET) Received: from localhost (localhost [127.0.0.1]) by theia.denx.de (Postfix) with ESMTP id B0ED14B62B for ; Tue, 27 Jan 2015 02:27:40 +0100 (CET) Received: from theia.denx.de ([127.0.0.1]) by localhost (theia.denx.de [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id oEOqvllrYg4X for ; Tue, 27 Jan 2015 02:27:40 +0100 (CET) X-policyd-weight: NOT_IN_SBL_XBL_SPAMHAUS=-1.5 NOT_IN_SPAMCOP=-1.5 NOT_IN_BL_NJABL=-1.5 (only DNSBL check requested) Received: from mail-qc0-f202.google.com (mail-qc0-f202.google.com [209.85.216.202]) by theia.denx.de (Postfix) with ESMTPS id E4A834B657 for ; Tue, 27 Jan 2015 02:27:33 +0100 (CET) Received: by mail-qc0-f202.google.com with SMTP id r5so927600qcx.1 for ; Mon, 26 Jan 2015 17:27:32 -0800 (PST) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=mzqYnjKnkNKAb/SeDajltznRmY50Gz8NK3FvTNWn0Xk=; b=WmvYa3mnB0I4iS08O7X2410mSXws/Nl1BcXiyuzqrYexhVUpNaj0JUYNnyw+fz0KUw vE4+ksUR3e82b0cG+wt3QtparqHVZX6c1O4W8jJ0s8dkF2CxLHVyIBCO+DK/4nPL/50/ tDFOUPLeHwF5kYfFjlHsKCngDCaxF5nkop+10vT/pqNIVjWBbx//khQ8UiJdypo+sugT i4rs7G6B1P5nhTWa1ywMjIqw4/ybnpW0qgsCMBGDHwzfq+MuaWpRATjCqLqgqChBRHEi 0HwM4yIP0zKiRsY1KxXUY38IdOExUf6Zwe+nipbG8k+4PwL6wm11I/5tbB2CXgoGifP+ GG8w== X-Gm-Message-State: ALoCoQlGEX9DB/QhmrA6X1jR/ex2ehLpMuQMYoViaXTgSWyMOiG2RyJ74ynZhTiRBKK5AFf/muOR X-Received: by 10.236.31.97 with SMTP id l61mr19390522yha.10.1422322052355; Mon, 26 Jan 2015 17:27:32 -0800 (PST) Received: from corpmail-nozzle1-1.hot.corp.google.com ([100.108.1.104]) by gmr-mx.google.com with ESMTPS id v10si1807905qcf.3.2015.01.26.17.27.31 (version=TLSv1.2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Mon, 26 Jan 2015 17:27:32 -0800 (PST) Received: from kaki.bld.corp.google.com ([172.29.216.32]) by corpmail-nozzle1-1.hot.corp.google.com with ESMTP id v4IAgDWl.1; Mon, 26 Jan 2015 17:27:32 -0800 Received: by kaki.bld.corp.google.com (Postfix, from userid 121222) id 408A72204BE; Mon, 26 Jan 2015 18:27:31 -0700 (MST) From: Simon Glass To: U-Boot Mailing List Date: Mon, 26 Jan 2015 18:27:09 -0700 Message-Id: <1422322036-9910-4-git-send-email-sjg@chromium.org> X-Mailer: git-send-email 2.2.0.rc0.207.ga3a616c In-Reply-To: <1422322036-9910-1-git-send-email-sjg@chromium.org> References: <1422322036-9910-1-git-send-email-sjg@chromium.org> Cc: WingMan Kwok , Sandeep Nair , Gregoire Gentil Subject: [U-Boot] [PATCH v2 3/3] serial: ns16550: Support debug UART X-BeenThere: u-boot@lists.denx.de X-Mailman-Version: 2.1.13 Precedence: list List-Id: U-Boot discussion List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Sender: u-boot-bounces@lists.denx.de Errors-To: u-boot-bounces@lists.denx.de Add debug UART functions to permit ns16550 to provide an early debug UART. Try to avoid using the stack so that this can be called from assembler before a stack is set up (at least on ARM and PowerPC). Signed-off-by: Simon Glass --- Changes in v2: - Split series out on its own - Add x86 support (asmlinkage, so it still needs a stack at present) - Add better cover letter drivers/serial/Kconfig | 13 +++++++++++++ drivers/serial/ns16550.c | 50 ++++++++++++++++++++++++++++++++++++++++++++++-- 2 files changed, 61 insertions(+), 2 deletions(-) diff --git a/drivers/serial/Kconfig b/drivers/serial/Kconfig index 268bb42..9d0d4c3 100644 --- a/drivers/serial/Kconfig +++ b/drivers/serial/Kconfig @@ -31,6 +31,19 @@ config DEBUG_UART serial drivers are up and running (done in serial_init()). Otherwise the drivers may conflict and you will get strange output. +choice + prompt "Select which UART will provide the debug UART" + depends on DEBUG_UART + +config DEBUG_UART_NS16550 + bool "ns16550" + help + Select this to enable a debug UART using the ns16550 driver. You + will need to provide parameters to make this work. The driver will + be available until the real driver model serial is running. + +endchoice + config DEBUG_UART_BASE hex "Base address of UART" depends on DEBUG_UART diff --git a/drivers/serial/ns16550.c b/drivers/serial/ns16550.c index 57e6125..eb00f1c 100644 --- a/drivers/serial/ns16550.c +++ b/drivers/serial/ns16550.c @@ -118,10 +118,15 @@ static int ns16550_readb(NS16550_t port, int offset) ns16550_readb(com_port, addr - (unsigned char *)com_port) #endif -int ns16550_calc_divisor(NS16550_t port, int clock, int baudrate) +static inline int calc_divisor(NS16550_t port, int clock, int baudrate) { const unsigned int mode_x_div = 16; + return DIV_ROUND_CLOSEST(clock, mode_x_div * baudrate); +} + +int ns16550_calc_divisor(NS16550_t port, int clock, int baudrate) +{ #ifdef CONFIG_OMAP1510 /* If can't cleanly clock 115200 set div to 1 */ if ((clock == 12000000) && (baudrate == 115200)) { @@ -131,7 +136,7 @@ int ns16550_calc_divisor(NS16550_t port, int clock, int baudrate) port->osc_12m_sel = 0; /* clear if previsouly set */ #endif - return DIV_ROUND_CLOSEST(clock, mode_x_div * baudrate); + return calc_divisor(port, clock, baudrate); } static void NS16550_setbrg(NS16550_t com_port, int baud_divisor) @@ -231,6 +236,47 @@ int NS16550_tstc(NS16550_t com_port) #endif /* CONFIG_NS16550_MIN_FUNCTIONS */ +#ifdef CONFIG_DEBUG_UART_NS16550 + +#include + +void debug_uart_init(void) +{ + struct NS16550 *com_port = (struct NS16550 *)CONFIG_DEBUG_UART_BASE; + int baud_divisor; + + /* + * We copy the code from above because it is already horribly messy. + * Trying to refactor to nicely remove the duplication doesn't seem + * feasible. The better fix is to move all users of this driver to + * driver model. + */ + baud_divisor = calc_divisor(com_port, CONFIG_DEBUG_UART_CLOCK, + CONFIG_BAUDRATE); + + serial_out_shift(&com_port->ier, 0, CONFIG_SYS_NS16550_IER); + serial_out_shift(&com_port->mcr, 0, UART_MCRVAL); + serial_out_shift(&com_port->fcr, 0, UART_FCRVAL); + + serial_out_shift(&com_port->lcr, 0, UART_LCR_BKSE | UART_LCRVAL); + serial_out_shift(&com_port->dll, 0, baud_divisor & 0xff); + serial_out_shift(&com_port->dlm, 0, (baud_divisor >> 8) & 0xff); + serial_out_shift(&com_port->lcr, 0, UART_LCRVAL); +} + +static inline void _debug_uart_putc(int ch) +{ + struct NS16550 *com_port = (struct NS16550 *)CONFIG_DEBUG_UART_BASE; + + while (!(serial_in_shift(&com_port->lsr, 0) & UART_LSR_THRE)) + ; + serial_out_shift(&com_port->thr, 0, ch); +} + +DEBUG_UART_FUNCS + +#endif + #ifdef CONFIG_DM_SERIAL static int ns16550_serial_putc(struct udevice *dev, const char ch) {