// SPDX-License-Identifier: GPL-2.0
/*
 * SCMI Powercap support.
 *
 * Copyright (C) 2022 ARM Ltd.
 */

#include <linux/device.h>
#include <linux/math.h>
#include <linux/limits.h>
#include <linux/list.h>
#include <linux/module.h>
#include <linux/powercap.h>
#include <linux/scmi_protocol.h>

#define to_scmi_powercap_zone(z)		\
	container_of(z, struct scmi_powercap_zone, zone)

static const struct scmi_powercap_proto_ops *powercap_ops;

struct scmi_powercap_zone {
	unsigned int height;
	struct device *dev;
	struct scmi_protocol_handle *ph;
	const struct scmi_powercap_info *info;
	struct scmi_powercap_zone *spzones;
	struct powercap_zone zone;
	struct list_head node;
};

struct scmi_powercap_root {
	unsigned int num_zones;
	struct scmi_powercap_zone *spzones;
	struct list_head *registered_zones;
};

static struct powercap_control_type *scmi_top_pcntrl;

static int scmi_powercap_zone_release(struct powercap_zone *pz)
{
	return 0;
}

static int scmi_powercap_get_max_power_range_uw(struct powercap_zone *pz,
						u64 *max_power_range_uw)
{
	*max_power_range_uw = U32_MAX;
	return 0;
}

static int scmi_powercap_get_power_uw(struct powercap_zone *pz,
				      u64 *power_uw)
{
	struct scmi_powercap_zone *spz = to_scmi_powercap_zone(pz);
	u32 avg_power, pai;
	int ret;

	if (!spz->info->powercap_monitoring)
		return -EINVAL;

	ret = powercap_ops->measurements_get(spz->ph, spz->info->id, &avg_power,
					     &pai);
	if (ret)
		return ret;

	*power_uw = avg_power;
	if (spz->info->powercap_scale_mw)
		*power_uw *= 1000;

	return 0;
}

static const struct powercap_zone_ops zone_ops = {
	.get_max_power_range_uw = scmi_powercap_get_max_power_range_uw,
	.get_power_uw = scmi_powercap_get_power_uw,
	.release = scmi_powercap_zone_release,
};

static void scmi_powercap_normalize_cap(const struct scmi_powercap_zone *spz,
					u64 power_limit_uw, u32 *norm)
{
	bool scale_mw = spz->info->powercap_scale_mw;
	u64 val;

	val = scale_mw ? DIV_ROUND_UP_ULL(power_limit_uw, 1000) : power_limit_uw;
	/*
	 * This cast is lossless since here @req_power is certain to be within
	 * the range [min_power_cap, max_power_cap] whose bounds are assured to
	 * be two unsigned 32bits quantities.
	 */
	*norm = clamp_t(u32, val, spz->info->min_power_cap,
			spz->info->max_power_cap);
	*norm = rounddown(*norm, spz->info->power_cap_step);

	val = (scale_mw) ? *norm * 1000 : *norm;
	if (power_limit_uw != val)
		dev_dbg(spz->dev,
			"Normalized %s:CAP - requested:%llu - normalized:%llu\n",
			spz->info->name, power_limit_uw, val);
}

static int scmi_powercap_set_power_limit_uw(struct powercap_zone *pz, int cid,
					    u64 power_uw)
{
	struct scmi_powercap_zone *spz = to_scmi_powercap_zone(pz);
	u32 norm_power;

	if (!spz->info->powercap_cap_config)
		return -EINVAL;

	scmi_powercap_normalize_cap(spz, power_uw, &norm_power);

	return powercap_ops->cap_set(spz->ph, spz->info->id, norm_power, false);
}

static int scmi_powercap_get_power_limit_uw(struct powercap_zone *pz, int cid,
					    u64 *power_limit_uw)
{
	struct scmi_powercap_zone *spz = to_scmi_powercap_zone(pz);
	u32 power;
	int ret;

	ret = powercap_ops->cap_get(spz->ph, spz->info->id, &power);
	if (ret)
		return ret;

	*power_limit_uw = power;
	if (spz->info->powercap_scale_mw)
		*power_limit_uw *= 1000;

	return 0;
}

static void scmi_powercap_normalize_time(const struct scmi_powercap_zone *spz,
					 u64 time_us, u32 *norm)
{
	/*
	 * This cast is lossless since here @time_us is certain to be within the
	 * range [min_pai, max_pai] whose bounds are assured to be two unsigned
	 * 32bits quantities.
	 */
	*norm = clamp_t(u32, time_us, spz->info->min_pai, spz->info->max_pai);
	*norm = rounddown(*norm, spz->info->pai_step);

	if (time_us != *norm)
		dev_dbg(spz->dev,
			"Normalized %s:PAI - requested:%llu - normalized:%u\n",
			spz->info->name, time_us, *norm);
}

static int scmi_powercap_set_time_window_us(struct powercap_zone *pz, int cid,
					    u64 time_window_us)
{
	struct scmi_powercap_zone *spz = to_scmi_powercap_zone(pz);
	u32 norm_pai;

	if (!spz->info->powercap_pai_config)
		return -EINVAL;

	scmi_powercap_normalize_time(spz, time_window_us, &norm_pai);

	return powercap_ops->pai_set(spz->ph, spz->info->id, norm_pai);
}

static int scmi_powercap_get_time_window_us(struct powercap_zone *pz, int cid,
					    u64 *time_window_us)
{
	struct scmi_powercap_zone *spz = to_scmi_powercap_zone(pz);
	int ret;
	u32 pai;

	ret = powercap_ops->pai_get(spz->ph, spz->info->id, &pai);
	if (ret)
		return ret;

	*time_window_us = pai;

	return 0;
}

static int scmi_powercap_get_max_power_uw(struct powercap_zone *pz, int cid,
					  u64 *max_power_uw)
{
	struct scmi_powercap_zone *spz = to_scmi_powercap_zone(pz);

	*max_power_uw = spz->info->max_power_cap;
	if (spz->info->powercap_scale_mw)
		*max_power_uw *= 1000;

	return 0;
}

static int scmi_powercap_get_min_power_uw(struct powercap_zone *pz, int cid,
					  u64 *min_power_uw)
{
	struct scmi_powercap_zone *spz = to_scmi_powercap_zone(pz);

	*min_power_uw = spz->info->min_power_cap;
	if (spz->info->powercap_scale_mw)
		*min_power_uw *= 1000;

	return 0;
}

static int scmi_powercap_get_max_time_window_us(struct powercap_zone *pz,
						int cid, u64 *time_window_us)
{
	struct scmi_powercap_zone *spz = to_scmi_powercap_zone(pz);

	*time_window_us = spz->info->max_pai;

	return 0;
}

static int scmi_powercap_get_min_time_window_us(struct powercap_zone *pz,
						int cid, u64 *time_window_us)
{
	struct scmi_powercap_zone *spz = to_scmi_powercap_zone(pz);

	*time_window_us = (u64)spz->info->min_pai;

	return 0;
}

static const char *scmi_powercap_get_name(struct powercap_zone *pz, int cid)
{
	return "SCMI power-cap";
}

static const struct powercap_zone_constraint_ops constraint_ops  = {
	.set_power_limit_uw = scmi_powercap_set_power_limit_uw,
	.get_power_limit_uw = scmi_powercap_get_power_limit_uw,
	.set_time_window_us = scmi_powercap_set_time_window_us,
	.get_time_window_us = scmi_powercap_get_time_window_us,
	.get_max_power_uw = scmi_powercap_get_max_power_uw,
	.get_min_power_uw = scmi_powercap_get_min_power_uw,
	.get_max_time_window_us = scmi_powercap_get_max_time_window_us,
	.get_min_time_window_us = scmi_powercap_get_min_time_window_us,
	.get_name = scmi_powercap_get_name,
};

static void scmi_powercap_unregister_all_zones(struct scmi_powercap_root *pr)
{
	int i;

	/* Un-register children zones first starting from the leaves */
	for (i = pr->num_zones - 1; i >= 0; i--) {
		if (!list_empty(&pr->registered_zones[i])) {
			struct scmi_powercap_zone *spz;

			list_for_each_entry(spz, &pr->registered_zones[i], node)
				powercap_unregister_zone(scmi_top_pcntrl,
							 &spz->zone);
		}
	}
}

static inline bool
scmi_powercap_is_zone_registered(struct scmi_powercap_zone *spz)
{
	return !list_empty(&spz->node);
}

static inline unsigned int
scmi_powercap_get_zone_height(struct scmi_powercap_zone *spz)
{
	if (spz->info->parent_id == SCMI_POWERCAP_ROOT_ZONE_ID)
		return 0;

	return spz->spzones[spz->info->parent_id].height + 1;
}

static inline struct scmi_powercap_zone *
scmi_powercap_get_parent_zone(struct scmi_powercap_zone *spz)
{
	if (spz->info->parent_id == SCMI_POWERCAP_ROOT_ZONE_ID)
		return NULL;

	return &spz->spzones[spz->info->parent_id];
}

/**
 * scmi_powercap_register_zone  - Register an SCMI powercap zone recursively
 *
 * @pr: A reference to the root powercap zones descriptors
 * @spz: A reference to the SCMI powercap zone to register
 *
 * When registering SCMI powercap zones with the powercap framework we should
 * take care to always register zones starting from the root ones and to
 * deregister starting from the leaves.
 *
 * Unfortunately we cannot assume that the array of available SCMI powercap
 * zones provided by the SCMI platform firmware is built to comply with such
 * requirement.
 *
 * This function, given an SCMI powercap zone to register, takes care to walk
 * the SCMI powercap zones tree up to the root looking recursively for
 * unregistered parent zones before registering the provided zone; at the same
 * time each registered zone height in such a tree is accounted for and each
 * zone, once registered, is stored in the @registered_zones array that is
 * indexed by zone height: this way will be trivial, at unregister time, to walk
 * the @registered_zones array backward and unregister all the zones starting
 * from the leaves, removing children zones before parents.
 *
 * While doing this, we prune away any zone marked as invalid (like the ones
 * sporting an SCMI abstract power scale) as long as they are positioned as
 * leaves in the SCMI powercap zones hierarchy: any non-leaf invalid zone causes
 * the entire process to fail since we cannot assume the correctness of an SCMI
 * powercap zones hierarchy if some of the internal nodes are missing.
 *
 * Note that the array of SCMI powercap zones as returned by the SCMI platform
 * is known to be sane, i.e. zones relationships have been validated at the
 * protocol layer.
 *
 * Return: 0 on Success
 */
static int scmi_powercap_register_zone(struct scmi_powercap_root *pr,
				       struct scmi_powercap_zone *spz)
{
	int ret = 0;
	struct scmi_powercap_zone *parent;

	if (!spz->info)
		return ret;

	parent = scmi_powercap_get_parent_zone(spz);
	if (parent && !scmi_powercap_is_zone_registered(parent)) {
		/*
		 * Bail out if a parent domain was marked as unsupported:
		 * only domains participating as leaves can be skipped.
		 */
		if (!parent->info)
			return -ENODEV;

		ret = scmi_powercap_register_zone(pr, parent);
		if (ret)
			return ret;
	}

	if (!scmi_powercap_is_zone_registered(spz)) {
		struct powercap_zone *z;

		z = powercap_register_zone(&spz->zone,
					   scmi_top_pcntrl,
					   spz->info->name,
					   parent ? &parent->zone : NULL,
					   &zone_ops, 1, &constraint_ops);
		if (!IS_ERR(z)) {
			spz->height = scmi_powercap_get_zone_height(spz);
			list_add(&spz->node,
				 &pr->registered_zones[spz->height]);
			dev_dbg(spz->dev,
				"Registered node %s - parent %s - height:%d\n",
				spz->info->name,
				parent ? parent->info->name : "ROOT",
				spz->height);
			ret = 0;
		} else {
			ret = PTR_ERR(z);
			dev_err(spz->dev,
				"Error registering node:%s - parent:%s - h:%d - ret:%d\n",
				 spz->info->name,
				 parent ? parent->info->name : "ROOT",
				 spz->height, ret);
		}
	}

	return ret;
}

static int scmi_powercap_probe(struct scmi_device *sdev)
{
	int ret, i;
	struct scmi_powercap_root *pr;
	struct scmi_powercap_zone *spz;
	struct scmi_protocol_handle *ph;
	struct device *dev = &sdev->dev;

	if (!sdev->handle)
		return -ENODEV;

	powercap_ops = sdev->handle->devm_protocol_get(sdev,
						       SCMI_PROTOCOL_POWERCAP,
						       &ph);
	if (IS_ERR(powercap_ops))
		return PTR_ERR(powercap_ops);

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

	ret = powercap_ops->num_domains_get(ph);
	if (ret < 0) {
		dev_err(dev, "number of powercap domains not found\n");
		return ret;
	}
	pr->num_zones = ret;

	pr->spzones = devm_kcalloc(dev, pr->num_zones,
				   sizeof(*pr->spzones), GFP_KERNEL);
	if (!pr->spzones)
		return -ENOMEM;

	/* Allocate for worst possible scenario of maximum tree height. */
	pr->registered_zones = devm_kcalloc(dev, pr->num_zones,
					    sizeof(*pr->registered_zones),
					    GFP_KERNEL);
	if (!pr->registered_zones)
		return -ENOMEM;

	for (i = 0, spz = pr->spzones; i < pr->num_zones; i++, spz++) {
		/*
		 * Powercap domains are validate by the protocol layer, i.e.
		 * when only non-NULL domains are returned here, whose
		 * parent_id is assured to point to another valid domain.
		 */
		spz->info = powercap_ops->info_get(ph, i);

		spz->dev = dev;
		spz->ph = ph;
		spz->spzones = pr->spzones;
		INIT_LIST_HEAD(&spz->node);
		INIT_LIST_HEAD(&pr->registered_zones[i]);

		/*
		 * Forcibly skip powercap domains using an abstract scale.
		 * Note that only leaves domains can be skipped, so this could
		 * lead later to a global failure.
		 */
		if (!spz->info->powercap_scale_uw &&
		    !spz->info->powercap_scale_mw) {
			dev_warn(dev,
				 "Abstract power scale not supported. Skip %s.\n",
				 spz->info->name);
			spz->info = NULL;
			continue;
		}
	}

	/*
	 * Scan array of retrieved SCMI powercap domains and register them
	 * recursively starting from the root domains.
	 */
	for (i = 0, spz = pr->spzones; i < pr->num_zones; i++, spz++) {
		ret = scmi_powercap_register_zone(pr, spz);
		if (ret) {
			dev_err(dev,
				"Failed to register powercap zone %s - ret:%d\n",
				spz->info->name, ret);
			scmi_powercap_unregister_all_zones(pr);
			return ret;
		}
	}

	dev_set_drvdata(dev, pr);

	dev_info(dev, "Registered %d SCMI Powercap domains !\n", pr->num_zones);

	return ret;
}

static void scmi_powercap_remove(struct scmi_device *sdev)
{
	struct device *dev = &sdev->dev;
	struct scmi_powercap_root *pr = dev_get_drvdata(dev);

	scmi_powercap_unregister_all_zones(pr);
}

static const struct scmi_device_id scmi_id_table[] = {
	{ SCMI_PROTOCOL_POWERCAP, "powercap" },
	{ },
};
MODULE_DEVICE_TABLE(scmi, scmi_id_table);

static struct scmi_driver scmi_powercap_driver = {
	.name = "scmi-powercap",
	.probe = scmi_powercap_probe,
	.remove = scmi_powercap_remove,
	.id_table = scmi_id_table,
};

static int __init scmi_powercap_init(void)
{
	int ret;

	scmi_top_pcntrl = powercap_register_control_type(NULL, "arm-scmi", NULL);
	if (IS_ERR(scmi_top_pcntrl))
		return PTR_ERR(scmi_top_pcntrl);

	ret = scmi_register(&scmi_powercap_driver);
	if (ret)
		powercap_unregister_control_type(scmi_top_pcntrl);

	return ret;
}
module_init(scmi_powercap_init);

static void __exit scmi_powercap_exit(void)
{
	scmi_unregister(&scmi_powercap_driver);

	powercap_unregister_control_type(scmi_top_pcntrl);
}
module_exit(scmi_powercap_exit);

MODULE_AUTHOR("Cristian Marussi <cristian.marussi@arm.com>");
MODULE_DESCRIPTION("ARM SCMI Powercap driver");
MODULE_LICENSE("GPL");
