diff options
Diffstat (limited to 'arch/blackfin/cpu/serial.c')
-rw-r--r-- | arch/blackfin/cpu/serial.c | 234 |
1 files changed, 176 insertions, 58 deletions
diff --git a/arch/blackfin/cpu/serial.c b/arch/blackfin/cpu/serial.c index 650202e..030160f 100644 --- a/arch/blackfin/cpu/serial.c +++ b/arch/blackfin/cpu/serial.c @@ -39,6 +39,8 @@ #include <common.h> #include <watchdog.h> +#include <serial.h> +#include <linux/compiler.h> #include <asm/blackfin.h> #include <asm/mach-common/bits/uart.h> @@ -49,9 +51,9 @@ DECLARE_GLOBAL_DATA_PTR; #include "serial.h" #ifdef CONFIG_DEBUG_SERIAL -uint16_t cached_lsr[256]; -uint16_t cached_rbr[256]; -size_t cache_count; +static uint16_t cached_lsr[256]; +static uint16_t cached_rbr[256]; +static 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. This also @@ -59,68 +61,34 @@ size_t cache_count; * tally of all the status bits. */ static uint16_t uart_lsr_save; -static uint16_t uart_lsr_read(void) +static uint16_t uart_lsr_read(uint32_t uart_base) { - uint16_t lsr = bfin_read16(&pUART->lsr); + uint16_t lsr = bfin_read(&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) +static void uart_lsr_clear(uint32_t uart_base) { uart_lsr_save = 0; - bfin_write16(&pUART->lsr, bfin_read16(&pUART->lsr) | -1); + bfin_write(&pUART->lsr, bfin_read(&pUART->lsr) | -1); } #else /* When debugging is disabled, we only care about the DR bit, so if other * bits get set/cleared, we don't really care since we don't read them * anyways (and thus anomaly 05000099 is irrelevant). */ -static uint16_t uart_lsr_read(void) +static inline uint16_t uart_lsr_read(uint32_t uart_base) { - return bfin_read16(&pUART->lsr); + return bfin_read(&pUART->lsr); } -static void uart_lsr_clear(void) +static void uart_lsr_clear(uint32_t uart_base) { - bfin_write16(&pUART->lsr, bfin_read16(&pUART->lsr) | -1); + bfin_write(&pUART->lsr, bfin_read(&pUART->lsr) | -1); } #endif -/* Symbol for our assembly to call. */ -void serial_set_baud(uint32_t baud) -{ - serial_early_set_baud(baud); -} - -/* Symbol for common u-boot code to call. - * Setup the baudrate (brg: baudrate generator). - */ -void serial_setbrg(void) -{ - serial_set_baud(gd->baudrate); -} - -/* Symbol for our assembly to call. */ -void serial_initialize(void) -{ - serial_early_init(); -} - -/* Symbol for common u-boot code to call. */ -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; -} - -void serial_putc(const char c) +static void uart_putc(uint32_t uart_base, const char c) { /* send a \r for compatibility */ if (c == '\n') @@ -129,36 +97,36 @@ void serial_putc(const char c) WATCHDOG_RESET(); /* wait for the hardware fifo to clear up */ - while (!(uart_lsr_read() & THRE)) + while (!(uart_lsr_read(uart_base) & THRE)) continue; /* queue the character for transmission */ - bfin_write16(&pUART->thr, c); + bfin_write(&pUART->thr, c); SSYNC(); WATCHDOG_RESET(); } -int serial_tstc(void) +static int uart_tstc(uint32_t uart_base) { WATCHDOG_RESET(); - return (uart_lsr_read() & DR) ? 1 : 0; + return (uart_lsr_read(uart_base) & DR) ? 1 : 0; } -int serial_getc(void) +static int uart_getc(uint32_t uart_base) { uint16_t uart_rbr_val; /* wait for data ! */ - while (!serial_tstc()) + while (!uart_tstc(uart_base)) continue; /* grab the new byte */ - uart_rbr_val = bfin_read16(&pUART->rbr); + uart_rbr_val = bfin_read(&pUART->rbr); #ifdef CONFIG_DEBUG_SERIAL /* grab & clear the LSR */ - uint16_t uart_lsr_val = uart_lsr_read(); + uint16_t uart_lsr_val = uart_lsr_read(uart_base); cached_lsr[cache_count] = uart_lsr_val; cached_rbr[cache_count] = uart_rbr_val; @@ -168,23 +136,171 @@ int serial_getc(void) uint16_t dll, dlh; printf("\n[SERIAL ERROR]\n"); ACCESS_LATCH(); - dll = bfin_read16(&pUART->dll); - dlh = bfin_read16(&pUART->dlh); + dll = bfin_read(&pUART->dll); + dlh = bfin_read(&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, + printf("\t%3zu: 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(); + uart_lsr_clear(uart_base); return uart_rbr_val; } +#ifdef CONFIG_SYS_BFIN_UART + +static void uart_puts(uint32_t uart_base, const char *s) +{ + while (*s) + uart_putc(uart_base, *s++); +} + +#define DECL_BFIN_UART(n) \ +static int uart##n##_init(void) \ +{ \ + const unsigned short pins[] = { _P_UART(n, RX), _P_UART(n, TX), 0, }; \ + peripheral_request_list(pins, "bfin-uart"); \ + uart_init(MMR_UART(n)); \ + serial_early_set_baud(MMR_UART(n), gd->baudrate); \ + uart_lsr_clear(MMR_UART(n)); \ + return 0; \ +} \ +\ +static int uart##n##_uninit(void) \ +{ \ + return serial_early_uninit(MMR_UART(n)); \ +} \ +\ +static void uart##n##_setbrg(void) \ +{ \ + serial_early_set_baud(MMR_UART(n), gd->baudrate); \ +} \ +\ +static int uart##n##_getc(void) \ +{ \ + return uart_getc(MMR_UART(n)); \ +} \ +\ +static int uart##n##_tstc(void) \ +{ \ + return uart_tstc(MMR_UART(n)); \ +} \ +\ +static void uart##n##_putc(const char c) \ +{ \ + uart_putc(MMR_UART(n), c); \ +} \ +\ +static void uart##n##_puts(const char *s) \ +{ \ + uart_puts(MMR_UART(n), s); \ +} \ +\ +struct serial_device bfin_serial##n##_device = { \ + .name = "bfin_uart"#n, \ + .init = uart##n##_init, \ + .uninit = uart##n##_uninit, \ + .setbrg = uart##n##_setbrg, \ + .getc = uart##n##_getc, \ + .tstc = uart##n##_tstc, \ + .putc = uart##n##_putc, \ + .puts = uart##n##_puts, \ +}; + +#ifdef UART0_DLL +DECL_BFIN_UART(0) +#endif +#ifdef UART1_DLL +DECL_BFIN_UART(1) +#endif +#ifdef UART2_DLL +DECL_BFIN_UART(2) +#endif +#ifdef UART3_DLL +DECL_BFIN_UART(3) +#endif + +__weak struct serial_device *default_serial_console(void) +{ +#if CONFIG_UART_CONSOLE == 0 + return &bfin_serial0_device; +#elif CONFIG_UART_CONSOLE == 1 + return &bfin_serial1_device; +#elif CONFIG_UART_CONSOLE == 2 + return &bfin_serial2_device; +#elif CONFIG_UART_CONSOLE == 3 + return &bfin_serial3_device; +#endif +} + +void serial_register_bfin_uart(void) +{ +#ifdef UART0_DLL + serial_register(&bfin_serial0_device); +#endif +#ifdef UART1_DLL + serial_register(&bfin_serial1_device); +#endif +#ifdef UART2_DLL + serial_register(&bfin_serial2_device); +#endif +#ifdef UART3_DLL + serial_register(&bfin_serial3_device); +#endif +} + +#else + +/* Symbol for our assembly to call. */ +void serial_set_baud(uint32_t baud) +{ + serial_early_set_baud(UART_DLL, baud); +} + +/* Symbol for common u-boot code to call. + * Setup the baudrate (brg: baudrate generator). + */ +void serial_setbrg(void) +{ + serial_set_baud(gd->baudrate); +} + +/* Symbol for our assembly to call. */ +void serial_initialize(void) +{ + serial_early_init(UART_DLL); +} + +/* Symbol for common u-boot code to call. */ +int serial_init(void) +{ + serial_initialize(); + serial_setbrg(); + uart_lsr_clear(UART_DLL); + return 0; +} + +int serial_tstc(void) +{ + return uart_tstc(UART_DLL); +} + +int serial_getc(void) +{ + return uart_getc(UART_DLL); +} + +void serial_putc(const char c) +{ + uart_putc(UART_DLL, c); +} + void serial_puts(const char *s) { while (*s) @@ -192,3 +308,5 @@ void serial_puts(const char *s) } #endif + +#endif |