/*
 * Copyright 2006, Segher Boessenkool, IBM Corporation.
 * 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/bootmem.h>
#include <linux/msi.h>
#include <asm/mpic.h>
#include <asm/prom.h>
#include <asm/hw_irq.h>
#include <asm/ppc-pci.h>
#include <asm/msi_bitmap.h>

#include "mpic.h"

/* A bit ugly, can we get this from the pci_dev somehow? */
static struct mpic *msi_mpic;

static void mpic_u3msi_mask_irq(unsigned int irq)
{
	mask_msi_irq(irq);
	mpic_mask_irq(irq);
}

static void mpic_u3msi_unmask_irq(unsigned int irq)
{
	mpic_unmask_irq(irq);
	unmask_msi_irq(irq);
}

static struct irq_chip mpic_u3msi_chip = {
	.shutdown	= mpic_u3msi_mask_irq,
	.mask		= mpic_u3msi_mask_irq,
	.unmask		= mpic_u3msi_unmask_irq,
	.eoi		= mpic_end_irq,
	.set_type	= mpic_set_irq_type,
	.set_affinity	= mpic_set_affinity,
	.name		= "MPIC-U3MSI",
};

static u64 read_ht_magic_addr(struct pci_dev *pdev, unsigned int pos)
{
	u8 flags;
	u32 tmp;
	u64 addr;

	pci_read_config_byte(pdev, pos + HT_MSI_FLAGS, &flags);

	if (flags & HT_MSI_FLAGS_FIXED)
		return HT_MSI_FIXED_ADDR;

	pci_read_config_dword(pdev, pos + HT_MSI_ADDR_LO, &tmp);
	addr = tmp & HT_MSI_ADDR_LO_MASK;
	pci_read_config_dword(pdev, pos + HT_MSI_ADDR_HI, &tmp);
	addr = addr | ((u64)tmp << 32);

	return addr;
}

static u64 find_ht_magic_addr(struct pci_dev *pdev, unsigned int hwirq)
{
	struct pci_bus *bus;
	unsigned int pos;

	for (bus = pdev->bus; bus && bus->self; bus = bus->parent) {
		pos = pci_find_ht_capability(bus->self, HT_CAPTYPE_MSI_MAPPING);
		if (pos)
			return read_ht_magic_addr(bus->self, pos);
	}

	return 0;
}

static u64 find_u4_magic_addr(struct pci_dev *pdev, unsigned int hwirq)
{
	struct pci_controller *hose = pci_bus_to_host(pdev->bus);

	/* U4 PCIe MSIs need to write to the special register in
	 * the bridge that generates interrupts. There should be
	 * theorically a register at 0xf8005000 where you just write
	 * the MSI number and that triggers the right interrupt, but
	 * unfortunately, this is busted in HW, the bridge endian swaps
	 * the value and hits the wrong nibble in the register.
	 *
	 * So instead we use another register set which is used normally
	 * for converting HT interrupts to MPIC interrupts, which decodes
	 * the interrupt number as part of the low address bits
	 *
	 * This will not work if we ever use more than one legacy MSI in
	 * a block but we never do. For one MSI or multiple MSI-X where
	 * each interrupt address can be specified separately, it works
	 * just fine.
	 */
	if (of_device_is_compatible(hose->dn, "u4-pcie") ||
	    of_device_is_compatible(hose->dn, "U4-pcie"))
		return 0xf8004000 | (hwirq << 4);

	return 0;
}

static int u3msi_msi_check_device(struct pci_dev *pdev, int nvec, int type)
{
	if (type == PCI_CAP_ID_MSIX)
		pr_debug("u3msi: MSI-X untested, trying anyway.\n");

	/* If we can't find a magic address then MSI ain't gonna work */
	if (find_ht_magic_addr(pdev, 0) == 0 &&
	    find_u4_magic_addr(pdev, 0) == 0) {
		pr_debug("u3msi: no magic address found for %s\n",
			 pci_name(pdev));
		return -ENXIO;
	}

	return 0;
}

static void u3msi_teardown_msi_irqs(struct pci_dev *pdev)
{
	struct msi_desc *entry;

        list_for_each_entry(entry, &pdev->msi_list, list) {
		if (entry->irq == NO_IRQ)
			continue;

		set_irq_msi(entry->irq, NULL);
		msi_bitmap_free_hwirqs(&msi_mpic->msi_bitmap,
				       virq_to_hw(entry->irq), 1);
		irq_dispose_mapping(entry->irq);
	}

	return;
}

static int u3msi_setup_msi_irqs(struct pci_dev *pdev, int nvec, int type)
{
	unsigned int virq;
	struct msi_desc *entry;
	struct msi_msg msg;
	u64 addr;
	int hwirq;

	list_for_each_entry(entry, &pdev->msi_list, list) {
		hwirq = msi_bitmap_alloc_hwirqs(&msi_mpic->msi_bitmap, 1);
		if (hwirq < 0) {
			pr_debug("u3msi: failed allocating hwirq\n");
			return hwirq;
		}

		addr = find_ht_magic_addr(pdev, hwirq);
		if (addr == 0)
			addr = find_u4_magic_addr(pdev, hwirq);
		msg.address_lo = addr & 0xFFFFFFFF;
		msg.address_hi = addr >> 32;

		virq = irq_create_mapping(msi_mpic->irqhost, hwirq);
		if (virq == NO_IRQ) {
			pr_debug("u3msi: failed mapping hwirq 0x%x\n", hwirq);
			msi_bitmap_free_hwirqs(&msi_mpic->msi_bitmap, hwirq, 1);
			return -ENOSPC;
		}

		set_irq_msi(virq, entry);
		set_irq_chip(virq, &mpic_u3msi_chip);
		set_irq_type(virq, IRQ_TYPE_EDGE_RISING);

		pr_debug("u3msi: allocated virq 0x%x (hw 0x%x) addr 0x%lx\n",
			  virq, hwirq, (unsigned long)addr);

		printk("u3msi: allocated virq 0x%x (hw 0x%x) addr 0x%lx\n",
			  virq, hwirq, (unsigned long)addr);
		msg.data = hwirq;
		write_msi_msg(virq, &msg);

		hwirq++;
	}

	return 0;
}

int mpic_u3msi_init(struct mpic *mpic)
{
	int rc;

	rc = mpic_msi_init_allocator(mpic);
	if (rc) {
		pr_debug("u3msi: Error allocating bitmap!\n");
		return rc;
	}

	pr_debug("u3msi: Registering MPIC U3 MSI callbacks.\n");

	BUG_ON(msi_mpic);
	msi_mpic = mpic;

	WARN_ON(ppc_md.setup_msi_irqs);
	ppc_md.setup_msi_irqs = u3msi_setup_msi_irqs;
	ppc_md.teardown_msi_irqs = u3msi_teardown_msi_irqs;
	ppc_md.msi_check_device = u3msi_msi_check_device;

	return 0;
}
