From patchwork Sat May 14 16:56:15 2011 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Mike Frysinger X-Patchwork-Id: 95570 X-Patchwork-Delegate: wd@denx.de 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 8F7A41007D1 for ; Sun, 15 May 2011 02:52:45 +1000 (EST) Received: from localhost (localhost [127.0.0.1]) by theia.denx.de (Postfix) with ESMTP id E52BE280AC; Sat, 14 May 2011 18:52:42 +0200 (CEST) X-Virus-Scanned: Debian amavisd-new at theia.denx.de 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 CI6TXPzy7OXV; Sat, 14 May 2011 18:52:42 +0200 (CEST) Received: from theia.denx.de (localhost [127.0.0.1]) by theia.denx.de (Postfix) with ESMTP id 4F1DA280A0; Sat, 14 May 2011 18:52:41 +0200 (CEST) Received: from localhost (localhost [127.0.0.1]) by theia.denx.de (Postfix) with ESMTP id 063C0280A0 for ; Sat, 14 May 2011 18:52:39 +0200 (CEST) X-Virus-Scanned: Debian amavisd-new at theia.denx.de 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 o2Y9-8FM610V for ; Sat, 14 May 2011 18:52:28 +0200 (CEST) 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 smtp.gentoo.org (smtp.gentoo.org [140.211.166.183]) by theia.denx.de (Postfix) with ESMTPS id 06AF22809F for ; Sat, 14 May 2011 18:52:26 +0200 (CEST) Received: from localhost.localdomain (localhost [127.0.0.1]) by smtp.gentoo.org (Postfix) with ESMTP id BB9891B4018 for ; Sat, 14 May 2011 16:52:21 +0000 (UTC) From: Mike Frysinger To: u-boot@lists.denx.de Date: Sat, 14 May 2011 12:56:15 -0400 Message-Id: <1305392175-31018-1-git-send-email-vapier@gentoo.org> X-Mailer: git-send-email 1.7.5.rc3 Subject: [U-Boot] [PATCH] serial: implement common uart post test X-BeenThere: u-boot@lists.denx.de X-Mailman-Version: 2.1.9 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 The current arch/driver specific UART posts basically boil down to setting the UART to loop back mode, then reading and writing data. If we ignore the loop back part, the rest can be built upon the existing common serial API. So let's do just that. First add a call back for serial drivers to implement loop back control. Then write a post test that walks all of the serial drivers, puts them into loop back mode, and verifies that reading/writing at all the diff baud rates is OK. If a serial driver doesn't support loop back mode (either it can't or it hasn't done so yet), then skip it. This should allow for people to easily migrate to the new post test with existing serial drivers. I haven't touched the few already existing uart post tests as I don't the hardware or knowledge of converting them over. So I've marked the new test as weak which will allow the existing tests to override the default until they are converted. Signed-off-by: Mike Frysinger --- common/serial.c | 90 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ include/serial.h | 5 +++ 2 files changed, 95 insertions(+), 0 deletions(-) diff --git a/common/serial.c b/common/serial.c index 07a1147..995d268 100644 --- a/common/serial.c +++ b/common/serial.c @@ -24,6 +24,8 @@ #include #include #include +#include +#include DECLARE_GLOBAL_DATA_PTR; @@ -224,3 +226,91 @@ void serial_puts (const char *s) serial_current->puts (s); } + +#if CONFIG_POST & CONFIG_SYS_POST_UART +static const int bauds[] = CONFIG_SYS_BAUDRATE_TABLE; + +/* Mark weak until post/cpu/.../uart.c migrate over */ +__weak +int uart_post_test(int flags) +{ + unsigned char c; + int ret, saved_baud, b; + struct serial_device *saved_dev, *s; + bd_t *bd = gd->bd; + + /* Save current serial state */ + ret = 0; + saved_dev = serial_current; + saved_baud = bd->bi_baudrate; + + for (s = serial_devices; s; s = s->next) { + /* If this driver doesn't support loop back, skip it */ + if (!s->loop) + continue; + + /* Test the next device */ + serial_current = s; + + ret = serial_init(); + if (ret) + goto done; + + /* Consume anything that happens to be queued */ + while (serial_tstc()) + serial_getc(); + + /* Enable loop back */ + s->loop(1); + + /* Test every available baud rate */ + for (b = 0; b < ARRAY_SIZE(bauds); ++b) { + bd->bi_baudrate = bauds[b]; + serial_setbrg(); + + /* + * Stick to printable chars to avoid issues: + * - terminal corruption + * - serial program reacting to sequences and sending + * back random extra data + * - most serial drivers add in extra chars (like \r\n) + */ + for (c = 0x20; c < 0x7f; ++c) { + /* Send it out */ + serial_putc(c); + + /* Make sure it's the same one */ + ret = (c != serial_getc()); + if (ret) { + s->loop(0); + goto done; + } + + /* Clean up the output in case it was sent */ + serial_putc('\b'); + ret = ('\b' != serial_getc()); + if (ret) { + s->loop(0); + goto done; + } + } + } + + /* Disable loop back */ + s->loop(0); + + /* XXX: There is no serial_uninit() !? */ + if (s->uninit) + s->uninit(); + } + + done: + /* Restore previous serial state */ + serial_current = saved_dev; + bd->bi_baudrate = saved_baud; + serial_reinit_all(); + serial_setbrg(); + + return ret; +} +#endif diff --git a/include/serial.h b/include/serial.h index aea2102..ff1ce99 100644 --- a/include/serial.h +++ b/include/serial.h @@ -1,6 +1,8 @@ #ifndef __SERIAL_H__ #define __SERIAL_H__ +#include + #define NAMESIZE 16 struct serial_device { @@ -13,6 +15,9 @@ struct serial_device { int (*tstc) (void); void (*putc) (const char c); void (*puts) (const char *s); +#if CONFIG_POST & CONFIG_SYS_POST_UART + void (*loop) (int); +#endif struct serial_device *next; };