/*
 * (c) 2015 Paul Thacker <paul.thacker@microchip.com>
 *
 * SPDX-License-Identifier:	GPL-2.0+
 *
 */
#include <common.h>
#include <clk.h>
#include <dm.h>
#include <serial.h>
#include <wait_bit.h>
#include <mach/pic32.h>
#include <dt-bindings/clock/microchip,clock.h>

DECLARE_GLOBAL_DATA_PTR;

/* UART Control Registers */
#define U_MOD		0x00
#define U_MODCLR	(U_MOD + _CLR_OFFSET)
#define U_MODSET	(U_MOD + _SET_OFFSET)
#define U_STA		0x10
#define U_STACLR	(U_STA + _CLR_OFFSET)
#define U_STASET	(U_STA + _SET_OFFSET)
#define U_TXR		0x20
#define U_RXR		0x30
#define U_BRG		0x40

/* U_MOD bits */
#define UART_ENABLE		BIT(15)

/* U_STA bits */
#define UART_RX_ENABLE		BIT(12)
#define UART_TX_BRK		BIT(11)
#define UART_TX_ENABLE		BIT(10)
#define UART_TX_FULL		BIT(9)
#define UART_TX_EMPTY		BIT(8)
#define UART_RX_OVER		BIT(1)
#define UART_RX_DATA_AVAIL	BIT(0)

struct pic32_uart_priv {
	void __iomem *base;
	ulong uartclk;
};

/*
 * Initialize the serial port with the given baudrate.
 * The settings are always 8 data bits, no parity, 1 stop bit, no start bits.
 */
static int pic32_serial_init(void __iomem *base, ulong clk, u32 baudrate)
{
	u32 div = DIV_ROUND_CLOSEST(clk, baudrate * 16);

	/* wait for TX FIFO to empty */
	wait_for_bit(__func__, base + U_STA, UART_TX_EMPTY,
		     true, CONFIG_SYS_HZ, false);

	/* send break */
	writel(UART_TX_BRK, base + U_STASET);

	/* disable and clear mode */
	writel(0, base + U_MOD);
	writel(0, base + U_STA);

	/* set baud rate generator */
	writel(div - 1, base + U_BRG);

	/* enable the UART for TX and RX */
	writel(UART_TX_ENABLE | UART_RX_ENABLE, base + U_STASET);

	/* enable the UART */
	writel(UART_ENABLE, base + U_MODSET);
	return 0;
}

/* Check whether any char pending in RX fifo */
static int pic32_uart_pending_input(void __iomem *base)
{
	/* check if rx buffer overrun error has occurred */
	if (readl(base + U_STA) & UART_RX_OVER) {
		readl(base + U_RXR);

		/* clear overrun error to keep receiving */
		writel(UART_RX_OVER, base + U_STACLR);
	}

	/* In PIC32 there is no way to know number of outstanding
	 * chars in rx-fifo. Only it can be known whether there is any.
	 */
	return readl(base + U_STA) & UART_RX_DATA_AVAIL;
}

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

	if (input)
		return pic32_uart_pending_input(priv->base);

	return !(readl(priv->base + U_STA) & UART_TX_EMPTY);
}

static int pic32_uart_setbrg(struct udevice *dev, int baudrate)
{
	struct pic32_uart_priv *priv = dev_get_priv(dev);

	return pic32_serial_init(priv->base, priv->uartclk, baudrate);
}

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

	/* Check if Tx FIFO is full */
	if (readl(priv->base + U_STA) & UART_TX_FULL)
		return -EAGAIN;

	/* pump the char to tx buffer */
	writel(ch, priv->base + U_TXR);

	return 0;
}

static int pic32_uart_getc(struct udevice *dev)
{
	struct pic32_uart_priv *priv = dev_get_priv(dev);

	/* return error if RX fifo is empty */
	if (!pic32_uart_pending_input(priv->base))
		return -EAGAIN;

	/* read the character from rx buffer */
	return readl(priv->base + U_RXR) & 0xff;
}

static int pic32_uart_probe(struct udevice *dev)
{
	struct pic32_uart_priv *priv = dev_get_priv(dev);
	struct udevice *clkdev;
	fdt_addr_t addr;
	fdt_size_t size;
	int ret;

	/* get address */
	addr = fdtdec_get_addr_size(gd->fdt_blob, dev->of_offset, "reg", &size);
	if (addr == FDT_ADDR_T_NONE)
		return -EINVAL;

	priv->base = ioremap(addr, size);

	/* get clock rate */
	ret = clk_get_by_index(dev, 0, &clkdev);
	if (ret < 0)
		return ret;
	priv->uartclk = clk_get_periph_rate(clkdev, ret);

	/* initialize serial */
	return pic32_serial_init(priv->base, priv->uartclk, CONFIG_BAUDRATE);
}

static const struct dm_serial_ops pic32_uart_ops = {
	.putc		= pic32_uart_putc,
	.pending	= pic32_uart_pending,
	.getc		= pic32_uart_getc,
	.setbrg		= pic32_uart_setbrg,
};

static const struct udevice_id pic32_uart_ids[] = {
	{ .compatible = "microchip,pic32mzda-uart" },
	{}
};

U_BOOT_DRIVER(pic32_serial) = {
	.name		= "pic32-uart",
	.id		= UCLASS_SERIAL,
	.of_match	= pic32_uart_ids,
	.probe		= pic32_uart_probe,
	.ops		= &pic32_uart_ops,
	.flags		= DM_FLAG_PRE_RELOC,
	.priv_auto_alloc_size = sizeof(struct pic32_uart_priv),
};

#ifdef CONFIG_DEBUG_UART_PIC32
#include <debug_uart.h>

static inline void _debug_uart_init(void)
{
	void __iomem *base = (void __iomem *)CONFIG_DEBUG_UART_BASE;

	pic32_serial_init(base, CONFIG_DEBUG_UART_CLOCK, CONFIG_BAUDRATE);
}

static inline void _debug_uart_putc(int ch)
{
	writel(ch, CONFIG_DEBUG_UART_BASE + U_TXR);
}

DEBUG_UART_FUNCS
#endif
