/*
 * PowerNV system parameter code
 *
 * Copyright (C) 2013 IBM
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that 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.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 */

#include <linux/kobject.h>
#include <linux/mutex.h>
#include <linux/slab.h>
#include <linux/of.h>
#include <linux/gfp.h>
#include <linux/stat.h>
#include <asm/opal.h>

#define MAX_PARAM_DATA_LEN	64

static DEFINE_MUTEX(opal_sysparam_mutex);
static struct kobject *sysparam_kobj;
static void *param_data_buf;

struct param_attr {
	struct list_head list;
	u32 param_id;
	u32 param_size;
	struct kobj_attribute kobj_attr;
};

static int opal_get_sys_param(u32 param_id, u32 length, void *buffer)
{
	struct opal_msg msg;
	int ret, token;

	token = opal_async_get_token_interruptible();
	if (token < 0) {
		if (token != -ERESTARTSYS)
			pr_err("%s: Couldn't get the token, returning\n",
					__func__);
		ret = token;
		goto out;
	}

	ret = opal_get_param(token, param_id, (u64)buffer, length);
	if (ret != OPAL_ASYNC_COMPLETION)
		goto out_token;

	ret = opal_async_wait_response(token, &msg);
	if (ret) {
		pr_err("%s: Failed to wait for the async response, %d\n",
				__func__, ret);
		goto out_token;
	}

	ret = be64_to_cpu(msg.params[1]);

out_token:
	opal_async_release_token(token);
out:
	return ret;
}

static int opal_set_sys_param(u32 param_id, u32 length, void *buffer)
{
	struct opal_msg msg;
	int ret, token;

	token = opal_async_get_token_interruptible();
	if (token < 0) {
		if (token != -ERESTARTSYS)
			pr_err("%s: Couldn't get the token, returning\n",
					__func__);
		ret = token;
		goto out;
	}

	ret = opal_set_param(token, param_id, (u64)buffer, length);

	if (ret != OPAL_ASYNC_COMPLETION)
		goto out_token;

	ret = opal_async_wait_response(token, &msg);
	if (ret) {
		pr_err("%s: Failed to wait for the async response, %d\n",
				__func__, ret);
		goto out_token;
	}

	ret = be64_to_cpu(msg.params[1]);

out_token:
	opal_async_release_token(token);
out:
	return ret;
}

static ssize_t sys_param_show(struct kobject *kobj,
		struct kobj_attribute *kobj_attr, char *buf)
{
	struct param_attr *attr = container_of(kobj_attr, struct param_attr,
			kobj_attr);
	int ret;

	mutex_lock(&opal_sysparam_mutex);
	ret = opal_get_sys_param(attr->param_id, attr->param_size,
			param_data_buf);
	if (ret)
		goto out;

	memcpy(buf, param_data_buf, attr->param_size);

out:
	mutex_unlock(&opal_sysparam_mutex);
	return ret ? ret : attr->param_size;
}

static ssize_t sys_param_store(struct kobject *kobj,
		struct kobj_attribute *kobj_attr, const char *buf, size_t count)
{
	struct param_attr *attr = container_of(kobj_attr, struct param_attr,
			kobj_attr);
	int ret;

	mutex_lock(&opal_sysparam_mutex);
	memcpy(param_data_buf, buf, count);
	ret = opal_set_sys_param(attr->param_id, attr->param_size,
			param_data_buf);
	mutex_unlock(&opal_sysparam_mutex);
	return ret ? ret : count;
}

void __init opal_sys_param_init(void)
{
	struct device_node *sysparam;
	struct param_attr *attr;
	u32 *id, *size;
	int count, i;
	u8 *perm;

	if (!opal_kobj) {
		pr_warn("SYSPARAM: opal kobject is not available\n");
		goto out;
	}

	sysparam_kobj = kobject_create_and_add("sysparams", opal_kobj);
	if (!sysparam_kobj) {
		pr_err("SYSPARAM: Failed to create sysparam kobject\n");
		goto out;
	}

	/* Allocate big enough buffer for any get/set transactions */
	param_data_buf = kzalloc(MAX_PARAM_DATA_LEN, GFP_KERNEL);
	if (!param_data_buf) {
		pr_err("SYSPARAM: Failed to allocate memory for param data "
				"buf\n");
		goto out_kobj_put;
	}

	sysparam = of_find_node_by_path("/ibm,opal/sysparams");
	if (!sysparam) {
		pr_err("SYSPARAM: Opal sysparam node not found\n");
		goto out_param_buf;
	}

	if (!of_device_is_compatible(sysparam, "ibm,opal-sysparams")) {
		pr_err("SYSPARAM: Opal sysparam node not compatible\n");
		goto out_node_put;
	}

	/* Number of parameters exposed through DT */
	count = of_property_count_strings(sysparam, "param-name");
	if (count < 0) {
		pr_err("SYSPARAM: No string found of property param-name in "
				"the node %s\n", sysparam->name);
		goto out_node_put;
	}

	id = kzalloc(sizeof(*id) * count, GFP_KERNEL);
	if (!id) {
		pr_err("SYSPARAM: Failed to allocate memory to read parameter "
				"id\n");
		goto out_node_put;
	}

	size = kzalloc(sizeof(*size) * count, GFP_KERNEL);
	if (!size) {
		pr_err("SYSPARAM: Failed to allocate memory to read parameter "
				"size\n");
		goto out_free_id;
	}

	perm = kzalloc(sizeof(*perm) * count, GFP_KERNEL);
	if (!perm) {
		pr_err("SYSPARAM: Failed to allocate memory to read supported "
				"action on the parameter");
		goto out_free_size;
	}

	if (of_property_read_u32_array(sysparam, "param-id", id, count)) {
		pr_err("SYSPARAM: Missing property param-id in the DT\n");
		goto out_free_perm;
	}

	if (of_property_read_u32_array(sysparam, "param-len", size, count)) {
		pr_err("SYSPARAM: Missing propery param-len in the DT\n");
		goto out_free_perm;
	}


	if (of_property_read_u8_array(sysparam, "param-perm", perm, count)) {
		pr_err("SYSPARAM: Missing propery param-perm in the DT\n");
		goto out_free_perm;
	}

	attr = kzalloc(sizeof(*attr) * count, GFP_KERNEL);
	if (!attr) {
		pr_err("SYSPARAM: Failed to allocate memory for parameter "
				"attributes\n");
		goto out_free_perm;
	}

	/* For each of the parameters, populate the parameter attributes */
	for (i = 0; i < count; i++) {
		sysfs_attr_init(&attr[i].kobj_attr.attr);
		attr[i].param_id = id[i];
		attr[i].param_size = size[i];
		if (of_property_read_string_index(sysparam, "param-name", i,
				&attr[i].kobj_attr.attr.name))
			continue;

		/* If the parameter is read-only or read-write */
		switch (perm[i] & 3) {
		case OPAL_SYSPARAM_READ:
			attr[i].kobj_attr.attr.mode = S_IRUGO;
			break;
		case OPAL_SYSPARAM_WRITE:
			attr[i].kobj_attr.attr.mode = S_IWUGO;
			break;
		case OPAL_SYSPARAM_RW:
			attr[i].kobj_attr.attr.mode = S_IRUGO | S_IWUGO;
			break;
		default:
			break;
		}

		attr[i].kobj_attr.show = sys_param_show;
		attr[i].kobj_attr.store = sys_param_store;

		if (sysfs_create_file(sysparam_kobj, &attr[i].kobj_attr.attr)) {
			pr_err("SYSPARAM: Failed to create sysfs file %s\n",
					attr[i].kobj_attr.attr.name);
			goto out_free_attr;
		}
	}

	kfree(perm);
	kfree(size);
	kfree(id);
	of_node_put(sysparam);
	return;

out_free_attr:
	kfree(attr);
out_free_perm:
	kfree(perm);
out_free_size:
	kfree(size);
out_free_id:
	kfree(id);
out_node_put:
	of_node_put(sysparam);
out_param_buf:
	kfree(param_data_buf);
out_kobj_put:
	kobject_put(sysparam_kobj);
out:
	return;
}
