diff options
Diffstat (limited to 'arch/sparc/cpu/leon2/serial.c')
-rw-r--r-- | arch/sparc/cpu/leon2/serial.c | 125 |
1 files changed, 59 insertions, 66 deletions
diff --git a/arch/sparc/cpu/leon2/serial.c b/arch/sparc/cpu/leon2/serial.c index 5cfbb9ed15..603364ee0b 100644 --- a/arch/sparc/cpu/leon2/serial.c +++ b/arch/sparc/cpu/leon2/serial.c @@ -1,72 +1,78 @@ /* GRLIB APBUART Serial controller driver * - * (C) Copyright 2008 - * Daniel Hellstrom, Gaisler Research, daniel@gaisler.com. + * (C) Copyright 2008, 2015 + * Daniel Hellstrom, Cobham Gaisler, daniel@gaisler.com. * * SPDX-License-Identifier: GPL-2.0+ */ #include <common.h> -#include <asm/processor.h> -#include <asm/leon.h> +#include <asm/io.h> #include <serial.h> -#include <linux/compiler.h> +#include <watchdog.h> DECLARE_GLOBAL_DATA_PTR; +static unsigned leon2_serial_calc_scaler(unsigned freq, unsigned baud) +{ + return (((freq*10) / (baud*8)) - 5) / 10; +} + static int leon2_serial_init(void) { - LEON2_regs *leon2 = (LEON2_regs *) LEON2_PREGS; + LEON2_regs *leon2 = (LEON2_regs *)LEON2_PREGS; LEON2_Uart_regs *regs; unsigned int tmp; - /* Init LEON2 UART - * - * Set scaler / baud rate - * - * Receiver & transmitter enable - */ #if LEON2_CONSOLE_SELECT == LEON_CONSOLE_UART1 - regs = (LEON2_Uart_regs *) & leon2->UART_Channel_1; + regs = (LEON2_Uart_regs *)&leon2->UART_Channel_1; #else - regs = (LEON2_Uart_regs *) & leon2->UART_Channel_2; + regs = (LEON2_Uart_regs *)&leon2->UART_Channel_2; #endif - regs->UART_Scaler = CONFIG_SYS_LEON2_UART1_SCALER; + /* Set scaler / baud rate */ + tmp = leon2_serial_calc_scaler(CONFIG_SYS_CLK_FREQ, CONFIG_BAUDRATE); + writel(tmp, ®s->UART_Scaler); /* Let bit 11 be unchanged (debug bit for GRMON) */ - tmp = READ_WORD(regs->UART_Control); + tmp = readl(®s->UART_Control) & LEON2_UART_CTRL_DBG; + tmp |= (LEON2_UART1_LOOPBACK_ENABLE << 7); + tmp |= (LEON2_UART1_FLOWCTRL_ENABLE << 6); + tmp |= (LEON2_UART1_PARITY_ENABLE << 5); + tmp |= (LEON2_UART1_ODDPAR_ENABLE << 4); + /* Receiver & transmitter enable */ + tmp |= (LEON2_UART_CTRL_RE | LEON2_UART_CTRL_TE); + writel(tmp, ®s->UART_Control); + + gd->arch.uart = regs; + return 0; +} - regs->UART_Control = ((tmp & LEON2_UART_CTRL_DBG) | - (LEON2_UART1_LOOPBACK_ENABLE << 7) | - (LEON2_UART1_FLOWCTRL_ENABLE << 6) | - (LEON2_UART1_PARITY_ENABLE << 5) | - (LEON2_UART1_ODDPAR_ENABLE << 4) | - LEON2_UART_CTRL_RE | LEON2_UART_CTRL_TE); +static inline LEON2_Uart_regs *leon2_get_uart_regs(void) +{ + LEON2_Uart_regs *uart = gd->arch.uart; - return 0; + return uart; } static void leon2_serial_putc_raw(const char c) { - LEON2_regs *leon2 = (LEON2_regs *) LEON2_PREGS; - LEON2_Uart_regs *regs; + LEON2_Uart_regs *uart = leon2_get_uart_regs(); -#if LEON2_CONSOLE_SELECT == LEON_CONSOLE_UART1 - regs = (LEON2_Uart_regs *) & leon2->UART_Channel_1; -#else - regs = (LEON2_Uart_regs *) & leon2->UART_Channel_2; -#endif + if (!uart) + return; /* Wait for last character to go. */ - while (!(READ_WORD(regs->UART_Status) & LEON2_UART_STAT_THE)) ; + while (!(readl(&uart->UART_Status) & LEON2_UART_STAT_THE)) + WATCHDOG_RESET(); /* Send data */ - regs->UART_Channel = c; + writel(c, &uart->UART_Channel); #ifdef LEON_DEBUG /* Wait for data to be sent */ - while (!(READ_WORD(regs->UART_Status) & LEON2_UART_STAT_TSE)) ; + while (!(readl(&uart->UART_Status) & LEON2_UART_STAT_TSE)) + WATCHDOG_RESET(); #endif } @@ -80,56 +86,43 @@ static void leon2_serial_putc(const char c) static int leon2_serial_getc(void) { - LEON2_regs *leon2 = (LEON2_regs *) LEON2_PREGS; - LEON2_Uart_regs *regs; + LEON2_Uart_regs *uart = leon2_get_uart_regs(); -#if LEON2_CONSOLE_SELECT == LEON_CONSOLE_UART1 - regs = (LEON2_Uart_regs *) & leon2->UART_Channel_1; -#else - regs = (LEON2_Uart_regs *) & leon2->UART_Channel_2; -#endif + if (!uart) + return 0; /* Wait for a character to arrive. */ - while (!(READ_WORD(regs->UART_Status) & LEON2_UART_STAT_DR)) ; + while (!(readl(&uart->UART_Status) & LEON2_UART_STAT_DR)) + WATCHDOG_RESET(); - /* read data */ - return READ_WORD(regs->UART_Channel); + /* Read character data */ + return readl(&uart->UART_Channel); } static int leon2_serial_tstc(void) { - LEON2_regs *leon2 = (LEON2_regs *) LEON2_PREGS; - LEON2_Uart_regs *regs; + LEON2_Uart_regs *uart = leon2_get_uart_regs(); -#if LEON2_CONSOLE_SELECT == LEON_CONSOLE_UART1 - regs = (LEON2_Uart_regs *) & leon2->UART_Channel_1; -#else - regs = (LEON2_Uart_regs *) & leon2->UART_Channel_2; -#endif + if (!uart) + return 0; - return (READ_WORD(regs->UART_Status) & LEON2_UART_STAT_DR); + return readl(&uart->UART_Status) & LEON2_UART_STAT_DR; } -/* set baud rate for uart */ static void leon2_serial_setbrg(void) { - /* update baud rate settings, read it from gd->baudrate */ + LEON2_Uart_regs *uart = leon2_get_uart_regs(); unsigned int scaler; - LEON2_regs *leon2 = (LEON2_regs *) LEON2_PREGS; - LEON2_Uart_regs *regs; -#if LEON2_CONSOLE_SELECT == LEON_CONSOLE_UART1 - regs = (LEON2_Uart_regs *) & leon2->UART_Channel_1; -#else - regs = (LEON2_Uart_regs *) & leon2->UART_Channel_2; -#endif + if (!uart) + return; + + if (!gd->baudrate) + gd->baudrate = CONFIG_BAUDRATE; + + scaler = leon2_serial_calc_scaler(CONFIG_SYS_CLK_FREQ, CONFIG_BAUDRATE); - if (gd->baudrate > 0) { - scaler = - (((CONFIG_SYS_CLK_FREQ * 10) / (gd->baudrate * 8)) - - 5) / 10; - regs->UART_Scaler = scaler; - } + writel(scaler, &uart->UART_Scaler); } static struct serial_device leon2_serial_drv = { |