diff options
Diffstat (limited to 'roms/u-boot/arch/sparc/cpu/leon3/serial.c')
-rw-r--r-- | roms/u-boot/arch/sparc/cpu/leon3/serial.c | 128 |
1 files changed, 128 insertions, 0 deletions
diff --git a/roms/u-boot/arch/sparc/cpu/leon3/serial.c b/roms/u-boot/arch/sparc/cpu/leon3/serial.c new file mode 100644 index 00000000..bca6b654 --- /dev/null +++ b/roms/u-boot/arch/sparc/cpu/leon3/serial.c @@ -0,0 +1,128 @@ +/* GRLIB APBUART Serial controller driver + * + * (C) Copyright 2007 + * Daniel Hellstrom, Gaisler Research, daniel@gaisler.com. + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <common.h> +#include <asm/processor.h> +#include <asm/leon.h> +#include <ambapp.h> +#include <serial.h> +#include <linux/compiler.h> + +DECLARE_GLOBAL_DATA_PTR; + +ambapp_dev_apbuart *leon3_apbuart = NULL; + +static int leon3_serial_init(void) +{ + ambapp_apbdev apbdev; + unsigned int tmp; + + /* find UART */ + if (ambapp_apb_first(VENDOR_GAISLER, GAISLER_APBUART, &apbdev) == 1) { + + leon3_apbuart = (ambapp_dev_apbuart *) apbdev.address; + + /* found apbuart, let's init... + * + * Set scaler / baud rate + * + * Receiver & transmitter enable + */ + leon3_apbuart->scaler = CONFIG_SYS_GRLIB_APBUART_SCALER; + + /* Let bit 11 be unchanged (debug bit for GRMON) */ + tmp = READ_WORD(leon3_apbuart->ctrl); + + leon3_apbuart->ctrl = ((tmp & LEON_REG_UART_CTRL_DBG) | + LEON_REG_UART_CTRL_RE | + LEON_REG_UART_CTRL_TE); + + return 0; + } + return -1; /* didn't find hardware */ +} + +static void leon3_serial_putc_raw(const char c) +{ + if (!leon3_apbuart) + return; + + /* Wait for last character to go. */ + while (!(READ_WORD(leon3_apbuart->status) & LEON_REG_UART_STATUS_THE)) ; + + /* Send data */ + leon3_apbuart->data = c; + +#ifdef LEON_DEBUG + /* Wait for data to be sent */ + while (!(READ_WORD(leon3_apbuart->status) & LEON_REG_UART_STATUS_TSE)) ; +#endif +} + +static void leon3_serial_putc(const char c) +{ + if (c == '\n') + leon3_serial_putc_raw('\r'); + + leon3_serial_putc_raw(c); +} + +static int leon3_serial_getc(void) +{ + if (!leon3_apbuart) + return 0; + + /* Wait for a character to arrive. */ + while (!(READ_WORD(leon3_apbuart->status) & LEON_REG_UART_STATUS_DR)) ; + + /* read data */ + return READ_WORD(leon3_apbuart->data); +} + +static int leon3_serial_tstc(void) +{ + if (leon3_apbuart) + return (READ_WORD(leon3_apbuart->status) & + LEON_REG_UART_STATUS_DR); + return 0; +} + +/* set baud rate for uart */ +static void leon3_serial_setbrg(void) +{ + /* update baud rate settings, read it from gd->baudrate */ + unsigned int scaler; + if (leon3_apbuart && (gd->baudrate > 0)) { + scaler = + (((CONFIG_SYS_CLK_FREQ * 10) / (gd->baudrate * 8)) - + 5) / 10; + leon3_apbuart->scaler = scaler; + } + return; +} + +static struct serial_device leon3_serial_drv = { + .name = "leon3_serial", + .start = leon3_serial_init, + .stop = NULL, + .setbrg = leon3_serial_setbrg, + .putc = leon3_serial_putc, + .puts = default_serial_puts, + .getc = leon3_serial_getc, + .tstc = leon3_serial_tstc, +}; + +void leon3_serial_initialize(void) +{ + serial_register(&leon3_serial_drv); +} + +__weak struct serial_device *default_serial_console(void) +{ + return &leon3_serial_drv; +} |