X-Git-Url: https://git.sur5r.net/?a=blobdiff_plain;f=drivers%2Fserial%2Fserial_pl01x.c;h=dfdba9f64eb8031144d6be6b2722f070df3cf047;hb=7a8e739cd5bc0c48511d343f469af89a88a3294d;hp=5dfcde8774700b4b2fdd8319003f92bcf07394ec;hpb=ed8456f64d8f7f116a35d9a668467864b9f75e82;p=u-boot diff --git a/drivers/serial/serial_pl01x.c b/drivers/serial/serial_pl01x.c index 5dfcde8774..dfdba9f64e 100644 --- a/drivers/serial/serial_pl01x.c +++ b/drivers/serial/serial_pl01x.c @@ -30,6 +30,8 @@ #include #include #include +#include +#include #include "serial_pl01x.h" /* @@ -54,7 +56,7 @@ static struct pl01x_regs *pl01x_get_regs(int portnum) #ifdef CONFIG_PL010_SERIAL -int serial_init (void) +static int pl01x_serial_init(void) { struct pl01x_regs *regs = pl01x_get_regs(CONSOLE_PORT); unsigned int divisor; @@ -104,13 +106,22 @@ int serial_init (void) #ifdef CONFIG_PL011_SERIAL -int serial_init (void) +static int pl01x_serial_init(void) { struct pl01x_regs *regs = pl01x_get_regs(CONSOLE_PORT); unsigned int temp; unsigned int divider; unsigned int remainder; unsigned int fraction; + unsigned int lcr; + +#ifdef CONFIG_PL011_SERIAL_FLUSH_ON_INIT + /* Empty RX fifo if necessary */ + if (readl(®s->pl011_cr) & UART_PL011_CR_UARTEN) { + while (!(readl(®s->fr) & UART_PL01x_FR_RXFE)) + readl(®s->dr); + } +#endif /* First, disable everything */ writel(0, ®s->pl011_cr); @@ -131,19 +142,36 @@ int serial_init (void) writel(fraction, ®s->pl011_fbrd); /* Set the UART to be 8 bits, 1 stop bit, no parity, fifo enabled */ - writel(UART_PL011_LCRH_WLEN_8 | UART_PL011_LCRH_FEN, - ®s->pl011_lcrh); - + lcr = UART_PL011_LCRH_WLEN_8 | UART_PL011_LCRH_FEN; + writel(lcr, ®s->pl011_lcrh); + +#ifdef CONFIG_PL011_SERIAL_RLCR + { + int i; + + /* + * Program receive line control register after waiting + * 10 bus cycles. Delay be writing to readonly register + * 10 times + */ + for (i = 0; i < 10; i++) + writel(lcr, ®s->fr); + + writel(lcr, ®s->pl011_rlcr); + /* lcrh needs to be set again for change to be effective */ + writel(lcr, ®s->pl011_lcrh); + } +#endif /* Finally, enable the UART */ - writel(UART_PL011_CR_UARTEN | UART_PL011_CR_TXE | UART_PL011_CR_RXE, - ®s->pl011_cr); + writel(UART_PL011_CR_UARTEN | UART_PL011_CR_TXE | UART_PL011_CR_RXE | + UART_PL011_CR_RTS, ®s->pl011_cr); return 0; } #endif /* CONFIG_PL011_SERIAL */ -void serial_putc (const char c) +static void pl01x_serial_putc(const char c) { if (c == '\n') pl01x_putc (CONSOLE_PORT, '\r'); @@ -151,26 +179,29 @@ void serial_putc (const char c) pl01x_putc (CONSOLE_PORT, c); } -void serial_puts (const char *s) -{ - while (*s) { - serial_putc (*s++); - } -} - -int serial_getc (void) +static int pl01x_serial_getc(void) { return pl01x_getc (CONSOLE_PORT); } -int serial_tstc (void) +static int pl01x_serial_tstc(void) { return pl01x_tstc (CONSOLE_PORT); } -void serial_setbrg (void) +static void pl01x_serial_setbrg(void) { + struct pl01x_regs *regs = pl01x_get_regs(CONSOLE_PORT); + baudrate = gd->baudrate; + /* + * Flush FIFO and wait for non-busy before changing baudrate to avoid + * crap in console + */ + while (!(readl(®s->fr) & UART_PL01x_FR_TXFE)) + WATCHDOG_RESET(); + while (readl(®s->fr) & UART_PL01x_FR_BUSY) + WATCHDOG_RESET(); serial_init(); } @@ -214,3 +245,24 @@ static int pl01x_tstc (int portnum) WATCHDOG_RESET(); return !(readl(®s->fr) & UART_PL01x_FR_RXFE); } + +static struct serial_device pl01x_serial_drv = { + .name = "pl01x_serial", + .start = pl01x_serial_init, + .stop = NULL, + .setbrg = pl01x_serial_setbrg, + .putc = pl01x_serial_putc, + .puts = default_serial_puts, + .getc = pl01x_serial_getc, + .tstc = pl01x_serial_tstc, +}; + +void pl01x_serial_initialize(void) +{ + serial_register(&pl01x_serial_drv); +} + +__weak struct serial_device *default_serial_console(void) +{ + return &pl01x_serial_drv; +}