/*
 * Copyright 2006-2007, Michael Ellerman, IBM Corporation.
 *
 * 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; version 2 of the
 * License.
 *
 */

#include <linux/irq.h>
#include <linux/bitmap.h>
#include <linux/msi.h>
#include <asm/mpic.h>
#include <asm/prom.h>
#include <asm/hw_irq.h>
#include <asm/ppc-pci.h>


static void __mpic_msi_reserve_hwirq(struct mpic *mpic, irq_hw_number_t hwirq)
{
	pr_debug("mpic: reserving hwirq 0x%lx\n", hwirq);
	bitmap_allocate_region(mpic->hwirq_bitmap, hwirq, 0);
}

void mpic_msi_reserve_hwirq(struct mpic *mpic, irq_hw_number_t hwirq)
{
	unsigned long flags;

	/* The mpic calls this even when there is no allocator setup */
	if (!mpic->hwirq_bitmap)
		return;

	spin_lock_irqsave(&mpic->bitmap_lock, flags);
	__mpic_msi_reserve_hwirq(mpic, hwirq);
	spin_unlock_irqrestore(&mpic->bitmap_lock, flags);
}

irq_hw_number_t mpic_msi_alloc_hwirqs(struct mpic *mpic, int num)
{
	unsigned long flags;
	int offset, order = get_count_order(num);

	spin_lock_irqsave(&mpic->bitmap_lock, flags);
	/*
	 * This is fast, but stricter than we need. We might want to add
	 * a fallback routine which does a linear search with no alignment.
	 */
	offset = bitmap_find_free_region(mpic->hwirq_bitmap, mpic->irq_count,
					 order);
	spin_unlock_irqrestore(&mpic->bitmap_lock, flags);

	pr_debug("mpic: allocated 0x%x (2^%d) at offset 0x%x\n",
		 num, order, offset);

	return offset;
}

void mpic_msi_free_hwirqs(struct mpic *mpic, int offset, int num)
{
	unsigned long flags;
	int order = get_count_order(num);

	pr_debug("mpic: freeing 0x%x (2^%d) at offset 0x%x\n",
		 num, order, offset);

	spin_lock_irqsave(&mpic->bitmap_lock, flags);
	bitmap_release_region(mpic->hwirq_bitmap, offset, order);
	spin_unlock_irqrestore(&mpic->bitmap_lock, flags);
}

#ifdef CONFIG_MPIC_U3_HT_IRQS
static int mpic_msi_reserve_u3_hwirqs(struct mpic *mpic)
{
	irq_hw_number_t hwirq;
	struct irq_host_ops *ops = mpic->irqhost->ops;
	struct device_node *np;
	int flags, index, i;
	struct of_irq oirq;

	pr_debug("mpic: found U3, guessing msi allocator setup\n");

	/* Reserve source numbers we know are reserved in the HW */
	for (i = 0;   i < 8;   i++)
		__mpic_msi_reserve_hwirq(mpic, i);

	for (i = 42;  i < 46;  i++)
		__mpic_msi_reserve_hwirq(mpic, i);

	for (i = 100; i < 105; i++)
		__mpic_msi_reserve_hwirq(mpic, i);

	np = NULL;
	while ((np = of_find_all_nodes(np))) {
		pr_debug("mpic: mapping hwirqs for %s\n", np->full_name);

		index = 0;
		while (of_irq_map_one(np, index++, &oirq) == 0) {
			ops->xlate(mpic->irqhost, NULL, oirq.specifier,
						oirq.size, &hwirq, &flags);
			__mpic_msi_reserve_hwirq(mpic, hwirq);
		}
	}

	return 0;
}
#else
static int mpic_msi_reserve_u3_hwirqs(struct mpic *mpic)
{
	return -1;
}
#endif

static int mpic_msi_reserve_dt_hwirqs(struct mpic *mpic)
{
	int i, len;
	const u32 *p;

	p = of_get_property(mpic->irqhost->of_node,
			    "msi-available-ranges", &len);
	if (!p) {
		pr_debug("mpic: no msi-available-ranges property found on %s\n",
			  mpic->irqhost->of_node->full_name);
		return -ENODEV;
	}

	if (len % 8 != 0) {
		printk(KERN_WARNING "mpic: Malformed msi-available-ranges "
		       "property on %s\n", mpic->irqhost->of_node->full_name);
		return -EINVAL;
	}

	bitmap_allocate_region(mpic->hwirq_bitmap, 0,
			       get_count_order(mpic->irq_count));

	/* Format is: (<u32 start> <u32 count>)+ */
	len /= sizeof(u32);
	for (i = 0; i < len / 2; i++, p += 2)
		mpic_msi_free_hwirqs(mpic, *p, *(p + 1));

	return 0;
}

int mpic_msi_init_allocator(struct mpic *mpic)
{
	int rc, size;

	BUG_ON(mpic->hwirq_bitmap);
	spin_lock_init(&mpic->bitmap_lock);

	size = BITS_TO_LONGS(mpic->irq_count) * sizeof(long);
	pr_debug("mpic: allocator bitmap size is 0x%x bytes\n", size);

	mpic->hwirq_bitmap = alloc_maybe_bootmem(size, GFP_KERNEL);

	if (!mpic->hwirq_bitmap) {
		pr_debug("mpic: ENOMEM allocating allocator bitmap!\n");
		return -ENOMEM;
	}

	memset(mpic->hwirq_bitmap, 0, size);

	rc = mpic_msi_reserve_dt_hwirqs(mpic);
	if (rc) {
		if (mpic->flags & MPIC_U3_HT_IRQS)
			rc = mpic_msi_reserve_u3_hwirqs(mpic);

		if (rc)
			goto out_free;
	}

	return 0;

 out_free:
	if (mem_init_done)
		kfree(mpic->hwirq_bitmap);

	mpic->hwirq_bitmap = NULL;
	return rc;
}
