/*
 * drivers/trace/exynos-condbg-dev.c
 *
 * Copyright (c) 2016 Samsung Electronics Co., Ltd.
 *		http://www.samsung.com
 *
 * Exynos-Console-Debugger for Exynos SoC
 * This codes are based on fiq_debugger of google
 * /driver/staging/android/fiq_debugger
 *
 * Author: Hosung Kim <hosung0.kim@samsung.com>
 *         Changki Kim <changki.kim@samsung.com>
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 as
 * published by the Free Software Foundation.
 */

#include <linux/delay.h>
#include <linux/io.h>
#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/slab.h>
#include <linux/stacktrace.h>
#include <linux/uaccess.h>
#include <linux/of.h>
#include <linux/serial_s3c.h>

#include "exynos-condbg-dev.h"

struct ecd_dev {
	struct ecd_pdata pdata;
	struct platform_device *pdev;
	void __iomem *debug_port_base;
	int irq;
	u32 baud;
	u32 frac_baud;
};

static inline struct ecd_dev *get_dbg(struct platform_device *pdev)
{
	struct ecd_pdata *pdata = dev_get_platdata(&pdev->dev);
	return container_of(pdata, struct ecd_dev, pdata);
}

static inline void exynos_write(struct ecd_dev *dbg,
			       unsigned int val, unsigned int off)
{
	__raw_writel(val, dbg->debug_port_base + off);
}

static inline unsigned int exynos_read(struct ecd_dev *dbg,
				      unsigned int off)
{
	return __raw_readl(dbg->debug_port_base + off);
}

static int debug_port_init(struct platform_device *pdev)
{
	struct ecd_dev *dbg = get_dbg(pdev);
	unsigned long timeout;

	exynos_write(dbg, dbg->baud, S3C2410_UBRDIV);
	exynos_write(dbg, dbg->frac_baud, S3C2443_DIVSLOT);

	/* Mask and clear all interrupts */
	exynos_write(dbg, 0xF, S3C64XX_UINTM);
	exynos_write(dbg, 0xF, S3C64XX_UINTP);

	exynos_write(dbg, S3C2410_LCON_CS8, S3C2410_ULCON);
	exynos_write(dbg, S5PV210_UCON_DEFAULT, S3C2410_UCON);
	exynos_write(dbg, S5PV210_UFCON_DEFAULT, S3C2410_UFCON);
	exynos_write(dbg, 0, S3C2410_UMCON);

	/* Reset TX and RX fifos */
	exynos_write(dbg, S5PV210_UFCON_DEFAULT | S3C2410_UFCON_RESETBOTH,
		S3C2410_UFCON);

	timeout = jiffies + HZ;
	while (exynos_read(dbg, S3C2410_UFCON) & S3C2410_UFCON_RESETBOTH)
		if (time_after(jiffies, timeout))
			return -ETIMEDOUT;

	/* Enable all interrupts except TX */
	exynos_write(dbg, S3C64XX_UINTM_TXD_MSK, S3C64XX_UINTM);

	return 0;
}

static int debug_getc(struct platform_device *pdev)
{
	struct ecd_dev *dbg = get_dbg(pdev);
	u32 stat;
	int ret = DEBUGGER_NO_CHAR;

	/* Clear all pending interrupts */
	exynos_write(dbg, 0xF, S3C64XX_UINTP);

	stat = exynos_read(dbg, S3C2410_UERSTAT);
	if (stat & S3C2410_UERSTAT_BREAK)
		return DEBUGGER_BREAK;

	stat = exynos_read(dbg, S3C2410_UTRSTAT);
	if (stat & S3C2410_UTRSTAT_RXDR)
		ret = exynos_read(dbg, S3C2410_URXH);

	return ret;
}

static void debug_putc(struct platform_device *pdev, unsigned int c)
{
	struct ecd_dev *dbg = get_dbg(pdev);
	int count = loops_per_jiffy;

	if (exynos_read(dbg, S3C2410_ULCON) != S3C2410_LCON_CS8)
		debug_port_init(pdev);

	while (exynos_read(dbg, S3C2410_UFSTAT) & S5PV210_UFSTAT_TXFULL)
		if (--count == 0)
			return;

	exynos_write(dbg, c, S3C2410_UTXH);
}

static void debug_flush(struct platform_device *pdev)
{
	struct ecd_dev *dbg = get_dbg(pdev);
	int count = loops_per_jiffy * HZ;

	while (!(exynos_read(dbg, S3C2410_UTRSTAT) & S3C2410_UTRSTAT_TXE))
		if (--count == 0)
			return;
}

static void debug_clear_rxfifo(struct platform_device *pdev)
{
	struct ecd_dev *dbg = get_dbg(pdev);
	u32 ufcon;

	ufcon = exynos_read(dbg, S3C2410_UFCON);
	ufcon |= S3C2410_UFCON_RESETRX;
	exynos_write(dbg, ufcon, S3C2410_UFCON);
}

static int debug_suspend(struct platform_device *pdev)
{
	struct ecd_dev *dbg = get_dbg(pdev);
#ifdef CONFIG_SERIAL_SAMSUNG_HWACG
	u32 ucon;
#endif

	exynos_write(dbg, 0xF, S3C64XX_UINTM);

#ifdef CONFIG_SERIAL_SAMSUNG_HWACG
	ucon = exynos_read(dbg, S3C2410_UCON);
	ucon &= ~(S3C2410_UCON_RXIRQMODE | S3C2410_UCON_TXIRQMODE);
	exynos_write(dbg, ucon, S3C2410_UCON);
#endif

	return 0;
}

static int debug_resume(struct platform_device *pdev)
{
	debug_port_init(pdev);

	return 0;
}

static int ecd_dev_probe(struct platform_device *pdev)
{
	struct device_node *np;
	int uart_irq;
	unsigned int uart_port;
	int ret = -ENOMEM;
	struct ecd_dev *dbg = NULL;
	struct resource *res;

	if (initial_no_firmware)
		return -EINVAL;

	dbg = devm_kzalloc(&pdev->dev, sizeof(struct ecd_dev), GFP_KERNEL);
	if (!dbg) {
		dev_err(&pdev->dev, "Failed to allocate dbg structure\n");
		return -ENOMEM;
	}

	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
	if (!res) {
		dev_err(&pdev->dev, "No mem resource\n");
		return -EINVAL;
	}

	dbg->debug_port_base = devm_ioremap_resource(&pdev->dev, res);
	if (dbg->debug_port_base == NULL) {
		dev_err(&pdev->dev, "failed to claim register region\n");
		return -ENOENT;
	}

	res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
	if (!res)
		return -ENXIO;

	uart_irq = platform_get_irq_byname(pdev, "uart_irq");
	if (uart_irq < 0) {
		dev_err(&pdev->dev, "No IRQ for uart_irq, error=%d\n", uart_irq);
		return uart_irq;
	}

	np = pdev->dev.of_node;
	of_property_read_u32(np, "uart_port", &uart_port);
	if (uart_port > CONFIG_SERIAL_SAMSUNG_UARTS) {
		dev_err(&pdev->dev, "wrong descriptor for uart_port, error=%d\n", uart_port);
		return -EINVAL;
	}

	pdev = kzalloc(sizeof(struct platform_device), GFP_KERNEL);
	if(!pdev) {
		pr_err("Failed to alloc ecd_dev platform device\n");
		goto err_pdev;
	}

	dbg->pdata.uart_init = debug_port_init;
	dbg->pdata.uart_getc = debug_getc;
	dbg->pdata.uart_putc = debug_putc;
	dbg->pdata.uart_flush = debug_flush;
	dbg->pdata.uart_clear_rxfifo = debug_clear_rxfifo;
	dbg->pdata.uart_dev_suspend = debug_suspend;
	dbg->pdata.uart_dev_resume = debug_resume;

	dbg->pdev = pdev;
	dbg->baud = exynos_read(dbg, S3C2410_UBRDIV);
	dbg->frac_baud = exynos_read(dbg, S3C2443_DIVSLOT);

	pdev->name = "console_debugger";
	pdev->id = uart_port;
	pdev->dev.platform_data = &dbg->pdata;
	pdev->resource = res;
	pdev->num_resources = 1;

	if (platform_device_register(pdev)) {
		pr_err("Failed to register ecd_dev \n");
		goto err_free;
	}

	pr_info("Success to register ECD UART\n");
	return 0;

err_pdev:
	kfree(pdev);
err_free:
	kfree(dbg);
	return ret;
}

static const struct of_device_id ecd_dev_match[] = {
	{.compatible = "samsung,exynos_console_debugger",},
	{},
};

static struct platform_driver ecd_dev_driver = {
	.probe      = ecd_dev_probe,
	.driver     = {
		.name   = "exynos_console_debugger",
		.owner  = THIS_MODULE,
		.of_match_table = of_match_ptr(ecd_dev_match),
	},
};

static int __init ecd_dev_init(void)
{
	return platform_driver_register(&ecd_dev_driver);
}

postcore_initcall_sync(ecd_dev_init);
