/*
 * SuperH SCIF device driver.
 * Copyright (C) 2013  Renesas Electronics Corporation
 * Copyright (C) 2007,2008,2010, 2014 Nobuhiro Iwamatsu
 * Copyright (C) 2002 - 2008  Paul Mundt
 *
 * SPDX-License-Identifier:	GPL-2.0+
 */

#include <common.h>
#include <errno.h>
#include <dm.h>
#include <asm/io.h>
#include <asm/processor.h>
#include <serial.h>
#include <linux/compiler.h>
#include <dm/platform_data/serial_sh.h>
#include "serial_sh.h"

#if defined(CONFIG_CPU_SH7760) || \
	defined(CONFIG_CPU_SH7780) || \
	defined(CONFIG_CPU_SH7785) || \
	defined(CONFIG_CPU_SH7786)
static int scif_rxfill(struct uart_port *port)
{
	return sci_in(port, SCRFDR) & 0xff;
}
#elif defined(CONFIG_CPU_SH7763)
static int scif_rxfill(struct uart_port *port)
{
	if ((port->mapbase == 0xffe00000) ||
	    (port->mapbase == 0xffe08000)) {
		/* SCIF0/1*/
		return sci_in(port, SCRFDR) & 0xff;
	} else {
		/* SCIF2 */
		return sci_in(port, SCFDR) & SCIF2_RFDC_MASK;
	}
}
#elif defined(CONFIG_ARCH_SH7372)
static int scif_rxfill(struct uart_port *port)
{
	if (port->type == PORT_SCIFA)
		return sci_in(port, SCFDR) & SCIF_RFDC_MASK;
	else
		return sci_in(port, SCRFDR);
}
#else
static int scif_rxfill(struct uart_port *port)
{
	return sci_in(port, SCFDR) & SCIF_RFDC_MASK;
}
#endif

static void sh_serial_init_generic(struct uart_port *port)
{
	sci_out(port, SCSCR , SCSCR_INIT(port));
	sci_out(port, SCSCR , SCSCR_INIT(port));
	sci_out(port, SCSMR, 0);
	sci_out(port, SCSMR, 0);
	sci_out(port, SCFCR, SCFCR_RFRST|SCFCR_TFRST);
	sci_in(port, SCFCR);
	sci_out(port, SCFCR, 0);
}

static void
sh_serial_setbrg_generic(struct uart_port *port, int clk, int baudrate)
{
	if (port->clk_mode == EXT_CLK) {
		unsigned short dl = DL_VALUE(baudrate, clk);
		sci_out(port, DL, dl);
		/* Need wait: Clock * 1/dl $B!_(B 1/16 */
		udelay((1000000 * dl * 16 / clk) * 1000 + 1);
	} else {
		sci_out(port, SCBRR, SCBRR_VALUE(baudrate, clk));
	}
}

static void handle_error(struct uart_port *port)
{
	sci_in(port, SCxSR);
	sci_out(port, SCxSR, SCxSR_ERROR_CLEAR(port));
	sci_in(port, SCLSR);
	sci_out(port, SCLSR, 0x00);
}

static int serial_raw_putc(struct uart_port *port, const char c)
{
	/* Tx fifo is empty */
	if (!(sci_in(port, SCxSR) & SCxSR_TEND(port)))
		return -EAGAIN;

	sci_out(port, SCxTDR, c);
	sci_out(port, SCxSR, sci_in(port, SCxSR) & ~SCxSR_TEND(port));

	return 0;
}

static int serial_rx_fifo_level(struct uart_port *port)
{
	return scif_rxfill(port);
}

static int sh_serial_tstc_generic(struct uart_port *port)
{
	if (sci_in(port, SCxSR) & SCIF_ERRORS) {
		handle_error(port);
		return 0;
	}

	return serial_rx_fifo_level(port) ? 1 : 0;
}

static int serial_getc_check(struct uart_port *port)
{
	unsigned short status;

	status = sci_in(port, SCxSR);

	if (status & SCIF_ERRORS)
		handle_error(port);
	if (sci_in(port, SCLSR) & SCxSR_ORER(port))
		handle_error(port);
	return status & (SCIF_DR | SCxSR_RDxF(port));
}

static int sh_serial_getc_generic(struct uart_port *port)
{
	unsigned short status;
	char ch;

	if (!serial_getc_check(port))
		return -EAGAIN;

	ch = sci_in(port, SCxRDR);
	status = sci_in(port, SCxSR);

	sci_out(port, SCxSR, SCxSR_RDxF_CLEAR(port));

	if (status & SCIF_ERRORS)
		handle_error(port);

	if (sci_in(port, SCLSR) & SCxSR_ORER(port))
		handle_error(port);

	return ch;
}

#ifdef CONFIG_DM_SERIAL

static int sh_serial_pending(struct udevice *dev, bool input)
{
	struct uart_port *priv = dev_get_priv(dev);

	return sh_serial_tstc_generic(priv);
}

static int sh_serial_putc(struct udevice *dev, const char ch)
{
	struct uart_port *priv = dev_get_priv(dev);

	return serial_raw_putc(priv, ch);
}

static int sh_serial_getc(struct udevice *dev)
{
	struct uart_port *priv = dev_get_priv(dev);

	return sh_serial_getc_generic(priv);
}

static int sh_serial_setbrg(struct udevice *dev, int baudrate)
{
	struct sh_serial_platdata *plat = dev_get_platdata(dev);
	struct uart_port *priv = dev_get_priv(dev);

	sh_serial_setbrg_generic(priv, plat->clk, baudrate);

	return 0;
}

static int sh_serial_probe(struct udevice *dev)
{
	struct sh_serial_platdata *plat = dev_get_platdata(dev);
	struct uart_port *priv = dev_get_priv(dev);

	priv->membase	= (unsigned char *)plat->base;
	priv->mapbase	= plat->base;
	priv->type	= plat->type;
	priv->clk_mode	= plat->clk_mode;

	sh_serial_init_generic(priv);

	return 0;
}

static const struct dm_serial_ops sh_serial_ops = {
	.putc = sh_serial_putc,
	.pending = sh_serial_pending,
	.getc = sh_serial_getc,
	.setbrg = sh_serial_setbrg,
};

U_BOOT_DRIVER(serial_sh) = {
	.name	= "serial_sh",
	.id	= UCLASS_SERIAL,
	.probe	= sh_serial_probe,
	.ops	= &sh_serial_ops,
	.flags	= DM_FLAG_PRE_RELOC,
	.priv_auto_alloc_size = sizeof(struct uart_port),
};

#else /* CONFIG_DM_SERIAL */

#if defined(CONFIG_CONS_SCIF0)
# define SCIF_BASE	SCIF0_BASE
#elif defined(CONFIG_CONS_SCIF1)
# define SCIF_BASE	SCIF1_BASE
#elif defined(CONFIG_CONS_SCIF2)
# define SCIF_BASE	SCIF2_BASE
#elif defined(CONFIG_CONS_SCIF3)
# define SCIF_BASE	SCIF3_BASE
#elif defined(CONFIG_CONS_SCIF4)
# define SCIF_BASE	SCIF4_BASE
#elif defined(CONFIG_CONS_SCIF5)
# define SCIF_BASE	SCIF5_BASE
#elif defined(CONFIG_CONS_SCIF6)
# define SCIF_BASE	SCIF6_BASE
#elif defined(CONFIG_CONS_SCIF7)
# define SCIF_BASE	SCIF7_BASE
#else
# error "Default SCIF doesn't set....."
#endif

#if defined(CONFIG_SCIF_A)
	#define SCIF_BASE_PORT	PORT_SCIFA
#else
	#define SCIF_BASE_PORT	PORT_SCIF
#endif

static struct uart_port sh_sci = {
	.membase	= (unsigned char *)SCIF_BASE,
	.mapbase	= SCIF_BASE,
	.type		= SCIF_BASE_PORT,
#ifdef CONFIG_SCIF_USE_EXT_CLK
	.clk_mode =	EXT_CLK,
#endif
};

static void sh_serial_setbrg(void)
{
	DECLARE_GLOBAL_DATA_PTR;
	struct uart_port *port = &sh_sci;

	sh_serial_setbrg_generic(port, CONFIG_SH_SCIF_CLK_FREQ, gd->baudrate);
}

static int sh_serial_init(void)
{
	struct uart_port *port = &sh_sci;

	sh_serial_init_generic(port);
	serial_setbrg();

	return 0;
}

static void sh_serial_putc(const char c)
{
	struct uart_port *port = &sh_sci;

	if (c == '\n') {
		while (1) {
			if  (serial_raw_putc(port, '\r') != -EAGAIN)
				break;
		}
	}
	while (1) {
		if  (serial_raw_putc(port, c) != -EAGAIN)
			break;
	}
}

static int sh_serial_tstc(void)
{
	struct uart_port *port = &sh_sci;

	return sh_serial_tstc_generic(port);
}

static int sh_serial_getc(void)
{
	struct uart_port *port = &sh_sci;
	int ch;

	while (1) {
		ch = sh_serial_getc_generic(port);
		if (ch != -EAGAIN)
			break;
	}

	return ch;
}

static struct serial_device sh_serial_drv = {
	.name	= "sh_serial",
	.start	= sh_serial_init,
	.stop	= NULL,
	.setbrg	= sh_serial_setbrg,
	.putc	= sh_serial_putc,
	.puts	= default_serial_puts,
	.getc	= sh_serial_getc,
	.tstc	= sh_serial_tstc,
};

void sh_serial_initialize(void)
{
	serial_register(&sh_serial_drv);
}

__weak struct serial_device *default_serial_console(void)
{
	return &sh_serial_drv;
}
#endif /* CONFIG_DM_SERIAL */
