+++ /dev/null
-ST-Ericsson DBx500 PRCM Mailbox Driver
-
-Required properties:
-- compatible : Should be
- "stericsson,db8500-mailbox" for db8500 and db9500
- "stericsson,db9540-mailbox" for db9540
-- reg : Physical base address and length of mailbox's
- registers and shared memory
-- reg-names : Should contain the reg names "prcm-reg" and
- "prcmu-tcdm"
-- interrupts : contains the IRQ line for the PRCM mailbox
-- interrupt-names : Should contain the interrupt name "irq"
-- legacy-offset : Memory offset in shared mem for legacy mailboxes
-
-Optional properties:
-- upap-offset : Memory offset in shared mem for upap mailboxes
-
-Examples:
-
-mailbox {
- compatible = "stericsson,db8500-mailbox";
- reg = <0x80157000 0x1000>, <0x801B8000 0x2000>;
- reg-names = "prcm-reg", "prcmu-tcdm";
- interrupts = <0 47 0x4>;
- interrupt-names = "irq";
- legacy-offset = <0xdd4>;
-};
CONFIG_ARCH_OMAP1=y
CONFIG_OMAP_RESET_CLOCKS=y
# CONFIG_OMAP_MUX is not set
-CONFIG_MAILBOX=y
-CONFIG_OMAP1_MBOX=y
+CONFIG_OMAP_MBOX_FWK=y
CONFIG_OMAP_32K_TIMER=y
CONFIG_OMAP_DM_TIMER=y
CONFIG_ARCH_OMAP730=y
# Power Management
obj-$(CONFIG_PM) += pm.o sleep.o
+# DSP
+obj-$(CONFIG_OMAP_MBOX_FWK) += mailbox_mach.o
+mailbox_mach-objs := mailbox.o
+
i2c-omap-$(CONFIG_I2C_OMAP) := i2c.o
obj-y += $(i2c-omap-m) $(i2c-omap-y)
#include <linux/interrupt.h>
#include <linux/platform_device.h>
#include <linux/io.h>
-#include <linux/delay.h>
-
-#include "mailbox_internal.h"
+#include <plat/mailbox.h>
#define MAILBOX_ARM2DSP1 0x00
#define MAILBOX_ARM2DSP1b 0x04
struct omap_mbox1_priv {
struct omap_mbox1_fifo tx_fifo;
struct omap_mbox1_fifo rx_fifo;
- u32 data;
- bool empty_flag;
};
static inline int mbox_read_reg(size_t ofs)
}
/* msg */
-static void omap1_mbox_fifo_read(struct mailbox *mbox, struct mailbox_msg *msg)
+static mbox_msg_t omap1_mbox_fifo_read(struct omap_mbox *mbox)
{
- struct omap_mbox1_priv *priv = mbox->priv;
- struct omap_mbox1_fifo *fifo = &priv->rx_fifo;
+ struct omap_mbox1_fifo *fifo =
+ &((struct omap_mbox1_priv *)mbox->priv)->rx_fifo;
+ mbox_msg_t msg;
- priv->data = mbox_read_reg(fifo->data);
- priv->data |= ((u32) mbox_read_reg(fifo->cmd)) << 16;
- MAILBOX_FILL_MSG((*msg), 0, priv->data, 0);
- priv->empty_flag = false;
+ msg = mbox_read_reg(fifo->data);
+ msg |= ((mbox_msg_t) mbox_read_reg(fifo->cmd)) << 16;
+
+ return msg;
}
-static int
-omap1_mbox_fifo_write(struct mailbox *mbox, struct mailbox_msg *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;
- u32 data = (u32)msg->pdata;
-
- mbox_write_reg(data & 0xffff, fifo->data);
- mbox_write_reg(data >> 16, fifo->cmd);
- return 0;
+ mbox_write_reg(msg & 0xffff, fifo->data);
+ mbox_write_reg(msg >> 16, fifo->cmd);
}
-static int omap1_mbox_fifo_empty(struct mailbox *mbox)
+static int omap1_mbox_fifo_empty(struct omap_mbox *mbox)
{
- struct omap_mbox1_priv *priv = (struct omap_mbox1_priv *)mbox->priv;
- if (priv->empty_flag)
- return 0;
- else
- return 1;
+ return 0;
}
-static int omap1_mbox_fifo_full(struct mailbox *mbox)
+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);
}
-static int omap1_mbox_poll_for_space(struct mailbox *mbox)
-{
- int ret = 0, i = 1000;
-
- while (omap1_mbox_fifo_full(mbox)) {
- if (--i == 0)
- return -1;
- udelay(1);
- }
- return ret;
-}
-
/* irq */
static void
-omap1_mbox_enable_irq(struct mailbox *mbox, mailbox_type_t irq)
+omap1_mbox_enable_irq(struct omap_mbox *mbox, omap_mbox_type_t irq)
{
if (irq == IRQ_RX)
enable_irq(mbox->irq);
}
static void
-omap1_mbox_disable_irq(struct mailbox *mbox, mailbox_type_t irq)
+omap1_mbox_disable_irq(struct omap_mbox *mbox, omap_mbox_type_t irq)
{
if (irq == IRQ_RX)
disable_irq(mbox->irq);
}
static int
-omap1_mbox_is_irq(struct mailbox *mbox, mailbox_type_t irq)
+omap1_mbox_is_irq(struct omap_mbox *mbox, omap_mbox_type_t irq)
{
- struct omap_mbox1_priv *priv = (struct omap_mbox1_priv *)mbox->priv;
-
if (irq == IRQ_TX)
return 0;
- if (irq == IRQ_RX)
- priv->empty_flag = true;
-
return 1;
}
-static struct mailbox_ops omap1_mbox_ops = {
- .type = MBOX_HW_FIFO1_TYPE,
- .read = omap1_mbox_fifo_read,
- .write = omap1_mbox_fifo_write,
- .empty = omap1_mbox_fifo_empty,
- .poll_for_space = omap1_mbox_poll_for_space,
+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,
},
};
-static struct mailbox mbox_dsp_info = {
+static struct omap_mbox mbox_dsp_info = {
.name = "dsp",
.ops = &omap1_mbox_ops,
.priv = &omap1_mbox_dsp_priv,
};
-static struct mailbox *omap1_mboxes[] = { &mbox_dsp_info, NULL };
+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 mailbox **list;
+ 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 -ENOMEM;
-
mbox_base = ioremap(mem->start, resource_size(mem));
if (!mbox_base)
return -ENOMEM;
- ret = mailbox_register(&pdev->dev, list);
+ ret = omap_mbox_register(&pdev->dev, list);
if (ret) {
iounmap(mbox_base);
return ret;
static int omap1_mbox_remove(struct platform_device *pdev)
{
- mailbox_unregister();
+ omap_mbox_unregister();
iounmap(mbox_base);
return 0;
}
obj-$(CONFIG_OMAP3_EMU) += emu.o
obj-$(CONFIG_HW_PERF_EVENTS) += pmu.o
+obj-$(CONFIG_OMAP_MBOX_FWK) += mailbox_mach.o
+mailbox_mach-objs := mailbox.o
+
iommu-$(CONFIG_OMAP_IOMMU) := omap-iommu.o
obj-y += $(iommu-m) $(iommu-y)
#include <linux/pinctrl/machine.h>
#include <linux/platform_data/omap4-keypad.h>
#include <linux/platform_data/omap_ocp2scp.h>
-#include <linux/platform_data/mailbox-omap.h>
#include <linux/usb/omap_control_usb.h>
#include <asm/mach-types.h>
return 0;
}
-#if defined(CONFIG_OMAP2PLUS_MBOX) || defined(CONFIG_OMAP2PLUS_MBOX_MODULE)
+#if defined(CONFIG_OMAP_MBOX_FWK) || defined(CONFIG_OMAP_MBOX_FWK_MODULE)
static inline void __init omap_init_mbox(void)
{
struct omap_hwmod *oh;
struct platform_device *pdev;
- struct omap_mbox_pdata *pdata;
oh = omap_hwmod_lookup("mailbox");
if (!oh) {
pr_err("%s: unable to find hwmod\n", __func__);
return;
}
- if (!oh->dev_attr) {
- pr_err("%s: hwmod doesn't have valid attrs\n", __func__);
- return;
- }
- pdata = (struct omap_mbox_pdata *)oh->dev_attr;
- pdev = omap_device_build("omap-mailbox", -1, oh, pdata, sizeof(*pdata));
+ pdev = omap_device_build("omap-mailbox", -1, oh, NULL, 0);
WARN(IS_ERR(pdev), "%s: could not build device, err %ld\n",
__func__, PTR_ERR(pdev));
}
#else
static inline void omap_init_mbox(void) { }
-#endif /* CONFIG_OMAP2PLUS_MBOX */
+#endif /* CONFIG_OMAP_MBOX_FWK */
static inline void omap_init_sti(void) {}
*/
#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 "mailbox_internal.h"
+#include <plat/mailbox.h>
+
+#include "soc.h"
#define MAILBOX_REVISION 0x000
#define MAILBOX_MESSAGE(m) (0x040 + 4 * (m))
u32 notfull_bit;
u32 ctx[OMAP4_MBOX_NR_REGS];
unsigned long irqdisable;
- u32 intr_type;
- u32 data;
};
-static void omap2_mbox_enable_irq(struct mailbox *mbox,
- mailbox_type_t irq);
+static void omap2_mbox_enable_irq(struct omap_mbox *mbox,
+ omap_mbox_type_t irq);
static inline unsigned int mbox_read_reg(size_t ofs)
{
}
/* Mailbox H/W preparations */
-static int omap2_mbox_startup(struct mailbox *mbox)
+static int omap2_mbox_startup(struct omap_mbox *mbox)
{
u32 l;
return 0;
}
-static void omap2_mbox_shutdown(struct mailbox *mbox)
+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 void omap2_mbox_fifo_read(struct mailbox *mbox, struct mailbox_msg *msg)
+static mbox_msg_t omap2_mbox_fifo_read(struct omap_mbox *mbox)
{
- struct omap_mbox2_priv *priv = mbox->priv;
- struct omap_mbox2_fifo *fifo = &priv->rx_fifo;
- priv->data = mbox_read_reg(fifo->msg);
- MAILBOX_FILL_MSG((*msg), 0, priv->data, 0);
+ struct omap_mbox2_fifo *fifo =
+ &((struct omap_mbox2_priv *)mbox->priv)->rx_fifo;
+ return (mbox_msg_t) mbox_read_reg(fifo->msg);
}
-static int omap2_mbox_fifo_write(struct mailbox *mbox, struct mailbox_msg *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((u32)msg->pdata, fifo->msg);
-
- return 0;
+ mbox_write_reg(msg, fifo->msg);
}
-static int omap2_mbox_fifo_empty(struct mailbox *mbox)
+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 mailbox *mbox)
+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);
}
-static int omap2_mbox_poll_for_space(struct mailbox *mbox)
-{
- if (omap2_mbox_fifo_full(mbox))
- return -1;
-
- return 0;
-}
-
/* Mailbox IRQ handle functions */
-static void omap2_mbox_enable_irq(struct mailbox *mbox,
- mailbox_type_t irq)
+static void omap2_mbox_enable_irq(struct omap_mbox *mbox,
+ omap_mbox_type_t irq)
{
struct omap_mbox2_priv *p = mbox->priv;
u32 l, bit = (irq == IRQ_TX) ? p->notfull_bit : p->newmsg_bit;
mbox_write_reg(l, p->irqenable);
}
-static void omap2_mbox_disable_irq(struct mailbox *mbox,
- mailbox_type_t irq)
+static void omap2_mbox_disable_irq(struct omap_mbox *mbox,
+ omap_mbox_type_t irq)
{
struct omap_mbox2_priv *p = mbox->priv;
u32 bit = (irq == IRQ_TX) ? p->notfull_bit : p->newmsg_bit;
- if (!p->intr_type)
+ if (!cpu_is_omap44xx())
bit = mbox_read_reg(p->irqdisable) & ~bit;
mbox_write_reg(bit, p->irqdisable);
}
-static void omap2_mbox_ack_irq(struct mailbox *mbox,
- mailbox_type_t irq)
+static void omap2_mbox_ack_irq(struct omap_mbox *mbox,
+ omap_mbox_type_t irq)
{
struct omap_mbox2_priv *p = mbox->priv;
u32 bit = (irq == IRQ_TX) ? p->notfull_bit : p->newmsg_bit;
mbox_read_reg(p->irqstatus);
}
-static int omap2_mbox_is_irq(struct mailbox *mbox,
- mailbox_type_t irq)
+static int omap2_mbox_is_irq(struct omap_mbox *mbox,
+ omap_mbox_type_t irq)
{
struct omap_mbox2_priv *p = mbox->priv;
u32 bit = (irq == IRQ_TX) ? p->notfull_bit : p->newmsg_bit;
return (int)(enable & status & bit);
}
-static void omap2_mbox_save_ctx(struct mailbox *mbox)
+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)
+ if (cpu_is_omap44xx())
nr_regs = OMAP4_MBOX_NR_REGS;
else
nr_regs = MBOX_NR_REGS;
p->ctx[i] = mbox_read_reg(i * sizeof(u32));
dev_dbg(mbox->dev, "%s: [%02x] %08x\n", __func__,
- i, p->ctx[i]);
+ i, p->ctx[i]);
}
}
-static void omap2_mbox_restore_ctx(struct mailbox *mbox)
+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)
+ if (cpu_is_omap44xx())
nr_regs = OMAP4_MBOX_NR_REGS;
else
nr_regs = MBOX_NR_REGS;
mbox_write_reg(p->ctx[i], i * sizeof(u32));
dev_dbg(mbox->dev, "%s: [%02x] %08x\n", __func__,
- i, p->ctx[i]);
+ i, p->ctx[i]);
}
}
-static struct mailbox_ops omap2_mbox_ops = {
- .type = MBOX_HW_FIFO2_TYPE,
+static struct omap_mbox_ops omap2_mbox_ops = {
+ .type = OMAP_MBOX_TYPE2,
.startup = omap2_mbox_startup,
.shutdown = omap2_mbox_shutdown,
- .read = omap2_mbox_fifo_read,
- .write = omap2_mbox_fifo_write,
- .empty = omap2_mbox_fifo_empty,
- .poll_for_space = omap2_mbox_poll_for_space,
+ .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,
.restore_ctx = omap2_mbox_restore_ctx,
};
+/*
+ * 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 */
+
+#if defined(CONFIG_ARCH_OMAP3) || defined(CONFIG_ARCH_OMAP2)
+/* 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),
+ .irqdisable = MAILBOX_IRQENABLE(0),
+};
+
+struct omap_mbox mbox_dsp_info = {
+ .name = "dsp",
+ .ops = &omap2_mbox_ops,
+ .priv = &omap2_mbox_dsp_priv,
+};
+#endif
+
+#if defined(CONFIG_ARCH_OMAP3)
+struct omap_mbox *omap3_mboxes[] = { &mbox_dsp_info, NULL };
+#endif
+
+#if defined(CONFIG_SOC_OMAP2420)
+/* 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),
+ .irqdisable = MAILBOX_IRQENABLE(3),
+};
+
+static struct omap_mbox mbox_iva_info = {
+ .name = "iva",
+ .ops = &omap2_mbox_ops,
+ .priv = &omap2_mbox_iva_priv,
+};
+#endif
+
+#ifdef CONFIG_ARCH_OMAP2
+struct omap_mbox *omap2_mboxes[] = {
+ &mbox_dsp_info,
+#ifdef CONFIG_SOC_OMAP2420
+ &mbox_iva_info,
+#endif
+ NULL
+};
+#endif
+
+#if defined(CONFIG_ARCH_OMAP4)
+/* OMAP4 */
+static struct omap_mbox2_priv omap2_mbox_1_priv = {
+ .tx_fifo = {
+ .msg = MAILBOX_MESSAGE(0),
+ .fifo_stat = MAILBOX_FIFOSTATUS(0),
+ },
+ .rx_fifo = {
+ .msg = MAILBOX_MESSAGE(1),
+ .msg_stat = MAILBOX_MSGSTATUS(1),
+ },
+ .irqenable = OMAP4_MAILBOX_IRQENABLE(0),
+ .irqstatus = OMAP4_MAILBOX_IRQSTATUS(0),
+ .notfull_bit = MAILBOX_IRQ_NOTFULL(0),
+ .newmsg_bit = MAILBOX_IRQ_NEWMSG(1),
+ .irqdisable = OMAP4_MAILBOX_IRQENABLE_CLR(0),
+};
+
+struct omap_mbox mbox_1_info = {
+ .name = "mailbox-1",
+ .ops = &omap2_mbox_ops,
+ .priv = &omap2_mbox_1_priv,
+};
+
+static struct omap_mbox2_priv omap2_mbox_2_priv = {
+ .tx_fifo = {
+ .msg = MAILBOX_MESSAGE(3),
+ .fifo_stat = MAILBOX_FIFOSTATUS(3),
+ },
+ .rx_fifo = {
+ .msg = MAILBOX_MESSAGE(2),
+ .msg_stat = MAILBOX_MSGSTATUS(2),
+ },
+ .irqenable = OMAP4_MAILBOX_IRQENABLE(0),
+ .irqstatus = OMAP4_MAILBOX_IRQSTATUS(0),
+ .notfull_bit = MAILBOX_IRQ_NOTFULL(3),
+ .newmsg_bit = MAILBOX_IRQ_NEWMSG(2),
+ .irqdisable = OMAP4_MAILBOX_IRQENABLE_CLR(0),
+};
+
+struct omap_mbox mbox_2_info = {
+ .name = "mailbox-2",
+ .ops = &omap2_mbox_ops,
+ .priv = &omap2_mbox_2_priv,
+};
+
+struct omap_mbox *omap4_mboxes[] = { &mbox_1_info, &mbox_2_info, NULL };
+#endif
+
static int omap2_mbox_probe(struct platform_device *pdev)
{
struct resource *mem;
int ret;
- struct mailbox **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;
+ struct omap_mbox **list;
- if (!pdata || !pdata->info_cnt || !pdata->info) {
- pr_err("%s: platform not supported\n", __func__);
- return -ENODEV;
+ if (false)
+ ;
+#if defined(CONFIG_ARCH_OMAP3)
+ else if (cpu_is_omap34xx()) {
+ list = omap3_mboxes;
+
+ list[0]->irq = platform_get_irq(pdev, 0);
}
+#endif
+#if defined(CONFIG_ARCH_OMAP2)
+ else if (cpu_is_omap2430()) {
+ list = omap2_mboxes;
- /* allocate one extra for marking end of list */
- list = kzalloc((pdata->info_cnt + 1) * sizeof(*list), GFP_KERNEL);
- if (!list)
- return -ENOMEM;
+ list[0]->irq = platform_get_irq(pdev, 0);
+ } else if (cpu_is_omap2420()) {
+ list = omap2_mboxes;
- mboxblk = mbox = kzalloc(pdata->info_cnt * sizeof(*mbox), GFP_KERNEL);
- if (!mboxblk) {
- ret = -ENOMEM;
- goto free_list;
+ list[0]->irq = platform_get_irq_byname(pdev, "dsp");
+ list[1]->irq = platform_get_irq_byname(pdev, "iva");
}
+#endif
+#if defined(CONFIG_ARCH_OMAP4)
+ else if (cpu_is_omap44xx()) {
+ list = omap4_mboxes;
- privblk = priv = kzalloc(pdata->info_cnt * sizeof(*priv), GFP_KERNEL);
- if (!privblk) {
- ret = -ENOMEM;
- goto free_mboxblk;
+ list[0]->irq = list[1]->irq = platform_get_irq(pdev, 0);
}
-
- 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);
- list[i] = mbox++;
+#endif
+ else {
+ pr_err("%s: platform not supported\n", __func__);
+ return -ENODEV;
}
mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- if (!mem) {
- ret = -ENOMEM;
- goto free_privblk;
- }
-
mbox_base = ioremap(mem->start, resource_size(mem));
- if (!mbox_base) {
- ret = -ENOMEM;
- goto free_privblk;
- }
+ if (!mbox_base)
+ return -ENOMEM;
- ret = mailbox_register(&pdev->dev, list);
- if (ret)
- goto unmap_mbox;
- platform_set_drvdata(pdev, list);
+ ret = omap_mbox_register(&pdev->dev, list);
+ if (ret) {
+ iounmap(mbox_base);
+ return ret;
+ }
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 mailbox **list = platform_get_drvdata(pdev);
- struct mailbox *mboxblk = list[0];
-
- privblk = mboxblk->priv;
- mailbox_unregister();
+ omap_mbox_unregister();
iounmap(mbox_base);
- kfree(privblk);
- kfree(mboxblk);
- kfree(list);
- platform_set_drvdata(pdev, NULL);
-
return 0;
}
static struct platform_driver omap2_mbox_driver = {
- .probe = omap2_mbox_probe,
- .remove = omap2_mbox_remove,
- .driver = {
+ .probe = omap2_mbox_probe,
+ .remove = omap2_mbox_remove,
+ .driver = {
.name = "omap-mailbox",
},
};
#include <linux/i2c-omap.h>
#include <linux/platform_data/spi-omap2-mcspi.h>
#include <linux/omap-dma.h>
-#include <linux/platform_data/mailbox-omap.h>
#include <plat/dmtimer.h>
#include "omap_hwmod.h"
};
/* mailbox */
-static struct omap_mbox_dev_info omap2420_mailbox_info[] = {
- { .name = "dsp", .tx_id = 0, .rx_id = 1, .irq_id = 0, .usr_id = 0 },
- { .name = "iva", .tx_id = 2, .rx_id = 3, .irq_id = 1, .usr_id = 3 },
-};
-
-static struct omap_mbox_pdata omap2420_mailbox_attrs = {
- .info_cnt = ARRAY_SIZE(omap2420_mailbox_info),
- .info = omap2420_mailbox_info,
-};
-
static struct omap_hwmod_irq_info omap2420_mailbox_irqs[] = {
{ .name = "dsp", .irq = 26 + OMAP_INTC_START, },
{ .name = "iva", .irq = 34 + OMAP_INTC_START, },
.idlest_idle_bit = OMAP24XX_ST_MAILBOXES_SHIFT,
},
},
- .dev_attr = &omap2420_mailbox_attrs,
};
/*
#include <linux/platform_data/asoc-ti-mcbsp.h>
#include <linux/platform_data/spi-omap2-mcspi.h>
#include <linux/omap-dma.h>
-#include <linux/platform_data/mailbox-omap.h>
#include <plat/dmtimer.h>
#include "omap_hwmod.h"
};
/* mailbox */
-static struct omap_mbox_dev_info omap2430_mailbox_info[] = {
- { .name = "dsp", .tx_id = 0, .rx_id = 1 },
-};
-
-static struct omap_mbox_pdata omap2430_mailbox_attrs = {
- .info_cnt = ARRAY_SIZE(omap2430_mailbox_info),
- .info = omap2430_mailbox_info,
-};
-
static struct omap_hwmod_irq_info omap2430_mailbox_irqs[] = {
{ .irq = 26 + OMAP_INTC_START, },
{ .irq = -1 },
.idlest_idle_bit = OMAP24XX_ST_MAILBOXES_SHIFT,
},
},
- .dev_attr = &omap2430_mailbox_attrs,
};
/* mcspi3 */
#include <linux/platform_data/asoc-ti-mcbsp.h>
#include <linux/platform_data/spi-omap2-mcspi.h>
#include <linux/platform_data/iommu-omap.h>
-#include <linux/platform_data/mailbox-omap.h>
#include <plat/dmtimer.h>
#include "am35xx.h"
.sysc = &omap3xxx_mailbox_sysc,
};
-static struct omap_mbox_dev_info omap3xxx_mailbox_info[] = {
- { .name = "dsp", .tx_id = 0, .rx_id = 1 },
-};
-
-static struct omap_mbox_pdata omap3xxx_mailbox_attrs = {
- .info_cnt = ARRAY_SIZE(omap3xxx_mailbox_info),
- .info = omap3xxx_mailbox_info,
-};
-
static struct omap_hwmod_irq_info omap3xxx_mailbox_irqs[] = {
{ .irq = 26 + OMAP_INTC_START, },
{ .irq = -1 },
.idlest_idle_bit = OMAP3430_ST_MAILBOXES_SHIFT,
},
},
- .dev_attr = &omap3xxx_mailbox_attrs,
};
/*
#include <linux/platform_data/spi-omap2-mcspi.h>
#include <linux/platform_data/asoc-ti-mcbsp.h>
#include <linux/platform_data/iommu-omap.h>
-#include <linux/platform_data/mailbox-omap.h>
#include <plat/dmtimer.h>
#include "omap_hwmod.h"
};
/* mailbox */
-static struct omap_mbox_dev_info omap44xx_mailbox_info[] = {
- { .name = "mbox-ipu", .tx_id = 0, .rx_id = 1 },
- { .name = "mbox-dsp", .tx_id = 3, .rx_id = 2 },
-};
-
-static struct omap_mbox_pdata omap44xx_mailbox_attrs = {
- .intr_type = MBOX_INTR_CFG_TYPE2,
- .info_cnt = ARRAY_SIZE(omap44xx_mailbox_info),
- .info = omap44xx_mailbox_info,
-};
-
static struct omap_hwmod_irq_info omap44xx_mailbox_irqs[] = {
{ .irq = 26 + OMAP44XX_IRQ_GIC_START },
{ .irq = -1 }
.context_offs = OMAP4_RM_L4CFG_MAILBOX_CONTEXT_OFFSET,
},
},
- .dev_attr = &omap44xx_mailbox_attrs,
};
/*
to change the pin multiplexing setup. When there are no warnings
printed, it's safe to deselect OMAP_MUX for your product.
+config OMAP_MBOX_FWK
+ tristate "Mailbox framework support"
+ depends on ARCH_OMAP && !ARCH_MULTIPLATFORM
+ help
+ Say Y here if you want to use OMAP Mailbox framework support for
+ DSP, IVA1.0 and IVA2 in OMAP1/2/3.
+
+config OMAP_MBOX_KFIFO_SIZE
+ int "Mailbox kfifo default buffer size (bytes)"
+ depends on OMAP_MBOX_FWK
+ default 256
+ help
+ Specify the default size of mailbox's kfifo buffers (bytes).
+ This can also be changed at runtime (via the mbox_kfifo_size
+ module parameter).
+
config OMAP_IOMMU_IVA2
bool
i2c-omap-$(CONFIG_I2C_OMAP) := i2c.o
obj-y += $(i2c-omap-m) $(i2c-omap-y)
+# OMAP mailbox framework
+obj-$(CONFIG_OMAP_MBOX_FWK) += mailbox.o
+
--- /dev/null
+/* mailbox.h */
+
+#ifndef MAILBOX_H
+#define MAILBOX_H
+
+#include <linux/spinlock.h>
+#include <linux/workqueue.h>
+#include <linux/interrupt.h>
+#include <linux/device.h>
+#include <linux/kfifo.h>
+
+typedef u32 mbox_msg_t;
+struct omap_mbox;
+
+typedef int __bitwise omap_mbox_irq_t;
+#define IRQ_TX ((__force omap_mbox_irq_t) 1)
+#define IRQ_RX ((__force omap_mbox_irq_t) 2)
+
+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 {
+ char *name;
+ unsigned 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_msg_send(struct omap_mbox *, mbox_msg_t msg);
+void omap_mbox_init_seq(struct omap_mbox *);
+
+struct omap_mbox *omap_mbox_get(const char *, struct notifier_block *nb);
+void omap_mbox_put(struct omap_mbox *mbox, struct notifier_block *nb);
+
+int omap_mbox_register(struct device *parent, struct omap_mbox **);
+int omap_mbox_unregister(void);
+
+static inline void omap_mbox_save_ctx(struct omap_mbox *mbox)
+{
+ if (!mbox->ops->save_ctx) {
+ dev_err(mbox->dev, "%s:\tno save\n", __func__);
+ return;
+ }
+
+ mbox->ops->save_ctx(mbox);
+}
+
+static inline void omap_mbox_restore_ctx(struct omap_mbox *mbox)
+{
+ if (!mbox->ops->restore_ctx) {
+ dev_err(mbox->dev, "%s:\tno restore\n", __func__);
+ return;
+ }
+
+ mbox->ops->restore_ctx(mbox);
+}
+
+static inline void omap_mbox_enable_irq(struct omap_mbox *mbox,
+ omap_mbox_irq_t irq)
+{
+ mbox->ops->enable_irq(mbox, irq);
+}
+
+static inline void omap_mbox_disable_irq(struct omap_mbox *mbox,
+ omap_mbox_irq_t irq)
+{
+ mbox->ops->disable_irq(mbox, irq);
+}
+
+#endif /* MAILBOX_H */
--- /dev/null
+/*
+ * OMAP mailbox driver
+ *
+ * Copyright (C) 2006-2009 Nokia Corporation. All rights reserved.
+ *
+ * Contact: Hiroshi DOYU <Hiroshi.DOYU@nokia.com>
+ *
+ * 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.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ *
+ */
+
+#include <linux/interrupt.h>
+#include <linux/spinlock.h>
+#include <linux/mutex.h>
+#include <linux/delay.h>
+#include <linux/slab.h>
+#include <linux/kfifo.h>
+#include <linux/err.h>
+#include <linux/notifier.h>
+#include <linux/module.h>
+
+#include <plat/mailbox.h>
+
+static struct omap_mbox **mboxes;
+
+static int mbox_configured;
+static DEFINE_MUTEX(mbox_configured_lock);
+
+static unsigned int mbox_kfifo_size = CONFIG_OMAP_MBOX_KFIFO_SIZE;
+module_param(mbox_kfifo_size, uint, S_IRUGO);
+MODULE_PARM_DESC(mbox_kfifo_size, "Size of omap's mailbox kfifo (bytes)");
+
+/* Mailbox FIFO handle functions */
+static inline mbox_msg_t mbox_fifo_read(struct omap_mbox *mbox)
+{
+ return mbox->ops->fifo_read(mbox);
+}
+static inline void mbox_fifo_write(struct omap_mbox *mbox, mbox_msg_t msg)
+{
+ mbox->ops->fifo_write(mbox, msg);
+}
+static inline int mbox_fifo_empty(struct omap_mbox *mbox)
+{
+ return mbox->ops->fifo_empty(mbox);
+}
+static inline int mbox_fifo_full(struct omap_mbox *mbox)
+{
+ return mbox->ops->fifo_full(mbox);
+}
+
+/* Mailbox IRQ handle functions */
+static inline void ack_mbox_irq(struct omap_mbox *mbox, omap_mbox_irq_t irq)
+{
+ if (mbox->ops->ack_irq)
+ mbox->ops->ack_irq(mbox, irq);
+}
+static inline int is_mbox_irq(struct omap_mbox *mbox, omap_mbox_irq_t irq)
+{
+ return mbox->ops->is_irq(mbox, irq);
+}
+
+/*
+ * 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)
+{
+ struct omap_mbox_queue *mq = mbox->txq;
+ int ret = 0, len;
+
+ spin_lock_bh(&mq->lock);
+
+ if (kfifo_avail(&mq->fifo) < sizeof(msg)) {
+ ret = -ENOMEM;
+ goto out;
+ }
+
+ if (kfifo_is_empty(&mq->fifo) && !__mbox_poll_for_space(mbox)) {
+ mbox_fifo_write(mbox, msg);
+ goto out;
+ }
+
+ len = kfifo_in(&mq->fifo, (unsigned char *)&msg, sizeof(msg));
+ WARN_ON(len != sizeof(msg));
+
+ tasklet_schedule(&mbox->txq->tasklet);
+
+out:
+ spin_unlock_bh(&mq->lock);
+ return ret;
+}
+EXPORT_SYMBOL(omap_mbox_msg_send);
+
+static void mbox_tx_tasklet(unsigned long tx_data)
+{
+ struct omap_mbox *mbox = (struct omap_mbox *)tx_data;
+ struct omap_mbox_queue *mq = mbox->txq;
+ mbox_msg_t msg;
+ int ret;
+
+ while (kfifo_len(&mq->fifo)) {
+ if (__mbox_poll_for_space(mbox)) {
+ omap_mbox_enable_irq(mbox, IRQ_TX);
+ break;
+ }
+
+ ret = kfifo_out(&mq->fifo, (unsigned char *)&msg,
+ sizeof(msg));
+ WARN_ON(ret != sizeof(msg));
+
+ mbox_fifo_write(mbox, msg);
+ }
+}
+
+/*
+ * Message receiver(workqueue)
+ */
+static void mbox_rx_work(struct work_struct *work)
+{
+ struct omap_mbox_queue *mq =
+ container_of(work, struct omap_mbox_queue, work);
+ mbox_msg_t msg;
+ int len;
+
+ while (kfifo_len(&mq->fifo) >= sizeof(msg)) {
+ len = kfifo_out(&mq->fifo, (unsigned char *)&msg, sizeof(msg));
+ WARN_ON(len != sizeof(msg));
+
+ blocking_notifier_call_chain(&mq->mbox->notifier, len,
+ (void *)msg);
+ spin_lock_irq(&mq->lock);
+ if (mq->full) {
+ mq->full = false;
+ omap_mbox_enable_irq(mq->mbox, IRQ_RX);
+ }
+ spin_unlock_irq(&mq->lock);
+ }
+}
+
+/*
+ * Mailbox interrupt handler
+ */
+static void __mbox_tx_interrupt(struct omap_mbox *mbox)
+{
+ omap_mbox_disable_irq(mbox, IRQ_TX);
+ ack_mbox_irq(mbox, IRQ_TX);
+ tasklet_schedule(&mbox->txq->tasklet);
+}
+
+static void __mbox_rx_interrupt(struct omap_mbox *mbox)
+{
+ struct omap_mbox_queue *mq = mbox->rxq;
+ mbox_msg_t msg;
+ int len;
+
+ while (!mbox_fifo_empty(mbox)) {
+ if (unlikely(kfifo_avail(&mq->fifo) < sizeof(msg))) {
+ omap_mbox_disable_irq(mbox, IRQ_RX);
+ mq->full = true;
+ goto nomem;
+ }
+
+ msg = mbox_fifo_read(mbox);
+
+ len = kfifo_in(&mq->fifo, (unsigned char *)&msg, sizeof(msg));
+ WARN_ON(len != sizeof(msg));
+
+ if (mbox->ops->type == OMAP_MBOX_TYPE1)
+ break;
+ }
+
+ /* no more messages in the fifo. clear IRQ source. */
+ ack_mbox_irq(mbox, IRQ_RX);
+nomem:
+ schedule_work(&mbox->rxq->work);
+}
+
+static irqreturn_t mbox_interrupt(int irq, void *p)
+{
+ struct omap_mbox *mbox = p;
+
+ if (is_mbox_irq(mbox, IRQ_TX))
+ __mbox_tx_interrupt(mbox);
+
+ if (is_mbox_irq(mbox, IRQ_RX))
+ __mbox_rx_interrupt(mbox);
+
+ return IRQ_HANDLED;
+}
+
+static struct omap_mbox_queue *mbox_queue_alloc(struct omap_mbox *mbox,
+ void (*work) (struct work_struct *),
+ void (*tasklet)(unsigned long))
+{
+ struct omap_mbox_queue *mq;
+
+ mq = kzalloc(sizeof(struct omap_mbox_queue), GFP_KERNEL);
+ if (!mq)
+ return NULL;
+
+ spin_lock_init(&mq->lock);
+
+ if (kfifo_alloc(&mq->fifo, mbox_kfifo_size, GFP_KERNEL))
+ goto error;
+
+ if (work)
+ INIT_WORK(&mq->work, work);
+
+ if (tasklet)
+ tasklet_init(&mq->tasklet, tasklet, (unsigned long)mbox);
+ return mq;
+error:
+ kfree(mq);
+ return NULL;
+}
+
+static void mbox_queue_free(struct omap_mbox_queue *q)
+{
+ kfifo_free(&q->fifo);
+ kfree(q);
+}
+
+static int omap_mbox_startup(struct omap_mbox *mbox)
+{
+ int ret = 0;
+ struct omap_mbox_queue *mq;
+
+ 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;
+ }
+
+ if (!mbox->use_count++) {
+ ret = request_irq(mbox->irq, mbox_interrupt, IRQF_SHARED,
+ mbox->name, mbox);
+ if (unlikely(ret)) {
+ pr_err("failed to register mailbox interrupt:%d\n",
+ ret);
+ goto fail_request_irq;
+ }
+ mq = mbox_queue_alloc(mbox, NULL, mbox_tx_tasklet);
+ if (!mq) {
+ ret = -ENOMEM;
+ goto fail_alloc_txq;
+ }
+ mbox->txq = mq;
+
+ mq = mbox_queue_alloc(mbox, mbox_rx_work, NULL);
+ if (!mq) {
+ ret = -ENOMEM;
+ goto fail_alloc_rxq;
+ }
+ mbox->rxq = mq;
+ mq->mbox = mbox;
+
+ omap_mbox_enable_irq(mbox, IRQ_RX);
+ }
+ mutex_unlock(&mbox_configured_lock);
+ return 0;
+
+fail_alloc_rxq:
+ mbox_queue_free(mbox->txq);
+fail_alloc_txq:
+ free_irq(mbox->irq, mbox);
+fail_request_irq:
+ if (mbox->ops->shutdown)
+ mbox->ops->shutdown(mbox);
+ mbox->use_count--;
+fail_startup:
+ mbox_configured--;
+ mutex_unlock(&mbox_configured_lock);
+ return ret;
+}
+
+static void omap_mbox_fini(struct omap_mbox *mbox)
+{
+ mutex_lock(&mbox_configured_lock);
+
+ if (!--mbox->use_count) {
+ omap_mbox_disable_irq(mbox, IRQ_RX);
+ free_irq(mbox->irq, mbox);
+ tasklet_kill(&mbox->txq->tasklet);
+ flush_work(&mbox->rxq->work);
+ mbox_queue_free(mbox->txq);
+ mbox_queue_free(mbox->rxq);
+ }
+
+ if (likely(mbox->ops->shutdown)) {
+ if (!--mbox_configured)
+ mbox->ops->shutdown(mbox);
+ }
+
+ mutex_unlock(&mbox_configured_lock);
+}
+
+struct omap_mbox *omap_mbox_get(const char *name, struct notifier_block *nb)
+{
+ struct omap_mbox *_mbox, *mbox = NULL;
+ int i, ret;
+
+ if (!mboxes)
+ return ERR_PTR(-EINVAL);
+
+ for (i = 0; (_mbox = mboxes[i]); i++) {
+ if (!strcmp(_mbox->name, name)) {
+ mbox = _mbox;
+ break;
+ }
+ }
+
+ if (!mbox)
+ return ERR_PTR(-ENOENT);
+
+ if (nb)
+ blocking_notifier_chain_register(&mbox->notifier, nb);
+
+ ret = omap_mbox_startup(mbox);
+ if (ret) {
+ blocking_notifier_chain_unregister(&mbox->notifier, nb);
+ return ERR_PTR(-ENODEV);
+ }
+
+ return mbox;
+}
+EXPORT_SYMBOL(omap_mbox_get);
+
+void omap_mbox_put(struct omap_mbox *mbox, struct notifier_block *nb)
+{
+ blocking_notifier_chain_unregister(&mbox->notifier, nb);
+ omap_mbox_fini(mbox);
+}
+EXPORT_SYMBOL(omap_mbox_put);
+
+static struct class omap_mbox_class = { .name = "mbox", };
+
+int omap_mbox_register(struct device *parent, struct omap_mbox **list)
+{
+ int ret;
+ int i;
+
+ mboxes = list;
+ if (!mboxes)
+ return -EINVAL;
+
+ for (i = 0; mboxes[i]; i++) {
+ struct omap_mbox *mbox = mboxes[i];
+ mbox->dev = device_create(&omap_mbox_class,
+ parent, 0, mbox, "%s", mbox->name);
+ if (IS_ERR(mbox->dev)) {
+ ret = PTR_ERR(mbox->dev);
+ goto err_out;
+ }
+
+ BLOCKING_INIT_NOTIFIER_HEAD(&mbox->notifier);
+ }
+ return 0;
+
+err_out:
+ while (i--)
+ device_unregister(mboxes[i]->dev);
+ return ret;
+}
+EXPORT_SYMBOL(omap_mbox_register);
+
+int omap_mbox_unregister(void)
+{
+ int i;
+
+ if (!mboxes)
+ return -EINVAL;
+
+ for (i = 0; mboxes[i]; i++)
+ device_unregister(mboxes[i]->dev);
+ mboxes = NULL;
+ return 0;
+}
+EXPORT_SYMBOL(omap_mbox_unregister);
+
+static int __init omap_mbox_init(void)
+{
+ int err;
+
+ err = class_register(&omap_mbox_class);
+ if (err)
+ return err;
+
+ /* kfifo size sanity check: alignment and minimal size */
+ mbox_kfifo_size = ALIGN(mbox_kfifo_size, sizeof(mbox_msg_t));
+ mbox_kfifo_size = max_t(unsigned int, mbox_kfifo_size,
+ sizeof(mbox_msg_t));
+
+ return 0;
+}
+subsys_initcall(omap_mbox_init);
+
+static void __exit omap_mbox_exit(void)
+{
+ class_unregister(&omap_mbox_class);
+}
+module_exit(omap_mbox_exit);
+
+MODULE_LICENSE("GPL v2");
+MODULE_DESCRIPTION("omap mailbox: interrupt driven messaging");
+MODULE_AUTHOR("Toshihiro Kobayashi");
+MODULE_AUTHOR("Hiroshi DOYU");
#include <linux/cpu.h>
#include <linux/err.h>
#include <linux/of.h>
-#include <linux/pl320-ipc.h>
+#include <linux/mailbox.h>
#include <linux/platform_device.h>
#define HB_CPUFREQ_CHANGE_NOTE 0x80000001
Management Engine, primarily for cpufreq. Say Y here if you want
to use the PL320 IPCM support.
-config OMAP1_MBOX
- tristate "OMAP1 Mailbox framework support"
- depends on ARCH_OMAP1
- 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
- tristate "OMAP2+ Mailbox framework support"
- depends on ARCH_OMAP2PLUS
- help
- Mailbox implementation for OMAP family chips with hardware for
- interprocessor communication involving DSP, IVA1.0 and IVA2 in
- OMAP2/3; or IPU, IVA HD and DSP in OMAP4. Say Y here if you want
- to use OMAP2+ Mailbox framework support.
-
-config DBX500_MBOX
- tristate "DBx500 Mailbox driver support"
- depends on ARCH_U8500
- help
- Say Y here if you want to use DBx500 Mailbox driver support for
- power coprocessor access on Ux500 and Ux540 families
-
-config MBOX_KFIFO_SIZE
- int "Mailbox kfifo default buffer size (bytes)"
- default 256
- help
- Specify the default size of mailbox's kfifo buffers (bytes).
- This can also be changed at runtime (via the mbox_kfifo_size
- module parameter).
-
-config MBOX_DATA_SIZE
- int "Mailbox associated data max size (bytes)"
- default 64 if DBX500_MBOX
- default 4
- help
- Specify the default size of mailbox's associated data buffer
- (bytes)
- This can also be changed at runtime (via the mbox_kfifo_size
- module parameter).
endif
obj-$(CONFIG_PL320_MBOX) += pl320-ipc.o
-
-obj-$(CONFIG_MAILBOX) += mailbox.o
-obj-$(CONFIG_OMAP1_MBOX) += mailbox-omap1.o
-obj-$(CONFIG_OMAP2PLUS_MBOX) += mailbox-omap2.o
-obj-$(CONFIG_DBX500_MBOX) += mailbox-dbx500.o
+++ /dev/null
-/*
- * Copyright (C) ST-Ericsson SA 2012
- *
- * License Terms: GNU General Public License v2
- * Author: Loic Pallardy <loic.pallardy@st.com> for ST-Ericsson
- * DBX500 PRCM Mailbox driver
- *
- */
-
-#include <linux/module.h>
-#include <linux/err.h>
-#include <linux/platform_device.h>
-#include <linux/irq.h>
-#include <linux/io.h>
-#include <linux/platform_data/mailbox-dbx500.h>
-#include <linux/of.h>
-#include <linux/of_device.h>
-#include <linux/irqdomain.h>
-
-#include "mailbox_internal.h"
-
-#define MAILBOX_LEGACY 0
-#define MAILBOX_UPAP 1
-
-enum {
- MAILBOX_BLOCKING,
- MAILBOX_ATOMIC,
-};
-
-/* CPU mailbox registers */
-#define PRCM_MBOX_CPU_VAL 0x0fc
-#define PRCM_MBOX_CPU_SET 0x100
-#define PRCM_MBOX_CPU_CLR 0x104
-
-#define PRCM_ARM_IT1_CLR 0x48C
-#define PRCM_ARM_IT1_VAL 0x494
-
-#define NUM_MB 8
-#define MBOX_BIT BIT
-#define ALL_MBOX_BITS (MBOX_BIT(NUM_MB) - 1)
-
-/* CPU mailbox shared memory */
-#define PRCM_MBOX_LEGACY_SIZE 0x220
-#define _PRCM_MBOX_HEADER 0x214 /* 16 bytes */
-#define PRCM_MBOX_HEADER_REQ_MB0 (_PRCM_MBOX_HEADER + 0x0)
-#define PRCM_MBOX_HEADER_REQ_MB1 (_PRCM_MBOX_HEADER + 0x1)
-#define PRCM_MBOX_HEADER_REQ_MB2 (_PRCM_MBOX_HEADER + 0x2)
-#define PRCM_MBOX_HEADER_REQ_MB3 (_PRCM_MBOX_HEADER + 0x3)
-#define PRCM_MBOX_HEADER_REQ_MB4 (_PRCM_MBOX_HEADER + 0x4)
-#define PRCM_MBOX_HEADER_REQ_MB5 (_PRCM_MBOX_HEADER + 0x5)
-#define PRCM_MBOX_HEADER_ACK_MB0 (_PRCM_MBOX_HEADER + 0x8)
-
-/* Req Mailboxes */
-#define PRCM_REQ_MB0 0x208 /* 12 bytes */
-#define PRCM_REQ_MB1 0x1FC /* 12 bytes */
-#define PRCM_REQ_MB2 0x1EC /* 16 bytes */
-#define PRCM_REQ_MB3 0x78 /* 372 bytes */
-#define PRCM_REQ_MB4 0x74 /* 4 bytes */
-#define PRCM_REQ_MB5 0x70 /* 4 bytes */
-#define PRCM_REQ_PASR 0x30 /* 4 bytes */
-
-/* Ack Mailboxes */
-#define PRCM_ACK_MB0 0x34 /* 52 bytes */
-#define PRCM_ACK_MB1 0x30 /* 4 bytes */
-#define PRCM_ACK_MB2 0x2C /* 4 bytes */
-#define PRCM_ACK_MB3 0x28 /* 4 bytes */
-#define PRCM_ACK_MB4 0x24 /* 4 bytes */
-#define PRCM_ACK_MB5 0x20 /* 4 bytes */
-
-/* Ack Mailboxe sizes */
-#define PRCM_ACK_MB0_SIZE 0x24 /* 52 bytes */
-#define PRCM_ACK_MB1_SIZE 0x4 /* 4 bytes */
-#define PRCM_ACK_MB2_SIZE 0x1 /* 1 bytes */
-#define PRCM_ACK_MB3_SIZE 0x2 /* 2 bytes */
-#define PRCM_ACK_MB4_SIZE 0x0 /* 0 bytes */
-#define PRCM_ACK_MB5_SIZE 0x4 /* 4 bytes */
-
-static void __iomem *mbox_base;
-static void __iomem *tcdm_mem_base;
-
-static u8 prcm_mbox_irq_mask; /* masked by default */
-static DEFINE_SPINLOCK(prcm_mbox_irqs_lock);
-
-struct dbx500_mbox_priv {
- int access_mode;
- int type;
- int header_size;
- unsigned int tx_header_offset;
- unsigned int rx_header_offset;
- unsigned int tx_offset;
- unsigned int rx_offset;
- unsigned int rx_size;
- unsigned int sw_irq;
- bool empty_flag;
-};
-
-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 struct irq_chip dbx500_mbox_irq_chip;
-static struct irq_domain *dbx500_mbox_irq_domain;
-
-static int dbx500_mbox_startup(struct mailbox *mbox)
-{
- /* Nothing to do */
- return 0;
-}
-
-/* Mailbox IRQ handle functions */
-
-static void dbx500_mbox_enable_irq(struct mailbox *mbox, mailbox_irq_t irq)
-{
- unsigned long flags;
-
- spin_lock_irqsave(&prcm_mbox_irqs_lock, flags);
-
- prcm_mbox_irq_mask |= MBOX_BIT(mbox->id);
-
- spin_unlock_irqrestore(&prcm_mbox_irqs_lock, flags);
-
-}
-
-static void dbx500_mbox_disable_irq(struct mailbox *mbox, mailbox_irq_t irq)
-{
- unsigned long flags;
-
- spin_lock_irqsave(&prcm_mbox_irqs_lock, flags);
-
- prcm_mbox_irq_mask &= ~MBOX_BIT(mbox->id);
-
- spin_unlock_irqrestore(&prcm_mbox_irqs_lock, flags);
-
-}
-
-static void dbx500_mbox_ack_irq(struct mailbox *mbox, mailbox_irq_t irq)
-{
- if (irq == IRQ_RX)
- mbox_write_reg(MBOX_BIT(mbox->id), PRCM_ARM_IT1_CLR);
-}
-
-static int dbx500_mbox_is_irq(struct mailbox *mbox, mailbox_irq_t irq)
-{
- struct dbx500_mbox_priv *priv = (struct dbx500_mbox_priv *)mbox->priv;
-
- if (irq == IRQ_RX) {
- if (mbox_read_reg(PRCM_ARM_IT1_VAL) & MBOX_BIT(mbox->id)) {
- priv->empty_flag = true;
- return 1;
- } else {
- return 0;
- }
- } else {
- return 0;
- }
-}
-
-/* message management */
-
-static int dbx500_mbox_is_ready(struct mailbox *mbox)
-{
- return mbox_read_reg(PRCM_MBOX_CPU_VAL) & MBOX_BIT(mbox->id);
-}
-
-static int dbx500_mbox_write(struct mailbox *mbox,
- struct mailbox_msg *msg)
-{
- int j;
- struct dbx500_mbox_priv *priv = (struct dbx500_mbox_priv *)mbox->priv;
-
- if (msg->size && !msg->pdata)
- return -EINVAL;
-
- while (dbx500_mbox_is_ready(mbox))
- cpu_relax();
-
- /* write header */
- if (priv->header_size)
- writeb(msg->header, tcdm_mem_base + priv->tx_header_offset);
-
- /* write data */
- for (j = 0; j < msg->size; j++)
- writeb(((unsigned char *)msg->pdata)[j],
- tcdm_mem_base + priv->tx_offset + j);
-
- /* send event */
- mbox_write_reg(MBOX_BIT(mbox->id), PRCM_MBOX_CPU_SET);
-
- return 0;
-}
-
-static void dbx500_mbox_read(struct mailbox *mbox, struct mailbox_msg *msg)
-{
- struct dbx500_mbox_priv *priv = (struct dbx500_mbox_priv *)mbox->priv;
-
- msg->header = readb(tcdm_mem_base + priv->rx_header_offset);
- msg->pdata = (unsigned char *)(tcdm_mem_base + priv->rx_offset);
-
- msg->size = priv->rx_size;
- priv->empty_flag = false;
-}
-
-static int dbx500_mbox_empty(struct mailbox *mbox)
-{
- struct dbx500_mbox_priv *priv = (struct dbx500_mbox_priv *)mbox->priv;
- if (priv->empty_flag)
- return 0;
- else
- return 1;
-}
-
-static int dbx500_mbox_poll_for_space(struct mailbox *mbox)
-{
- return 0;
-}
-/* interrupt management */
-
-/* mask/unmask must be managed by SW */
-
-static void mbox_irq_mask(struct irq_data *d)
-{
- unsigned long flags;
-
- spin_lock_irqsave(&prcm_mbox_irqs_lock, flags);
-
- prcm_mbox_irq_mask &= ~MBOX_BIT(d->hwirq);
-
- spin_unlock_irqrestore(&prcm_mbox_irqs_lock, flags);
-}
-
-static void mbox_irq_unmask(struct irq_data *d)
-{
- unsigned long flags;
-
- spin_lock_irqsave(&prcm_mbox_irqs_lock, flags);
-
- prcm_mbox_irq_mask |= MBOX_BIT(d->hwirq);
-
- spin_unlock_irqrestore(&prcm_mbox_irqs_lock, flags);
-}
-
-static void mbox_irq_ack(struct irq_data *d)
-{
- mbox_write_reg(MBOX_BIT(d->hwirq), PRCM_ARM_IT1_CLR);
-}
-
-static struct irq_chip dbx500_mbox_irq_chip = {
- .name = "dbx500_mbox",
- .irq_disable = mbox_irq_unmask,
- .irq_ack = mbox_irq_ack,
- .irq_mask = mbox_irq_mask,
- .irq_unmask = mbox_irq_unmask,
-};
-
-static int dbx500_mbox_irq_map(struct irq_domain *d, unsigned int irq,
- irq_hw_number_t hwirq)
-{
- irq_set_chip_and_handler(irq, &dbx500_mbox_irq_chip,
- handle_simple_irq);
- set_irq_flags(irq, IRQF_VALID);
-
- return 0;
-}
-
-static struct irq_domain_ops dbx500_mbox_irq_ops = {
- .map = dbx500_mbox_irq_map,
- .xlate = irq_domain_xlate_twocell,
-};
-
-static irqreturn_t dbx500_mbox_irq_handler(int irq, void *data)
-{
- u32 bits;
- u8 n;
-
- bits = (mbox_read_reg(PRCM_ARM_IT1_VAL) & ALL_MBOX_BITS);
- if (unlikely(!bits))
- return IRQ_NONE;
-
- bits &= prcm_mbox_irq_mask;
-
- for (n = 0; bits; n++) {
- if (bits & MBOX_BIT(n)) {
- bits -= MBOX_BIT(n);
- generic_handle_irq(
- irq_find_mapping(dbx500_mbox_irq_domain, n));
- }
- }
- return IRQ_HANDLED;
-}
-
-/* 5 mailboxes AP <--> PRCMU */
-static struct mailbox_ops dbx500_mbox_ops = {
- .type = MBOX_SHARED_MEM_TYPE,
- .startup = dbx500_mbox_startup,
- .enable_irq = dbx500_mbox_enable_irq,
- .disable_irq = dbx500_mbox_disable_irq,
- .ack_irq = dbx500_mbox_ack_irq,
- .is_irq = dbx500_mbox_is_irq,
- .read = dbx500_mbox_read,
- .write = dbx500_mbox_write,
- .empty = dbx500_mbox_empty,
- .poll_for_space = dbx500_mbox_poll_for_space,
-};
-
-struct dbx500_mbox_priv mbox0_priv = {
- .access_mode = MAILBOX_ATOMIC,
- .type = MAILBOX_LEGACY,
- .tx_header_offset = PRCM_MBOX_HEADER_REQ_MB0,
- .header_size = 1,
- .tx_offset = PRCM_REQ_MB0,
- .rx_header_offset = PRCM_MBOX_HEADER_ACK_MB0,
- .rx_offset = PRCM_ACK_MB0,
- .rx_size = PRCM_ACK_MB0_SIZE,
-};
-
-struct mailbox mbox0_info = {
- .name = "mbox0",
- .id = 0,
- .ops = &dbx500_mbox_ops,
- .priv = &mbox0_priv,
-};
-
-struct dbx500_mbox_priv mbox1_priv = {
- .access_mode = MAILBOX_BLOCKING,
- .type = MAILBOX_LEGACY,
- .tx_header_offset = PRCM_MBOX_HEADER_REQ_MB1,
- .header_size = 1,
- .tx_offset = PRCM_REQ_MB1,
- .rx_header_offset = PRCM_MBOX_HEADER_REQ_MB1,
- .rx_offset = PRCM_ACK_MB1,
- .rx_size = PRCM_ACK_MB1_SIZE,
-};
-
-struct mailbox mbox1_info = {
- .name = "mbox1",
- .id = 1,
- .ops = &dbx500_mbox_ops,
- .priv = &mbox1_priv,
-};
-
-struct dbx500_mbox_priv mbox2_priv = {
- .access_mode = MAILBOX_BLOCKING,
- .type = MAILBOX_LEGACY,
- .tx_header_offset = PRCM_MBOX_HEADER_REQ_MB2,
- .header_size = 1,
- .tx_offset = PRCM_REQ_MB2,
- .rx_header_offset = PRCM_MBOX_HEADER_REQ_MB2,
- .rx_offset = PRCM_ACK_MB2,
- .rx_size = PRCM_ACK_MB2_SIZE,
-};
-
-struct mailbox mbox2_info = {
- .name = "mbox2",
- .id = 2,
- .ops = &dbx500_mbox_ops,
- .priv = &mbox2_priv,
-};
-
-struct dbx500_mbox_priv mbox3_priv = {
- .access_mode = MAILBOX_BLOCKING,
- .type = MAILBOX_LEGACY,
- .tx_header_offset = PRCM_MBOX_HEADER_REQ_MB3,
- .header_size = 1,
- .tx_offset = PRCM_REQ_MB3,
- .rx_header_offset = PRCM_MBOX_HEADER_REQ_MB3,
- .rx_offset = PRCM_ACK_MB3,
- .rx_size = PRCM_ACK_MB3_SIZE,
-};
-
-struct mailbox mbox3_info = {
- .name = "mbox3",
- .id = 3,
- .ops = &dbx500_mbox_ops,
- .priv = &mbox3_priv,
-};
-
-struct dbx500_mbox_priv mbox4_priv = {
- .access_mode = MAILBOX_BLOCKING,
- .type = MAILBOX_LEGACY,
- .tx_header_offset = PRCM_MBOX_HEADER_REQ_MB4,
- .header_size = 1,
- .tx_offset = PRCM_REQ_MB4,
- .rx_header_offset = PRCM_MBOX_HEADER_REQ_MB4,
- .rx_offset = PRCM_ACK_MB4,
- .rx_size = PRCM_ACK_MB4_SIZE,
-};
-
-struct mailbox mbox4_info = {
- .name = "mbox4",
- .id = 4,
- .ops = &dbx500_mbox_ops,
- .priv = &mbox4_priv,
-};
-
-struct dbx500_mbox_priv mbox5_priv = {
- .access_mode = MAILBOX_BLOCKING,
- .type = MAILBOX_LEGACY,
- .tx_header_offset = PRCM_MBOX_HEADER_REQ_MB5,
- .header_size = 1,
- .tx_offset = PRCM_REQ_MB5,
- .rx_header_offset = PRCM_MBOX_HEADER_REQ_MB5,
- .rx_offset = PRCM_ACK_MB5,
- .rx_size = PRCM_ACK_MB5_SIZE,
-};
-
-struct mailbox mbox5_info = {
- .name = "mbox5",
- .id = 5,
- .ops = &dbx500_mbox_ops,
- .priv = &mbox5_priv,
-};
-
-struct mailbox mbox6_info = {
- .name = "mbox6",
- .id = 6,
- .ops = &dbx500_mbox_ops,
-};
-
-struct mailbox mbox7_info = {
- .name = "mbox7",
- .id = 7,
- .ops = &dbx500_mbox_ops,
-};
-
-/* x540 mailbox definition */
-struct dbx500_mbox_priv mbox1_upap_priv = {
- .access_mode = MAILBOX_BLOCKING,
- .type = MAILBOX_UPAP,
- .tx_header_offset = 0,
- .header_size = 0,
- .tx_offset = 0,
- .rx_offset = 0, /* TODO to be replaced by dynamic detection */
- .rx_size = 0x40,
-};
-
-struct mailbox mbox1_upap_info = {
- .name = "mbox1_upap",
- .id = 1,
- .ops = &dbx500_mbox_ops,
- .priv = &mbox1_upap_priv,
-};
-
-struct mailbox *db8500_mboxes[] = { &mbox0_info, &mbox1_info, &mbox2_info,
- &mbox3_info, &mbox4_info, &mbox5_info, &mbox6_info, &mbox7_info,
- NULL };
-
-struct mailbox *dbx540_mboxes[] = { &mbox0_info, &mbox2_info,
- &mbox3_info, &mbox4_info, &mbox5_info, &mbox6_info, &mbox7_info,
- &mbox1_upap_info, NULL };
-
-static const struct of_device_id dbx500_mailbox_match[] = {
- { .compatible = "stericsson,db8500-mailbox",
- .data = (void *)db8500_mboxes,
- },
- { .compatible = "stericsson,db9540-mailbox",
- .data = (void *)dbx540_mboxes,
- },
- { /* sentinel */}
-};
-
-static int dbx500_mbox_probe(struct platform_device *pdev)
-{
- const struct platform_device_id *platid = platform_get_device_id(pdev);
- struct resource *mem;
- int ret, i, irq;
- u32 legacy_offset = 0;
- u32 upap_offset = 0, upap_size = PRCM_MBOX_LEGACY_SIZE;
- struct mailbox **list;
- struct dbx500_plat_data *pdata = dev_get_platdata(&pdev->dev);
- struct device_node *np = pdev->dev.of_node;
- bool upap_used = false;
-
- if (!pdata) {
- if (np) {
- if (of_property_read_u32(np, "legacy-offset",
- &legacy_offset)) {
- /* missing legacy-offset */
- dev_err(&pdev->dev, "No legacy offset found\n");
- return -ENODEV;
- }
- if (of_property_read_u32(np, "upap-offset",
- &upap_offset)) {
- dev_dbg(&pdev->dev, "No upap offset found\n");
- upap_offset = -1;
- }
- list = (struct mailbox **)of_match_device(
- dbx500_mailbox_match, &pdev->dev)->data;
- if (!list) {
- /* No mailbox configuration */
- dev_err(&pdev->dev, "No configuration found\n");
- return -ENODEV;
- }
- } else {
- /* No mailbox configuration */
- dev_err(&pdev->dev, "No configuration found\n");
- return -ENODEV;
- }
- } else {
- list = (struct mailbox **)platid->driver_data;
- legacy_offset = pdata->legacy_offset;
- upap_offset = pdata->upap_offset;
- }
-
- mem = platform_get_resource_byname(pdev, IORESOURCE_MEM, "prcm-reg");
- mbox_base = devm_ioremap(&pdev->dev, mem->start, resource_size(mem));
- if (!mbox_base) {
- ret = -ENOMEM;
- goto out;
- }
-
- mem = platform_get_resource_byname(pdev, IORESOURCE_MEM, "prcmu-tcdm");
- tcdm_mem_base = devm_ioremap(&pdev->dev, mem->start,
- resource_size(mem));
- if (!tcdm_mem_base) {
- ret = -ENOMEM;
- goto out;
- }
-
- /* check mailbox offset values */
- if (legacy_offset >= (resource_size(mem) - PRCM_MBOX_LEGACY_SIZE)) {
- dev_err(&pdev->dev, "Incorrect legacy offset value\n");
- ret = -EINVAL;
- goto out;
- }
-
- for (i = 0; list[i]; i++) {
- struct mailbox *mbox = list[i];
- struct dbx500_mbox_priv *priv =
- (struct dbx500_mbox_priv *)mbox->priv;
- if (!priv)
- continue;
- if (priv->type == MAILBOX_UPAP) {
- upap_used = true;
- upap_size += priv->rx_size;
- break;
- }
- }
-
- if (upap_used && (upap_offset >= (resource_size(mem) - upap_size))) {
- dev_err(&pdev->dev, "Incorrect upap offset value\n");
- ret = -EINVAL;
- goto out;
- }
-
- irq = platform_get_irq(pdev, 0);
- /* clean all mailboxes */
- mbox_write_reg(ALL_MBOX_BITS, PRCM_ARM_IT1_CLR);
- ret = request_irq(irq, dbx500_mbox_irq_handler,
- IRQF_NO_SUSPEND, "db8500_mbox", NULL);
- if (ret) {
- ret = -EINVAL;
- goto out;
- }
-
- dbx500_mbox_irq_domain = irq_domain_add_linear(
- np, NUM_MB, &dbx500_mbox_irq_ops, NULL);
-
- if (!dbx500_mbox_irq_domain) {
- dev_err(&pdev->dev, "Failed to create irqdomain\n");
- ret = -ENOSYS;
- goto irq_free;
- }
-
- /*
- * Update mailbox shared memory buffer offset according to mailbox
- * type
- */
- for (i = 0; list[i]; i++) {
- struct mailbox *mbox = list[i];
- struct dbx500_mbox_priv *priv =
- (struct dbx500_mbox_priv *)mbox->priv;
- if (!priv)
- continue;
- mbox->irq = irq_create_mapping(dbx500_mbox_irq_domain,
- mbox->id);
- if (priv->type == MAILBOX_LEGACY) {
- priv->rx_offset += legacy_offset;
- priv->rx_header_offset += legacy_offset;
- priv->tx_offset += legacy_offset;
- priv->tx_header_offset += legacy_offset;
- } else if (priv->type == MAILBOX_UPAP) {
- priv->tx_offset += upap_offset;
- priv->rx_offset += upap_offset;
- }
- }
-
- ret = mailbox_register(&pdev->dev, list);
-irq_free:
- if (ret)
- free_irq(irq, NULL);
-
-out:
- return ret;
-}
-
-static int dbx500_mbox_remove(struct platform_device *pdev)
-{
- mailbox_unregister();
- iounmap(mbox_base);
- return 0;
-}
-
-static const struct platform_device_id dbx500_mbox_id[] = {
- {
- .name = "db8500-mailbox",
- .driver_data = (unsigned long) db8500_mboxes,
- }, {
- .name = "db9540-mailbox",
- .driver_data = (unsigned long) dbx540_mboxes,
- }, {
- /* sentinel */
- }
-};
-
-static struct platform_driver dbx500_mbox_driver = {
- .probe = dbx500_mbox_probe,
- .remove = dbx500_mbox_remove,
- .driver = {
- .name = "dbx500-mailbox",
- .of_match_table = dbx500_mailbox_match,
- },
- .id_table = dbx500_mbox_id,
-};
-
-static int __init dbx500_mbox_init(void)
-{
- return platform_driver_register(&dbx500_mbox_driver);
-}
-
-static void __exit dbx500_mbox_exit(void)
-{
- platform_driver_unregister(&dbx500_mbox_driver);
-}
-
-postcore_initcall(dbx500_mbox_init);
-module_exit(dbx500_mbox_exit);
-
-MODULE_LICENSE("GPL v2");
-MODULE_DESCRIPTION("ST-Ericsson mailbox: dbx500 architecture specific functions");
-MODULE_AUTHOR("Loic Pallardy <loic.pallardy@st.com>");
-MODULE_ALIAS("platform:dbx500-mailbox");
+++ /dev/null
-/*
- * Mailbox framework
- *
- * Copyright (C) 2006-2009 Nokia Corporation. All rights reserved.
- *
- * Contact: Hiroshi DOYU <Hiroshi.DOYU@nokia.com>
- * Author: Loic Pallardy <loic.pallardy@st.com> for ST-Ericsson
- *
- * 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.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA
- *
- */
-
-#include <linux/interrupt.h>
-#include <linux/spinlock.h>
-#include <linux/mutex.h>
-#include <linux/delay.h>
-#include <linux/slab.h>
-#include <linux/kfifo.h>
-#include <linux/err.h>
-#include <linux/notifier.h>
-#include <linux/module.h>
-
-#include "mailbox_internal.h"
-
-static struct mailbox **mboxes;
-
-static int mbox_configured;
-static DEFINE_MUTEX(mbox_configured_lock);
-
-static unsigned int mbox_kfifo_size = CONFIG_MBOX_KFIFO_SIZE;
-module_param(mbox_kfifo_size, uint, S_IRUGO);
-MODULE_PARM_DESC(mbox_kfifo_size, "Size of mailbox kfifo (bytes)");
-
-/* Mailbox FIFO handle functions */
-static inline void mbox_read(struct mailbox *mbox, struct mailbox_msg *msg)
-{
- mbox->ops->read(mbox, msg);
-}
-static inline int mbox_write(struct mailbox *mbox, struct mailbox_msg *msg)
-{
- return mbox->ops->write(mbox, msg);
-}
-static inline int mbox_empty(struct mailbox *mbox)
-{
- return mbox->ops->empty(mbox);
-}
-
-/* Mailbox IRQ handle functions */
-static inline void ack_mbox_irq(struct mailbox *mbox, mailbox_irq_t irq)
-{
- if (mbox->ops->ack_irq)
- mbox->ops->ack_irq(mbox, irq);
-}
-static inline int is_mbox_irq(struct mailbox *mbox, mailbox_irq_t irq)
-{
- return mbox->ops->is_irq(mbox, irq);
-}
-
-/*
- * message sender
- */
-static int __mbox_poll_for_space(struct mailbox *mbox)
-{
- return mbox->ops->poll_for_space(mbox);
-}
-
-int mailbox_msg_send(struct mailbox *mbox, struct mailbox_msg *msg)
-{
- struct mailbox_queue *mq = mbox->txq;
- int ret = 0, len;
-
- mutex_lock(&mq->mlock);
-
- if (kfifo_avail(&mq->fifo) < (sizeof(*msg) + msg->size)) {
- ret = -ENOMEM;
- goto out;
- }
-
- if (kfifo_is_empty(&mq->fifo) && !__mbox_poll_for_space(mbox)) {
- ret = mbox_write(mbox, msg);
- goto out;
- }
-
- len = kfifo_in(&mq->fifo, (unsigned char *)msg, sizeof(*msg));
- WARN_ON(len != sizeof(*msg));
-
- if (msg->size && msg->pdata) {
- len = kfifo_in(&mq->fifo, (unsigned char *)msg->pdata,
- msg->size);
- WARN_ON(len != msg->size);
- }
-
- tasklet_schedule(&mbox->txq->tasklet);
-
-out:
- mutex_unlock(&mq->mlock);
- return ret;
-}
-EXPORT_SYMBOL(mailbox_msg_send);
-
-#define TRANSFER_TIMEOUT 30000 /* Becomes ~3s timeout */
-
-static struct mailbox_msg no_irq_msg_res;
-
-struct mailbox_msg *mailbox_msg_send_receive_no_irq(struct mailbox *mbox,
- struct mailbox_msg *msg)
-{
- int ret = 0;
- int count = 0;
-
- BUG_ON(!irqs_disabled());
-
- if (likely(mbox->ops->write && mbox->ops->read)) {
- if (__mbox_poll_for_space(mbox)) {
- ret = -EBUSY;
- goto out;
- }
- mbox->ops->write(mbox, msg);
- while (!is_mbox_irq(mbox, IRQ_RX)) {
- udelay(100);
- cpu_relax();
- count++;
- if (count > TRANSFER_TIMEOUT) {
- pr_err("%s: Error: transfer timed out\n",
- __func__);
- ret = -EINVAL;
- goto out;
- }
- }
- mbox->ops->read(mbox, &no_irq_msg_res);
- ack_mbox_irq(mbox, IRQ_RX);
- } else {
- ret = -EINVAL;
- }
-
-out:
- BUG_ON(ret < 0);
-
- return &no_irq_msg_res;
-}
-EXPORT_SYMBOL(mailbox_msg_send_receive_no_irq);
-
-int mailbox_msg_send_no_irq(struct mailbox *mbox,
- struct mailbox_msg *msg)
-{
- int ret = 0;
-
- BUG_ON(!irqs_disabled());
-
- if (likely(mbox->ops->write)) {
- if (__mbox_poll_for_space(mbox)) {
- ret = -EBUSY;
- goto out;
- }
- mbox->ops->write(mbox, msg);
- } else {
- ret = -EINVAL;
- }
-
-out:
- WARN_ON(ret < 0);
-
- return ret;
-}
-EXPORT_SYMBOL(mailbox_msg_send_no_irq);
-
-void mailbox_save_ctx(struct mailbox *mbox)
-{
- if (!mbox->ops->save_ctx) {
- dev_err(mbox->dev, "%s:\tno save\n", __func__);
- return;
- }
-
- mbox->ops->save_ctx(mbox);
-}
-EXPORT_SYMBOL(mailbox_save_ctx);
-
-void mailbox_restore_ctx(struct mailbox *mbox)
-{
- if (!mbox->ops->restore_ctx) {
- dev_err(mbox->dev, "%s:\tno restore\n", __func__);
- return;
- }
-
- mbox->ops->restore_ctx(mbox);
-}
-EXPORT_SYMBOL(mailbox_restore_ctx);
-
-void mailbox_enable_irq(struct mailbox *mbox, mailbox_irq_t irq)
-{
- mbox->ops->enable_irq(mbox, irq);
-}
-EXPORT_SYMBOL(mailbox_enable_irq);
-
-void mailbox_disable_irq(struct mailbox *mbox, mailbox_irq_t irq)
-{
- mbox->ops->disable_irq(mbox, irq);
-}
-EXPORT_SYMBOL(mailbox_disable_irq);
-
-static void mbox_tx_tasklet(unsigned long tx_data)
-{
- struct mailbox *mbox = (struct mailbox *)tx_data;
- struct mailbox_queue *mq = mbox->txq;
- struct mailbox_msg msg;
- int ret;
- unsigned char tx_data_buf[CONFIG_MBOX_DATA_SIZE];
-
- while (kfifo_len(&mq->fifo)) {
- if (__mbox_poll_for_space(mbox)) {
- mailbox_enable_irq(mbox, IRQ_TX);
- break;
- }
-
- ret = kfifo_out(&mq->fifo, (unsigned char *)&msg, sizeof(msg));
- WARN_ON(ret != sizeof(msg));
-
- if (msg.size) {
- ret = kfifo_out(&mq->fifo, tx_data_buf,
- sizeof(msg.size));
- WARN_ON(ret != msg.size);
- msg.pdata = tx_data_buf;
- }
-
- ret = mbox_write(mbox, &msg);
- WARN_ON(ret);
- }
-}
-
-/*
- * Message receiver(workqueue)
- */
-static unsigned char rx_work_data[CONFIG_MBOX_DATA_SIZE];
-
-static void mbox_rx_work(struct work_struct *work)
-{
- struct mailbox_queue *mq =
- container_of(work, struct mailbox_queue, work);
- int len;
- struct mailbox *mbox = mq->mbox;
- struct mailbox_msg msg;
-
- while (kfifo_len(&mq->fifo) >= sizeof(msg)) {
- len = kfifo_out(&mq->fifo, (unsigned char *)&msg, sizeof(msg));
- WARN_ON(len != sizeof(msg));
-
- if (msg.size) {
- len = kfifo_out(&mq->fifo, rx_work_data, msg.size);
- WARN_ON(len != msg.size);
- msg.pdata = rx_work_data;
- }
-
- blocking_notifier_call_chain(&mbox->notifier, len,
- (void *)&msg);
- spin_lock_irq(&mq->lock);
- if (mq->full) {
- mq->full = false;
- mailbox_enable_irq(mbox, IRQ_RX);
- }
- spin_unlock_irq(&mq->lock);
- }
-}
-
-/*
- * Mailbox interrupt handler
- */
-static void __mbox_tx_interrupt(struct mailbox *mbox)
-{
- mailbox_disable_irq(mbox, IRQ_TX);
- ack_mbox_irq(mbox, IRQ_TX);
- tasklet_schedule(&mbox->txq->tasklet);
-}
-
-static void __mbox_rx_interrupt(struct mailbox *mbox)
-{
- struct mailbox_queue *mq = mbox->rxq;
- struct mailbox_msg msg;
- int len;
-
- while (!mbox_empty(mbox)) {
- if (unlikely(kfifo_avail(&mq->fifo) <
- (sizeof(msg) + CONFIG_MBOX_DATA_SIZE))) {
- mailbox_disable_irq(mbox, IRQ_RX);
- mq->full = true;
- goto nomem;
- }
-
- mbox_read(mbox, &msg);
-
- len = kfifo_in(&mq->fifo, (unsigned char *)&msg, sizeof(msg));
- WARN_ON(len != sizeof(msg));
-
- if (msg.pdata && msg.size) {
- len = kfifo_in(&mq->fifo, (unsigned char *)msg.pdata,
- msg.size);
- WARN_ON(len != msg.size);
- }
- }
-
- /* no more messages in the fifo. clear IRQ source. */
- ack_mbox_irq(mbox, IRQ_RX);
-nomem:
- schedule_work(&mbox->rxq->work);
-}
-
-static irqreturn_t mbox_interrupt(int irq, void *p)
-{
- struct mailbox *mbox = p;
-
- if (is_mbox_irq(mbox, IRQ_TX))
- __mbox_tx_interrupt(mbox);
-
- if (is_mbox_irq(mbox, IRQ_RX))
- __mbox_rx_interrupt(mbox);
-
- return IRQ_HANDLED;
-}
-
-static struct mailbox_queue *mbox_queue_alloc(struct mailbox *mbox,
- void (*work) (struct work_struct *),
- void (*tasklet)(unsigned long))
-{
- struct mailbox_queue *mq;
-
- mq = kzalloc(sizeof(struct mailbox_queue), GFP_KERNEL);
- if (!mq)
- return NULL;
-
- spin_lock_init(&mq->lock);
- mutex_init(&mq->mlock);
-
- if (kfifo_alloc(&mq->fifo, mbox_kfifo_size, GFP_KERNEL))
- goto error;
-
- if (work)
- INIT_WORK(&mq->work, work);
-
- if (tasklet)
- tasklet_init(&mq->tasklet, tasklet, (unsigned long)mbox);
- return mq;
-error:
- kfree(mq);
- return NULL;
-}
-
-static void mbox_queue_free(struct mailbox_queue *q)
-{
- kfifo_free(&q->fifo);
- kfree(q);
-}
-
-static int mailbox_startup(struct mailbox *mbox)
-{
- int ret = 0;
- struct mailbox_queue *mq;
-
- 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;
- }
-
- if (!mbox->use_count++) {
- mq = mbox_queue_alloc(mbox, NULL, mbox_tx_tasklet);
- if (!mq) {
- ret = -ENOMEM;
- goto fail_alloc_txq;
- }
- mbox->txq = mq;
-
- mq = mbox_queue_alloc(mbox, mbox_rx_work, NULL);
- if (!mq) {
- ret = -ENOMEM;
- goto fail_alloc_rxq;
- }
- mbox->rxq = mq;
- mq->mbox = mbox;
- ret = request_irq(mbox->irq, mbox_interrupt,
- IRQF_SHARED | IRQF_NO_SUSPEND,
- mbox->name, mbox);
- if (unlikely(ret)) {
- pr_err("failed to register mailbox interrupt:%d\n",
- ret);
- goto fail_request_irq;
- }
-
- mailbox_enable_irq(mbox, IRQ_RX);
- }
- mutex_unlock(&mbox_configured_lock);
- return 0;
-
-fail_request_irq:
- mbox_queue_free(mbox->rxq);
-fail_alloc_rxq:
- mbox_queue_free(mbox->txq);
-fail_alloc_txq:
- if (mbox->ops->shutdown)
- mbox->ops->shutdown(mbox);
- mbox->use_count--;
-fail_startup:
- mbox_configured--;
- mutex_unlock(&mbox_configured_lock);
- return ret;
-}
-
-static void mailbox_fini(struct mailbox *mbox)
-{
- mutex_lock(&mbox_configured_lock);
-
- if (!--mbox->use_count) {
- mailbox_disable_irq(mbox, IRQ_RX);
- free_irq(mbox->irq, mbox);
- tasklet_kill(&mbox->txq->tasklet);
- flush_work(&mbox->rxq->work);
- mbox_queue_free(mbox->txq);
- mbox_queue_free(mbox->rxq);
- }
-
- if (likely(mbox->ops->shutdown)) {
- if (!--mbox_configured)
- mbox->ops->shutdown(mbox);
- }
-
- mutex_unlock(&mbox_configured_lock);
-}
-
-struct mailbox *mailbox_get(const char *name, struct notifier_block *nb)
-{
- struct mailbox *_mbox, *mbox = NULL;
- int i, ret;
-
- if (!mboxes)
- return ERR_PTR(-EINVAL);
-
- for (i = 0; (_mbox = mboxes[i]); i++) {
- if (!strcmp(_mbox->name, name)) {
- mbox = _mbox;
- break;
- }
- }
-
- if (!mbox)
- return ERR_PTR(-ENOENT);
-
- if (nb)
- blocking_notifier_chain_register(&mbox->notifier, nb);
-
- ret = mailbox_startup(mbox);
- if (ret) {
- blocking_notifier_chain_unregister(&mbox->notifier, nb);
- return ERR_PTR(-ENODEV);
- }
-
- return mbox;
-}
-EXPORT_SYMBOL(mailbox_get);
-
-void mailbox_put(struct mailbox *mbox, struct notifier_block *nb)
-{
- if (nb)
- blocking_notifier_chain_unregister(&mbox->notifier, nb);
- mailbox_fini(mbox);
-}
-EXPORT_SYMBOL(mailbox_put);
-
-static struct class mailbox_class = { .name = "mbox", };
-
-int mailbox_register(struct device *parent, struct mailbox **list)
-{
- int ret;
- int i;
-
- mboxes = list;
- if (!mboxes)
- return -EINVAL;
-
- for (i = 0; mboxes[i]; i++) {
- struct mailbox *mbox = mboxes[i];
- mbox->dev = device_create(&mailbox_class,
- parent, 0, mbox, "%s", mbox->name);
- if (IS_ERR(mbox->dev)) {
- ret = PTR_ERR(mbox->dev);
- goto err_out;
- }
-
- BLOCKING_INIT_NOTIFIER_HEAD(&mbox->notifier);
- }
- return 0;
-
-err_out:
- while (i--)
- device_unregister(mboxes[i]->dev);
- return ret;
-}
-EXPORT_SYMBOL(mailbox_register);
-
-int mailbox_unregister(void)
-{
- int i;
-
- if (!mboxes)
- return -EINVAL;
-
- for (i = 0; mboxes[i]; i++)
- device_unregister(mboxes[i]->dev);
- mboxes = NULL;
- return 0;
-}
-EXPORT_SYMBOL(mailbox_unregister);
-
-static int __init mailbox_init(void)
-{
- int err;
-
- err = class_register(&mailbox_class);
- if (err)
- return err;
-
- /* kfifo size sanity check: alignment and minimal size */
- mbox_kfifo_size = ALIGN(mbox_kfifo_size, sizeof(struct mailbox_msg));
- mbox_kfifo_size = max_t(unsigned int, mbox_kfifo_size,
- sizeof(struct mailbox_msg) + CONFIG_MBOX_DATA_SIZE);
- return 0;
-}
-subsys_initcall(mailbox_init);
-
-static void __exit mailbox_exit(void)
-{
- class_unregister(&mailbox_class);
-}
-module_exit(mailbox_exit);
-
-MODULE_LICENSE("GPL v2");
-MODULE_DESCRIPTION("mailbox framework: interrupt driven messaging");
-MODULE_AUTHOR("Toshihiro Kobayashi");
-MODULE_AUTHOR("Hiroshi DOYU");
+++ /dev/null
-/*
- * mailbox: interprocessor communication module
- *
- * 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 MAILBOX_INTERNAL_H
-#define MAILBOX_INTERNAL_H
-
-#include <linux/device.h>
-#include <linux/interrupt.h>
-#include <linux/kfifo.h>
-#include <linux/mailbox.h>
-#include <linux/spinlock.h>
-#include <linux/workqueue.h>
-
-typedef int __bitwise mailbox_type_t;
-#define MBOX_HW_FIFO1_TYPE ((__force mailbox_type_t) 1)
-#define MBOX_HW_FIFO2_TYPE ((__force mailbox_type_t) 2)
-#define MBOX_SHARED_MEM_TYPE ((__force mailbox_type_t) 3)
-
-struct mailbox_ops {
- mailbox_type_t type;
- int (*startup)(struct mailbox *mbox);
- void (*shutdown)(struct mailbox *mbox);
- /* mailbox access */
- void (*read)(struct mailbox *mbox, struct mailbox_msg *msg);
- int (*write)(struct mailbox *mbox, struct mailbox_msg *msg);
- int (*empty)(struct mailbox *mbox);
- int (*poll_for_space)(struct mailbox *mbox);
- /* irq */
- void (*enable_irq)(struct mailbox *mbox, mailbox_irq_t irq);
- void (*disable_irq)(struct mailbox *mbox, mailbox_irq_t irq);
- void (*ack_irq)(struct mailbox *mbox, mailbox_irq_t irq);
- int (*is_irq)(struct mailbox *mbox, mailbox_irq_t irq);
- /* ctx */
- void (*save_ctx)(struct mailbox *mbox);
- void (*restore_ctx)(struct mailbox *mbox);
-};
-
-struct mailbox_queue {
- spinlock_t lock;
- struct mutex mlock;
- struct kfifo fifo;
- struct work_struct work;
- struct tasklet_struct tasklet;
- struct mailbox *mbox;
- bool full;
-};
-
-struct mailbox {
- const char *name;
- unsigned int id;
- unsigned int irq;
- struct mailbox_queue *txq, *rxq;
- struct mailbox_ops *ops;
- struct device *dev;
- void *priv;
- int use_count;
- struct blocking_notifier_head notifier;
-};
-
-void mailbox_init_seq(struct mailbox *);
-
-int mailbox_register(struct device *parent, struct mailbox **);
-int mailbox_unregister(void);
-
-#endif /* MAILBOX_INTERNAL_H */
#include <linux/device.h>
#include <linux/amba/bus.h>
-#include <linux/pl320-ipc.h>
+#include <linux/mailbox.h>
#define IPCMxSOURCE(m) ((m) * 0x40)
#define IPCMxDSET(m) (((m) * 0x40) + 0x004)
depends on HAS_DMA
depends on ARCH_OMAP4 || SOC_OMAP5
depends on OMAP_IOMMU
+ depends on OMAP_MBOX_FWK
select REMOTEPROC
- select MAILBOX
- select OMAP2PLUS_MBOX
select RPMSG
help
Say y here to support OMAP's remote processors (dual M3
#include <linux/platform_device.h>
#include <linux/dma-mapping.h>
#include <linux/remoteproc.h>
-#include <linux/mailbox.h>
+#include <plat/mailbox.h>
#include <linux/platform_data/remoteproc-omap.h>
#include "omap_remoteproc.h"
* @rproc: rproc handle
*/
struct omap_rproc {
- struct mailbox *mbox;
+ struct omap_mbox *mbox;
struct notifier_block nb;
struct rproc *rproc;
};
static int omap_rproc_mbox_callback(struct notifier_block *this,
unsigned long index, void *data)
{
+ mbox_msg_t msg = (mbox_msg_t) data;
struct omap_rproc *oproc = container_of(this, struct omap_rproc, nb);
struct device *dev = oproc->rproc->dev.parent;
- struct mailbox_msg *msg = data;
const char *name = oproc->rproc->name;
- u32 msg_data = (u32)msg->pdata;
- dev_dbg(dev, "mbox msg: 0x%x\n", msg_data);
+ dev_dbg(dev, "mbox msg: 0x%x\n", msg);
- switch (msg_data) {
+ switch (msg) {
case RP_MBOX_CRASH:
/* just log this for now. later, we'll also do recovery */
dev_err(dev, "omap rproc %s crashed\n", name);
break;
default:
/* msg contains the index of the triggered vring */
- if (rproc_vq_interrupt(oproc->rproc, msg_data) == IRQ_NONE)
- dev_dbg(dev, "no message was found in vqid %d\n",
- msg_data);
+ if (rproc_vq_interrupt(oproc->rproc, msg) == IRQ_NONE)
+ dev_dbg(dev, "no message was found in vqid %d\n", msg);
}
return NOTIFY_DONE;
{
struct omap_rproc *oproc = rproc->priv;
struct device *dev = rproc->dev.parent;
- struct mailbox_msg msg;
int ret;
/* send the index of the triggered virtqueue in the mailbox payload */
- MAILBOX_FILL_MSG(msg, 0, vqid, 0);
- ret = mailbox_msg_send(oproc->mbox, &msg);
+ ret = omap_mbox_msg_send(oproc->mbox, vqid);
if (ret)
- dev_err(dev, "mailbox_msg_send failed: %d\n", ret);
+ dev_err(dev, "omap_mbox_msg_send failed: %d\n", ret);
}
/*
struct device *dev = rproc->dev.parent;
struct platform_device *pdev = to_platform_device(dev);
struct omap_rproc_pdata *pdata = pdev->dev.platform_data;
- struct mailbox_msg msg;
int ret;
if (pdata->set_bootaddr)
oproc->nb.notifier_call = omap_rproc_mbox_callback;
/* every omap rproc is assigned a mailbox instance for messaging */
- oproc->mbox = mailbox_get(pdata->mbox_name, &oproc->nb);
+ oproc->mbox = omap_mbox_get(pdata->mbox_name, &oproc->nb);
if (IS_ERR(oproc->mbox)) {
ret = PTR_ERR(oproc->mbox);
- dev_err(dev, "mailbox_get failed: %d\n", ret);
+ dev_err(dev, "omap_mbox_get failed: %d\n", ret);
return ret;
}
* Note that the reply will _not_ arrive immediately: this message
* will wait in the mailbox fifo until the remote processor is booted.
*/
- MAILBOX_FILL_MSG(msg, 0, RP_MBOX_ECHO_REQUEST, 0);
- ret = mailbox_msg_send(oproc->mbox, &msg);
+ ret = omap_mbox_msg_send(oproc->mbox, RP_MBOX_ECHO_REQUEST);
if (ret) {
- dev_err(dev, "mailbox_get failed: %d\n", ret);
+ dev_err(dev, "omap_mbox_get failed: %d\n", ret);
goto put_mbox;
}
return 0;
put_mbox:
- mailbox_put(oproc->mbox, &oproc->nb);
+ omap_mbox_put(oproc->mbox, &oproc->nb);
return ret;
}
if (ret)
return ret;
- mailbox_put(oproc->mbox, &oproc->nb);
+ omap_mbox_put(oproc->mbox, &oproc->nb);
return 0;
}
menuconfig TIDSPBRIDGE
tristate "DSP Bridge driver"
depends on ARCH_OMAP3 && !ARCH_MULTIPLATFORM
- select MAILBOX
- select OMAP2PLUS_MBOX
+ select OMAP_MBOX_FWK
help
DSP/BIOS Bridge is designed for platforms that contain a GPP and
one or more attached DSPs. The GPP is considered the master or
u32 dsp_start_add; /* API Boot vector */
u32 internal_size; /* Internal memory size */
- struct mailbox *mbox; /* Mail box handle */
+ struct omap_mbox *mbox; /* Mail box handle */
struct cfg_hostres *resources; /* Host Resources */
* we disable ALL DPCs. We will try to disable ONLY IO DPC later. */
chnl_mgr_obj = pchnl->chnl_mgr_obj;
spin_lock_bh(&chnl_mgr_obj->chnl_mgr_lock);
- mailbox_disable_irq(dev_ctxt->mbox, IRQ_RX);
+ omap_mbox_disable_irq(dev_ctxt->mbox, IRQ_RX);
if (pchnl->chnl_type == CHNL_PCPY) {
/* This is a processor-copy channel. */
if (CHNL_IS_OUTPUT(pchnl->chnl_mode)) {
IO_OUTPUT), &mb_val);
sched_dpc = true;
out:
- mailbox_enable_irq(dev_ctxt->mbox, IRQ_RX);
+ omap_mbox_enable_irq(dev_ctxt->mbox, IRQ_RX);
spin_unlock_bh(&chnl_mgr_obj->chnl_mgr_lock);
if (mb_val != 0)
sm_interrupt_dsp(dev_ctxt, mb_val);
}
/* See comment in AddIOReq */
spin_lock_bh(&pchnl->chnl_mgr_obj->chnl_mgr_lock);
- mailbox_disable_irq(dev_ctxt->mbox, IRQ_RX);
+ omap_mbox_disable_irq(dev_ctxt->mbox, IRQ_RX);
if (dequeue_ioc) {
/* Dequeue IOC and set chan_ioc; */
chnl_packet_obj = list_first_entry(&pchnl->io_completions,
/* else, if list is empty, ensure event is reset. */
sync_reset_event(pchnl->sync_event);
}
- mailbox_enable_irq(dev_ctxt->mbox, IRQ_RX);
+ omap_mbox_enable_irq(dev_ctxt->mbox, IRQ_RX);
spin_unlock_bh(&pchnl->chnl_mgr_obj->chnl_mgr_lock);
if (dequeue_ioc
&& (pchnl->chnl_type == CHNL_PCPY && pchnl->chnl_id > 1)) {
* Calls the Bridge's CHNL_ISR to determine if this interrupt is ours, then
* schedules a DPC to dispatch I/O.
*/
-int io_mbox_msg(struct notifier_block *self, unsigned long len, void *data)
+int io_mbox_msg(struct notifier_block *self, unsigned long len, void *msg)
{
struct io_mgr *pio_mgr;
struct dev_object *dev_obj;
- u32 msg = (u32)((struct mailbox_msg *)data)->pdata;
unsigned long flags;
dev_obj = dev_get_first();
if (!pio_mgr)
return NOTIFY_BAD;
- pio_mgr->intr_val = (u16)(msg);
+ pio_mgr->intr_val = (u16)((u32)msg);
if (pio_mgr->intr_val & MBX_PM_CLASS)
io_dispatch_pm(pio_mgr);
* Enable Mailbox events and also drain any pending
* stale messages.
*/
- dev_context->mbox = mailbox_get("dsp", &dsp_mbox_notifier);
+ dev_context->mbox = omap_mbox_get("dsp", &dsp_mbox_notifier);
if (IS_ERR(dev_context->mbox)) {
dev_context->mbox = NULL;
pr_err("%s: Failed to get dsp mailbox handle\n",
}
/* Disable the mailbox interrupts */
if (dev_context->mbox) {
- mailbox_disable_irq(dev_context->mbox, IRQ_RX);
- mailbox_put(dev_context->mbox, &dsp_mbox_notifier);
+ omap_mbox_disable_irq(dev_context->mbox, IRQ_RX);
+ omap_mbox_put(dev_context->mbox, &dsp_mbox_notifier);
dev_context->mbox = NULL;
}
/* Reset IVA2 clocks*/
} else {
/* Save mailbox settings */
- mailbox_save_ctx(dev_context->mbox);
+ omap_mbox_save_ctx(dev_context->mbox);
/* Turn off DSP Peripheral clocks and DSP Load monitor timer */
status = dsp_clock_disable_all(dev_context->dsp_per_clks);
switch (dev_context->brd_state) {
case BRD_RUNNING:
- mailbox_save_ctx(dev_context->mbox);
+ omap_mbox_save_ctx(dev_context->mbox);
if (dsp_test_sleepstate == PWRDM_POWER_OFF) {
sm_interrupt_dsp(dev_context, MBX_PM_DSPHIBERNATE);
dev_dbg(bridge, "PM: %s - sent hibernate cmd to DSP\n",
}
break;
case BRD_RETENTION:
- mailbox_save_ctx(dev_context->mbox);
+ omap_mbox_save_ctx(dev_context->mbox);
if (dsp_test_sleepstate == PWRDM_POWER_OFF) {
sm_interrupt_dsp(dev_context, MBX_PM_DSPHIBERNATE);
target_pwr_state = PWRDM_POWER_OFF;
struct omap_dsp_platform_data *pdata =
omap_dspbridge_dev->dev.platform_data;
struct cfg_hostres *resources = dev_context->resources;
- struct mailbox_msg msg;
int status = 0;
u32 temp;
OMAP3430_IVA2_MOD, OMAP3430_CM_CLKEN_PLL);
/* Restore mailbox settings */
- mailbox_restore_ctx(dev_context->mbox);
+ omap_mbox_restore_ctx(dev_context->mbox);
/* Access MMU SYS CONFIG register to generate a short wakeup */
temp = readl(resources->dmmu_base + 0x10);
dsp_clock_enable_all(dev_context->dsp_per_clks);
}
- temp = mb_val;
- MAILBOX_FILL_MSG(msg, 0, temp, 0);
- status = mailbox_msg_send(dev_context->mbox, &msg);
+ status = omap_mbox_msg_send(dev_context->mbox, mb_val);
if (status) {
- pr_err("mailbox_msg_send Fail and status = %d\n", status);
+ pr_err("omap_mbox_msg_send Fail and status = %d\n", status);
status = -EPERM;
}
#include <linux/ioport.h>
#include <linux/platform_device.h>
#include <linux/clk.h>
-#include <linux/mailbox.h>
+#include <plat/mailbox.h>
#include <linux/pagemap.h>
#include <asm/cacheflush.h>
#include <linux/dma-mapping.h>
/*
- * mailbox: interprocessor communication module
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
*
- * 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.
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program. If not, see <http://www.gnu.org/licenses/>.
*/
-#ifndef MAILBOX_H
-#define MAILBOX_H
-
-struct mailbox;
-
-typedef int __bitwise mailbox_irq_t;
-#define IRQ_TX ((__force mailbox_irq_t) 1)
-#define IRQ_RX ((__force mailbox_irq_t) 2)
-
-struct mailbox_msg {
- int size;
- u32 header;
- void *pdata;
-};
-
-#define MAILBOX_FILL_MSG(_msg, _header, _pdata, _size) { \
- _msg.header = _header; \
- _msg.pdata = (void *)_pdata; \
- _msg.size = _size; \
-}
-
-int mailbox_msg_send(struct mailbox *, struct mailbox_msg *msg);
-struct mailbox_msg *mailbox_msg_send_receive_no_irq(struct mailbox *,
- struct mailbox_msg *msg);
-int mailbox_msg_send_no_irq(struct mailbox *, struct mailbox_msg *msg);
-
-struct mailbox *mailbox_get(const char *, struct notifier_block *nb);
-void mailbox_put(struct mailbox *mbox, struct notifier_block *nb);
-
-void mailbox_save_ctx(struct mailbox *mbox);
-void mailbox_restore_ctx(struct mailbox *mbox);
-void mailbox_enable_irq(struct mailbox *mbox, mailbox_irq_t irq);
-void mailbox_disable_irq(struct mailbox *mbox, mailbox_irq_t irq);
-
-#endif /* MAILBOX_H */
+int pl320_ipc_transmit(u32 *data);
+int pl320_ipc_register_notifier(struct notifier_block *nb);
+int pl320_ipc_unregister_notifier(struct notifier_block *nb);
+++ /dev/null
-/*
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program. If not, see <http://www.gnu.org/licenses/>.
- */
-
-int pl320_ipc_transmit(u32 *data);
-int pl320_ipc_register_notifier(struct notifier_block *nb);
-int pl320_ipc_unregister_notifier(struct notifier_block *nb);
+++ /dev/null
-/*
- * mailbox-dbx500.h
- *
- * Copyright (C) ST-Ericsson SA 2012
- * Author: <loic.pallardy@st.com> for ST-Ericsson.
- * License terms: GNU General Public License (GPL), version 2
- */
-
-struct dbx500_plat_data {
- unsigned int legacy_offset;
- unsigned int upap_offset;
-};
+++ /dev/null
-/*
- * mailbox-omap.h
- *
- * Copyright (C) 2013 Texas Instruments, Inc.
- *
- * 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.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- */
-
-#ifndef _PLAT_MAILBOX_H
-#define _PLAT_MAILBOX_H
-
-/* Interrupt register configuration types */
-#define MBOX_INTR_CFG_TYPE1 (0)
-#define MBOX_INTR_CFG_TYPE2 (1)
-
-/**
- * struct omap_mbox_dev_info - OMAP mailbox device attribute info
- * @name: name of the mailbox device
- * @tx_id: mailbox queue id used for transmitting messages
- * @rx_id: mailbox queue id on which messages are received
- * @irq_id: irq identifier number to use from the hwmod data
- * @usr_id: mailbox user id for identifying the interrupt into
- * the MPU interrupt controller.
- */
-struct omap_mbox_dev_info {
- const char *name;
- u32 tx_id;
- u32 rx_id;
- u32 irq_id;
- u32 usr_id;
-};
-
-/**
- * struct omap_mbox_pdata - OMAP mailbox platform data
- * @intr_type: type of interrupt configuration registers used
- while programming mailbox queue interrupts
- * @info_cnt: number of mailbox devices for the platform
- * @info: array of mailbox device attributes
- */
-struct omap_mbox_pdata {
- u32 intr_type;
- u32 info_cnt;
- struct omap_mbox_dev_info *info;
-};
-
-#endif /* _PLAT_MAILBOX_H */