/*
 *  drivers/irqchip/irq-crossbar.c
 *
 *  Copyright (C) 2013 Texas Instruments Incorporated - http://www.ti.com
 *  Author: Sricharan R <r.sricharan@ti.com>
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 as
 * published by the Free Software Foundation.
 *
 */
#include <linux/err.h>
#include <linux/io.h>
#include <linux/of_address.h>
#include <linux/of_irq.h>
#include <linux/slab.h>
#include <linux/irqchip/arm-gic.h>
#include <linux/irqchip/irq-crossbar.h>

#define IRQ_FREE	-1
#define IRQ_RESERVED	-2
#define IRQ_SKIP	-3
#define GIC_IRQ_START	32

/**
 * struct crossbar_device - crossbar device description
 * @int_max: maximum number of supported interrupts
 * @safe_map: safe default value to initialize the crossbar
 * @max_crossbar_sources: Maximum number of crossbar sources
 * @irq_map: array of interrupts to crossbar number mapping
 * @crossbar_base: crossbar base address
 * @register_offsets: offsets for each irq number
 * @write: register write function pointer
 */
struct crossbar_device {
	uint int_max;
	uint safe_map;
	uint max_crossbar_sources;
	uint *irq_map;
	void __iomem *crossbar_base;
	int *register_offsets;
	void (*write)(int, int);
};

static struct crossbar_device *cb;

static inline void crossbar_writel(int irq_no, int cb_no)
{
	writel(cb_no, cb->crossbar_base + cb->register_offsets[irq_no]);
}

static inline void crossbar_writew(int irq_no, int cb_no)
{
	writew(cb_no, cb->crossbar_base + cb->register_offsets[irq_no]);
}

static inline void crossbar_writeb(int irq_no, int cb_no)
{
	writeb(cb_no, cb->crossbar_base + cb->register_offsets[irq_no]);
}

static inline int get_prev_map_irq(int cb_no)
{
	int i;

	for (i = cb->int_max - 1; i >= 0; i--)
		if (cb->irq_map[i] == cb_no)
			return i;

	return -ENODEV;
}

static inline int allocate_free_irq(int cb_no)
{
	int i;

	for (i = cb->int_max - 1; i >= 0; i--) {
		if (cb->irq_map[i] == IRQ_FREE) {
			cb->irq_map[i] = cb_no;
			return i;
		}
	}

	return -ENODEV;
}

static inline bool needs_crossbar_write(irq_hw_number_t hw)
{
	int cb_no;

	if (hw > GIC_IRQ_START) {
		cb_no = cb->irq_map[hw - GIC_IRQ_START];
		if (cb_no != IRQ_RESERVED && cb_no != IRQ_SKIP)
			return true;
	}

	return false;
}

static int crossbar_domain_map(struct irq_domain *d, unsigned int irq,
			       irq_hw_number_t hw)
{
	if (needs_crossbar_write(hw))
		cb->write(hw - GIC_IRQ_START, cb->irq_map[hw - GIC_IRQ_START]);

	return 0;
}

/**
 * crossbar_domain_unmap - unmap a crossbar<->irq connection
 * @d: domain of irq to unmap
 * @irq: virq number
 *
 * We do not maintain a use count of total number of map/unmap
 * calls for a particular irq to find out if a irq can be really
 * unmapped. This is because unmap is called during irq_dispose_mapping(irq),
 * after which irq is anyways unusable. So an explicit map has to be called
 * after that.
 */
static void crossbar_domain_unmap(struct irq_domain *d, unsigned int irq)
{
	irq_hw_number_t hw = irq_get_irq_data(irq)->hwirq;

	if (needs_crossbar_write(hw)) {
		cb->irq_map[hw - GIC_IRQ_START] = IRQ_FREE;
		cb->write(hw - GIC_IRQ_START, cb->safe_map);
	}
}

static int crossbar_domain_xlate(struct irq_domain *d,
				 struct device_node *controller,
				 const u32 *intspec, unsigned int intsize,
				 unsigned long *out_hwirq,
				 unsigned int *out_type)
{
	int ret;
	int req_num = intspec[1];
	int direct_map_num;

	if (req_num >= cb->max_crossbar_sources) {
		direct_map_num = req_num - cb->max_crossbar_sources;
		if (direct_map_num < cb->int_max) {
			ret = cb->irq_map[direct_map_num];
			if (ret == IRQ_RESERVED || ret == IRQ_SKIP) {
				/* We use the interrupt num as h/w irq num */
				ret = direct_map_num;
				goto found;
			}
		}

		pr_err("%s: requested crossbar number %d > max %d\n",
		       __func__, req_num, cb->max_crossbar_sources);
		return -EINVAL;
	}

	ret = get_prev_map_irq(req_num);
	if (ret >= 0)
		goto found;

	ret = allocate_free_irq(req_num);

	if (ret < 0)
		return ret;

found:
	*out_hwirq = ret + GIC_IRQ_START;
	return 0;
}

static const struct irq_domain_ops routable_irq_domain_ops = {
	.map = crossbar_domain_map,
	.unmap = crossbar_domain_unmap,
	.xlate = crossbar_domain_xlate
};

static int __init crossbar_of_init(struct device_node *node)
{
	int i, size, max = 0, reserved = 0, entry;
	const __be32 *irqsr;
	int ret = -ENOMEM;

	cb = kzalloc(sizeof(*cb), GFP_KERNEL);

	if (!cb)
		return ret;

	cb->crossbar_base = of_iomap(node, 0);
	if (!cb->crossbar_base)
		goto err_cb;

	of_property_read_u32(node, "ti,max-crossbar-sources",
			     &cb->max_crossbar_sources);
	if (!cb->max_crossbar_sources) {
		pr_err("missing 'ti,max-crossbar-sources' property\n");
		ret = -EINVAL;
		goto err_base;
	}

	of_property_read_u32(node, "ti,max-irqs", &max);
	if (!max) {
		pr_err("missing 'ti,max-irqs' property\n");
		ret = -EINVAL;
		goto err_base;
	}
	cb->irq_map = kcalloc(max, sizeof(int), GFP_KERNEL);
	if (!cb->irq_map)
		goto err_base;

	cb->int_max = max;

	for (i = 0; i < max; i++)
		cb->irq_map[i] = IRQ_FREE;

	/* Get and mark reserved irqs */
	irqsr = of_get_property(node, "ti,irqs-reserved", &size);
	if (irqsr) {
		size /= sizeof(__be32);

		for (i = 0; i < size; i++) {
			of_property_read_u32_index(node,
						   "ti,irqs-reserved",
						   i, &entry);
			if (entry > max) {
				pr_err("Invalid reserved entry\n");
				ret = -EINVAL;
				goto err_irq_map;
			}
			cb->irq_map[entry] = IRQ_RESERVED;
		}
	}

	/* Skip irqs hardwired to bypass the crossbar */
	irqsr = of_get_property(node, "ti,irqs-skip", &size);
	if (irqsr) {
		size /= sizeof(__be32);

		for (i = 0; i < size; i++) {
			of_property_read_u32_index(node,
						   "ti,irqs-skip",
						   i, &entry);
			if (entry > max) {
				pr_err("Invalid skip entry\n");
				ret = -EINVAL;
				goto err_irq_map;
			}
			cb->irq_map[entry] = IRQ_SKIP;
		}
	}


	cb->register_offsets = kcalloc(max, sizeof(int), GFP_KERNEL);
	if (!cb->register_offsets)
		goto err_irq_map;

	of_property_read_u32(node, "ti,reg-size", &size);

	switch (size) {
	case 1:
		cb->write = crossbar_writeb;
		break;
	case 2:
		cb->write = crossbar_writew;
		break;
	case 4:
		cb->write = crossbar_writel;
		break;
	default:
		pr_err("Invalid reg-size property\n");
		ret = -EINVAL;
		goto err_reg_offset;
		break;
	}

	/*
	 * Register offsets are not linear because of the
	 * reserved irqs. so find and store the offsets once.
	 */
	for (i = 0; i < max; i++) {
		if (cb->irq_map[i] == IRQ_RESERVED)
			continue;

		cb->register_offsets[i] = reserved;
		reserved += size;
	}

	of_property_read_u32(node, "ti,irqs-safe-map", &cb->safe_map);
	/* Initialize the crossbar with safe map to start with */
	for (i = 0; i < max; i++) {
		if (cb->irq_map[i] == IRQ_RESERVED ||
		    cb->irq_map[i] == IRQ_SKIP)
			continue;

		cb->write(i, cb->safe_map);
	}

	register_routable_domain_ops(&routable_irq_domain_ops);
	return 0;

err_reg_offset:
	kfree(cb->register_offsets);
err_irq_map:
	kfree(cb->irq_map);
err_base:
	iounmap(cb->crossbar_base);
err_cb:
	kfree(cb);

	cb = NULL;
	return ret;
}

static const struct of_device_id crossbar_match[] __initconst = {
	{ .compatible = "ti,irq-crossbar" },
	{}
};

int __init irqcrossbar_init(void)
{
	struct device_node *np;
	np = of_find_matching_node(NULL, crossbar_match);
	if (!np)
		return -ENODEV;

	crossbar_of_init(np);
	return 0;
}
