/*
 * Support for Serial I/O using STMicroelectronics' on-chip ASC.
 *
 *  Copyright (c) 2017
 *  Patrice Chotard <patrice.chotard@st.com>
 *
 * SPDX-License-Identifier:	GPL-2.0
 */

#include <common.h>
#include <dm.h>
#include <serial.h>
#include <asm/io.h>

DECLARE_GLOBAL_DATA_PTR;

#define BAUDMODE	0x00001000
#define RXENABLE	0x00000100
#define RUN		0x00000080
#define MODE		0x00000001
#define MODE_8BIT	0x0001
#define STOP_1BIT	0x0008
#define PARITYODD	0x0020

#define STA_TF		BIT(9)
#define STA_RBF		BIT(0)

struct sti_asc_uart {
	u32 baudrate;
	u32 txbuf;
	u32 rxbuf;
	u32 control;
	u32 inten;
	u32 status;
	u32 guardtime;
	u32 timeout;
	u32 txreset;
	u32 rxreset;
};

struct sti_asc_serial {
	/* address of registers in physical memory */
	struct sti_asc_uart *regs;
};

/* Values for the BAUDRATE Register */
#define PCLK			(200ul * 1000000ul)
#define BAUDRATE_VAL_M0(bps)	(PCLK / (16 * (bps)))
#define BAUDRATE_VAL_M1(bps)	((bps * (1 << 14)) + (1<<13)) / (PCLK/(1 << 6))

/*
 * MODE 0
 *                       ICCLK
 * ASCBaudRate =   ----------------
 *                   baudrate * 16
 *
 * MODE 1
 *                   baudrate * 16 * 2^16
 * ASCBaudRate =   ------------------------
 *                          ICCLK
 *
 * NOTE:
 * Mode 1 should be used for baudrates of 19200, and above, as it
 * has a lower deviation error than Mode 0 for higher frequencies.
 * Mode 0 should be used for all baudrates below 19200.
 */

static int sti_asc_pending(struct udevice *dev, bool input)
{
	struct sti_asc_serial *priv = dev_get_priv(dev);
	struct sti_asc_uart *const uart = priv->regs;
	unsigned long status;

	status = readl(&uart->status);
	if (input)
		return status & STA_RBF;
	else
		return status & STA_TF;
}

static int _sti_asc_serial_setbrg(struct sti_asc_uart *uart, int baudrate)
{
	unsigned long val;
	int t, mode = 1;

	switch (baudrate) {
	case 9600:
		t = BAUDRATE_VAL_M0(9600);
		mode = 0;
		break;
	case 19200:
		t = BAUDRATE_VAL_M1(19200);
		break;
	case 38400:
		t = BAUDRATE_VAL_M1(38400);
		break;
	case 57600:
		t = BAUDRATE_VAL_M1(57600);
		break;
	default:
		debug("ASC: unsupported baud rate: %d, using 115200 instead.\n",
		      baudrate);
	case 115200:
		t = BAUDRATE_VAL_M1(115200);
		break;
	}

	/* disable the baudrate generator */
	val = readl(&uart->control);
	writel(val & ~RUN, &uart->control);

	/* set baud generator reload value */
	writel(t, &uart->baudrate);
	/* reset the RX & TX buffers */
	writel(1, &uart->txreset);
	writel(1, &uart->rxreset);

	/* set baud generator mode */
	if (mode)
		val |= BAUDMODE;

	/* finally, write value and enable ASC */
	writel(val, &uart->control);

	return 0;
}

/* called to adjust baud-rate */
static int sti_asc_serial_setbrg(struct udevice *dev, int baudrate)
{
	struct sti_asc_serial *priv = dev_get_priv(dev);
	struct sti_asc_uart *const uart = priv->regs;

	return _sti_asc_serial_setbrg(uart, baudrate);
}

/* blocking function, that returns next char */
static int sti_asc_serial_getc(struct udevice *dev)
{
	struct sti_asc_serial *priv = dev_get_priv(dev);
	struct sti_asc_uart *const uart = priv->regs;

	/* polling wait: for a char to be read */
	if (!sti_asc_pending(dev, true))
		return -EAGAIN;

	return readl(&uart->rxbuf);
}

/* write write out a single char */
static int sti_asc_serial_putc(struct udevice *dev, const char c)
{
	struct sti_asc_serial *priv = dev_get_priv(dev);
	struct sti_asc_uart *const uart = priv->regs;

	/* wait till safe to write next char */
	if (sti_asc_pending(dev, false))
		return -EAGAIN;

	/* finally, write next char */
	writel(c, &uart->txbuf);

	return 0;
}

/* initialize the ASC */
static int sti_asc_serial_probe(struct udevice *dev)
{
	struct sti_asc_serial *priv = dev_get_priv(dev);
	unsigned long val;
	fdt_addr_t base;

	base = devfdt_get_addr(dev);
	if (base == FDT_ADDR_T_NONE)
		return -EINVAL;

	priv->regs = (struct sti_asc_uart *)base;
	sti_asc_serial_setbrg(dev, gd->baudrate);

	/*
	 * build up the value to be written to CONTROL
	 * set character length, bit stop number, odd parity
	 */
	val = RXENABLE | RUN | MODE_8BIT | STOP_1BIT | PARITYODD;
	writel(val, &priv->regs->control);

	return 0;
}

static const struct dm_serial_ops sti_asc_serial_ops = {
	.putc = sti_asc_serial_putc,
	.pending = sti_asc_pending,
	.getc = sti_asc_serial_getc,
	.setbrg = sti_asc_serial_setbrg,
};

static const struct udevice_id sti_serial_of_match[] = {
	{ .compatible = "st,asc" },
	{ }
};

U_BOOT_DRIVER(serial_sti_asc) = {
	.name = "serial_sti_asc",
	.id = UCLASS_SERIAL,
	.of_match = sti_serial_of_match,
	.ops = &sti_asc_serial_ops,
	.probe = sti_asc_serial_probe,
	.priv_auto_alloc_size = sizeof(struct sti_asc_serial),
	.flags = DM_FLAG_PRE_RELOC,
};

