/* GRLIB APBUART Serial controller driver
*
- * (C) Copyright 2008
- * Daniel Hellstrom, Gaisler Research, daniel@gaisler.com.
- *
- * See file CREDITS for list of people who contributed to this
- * project.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation; either version 2 of
- * the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
- * MA 02111-1307 USA
+ * (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;
-/* Force cache miss each time a serial controller reg is read */
-#define CACHE_BYPASS 1
-
-#ifdef CACHE_BYPASS
-#define READ_BYTE(var) SPARC_NOCACHE_READ_BYTE((unsigned int)&(var))
-#define READ_HWORD(var) SPARC_NOCACHE_READ_HWORD((unsigned int)&(var))
-#define READ_WORD(var) SPARC_NOCACHE_READ((unsigned int)&(var))
-#define READ_DWORD(var) SPARC_NOCACHE_READ_DWORD((unsigned int)&(var))
-#endif
+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
}
leon2_serial_putc_raw(c);
}
-static void leon2_serial_puts(const char *s)
-{
- while (*s) {
- serial_putc(*s++);
- }
-}
-
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, gd->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 = {
.stop = NULL,
.setbrg = leon2_serial_setbrg,
.putc = leon2_serial_putc,
- .puts = leon2_serial_puts,
+ .puts = default_serial_puts,
.getc = leon2_serial_getc,
.tstc = leon2_serial_tstc,
};