/*
 * Intel(R) Trace Hub Software Trace Hub support
 *
 * Copyright (C) 2014-2015 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/io.h>
#include <linux/mm.h>
#include <linux/slab.h>
#include <linux/stm.h>

#include "intel_th.h"
#include "sth.h"

struct sth_device {
	void __iomem	*base;
	void __iomem	*channels;
	phys_addr_t	channels_phys;
	struct device	*dev;
	struct stm_data	stm;
	unsigned int	sw_nmasters;
};

static struct intel_th_channel __iomem *
sth_channel(struct sth_device *sth, unsigned int master, unsigned int channel)
{
	struct intel_th_channel __iomem *sw_map = sth->channels;

	return &sw_map[(master - sth->stm.sw_start) * sth->stm.sw_nchannels +
		       channel];
}

static void sth_iowrite(void __iomem *dest, const unsigned char *payload,
			unsigned int size)
{
	switch (size) {
#ifdef CONFIG_64BIT
	case 8:
		writeq_relaxed(*(u64 *)payload, dest);
		break;
#endif
	case 4:
		writel_relaxed(*(u32 *)payload, dest);
		break;
	case 2:
		writew_relaxed(*(u16 *)payload, dest);
		break;
	case 1:
		writeb_relaxed(*(u8 *)payload, dest);
		break;
	default:
		break;
	}
}

static ssize_t notrace sth_stm_packet(struct stm_data *stm_data,
				      unsigned int master,
				      unsigned int channel,
				      unsigned int packet,
				      unsigned int flags,
				      unsigned int size,
				      const unsigned char *payload)
{
	struct sth_device *sth = container_of(stm_data, struct sth_device, stm);
	struct intel_th_channel __iomem *out =
		sth_channel(sth, master, channel);
	u64 __iomem *outp = &out->Dn;
	unsigned long reg = REG_STH_TRIG;

#ifndef CONFIG_64BIT
	if (size > 4)
		size = 4;
#endif

	size = rounddown_pow_of_two(size);

	switch (packet) {
	/* Global packets (GERR, XSYNC, TRIG) are sent with register writes */
	case STP_PACKET_GERR:
		reg += 4;
	case STP_PACKET_XSYNC:
		reg += 8;
	case STP_PACKET_TRIG:
		if (flags & STP_PACKET_TIMESTAMPED)
			reg += 4;
		writeb_relaxed(*payload, sth->base + reg);
		break;

	case STP_PACKET_MERR:
		if (size > 4)
			size = 4;

		sth_iowrite(&out->MERR, payload, size);
		break;

	case STP_PACKET_FLAG:
		if (flags & STP_PACKET_TIMESTAMPED)
			outp = (u64 __iomem *)&out->FLAG_TS;
		else
			outp = (u64 __iomem *)&out->FLAG;

		size = 0;
		writeb_relaxed(0, outp);
		break;

	case STP_PACKET_USER:
		if (flags & STP_PACKET_TIMESTAMPED)
			outp = &out->USER_TS;
		else
			outp = &out->USER;
		sth_iowrite(outp, payload, size);
		break;

	case STP_PACKET_DATA:
		outp = &out->Dn;

		if (flags & STP_PACKET_TIMESTAMPED)
			outp += 2;
		if (flags & STP_PACKET_MARKED)
			outp++;

		sth_iowrite(outp, payload, size);
		break;
	default:
		return -ENOTSUPP;
	}

	return size;
}

static phys_addr_t
sth_stm_mmio_addr(struct stm_data *stm_data, unsigned int master,
		  unsigned int channel, unsigned int nr_chans)
{
	struct sth_device *sth = container_of(stm_data, struct sth_device, stm);
	phys_addr_t addr;

	master -= sth->stm.sw_start;
	addr = sth->channels_phys + (master * sth->stm.sw_nchannels + channel) *
		sizeof(struct intel_th_channel);

	if (offset_in_page(addr) ||
	    offset_in_page(nr_chans * sizeof(struct intel_th_channel)))
		return 0;

	return addr;
}

static int sth_stm_link(struct stm_data *stm_data, unsigned int master,
			 unsigned int channel)
{
	struct sth_device *sth = container_of(stm_data, struct sth_device, stm);

	intel_th_set_output(to_intel_th_device(sth->dev), master);

	return 0;
}

static int intel_th_sw_init(struct sth_device *sth)
{
	u32 reg;

	reg = ioread32(sth->base + REG_STH_STHCAP1);
	sth->stm.sw_nchannels = reg & 0xff;

	reg = ioread32(sth->base + REG_STH_STHCAP0);
	sth->stm.sw_start = reg & 0xffff;
	sth->stm.sw_end = reg >> 16;

	sth->sw_nmasters = sth->stm.sw_end - sth->stm.sw_start;
	dev_dbg(sth->dev, "sw_start: %x sw_end: %x masters: %x nchannels: %x\n",
		sth->stm.sw_start, sth->stm.sw_end, sth->sw_nmasters,
		sth->stm.sw_nchannels);

	return 0;
}

static int intel_th_sth_probe(struct intel_th_device *thdev)
{
	struct device *dev = &thdev->dev;
	struct sth_device *sth;
	struct resource *res;
	void __iomem *base, *channels;
	int err;

	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;

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

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

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

	sth->dev = dev;
	sth->base = base;
	sth->channels = channels;
	sth->channels_phys = res->start;
	sth->stm.name = dev_name(dev);
	sth->stm.packet = sth_stm_packet;
	sth->stm.mmio_addr = sth_stm_mmio_addr;
	sth->stm.sw_mmiosz = sizeof(struct intel_th_channel);
	sth->stm.link = sth_stm_link;

	err = intel_th_sw_init(sth);
	if (err)
		return err;

	err = stm_register_device(dev, &sth->stm, THIS_MODULE);
	if (err) {
		dev_err(dev, "stm_register_device failed\n");
		return err;
	}

	dev_set_drvdata(dev, sth);

	return 0;
}

static void intel_th_sth_remove(struct intel_th_device *thdev)
{
	struct sth_device *sth = dev_get_drvdata(&thdev->dev);

	stm_unregister_device(&sth->stm);
}

static struct intel_th_driver intel_th_sth_driver = {
	.probe	= intel_th_sth_probe,
	.remove	= intel_th_sth_remove,
	.driver	= {
		.name	= "sth",
		.owner	= THIS_MODULE,
	},
};

module_driver(intel_th_sth_driver,
	      intel_th_driver_register,
	      intel_th_driver_unregister);

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