/*
 * 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);
			len = s - dev->bus_id;
		} else {
			s = dev->bus_id;
			len = strlen(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);
