Skip to content
Browse files

mailbox: add shared memory mailbox type

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>
  • Loading branch information...
1 parent 4564a6b commit 569b1c9af95e31555988b4bbde6798642547e771 @ydrallap ydrallap committed with Jan 31, 2013
Showing with 62 additions and 43 deletions.
  1. +30 −5 drivers/mailbox/mailbox-omap1.c
  2. +12 −4 drivers/mailbox/mailbox-omap2.c
  3. +11 −27 drivers/mailbox/mailbox.c
  4. +9 −7 drivers/mailbox/mailbox_internal.h
View
35 drivers/mailbox/mailbox-omap1.c
@@ -14,6 +14,8 @@
#include <linux/platform_device.h>
#include <linux/io.h>
+#include <asm/delay.h>
+
#include "mailbox_internal.h"
#define MAILBOX_ARM2DSP1 0x00
@@ -38,6 +40,7 @@ struct omap_mbox1_priv {
struct omap_mbox1_fifo tx_fifo;
struct omap_mbox1_fifo rx_fifo;
unsigned long data;
+ bool empty_flag;
};
static inline int mbox_read_reg(size_t ofs)
@@ -59,6 +62,7 @@ static void omap1_mbox_fifo_read(struct mailbox *mbox, struct mailbox_msg *msg)
priv->data = mbox_read_reg(fifo->data);
priv->data |= ((unsigned long) mbox_read_reg(fifo->cmd)) << 16;
MAILBOX_FILL_MSG((*msg), 0, priv->data, 0);
+ priv->empty_flag = false;
}
static int
@@ -79,7 +83,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)
@@ -90,6 +98,18 @@ static int omap1_mbox_fifo_full(struct mailbox *mbox)
return mbox_read_reg(fifo->flag);
}
+static int ompa1_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)
@@ -108,17 +128,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 = ompa1_mbox_poll_for_space,
.enable_irq = omap1_mbox_enable_irq,
.disable_irq = omap1_mbox_disable_irq,
.is_irq = omap1_mbox_is_irq,
View
16 drivers/mailbox/mailbox-omap2.c
@@ -132,6 +132,14 @@ static int omap2_mbox_fifo_full(struct mailbox *mbox)
return mbox_read_reg(fifo->fifo_stat);
}
+static int ompa2_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)
@@ -219,10 +227,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 = ompa2_mbox_poll_for_space,
.enable_irq = omap2_mbox_enable_irq,
.disable_irq = omap2_mbox_disable_irq,
.ack_irq = omap2_mbox_ack_irq,
View
38 drivers/mailbox/mailbox.c
@@ -45,21 +45,17 @@ 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 */
@@ -78,16 +74,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)
@@ -103,7 +90,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);
}
}
@@ -235,15 +222,15 @@ 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);
mq->full = true;
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));
@@ -253,9 +240,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. */
View
16 drivers/mailbox/mailbox_internal.h
@@ -17,18 +17,19 @@
#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);
@@ -53,6 +54,7 @@ struct mailbox_queue {
struct mailbox {
char *name;
+ unsigned int id;
unsigned int irq;
struct mailbox_queue *txq, *rxq;
struct mailbox_ops *ops;

0 comments on commit 569b1c9

Please sign in to comment.
Something went wrong with that request. Please try again.