/*
 * PPC System library functions
 *
 * Maintainer: Kumar Gala <galak@kernel.crashing.org>
 *
 * Copyright 2005 Freescale Semiconductor Inc.
 * Copyright 2005 MontaVista, Inc. by Vitaly Bordug <vbordug@ru.mvista.com>
 *
 * 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/string.h>
#include <linux/bootmem.h>
#include <asm/ppc_sys.h>

int (*ppc_sys_device_fixup) (struct platform_device * pdev);

static int ppc_sys_inited;
static int ppc_sys_func_inited;

static const char *ppc_sys_func_names[] = {
	[PPC_SYS_FUNC_DUMMY] = "dummy",
	[PPC_SYS_FUNC_ETH] = "eth",
	[PPC_SYS_FUNC_UART] = "uart",
	[PPC_SYS_FUNC_HLDC] = "hldc",
	[PPC_SYS_FUNC_USB] = "usb",
	[PPC_SYS_FUNC_IRDA] = "irda",
};

void __init identify_ppc_sys_by_id(u32 id)
{
	unsigned int i = 0;
	while (1) {
		if ((ppc_sys_specs[i].mask & id) == ppc_sys_specs[i].value)
			break;
		i++;
	}

	cur_ppc_sys_spec = &ppc_sys_specs[i];

	return;
}

void __init identify_ppc_sys_by_name(char *name)
{
	unsigned int i = 0;
	while (ppc_sys_specs[i].ppc_sys_name[0]) {
		if (!strcmp(ppc_sys_specs[i].ppc_sys_name, name))
			break;
		i++;
	}
	cur_ppc_sys_spec = &ppc_sys_specs[i];

	return;
}

static int __init count_sys_specs(void)
{
	int i = 0;
	while (ppc_sys_specs[i].ppc_sys_name[0])
		i++;
	return i;
}

static int __init find_chip_by_name_and_id(char *name, u32 id)
{
	int ret = -1;
	unsigned int i = 0;
	unsigned int j = 0;
	unsigned int dups = 0;

	unsigned char matched[count_sys_specs()];

	while (ppc_sys_specs[i].ppc_sys_name[0]) {
		if (!strcmp(ppc_sys_specs[i].ppc_sys_name, name))
			matched[j++] = i;
		i++;
	}

	ret = i;

	if (j != 0) {
		for (i = 0; i < j; i++) {
			if ((ppc_sys_specs[matched[i]].mask & id) ==
			    ppc_sys_specs[matched[i]].value) {
				ret = matched[i];
				dups++;
			}
		}
		ret = (dups == 1) ? ret : (-1 * dups);
	}
	return ret;
}

void __init identify_ppc_sys_by_name_and_id(char *name, u32 id)
{
	int i = find_chip_by_name_and_id(name, id);
	BUG_ON(i < 0);
	cur_ppc_sys_spec = &ppc_sys_specs[i];
}

/* Update all memory resources by paddr, call before platform_device_register */
void __init
ppc_sys_fixup_mem_resource(struct platform_device *pdev, phys_addr_t paddr)
{
	int i;
	for (i = 0; i < pdev->num_resources; i++) {
		struct resource *r = &pdev->resource[i];
		if ((r->flags & IORESOURCE_MEM) == IORESOURCE_MEM) {
			r->start += paddr;
			r->end += paddr;
		}
	}
}

/* Get platform_data pointer out of platform device, call before platform_device_register */
void *__init ppc_sys_get_pdata(enum ppc_sys_devices dev)
{
	return ppc_sys_platform_devices[dev].dev.platform_data;
}

void ppc_sys_device_remove(enum ppc_sys_devices dev)
{
	unsigned int i;

	if (ppc_sys_inited) {
		platform_device_unregister(&ppc_sys_platform_devices[dev]);
	} else {
		if (cur_ppc_sys_spec == NULL)
			return;
		for (i = 0; i < cur_ppc_sys_spec->num_devices; i++)
			if (cur_ppc_sys_spec->device_list[i] == dev)
				cur_ppc_sys_spec->device_list[i] = -1;
	}
}

/* Platform-notify mapping
 * Helper function for BSP code to assign board-specific platfom-divice bits
 */

void platform_notify_map(const struct platform_notify_dev_map *map,
			 struct device *dev)
{
	struct platform_device *pdev;
	int len, idx;
	const char *s;

	/* do nothing if no device or no bus_id */
	if (!dev || !dev->bus_id)
		return;

	/* call per device map */
	while (map->bus_id != NULL) {
		idx = -1;
		s = strrchr(dev->bus_id, '.');
		if (s != NULL)
			idx = (int)simple_strtol(s + 1, NULL, 10);
		else
			s = dev->bus_id;

		len = s - dev->bus_id;

		if (!strncmp(dev->bus_id, map->bus_id, len)) {
			pdev = container_of(dev, struct platform_device, dev);
			map->rtn(pdev, idx);
		}
		map++;
	}
}

/*
   Function assignment stuff.
 Intended to work as follows:
 the device name defined in foo_devices.c will be concatenated with :"func",
 where func is string map of respective function from platfom_device_func enum

 The PPC_SYS_FUNC_DUMMY function is intended to remove all assignments, making the device to appear
 in platform bus with unmodified name.
 */

/*
   Here we'll replace .name pointers with fixed-lenght strings
   Hereby, this should be called *before* any func stuff triggeded.
 */
void ppc_sys_device_initfunc(void)
{
	int i;
	const char *name;
	static char new_names[NUM_PPC_SYS_DEVS][BUS_ID_SIZE];
	enum ppc_sys_devices cur_dev;

	/* If inited yet, do nothing */
	if (ppc_sys_func_inited)
		return;

	for (i = 0; i < cur_ppc_sys_spec->num_devices; i++) {
		if ((cur_dev = cur_ppc_sys_spec->device_list[i]) < 0)
			continue;

		if (ppc_sys_platform_devices[cur_dev].name) {
			/*backup name */
			name = ppc_sys_platform_devices[cur_dev].name;
			strlcpy(new_names[i], name, BUS_ID_SIZE);
			ppc_sys_platform_devices[cur_dev].name = new_names[i];
		}
	}

	ppc_sys_func_inited = 1;
}

/*The "engine" of the func stuff. Here we either concat specified function string description
 to the name, or remove it if PPC_SYS_FUNC_DUMMY parameter is passed here*/
void ppc_sys_device_setfunc(enum ppc_sys_devices dev,
			    enum platform_device_func func)
{
	char *s;
	char *name = (char *)ppc_sys_platform_devices[dev].name;
	char tmp[BUS_ID_SIZE];

	if (!ppc_sys_func_inited) {
		printk(KERN_ERR "Unable to alter function - not inited!\n");
		return;
	}

	if (ppc_sys_inited) {
		platform_device_unregister(&ppc_sys_platform_devices[dev]);
	}

	if ((s = (char *)strchr(name, ':')) != NULL) {	/* reassign */
		/* Either change the name after ':' or remove func modifications */
		if (func != PPC_SYS_FUNC_DUMMY)
			strlcpy(s + 1, ppc_sys_func_names[func], BUS_ID_SIZE);
		else
			*s = 0;
	} else if (func != PPC_SYS_FUNC_DUMMY) {
		/* do assignment if it is not just "clear"  request */
		sprintf(tmp, "%s:%s", name, ppc_sys_func_names[func]);
		strlcpy(name, tmp, BUS_ID_SIZE);
	}

	if (ppc_sys_inited) {
		platform_device_register(&ppc_sys_platform_devices[dev]);
	}
}

void ppc_sys_device_disable(enum ppc_sys_devices dev)
{
	BUG_ON(cur_ppc_sys_spec == NULL);

	/*Check if it is enabled*/
	if(!(cur_ppc_sys_spec->config[dev] & PPC_SYS_CONFIG_DISABLED)) {
		if (ppc_sys_inited) {
			platform_device_unregister(&ppc_sys_platform_devices[dev]);
		}
		cur_ppc_sys_spec->config[dev] |= PPC_SYS_CONFIG_DISABLED;
	}
}

void ppc_sys_device_enable(enum ppc_sys_devices dev)
{
	BUG_ON(cur_ppc_sys_spec == NULL);

	/*Check if it is disabled*/
	if(cur_ppc_sys_spec->config[dev] & PPC_SYS_CONFIG_DISABLED) {
		if (ppc_sys_inited) {
			platform_device_register(&ppc_sys_platform_devices[dev]);
		}
		cur_ppc_sys_spec->config[dev] &= ~PPC_SYS_CONFIG_DISABLED;
	}

}

void ppc_sys_device_enable_all(void)
{
	enum ppc_sys_devices cur_dev;
	int i;

	for (i = 0; i < cur_ppc_sys_spec->num_devices; i++) {
		cur_dev = cur_ppc_sys_spec->device_list[i];
		ppc_sys_device_enable(cur_dev);
	}
}

void ppc_sys_device_disable_all(void)
{
	enum ppc_sys_devices cur_dev;
	int i;

	for (i = 0; i < cur_ppc_sys_spec->num_devices; i++) {
		cur_dev = cur_ppc_sys_spec->device_list[i];
		ppc_sys_device_disable(cur_dev);
	}
}


static int __init ppc_sys_init(void)
{
	unsigned int i, dev_id, ret = 0;

	BUG_ON(cur_ppc_sys_spec == NULL);

	for (i = 0; i < cur_ppc_sys_spec->num_devices; i++) {
		dev_id = cur_ppc_sys_spec->device_list[i];
		if ((dev_id != -1) &&
		!(cur_ppc_sys_spec->config[dev_id] & PPC_SYS_CONFIG_DISABLED)) {
			if (ppc_sys_device_fixup != NULL)
				ppc_sys_device_fixup(&ppc_sys_platform_devices
						     [dev_id]);
			if (platform_device_register
			    (&ppc_sys_platform_devices[dev_id])) {
				ret = 1;
				printk(KERN_ERR
				       "unable to register device %d\n",
				       dev_id);
			}
		}
	}

	ppc_sys_inited = 1;
	return ret;
}

subsys_initcall(ppc_sys_init);
