/*
 * (c) Copyright 2006 Benjamin Herrenschmidt, IBM Corp.
 *                    <benh@kernel.crashing.org>
 *
 *   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
 */

#undef DEBUG

#include <linux/kernel.h>
#include <asm/prom.h>
#include <asm/dcr.h>

#ifdef CONFIG_PPC_DCR_MMIO
static struct device_node *find_dcr_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, "dcr-controller", NULL))
			break;
		p = of_get_property(par, "dcr-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;
}
#endif

#if defined(CONFIG_PPC_DCR_NATIVE) && defined(CONFIG_PPC_DCR_MMIO)

bool dcr_map_ok_generic(dcr_host_t host)
{
	if (host.type == DCR_HOST_NATIVE)
		return dcr_map_ok_native(host.host.native);
	else if (host.type == DCR_HOST_MMIO)
		return dcr_map_ok_mmio(host.host.mmio);
	else
		return 0;
}
EXPORT_SYMBOL_GPL(dcr_map_ok_generic);

dcr_host_t dcr_map_generic(struct device_node *dev,
			   unsigned int dcr_n,
			   unsigned int dcr_c)
{
	dcr_host_t host;
	struct device_node *dp;
	const char *prop;

	host.type = DCR_HOST_INVALID;

	dp = find_dcr_parent(dev);
	if (dp == NULL)
		return host;

	prop = of_get_property(dp, "dcr-access-method", NULL);

	pr_debug("dcr_map_generic(dcr-access-method = %s)\n", prop);

	if (!strcmp(prop, "native")) {
		host.type = DCR_HOST_NATIVE;
		host.host.native = dcr_map_native(dev, dcr_n, dcr_c);
	} else if (!strcmp(prop, "mmio")) {
		host.type = DCR_HOST_MMIO;
		host.host.mmio = dcr_map_mmio(dev, dcr_n, dcr_c);
	}

	of_node_put(dp);
	return host;
}
EXPORT_SYMBOL_GPL(dcr_map_generic);

void dcr_unmap_generic(dcr_host_t host, unsigned int dcr_c)
{
	if (host.type == DCR_HOST_NATIVE)
		dcr_unmap_native(host.host.native, dcr_c);
	else if (host.type == DCR_HOST_MMIO)
		dcr_unmap_mmio(host.host.mmio, dcr_c);
	else /* host.type == DCR_HOST_INVALID */
		WARN_ON(true);
}
EXPORT_SYMBOL_GPL(dcr_unmap_generic);

u32 dcr_read_generic(dcr_host_t host, unsigned int dcr_n)
{
	if (host.type == DCR_HOST_NATIVE)
		return dcr_read_native(host.host.native, dcr_n);
	else if (host.type == DCR_HOST_MMIO)
		return dcr_read_mmio(host.host.mmio, dcr_n);
	else /* host.type == DCR_HOST_INVALID */
		WARN_ON(true);
	return 0;
}
EXPORT_SYMBOL_GPL(dcr_read_generic);

void dcr_write_generic(dcr_host_t host, unsigned int dcr_n, u32 value)
{
	if (host.type == DCR_HOST_NATIVE)
		dcr_write_native(host.host.native, dcr_n, value);
	else if (host.type == DCR_HOST_MMIO)
		dcr_write_mmio(host.host.mmio, dcr_n, value);
	else /* host.type == DCR_HOST_INVALID */
		WARN_ON(true);
}
EXPORT_SYMBOL_GPL(dcr_write_generic);

#endif /* defined(CONFIG_PPC_DCR_NATIVE) && defined(CONFIG_PPC_DCR_MMIO) */

unsigned int dcr_resource_start(struct device_node *np, unsigned int index)
{
	unsigned int ds;
	const u32 *dr = of_get_property(np, "dcr-reg", &ds);

	if (dr == NULL || ds & 1 || index >= (ds / 8))
		return 0;

	return dr[index * 2];
}
EXPORT_SYMBOL_GPL(dcr_resource_start);

unsigned int dcr_resource_len(struct device_node *np, unsigned int index)
{
	unsigned int ds;
	const u32 *dr = of_get_property(np, "dcr-reg", &ds);

	if (dr == NULL || ds & 1 || index >= (ds / 8))
		return 0;

	return dr[index * 2 + 1];
}
EXPORT_SYMBOL_GPL(dcr_resource_len);

#ifdef CONFIG_PPC_DCR_MMIO

u64 of_translate_dcr_address(struct device_node *dev,
			     unsigned int dcr_n,
			     unsigned int *out_stride)
{
	struct device_node *dp;
	const u32 *p;
	unsigned int stride;
	u64 ret = OF_BAD_ADDR;

	dp = find_dcr_parent(dev);
	if (dp == NULL)
		return OF_BAD_ADDR;

	/* Stride is not properly defined yet, default to 0x10 for Axon */
	p = of_get_property(dp, "dcr-mmio-stride", NULL);
	stride = (p == NULL) ? 0x10 : *p;

	/* XXX FIXME: Which property name is to use of the 2 following ? */
	p = of_get_property(dp, "dcr-mmio-range", NULL);
	if (p == NULL)
		p = of_get_property(dp, "dcr-mmio-space", NULL);
	if (p == NULL)
		goto done;

	/* Maybe could do some better range checking here */
	ret = of_translate_address(dp, p);
	if (ret != OF_BAD_ADDR)
		ret += (u64)(stride) * (u64)dcr_n;
	if (out_stride)
		*out_stride = stride;

 done:
	of_node_put(dp);
	return ret;
}

dcr_host_mmio_t dcr_map_mmio(struct device_node *dev,
			     unsigned int dcr_n,
			     unsigned int dcr_c)
{
	dcr_host_mmio_t ret = { .token = NULL, .stride = 0, .base = dcr_n };
	u64 addr;

	pr_debug("dcr_map(%s, 0x%x, 0x%x)\n",
		 dev->full_name, dcr_n, dcr_c);

	addr = of_translate_dcr_address(dev, dcr_n, &ret.stride);
	pr_debug("translates to addr: 0x%llx, stride: 0x%x\n",
		 (unsigned long long) addr, ret.stride);
	if (addr == OF_BAD_ADDR)
		return ret;
	pr_debug("mapping 0x%x bytes\n", dcr_c * ret.stride);
	ret.token = ioremap(addr, dcr_c * ret.stride);
	if (ret.token == NULL)
		return ret;
	pr_debug("mapped at 0x%p -> base is 0x%p\n",
		 ret.token, ret.token - dcr_n * ret.stride);
	ret.token -= dcr_n * ret.stride;
	return ret;
}
EXPORT_SYMBOL_GPL(dcr_map_mmio);

void dcr_unmap_mmio(dcr_host_mmio_t host, unsigned int dcr_c)
{
	dcr_host_mmio_t h = host;

	if (h.token == NULL)
		return;
	h.token += host.base * h.stride;
	iounmap(h.token);
	h.token = NULL;
}
EXPORT_SYMBOL_GPL(dcr_unmap_mmio);

#endif /* defined(CONFIG_PPC_DCR_MMIO) */

#ifdef CONFIG_PPC_DCR_NATIVE
DEFINE_SPINLOCK(dcr_ind_lock);
#endif	/* defined(CONFIG_PPC_DCR_NATIVE) */

