/*
 * OLPC-specific OFW device tree support code.
 *
 * Paul Mackerras	August 1996.
 * Copyright (C) 1996-2005 Paul Mackerras.
 *
 *  Adapted for 64bit PowerPC by Dave Engebretsen and Peter Bergner.
 *    {engebret|bergner}@us.ibm.com
 *
 *  Adapted for sparc by David S. Miller davem@davemloft.net
 *  Adapted for x86/OLPC by Andres Salomon <dilinger@queued.net>
 *
 *      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.
 */

#include <linux/kernel.h>
#include <linux/bootmem.h>
#include <linux/of.h>
#include <linux/of_platform.h>
#include <linux/of_pdt.h>
#include <asm/olpc.h>
#include <asm/olpc_ofw.h>

static phandle __init olpc_dt_getsibling(phandle node)
{
	const void *args[] = { (void *)node };
	void *res[] = { &node };

	if ((s32)node == -1)
		return 0;

	if (olpc_ofw("peer", args, res) || (s32)node == -1)
		return 0;

	return node;
}

static phandle __init olpc_dt_getchild(phandle node)
{
	const void *args[] = { (void *)node };
	void *res[] = { &node };

	if ((s32)node == -1)
		return 0;

	if (olpc_ofw("child", args, res) || (s32)node == -1) {
		pr_err("PROM: %s: fetching child failed!\n", __func__);
		return 0;
	}

	return node;
}

static int __init olpc_dt_getproplen(phandle node, const char *prop)
{
	const void *args[] = { (void *)node, prop };
	int len;
	void *res[] = { &len };

	if ((s32)node == -1)
		return -1;

	if (olpc_ofw("getproplen", args, res)) {
		pr_err("PROM: %s: getproplen failed!\n", __func__);
		return -1;
	}

	return len;
}

static int __init olpc_dt_getproperty(phandle node, const char *prop,
		char *buf, int bufsize)
{
	int plen;

	plen = olpc_dt_getproplen(node, prop);
	if (plen > bufsize || plen < 1) {
		return -1;
	} else {
		const void *args[] = { (void *)node, prop, buf, (void *)plen };
		void *res[] = { &plen };

		if (olpc_ofw("getprop", args, res)) {
			pr_err("PROM: %s: getprop failed!\n", __func__);
			return -1;
		}
	}

	return plen;
}

static int __init olpc_dt_nextprop(phandle node, char *prev, char *buf)
{
	const void *args[] = { (void *)node, prev, buf };
	int success;
	void *res[] = { &success };

	buf[0] = '\0';

	if ((s32)node == -1)
		return -1;

	if (olpc_ofw("nextprop", args, res) || success != 1)
		return -1;

	return 0;
}

static int __init olpc_dt_pkg2path(phandle node, char *buf,
		const int buflen, int *len)
{
	const void *args[] = { (void *)node, buf, (void *)buflen };
	void *res[] = { len };

	if ((s32)node == -1)
		return -1;

	if (olpc_ofw("package-to-path", args, res) || *len < 1)
		return -1;

	return 0;
}

static unsigned int prom_early_allocated __initdata;

void * __init prom_early_alloc(unsigned long size)
{
	static u8 *mem;
	static size_t free_mem;
	void *res;

	if (free_mem < size) {
		const size_t chunk_size = max(PAGE_SIZE, size);

		/*
		 * To mimimize the number of allocations, grab at least
		 * PAGE_SIZE of memory (that's an arbitrary choice that's
		 * fast enough on the platforms we care about while minimizing
		 * wasted bootmem) and hand off chunks of it to callers.
		 */
		res = alloc_bootmem(chunk_size);
		BUG_ON(!res);
		prom_early_allocated += chunk_size;
		memset(res, 0, chunk_size);
		free_mem = chunk_size;
		mem = res;
	}

	/* allocate from the local cache */
	free_mem -= size;
	res = mem;
	mem += size;
	return res;
}

static struct of_pdt_ops prom_olpc_ops __initdata = {
	.nextprop = olpc_dt_nextprop,
	.getproplen = olpc_dt_getproplen,
	.getproperty = olpc_dt_getproperty,
	.getchild = olpc_dt_getchild,
	.getsibling = olpc_dt_getsibling,
	.pkg2path = olpc_dt_pkg2path,
};

static phandle __init olpc_dt_finddevice(const char *path)
{
	phandle node;
	const void *args[] = { path };
	void *res[] = { &node };

	if (olpc_ofw("finddevice", args, res)) {
		pr_err("olpc_dt: finddevice failed!\n");
		return 0;
	}

	if ((s32) node == -1)
		return 0;

	return node;
}

static int __init olpc_dt_interpret(const char *words)
{
	int result;
	const void *args[] = { words };
	void *res[] = { &result };

	if (olpc_ofw("interpret", args, res)) {
		pr_err("olpc_dt: interpret failed!\n");
		return -1;
	}

	return result;
}

/*
 * Extract board revision directly from OFW device tree.
 * We can't use olpc_platform_info because that hasn't been set up yet.
 */
static u32 __init olpc_dt_get_board_revision(void)
{
	phandle node;
	__be32 rev;
	int r;

	node = olpc_dt_finddevice("/");
	if (!node)
		return 0;

	r = olpc_dt_getproperty(node, "board-revision-int",
				(char *) &rev, sizeof(rev));
	if (r < 0)
		return 0;

	return be32_to_cpu(rev);
}

void __init olpc_dt_fixup(void)
{
	int r;
	char buf[64];
	phandle node;
	u32 board_rev;

	node = olpc_dt_finddevice("/battery@0");
	if (!node)
		return;

	/*
	 * If the battery node has a compatible property, we are running a new
	 * enough firmware and don't have fixups to make.
	 */
	r = olpc_dt_getproperty(node, "compatible", buf, sizeof(buf));
	if (r > 0)
		return;

	pr_info("PROM DT: Old firmware detected, applying fixes\n");

	/* Add olpc,xo1-battery compatible marker to battery node */
	olpc_dt_interpret("\" /battery@0\" find-device"
		" \" olpc,xo1-battery\" +compatible"
		" device-end");

	board_rev = olpc_dt_get_board_revision();
	if (!board_rev)
		return;

	if (board_rev >= olpc_board_pre(0xd0)) {
		/* XO-1.5: add dcon device */
		olpc_dt_interpret("\" /pci/display@1\" find-device"
			" new-device"
			" \" dcon\" device-name \" olpc,xo1-dcon\" +compatible"
			" finish-device device-end");
	} else {
		/* XO-1: add dcon device, mark RTC as olpc,xo1-rtc */
		olpc_dt_interpret("\" /pci/display@1,1\" find-device"
			" new-device"
			" \" dcon\" device-name \" olpc,xo1-dcon\" +compatible"
			" finish-device device-end"
			" \" /rtc\" find-device"
			" \" olpc,xo1-rtc\" +compatible"
			" device-end");
	}
}

void __init olpc_dt_build_devicetree(void)
{
	phandle root;

	if (!olpc_ofw_is_installed())
		return;

	olpc_dt_fixup();

	root = olpc_dt_getsibling(0);
	if (!root) {
		pr_err("PROM: unable to get root node from OFW!\n");
		return;
	}
	of_pdt_build_devicetree(root, &prom_olpc_ops);

	pr_info("PROM DT: Built device tree with %u bytes of memory.\n",
			prom_early_allocated);
}

/* A list of DT node/bus matches that we want to expose as platform devices */
static struct of_device_id __initdata of_ids[] = {
	{ .compatible = "olpc,xo1-battery" },
	{ .compatible = "olpc,xo1-dcon" },
	{ .compatible = "olpc,xo1-rtc" },
	{},
};

static int __init olpc_create_platform_devices(void)
{
	if (machine_is_olpc())
		return of_platform_bus_probe(NULL, of_ids, NULL);
	else
		return 0;
}
device_initcall(olpc_create_platform_devices);
