/*
 * Mailbox reservation modules for OMAP2
 *
 * Copyright (C) 2006 Nokia Corporation
 * Written by: Hiroshi DOYU <Hiroshi.DOYU@nokia.com>
 *        and  Paul Mundt <paul.mundt@nokia.com>
 *
 * This file is subject to the terms and conditions of the GNU General Public
 * License.  See the file "COPYING" in the main directory of this archive
 * for more details.
 */

#include <linux/kernel.h>
#include <linux/clk.h>
#include <linux/err.h>
#include <linux/platform_device.h>
#include <linux/io.h>
#include <mach/mailbox.h>
#include <mach/irqs.h>

#define MAILBOX_REVISION		0x00
#define MAILBOX_SYSCONFIG		0x10
#define MAILBOX_SYSSTATUS		0x14
#define MAILBOX_MESSAGE_0		0x40
#define MAILBOX_MESSAGE_1		0x44
#define MAILBOX_MESSAGE_2		0x48
#define MAILBOX_MESSAGE_3		0x4c
#define MAILBOX_MESSAGE_4		0x50
#define MAILBOX_MESSAGE_5		0x54
#define MAILBOX_FIFOSTATUS_0		0x80
#define MAILBOX_FIFOSTATUS_1		0x84
#define MAILBOX_FIFOSTATUS_2		0x88
#define MAILBOX_FIFOSTATUS_3		0x8c
#define MAILBOX_FIFOSTATUS_4		0x90
#define MAILBOX_FIFOSTATUS_5		0x94
#define MAILBOX_MSGSTATUS_0		0xc0
#define MAILBOX_MSGSTATUS_1		0xc4
#define MAILBOX_MSGSTATUS_2		0xc8
#define MAILBOX_MSGSTATUS_3		0xcc
#define MAILBOX_MSGSTATUS_4		0xd0
#define MAILBOX_MSGSTATUS_5		0xd4
#define MAILBOX_IRQSTATUS_0		0x100
#define MAILBOX_IRQENABLE_0		0x104
#define MAILBOX_IRQSTATUS_1		0x108
#define MAILBOX_IRQENABLE_1		0x10c
#define MAILBOX_IRQSTATUS_2		0x110
#define MAILBOX_IRQENABLE_2		0x114
#define MAILBOX_IRQSTATUS_3		0x118
#define MAILBOX_IRQENABLE_3		0x11c

static unsigned long mbox_base;

#define MAILBOX_IRQ_NOTFULL(n)		(1 << (2 * (n) + 1))
#define MAILBOX_IRQ_NEWMSG(n)		(1 << (2 * (n)))

struct omap_mbox2_fifo {
	unsigned long msg;
	unsigned long fifo_stat;
	unsigned long msg_stat;
};

struct omap_mbox2_priv {
	struct omap_mbox2_fifo tx_fifo;
	struct omap_mbox2_fifo rx_fifo;
	unsigned long irqenable;
	unsigned long irqstatus;
	u32 newmsg_bit;
	u32 notfull_bit;
};

static struct clk *mbox_ick_handle;

static void omap2_mbox_enable_irq(struct omap_mbox *mbox,
				  omap_mbox_type_t irq);

static inline unsigned int mbox_read_reg(unsigned int reg)
{
	return __raw_readl(mbox_base + reg);
}

static inline void mbox_write_reg(unsigned int val, unsigned int reg)
{
	__raw_writel(val, mbox_base + reg);
}

/* Mailbox H/W preparations */
static int omap2_mbox_startup(struct omap_mbox *mbox)
{
	unsigned int l;

	mbox_ick_handle = clk_get(NULL, "mailboxes_ick");
	if (IS_ERR(mbox_ick_handle)) {
		printk("Could not get mailboxes_ick\n");
		return -ENODEV;
	}
	clk_enable(mbox_ick_handle);

	/* set smart-idle & autoidle */
	l = mbox_read_reg(MAILBOX_SYSCONFIG);
	l |= 0x00000011;
	mbox_write_reg(l, MAILBOX_SYSCONFIG);

	omap2_mbox_enable_irq(mbox, IRQ_RX);

	return 0;
}

static void omap2_mbox_shutdown(struct omap_mbox *mbox)
{
	clk_disable(mbox_ick_handle);
	clk_put(mbox_ick_handle);
}

/* Mailbox FIFO handle functions */
static mbox_msg_t omap2_mbox_fifo_read(struct omap_mbox *mbox)
{
	struct omap_mbox2_fifo *fifo =
		&((struct omap_mbox2_priv *)mbox->priv)->rx_fifo;
	return (mbox_msg_t) mbox_read_reg(fifo->msg);
}

static void omap2_mbox_fifo_write(struct omap_mbox *mbox, mbox_msg_t msg)
{
	struct omap_mbox2_fifo *fifo =
		&((struct omap_mbox2_priv *)mbox->priv)->tx_fifo;
	mbox_write_reg(msg, fifo->msg);
}

static int omap2_mbox_fifo_empty(struct omap_mbox *mbox)
{
	struct omap_mbox2_fifo *fifo =
		&((struct omap_mbox2_priv *)mbox->priv)->rx_fifo;
	return (mbox_read_reg(fifo->msg_stat) == 0);
}

static int omap2_mbox_fifo_full(struct omap_mbox *mbox)
{
	struct omap_mbox2_fifo *fifo =
		&((struct omap_mbox2_priv *)mbox->priv)->tx_fifo;
	return (mbox_read_reg(fifo->fifo_stat));
}

/* Mailbox IRQ handle functions */
static void omap2_mbox_enable_irq(struct omap_mbox *mbox,
		omap_mbox_type_t irq)
{
	struct omap_mbox2_priv *p = (struct omap_mbox2_priv *)mbox->priv;
	u32 l, bit = (irq == IRQ_TX) ? p->notfull_bit : p->newmsg_bit;

	l = mbox_read_reg(p->irqenable);
	l |= bit;
	mbox_write_reg(l, p->irqenable);
}

static void omap2_mbox_disable_irq(struct omap_mbox *mbox,
		omap_mbox_type_t irq)
{
	struct omap_mbox2_priv *p = (struct omap_mbox2_priv *)mbox->priv;
	u32 l, bit = (irq == IRQ_TX) ? p->notfull_bit : p->newmsg_bit;

	l = mbox_read_reg(p->irqenable);
	l &= ~bit;
	mbox_write_reg(l, p->irqenable);
}

static void omap2_mbox_ack_irq(struct omap_mbox *mbox,
		omap_mbox_type_t irq)
{
	struct omap_mbox2_priv *p = (struct omap_mbox2_priv *)mbox->priv;
	u32 bit = (irq == IRQ_TX) ? p->notfull_bit : p->newmsg_bit;

	mbox_write_reg(bit, p->irqstatus);
}

static int omap2_mbox_is_irq(struct omap_mbox *mbox,
		omap_mbox_type_t irq)
{
	struct omap_mbox2_priv *p = (struct omap_mbox2_priv *)mbox->priv;
	u32 bit = (irq == IRQ_TX) ? p->notfull_bit : p->newmsg_bit;
	u32 enable = mbox_read_reg(p->irqenable);
	u32 status = mbox_read_reg(p->irqstatus);

	return (enable & status & bit);
}

static struct omap_mbox_ops omap2_mbox_ops = {
	.type		= OMAP_MBOX_TYPE2,
	.startup	= omap2_mbox_startup,
	.shutdown	= omap2_mbox_shutdown,
	.fifo_read	= omap2_mbox_fifo_read,
	.fifo_write	= omap2_mbox_fifo_write,
	.fifo_empty	= omap2_mbox_fifo_empty,
	.fifo_full	= omap2_mbox_fifo_full,
	.enable_irq	= omap2_mbox_enable_irq,
	.disable_irq	= omap2_mbox_disable_irq,
	.ack_irq	= omap2_mbox_ack_irq,
	.is_irq		= omap2_mbox_is_irq,
};

/*
 * MAILBOX 0: ARM -> DSP,
 * MAILBOX 1: ARM <- DSP.
 * MAILBOX 2: ARM -> IVA,
 * MAILBOX 3: ARM <- IVA.
 */

/* FIXME: the following structs should be filled automatically by the user id */

/* DSP */
static struct omap_mbox2_priv omap2_mbox_dsp_priv = {
	.tx_fifo = {
		.msg		= MAILBOX_MESSAGE_0,
		.fifo_stat	= MAILBOX_FIFOSTATUS_0,
	},
	.rx_fifo = {
		.msg		= MAILBOX_MESSAGE_1,
		.msg_stat	= MAILBOX_MSGSTATUS_1,
	},
	.irqenable	= MAILBOX_IRQENABLE_0,
	.irqstatus	= MAILBOX_IRQSTATUS_0,
	.notfull_bit	= MAILBOX_IRQ_NOTFULL(0),
	.newmsg_bit	= MAILBOX_IRQ_NEWMSG(1),
};

struct omap_mbox mbox_dsp_info = {
	.name	= "dsp",
	.ops	= &omap2_mbox_ops,
	.priv	= &omap2_mbox_dsp_priv,
};
EXPORT_SYMBOL(mbox_dsp_info);

/* IVA */
static struct omap_mbox2_priv omap2_mbox_iva_priv = {
	.tx_fifo = {
		.msg		= MAILBOX_MESSAGE_2,
		.fifo_stat	= MAILBOX_FIFOSTATUS_2,
	},
	.rx_fifo = {
		.msg		= MAILBOX_MESSAGE_3,
		.msg_stat	= MAILBOX_MSGSTATUS_3,
	},
	.irqenable	= MAILBOX_IRQENABLE_3,
	.irqstatus	= MAILBOX_IRQSTATUS_3,
	.notfull_bit	= MAILBOX_IRQ_NOTFULL(2),
	.newmsg_bit	= MAILBOX_IRQ_NEWMSG(3),
};

static struct omap_mbox mbox_iva_info = {
	.name	= "iva",
	.ops	= &omap2_mbox_ops,
	.priv	= &omap2_mbox_iva_priv,
};

static int __init omap2_mbox_probe(struct platform_device *pdev)
{
	struct resource *res;
	int ret = 0;

	if (pdev->num_resources != 3) {
		dev_err(&pdev->dev, "invalid number of resources: %d\n",
			pdev->num_resources);
		return -ENODEV;
	}

	/* MBOX base */
	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
	if (unlikely(!res)) {
		dev_err(&pdev->dev, "invalid mem resource\n");
		return -ENODEV;
	}
	mbox_base = res->start;

	/* DSP IRQ */
	res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
	if (unlikely(!res)) {
		dev_err(&pdev->dev, "invalid irq resource\n");
		return -ENODEV;
	}
	mbox_dsp_info.irq = res->start;

	ret = omap_mbox_register(&mbox_dsp_info);

	/* IVA IRQ */
	res = platform_get_resource(pdev, IORESOURCE_IRQ, 1);
	if (unlikely(!res)) {
		dev_err(&pdev->dev, "invalid irq resource\n");
		return -ENODEV;
	}
	mbox_iva_info.irq = res->start;

	ret = omap_mbox_register(&mbox_iva_info);

	return ret;
}

static int omap2_mbox_remove(struct platform_device *pdev)
{
	omap_mbox_unregister(&mbox_dsp_info);
	return 0;
}

static struct platform_driver omap2_mbox_driver = {
	.probe = omap2_mbox_probe,
	.remove = omap2_mbox_remove,
	.driver = {
		.name = "mailbox",
	},
};

static int __init omap2_mbox_init(void)
{
	return platform_driver_register(&omap2_mbox_driver);
}

static void __exit omap2_mbox_exit(void)
{
	platform_driver_unregister(&omap2_mbox_driver);
}

module_init(omap2_mbox_init);
module_exit(omap2_mbox_exit);

MODULE_LICENSE("GPL");
