// SPDX-License-Identifier: GPL-2.0
/*
 * Intel(R) Trace Hub Software Trace Hub support
 *
 * Copyright (C) 2014-2015 Intel Corporation.
 */

#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);
	unsigned long reg = REG_STH_TRIG;
	u64 __iomem *outp;

#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;
		fallthrough;

	case STP_PACKET_XSYNC:
		reg += 8;
		fallthrough;

	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);

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

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>");
