omap: mailbox: Add an API for flushing the FIFO
authorVaibhav Bedia <vaibhav.bedia@ti.com>
Tue, 20 Dec 2011 11:37:37 +0000 (17:07 +0530)
committerVaibhav Hiremath <hvaibhav@ti.com>
Mon, 23 Jan 2012 19:14:42 +0000 (00:44 +0530)
On some platforms like AM33XX, the mailbox module is a
one-way communication between certain processors.

In these scenarios, the initiator (eg. MPU) is completely
responsible for FIFO maintenance and interrupt generation.
The initiator needs a mechanism to flush the FIFO to avoid
overflows or when going to suspend. Without the FIFO being
flushed, the IP block doesn't get disabled thereby blocking
system suspend.

This patch adds an API which the suspend code can invoke
to flush the FIFO and successfully enter suspend state.

Signed-off-by: Vaibhav Bedia <vaibhav.bedia@ti.com>
arch/arm/mach-omap2/mailbox.c
arch/arm/plat-omap/include/plat/mailbox.h
arch/arm/plat-omap/mailbox.c

index e804f7805a154dc81702d3b803a8fe47c30b681d..6dbc5b7ca942852a9e21d663e7e563702fcbc7e5 100644 (file)
@@ -127,6 +127,20 @@ static int omap2_mbox_fifo_full(struct omap_mbox *mbox)
        return mbox_read_reg(fifo->fifo_stat);
 }
 
+static int omap2_mbox_fifo_needs_flush(struct omap_mbox *mbox)
+{
+       struct omap_mbox2_fifo *fifo =
+               &((struct omap_mbox2_priv *)mbox->priv)->tx_fifo;
+       return (mbox_read_reg(fifo->msg_stat) == 0);
+}
+
+static mbox_msg_t omap2_mbox_fifo_readback(struct omap_mbox *mbox)
+{
+       struct omap_mbox2_fifo *fifo =
+               &((struct omap_mbox2_priv *)mbox->priv)->tx_fifo;
+       return (mbox_msg_t) mbox_read_reg(fifo->msg);
+}
+
 /* Mailbox IRQ handle functions */
 static void omap2_mbox_enable_irq(struct omap_mbox *mbox,
                omap_mbox_type_t irq)
@@ -209,19 +223,21 @@ static void omap2_mbox_restore_ctx(struct omap_mbox *mbox)
 }
 
 static struct omap_mbox_ops omap2_mbox_ops = {
-       .type           = OMAP_MBOX_TYPE2,
-       .startup        = omap2_mbox_startup,
-       .shutdown       = omap2_mbox_shutdown,
-       .fifo_read      = omap2_mbox_fifo_read,
-       .fifo_write     = omap2_mbox_fifo_write,
-       .fifo_empty     = omap2_mbox_fifo_empty,
-       .fifo_full      = omap2_mbox_fifo_full,
-       .enable_irq     = omap2_mbox_enable_irq,
-       .disable_irq    = omap2_mbox_disable_irq,
-       .ack_irq        = omap2_mbox_ack_irq,
-       .is_irq         = omap2_mbox_is_irq,
-       .save_ctx       = omap2_mbox_save_ctx,
-       .restore_ctx    = omap2_mbox_restore_ctx,
+       .type                   = OMAP_MBOX_TYPE2,
+       .startup                = omap2_mbox_startup,
+       .shutdown               = omap2_mbox_shutdown,
+       .fifo_read              = omap2_mbox_fifo_read,
+       .fifo_write             = omap2_mbox_fifo_write,
+       .fifo_empty             = omap2_mbox_fifo_empty,
+       .fifo_full              = omap2_mbox_fifo_full,
+       .fifo_needs_flush       = omap2_mbox_fifo_needs_flush,
+       .fifo_readback          = omap2_mbox_fifo_readback,
+       .enable_irq             = omap2_mbox_enable_irq,
+       .disable_irq            = omap2_mbox_disable_irq,
+       .ack_irq                = omap2_mbox_ack_irq,
+       .is_irq                 = omap2_mbox_is_irq,
+       .save_ctx               = omap2_mbox_save_ctx,
+       .restore_ctx            = omap2_mbox_restore_ctx,
 };
 
 /*
index cc3921e9059c8995d55334dba80ee64cba8d9aff..e136529f30e21adf0d511baf412fbdc391413a7f 100644 (file)
@@ -29,6 +29,8 @@ struct omap_mbox_ops {
        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);
+       int             (*fifo_needs_flush)(struct omap_mbox *mbox);
+       mbox_msg_t      (*fifo_readback)(struct omap_mbox *mbox);
        /* irq */
        void            (*enable_irq)(struct omap_mbox *mbox,
                                                omap_mbox_irq_t irq);
@@ -61,6 +63,7 @@ struct omap_mbox {
        struct blocking_notifier_head   notifier;
 };
 
+int omap_mbox_msg_rx_flush(struct omap_mbox *mbox);
 int omap_mbox_msg_send(struct omap_mbox *, mbox_msg_t msg);
 void omap_mbox_init_seq(struct omap_mbox *);
 
index ad80112c22751defaaa4cb5b9aefe11eac27e6be..4ebacb2739adbea564a3620eb524c15bae0164fc 100644 (file)
@@ -59,6 +59,14 @@ static inline int mbox_fifo_full(struct omap_mbox *mbox)
 {
        return mbox->ops->fifo_full(mbox);
 }
+static inline int mbox_fifo_needs_flush(struct omap_mbox *mbox)
+{
+       return mbox->ops->fifo_needs_flush(mbox);
+}
+static inline mbox_msg_t mbox_fifo_readback(struct omap_mbox *mbox)
+{
+       return mbox->ops->fifo_readback(mbox);
+}
 
 /* Mailbox IRQ handle functions */
 static inline void ack_mbox_irq(struct omap_mbox *mbox, omap_mbox_irq_t irq)
@@ -116,6 +124,28 @@ out:
 }
 EXPORT_SYMBOL(omap_mbox_msg_send);
 
+/*
+ * Flush the Rx FIFO by reading back the messages
+ * Since the normal expectation is that the Rx will do the
+ * reading, add a debug message to indicate if we really flush
+ * returns the no. of messages read back
+ */
+int omap_mbox_msg_rx_flush(struct omap_mbox *mbox)
+{
+       int ret = 0;
+       mbox_msg_t msg;
+
+       while (!mbox_fifo_needs_flush(mbox)) {
+               ret++;
+               msg = mbox_fifo_readback(mbox);
+       }
+       if (!ret)
+               pr_info("Flushed %s Rx FIFO by reading back\n", mbox->name);
+
+       return ret;
+}
+EXPORT_SYMBOL(omap_mbox_msg_rx_flush);
+
 static void mbox_tx_tasklet(unsigned long tx_data)
 {
        struct omap_mbox *mbox = (struct omap_mbox *)tx_data;