/* GRLIB APBUART Serial controller driver
 *
 * (C) Copyright 2007, 2015
 * Daniel Hellstrom, Cobham Gaisler, daniel@gaisler.com.
 *
 * SPDX-License-Identifier:	GPL-2.0+
 */

#include <common.h>
#include <asm/io.h>
#include <ambapp.h>
#include <serial.h>
#include <watchdog.h>

DECLARE_GLOBAL_DATA_PTR;

/* Select which UART that will become u-boot console */
#ifndef CONFIG_SYS_GRLIB_APBUART_INDEX
#define CONFIG_SYS_GRLIB_APBUART_INDEX 0
#endif

static int leon3_serial_init(void)
{
	ambapp_dev_apbuart *uart;
	ambapp_apbdev apbdev;
	unsigned int tmp;

	/* find UART */
	if (ambapp_apb_find(&ambapp_plb, VENDOR_GAISLER, GAISLER_APBUART,
		CONFIG_SYS_GRLIB_APBUART_INDEX, &apbdev) != 1)
		return -1; /* didn't find hardware */

	/* found apbuart, let's init .. */
	uart = (ambapp_dev_apbuart *) apbdev.address;

	/* Set scaler / baud rate */
	tmp = (((CONFIG_SYS_CLK_FREQ*10) / (CONFIG_BAUDRATE*8)) - 5)/10;
	writel(tmp, &uart->scaler);

	/* Let bit 11 be unchanged (debug bit for GRMON) */
	tmp = readl(&uart->ctrl) & LEON_REG_UART_CTRL_DBG;
	/* Receiver & transmitter enable */
	tmp |= LEON_REG_UART_CTRL_RE | LEON_REG_UART_CTRL_TE;
	writel(tmp, &uart->ctrl);

	gd->arch.uart = uart;
	return 0;
}

static inline ambapp_dev_apbuart *leon3_get_uart_regs(void)
{
	ambapp_dev_apbuart *uart = gd->arch.uart;
	return uart;
}

static void leon3_serial_putc_raw(const char c)
{
	ambapp_dev_apbuart * const uart = leon3_get_uart_regs();

	if (!uart)
		return;

	/* Wait for last character to go. */
	while (!(readl(&uart->status) & LEON_REG_UART_STATUS_THE))
		WATCHDOG_RESET();

	/* Send data */
	writel(c, &uart->data);

#ifdef LEON_DEBUG
	/* Wait for data to be sent */
	while (!(readl(&uart->status) & LEON_REG_UART_STATUS_TSE))
		WATCHDOG_RESET();
#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)
{
	ambapp_dev_apbuart * const uart = leon3_get_uart_regs();

	if (!uart)
		return 0;

	/* Wait for a character to arrive. */
	while (!(readl(&uart->status) & LEON_REG_UART_STATUS_DR))
		WATCHDOG_RESET();

	/* Read character data */
	return readl(&uart->data);
}

static int leon3_serial_tstc(void)
{
	ambapp_dev_apbuart * const uart = leon3_get_uart_regs();

	if (!uart)
		return 0;

	return readl(&uart->status) & LEON_REG_UART_STATUS_DR;
}

/* set baud rate for uart */
static void leon3_serial_setbrg(void)
{
	ambapp_dev_apbuart * const uart = leon3_get_uart_regs();
	unsigned int scaler;

	if (!uart)
		return;

	if (!gd->baudrate)
		gd->baudrate = CONFIG_BAUDRATE;

	scaler = (((CONFIG_SYS_CLK_FREQ*10) / (gd->baudrate*8)) - 5)/10;

	writel(scaler, &uart->scaler);
}

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;
}
