// SPDX-License-Identifier: GPL-2.0-only
/*
 * processor thermal device interface for reading workload type hints
 * from the user space. The hints are provided by the firmware.
 *
 * Operation:
 * When user space enables workload type prediction:
 * - Use mailbox to:
 *	Configure notification delay
 *	Enable processor thermal device interrupt
 *
 * - The predicted workload type can be read from MMIO:
 *	Offset 0x5B18 shows if there was an interrupt
 *	active for change in workload type and also
 *	predicted workload type.
 *
 * Two interface functions are provided to call when there is a
 * thermal device interrupt:
 * - proc_thermal_check_wt_intr():
 *     Check if the interrupt is for change in workload type. Called from
 *     interrupt context.
 *
 * - proc_thermal_wt_intr_callback():
 *     Callback for interrupt processing in thread context. This involves
 *	sending notification to user space that there is a change in the
 *     workload type.
 *
 * Copyright (c) 2023, Intel Corporation.
 */

#include <linux/bitfield.h>
#include <linux/pci.h>
#include "processor_thermal_device.h"

#define SOC_WT				GENMASK_ULL(47, 40)

#define SOC_WT_PREDICTION_INT_ENABLE_BIT	23

#define SOC_WT_PREDICTION_INT_ACTIVE	BIT(2)

/*
 * Closest possible to 1 Second is 1024 ms with programmed time delay
 * of 0x0A.
 */
static u8 notify_delay = 0x0A;
static u16 notify_delay_ms = 1024;

static DEFINE_MUTEX(wt_lock);
static u8 wt_enable;

/* Show current predicted workload type index */
static ssize_t workload_type_index_show(struct device *dev,
					struct device_attribute *attr,
					char *buf)
{
	struct proc_thermal_device *proc_priv;
	struct pci_dev *pdev = to_pci_dev(dev);
	u64 status = 0;
	int wt;

	mutex_lock(&wt_lock);
	if (!wt_enable) {
		mutex_unlock(&wt_lock);
		return -ENODATA;
	}

	proc_priv = pci_get_drvdata(pdev);

	status = readq(proc_priv->mmio_base + SOC_WT_RES_INT_STATUS_OFFSET);

	mutex_unlock(&wt_lock);

	wt = FIELD_GET(SOC_WT, status);

	return sysfs_emit(buf, "%d\n", wt);
}

static DEVICE_ATTR_RO(workload_type_index);

static ssize_t workload_hint_enable_show(struct device *dev,
					 struct device_attribute *attr,
					 char *buf)
{
	return sysfs_emit(buf, "%d\n", wt_enable);
}

static ssize_t workload_hint_enable_store(struct device *dev,
					  struct device_attribute *attr,
					  const char *buf, size_t size)
{
	struct pci_dev *pdev = to_pci_dev(dev);
	u8 mode;
	int ret;

	if (kstrtou8(buf, 10, &mode) || mode > 1)
		return -EINVAL;

	mutex_lock(&wt_lock);

	if (mode)
		ret = processor_thermal_mbox_interrupt_config(pdev, true,
							      SOC_WT_PREDICTION_INT_ENABLE_BIT,
							      notify_delay);
	else
		ret = processor_thermal_mbox_interrupt_config(pdev, false,
							      SOC_WT_PREDICTION_INT_ENABLE_BIT, 0);

	if (ret)
		goto ret_enable_store;

	ret = size;
	wt_enable = mode;

ret_enable_store:
	mutex_unlock(&wt_lock);

	return ret;
}

static DEVICE_ATTR_RW(workload_hint_enable);

static ssize_t notification_delay_ms_show(struct device *dev,
					  struct device_attribute *attr,
					  char *buf)
{
	return sysfs_emit(buf, "%u\n", notify_delay_ms);
}

static ssize_t notification_delay_ms_store(struct device *dev,
					   struct device_attribute *attr,
					   const char *buf, size_t size)
{
	struct pci_dev *pdev = to_pci_dev(dev);
	u16 new_tw;
	int ret;
	u8 tm;

	/*
	 * Time window register value:
	 * Formula: (1 + x/4) * power(2,y)
	 * x = 2 msbs, that is [30:29] y = 5 [28:24]
	 * in INTR_CONFIG register.
	 * The result will be in milli seconds.
	 * Here, just keep x = 0, and just change y.
	 * First round up the user value to power of 2 and
	 * then take log2, to get "y" value to program.
	 */
	ret = kstrtou16(buf, 10, &new_tw);
	if (ret)
		return ret;

	if (!new_tw)
		return -EINVAL;

	new_tw = roundup_pow_of_two(new_tw);
	tm = ilog2(new_tw);
	if (tm > 31)
		return -EINVAL;

	mutex_lock(&wt_lock);

	/* If the workload hint was already enabled, then update with the new delay */
	if (wt_enable)
		ret = processor_thermal_mbox_interrupt_config(pdev, true,
							      SOC_WT_PREDICTION_INT_ENABLE_BIT,
							      tm);

	if (!ret) {
		ret = size;
		notify_delay = tm;
		notify_delay_ms = new_tw;
	}

	mutex_unlock(&wt_lock);

	return ret;
}

static DEVICE_ATTR_RW(notification_delay_ms);

static struct attribute *workload_hint_attrs[] = {
	&dev_attr_workload_type_index.attr,
	&dev_attr_workload_hint_enable.attr,
	&dev_attr_notification_delay_ms.attr,
	NULL
};

static const struct attribute_group workload_hint_attribute_group = {
	.attrs = workload_hint_attrs,
	.name = "workload_hint"
};

/*
 * Callback to check if the interrupt for prediction is active.
 * Caution: Called from the interrupt context.
 */
bool proc_thermal_check_wt_intr(struct proc_thermal_device *proc_priv)
{
	u64 int_status;

	int_status = readq(proc_priv->mmio_base + SOC_WT_RES_INT_STATUS_OFFSET);
	if (int_status & SOC_WT_PREDICTION_INT_ACTIVE)
		return true;

	return false;
}
EXPORT_SYMBOL_NS_GPL(proc_thermal_check_wt_intr, INT340X_THERMAL);

/* Callback to notify user space */
void proc_thermal_wt_intr_callback(struct pci_dev *pdev, struct proc_thermal_device *proc_priv)
{
	u64 status;

	status = readq(proc_priv->mmio_base + SOC_WT_RES_INT_STATUS_OFFSET);
	if (!(status & SOC_WT_PREDICTION_INT_ACTIVE))
		return;

	sysfs_notify(&pdev->dev.kobj, "workload_hint", "workload_type_index");
}
EXPORT_SYMBOL_NS_GPL(proc_thermal_wt_intr_callback, INT340X_THERMAL);

static bool workload_hint_created;

int proc_thermal_wt_hint_add(struct pci_dev *pdev, struct proc_thermal_device *proc_priv)
{
	int ret;

	ret = sysfs_create_group(&pdev->dev.kobj, &workload_hint_attribute_group);
	if (ret)
		return ret;

	workload_hint_created = true;

	return 0;
}
EXPORT_SYMBOL_NS_GPL(proc_thermal_wt_hint_add, INT340X_THERMAL);

void proc_thermal_wt_hint_remove(struct pci_dev *pdev)
{
	mutex_lock(&wt_lock);
	if (wt_enable)
		processor_thermal_mbox_interrupt_config(pdev, false,
							SOC_WT_PREDICTION_INT_ENABLE_BIT,
							0);
	mutex_unlock(&wt_lock);

	if (workload_hint_created)
		sysfs_remove_group(&pdev->dev.kobj, &workload_hint_attribute_group);

	workload_hint_created = false;
}
EXPORT_SYMBOL_NS_GPL(proc_thermal_wt_hint_remove, INT340X_THERMAL);

MODULE_IMPORT_NS(INT340X_THERMAL);
MODULE_LICENSE("GPL");
