/*
 * Copyright 2010 Benjamin Herrenschmidt, IBM Corp
 *                <benh@kernel.crashing.org>
 *     and        David Gibson, IBM Corporation.
 *
 *   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/kernel.h>
#include <linux/slab.h>
#include <linux/export.h>
#include <asm/debugfs.h>
#include <asm/prom.h>
#include <asm/scom.h>
#include <linux/uaccess.h>

const struct scom_controller *scom_controller;
EXPORT_SYMBOL_GPL(scom_controller);

struct device_node *scom_find_parent(struct device_node *node)
{
	struct device_node *par, *tmp;
	const u32 *p;

	for (par = of_node_get(node); par;) {
		if (of_get_property(par, "scom-controller", NULL))
			break;
		p = of_get_property(par, "scom-parent", NULL);
		tmp = par;
		if (p == NULL)
			par = of_get_parent(par);
		else
			par = of_find_node_by_phandle(*p);
		of_node_put(tmp);
	}
	return par;
}
EXPORT_SYMBOL_GPL(scom_find_parent);

scom_map_t scom_map_device(struct device_node *dev, int index)
{
	struct device_node *parent;
	unsigned int cells, size;
	const __be32 *prop, *sprop;
	u64 reg, cnt;
	scom_map_t ret;

	parent = scom_find_parent(dev);

	if (parent == NULL)
		return 0;

	/*
	 * We support "scom-reg" properties for adding scom registers
	 * to a random device-tree node with an explicit scom-parent
	 *
	 * We also support the simple "reg" property if the device is
	 * a direct child of a scom controller.
	 *
	 * In case both exist, "scom-reg" takes precedence.
	 */
	prop = of_get_property(dev, "scom-reg", &size);
	sprop = of_get_property(parent, "#scom-cells", NULL);
	if (!prop && parent == dev->parent) {
		prop = of_get_property(dev, "reg", &size);
		sprop = of_get_property(parent, "#address-cells", NULL);
	}
	if (!prop)
		return NULL;
	cells = sprop ? be32_to_cpup(sprop) : 1;
	size >>= 2;

	if (index >= (size / (2*cells)))
		return 0;

	reg = of_read_number(&prop[index * cells * 2], cells);
	cnt = of_read_number(&prop[index * cells * 2 + cells], cells);

	ret = scom_map(parent, reg, cnt);
	of_node_put(parent);

	return ret;
}
EXPORT_SYMBOL_GPL(scom_map_device);

#ifdef CONFIG_SCOM_DEBUGFS
struct scom_debug_entry {
	struct device_node *dn;
	struct debugfs_blob_wrapper path;
	char name[16];
};

static ssize_t scom_debug_read(struct file *filp, char __user *ubuf,
			       size_t count, loff_t *ppos)
{
	struct scom_debug_entry *ent = filp->private_data;
	u64 __user *ubuf64 = (u64 __user *)ubuf;
	loff_t off = *ppos;
	ssize_t done = 0; 
	u64 reg, reg_cnt, val;
	scom_map_t map;
	int rc;

	if (off < 0 || (off & 7) || (count & 7))
		return -EINVAL;
	reg = off >> 3;
	reg_cnt = count >> 3;

	map = scom_map(ent->dn, reg, reg_cnt);
	if (!scom_map_ok(map))
		return -ENXIO;

	for (reg = 0; reg < reg_cnt; reg++) {
		rc = scom_read(map, reg, &val);
		if (!rc)
			rc = put_user(val, ubuf64);
		if (rc) {
			if (!done)
				done = rc;
			break;
		}
		ubuf64++;
		*ppos += 8;
		done += 8;
	}
	scom_unmap(map);
	return done;
}

static ssize_t scom_debug_write(struct file* filp, const char __user *ubuf,
				size_t count, loff_t *ppos)
{
	struct scom_debug_entry *ent = filp->private_data;
	u64 __user *ubuf64 = (u64 __user *)ubuf;
	loff_t off = *ppos;
	ssize_t done = 0; 
	u64 reg, reg_cnt, val;
	scom_map_t map;
	int rc;

	if (off < 0 || (off & 7) || (count & 7))
		return -EINVAL;
	reg = off >> 3;
	reg_cnt = count >> 3;

	map = scom_map(ent->dn, reg, reg_cnt);
	if (!scom_map_ok(map))
		return -ENXIO;

	for (reg = 0; reg < reg_cnt; reg++) {
		rc = get_user(val, ubuf64);
		if (!rc)
			rc = scom_write(map, reg,  val);
		if (rc) {
			if (!done)
				done = rc;
			break;
		}
		ubuf64++;
		done += 8;
	}
	scom_unmap(map);
	return done;
}

static const struct file_operations scom_debug_fops = {
	.read =		scom_debug_read,
	.write =	scom_debug_write,
	.open =		simple_open,
	.llseek =	default_llseek,
};

static int scom_debug_init_one(struct dentry *root, struct device_node *dn,
			       int i)
{
	struct scom_debug_entry *ent;
	struct dentry *dir;

	ent = kzalloc(sizeof(*ent), GFP_KERNEL);
	if (!ent)
		return -ENOMEM;

	ent->dn = of_node_get(dn);
	snprintf(ent->name, 16, "%08x", i);
	ent->path.data = (void*)kasprintf(GFP_KERNEL, "%pOF", dn);
	ent->path.size = strlen((char *)ent->path.data);

	dir = debugfs_create_dir(ent->name, root);
	if (!dir) {
		of_node_put(dn);
		kfree(ent->path.data);
		kfree(ent);
		return -1;
	}

	debugfs_create_blob("devspec", 0400, dir, &ent->path);
	debugfs_create_file("access", 0600, dir, ent, &scom_debug_fops);

	return 0;
}

static int scom_debug_init(void)
{
	struct device_node *dn;
	struct dentry *root;
	int i, rc;

	root = debugfs_create_dir("scom", powerpc_debugfs_root);
	if (!root)
		return -1;

	i = rc = 0;
	for_each_node_with_property(dn, "scom-controller") {
		int id = of_get_ibm_chip_id(dn);
		if (id == -1)
			id = i;
		rc |= scom_debug_init_one(root, dn, id);
		i++;
	}

	return rc;
}
device_initcall(scom_debug_init);
#endif /* CONFIG_SCOM_DEBUGFS */
