diff options
| -rw-r--r-- | common/serial.c | 90 | ||||
| -rw-r--r-- | include/serial.h | 5 | 
2 files changed, 95 insertions, 0 deletions
| diff --git a/common/serial.c b/common/serial.c index bf7740950..748e5d5b1 100644 --- a/common/serial.c +++ b/common/serial.c @@ -24,6 +24,8 @@  #include <common.h>  #include <serial.h>  #include <stdio_dev.h> +#include <post.h> +#include <linux/compiler.h>  DECLARE_GLOBAL_DATA_PTR; @@ -221,3 +223,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 e6d3859bd..08d106a7c 100644 --- a/include/serial.h +++ b/include/serial.h @@ -1,6 +1,8 @@  #ifndef __SERIAL_H__  #define __SERIAL_H__ +#include <post.h> +  #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;  }; |