|
@@ -109,3 +109,119 @@ static void omap2_mbox_fifo_write(struct omap_mbox *mbox, mbox_msg_t msg)
|
|
|
mbox_write_reg(msg, fifo->msg);
|
|
|
}
|
|
|
|
|
|
+static int omap2_mbox_fifo_empty(struct omap_mbox *mbox)
|
|
|
+{
|
|
|
+ struct omap_mbox2_fifo *fifo =
|
|
|
+ &((struct omap_mbox2_priv *)mbox->priv)->rx_fifo;
|
|
|
+ return (mbox_read_reg(fifo->msg_stat) == 0);
|
|
|
+}
|
|
|
+
|
|
|
+static int omap2_mbox_fifo_full(struct omap_mbox *mbox)
|
|
|
+{
|
|
|
+ struct omap_mbox2_fifo *fifo =
|
|
|
+ &((struct omap_mbox2_priv *)mbox->priv)->tx_fifo;
|
|
|
+ return mbox_read_reg(fifo->fifo_stat);
|
|
|
+}
|
|
|
+
|
|
|
+/* Mailbox IRQ handle functions */
|
|
|
+static void omap2_mbox_enable_irq(struct omap_mbox *mbox,
|
|
|
+ omap_mbox_type_t irq)
|
|
|
+{
|
|
|
+ struct omap_mbox2_priv *p = mbox->priv;
|
|
|
+ u32 l, bit = (irq == IRQ_TX) ? p->notfull_bit : p->newmsg_bit;
|
|
|
+
|
|
|
+ l = mbox_read_reg(p->irqenable);
|
|
|
+ l |= bit;
|
|
|
+ mbox_write_reg(l, p->irqenable);
|
|
|
+}
|
|
|
+
|
|
|
+static void omap2_mbox_disable_irq(struct omap_mbox *mbox,
|
|
|
+ omap_mbox_type_t irq)
|
|
|
+{
|
|
|
+ struct omap_mbox2_priv *p = mbox->priv;
|
|
|
+ u32 bit = (irq == IRQ_TX) ? p->notfull_bit : p->newmsg_bit;
|
|
|
+
|
|
|
+ if (!cpu_is_omap44xx())
|
|
|
+ bit = mbox_read_reg(p->irqdisable) & ~bit;
|
|
|
+
|
|
|
+ mbox_write_reg(bit, p->irqdisable);
|
|
|
+}
|
|
|
+
|
|
|
+static void omap2_mbox_ack_irq(struct omap_mbox *mbox,
|
|
|
+ omap_mbox_type_t irq)
|
|
|
+{
|
|
|
+ struct omap_mbox2_priv *p = mbox->priv;
|
|
|
+ u32 bit = (irq == IRQ_TX) ? p->notfull_bit : p->newmsg_bit;
|
|
|
+
|
|
|
+ mbox_write_reg(bit, p->irqstatus);
|
|
|
+
|
|
|
+ /* Flush posted write for irq status to avoid spurious interrupts */
|
|
|
+ mbox_read_reg(p->irqstatus);
|
|
|
+}
|
|
|
+
|
|
|
+static int omap2_mbox_is_irq(struct omap_mbox *mbox,
|
|
|
+ omap_mbox_type_t irq)
|
|
|
+{
|
|
|
+ struct omap_mbox2_priv *p = mbox->priv;
|
|
|
+ u32 bit = (irq == IRQ_TX) ? p->notfull_bit : p->newmsg_bit;
|
|
|
+ u32 enable = mbox_read_reg(p->irqenable);
|
|
|
+ u32 status = mbox_read_reg(p->irqstatus);
|
|
|
+
|
|
|
+ return (int)(enable & status & bit);
|
|
|
+}
|
|
|
+
|
|
|
+static void omap2_mbox_save_ctx(struct omap_mbox *mbox)
|
|
|
+{
|
|
|
+ int i;
|
|
|
+ struct omap_mbox2_priv *p = mbox->priv;
|
|
|
+ int nr_regs;
|
|
|
+ if (cpu_is_omap44xx())
|
|
|
+ nr_regs = OMAP4_MBOX_NR_REGS;
|
|
|
+ else
|
|
|
+ nr_regs = MBOX_NR_REGS;
|
|
|
+ for (i = 0; i < nr_regs; i++) {
|
|
|
+ p->ctx[i] = mbox_read_reg(i * sizeof(u32));
|
|
|
+
|
|
|
+ dev_dbg(mbox->dev, "%s: [%02x] %08x\n", __func__,
|
|
|
+ i, p->ctx[i]);
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+static void omap2_mbox_restore_ctx(struct omap_mbox *mbox)
|
|
|
+{
|
|
|
+ int i;
|
|
|
+ struct omap_mbox2_priv *p = mbox->priv;
|
|
|
+ int nr_regs;
|
|
|
+ if (cpu_is_omap44xx())
|
|
|
+ nr_regs = OMAP4_MBOX_NR_REGS;
|
|
|
+ else
|
|
|
+ nr_regs = MBOX_NR_REGS;
|
|
|
+ for (i = 0; i < nr_regs; i++) {
|
|
|
+ mbox_write_reg(p->ctx[i], i * sizeof(u32));
|
|
|
+
|
|
|
+ dev_dbg(mbox->dev, "%s: [%02x] %08x\n", __func__,
|
|
|
+ i, p->ctx[i]);
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+static struct omap_mbox_ops omap2_mbox_ops = {
|
|
|
+ .type = OMAP_MBOX_TYPE2,
|
|
|
+ .startup = omap2_mbox_startup,
|
|
|
+ .shutdown = omap2_mbox_shutdown,
|
|
|
+ .fifo_read = omap2_mbox_fifo_read,
|
|
|
+ .fifo_write = omap2_mbox_fifo_write,
|
|
|
+ .fifo_empty = omap2_mbox_fifo_empty,
|
|
|
+ .fifo_full = omap2_mbox_fifo_full,
|
|
|
+ .enable_irq = omap2_mbox_enable_irq,
|
|
|
+ .disable_irq = omap2_mbox_disable_irq,
|
|
|
+ .ack_irq = omap2_mbox_ack_irq,
|
|
|
+ .is_irq = omap2_mbox_is_irq,
|
|
|
+ .save_ctx = omap2_mbox_save_ctx,
|
|
|
+ .restore_ctx = omap2_mbox_restore_ctx,
|
|
|
+};
|
|
|
+
|
|
|
+/*
|
|
|
+ * MAILBOX 0: ARM -> DSP,
|
|
|
+ * MAILBOX 1: ARM <- DSP.
|
|
|
+ * MAILBOX 2: ARM -> IVA,
|
|
|
+ * MAILBOX 3: ARM <- IVA.
|