/*
 * Copyright (C) 2012 CERN (www.cern.ch)
 * Author: Alessandro Rubini <rubini@gnudd.com>
 *
 * Released according to the GNU GPL, version 2 or any later version.
 *
 * This work is part of the White Rabbit project, a research effort led
 * by CERN, the European Institute for Nuclear Research.
 */
#include <linux/module.h>
#include <linux/slab.h>
#include <linux/fmc.h>
#include <linux/sdb.h>
#include <linux/err.h>
#include <linux/fmc-sdb.h>
#include <asm/byteorder.h>

static uint32_t __sdb_rd(struct fmc_device *fmc, unsigned long address,
			int convert)
{
	uint32_t res = fmc_readl(fmc, address);
	if (convert)
		return __be32_to_cpu(res);
	return res;
}

static struct sdb_array *__fmc_scan_sdb_tree(struct fmc_device *fmc,
					     unsigned long sdb_addr,
					     unsigned long reg_base, int level)
{
	uint32_t onew;
	int i, j, n, convert = 0;
	struct sdb_array *arr, *sub;

	onew = fmc_readl(fmc, sdb_addr);
	if (onew == SDB_MAGIC) {
		/* Uh! If we are little-endian, we must convert */
		if (SDB_MAGIC != __be32_to_cpu(SDB_MAGIC))
			convert = 1;
	} else if (onew == __be32_to_cpu(SDB_MAGIC)) {
		/* ok, don't convert */
	} else {
		return ERR_PTR(-ENOENT);
	}
	/* So, the magic was there: get the count from offset 4*/
	onew = __sdb_rd(fmc, sdb_addr + 4, convert);
	n = __be16_to_cpu(*(uint16_t *)&onew);
	arr = kzalloc(sizeof(*arr), GFP_KERNEL);
	if (!arr)
		return ERR_PTR(-ENOMEM);
	arr->record = kzalloc(sizeof(arr->record[0]) * n, GFP_KERNEL);
	arr->subtree = kzalloc(sizeof(arr->subtree[0]) * n, GFP_KERNEL);
	if (!arr->record || !arr->subtree) {
		kfree(arr->record);
		kfree(arr->subtree);
		kfree(arr);
		return ERR_PTR(-ENOMEM);
	}

	arr->len = n;
	arr->level = level;
	arr->fmc = fmc;
	for (i = 0; i < n; i++) {
		union  sdb_record *r;

		for (j = 0; j < sizeof(arr->record[0]); j += 4) {
			*(uint32_t *)((void *)(arr->record + i) + j) =
				__sdb_rd(fmc, sdb_addr + (i * 64) + j, convert);
		}
		r = &arr->record[i];
		arr->subtree[i] = ERR_PTR(-ENODEV);
		if (r->empty.record_type == sdb_type_bridge) {
			struct sdb_component *c = &r->bridge.sdb_component;
			uint64_t subaddr = __be64_to_cpu(r->bridge.sdb_child);
			uint64_t newbase = __be64_to_cpu(c->addr_first);

			subaddr += reg_base;
			newbase += reg_base;
			sub = __fmc_scan_sdb_tree(fmc, subaddr, newbase,
						  level + 1);
			arr->subtree[i] = sub; /* may be error */
			if (IS_ERR(sub))
				continue;
			sub->parent = arr;
			sub->baseaddr = newbase;
		}
	}
	return arr;
}

int fmc_scan_sdb_tree(struct fmc_device *fmc, unsigned long address)
{
	struct sdb_array *ret;
	if (fmc->sdb)
		return -EBUSY;
	ret = __fmc_scan_sdb_tree(fmc, address, 0 /* regs */, 0);
	if (IS_ERR(ret))
		return PTR_ERR(ret);
	fmc->sdb = ret;
	return 0;
}
EXPORT_SYMBOL(fmc_scan_sdb_tree);

static void __fmc_sdb_free(struct sdb_array *arr)
{
	int i, n;

	if (!arr)
		return;
	n = arr->len;
	for (i = 0; i < n; i++) {
		if (IS_ERR(arr->subtree[i]))
			continue;
		__fmc_sdb_free(arr->subtree[i]);
	}
	kfree(arr->record);
	kfree(arr->subtree);
	kfree(arr);
}

int fmc_free_sdb_tree(struct fmc_device *fmc)
{
	__fmc_sdb_free(fmc->sdb);
	fmc->sdb = NULL;
	return 0;
}
EXPORT_SYMBOL(fmc_free_sdb_tree);

/* This helper calls reprogram and inizialized sdb as well */
int fmc_reprogram(struct fmc_device *fmc, struct fmc_driver *d, char *gw,
			 int sdb_entry)
{
	int ret;

	ret = fmc->op->reprogram(fmc, d, gw);
	if (ret < 0)
		return ret;
	if (sdb_entry < 0)
		return ret;

	/* We are required to find SDB at a given offset */
	ret = fmc_scan_sdb_tree(fmc, sdb_entry);
	if (ret < 0) {
		dev_err(&fmc->dev, "Can't find SDB at address 0x%x\n",
			sdb_entry);
		return -ENODEV;
	}
	fmc_dump_sdb(fmc);
	return 0;
}
EXPORT_SYMBOL(fmc_reprogram);

static char *__strip_trailing_space(char *buf, char *str, int len)
{
	int i = len - 1;

	memcpy(buf, str, len);
	while(i >= 0 && buf[i] == ' ')
		buf[i--] = '\0';
	return buf;
}

#define __sdb_string(buf, field) ({			\
	BUILD_BUG_ON(sizeof(buf) < sizeof(field));	\
	__strip_trailing_space(buf, (void *)(field), sizeof(field));	\
		})

static void __fmc_show_sdb_tree(const struct fmc_device *fmc,
				const struct sdb_array *arr)
{
	unsigned long base = arr->baseaddr;
	int i, j, n = arr->len, level = arr->level;
	char buf[64];

	for (i = 0; i < n; i++) {
		union  sdb_record *r;
		struct sdb_product *p;
		struct sdb_component *c;
		r = &arr->record[i];
		c = &r->dev.sdb_component;
		p = &c->product;

		dev_info(&fmc->dev, "SDB: ");

		for (j = 0; j < level; j++)
			printk(KERN_CONT "   ");
		switch (r->empty.record_type) {
		case sdb_type_interconnect:
			printk(KERN_CONT "%08llx:%08x %.19s\n",
			       __be64_to_cpu(p->vendor_id),
			       __be32_to_cpu(p->device_id),
			       p->name);
			break;
		case sdb_type_device:
			printk(KERN_CONT "%08llx:%08x %.19s (%08llx-%08llx)\n",
			       __be64_to_cpu(p->vendor_id),
			       __be32_to_cpu(p->device_id),
			       p->name,
			       __be64_to_cpu(c->addr_first) + base,
			       __be64_to_cpu(c->addr_last) + base);
			break;
		case sdb_type_bridge:
			printk(KERN_CONT "%08llx:%08x %.19s (bridge: %08llx)\n",
			       __be64_to_cpu(p->vendor_id),
			       __be32_to_cpu(p->device_id),
			       p->name,
			       __be64_to_cpu(c->addr_first) + base);
			if (IS_ERR(arr->subtree[i])) {
				dev_info(&fmc->dev, "SDB: (bridge error %li)\n",
					 PTR_ERR(arr->subtree[i]));
				break;
			}
			__fmc_show_sdb_tree(fmc, arr->subtree[i]);
			break;
		case sdb_type_integration:
			printk(KERN_CONT "integration\n");
			break;
		case sdb_type_repo_url:
			printk(KERN_CONT "Synthesis repository: %s\n",
			       __sdb_string(buf, r->repo_url.repo_url));
			break;
		case sdb_type_synthesis:
			printk(KERN_CONT "Bitstream '%s' ",
			       __sdb_string(buf, r->synthesis.syn_name));
			printk(KERN_CONT "synthesized %08x by %s ",
			       __be32_to_cpu(r->synthesis.date),
			       __sdb_string(buf, r->synthesis.user_name));
			printk(KERN_CONT "(%s version %x), ",
			       __sdb_string(buf, r->synthesis.tool_name),
			       __be32_to_cpu(r->synthesis.tool_version));
			printk(KERN_CONT "commit %pm\n",
			       r->synthesis.commit_id);
			break;
		case sdb_type_empty:
			printk(KERN_CONT "empty\n");
			break;
		default:
			printk(KERN_CONT "UNKNOWN TYPE 0x%02x\n",
			       r->empty.record_type);
			break;
		}
	}
}

void fmc_show_sdb_tree(const struct fmc_device *fmc)
{
	if (!fmc->sdb)
		return;
	__fmc_show_sdb_tree(fmc, fmc->sdb);
}
EXPORT_SYMBOL(fmc_show_sdb_tree);

signed long fmc_find_sdb_device(struct sdb_array *tree,
				uint64_t vid, uint32_t did, unsigned long *sz)
{
	signed long res = -ENODEV;
	union  sdb_record *r;
	struct sdb_product *p;
	struct sdb_component *c;
	int i, n = tree->len;
	uint64_t last, first;

	/* FIXME: what if the first interconnect is not at zero? */
	for (i = 0; i < n; i++) {
		r = &tree->record[i];
		c = &r->dev.sdb_component;
		p = &c->product;

		if (!IS_ERR(tree->subtree[i]))
			res = fmc_find_sdb_device(tree->subtree[i],
						  vid, did, sz);
		if (res >= 0)
			return res + tree->baseaddr;
		if (r->empty.record_type != sdb_type_device)
			continue;
		if (__be64_to_cpu(p->vendor_id) != vid)
			continue;
		if (__be32_to_cpu(p->device_id) != did)
			continue;
		/* found */
		last = __be64_to_cpu(c->addr_last);
		first = __be64_to_cpu(c->addr_first);
		if (sz)
			*sz = (typeof(*sz))(last + 1 - first);
		return first + tree->baseaddr;
	}
	return res;
}
EXPORT_SYMBOL(fmc_find_sdb_device);
