// SPDX-License-Identifier: GPL-2.0-or-later
/*
 * PowerNV OPAL Powercap interface
 *
 * Copyright 2017 IBM Corp.
 */

#define pr_fmt(fmt)     "opal-powercap: " fmt

#include <linux/of.h>
#include <linux/kobject.h>
#include <linux/slab.h>

#include <asm/opal.h>

static DEFINE_MUTEX(powercap_mutex);

static struct kobject *powercap_kobj;

struct powercap_attr {
	u32 handle;
	struct kobj_attribute attr;
};

static struct pcap {
	struct attribute_group pg;
	struct powercap_attr *pattrs;
} *pcaps;

static ssize_t powercap_show(struct kobject *kobj, struct kobj_attribute *attr,
			     char *buf)
{
	struct powercap_attr *pcap_attr = container_of(attr,
						struct powercap_attr, attr);
	struct opal_msg msg;
	u32 pcap;
	int ret, token;

	token = opal_async_get_token_interruptible();
	if (token < 0) {
		pr_devel("Failed to get token\n");
		return token;
	}

	ret = mutex_lock_interruptible(&powercap_mutex);
	if (ret)
		goto out_token;

	ret = opal_get_powercap(pcap_attr->handle, token, (u32 *)__pa(&pcap));
	switch (ret) {
	case OPAL_ASYNC_COMPLETION:
		ret = opal_async_wait_response(token, &msg);
		if (ret) {
			pr_devel("Failed to wait for the async response\n");
			ret = -EIO;
			goto out;
		}
		ret = opal_error_code(opal_get_async_rc(msg));
		if (!ret) {
			ret = sprintf(buf, "%u\n", be32_to_cpu(pcap));
			if (ret < 0)
				ret = -EIO;
		}
		break;
	case OPAL_SUCCESS:
		ret = sprintf(buf, "%u\n", be32_to_cpu(pcap));
		if (ret < 0)
			ret = -EIO;
		break;
	default:
		ret = opal_error_code(ret);
	}

out:
	mutex_unlock(&powercap_mutex);
out_token:
	opal_async_release_token(token);
	return ret;
}

static ssize_t powercap_store(struct kobject *kobj,
			      struct kobj_attribute *attr, const char *buf,
			      size_t count)
{
	struct powercap_attr *pcap_attr = container_of(attr,
						struct powercap_attr, attr);
	struct opal_msg msg;
	u32 pcap;
	int ret, token;

	ret = kstrtoint(buf, 0, &pcap);
	if (ret)
		return ret;

	token = opal_async_get_token_interruptible();
	if (token < 0) {
		pr_devel("Failed to get token\n");
		return token;
	}

	ret = mutex_lock_interruptible(&powercap_mutex);
	if (ret)
		goto out_token;

	ret = opal_set_powercap(pcap_attr->handle, token, pcap);
	switch (ret) {
	case OPAL_ASYNC_COMPLETION:
		ret = opal_async_wait_response(token, &msg);
		if (ret) {
			pr_devel("Failed to wait for the async response\n");
			ret = -EIO;
			goto out;
		}
		ret = opal_error_code(opal_get_async_rc(msg));
		if (!ret)
			ret = count;
		break;
	case OPAL_SUCCESS:
		ret = count;
		break;
	default:
		ret = opal_error_code(ret);
	}

out:
	mutex_unlock(&powercap_mutex);
out_token:
	opal_async_release_token(token);
	return ret;
}

static void __init powercap_add_attr(int handle, const char *name,
			      struct powercap_attr *attr)
{
	attr->handle = handle;
	sysfs_attr_init(&attr->attr.attr);
	attr->attr.attr.name = name;
	attr->attr.attr.mode = 0444;
	attr->attr.show = powercap_show;
}

void __init opal_powercap_init(void)
{
	struct device_node *powercap, *node;
	int i = 0;

	powercap = of_find_compatible_node(NULL, NULL, "ibm,opal-powercap");
	if (!powercap) {
		pr_devel("Powercap node not found\n");
		return;
	}

	pcaps = kcalloc(of_get_child_count(powercap), sizeof(*pcaps),
			GFP_KERNEL);
	if (!pcaps)
		goto out_put_powercap;

	powercap_kobj = kobject_create_and_add("powercap", opal_kobj);
	if (!powercap_kobj) {
		pr_warn("Failed to create powercap kobject\n");
		goto out_pcaps;
	}

	i = 0;
	for_each_child_of_node(powercap, node) {
		u32 cur, min, max;
		int j = 0;
		bool has_cur = false, has_min = false, has_max = false;

		if (!of_property_read_u32(node, "powercap-min", &min)) {
			j++;
			has_min = true;
		}

		if (!of_property_read_u32(node, "powercap-max", &max)) {
			j++;
			has_max = true;
		}

		if (!of_property_read_u32(node, "powercap-current", &cur)) {
			j++;
			has_cur = true;
		}

		pcaps[i].pattrs = kcalloc(j, sizeof(struct powercap_attr),
					  GFP_KERNEL);
		if (!pcaps[i].pattrs)
			goto out_pcaps_pattrs;

		pcaps[i].pg.attrs = kcalloc(j + 1, sizeof(struct attribute *),
					    GFP_KERNEL);
		if (!pcaps[i].pg.attrs) {
			kfree(pcaps[i].pattrs);
			goto out_pcaps_pattrs;
		}

		j = 0;
		pcaps[i].pg.name = kasprintf(GFP_KERNEL, "%pOFn", node);
		if (has_min) {
			powercap_add_attr(min, "powercap-min",
					  &pcaps[i].pattrs[j]);
			pcaps[i].pg.attrs[j] = &pcaps[i].pattrs[j].attr.attr;
			j++;
		}

		if (has_max) {
			powercap_add_attr(max, "powercap-max",
					  &pcaps[i].pattrs[j]);
			pcaps[i].pg.attrs[j] = &pcaps[i].pattrs[j].attr.attr;
			j++;
		}

		if (has_cur) {
			powercap_add_attr(cur, "powercap-current",
					  &pcaps[i].pattrs[j]);
			pcaps[i].pattrs[j].attr.attr.mode |= 0220;
			pcaps[i].pattrs[j].attr.store = powercap_store;
			pcaps[i].pg.attrs[j] = &pcaps[i].pattrs[j].attr.attr;
			j++;
		}

		if (sysfs_create_group(powercap_kobj, &pcaps[i].pg)) {
			pr_warn("Failed to create powercap attribute group %s\n",
				pcaps[i].pg.name);
			goto out_pcaps_pattrs;
		}
		i++;
	}
	of_node_put(powercap);

	return;

out_pcaps_pattrs:
	while (--i >= 0) {
		kfree(pcaps[i].pattrs);
		kfree(pcaps[i].pg.attrs);
		kfree(pcaps[i].pg.name);
	}
	kobject_put(powercap_kobj);
	of_node_put(node);
out_pcaps:
	kfree(pcaps);
out_put_powercap:
	of_node_put(powercap);
}
