diff options
Diffstat (limited to 'drivers/serial/serial_zynq.c')
-rw-r--r-- | drivers/serial/serial_zynq.c | 77 |
1 files changed, 61 insertions, 16 deletions
diff --git a/drivers/serial/serial_zynq.c b/drivers/serial/serial_zynq.c index 9d84290196..3b12c01538 100644 --- a/drivers/serial/serial_zynq.c +++ b/drivers/serial/serial_zynq.c @@ -6,6 +6,7 @@ */ #include <common.h> +#include <errno.h> #include <fdtdec.h> #include <watchdog.h> #include <asm/io.h> @@ -43,20 +44,16 @@ static struct uart_zynq *uart_zynq_ports[2] = { }; /* Set up the baud rate in gd struct */ -static void uart_zynq_serial_setbrg(const int port) +static void _uart_zynq_serial_setbrg(struct uart_zynq *regs, + unsigned long clock, unsigned long baud) { /* Calculation results. */ unsigned int calc_bauderror, bdiv, bgen; unsigned long calc_baud = 0; - unsigned long baud; - unsigned long clock = get_uart_clk(port); - struct uart_zynq *regs = uart_zynq_ports[port]; /* Covering case where input clock is so slow */ - if (clock < 1000000 && gd->baudrate > 4800) - gd->baudrate = 4800; - - baud = gd->baudrate; + if (clock < 1000000 && baud > 4800) + baud = 4800; /* master clock * Baud rate = ------------------ @@ -87,36 +84,59 @@ static void uart_zynq_serial_setbrg(const int port) writel(bgen, ®s->baud_rate_gen); } -/* Initialize the UART, with...some settings. */ -static int uart_zynq_serial_init(const int port) +/* Set up the baud rate in gd struct */ +static void uart_zynq_serial_setbrg(const int port) { + unsigned long clock = get_uart_clk(port); struct uart_zynq *regs = uart_zynq_ports[port]; - if (!regs) - return -1; + return _uart_zynq_serial_setbrg(regs, clock, gd->baudrate); +} +/* Initialize the UART, with...some settings. */ +static void _uart_zynq_serial_init(struct uart_zynq *regs) +{ /* RX/TX enabled & reset */ writel(ZYNQ_UART_CR_TX_EN | ZYNQ_UART_CR_RX_EN | ZYNQ_UART_CR_TXRST | \ ZYNQ_UART_CR_RXRST, ®s->control); writel(ZYNQ_UART_MR_PARITY_NONE, ®s->mode); /* 8 bit, no parity */ +} + +/* Initialize the UART, with...some settings. */ +static int uart_zynq_serial_init(const int port) +{ + struct uart_zynq *regs = uart_zynq_ports[port]; + + if (!regs) + return -1; + + _uart_zynq_serial_init(regs); uart_zynq_serial_setbrg(port); return 0; } +static int _uart_zynq_serial_putc(struct uart_zynq *regs, const char c) +{ + if (readl(®s->channel_sts) & ZYNQ_UART_SR_TXFULL) + return -EAGAIN; + + writel(c, ®s->tx_rx_fifo); + + return 0; +} + static void uart_zynq_serial_putc(const char c, const int port) { struct uart_zynq *regs = uart_zynq_ports[port]; - while ((readl(®s->channel_sts) & ZYNQ_UART_SR_TXFULL) != 0) + while (_uart_zynq_serial_putc(regs, c) == -EAGAIN) WATCHDOG_RESET(); if (c == '\n') { - writel('\r', ®s->tx_rx_fifo); - while ((readl(®s->channel_sts) & ZYNQ_UART_SR_TXFULL) != 0) + while (_uart_zynq_serial_putc(regs, '\r') == -EAGAIN) WATCHDOG_RESET(); } - writel(c, ®s->tx_rx_fifo); } static void uart_zynq_serial_puts(const char *s, const int port) @@ -218,3 +238,28 @@ void zynq_serial_initialize(void) serial_register(&uart_zynq_serial0_device); serial_register(&uart_zynq_serial1_device); } + +#ifdef CONFIG_DEBUG_UART_ZYNQ + +#include <debug_uart.h> + +void _debug_uart_init(void) +{ + struct uart_zynq *regs = (struct uart_zynq *)CONFIG_DEBUG_UART_BASE; + + _uart_zynq_serial_init(regs); + _uart_zynq_serial_setbrg(regs, CONFIG_DEBUG_UART_CLOCK, + CONFIG_BAUDRATE); +} + +static inline void _debug_uart_putc(int ch) +{ + struct uart_zynq *regs = (struct uart_zynq *)CONFIG_DEBUG_UART_BASE; + + while (_uart_zynq_serial_putc(regs, ch) == -EAGAIN) + WATCHDOG_RESET(); +} + +DEBUG_UART_FUNCS + +#endif |