/*
 * Intel(R) Trace Hub PTI output driver
 *
 * Copyright (C) 2014-2016 Intel Corporation.
 *
 * This program is free software; you can redistribute it and/or modify it
 * under the terms and conditions of the GNU General Public License,
 * version 2, as published by the Free Software Foundation.
 *
 * This program is distributed in the hope it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
 * more details.
 */

#define pr_fmt(fmt)	KBUILD_MODNAME ": " fmt

#include <linux/types.h>
#include <linux/module.h>
#include <linux/device.h>
#include <linux/sizes.h>
#include <linux/printk.h>
#include <linux/slab.h>
#include <linux/mm.h>
#include <linux/io.h>

#include "intel_th.h"
#include "pti.h"

struct pti_device {
	void __iomem		*base;
	struct intel_th_device	*thdev;
	unsigned int		mode;
	unsigned int		freeclk;
	unsigned int		clkdiv;
	unsigned int		patgen;
	unsigned int		lpp_dest_mask;
	unsigned int		lpp_dest;
};

/* map PTI widths to MODE settings of PTI_CTL register */
static const unsigned int pti_mode[] = {
	0, 4, 8, 0, 12, 0, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0,
};

static int pti_width_mode(unsigned int width)
{
	int i;

	for (i = 0; i < ARRAY_SIZE(pti_mode); i++)
		if (pti_mode[i] == width)
			return i;

	return -EINVAL;
}

static ssize_t mode_show(struct device *dev, struct device_attribute *attr,
			 char *buf)
{
	struct pti_device *pti = dev_get_drvdata(dev);

	return scnprintf(buf, PAGE_SIZE, "%d\n", pti_mode[pti->mode]);
}

static ssize_t mode_store(struct device *dev, struct device_attribute *attr,
			  const char *buf, size_t size)
{
	struct pti_device *pti = dev_get_drvdata(dev);
	unsigned long val;
	int ret;

	ret = kstrtoul(buf, 10, &val);
	if (ret)
		return ret;

	ret = pti_width_mode(val);
	if (ret < 0)
		return ret;

	pti->mode = ret;

	return size;
}

static DEVICE_ATTR_RW(mode);

static ssize_t
freerunning_clock_show(struct device *dev, struct device_attribute *attr,
		       char *buf)
{
	struct pti_device *pti = dev_get_drvdata(dev);

	return scnprintf(buf, PAGE_SIZE, "%d\n", pti->freeclk);
}

static ssize_t
freerunning_clock_store(struct device *dev, struct device_attribute *attr,
			const char *buf, size_t size)
{
	struct pti_device *pti = dev_get_drvdata(dev);
	unsigned long val;
	int ret;

	ret = kstrtoul(buf, 10, &val);
	if (ret)
		return ret;

	pti->freeclk = !!val;

	return size;
}

static DEVICE_ATTR_RW(freerunning_clock);

static ssize_t
clock_divider_show(struct device *dev, struct device_attribute *attr,
		   char *buf)
{
	struct pti_device *pti = dev_get_drvdata(dev);

	return scnprintf(buf, PAGE_SIZE, "%d\n", 1u << pti->clkdiv);
}

static ssize_t
clock_divider_store(struct device *dev, struct device_attribute *attr,
		    const char *buf, size_t size)
{
	struct pti_device *pti = dev_get_drvdata(dev);
	unsigned long val;
	int ret;

	ret = kstrtoul(buf, 10, &val);
	if (ret)
		return ret;

	if (!is_power_of_2(val) || val > 8 || !val)
		return -EINVAL;

	pti->clkdiv = val;

	return size;
}

static DEVICE_ATTR_RW(clock_divider);

static struct attribute *pti_output_attrs[] = {
	&dev_attr_mode.attr,
	&dev_attr_freerunning_clock.attr,
	&dev_attr_clock_divider.attr,
	NULL,
};

static struct attribute_group pti_output_group = {
	.attrs	= pti_output_attrs,
};

static int intel_th_pti_activate(struct intel_th_device *thdev)
{
	struct pti_device *pti = dev_get_drvdata(&thdev->dev);
	u32 ctl = PTI_EN;

	if (pti->patgen)
		ctl |= pti->patgen << __ffs(PTI_PATGENMODE);
	if (pti->freeclk)
		ctl |= PTI_FCEN;
	ctl |= pti->mode << __ffs(PTI_MODE);
	ctl |= pti->clkdiv << __ffs(PTI_CLKDIV);
	ctl |= pti->lpp_dest << __ffs(LPP_DEST);

	iowrite32(ctl, pti->base + REG_PTI_CTL);

	intel_th_trace_enable(thdev);

	return 0;
}

static void intel_th_pti_deactivate(struct intel_th_device *thdev)
{
	struct pti_device *pti = dev_get_drvdata(&thdev->dev);

	intel_th_trace_disable(thdev);

	iowrite32(0, pti->base + REG_PTI_CTL);
}

static void read_hw_config(struct pti_device *pti)
{
	u32 ctl = ioread32(pti->base + REG_PTI_CTL);

	pti->mode	= (ctl & PTI_MODE) >> __ffs(PTI_MODE);
	pti->clkdiv	= (ctl & PTI_CLKDIV) >> __ffs(PTI_CLKDIV);
	pti->freeclk	= !!(ctl & PTI_FCEN);

	if (!pti_mode[pti->mode])
		pti->mode = pti_width_mode(4);
	if (!pti->clkdiv)
		pti->clkdiv = 1;

	if (pti->thdev->output.type == GTH_LPP) {
		if (ctl & LPP_PTIPRESENT)
			pti->lpp_dest_mask |= LPP_DEST_PTI;
		if (ctl & LPP_BSSBPRESENT)
			pti->lpp_dest_mask |= LPP_DEST_EXI;
		if (ctl & LPP_DEST)
			pti->lpp_dest = 1;
	}
}

static int intel_th_pti_probe(struct intel_th_device *thdev)
{
	struct device *dev = &thdev->dev;
	struct resource *res;
	struct pti_device *pti;
	void __iomem *base;

	res = intel_th_device_get_resource(thdev, IORESOURCE_MEM, 0);
	if (!res)
		return -ENODEV;

	base = devm_ioremap(dev, res->start, resource_size(res));
	if (!base)
		return -ENOMEM;

	pti = devm_kzalloc(dev, sizeof(*pti), GFP_KERNEL);
	if (!pti)
		return -ENOMEM;

	pti->thdev = thdev;
	pti->base = base;

	read_hw_config(pti);

	dev_set_drvdata(dev, pti);

	return 0;
}

static void intel_th_pti_remove(struct intel_th_device *thdev)
{
}

static struct intel_th_driver intel_th_pti_driver = {
	.probe	= intel_th_pti_probe,
	.remove	= intel_th_pti_remove,
	.activate	= intel_th_pti_activate,
	.deactivate	= intel_th_pti_deactivate,
	.attr_group	= &pti_output_group,
	.driver	= {
		.name	= "pti",
		.owner	= THIS_MODULE,
	},
};

static const char * const lpp_dest_str[] = { "pti", "exi" };

static ssize_t lpp_dest_show(struct device *dev, struct device_attribute *attr,
			     char *buf)
{
	struct pti_device *pti = dev_get_drvdata(dev);
	ssize_t ret = 0;
	int i;

	for (i = ARRAY_SIZE(lpp_dest_str) - 1; i >= 0; i--) {
		const char *fmt = pti->lpp_dest == i ? "[%s] " : "%s ";

		if (!(pti->lpp_dest_mask & BIT(i)))
			continue;

		ret += scnprintf(buf + ret, PAGE_SIZE - ret,
				 fmt, lpp_dest_str[i]);
	}

	if (ret)
		buf[ret - 1] = '\n';

	return ret;
}

static ssize_t lpp_dest_store(struct device *dev, struct device_attribute *attr,
			      const char *buf, size_t size)
{
	struct pti_device *pti = dev_get_drvdata(dev);
	ssize_t ret = -EINVAL;
	int i;

	for (i = 0; i < ARRAY_SIZE(lpp_dest_str); i++)
		if (sysfs_streq(buf, lpp_dest_str[i]))
			break;

	if (i < ARRAY_SIZE(lpp_dest_str) && pti->lpp_dest_mask & BIT(i)) {
		pti->lpp_dest = i;
		ret = size;
	}

	return ret;
}

static DEVICE_ATTR_RW(lpp_dest);

static struct attribute *lpp_output_attrs[] = {
	&dev_attr_mode.attr,
	&dev_attr_freerunning_clock.attr,
	&dev_attr_clock_divider.attr,
	&dev_attr_lpp_dest.attr,
	NULL,
};

static struct attribute_group lpp_output_group = {
	.attrs	= lpp_output_attrs,
};

static struct intel_th_driver intel_th_lpp_driver = {
	.probe		= intel_th_pti_probe,
	.remove		= intel_th_pti_remove,
	.activate	= intel_th_pti_activate,
	.deactivate	= intel_th_pti_deactivate,
	.attr_group	= &lpp_output_group,
	.driver	= {
		.name	= "lpp",
		.owner	= THIS_MODULE,
	},
};

static int __init intel_th_pti_lpp_init(void)
{
	int err;

	err = intel_th_driver_register(&intel_th_pti_driver);
	if (err)
		return err;

	err = intel_th_driver_register(&intel_th_lpp_driver);
	if (err) {
		intel_th_driver_unregister(&intel_th_pti_driver);
		return err;
	}

	return 0;
}

module_init(intel_th_pti_lpp_init);

static void __exit intel_th_pti_lpp_exit(void)
{
	intel_th_driver_unregister(&intel_th_pti_driver);
	intel_th_driver_unregister(&intel_th_lpp_driver);
}

module_exit(intel_th_pti_lpp_exit);

MODULE_LICENSE("GPL v2");
MODULE_DESCRIPTION("Intel(R) Trace Hub PTI/LPP output driver");
MODULE_AUTHOR("Alexander Shishkin <alexander.shishkin@linux.intel.com>");
