/*
 * Copyright 2011-2012, Meador Inge, Mentor Graphics Corporation.
 *
 * Some ideas based on un-pushed work done by Vivek Mahajan, Jason Jin, and
 * Mingkai Hu from Freescale Semiconductor, Inc.
 *
 * 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/list.h>
#include <linux/of_platform.h>
#include <linux/errno.h>
#include <asm/prom.h>
#include <asm/hw_irq.h>
#include <asm/ppc-pci.h>
#include <asm/mpic_msgr.h>

#define MPIC_MSGR_REGISTERS_PER_BLOCK	4
#define MPIC_MSGR_STRIDE		0x10
#define MPIC_MSGR_MER_OFFSET		0x100
#define MSGR_INUSE			0
#define MSGR_FREE			1

static struct mpic_msgr **mpic_msgrs;
static unsigned int mpic_msgr_count;
static DEFINE_RAW_SPINLOCK(msgrs_lock);

static inline void _mpic_msgr_mer_write(struct mpic_msgr *msgr, u32 value)
{
	out_be32(msgr->mer, value);
}

static inline u32 _mpic_msgr_mer_read(struct mpic_msgr *msgr)
{
	return in_be32(msgr->mer);
}

static inline void _mpic_msgr_disable(struct mpic_msgr *msgr)
{
	u32 mer = _mpic_msgr_mer_read(msgr);

	_mpic_msgr_mer_write(msgr, mer & ~(1 << msgr->num));
}

struct mpic_msgr *mpic_msgr_get(unsigned int reg_num)
{
	unsigned long flags;
	struct mpic_msgr *msgr;

	/* Assume busy until proven otherwise.  */
	msgr = ERR_PTR(-EBUSY);

	if (reg_num >= mpic_msgr_count)
		return ERR_PTR(-ENODEV);

	raw_spin_lock_irqsave(&msgrs_lock, flags);
	msgr = mpic_msgrs[reg_num];
	if (msgr->in_use == MSGR_FREE)
		msgr->in_use = MSGR_INUSE;
	raw_spin_unlock_irqrestore(&msgrs_lock, flags);

	return msgr;
}
EXPORT_SYMBOL_GPL(mpic_msgr_get);

void mpic_msgr_put(struct mpic_msgr *msgr)
{
	unsigned long flags;

	raw_spin_lock_irqsave(&msgr->lock, flags);
	msgr->in_use = MSGR_FREE;
	_mpic_msgr_disable(msgr);
	raw_spin_unlock_irqrestore(&msgr->lock, flags);
}
EXPORT_SYMBOL_GPL(mpic_msgr_put);

void mpic_msgr_enable(struct mpic_msgr *msgr)
{
	unsigned long flags;
	u32 mer;

	raw_spin_lock_irqsave(&msgr->lock, flags);
	mer = _mpic_msgr_mer_read(msgr);
	_mpic_msgr_mer_write(msgr, mer | (1 << msgr->num));
	raw_spin_unlock_irqrestore(&msgr->lock, flags);
}
EXPORT_SYMBOL_GPL(mpic_msgr_enable);

void mpic_msgr_disable(struct mpic_msgr *msgr)
{
	unsigned long flags;

	raw_spin_lock_irqsave(&msgr->lock, flags);
	_mpic_msgr_disable(msgr);
	raw_spin_unlock_irqrestore(&msgr->lock, flags);
}
EXPORT_SYMBOL_GPL(mpic_msgr_disable);

/* The following three functions are used to compute the order and number of
 * the message register blocks.  They are clearly very inefficent.  However,
 * they are called *only* a few times during device initialization.
 */
static unsigned int mpic_msgr_number_of_blocks(void)
{
	unsigned int count;
	struct device_node *aliases;

	count = 0;
	aliases = of_find_node_by_name(NULL, "aliases");

	if (aliases) {
		char buf[32];

		for (;;) {
			snprintf(buf, sizeof(buf), "mpic-msgr-block%d", count);
			if (!of_find_property(aliases, buf, NULL))
				break;

			count += 1;
		}
	}

	return count;
}

static unsigned int mpic_msgr_number_of_registers(void)
{
	return mpic_msgr_number_of_blocks() * MPIC_MSGR_REGISTERS_PER_BLOCK;
}

static int mpic_msgr_block_number(struct device_node *node)
{
	struct device_node *aliases;
	unsigned int index, number_of_blocks;
	char buf[64];

	number_of_blocks = mpic_msgr_number_of_blocks();
	aliases = of_find_node_by_name(NULL, "aliases");
	if (!aliases)
		return -1;

	for (index = 0; index < number_of_blocks; ++index) {
		struct property *prop;

		snprintf(buf, sizeof(buf), "mpic-msgr-block%d", index);
		prop = of_find_property(aliases, buf, NULL);
		if (node == of_find_node_by_path(prop->value))
			break;
	}

	return index == number_of_blocks ? -1 : index;
}

/* The probe function for a single message register block.
 */
static __devinit int mpic_msgr_probe(struct platform_device *dev)
{
	void __iomem *msgr_block_addr;
	int block_number;
	struct resource rsrc;
	unsigned int i;
	unsigned int irq_index;
	struct device_node *np = dev->dev.of_node;
	unsigned int receive_mask;
	const unsigned int *prop;

	if (!np) {
		dev_err(&dev->dev, "Device OF-Node is NULL");
		return -EFAULT;
	}

	/* Allocate the message register array upon the first device
	 * registered.
	 */
	if (!mpic_msgrs) {
		mpic_msgr_count = mpic_msgr_number_of_registers();
		dev_info(&dev->dev, "Found %d message registers\n",
				mpic_msgr_count);

		mpic_msgrs = kzalloc(sizeof(struct mpic_msgr) * mpic_msgr_count,
							 GFP_KERNEL);
		if (!mpic_msgrs) {
			dev_err(&dev->dev,
				"No memory for message register blocks\n");
			return -ENOMEM;
		}
	}
	dev_info(&dev->dev, "Of-device full name %s\n", np->full_name);

	/* IO map the message register block. */
	of_address_to_resource(np, 0, &rsrc);
	msgr_block_addr = ioremap(rsrc.start, rsrc.end - rsrc.start);
	if (!msgr_block_addr) {
		dev_err(&dev->dev, "Failed to iomap MPIC message registers");
		return -EFAULT;
	}

	/* Ensure the block has a defined order. */
	block_number = mpic_msgr_block_number(np);
	if (block_number < 0) {
		dev_err(&dev->dev,
			"Failed to find message register block alias\n");
		return -ENODEV;
	}
	dev_info(&dev->dev, "Setting up message register block %d\n",
			block_number);

	/* Grab the receive mask which specifies what registers can receive
	 * interrupts.
	 */
	prop = of_get_property(np, "mpic-msgr-receive-mask", NULL);
	receive_mask = (prop) ? *prop : 0xF;

	/* Build up the appropriate message register data structures. */
	for (i = 0, irq_index = 0; i < MPIC_MSGR_REGISTERS_PER_BLOCK; ++i) {
		struct mpic_msgr *msgr;
		unsigned int reg_number;

		msgr = kzalloc(sizeof(struct mpic_msgr), GFP_KERNEL);
		if (!msgr) {
			dev_err(&dev->dev, "No memory for message register\n");
			return -ENOMEM;
		}

		reg_number = block_number * MPIC_MSGR_REGISTERS_PER_BLOCK + i;
		msgr->base = msgr_block_addr + i * MPIC_MSGR_STRIDE;
		msgr->mer = (u32 *)((u8 *)msgr->base + MPIC_MSGR_MER_OFFSET);
		msgr->in_use = MSGR_FREE;
		msgr->num = i;
		raw_spin_lock_init(&msgr->lock);

		if (receive_mask & (1 << i)) {
			struct resource irq;

			if (of_irq_to_resource(np, irq_index, &irq) == NO_IRQ) {
				dev_err(&dev->dev,
						"Missing interrupt specifier");
				kfree(msgr);
				return -EFAULT;
			}
			msgr->irq = irq.start;
			irq_index += 1;
		} else {
			msgr->irq = NO_IRQ;
		}

		mpic_msgrs[reg_number] = msgr;
		mpic_msgr_disable(msgr);
		dev_info(&dev->dev, "Register %d initialized: irq %d\n",
				reg_number, msgr->irq);

	}

	return 0;
}

static const struct of_device_id mpic_msgr_ids[] = {
	{
		.compatible = "fsl,mpic-v3.1-msgr",
		.data = NULL,
	},
	{}
};

static struct platform_driver mpic_msgr_driver = {
	.driver = {
		.name = "mpic-msgr",
		.owner = THIS_MODULE,
		.of_match_table = mpic_msgr_ids,
	},
	.probe = mpic_msgr_probe,
};

static __init int mpic_msgr_init(void)
{
	return platform_driver_register(&mpic_msgr_driver);
}
subsys_initcall(mpic_msgr_init);
