X-Git-Url: https://git.librecmc.org/?a=blobdiff_plain;f=cpu%2Fblackfin%2Fserial.c;h=42534bd9b9c575a8f49d2ef22ebf297bf9317a01;hb=7633903bff432ec7b27905dce7396958553f2be6;hp=406d9d023d6805c6bc4ea6837c50e9fbc11bb694;hpb=10a3367955bc2033b288915f8f10d0e507fe2fa1;p=oweals%2Fu-boot.git diff --git a/cpu/blackfin/serial.c b/cpu/blackfin/serial.c index 406d9d023d..42534bd9b9 100644 --- a/cpu/blackfin/serial.c +++ b/cpu/blackfin/serial.c @@ -29,12 +29,40 @@ #include #include +#ifdef CONFIG_UART_CONSOLE + #if defined(UART_LSR) && (CONFIG_UART_CONSOLE != 0) # error CONFIG_UART_CONSOLE must be 0 on parts with only one UART #endif #include "serial.h" +#ifdef CONFIG_DEBUG_SERIAL +uint16_t cached_lsr[256]; +uint16_t cached_rbr[256]; +size_t cache_count; + +/* The LSR is read-to-clear on some parts, so we have to make sure status + * bits aren't inadvertently lost when doing various tests. + */ +static uint16_t uart_lsr_save; +static uint16_t uart_lsr_read(void) +{ + uint16_t lsr = *pUART_LSR; + uart_lsr_save |= (lsr & (OE|PE|FE|BI)); + return lsr | uart_lsr_save; +} +/* Just do the clear for everyone since it can't hurt. */ +static void uart_lsr_clear(void) +{ + uart_lsr_save = 0; + *pUART_LSR |= -1; +} +#else +static inline uint16_t uart_lsr_read(void) { return *pUART_LSR; } +static inline void uart_lsr_clear(void) { *pUART_LSR = -1; } +#endif + /* Symbol for our assembly to call. */ void serial_set_baud(uint32_t baud) { @@ -61,6 +89,12 @@ int serial_init(void) { serial_initialize(); serial_setbrg(); + uart_lsr_clear(); +#ifdef CONFIG_DEBUG_SERIAL + cache_count = 0; + memset(cached_lsr, 0x00, sizeof(cached_lsr)); + memset(cached_rbr, 0x00, sizeof(cached_rbr)); +#endif return 0; } @@ -73,7 +107,7 @@ void serial_putc(const char c) WATCHDOG_RESET(); /* wait for the hardware fifo to clear up */ - while (!(*pUART_LSR & THRE)) + while (!(uart_lsr_read() & THRE)) continue; /* queue the character for transmission */ @@ -83,38 +117,54 @@ void serial_putc(const char c) WATCHDOG_RESET(); /* wait for the byte to be shifted over the line */ - while (!(*pUART_LSR & TEMT)) + while (!(uart_lsr_read() & TEMT)) continue; } int serial_tstc(void) { WATCHDOG_RESET(); - return (*pUART_LSR & DR) ? 1 : 0; + return (uart_lsr_read() & DR) ? 1 : 0; } int serial_getc(void) { - uint16_t uart_lsr_val, uart_rbr_val; + uint16_t uart_rbr_val; /* wait for data ! */ while (!serial_tstc()) continue; - /* clear the status and grab the new byte */ - uart_lsr_val = *pUART_LSR; + /* grab the new byte */ uart_rbr_val = *pUART_RBR; +#ifdef CONFIG_DEBUG_SERIAL + /* grab & clear the LSR */ + uint16_t uart_lsr_val = uart_lsr_read(); + + cached_lsr[cache_count] = uart_lsr_val; + cached_rbr[cache_count] = uart_rbr_val; + cache_count = (cache_count + 1) % ARRAY_SIZE(cached_lsr); + if (uart_lsr_val & (OE|PE|FE|BI)) { - /* Some parts are read-to-clear while others are - * write-to-clear. Just do the write for everyone - * since it cant hurt (other than code size). - */ - *pUART_LSR = (OE|PE|FE|BI); + uint16_t dll, dlh; + printf("\n[SERIAL ERROR]\n"); + ACCESS_LATCH(); + dll = *pUART_DLL; + dlh = *pUART_DLH; + ACCESS_PORT_IER(); + printf("\tDLL=0x%x DLH=0x%x\n", dll, dlh); + do { + --cache_count; + printf("\t%3i: RBR=0x%02x LSR=0x%02x\n", cache_count, + cached_rbr[cache_count], cached_lsr[cache_count]); + } while (cache_count > 0); return -1; } +#endif + uart_lsr_clear(); - return uart_rbr_val & 0xFF; + return uart_rbr_val; } void serial_puts(const char *s) @@ -122,3 +172,5 @@ void serial_puts(const char *s) while (*s) serial_putc(*s++); } + +#endif