Browse Source

Merge tag 'omap-for-v3.17/mailbox-cleanup' of git://git.kernel.org/pub/scm/linux/kernel/git/tmlind/linux-omap into next/drivers

Merge "late omap mailbox clean-up, driver parts" from Tony Lindgren:

Driver specific omap mailbox cleanup. Mostly to remove
broken legacy code for omap1 and move things towards
device tree.

These patches were posted a while back, but I did not
realize I was supposed to merge the driver related
parts too. So apologies for a late pull request on
these changes.

* tag 'omap-for-v3.17/mailbox-cleanup' of git://git.kernel.org/pub/scm/linux/kernel/git/tmlind/linux-omap:
  mailbox/omap: add a parent structure for every IP instance
  mailbox/omap: remove the private mailbox structure
  mailbox/omap: consolidate OMAP mailbox driver
  mailbox/omap: simplify the fifo assignment by using macros
  mailbox/omap: remove omap_mbox_type_t from mailbox ops
  mailbox/omap: remove OMAP1 mailbox driver
  mailbox/omap: use devm_* interfaces

Signed-off-by: Arnd Bergmann <arnd@arndb.de>
Arnd Bergmann 11 years ago
parent
commit
f64a3c895b

+ 0 - 2
arch/arm/configs/omap1_defconfig

@@ -26,8 +26,6 @@ CONFIG_ARCH_OMAP=y
 CONFIG_ARCH_OMAP1=y
 CONFIG_ARCH_OMAP1=y
 CONFIG_OMAP_RESET_CLOCKS=y
 CONFIG_OMAP_RESET_CLOCKS=y
 # CONFIG_OMAP_MUX is not set
 # CONFIG_OMAP_MUX is not set
-CONFIG_MAILBOX=y
-CONFIG_OMAP1_MBOX=y
 CONFIG_OMAP_32K_TIMER=y
 CONFIG_OMAP_32K_TIMER=y
 CONFIG_OMAP_DM_TIMER=y
 CONFIG_OMAP_DM_TIMER=y
 CONFIG_ARCH_OMAP730=y
 CONFIG_ARCH_OMAP730=y

+ 1 - 18
drivers/mailbox/Kconfig

@@ -16,26 +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_OMAP1_MBOX or CONFIG_OMAP2PLUS_MBOX. This
-	  enables the common OMAP mailbox framework code.
-
-config OMAP1_MBOX
-	tristate "OMAP1 Mailbox framework support"
-	depends on ARCH_OMAP1
-	select OMAP_MBOX
-	help
-	  Mailbox implementation for OMAP chips with hardware for
-	  interprocessor communication involving DSP in OMAP1. Say Y here
-	  if you want to use OMAP1 Mailbox framework support.
-
 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
@@ -44,7 +27,7 @@ config OMAP2PLUS_MBOX
 
 
 config OMAP_MBOX_KFIFO_SIZE
 config OMAP_MBOX_KFIFO_SIZE
 	int "Mailbox kfifo default buffer size (bytes)"
 	int "Mailbox kfifo default buffer size (bytes)"
-	depends on OMAP2PLUS_MBOX || OMAP1_MBOX
+	depends on OMAP2PLUS_MBOX
 	default 256
 	default 256
 	help
 	help
 	  Specify the default size of mailbox's kfifo buffers (bytes).
 	  Specify the default size of mailbox's kfifo buffers (bytes).

+ 1 - 5
drivers/mailbox/Makefile

@@ -1,7 +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_OMAP1_MBOX)	+= mailbox_omap1.o
-mailbox_omap1-objs		:= mailbox-omap1.o
-obj-$(CONFIG_OMAP2PLUS_MBOX)	+= mailbox_omap2.o
-mailbox_omap2-objs		:= mailbox-omap2.o
+obj-$(CONFIG_OMAP2PLUS_MBOX)	+= omap-mailbox.o

+ 0 - 203
drivers/mailbox/mailbox-omap1.c

@@ -1,203 +0,0 @@
-/*
- * Mailbox reservation modules for OMAP1
- *
- * Copyright (C) 2006-2009 Nokia Corporation
- * Written by: Hiroshi DOYU <Hiroshi.DOYU@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/module.h>
-#include <linux/interrupt.h>
-#include <linux/platform_device.h>
-#include <linux/io.h>
-
-#include "omap-mbox.h"
-
-#define MAILBOX_ARM2DSP1		0x00
-#define MAILBOX_ARM2DSP1b		0x04
-#define MAILBOX_DSP2ARM1		0x08
-#define MAILBOX_DSP2ARM1b		0x0c
-#define MAILBOX_DSP2ARM2		0x10
-#define MAILBOX_DSP2ARM2b		0x14
-#define MAILBOX_ARM2DSP1_Flag		0x18
-#define MAILBOX_DSP2ARM1_Flag		0x1c
-#define MAILBOX_DSP2ARM2_Flag		0x20
-
-static void __iomem *mbox_base;
-
-struct omap_mbox1_fifo {
-	unsigned long cmd;
-	unsigned long data;
-	unsigned long flag;
-};
-
-struct omap_mbox1_priv {
-	struct omap_mbox1_fifo tx_fifo;
-	struct omap_mbox1_fifo rx_fifo;
-};
-
-static inline int mbox_read_reg(size_t ofs)
-{
-	return __raw_readw(mbox_base + ofs);
-}
-
-static inline void mbox_write_reg(u32 val, size_t ofs)
-{
-	__raw_writew(val, mbox_base + ofs);
-}
-
-/* msg */
-static mbox_msg_t omap1_mbox_fifo_read(struct omap_mbox *mbox)
-{
-	struct omap_mbox1_fifo *fifo =
-		&((struct omap_mbox1_priv *)mbox->priv)->rx_fifo;
-	mbox_msg_t msg;
-
-	msg = mbox_read_reg(fifo->data);
-	msg |= ((mbox_msg_t) mbox_read_reg(fifo->cmd)) << 16;
-
-	return msg;
-}
-
-static void
-omap1_mbox_fifo_write(struct omap_mbox *mbox, mbox_msg_t msg)
-{
-	struct omap_mbox1_fifo *fifo =
-		&((struct omap_mbox1_priv *)mbox->priv)->tx_fifo;
-
-	mbox_write_reg(msg & 0xffff, fifo->data);
-	mbox_write_reg(msg >> 16, fifo->cmd);
-}
-
-static int omap1_mbox_fifo_empty(struct omap_mbox *mbox)
-{
-	return 0;
-}
-
-static int omap1_mbox_fifo_full(struct omap_mbox *mbox)
-{
-	struct omap_mbox1_fifo *fifo =
-		&((struct omap_mbox1_priv *)mbox->priv)->rx_fifo;
-
-	return mbox_read_reg(fifo->flag);
-}
-
-/* irq */
-static void
-omap1_mbox_enable_irq(struct omap_mbox *mbox, omap_mbox_irq_t irq)
-{
-	if (irq == IRQ_RX)
-		enable_irq(mbox->irq);
-}
-
-static void
-omap1_mbox_disable_irq(struct omap_mbox *mbox, omap_mbox_irq_t irq)
-{
-	if (irq == IRQ_RX)
-		disable_irq(mbox->irq);
-}
-
-static int
-omap1_mbox_is_irq(struct omap_mbox *mbox, omap_mbox_irq_t irq)
-{
-	if (irq == IRQ_TX)
-		return 0;
-	return 1;
-}
-
-static struct omap_mbox_ops omap1_mbox_ops = {
-	.type		= OMAP_MBOX_TYPE1,
-	.fifo_read	= omap1_mbox_fifo_read,
-	.fifo_write	= omap1_mbox_fifo_write,
-	.fifo_empty	= omap1_mbox_fifo_empty,
-	.fifo_full	= omap1_mbox_fifo_full,
-	.enable_irq	= omap1_mbox_enable_irq,
-	.disable_irq	= omap1_mbox_disable_irq,
-	.is_irq		= omap1_mbox_is_irq,
-};
-
-/* FIXME: the following struct should be created automatically by the user id */
-
-/* DSP */
-static struct omap_mbox1_priv omap1_mbox_dsp_priv = {
-	.tx_fifo = {
-		.cmd	= MAILBOX_ARM2DSP1b,
-		.data	= MAILBOX_ARM2DSP1,
-		.flag	= MAILBOX_ARM2DSP1_Flag,
-	},
-	.rx_fifo = {
-		.cmd	= MAILBOX_DSP2ARM1b,
-		.data	= MAILBOX_DSP2ARM1,
-		.flag	= MAILBOX_DSP2ARM1_Flag,
-	},
-};
-
-static struct omap_mbox mbox_dsp_info = {
-	.name	= "dsp",
-	.ops	= &omap1_mbox_ops,
-	.priv	= &omap1_mbox_dsp_priv,
-};
-
-static struct omap_mbox *omap1_mboxes[] = { &mbox_dsp_info, NULL };
-
-static int omap1_mbox_probe(struct platform_device *pdev)
-{
-	struct resource *mem;
-	int ret;
-	struct omap_mbox **list;
-
-	list = omap1_mboxes;
-	list[0]->irq = platform_get_irq_byname(pdev, "dsp");
-
-	mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-	if (!mem)
-		return -ENOENT;
-
-	mbox_base = ioremap(mem->start, resource_size(mem));
-	if (!mbox_base)
-		return -ENOMEM;
-
-	ret = omap_mbox_register(&pdev->dev, list);
-	if (ret) {
-		iounmap(mbox_base);
-		return ret;
-	}
-
-	return 0;
-}
-
-static int omap1_mbox_remove(struct platform_device *pdev)
-{
-	omap_mbox_unregister();
-	iounmap(mbox_base);
-	return 0;
-}
-
-static struct platform_driver omap1_mbox_driver = {
-	.probe	= omap1_mbox_probe,
-	.remove	= omap1_mbox_remove,
-	.driver	= {
-		.name	= "omap-mailbox",
-	},
-};
-
-static int __init omap1_mbox_init(void)
-{
-	return platform_driver_register(&omap1_mbox_driver);
-}
-
-static void __exit omap1_mbox_exit(void)
-{
-	platform_driver_unregister(&omap1_mbox_driver);
-}
-
-module_init(omap1_mbox_init);
-module_exit(omap1_mbox_exit);
-
-MODULE_LICENSE("GPL v2");
-MODULE_DESCRIPTION("omap mailbox: omap1 architecture specific functions");
-MODULE_AUTHOR("Hiroshi DOYU <Hiroshi.DOYU@nokia.com>");
-MODULE_ALIAS("platform:omap1-mailbox");

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

@@ -1,357 +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 MAILBOX_IRQSTATUS(u)		(0x100 + 8 * (u))
-#define 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_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 = {
-	.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,
-	.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;
-	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 = kzalloc((pdata->info_cnt + 1) * sizeof(*list), GFP_KERNEL);
-	if (!list)
-		return -ENOMEM;
-
-	mboxblk = mbox = kzalloc(pdata->info_cnt * sizeof(*mbox), GFP_KERNEL);
-	if (!mboxblk) {
-		ret = -ENOMEM;
-		goto free_list;
-	}
-
-	privblk = priv = kzalloc(pdata->info_cnt * sizeof(*priv), GFP_KERNEL);
-	if (!privblk) {
-		ret = -ENOMEM;
-		goto free_mboxblk;
-	}
-
-	info = pdata->info;
-	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);
-		if (pdata->intr_type) {
-			priv->irqenable = OMAP4_MAILBOX_IRQENABLE(info->usr_id);
-			priv->irqstatus = OMAP4_MAILBOX_IRQSTATUS(info->usr_id);
-			priv->irqdisable =
-				OMAP4_MAILBOX_IRQENABLE_CLR(info->usr_id);
-		} else {
-			priv->irqenable = MAILBOX_IRQENABLE(info->usr_id);
-			priv->irqstatus = MAILBOX_IRQSTATUS(info->usr_id);
-			priv->irqdisable = MAILBOX_IRQENABLE(info->usr_id);
-		}
-		priv->intr_type = pdata->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) {
-			ret = mbox->irq;
-			goto free_privblk;
-		}
-		list[i] = mbox++;
-	}
-
-	mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-	if (!mem) {
-		ret = -ENOENT;
-		goto free_privblk;
-	}
-
-	mbox_base = ioremap(mem->start, resource_size(mem));
-	if (!mbox_base) {
-		ret = -ENOMEM;
-		goto free_privblk;
-	}
-
-	ret = omap_mbox_register(&pdev->dev, list);
-	if (ret)
-		goto unmap_mbox;
-	platform_set_drvdata(pdev, list);
-
-	return 0;
-
-unmap_mbox:
-	iounmap(mbox_base);
-free_privblk:
-	kfree(privblk);
-free_mboxblk:
-	kfree(mboxblk);
-free_list:
-	kfree(list);
-	return ret;
-}
-
-static int omap2_mbox_remove(struct platform_device *pdev)
-{
-	struct omap_mbox2_priv *privblk;
-	struct omap_mbox **list = platform_get_drvdata(pdev);
-	struct omap_mbox *mboxblk = list[0];
-
-	privblk = mboxblk->priv;
-	omap_mbox_unregister();
-	iounmap(mbox_base);
-	kfree(privblk);
-	kfree(mboxblk);
-	kfree(list);
-
-	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");

+ 358 - 86
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
@@ -24,70 +26,164 @@
 #include <linux/interrupt.h>
 #include <linux/interrupt.h>
 #include <linux/spinlock.h>
 #include <linux/spinlock.h>
 #include <linux/mutex.h>
 #include <linux/mutex.h>
-#include <linux/delay.h>
 #include <linux/slab.h>
 #include <linux/slab.h>
 #include <linux/kfifo.h>
 #include <linux/kfifo.h>
 #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"
-
-static struct omap_mbox **mboxes;
-
-static int mbox_configured;
-static DEFINE_MUTEX(mbox_configured_lock);
+#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;
+	unsigned long irqenable;
+	unsigned long irqstatus;
+	unsigned long irqdisable;
+	u32 intr_bit;
+};
+
+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_device {
+	struct device *dev;
+	struct mutex cfg_lock;
+	void __iomem *mbox_base;
+	u32 num_users;
+	u32 num_fifos;
+	struct omap_mbox **mboxes;
+	struct list_head elem;
+};
+
+struct omap_mbox {
+	const char		*name;
+	int			irq;
+	struct omap_mbox_queue	*txq, *rxq;
+	struct device		*dev;
+	struct omap_mbox_device *parent;
+	struct omap_mbox_fifo	tx_fifo;
+	struct omap_mbox_fifo	rx_fifo;
+	u32			ctx[OMAP4_MBOX_NR_REGS];
+	u32			intr_type;
+	int			use_count;
+	struct blocking_notifier_head	notifier;
+};
+
+/* global variables for the mailbox devices */
+static DEFINE_MUTEX(omap_mbox_devices_lock);
+static LIST_HEAD(omap_mbox_devices);
 
 
 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(struct omap_mbox_device *mdev, size_t ofs)
+{
+	return __raw_readl(mdev->mbox_base + ofs);
+}
+
+static inline
+void mbox_write_reg(struct omap_mbox_device *mdev, u32 val, size_t ofs)
+{
+	__raw_writel(val, mdev->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 = &mbox->rx_fifo;
+	return (mbox_msg_t) mbox_read_reg(mbox->parent, 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 = &mbox->tx_fifo;
+	mbox_write_reg(mbox->parent, 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 = &mbox->rx_fifo;
+	return (mbox_read_reg(mbox->parent, 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 = &mbox->tx_fifo;
+	return mbox_read_reg(mbox->parent, 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_fifo *fifo = (irq == IRQ_TX) ?
+				&mbox->tx_fifo : &mbox->rx_fifo;
+	u32 bit = fifo->intr_bit;
+	u32 irqstatus = fifo->irqstatus;
+
+	mbox_write_reg(mbox->parent, bit, irqstatus);
+
+	/* Flush posted write for irq status to avoid spurious interrupts */
+	mbox_read_reg(mbox->parent, 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_fifo *fifo = (irq == IRQ_TX) ?
+				&mbox->tx_fifo : &mbox->rx_fifo;
+	u32 bit = fifo->intr_bit;
+	u32 irqenable = fifo->irqenable;
+	u32 irqstatus = fifo->irqstatus;
+
+	u32 enable = mbox_read_reg(mbox->parent, irqenable);
+	u32 status = mbox_read_reg(mbox->parent, irqstatus);
+
+	return (int)(enable & status & bit);
 }
 }
 
 
 /*
 /*
  * message sender
  * message sender
  */
  */
-static int __mbox_poll_for_space(struct omap_mbox *mbox)
-{
-	int ret = 0, i = 1000;
-
-	while (mbox_fifo_full(mbox)) {
-		if (mbox->ops->type == OMAP_MBOX_TYPE2)
-			return -1;
-		if (--i == 0)
-			return -1;
-		udelay(1);
-	}
-	return ret;
-}
-
 int omap_mbox_msg_send(struct omap_mbox *mbox, mbox_msg_t msg)
 int omap_mbox_msg_send(struct omap_mbox *mbox, mbox_msg_t msg)
 {
 {
 	struct omap_mbox_queue *mq = mbox->txq;
 	struct omap_mbox_queue *mq = mbox->txq;
@@ -100,7 +196,7 @@ int omap_mbox_msg_send(struct omap_mbox *mbox, mbox_msg_t msg)
 		goto out;
 		goto out;
 	}
 	}
 
 
-	if (kfifo_is_empty(&mq->fifo) && !__mbox_poll_for_space(mbox)) {
+	if (kfifo_is_empty(&mq->fifo) && !mbox_fifo_full(mbox)) {
 		mbox_fifo_write(mbox, msg);
 		mbox_fifo_write(mbox, msg);
 		goto out;
 		goto out;
 	}
 	}
@@ -118,35 +214,69 @@ 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;
+	int nr_regs;
+
+	if (mbox->intr_type)
+		nr_regs = OMAP4_MBOX_NR_REGS;
+	else
+		nr_regs = MBOX_NR_REGS;
+	for (i = 0; i < nr_regs; i++) {
+		mbox->ctx[i] = mbox_read_reg(mbox->parent, i * sizeof(u32));
 
 
-	mbox->ops->save_ctx(mbox);
+		dev_dbg(mbox->dev, "%s: [%02x] %08x\n", __func__,
+			i, mbox->ctx[i]);
+	}
 }
 }
 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;
+	int nr_regs;
 
 
-	mbox->ops->restore_ctx(mbox);
+	if (mbox->intr_type)
+		nr_regs = OMAP4_MBOX_NR_REGS;
+	else
+		nr_regs = MBOX_NR_REGS;
+	for (i = 0; i < nr_regs; i++) {
+		mbox_write_reg(mbox->parent, mbox->ctx[i], i * sizeof(u32));
+
+		dev_dbg(mbox->dev, "%s: [%02x] %08x\n", __func__,
+			i, mbox->ctx[i]);
+	}
 }
 }
 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);
+	u32 l;
+	struct omap_mbox_fifo *fifo = (irq == IRQ_TX) ?
+				&mbox->tx_fifo : &mbox->rx_fifo;
+	u32 bit = fifo->intr_bit;
+	u32 irqenable = fifo->irqenable;
+
+	l = mbox_read_reg(mbox->parent, irqenable);
+	l |= bit;
+	mbox_write_reg(mbox->parent, l, 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_fifo *fifo = (irq == IRQ_TX) ?
+				&mbox->tx_fifo : &mbox->rx_fifo;
+	u32 bit = fifo->intr_bit;
+	u32 irqdisable = fifo->irqdisable;
+
+	/*
+	 * Read and update the interrupt configuration register for pre-OMAP4.
+	 * OMAP4 and later SoCs have a dedicated interrupt disabling register.
+	 */
+	if (!mbox->intr_type)
+		bit = mbox_read_reg(mbox->parent, irqdisable) & ~bit;
+
+	mbox_write_reg(mbox->parent, bit, irqdisable);
 }
 }
 EXPORT_SYMBOL(omap_mbox_disable_irq);
 EXPORT_SYMBOL(omap_mbox_disable_irq);
 
 
@@ -158,7 +288,7 @@ static void mbox_tx_tasklet(unsigned long tx_data)
 	int ret;
 	int ret;
 
 
 	while (kfifo_len(&mq->fifo)) {
 	while (kfifo_len(&mq->fifo)) {
-		if (__mbox_poll_for_space(mbox)) {
+		if (mbox_fifo_full(mbox)) {
 			omap_mbox_enable_irq(mbox, IRQ_TX);
 			omap_mbox_enable_irq(mbox, IRQ_TX);
 			break;
 			break;
 		}
 		}
@@ -223,9 +353,6 @@ static void __mbox_rx_interrupt(struct omap_mbox *mbox)
 
 
 		len = kfifo_in(&mq->fifo, (unsigned char *)&msg, sizeof(msg));
 		len = kfifo_in(&mq->fifo, (unsigned char *)&msg, sizeof(msg));
 		WARN_ON(len != sizeof(msg));
 		WARN_ON(len != sizeof(msg));
-
-		if (mbox->ops->type == OMAP_MBOX_TYPE1)
-			break;
 	}
 	}
 
 
 	/* no more messages in the fifo. clear IRQ source. */
 	/* no more messages in the fifo. clear IRQ source. */
@@ -283,16 +410,12 @@ static int omap_mbox_startup(struct omap_mbox *mbox)
 {
 {
 	int ret = 0;
 	int ret = 0;
 	struct omap_mbox_queue *mq;
 	struct omap_mbox_queue *mq;
+	struct omap_mbox_device *mdev = mbox->parent;
 
 
-	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;
-	}
+	mutex_lock(&mdev->cfg_lock);
+	ret = pm_runtime_get_sync(mdev->dev);
+	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);
@@ -319,7 +442,7 @@ static int omap_mbox_startup(struct omap_mbox *mbox)
 
 
 		omap_mbox_enable_irq(mbox, IRQ_RX);
 		omap_mbox_enable_irq(mbox, IRQ_RX);
 	}
 	}
-	mutex_unlock(&mbox_configured_lock);
+	mutex_unlock(&mdev->cfg_lock);
 	return 0;
 	return 0;
 
 
 fail_request_irq:
 fail_request_irq:
@@ -327,18 +450,18 @@ 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(mdev->dev);
 	mbox->use_count--;
 	mbox->use_count--;
 fail_startup:
 fail_startup:
-	mbox_configured--;
-	mutex_unlock(&mbox_configured_lock);
+	mutex_unlock(&mdev->cfg_lock);
 	return ret;
 	return ret;
 }
 }
 
 
 static void omap_mbox_fini(struct omap_mbox *mbox)
 static void omap_mbox_fini(struct omap_mbox *mbox)
 {
 {
-	mutex_lock(&mbox_configured_lock);
+	struct omap_mbox_device *mdev = mbox->parent;
+
+	mutex_lock(&mdev->cfg_lock);
 
 
 	if (!--mbox->use_count) {
 	if (!--mbox->use_count) {
 		omap_mbox_disable_irq(mbox, IRQ_RX);
 		omap_mbox_disable_irq(mbox, IRQ_RX);
@@ -349,28 +472,43 @@ 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(mdev->dev);
 
 
-	mutex_unlock(&mbox_configured_lock);
+	mutex_unlock(&mdev->cfg_lock);
 }
 }
 
 
-struct omap_mbox *omap_mbox_get(const char *name, struct notifier_block *nb)
+static struct omap_mbox *omap_mbox_device_find(struct omap_mbox_device *mdev,
+					       const char *mbox_name)
 {
 {
 	struct omap_mbox *_mbox, *mbox = NULL;
 	struct omap_mbox *_mbox, *mbox = NULL;
-	int i, ret;
+	struct omap_mbox **mboxes = mdev->mboxes;
+	int i;
 
 
 	if (!mboxes)
 	if (!mboxes)
-		return ERR_PTR(-EINVAL);
+		return NULL;
 
 
 	for (i = 0; (_mbox = mboxes[i]); i++) {
 	for (i = 0; (_mbox = mboxes[i]); i++) {
-		if (!strcmp(_mbox->name, name)) {
+		if (!strcmp(_mbox->name, mbox_name)) {
 			mbox = _mbox;
 			mbox = _mbox;
 			break;
 			break;
 		}
 		}
 	}
 	}
+	return mbox;
+}
+
+struct omap_mbox *omap_mbox_get(const char *name, struct notifier_block *nb)
+{
+	struct omap_mbox *mbox = NULL;
+	struct omap_mbox_device *mdev;
+	int ret;
+
+	mutex_lock(&omap_mbox_devices_lock);
+	list_for_each_entry(mdev, &omap_mbox_devices, elem) {
+		mbox = omap_mbox_device_find(mdev, name);
+		if (mbox)
+			break;
+	}
+	mutex_unlock(&omap_mbox_devices_lock);
 
 
 	if (!mbox)
 	if (!mbox)
 		return ERR_PTR(-ENOENT);
 		return ERR_PTR(-ENOENT);
@@ -397,19 +535,20 @@ 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 omap_mbox_device *mdev)
 {
 {
 	int ret;
 	int ret;
 	int i;
 	int i;
+	struct omap_mbox **mboxes;
 
 
-	mboxes = list;
-	if (!mboxes)
+	if (!mdev || !mdev->mboxes)
 		return -EINVAL;
 		return -EINVAL;
 
 
+	mboxes = mdev->mboxes;
 	for (i = 0; mboxes[i]; i++) {
 	for (i = 0; mboxes[i]; i++) {
 		struct omap_mbox *mbox = mboxes[i];
 		struct omap_mbox *mbox = mboxes[i];
 		mbox->dev = device_create(&omap_mbox_class,
 		mbox->dev = device_create(&omap_mbox_class,
-				parent, 0, mbox, "%s", mbox->name);
+				mdev->dev, 0, mbox, "%s", mbox->name);
 		if (IS_ERR(mbox->dev)) {
 		if (IS_ERR(mbox->dev)) {
 			ret = PTR_ERR(mbox->dev);
 			ret = PTR_ERR(mbox->dev);
 			goto err_out;
 			goto err_out;
@@ -417,6 +556,11 @@ int omap_mbox_register(struct device *parent, struct omap_mbox **list)
 
 
 		BLOCKING_INIT_NOTIFIER_HEAD(&mbox->notifier);
 		BLOCKING_INIT_NOTIFIER_HEAD(&mbox->notifier);
 	}
 	}
+
+	mutex_lock(&omap_mbox_devices_lock);
+	list_add(&mdev->elem, &omap_mbox_devices);
+	mutex_unlock(&omap_mbox_devices_lock);
+
 	return 0;
 	return 0;
 
 
 err_out:
 err_out:
@@ -424,21 +568,148 @@ 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(struct omap_mbox_device *mdev)
 {
 {
 	int i;
 	int i;
+	struct omap_mbox **mboxes;
 
 
-	if (!mboxes)
+	if (!mdev || !mdev->mboxes)
 		return -EINVAL;
 		return -EINVAL;
 
 
+	mutex_lock(&omap_mbox_devices_lock);
+	list_del(&mdev->elem);
+	mutex_unlock(&omap_mbox_devices_lock);
+
+	mboxes = mdev->mboxes;
 	for (i = 0; mboxes[i]; i++)
 	for (i = 0; mboxes[i]; i++)
 		device_unregister(mboxes[i]->dev);
 		device_unregister(mboxes[i]->dev);
-	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_pdata *pdata = pdev->dev.platform_data;
+	struct omap_mbox_dev_info *info;
+	struct omap_mbox_device *mdev;
+	struct omap_mbox_fifo *fifo;
+	u32 intr_type;
+	u32 l;
+	int i;
+
+	if (!pdata || !pdata->info_cnt || !pdata->info) {
+		pr_err("%s: platform not supported\n", __func__);
+		return -ENODEV;
+	}
+
+	mdev = devm_kzalloc(&pdev->dev, sizeof(*mdev), GFP_KERNEL);
+	if (!mdev)
+		return -ENOMEM;
+
+	mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	mdev->mbox_base = devm_ioremap_resource(&pdev->dev, mem);
+	if (IS_ERR(mdev->mbox_base))
+		return PTR_ERR(mdev->mbox_base);
+
+	/* 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;
+
+	info = pdata->info;
+	intr_type = pdata->intr_type;
+	mbox = mboxblk;
+	for (i = 0; i < pdata->info_cnt; i++, info++) {
+		fifo = &mbox->tx_fifo;
+		fifo->msg = MAILBOX_MESSAGE(info->tx_id);
+		fifo->fifo_stat = MAILBOX_FIFOSTATUS(info->tx_id);
+		fifo->intr_bit = MAILBOX_IRQ_NOTFULL(info->tx_id);
+		fifo->irqenable = MAILBOX_IRQENABLE(intr_type, info->usr_id);
+		fifo->irqstatus = MAILBOX_IRQSTATUS(intr_type, info->usr_id);
+		fifo->irqdisable = MAILBOX_IRQDISABLE(intr_type, info->usr_id);
+
+		fifo = &mbox->rx_fifo;
+		fifo->msg =  MAILBOX_MESSAGE(info->rx_id);
+		fifo->msg_stat =  MAILBOX_MSGSTATUS(info->rx_id);
+		fifo->intr_bit = MAILBOX_IRQ_NEWMSG(info->rx_id);
+		fifo->irqenable = MAILBOX_IRQENABLE(intr_type, info->usr_id);
+		fifo->irqstatus = MAILBOX_IRQSTATUS(intr_type, info->usr_id);
+		fifo->irqdisable = MAILBOX_IRQDISABLE(intr_type, info->usr_id);
+
+		mbox->intr_type = intr_type;
+
+		mbox->parent = mdev;
+		mbox->name = info->name;
+		mbox->irq = platform_get_irq(pdev, info->irq_id);
+		if (mbox->irq < 0)
+			return mbox->irq;
+		list[i] = mbox++;
+	}
+
+	mutex_init(&mdev->cfg_lock);
+	mdev->dev = &pdev->dev;
+	mdev->num_users = pdata->num_users;
+	mdev->num_fifos = pdata->num_fifos;
+	mdev->mboxes = list;
+	ret = omap_mbox_register(mdev);
+	if (ret)
+		return ret;
+
+	platform_set_drvdata(pdev, mdev);
+	pm_runtime_enable(mdev->dev);
+
+	ret = pm_runtime_get_sync(mdev->dev);
+	if (ret < 0) {
+		pm_runtime_put_noidle(mdev->dev);
+		goto unregister;
+	}
+
+	/*
+	 * just print the raw revision register, the format is not
+	 * uniform across all SoCs
+	 */
+	l = mbox_read_reg(mdev, MAILBOX_REVISION);
+	dev_info(mdev->dev, "omap mailbox rev 0x%x\n", l);
+
+	ret = pm_runtime_put_sync(mdev->dev);
+	if (ret < 0)
+		goto unregister;
+
+	return 0;
+
+unregister:
+	pm_runtime_disable(mdev->dev);
+	omap_mbox_unregister(mdev);
+	return ret;
+}
+
+static int omap_mbox_remove(struct platform_device *pdev)
+{
+	struct omap_mbox_device *mdev = platform_get_drvdata(pdev);
+
+	pm_runtime_disable(mdev->dev);
+	omap_mbox_unregister(mdev);
+
+	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)
 {
 {
@@ -453,12 +724,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 - 67
drivers/mailbox/omap-mbox.h

@@ -1,67 +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>
-
-typedef int __bitwise omap_mbox_type_t;
-#define OMAP_MBOX_TYPE1 ((__force omap_mbox_type_t) 1)
-#define OMAP_MBOX_TYPE2 ((__force omap_mbox_type_t) 2)
-
-struct omap_mbox_ops {
-	omap_mbox_type_t	type;
-	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 */