]> git.karo-electronics.de Git - karo-tx-linux.git/commitdiff
mailbox: add shared memory mailbox type
authorLoic Pallardy <loic.pallardy@st.com>
Thu, 31 Jan 2013 16:55:29 +0000 (17:55 +0100)
committerSuman Anna <s-anna@ti.com>
Thu, 14 Mar 2013 18:07:39 +0000 (13:07 -0500)
Some mailboxes are made up of cross interrupts
and associated shared memory.
Shared memory mapping is fixed and cross interrupt/shared
memory relation make impossible the use of virtio.
Mailbox framework must be enough opened to support
any kind of mailbox.

Signed-off-by: Loic Pallardy <loic.pallardy@st.com>
Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
Signed-off-by: Suman Anna <s-anna@ti.com>
drivers/mailbox/mailbox-omap1.c
drivers/mailbox/mailbox-omap2.c
drivers/mailbox/mailbox.c
drivers/mailbox/mailbox_internal.h

index 9268f986645af483586fe1f2082fcf115206da44..7b301579afbbe0918e9cc7b604b3e5235c3dfff4 100644 (file)
@@ -13,6 +13,7 @@
 #include <linux/interrupt.h>
 #include <linux/platform_device.h>
 #include <linux/io.h>
+#include <linux/delay.h>
 
 #include "mailbox_internal.h"
 
@@ -38,6 +39,7 @@ 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)
@@ -59,6 +61,7 @@ static void omap1_mbox_fifo_read(struct mailbox *mbox, struct mailbox_msg *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;
 }
 
 static int
@@ -76,7 +79,11 @@ omap1_mbox_fifo_write(struct mailbox *mbox, struct mailbox_msg *msg)
 
 static int omap1_mbox_fifo_empty(struct mailbox *mbox)
 {
-       return 0;
+       struct omap_mbox1_priv *priv = (struct omap_mbox1_priv *)mbox->priv;
+       if (priv->empty_flag)
+               return 0;
+       else
+               return 1;
 }
 
 static int omap1_mbox_fifo_full(struct mailbox *mbox)
@@ -87,6 +94,18 @@ static int omap1_mbox_fifo_full(struct mailbox *mbox)
        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)
@@ -105,17 +124,22 @@ omap1_mbox_disable_irq(struct mailbox *mbox, mailbox_type_t irq)
 static int
 omap1_mbox_is_irq(struct mailbox *mbox, mailbox_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,
-       .fifo_read      = omap1_mbox_fifo_read,
-       .fifo_write     = omap1_mbox_fifo_write,
-       .fifo_empty     = omap1_mbox_fifo_empty,
-       .fifo_full      = omap1_mbox_fifo_full,
+       .read           = omap1_mbox_fifo_read,
+       .write          = omap1_mbox_fifo_write,
+       .empty          = omap1_mbox_fifo_empty,
+       .poll_for_space = omap1_mbox_poll_for_space,
        .enable_irq     = omap1_mbox_enable_irq,
        .disable_irq    = omap1_mbox_disable_irq,
        .is_irq         = omap1_mbox_is_irq,
index 43704fd2487e5887c00ebe9e0458d18541d7854d..72f83684294094fdf002a4c0c06029de8c155830 100644 (file)
@@ -129,6 +129,14 @@ static int omap2_mbox_fifo_full(struct mailbox *mbox)
        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)
@@ -216,10 +224,10 @@ static struct mailbox_ops omap2_mbox_ops = {
        .type           = MBOX_HW_FIFO2_TYPE,
        .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,
+       .read           = omap2_mbox_fifo_read,
+       .write          = omap2_mbox_fifo_write,
+       .empty          = omap2_mbox_fifo_empty,
+       .poll_for_space = omap2_mbox_poll_for_space,
        .enable_irq     = omap2_mbox_enable_irq,
        .disable_irq    = omap2_mbox_disable_irq,
        .ack_irq        = omap2_mbox_ack_irq,
index ff6595ad19218f2ea35b7a13ee63c74c1ecb42c0..08da5b0efae1c0a4f268cebc25f51fdfd3cad75e 100644 (file)
@@ -44,21 +44,17 @@ 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_fifo_read(struct mailbox *mbox, struct mailbox_msg *msg)
+static inline void mbox_read(struct mailbox *mbox, struct mailbox_msg *msg)
 {
-       mbox->ops->fifo_read(mbox, msg);
+       mbox->ops->read(mbox, msg);
 }
-static inline int mbox_fifo_write(struct mailbox *mbox, struct mailbox_msg *msg)
+static inline int mbox_write(struct mailbox *mbox, struct mailbox_msg *msg)
 {
-       return mbox->ops->fifo_write(mbox, msg);
+       return mbox->ops->write(mbox, msg);
 }
-static inline int mbox_fifo_empty(struct mailbox *mbox)
+static inline int mbox_empty(struct mailbox *mbox)
 {
-       return mbox->ops->fifo_empty(mbox);
-}
-static inline int mbox_fifo_full(struct mailbox *mbox)
-{
-       return mbox->ops->fifo_full(mbox);
+       return mbox->ops->empty(mbox);
 }
 
 /* Mailbox IRQ handle functions */
@@ -77,16 +73,7 @@ static inline int is_mbox_irq(struct mailbox *mbox, mailbox_irq_t irq)
  */
 static int __mbox_poll_for_space(struct mailbox *mbox)
 {
-       int ret = 0, i = 1000;
-
-       while (mbox_fifo_full(mbox)) {
-               if (mbox->ops->type == MBOX_HW_FIFO2_TYPE)
-                       return -1;
-               if (--i == 0)
-                       return -1;
-               udelay(1);
-       }
-       return ret;
+       return mbox->ops->poll_for_space(mbox);
 }
 
 int mailbox_msg_send(struct mailbox *mbox, struct mailbox_msg *msg)
@@ -102,7 +89,7 @@ int mailbox_msg_send(struct mailbox *mbox, struct mailbox_msg *msg)
        }
 
        if (kfifo_is_empty(&mq->fifo) && !__mbox_poll_for_space(mbox)) {
-               ret = mbox_fifo_write(mbox, msg);
+               ret = mbox_write(mbox, msg);
                goto out;
        }
 
@@ -181,7 +168,7 @@ static void mbox_tx_tasklet(unsigned long tx_data)
                        msg.pdata = tx_data_buf;
                }
 
-               ret = mbox_fifo_write(mbox, &msg);
+               ret = mbox_write(mbox, &msg);
                WARN_ON(ret);
        }
 }
@@ -236,7 +223,7 @@ static void __mbox_rx_interrupt(struct mailbox *mbox)
        struct mailbox_msg msg;
        int len;
 
-       while (!mbox_fifo_empty(mbox)) {
+       while (!mbox_empty(mbox)) {
                if (unlikely(kfifo_avail(&mq->fifo) <
                                (sizeof(msg) + CONFIG_MBOX_DATA_SIZE))) {
                        mailbox_disable_irq(mbox, IRQ_RX);
@@ -244,7 +231,7 @@ static void __mbox_rx_interrupt(struct mailbox *mbox)
                        goto nomem;
                }
 
-               mbox_fifo_read(mbox, &msg);
+               mbox_read(mbox, &msg);
 
                len = kfifo_in(&mq->fifo, (unsigned char *)&msg, sizeof(msg));
                WARN_ON(len != sizeof(msg));
@@ -254,9 +241,6 @@ static void __mbox_rx_interrupt(struct mailbox *mbox)
                                        msg.size);
                        WARN_ON(len != msg.size);
                }
-
-               if (mbox->ops->type == MBOX_HW_FIFO1_TYPE)
-                       break;
        }
 
        /* no more messages in the fifo. clear IRQ source. */
index 7ac8bb8205bdc5321652ac219c8d5108c10c9fc2..8aded9584dc0f9b6cc550dbd0dd19ae46c0d56cb 100644 (file)
 #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_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);
-       /* fifo */
-       void            (*fifo_read)(struct mailbox *mbox,
-                                               struct mailbox_msg *msg);
-       int             (*fifo_write)(struct mailbox *mbox,
-                                               struct mailbox_msg *msg);
-       int             (*fifo_empty)(struct mailbox *mbox);
-       int             (*fifo_full)(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);
@@ -53,6 +52,7 @@ struct mailbox_queue {
 
 struct mailbox {
        const char              *name;
+       unsigned int            id;
        unsigned int            irq;
        struct mailbox_queue    *txq, *rxq;
        struct mailbox_ops      *ops;