Browse Source

mailbox/omap: consolidate OMAP mailbox driver

There is no need for a separate common OMAP mailbox module
now that the OMAP1 mailbox driver has been removed. So,
consolidate the two individual OMAP mailbox modules into a
single driver. This streamlines the driver for converting
to mailbox framework.

The following are the main changes:
- collapse mailbox-omap2.c into omap-mailbox.c
- remove omap_mbox_ops and replace the ops calls with
  the equivalent functionality.
- simplify the sub-mailbox startup/shutdown functionality,
  the one-time operations are moved into probe, and the
  pm_runtime_get_sync and pm_runtime_put_sync can be invoked
  without using a configuration counter.
- move all definitions from private omap_mbox.h into the
  source code, and eliminate this internal header.
- rename some variables that used the omap2_mbox prefix with
  a generic omap_mbox prefix.

Signed-off-by: Suman Anna <s-anna@ti.com>
Signed-off-by: Tony Lindgren <tony@atomide.com>
Suman Anna 11 years ago
parent
commit
5040f53438

+ 0 - 8
drivers/mailbox/Kconfig

@@ -16,17 +16,9 @@ config PL320_MBOX
 	  Management Engine, primarily for cpufreq. Say Y here if you want
 	  Management Engine, primarily for cpufreq. Say Y here if you want
 	  to use the PL320 IPCM support.
 	  to use the PL320 IPCM support.
 
 
-config OMAP_MBOX
-	tristate
-	help
-	  This option is selected by any OMAP architecture specific mailbox
-	  driver such as CONFIG_OMAP2PLUS_MBOX. This enables the common OMAP
-	  mailbox framework code.
-
 config OMAP2PLUS_MBOX
 config OMAP2PLUS_MBOX
 	tristate "OMAP2+ Mailbox framework support"
 	tristate "OMAP2+ Mailbox framework support"
 	depends on ARCH_OMAP2PLUS
 	depends on ARCH_OMAP2PLUS
-	select OMAP_MBOX
 	help
 	help
 	  Mailbox implementation for OMAP family chips with hardware for
 	  Mailbox implementation for OMAP family chips with hardware for
 	  interprocessor communication involving DSP, IVA1.0 and IVA2 in
 	  interprocessor communication involving DSP, IVA1.0 and IVA2 in

+ 1 - 3
drivers/mailbox/Makefile

@@ -1,5 +1,3 @@
 obj-$(CONFIG_PL320_MBOX)	+= pl320-ipc.o
 obj-$(CONFIG_PL320_MBOX)	+= pl320-ipc.o
 
 
-obj-$(CONFIG_OMAP_MBOX)		+= omap-mailbox.o
-obj-$(CONFIG_OMAP2PLUS_MBOX)	+= mailbox_omap2.o
-mailbox_omap2-objs		:= mailbox-omap2.o
+obj-$(CONFIG_OMAP2PLUS_MBOX)	+= omap-mailbox.o

+ 0 - 333
drivers/mailbox/mailbox-omap2.c

@@ -1,333 +0,0 @@
-/*
- * Mailbox reservation modules for OMAP2/3
- *
- * Copyright (C) 2006-2009 Nokia Corporation
- * Written by: Hiroshi DOYU <Hiroshi.DOYU@nokia.com>
- *        and  Paul Mundt
- *
- * 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/module.h>
-#include <linux/slab.h>
-#include <linux/clk.h>
-#include <linux/err.h>
-#include <linux/platform_device.h>
-#include <linux/io.h>
-#include <linux/pm_runtime.h>
-#include <linux/platform_data/mailbox-omap.h>
-
-#include "omap-mbox.h"
-
-#define MAILBOX_REVISION		0x000
-#define MAILBOX_MESSAGE(m)		(0x040 + 4 * (m))
-#define MAILBOX_FIFOSTATUS(m)		(0x080 + 4 * (m))
-#define MAILBOX_MSGSTATUS(m)		(0x0c0 + 4 * (m))
-
-#define OMAP2_MAILBOX_IRQSTATUS(u)	(0x100 + 8 * (u))
-#define OMAP2_MAILBOX_IRQENABLE(u)	(0x104 + 8 * (u))
-
-#define OMAP4_MAILBOX_IRQSTATUS(u)	(0x104 + 0x10 * (u))
-#define OMAP4_MAILBOX_IRQENABLE(u)	(0x108 + 0x10 * (u))
-#define OMAP4_MAILBOX_IRQENABLE_CLR(u)	(0x10c + 0x10 * (u))
-
-#define MAILBOX_IRQSTATUS(type, u)	(type ? OMAP4_MAILBOX_IRQSTATUS(u) : \
-						OMAP2_MAILBOX_IRQSTATUS(u))
-#define MAILBOX_IRQENABLE(type, u)	(type ? OMAP4_MAILBOX_IRQENABLE(u) : \
-						OMAP2_MAILBOX_IRQENABLE(u))
-#define MAILBOX_IRQDISABLE(type, u)	(type ? OMAP4_MAILBOX_IRQENABLE_CLR(u) \
-						: OMAP2_MAILBOX_IRQENABLE(u))
-
-#define MAILBOX_IRQ_NEWMSG(m)		(1 << (2 * (m)))
-#define MAILBOX_IRQ_NOTFULL(m)		(1 << (2 * (m) + 1))
-
-#define MBOX_REG_SIZE			0x120
-
-#define OMAP4_MBOX_REG_SIZE		0x130
-
-#define MBOX_NR_REGS			(MBOX_REG_SIZE / sizeof(u32))
-#define OMAP4_MBOX_NR_REGS		(OMAP4_MBOX_REG_SIZE / sizeof(u32))
-
-static void __iomem *mbox_base;
-
-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;
-	u32 ctx[OMAP4_MBOX_NR_REGS];
-	unsigned long irqdisable;
-	u32 intr_type;
-};
-
-static inline unsigned int mbox_read_reg(size_t ofs)
-{
-	return __raw_readl(mbox_base + ofs);
-}
-
-static inline void mbox_write_reg(u32 val, size_t ofs)
-{
-	__raw_writel(val, mbox_base + ofs);
-}
-
-/* Mailbox H/W preparations */
-static int omap2_mbox_startup(struct omap_mbox *mbox)
-{
-	u32 l;
-
-	pm_runtime_enable(mbox->dev->parent);
-	pm_runtime_get_sync(mbox->dev->parent);
-
-	l = mbox_read_reg(MAILBOX_REVISION);
-	pr_debug("omap mailbox rev %d.%d\n", (l & 0xf0) >> 4, (l & 0x0f));
-
-	return 0;
-}
-
-static void omap2_mbox_shutdown(struct omap_mbox *mbox)
-{
-	pm_runtime_put_sync(mbox->dev->parent);
-	pm_runtime_disable(mbox->dev->parent);
-}
-
-/* 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_irq_t irq)
-{
-	struct omap_mbox2_priv *p = 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_irq_t irq)
-{
-	struct omap_mbox2_priv *p = mbox->priv;
-	u32 bit = (irq == IRQ_TX) ? p->notfull_bit : p->newmsg_bit;
-
-	/*
-	 * Read and update the interrupt configuration register for pre-OMAP4.
-	 * OMAP4 and later SoCs have a dedicated interrupt disabling register.
-	 */
-	if (!p->intr_type)
-		bit = mbox_read_reg(p->irqdisable) & ~bit;
-
-	mbox_write_reg(bit, p->irqdisable);
-}
-
-static void omap2_mbox_ack_irq(struct omap_mbox *mbox, omap_mbox_irq_t irq)
-{
-	struct omap_mbox2_priv *p = mbox->priv;
-	u32 bit = (irq == IRQ_TX) ? p->notfull_bit : p->newmsg_bit;
-
-	mbox_write_reg(bit, p->irqstatus);
-
-	/* Flush posted write for irq status to avoid spurious interrupts */
-	mbox_read_reg(p->irqstatus);
-}
-
-static int omap2_mbox_is_irq(struct omap_mbox *mbox, omap_mbox_irq_t irq)
-{
-	struct omap_mbox2_priv *p = 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 (int)(enable & status & bit);
-}
-
-static void omap2_mbox_save_ctx(struct omap_mbox *mbox)
-{
-	int i;
-	struct omap_mbox2_priv *p = mbox->priv;
-	int nr_regs;
-
-	if (p->intr_type)
-		nr_regs = OMAP4_MBOX_NR_REGS;
-	else
-		nr_regs = MBOX_NR_REGS;
-	for (i = 0; i < nr_regs; i++) {
-		p->ctx[i] = mbox_read_reg(i * sizeof(u32));
-
-		dev_dbg(mbox->dev, "%s: [%02x] %08x\n", __func__,
-			i, p->ctx[i]);
-	}
-}
-
-static void omap2_mbox_restore_ctx(struct omap_mbox *mbox)
-{
-	int i;
-	struct omap_mbox2_priv *p = mbox->priv;
-	int nr_regs;
-
-	if (p->intr_type)
-		nr_regs = OMAP4_MBOX_NR_REGS;
-	else
-		nr_regs = MBOX_NR_REGS;
-	for (i = 0; i < nr_regs; i++) {
-		mbox_write_reg(p->ctx[i], i * sizeof(u32));
-
-		dev_dbg(mbox->dev, "%s: [%02x] %08x\n", __func__,
-			i, p->ctx[i]);
-	}
-}
-
-static struct omap_mbox_ops omap2_mbox_ops = {
-	.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,
-	.save_ctx	= omap2_mbox_save_ctx,
-	.restore_ctx	= omap2_mbox_restore_ctx,
-};
-
-static int omap2_mbox_probe(struct platform_device *pdev)
-{
-	struct resource *mem;
-	int ret;
-	struct omap_mbox **list, *mbox, *mboxblk;
-	struct omap_mbox2_priv *priv, *privblk;
-	struct omap_mbox_pdata *pdata = pdev->dev.platform_data;
-	struct omap_mbox_dev_info *info;
-	u32 intr_type;
-	int i;
-
-	if (!pdata || !pdata->info_cnt || !pdata->info) {
-		pr_err("%s: platform not supported\n", __func__);
-		return -ENODEV;
-	}
-
-	/* allocate one extra for marking end of list */
-	list = devm_kzalloc(&pdev->dev, (pdata->info_cnt + 1) * sizeof(*list),
-			    GFP_KERNEL);
-	if (!list)
-		return -ENOMEM;
-
-	mboxblk = devm_kzalloc(&pdev->dev, pdata->info_cnt * sizeof(*mbox),
-			       GFP_KERNEL);
-	if (!mboxblk)
-		return -ENOMEM;
-
-	privblk = devm_kzalloc(&pdev->dev, pdata->info_cnt * sizeof(*priv),
-			       GFP_KERNEL);
-	if (!privblk)
-		return -ENOMEM;
-
-	info = pdata->info;
-	intr_type = pdata->intr_type;
-	mbox = mboxblk;
-	priv = privblk;
-	for (i = 0; i < pdata->info_cnt; i++, info++, priv++) {
-		priv->tx_fifo.msg = MAILBOX_MESSAGE(info->tx_id);
-		priv->tx_fifo.fifo_stat = MAILBOX_FIFOSTATUS(info->tx_id);
-		priv->rx_fifo.msg =  MAILBOX_MESSAGE(info->rx_id);
-		priv->rx_fifo.msg_stat =  MAILBOX_MSGSTATUS(info->rx_id);
-		priv->notfull_bit = MAILBOX_IRQ_NOTFULL(info->tx_id);
-		priv->newmsg_bit = MAILBOX_IRQ_NEWMSG(info->rx_id);
-		priv->irqenable = MAILBOX_IRQENABLE(intr_type, info->usr_id);
-		priv->irqstatus = MAILBOX_IRQSTATUS(intr_type, info->usr_id);
-		priv->irqdisable = MAILBOX_IRQDISABLE(intr_type, info->usr_id);
-		priv->intr_type = intr_type;
-
-		mbox->priv = priv;
-		mbox->name = info->name;
-		mbox->ops = &omap2_mbox_ops;
-		mbox->irq = platform_get_irq(pdev, info->irq_id);
-		if (mbox->irq < 0)
-			return mbox->irq;
-		list[i] = mbox++;
-	}
-
-	mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-	mbox_base = devm_ioremap_resource(&pdev->dev, mem);
-	if (IS_ERR(mbox_base))
-		return PTR_ERR(mbox_base);
-
-	ret = omap_mbox_register(&pdev->dev, list);
-	if (ret)
-		return ret;
-
-	platform_set_drvdata(pdev, list);
-
-	return 0;
-}
-
-static int omap2_mbox_remove(struct platform_device *pdev)
-{
-	omap_mbox_unregister();
-
-	return 0;
-}
-
-static struct platform_driver omap2_mbox_driver = {
-	.probe	= omap2_mbox_probe,
-	.remove	= omap2_mbox_remove,
-	.driver	= {
-		.name = "omap-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 v2");
-MODULE_DESCRIPTION("omap mailbox: omap2/3/4 architecture specific functions");
-MODULE_AUTHOR("Hiroshi DOYU <Hiroshi.DOYU@nokia.com>");
-MODULE_AUTHOR("Paul Mundt");
-MODULE_ALIAS("platform:omap2-mailbox");

+ 282 - 49
drivers/mailbox/omap-mailbox.c

@@ -2,8 +2,10 @@
  * OMAP mailbox driver
  * OMAP mailbox driver
  *
  *
  * Copyright (C) 2006-2009 Nokia Corporation. All rights reserved.
  * Copyright (C) 2006-2009 Nokia Corporation. All rights reserved.
+ * Copyright (C) 2013-2014 Texas Instruments Inc.
  *
  *
  * Contact: Hiroshi DOYU <Hiroshi.DOYU@nokia.com>
  * Contact: Hiroshi DOYU <Hiroshi.DOYU@nokia.com>
+ *          Suman Anna <s-anna@ti.com>
  *
  *
  * This program is free software; you can redistribute it and/or
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU General Public License
  * modify it under the terms of the GNU General Public License
@@ -29,45 +31,145 @@
 #include <linux/err.h>
 #include <linux/err.h>
 #include <linux/notifier.h>
 #include <linux/notifier.h>
 #include <linux/module.h>
 #include <linux/module.h>
-
-#include "omap-mbox.h"
-
+#include <linux/platform_device.h>
+#include <linux/pm_runtime.h>
+#include <linux/platform_data/mailbox-omap.h>
+#include <linux/omap-mailbox.h>
+
+#define MAILBOX_REVISION		0x000
+#define MAILBOX_MESSAGE(m)		(0x040 + 4 * (m))
+#define MAILBOX_FIFOSTATUS(m)		(0x080 + 4 * (m))
+#define MAILBOX_MSGSTATUS(m)		(0x0c0 + 4 * (m))
+
+#define OMAP2_MAILBOX_IRQSTATUS(u)	(0x100 + 8 * (u))
+#define OMAP2_MAILBOX_IRQENABLE(u)	(0x104 + 8 * (u))
+
+#define OMAP4_MAILBOX_IRQSTATUS(u)	(0x104 + 0x10 * (u))
+#define OMAP4_MAILBOX_IRQENABLE(u)	(0x108 + 0x10 * (u))
+#define OMAP4_MAILBOX_IRQENABLE_CLR(u)	(0x10c + 0x10 * (u))
+
+#define MAILBOX_IRQSTATUS(type, u)	(type ? OMAP4_MAILBOX_IRQSTATUS(u) : \
+						OMAP2_MAILBOX_IRQSTATUS(u))
+#define MAILBOX_IRQENABLE(type, u)	(type ? OMAP4_MAILBOX_IRQENABLE(u) : \
+						OMAP2_MAILBOX_IRQENABLE(u))
+#define MAILBOX_IRQDISABLE(type, u)	(type ? OMAP4_MAILBOX_IRQENABLE_CLR(u) \
+						: OMAP2_MAILBOX_IRQENABLE(u))
+
+#define MAILBOX_IRQ_NEWMSG(m)		(1 << (2 * (m)))
+#define MAILBOX_IRQ_NOTFULL(m)		(1 << (2 * (m) + 1))
+
+#define MBOX_REG_SIZE			0x120
+
+#define OMAP4_MBOX_REG_SIZE		0x130
+
+#define MBOX_NR_REGS			(MBOX_REG_SIZE / sizeof(u32))
+#define OMAP4_MBOX_NR_REGS		(OMAP4_MBOX_REG_SIZE / sizeof(u32))
+
+struct omap_mbox_fifo {
+	unsigned long msg;
+	unsigned long fifo_stat;
+	unsigned long msg_stat;
+};
+
+struct omap_mbox_priv {
+	struct omap_mbox_fifo tx_fifo;
+	struct omap_mbox_fifo rx_fifo;
+	unsigned long irqenable;
+	unsigned long irqstatus;
+	u32 newmsg_bit;
+	u32 notfull_bit;
+	u32 ctx[OMAP4_MBOX_NR_REGS];
+	unsigned long irqdisable;
+	u32 intr_type;
+};
+
+struct omap_mbox_queue {
+	spinlock_t		lock;
+	struct kfifo		fifo;
+	struct work_struct	work;
+	struct tasklet_struct	tasklet;
+	struct omap_mbox	*mbox;
+	bool full;
+};
+
+struct omap_mbox {
+	const char		*name;
+	int			irq;
+	struct omap_mbox_queue	*txq, *rxq;
+	struct device		*dev;
+	void			*priv;
+	int			use_count;
+	struct blocking_notifier_head	notifier;
+};
+
+static void __iomem *mbox_base;
 static struct omap_mbox **mboxes;
 static struct omap_mbox **mboxes;
 
 
-static int mbox_configured;
 static DEFINE_MUTEX(mbox_configured_lock);
 static DEFINE_MUTEX(mbox_configured_lock);
 
 
 static unsigned int mbox_kfifo_size = CONFIG_OMAP_MBOX_KFIFO_SIZE;
 static unsigned int mbox_kfifo_size = CONFIG_OMAP_MBOX_KFIFO_SIZE;
 module_param(mbox_kfifo_size, uint, S_IRUGO);
 module_param(mbox_kfifo_size, uint, S_IRUGO);
 MODULE_PARM_DESC(mbox_kfifo_size, "Size of omap's mailbox kfifo (bytes)");
 MODULE_PARM_DESC(mbox_kfifo_size, "Size of omap's mailbox kfifo (bytes)");
 
 
+static inline unsigned int mbox_read_reg(size_t ofs)
+{
+	return __raw_readl(mbox_base + ofs);
+}
+
+static inline void mbox_write_reg(u32 val, size_t ofs)
+{
+	__raw_writel(val, mbox_base + ofs);
+}
+
 /* Mailbox FIFO handle functions */
 /* Mailbox FIFO handle functions */
-static inline mbox_msg_t mbox_fifo_read(struct omap_mbox *mbox)
+static mbox_msg_t mbox_fifo_read(struct omap_mbox *mbox)
 {
 {
-	return mbox->ops->fifo_read(mbox);
+	struct omap_mbox_fifo *fifo =
+		&((struct omap_mbox_priv *)mbox->priv)->rx_fifo;
+	return (mbox_msg_t) mbox_read_reg(fifo->msg);
 }
 }
-static inline void mbox_fifo_write(struct omap_mbox *mbox, mbox_msg_t msg)
+
+static void mbox_fifo_write(struct omap_mbox *mbox, mbox_msg_t msg)
 {
 {
-	mbox->ops->fifo_write(mbox, msg);
+	struct omap_mbox_fifo *fifo =
+		&((struct omap_mbox_priv *)mbox->priv)->tx_fifo;
+	mbox_write_reg(msg, fifo->msg);
 }
 }
-static inline int mbox_fifo_empty(struct omap_mbox *mbox)
+
+static int mbox_fifo_empty(struct omap_mbox *mbox)
 {
 {
-	return mbox->ops->fifo_empty(mbox);
+	struct omap_mbox_fifo *fifo =
+		&((struct omap_mbox_priv *)mbox->priv)->rx_fifo;
+	return (mbox_read_reg(fifo->msg_stat) == 0);
 }
 }
-static inline int mbox_fifo_full(struct omap_mbox *mbox)
+
+static int mbox_fifo_full(struct omap_mbox *mbox)
 {
 {
-	return mbox->ops->fifo_full(mbox);
+	struct omap_mbox_fifo *fifo =
+		&((struct omap_mbox_priv *)mbox->priv)->tx_fifo;
+	return mbox_read_reg(fifo->fifo_stat);
 }
 }
 
 
 /* Mailbox IRQ handle functions */
 /* Mailbox IRQ handle functions */
-static inline void ack_mbox_irq(struct omap_mbox *mbox, omap_mbox_irq_t irq)
+static void ack_mbox_irq(struct omap_mbox *mbox, omap_mbox_irq_t irq)
 {
 {
-	if (mbox->ops->ack_irq)
-		mbox->ops->ack_irq(mbox, irq);
+	struct omap_mbox_priv *p = mbox->priv;
+	u32 bit = (irq == IRQ_TX) ? p->notfull_bit : p->newmsg_bit;
+
+	mbox_write_reg(bit, p->irqstatus);
+
+	/* Flush posted write for irq status to avoid spurious interrupts */
+	mbox_read_reg(p->irqstatus);
 }
 }
-static inline int is_mbox_irq(struct omap_mbox *mbox, omap_mbox_irq_t irq)
+
+static int is_mbox_irq(struct omap_mbox *mbox, omap_mbox_irq_t irq)
 {
 {
-	return mbox->ops->is_irq(mbox, irq);
+	struct omap_mbox_priv *p = 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 (int)(enable & status & bit);
 }
 }
 
 
 /*
 /*
@@ -103,35 +205,66 @@ EXPORT_SYMBOL(omap_mbox_msg_send);
 
 
 void omap_mbox_save_ctx(struct omap_mbox *mbox)
 void omap_mbox_save_ctx(struct omap_mbox *mbox)
 {
 {
-	if (!mbox->ops->save_ctx) {
-		dev_err(mbox->dev, "%s:\tno save\n", __func__);
-		return;
+	int i;
+	struct omap_mbox_priv *p = mbox->priv;
+	int nr_regs;
+
+	if (p->intr_type)
+		nr_regs = OMAP4_MBOX_NR_REGS;
+	else
+		nr_regs = MBOX_NR_REGS;
+	for (i = 0; i < nr_regs; i++) {
+		p->ctx[i] = mbox_read_reg(i * sizeof(u32));
+
+		dev_dbg(mbox->dev, "%s: [%02x] %08x\n", __func__,
+			i, p->ctx[i]);
 	}
 	}
-
-	mbox->ops->save_ctx(mbox);
 }
 }
 EXPORT_SYMBOL(omap_mbox_save_ctx);
 EXPORT_SYMBOL(omap_mbox_save_ctx);
 
 
 void omap_mbox_restore_ctx(struct omap_mbox *mbox)
 void omap_mbox_restore_ctx(struct omap_mbox *mbox)
 {
 {
-	if (!mbox->ops->restore_ctx) {
-		dev_err(mbox->dev, "%s:\tno restore\n", __func__);
-		return;
+	int i;
+	struct omap_mbox_priv *p = mbox->priv;
+	int nr_regs;
+
+	if (p->intr_type)
+		nr_regs = OMAP4_MBOX_NR_REGS;
+	else
+		nr_regs = MBOX_NR_REGS;
+	for (i = 0; i < nr_regs; i++) {
+		mbox_write_reg(p->ctx[i], i * sizeof(u32));
+
+		dev_dbg(mbox->dev, "%s: [%02x] %08x\n", __func__,
+			i, p->ctx[i]);
 	}
 	}
-
-	mbox->ops->restore_ctx(mbox);
 }
 }
 EXPORT_SYMBOL(omap_mbox_restore_ctx);
 EXPORT_SYMBOL(omap_mbox_restore_ctx);
 
 
 void omap_mbox_enable_irq(struct omap_mbox *mbox, omap_mbox_irq_t irq)
 void omap_mbox_enable_irq(struct omap_mbox *mbox, omap_mbox_irq_t irq)
 {
 {
-	mbox->ops->enable_irq(mbox, irq);
+	struct omap_mbox_priv *p = 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);
 }
 }
 EXPORT_SYMBOL(omap_mbox_enable_irq);
 EXPORT_SYMBOL(omap_mbox_enable_irq);
 
 
 void omap_mbox_disable_irq(struct omap_mbox *mbox, omap_mbox_irq_t irq)
 void omap_mbox_disable_irq(struct omap_mbox *mbox, omap_mbox_irq_t irq)
 {
 {
-	mbox->ops->disable_irq(mbox, irq);
+	struct omap_mbox_priv *p = mbox->priv;
+	u32 bit = (irq == IRQ_TX) ? p->notfull_bit : p->newmsg_bit;
+
+	/*
+	 * Read and update the interrupt configuration register for pre-OMAP4.
+	 * OMAP4 and later SoCs have a dedicated interrupt disabling register.
+	 */
+	if (!p->intr_type)
+		bit = mbox_read_reg(p->irqdisable) & ~bit;
+
+	mbox_write_reg(bit, p->irqdisable);
 }
 }
 EXPORT_SYMBOL(omap_mbox_disable_irq);
 EXPORT_SYMBOL(omap_mbox_disable_irq);
 
 
@@ -267,14 +400,9 @@ static int omap_mbox_startup(struct omap_mbox *mbox)
 	struct omap_mbox_queue *mq;
 	struct omap_mbox_queue *mq;
 
 
 	mutex_lock(&mbox_configured_lock);
 	mutex_lock(&mbox_configured_lock);
-	if (!mbox_configured++) {
-		if (likely(mbox->ops->startup)) {
-			ret = mbox->ops->startup(mbox);
-			if (unlikely(ret))
-				goto fail_startup;
-		} else
-			goto fail_startup;
-	}
+	ret = pm_runtime_get_sync(mbox->dev->parent);
+	if (unlikely(ret < 0))
+		goto fail_startup;
 
 
 	if (!mbox->use_count++) {
 	if (!mbox->use_count++) {
 		mq = mbox_queue_alloc(mbox, NULL, mbox_tx_tasklet);
 		mq = mbox_queue_alloc(mbox, NULL, mbox_tx_tasklet);
@@ -309,11 +437,9 @@ fail_request_irq:
 fail_alloc_rxq:
 fail_alloc_rxq:
 	mbox_queue_free(mbox->txq);
 	mbox_queue_free(mbox->txq);
 fail_alloc_txq:
 fail_alloc_txq:
-	if (mbox->ops->shutdown)
-		mbox->ops->shutdown(mbox);
+	pm_runtime_put_sync(mbox->dev->parent);
 	mbox->use_count--;
 	mbox->use_count--;
 fail_startup:
 fail_startup:
-	mbox_configured--;
 	mutex_unlock(&mbox_configured_lock);
 	mutex_unlock(&mbox_configured_lock);
 	return ret;
 	return ret;
 }
 }
@@ -331,10 +457,7 @@ static void omap_mbox_fini(struct omap_mbox *mbox)
 		mbox_queue_free(mbox->rxq);
 		mbox_queue_free(mbox->rxq);
 	}
 	}
 
 
-	if (likely(mbox->ops->shutdown)) {
-		if (!--mbox_configured)
-			mbox->ops->shutdown(mbox);
-	}
+	pm_runtime_put_sync(mbox->dev->parent);
 
 
 	mutex_unlock(&mbox_configured_lock);
 	mutex_unlock(&mbox_configured_lock);
 }
 }
@@ -379,7 +502,7 @@ EXPORT_SYMBOL(omap_mbox_put);
 
 
 static struct class omap_mbox_class = { .name = "mbox", };
 static struct class omap_mbox_class = { .name = "mbox", };
 
 
-int omap_mbox_register(struct device *parent, struct omap_mbox **list)
+static int omap_mbox_register(struct device *parent, struct omap_mbox **list)
 {
 {
 	int ret;
 	int ret;
 	int i;
 	int i;
@@ -406,9 +529,8 @@ err_out:
 		device_unregister(mboxes[i]->dev);
 		device_unregister(mboxes[i]->dev);
 	return ret;
 	return ret;
 }
 }
-EXPORT_SYMBOL(omap_mbox_register);
 
 
-int omap_mbox_unregister(void)
+static int omap_mbox_unregister(void)
 {
 {
 	int i;
 	int i;
 
 
@@ -420,7 +542,117 @@ int omap_mbox_unregister(void)
 	mboxes = NULL;
 	mboxes = NULL;
 	return 0;
 	return 0;
 }
 }
-EXPORT_SYMBOL(omap_mbox_unregister);
+
+static int omap_mbox_probe(struct platform_device *pdev)
+{
+	struct resource *mem;
+	int ret;
+	struct omap_mbox **list, *mbox, *mboxblk;
+	struct omap_mbox_priv *priv, *privblk;
+	struct omap_mbox_pdata *pdata = pdev->dev.platform_data;
+	struct omap_mbox_dev_info *info;
+	u32 intr_type;
+	u32 l;
+	int i;
+
+	if (!pdata || !pdata->info_cnt || !pdata->info) {
+		pr_err("%s: platform not supported\n", __func__);
+		return -ENODEV;
+	}
+
+	/* allocate one extra for marking end of list */
+	list = devm_kzalloc(&pdev->dev, (pdata->info_cnt + 1) * sizeof(*list),
+			    GFP_KERNEL);
+	if (!list)
+		return -ENOMEM;
+
+	mboxblk = devm_kzalloc(&pdev->dev, pdata->info_cnt * sizeof(*mbox),
+			       GFP_KERNEL);
+	if (!mboxblk)
+		return -ENOMEM;
+
+	privblk = devm_kzalloc(&pdev->dev, pdata->info_cnt * sizeof(*priv),
+			       GFP_KERNEL);
+	if (!privblk)
+		return -ENOMEM;
+
+	info = pdata->info;
+	intr_type = pdata->intr_type;
+	mbox = mboxblk;
+	priv = privblk;
+	for (i = 0; i < pdata->info_cnt; i++, info++, priv++) {
+		priv->tx_fifo.msg = MAILBOX_MESSAGE(info->tx_id);
+		priv->tx_fifo.fifo_stat = MAILBOX_FIFOSTATUS(info->tx_id);
+		priv->rx_fifo.msg =  MAILBOX_MESSAGE(info->rx_id);
+		priv->rx_fifo.msg_stat =  MAILBOX_MSGSTATUS(info->rx_id);
+		priv->notfull_bit = MAILBOX_IRQ_NOTFULL(info->tx_id);
+		priv->newmsg_bit = MAILBOX_IRQ_NEWMSG(info->rx_id);
+		priv->irqenable = MAILBOX_IRQENABLE(intr_type, info->usr_id);
+		priv->irqstatus = MAILBOX_IRQSTATUS(intr_type, info->usr_id);
+		priv->irqdisable = MAILBOX_IRQDISABLE(intr_type, info->usr_id);
+		priv->intr_type = intr_type;
+
+		mbox->priv = priv;
+		mbox->name = info->name;
+		mbox->irq = platform_get_irq(pdev, info->irq_id);
+		if (mbox->irq < 0)
+			return mbox->irq;
+		list[i] = mbox++;
+	}
+
+	mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	mbox_base = devm_ioremap_resource(&pdev->dev, mem);
+	if (IS_ERR(mbox_base))
+		return PTR_ERR(mbox_base);
+
+	ret = omap_mbox_register(&pdev->dev, list);
+	if (ret)
+		return ret;
+
+	platform_set_drvdata(pdev, list);
+	pm_runtime_enable(&pdev->dev);
+
+	ret = pm_runtime_get_sync(&pdev->dev);
+	if (ret < 0) {
+		pm_runtime_put_noidle(&pdev->dev);
+		goto unregister;
+	}
+
+	/*
+	 * just print the raw revision register, the format is not
+	 * uniform across all SoCs
+	 */
+	l = mbox_read_reg(MAILBOX_REVISION);
+	dev_info(&pdev->dev, "omap mailbox rev 0x%x\n", l);
+
+	ret = pm_runtime_put_sync(&pdev->dev);
+	if (ret < 0)
+		goto unregister;
+
+	return 0;
+
+unregister:
+	pm_runtime_disable(&pdev->dev);
+	omap_mbox_unregister();
+	return ret;
+}
+
+static int omap_mbox_remove(struct platform_device *pdev)
+{
+	pm_runtime_disable(&pdev->dev);
+	omap_mbox_unregister();
+
+	return 0;
+}
+
+static struct platform_driver omap_mbox_driver = {
+	.probe	= omap_mbox_probe,
+	.remove	= omap_mbox_remove,
+	.driver	= {
+		.name = "omap-mailbox",
+		.owner = THIS_MODULE,
+	},
+};
 
 
 static int __init omap_mbox_init(void)
 static int __init omap_mbox_init(void)
 {
 {
@@ -435,12 +667,13 @@ static int __init omap_mbox_init(void)
 	mbox_kfifo_size = max_t(unsigned int, mbox_kfifo_size,
 	mbox_kfifo_size = max_t(unsigned int, mbox_kfifo_size,
 							sizeof(mbox_msg_t));
 							sizeof(mbox_msg_t));
 
 
-	return 0;
+	return platform_driver_register(&omap_mbox_driver);
 }
 }
 subsys_initcall(omap_mbox_init);
 subsys_initcall(omap_mbox_init);
 
 
 static void __exit omap_mbox_exit(void)
 static void __exit omap_mbox_exit(void)
 {
 {
+	platform_driver_unregister(&omap_mbox_driver);
 	class_unregister(&omap_mbox_class);
 	class_unregister(&omap_mbox_class);
 }
 }
 module_exit(omap_mbox_exit);
 module_exit(omap_mbox_exit);

+ 0 - 62
drivers/mailbox/omap-mbox.h

@@ -1,62 +0,0 @@
-/*
- * omap-mbox.h: OMAP mailbox internal definitions
- *
- * 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.
- */
-
-#ifndef OMAP_MBOX_H
-#define OMAP_MBOX_H
-
-#include <linux/device.h>
-#include <linux/interrupt.h>
-#include <linux/kfifo.h>
-#include <linux/spinlock.h>
-#include <linux/workqueue.h>
-#include <linux/omap-mailbox.h>
-
-struct omap_mbox_ops {
-	int		(*startup)(struct omap_mbox *mbox);
-	void		(*shutdown)(struct omap_mbox *mbox);
-	/* fifo */
-	mbox_msg_t	(*fifo_read)(struct omap_mbox *mbox);
-	void		(*fifo_write)(struct omap_mbox *mbox, mbox_msg_t msg);
-	int		(*fifo_empty)(struct omap_mbox *mbox);
-	int		(*fifo_full)(struct omap_mbox *mbox);
-	/* irq */
-	void		(*enable_irq)(struct omap_mbox *mbox,
-						omap_mbox_irq_t irq);
-	void		(*disable_irq)(struct omap_mbox *mbox,
-						omap_mbox_irq_t irq);
-	void		(*ack_irq)(struct omap_mbox *mbox, omap_mbox_irq_t irq);
-	int		(*is_irq)(struct omap_mbox *mbox, omap_mbox_irq_t irq);
-	/* ctx */
-	void		(*save_ctx)(struct omap_mbox *mbox);
-	void		(*restore_ctx)(struct omap_mbox *mbox);
-};
-
-struct omap_mbox_queue {
-	spinlock_t		lock;
-	struct kfifo		fifo;
-	struct work_struct	work;
-	struct tasklet_struct	tasklet;
-	struct omap_mbox	*mbox;
-	bool full;
-};
-
-struct omap_mbox {
-	const char		*name;
-	int			irq;
-	struct omap_mbox_queue	*txq, *rxq;
-	struct omap_mbox_ops	*ops;
-	struct device		*dev;
-	void			*priv;
-	int			use_count;
-	struct blocking_notifier_head	notifier;
-};
-
-int omap_mbox_register(struct device *parent, struct omap_mbox **);
-int omap_mbox_unregister(void);
-
-#endif /* OMAP_MBOX_H */