/*
 * exynos-nocp.c - EXYNOS NoC (Network On Chip) Probe support
 *
 * Copyright (c) 2016 Samsung Electronics Co., Ltd.
 * Author : Chanwoo Choi <cw00.choi@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/clk.h>
#include <linux/module.h>
#include <linux/devfreq-event.h>
#include <linux/kernel.h>
#include <linux/of_address.h>
#include <linux/platform_device.h>
#include <linux/regmap.h>

#include "exynos-nocp.h"

struct exynos_nocp {
	struct devfreq_event_dev *edev;
	struct devfreq_event_desc desc;

	struct device *dev;

	struct regmap *regmap;
	struct clk *clk;
};

/*
 * The devfreq-event ops structure for nocp probe.
 */
static int exynos_nocp_set_event(struct devfreq_event_dev *edev)
{
	struct exynos_nocp *nocp = devfreq_event_get_drvdata(edev);
	int ret;

	/* Disable NoC probe */
	ret = regmap_update_bits(nocp->regmap, NOCP_MAIN_CTL,
				NOCP_MAIN_CTL_STATEN_MASK, 0);
	if (ret < 0) {
		dev_err(nocp->dev, "failed to disable the NoC probe device\n");
		return ret;
	}

	/* Set a statistics dump period to 0 */
	ret = regmap_write(nocp->regmap, NOCP_STAT_PERIOD, 0x0);
	if (ret < 0)
		goto out;

	/* Set the IntEvent fields of *_SRC */
	ret = regmap_update_bits(nocp->regmap, NOCP_COUNTERS_0_SRC,
				NOCP_CNT_SRC_INTEVENT_MASK,
				NOCP_CNT_SRC_INTEVENT_BYTE_MASK);
	if (ret < 0)
		goto out;

	ret = regmap_update_bits(nocp->regmap, NOCP_COUNTERS_1_SRC,
				NOCP_CNT_SRC_INTEVENT_MASK,
				NOCP_CNT_SRC_INTEVENT_CHAIN_MASK);
	if (ret < 0)
		goto out;

	ret = regmap_update_bits(nocp->regmap, NOCP_COUNTERS_2_SRC,
				NOCP_CNT_SRC_INTEVENT_MASK,
				NOCP_CNT_SRC_INTEVENT_CYCLE_MASK);
	if (ret < 0)
		goto out;

	ret = regmap_update_bits(nocp->regmap, NOCP_COUNTERS_3_SRC,
				NOCP_CNT_SRC_INTEVENT_MASK,
				NOCP_CNT_SRC_INTEVENT_CHAIN_MASK);
	if (ret < 0)
		goto out;


	/* Set an alarm with a max/min value of 0 to generate StatALARM */
	ret = regmap_write(nocp->regmap, NOCP_STAT_ALARM_MIN, 0x0);
	if (ret < 0)
		goto out;

	ret = regmap_write(nocp->regmap, NOCP_STAT_ALARM_MAX, 0x0);
	if (ret < 0)
		goto out;

	/* Set AlarmMode */
	ret = regmap_update_bits(nocp->regmap, NOCP_COUNTERS_0_ALARM_MODE,
				NOCP_CNT_ALARM_MODE_MASK,
				NOCP_CNT_ALARM_MODE_MIN_MAX_MASK);
	if (ret < 0)
		goto out;

	ret = regmap_update_bits(nocp->regmap, NOCP_COUNTERS_1_ALARM_MODE,
				NOCP_CNT_ALARM_MODE_MASK,
				NOCP_CNT_ALARM_MODE_MIN_MAX_MASK);
	if (ret < 0)
		goto out;

	ret = regmap_update_bits(nocp->regmap, NOCP_COUNTERS_2_ALARM_MODE,
				NOCP_CNT_ALARM_MODE_MASK,
				NOCP_CNT_ALARM_MODE_MIN_MAX_MASK);
	if (ret < 0)
		goto out;

	ret = regmap_update_bits(nocp->regmap, NOCP_COUNTERS_3_ALARM_MODE,
				NOCP_CNT_ALARM_MODE_MASK,
				NOCP_CNT_ALARM_MODE_MIN_MAX_MASK);
	if (ret < 0)
		goto out;

	/* Enable the measurements by setting AlarmEn and StatEn */
	ret = regmap_update_bits(nocp->regmap, NOCP_MAIN_CTL,
			NOCP_MAIN_CTL_STATEN_MASK | NOCP_MAIN_CTL_ALARMEN_MASK,
			NOCP_MAIN_CTL_STATEN_MASK | NOCP_MAIN_CTL_ALARMEN_MASK);
	if (ret < 0)
		goto out;

	/* Set GlobalEN */
	ret = regmap_update_bits(nocp->regmap, NOCP_CFG_CTL,
				NOCP_CFG_CTL_GLOBALEN_MASK,
				NOCP_CFG_CTL_GLOBALEN_MASK);
	if (ret < 0)
		goto out;

	/* Enable NoC probe */
	ret = regmap_update_bits(nocp->regmap, NOCP_MAIN_CTL,
				NOCP_MAIN_CTL_STATEN_MASK,
				NOCP_MAIN_CTL_STATEN_MASK);
	if (ret < 0)
		goto out;

	return 0;

out:
	/* Reset NoC probe */
	if (regmap_update_bits(nocp->regmap, NOCP_MAIN_CTL,
				NOCP_MAIN_CTL_STATEN_MASK, 0)) {
		dev_err(nocp->dev, "Failed to reset NoC probe device\n");
	}

	return ret;
}

static int exynos_nocp_get_event(struct devfreq_event_dev *edev,
				struct devfreq_event_data *edata)
{
	struct exynos_nocp *nocp = devfreq_event_get_drvdata(edev);
	unsigned int counter[4];
	int ret;

	/* Read cycle count */
	ret = regmap_read(nocp->regmap, NOCP_COUNTERS_0_VAL, &counter[0]);
	if (ret < 0)
		goto out;

	ret = regmap_read(nocp->regmap, NOCP_COUNTERS_1_VAL, &counter[1]);
	if (ret < 0)
		goto out;

	ret = regmap_read(nocp->regmap, NOCP_COUNTERS_2_VAL, &counter[2]);
	if (ret < 0)
		goto out;

	ret = regmap_read(nocp->regmap, NOCP_COUNTERS_3_VAL, &counter[3]);
	if (ret < 0)
		goto out;

	edata->load_count = ((counter[1] << 16) | counter[0]);
	edata->total_count = ((counter[3] << 16) | counter[2]);

	dev_dbg(&edev->dev, "%s (event: %ld/%ld)\n", edev->desc->name,
					edata->load_count, edata->total_count);

	return 0;

out:
	dev_err(nocp->dev, "Failed to read the counter of NoC probe device\n");

	return ret;
}

static const struct devfreq_event_ops exynos_nocp_ops = {
	.set_event = exynos_nocp_set_event,
	.get_event = exynos_nocp_get_event,
};

static const struct of_device_id exynos_nocp_id_match[] = {
	{ .compatible = "samsung,exynos5420-nocp", },
	{ /* sentinel */ },
};

static struct regmap_config exynos_nocp_regmap_config = {
	.reg_bits = 32,
	.val_bits = 32,
	.reg_stride = 4,
	.max_register = NOCP_COUNTERS_3_VAL,
};

static int exynos_nocp_parse_dt(struct platform_device *pdev,
				struct exynos_nocp *nocp)
{
	struct device *dev = nocp->dev;
	struct device_node *np = dev->of_node;
	struct resource *res;
	void __iomem *base;

	if (!np) {
		dev_err(dev, "failed to find devicetree node\n");
		return -EINVAL;
	}

	nocp->clk = devm_clk_get(dev, "nocp");
	if (IS_ERR(nocp->clk))
		nocp->clk = NULL;

	/* Maps the memory mapped IO to control nocp register */
	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
	base = devm_ioremap_resource(dev, res);
	if (IS_ERR(base))
		return PTR_ERR(base);

	exynos_nocp_regmap_config.max_register = resource_size(res) - 4;

	nocp->regmap = devm_regmap_init_mmio(dev, base,
					&exynos_nocp_regmap_config);
	if (IS_ERR(nocp->regmap)) {
		dev_err(dev, "failed to initialize regmap\n");
		return PTR_ERR(nocp->regmap);
	}

	return 0;
}

static int exynos_nocp_probe(struct platform_device *pdev)
{
	struct device *dev = &pdev->dev;
	struct device_node *np = dev->of_node;
	struct exynos_nocp *nocp;
	int ret;

	nocp = devm_kzalloc(&pdev->dev, sizeof(*nocp), GFP_KERNEL);
	if (!nocp)
		return -ENOMEM;

	nocp->dev = &pdev->dev;

	/* Parse dt data to get resource */
	ret = exynos_nocp_parse_dt(pdev, nocp);
	if (ret < 0) {
		dev_err(&pdev->dev,
			"failed to parse devicetree for resource\n");
		return ret;
	}

	/* Add devfreq-event device to measure the bandwidth of NoC */
	nocp->desc.ops = &exynos_nocp_ops;
	nocp->desc.driver_data = nocp;
	nocp->desc.name = np->full_name;
	nocp->edev = devm_devfreq_event_add_edev(&pdev->dev, &nocp->desc);
	if (IS_ERR(nocp->edev)) {
		dev_err(&pdev->dev,
			"failed to add devfreq-event device\n");
		return PTR_ERR(nocp->edev);
	}
	platform_set_drvdata(pdev, nocp);

	clk_prepare_enable(nocp->clk);

	pr_info("exynos-nocp: new NoC Probe device registered: %s\n",
			dev_name(dev));

	return 0;
}

static int exynos_nocp_remove(struct platform_device *pdev)
{
	struct exynos_nocp *nocp = platform_get_drvdata(pdev);

	clk_disable_unprepare(nocp->clk);

	return 0;
}

static struct platform_driver exynos_nocp_driver = {
	.probe	= exynos_nocp_probe,
	.remove	= exynos_nocp_remove,
	.driver = {
		.name	= "exynos-nocp",
		.of_match_table = exynos_nocp_id_match,
	},
};
module_platform_driver(exynos_nocp_driver);

MODULE_DESCRIPTION("Exynos NoC (Network on Chip) Probe driver");
MODULE_AUTHOR("Chanwoo Choi <cw00.choi@samsung.com>");
MODULE_LICENSE("GPL");
