summaryrefslogtreecommitdiff
path: root/arch/sparc/cpu/leon2/serial.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/sparc/cpu/leon2/serial.c')
-rw-r--r--arch/sparc/cpu/leon2/serial.c125
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, &regs->UART_Scaler);
/* Let bit 11 be unchanged (debug bit for GRMON) */
- tmp = READ_WORD(regs->UART_Control);
+ tmp = readl(&regs->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, &regs->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 = {