// SPDX-License-Identifier: GPL-2.0+
/*
 * Support for Serial I/O using STMicroelectronics' on-chip ASC.
 *
 * Copyright (C) 2017, STMicroelectronics - All Rights Reserved
 * Author(s): Patrice Chotard, <patrice.chotard@st.com> for STMicroelectronics.
 */

#include <common.h>
#include <dm.h>
#include <log.h>
#include <serial.h>
#include <asm/io.h>
#include <linux/bitops.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 = dev_read_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	= sizeof(struct sti_asc_serial),
};

