Commit 2e560903e75ef790fd0428dbb53f65a2ee1ad4c6

Authored by Dave Gerlach
Committed by Tero Kristo
1 parent fbcd049eaa

mailbox/omap: Add ti,mbox-send-noirq quirk to fix AM33xx CPU Idle

The mailbox framework controls the transmission queue and requires
either its controller implementations or clients to run the state
machine for the Tx queue. The OMAP mailbox controller uses a Tx-ready
interrupt as the equivalent of a Tx-done interrupt to run this Tx
queue state-machine.

The WkupM3 processor on AM33xx and AM43xx SoCs is used to offload
certain PM tasks, like doing the necessary operations for Device
PM suspend/resume or for entering lower c-states during cpuidle.

The CPUIdle on AM33xx requires the messages to be sent without
having to trigger the Tx-ready interrupts, as the interrupt
would immediately terminate the CPUIdle operation. Support for
this has been added by introducing a DT quirk, "ti,mbox-send-noirq"
and using it to modify the normal OMAP mailbox controller behavior
on the sub-mailboxes used to communicate with the WkupM3 remote
processor. This also requires the wkup_m3_ipc driver to adjust
its mailbox usage logic to run the Tx state machine.

NOTE:
- AM43xx does not communicate with WkupM3 for CPU Idle, so is
  not affected by this behavior. But, it uses the same IPC driver
  for PM suspend/resume functionality, so requires the quirk as
  well, because of changes to the common wkup_m3_ipc driver.

Signed-off-by: Dave Gerlach <d-gerlach@ti.com>
[s-anna@ti.com: revise logic and update comments/patch description]
Signed-off-by: Suman Anna <s-anna@ti.com>

Showing 2 changed files with 58 additions and 4 deletions Side-by-side Diff

Documentation/devicetree/bindings/mailbox/omap-mailbox.txt
... ... @@ -75,6 +75,14 @@
75 75 Cell #3 (usr_id) - mailbox user id for identifying the interrupt line
76 76 associated with generating a tx/rx fifo interrupt.
77 77  
  78 +Optional Properties:
  79 +--------------------
  80 +- ti,mbox-send-noirq: Quirk flag to allow the client user of this sub-mailbox
  81 + to send messages without triggering a Tx ready interrupt,
  82 + and to control the Tx ticker. Should be used only on
  83 + sub-mailboxes used to communicate with WkupM3 remote
  84 + processor on AM33xx/AM43xx SoCs.
  85 +
78 86 Mailbox Users:
79 87 ==============
80 88 A device needing to communicate with a target processor device should specify
drivers/mailbox/omap-mailbox.c
... ... @@ -67,6 +67,13 @@
67 67 #define MBOX_NR_REGS (MBOX_REG_SIZE / sizeof(u32))
68 68 #define OMAP4_MBOX_NR_REGS (OMAP4_MBOX_REG_SIZE / sizeof(u32))
69 69  
  70 +/*
  71 + * We need this for special case handling where controller indicates done
  72 + * state with IRQ but a specific channel needs to use manually ACK (used
  73 + * by wkup_m3 on AM33xx/AM43xx).
  74 + */
  75 +#define MBOX_TXDONE_BY_ACK (1 << 2)
  76 +
70 77 struct omap_mbox_fifo {
71 78 unsigned long msg;
72 79 unsigned long fifo_stat;
... ... @@ -106,6 +113,7 @@
106 113 int rx_irq;
107 114  
108 115 const char *name;
  116 + bool send_no_irq;
109 117 };
110 118  
111 119 struct omap_mbox {
... ... @@ -119,6 +127,7 @@
119 127 u32 ctx[OMAP4_MBOX_NR_REGS];
120 128 u32 intr_type;
121 129 struct mbox_chan *chan;
  130 + bool send_no_irq;
122 131 };
123 132  
124 133 /* global variables for the mailbox devices */
... ... @@ -418,6 +427,9 @@
418 427 goto fail_request_irq;
419 428 }
420 429  
  430 + if (mbox->send_no_irq)
  431 + mbox->chan->txdone_method = MBOX_TXDONE_BY_ACK;
  432 +
421 433 _omap_mbox_enable_irq(mbox, IRQ_RX);
422 434  
423 435 return 0;
424 436  
425 437  
426 438  
... ... @@ -586,14 +598,28 @@
586 598 mutex_unlock(&mdev->cfg_lock);
587 599 }
588 600  
589   -static int omap_mbox_chan_send_data(struct mbox_chan *chan, void *data)
  601 +static int omap_mbox_chan_send_noirq(struct omap_mbox *mbox, void *data)
590 602 {
591   - struct omap_mbox *mbox = mbox_chan_to_omap_mbox(chan);
592 603 int ret = -EBUSY;
593 604  
594   - if (!mbox)
595   - return -EINVAL;
  605 + if (!mbox_fifo_full(mbox)) {
  606 + _omap_mbox_enable_irq(mbox, IRQ_RX);
  607 + mbox_fifo_write(mbox, (mbox_msg_t)data);
  608 + ret = 0;
  609 + _omap_mbox_disable_irq(mbox, IRQ_RX);
596 610  
  611 + /* we must read and ack the interrupt directly from here */
  612 + mbox_fifo_read(mbox);
  613 + ack_mbox_irq(mbox, IRQ_RX);
  614 + }
  615 +
  616 + return ret;
  617 +}
  618 +
  619 +static int omap_mbox_chan_send(struct omap_mbox *mbox, void *data)
  620 +{
  621 + int ret = -EBUSY;
  622 +
597 623 if (!mbox_fifo_full(mbox)) {
598 624 mbox_fifo_write(mbox, (mbox_msg_t)data);
599 625 ret = 0;
... ... @@ -604,6 +630,22 @@
604 630 return ret;
605 631 }
606 632  
  633 +static int omap_mbox_chan_send_data(struct mbox_chan *chan, void *data)
  634 +{
  635 + struct omap_mbox *mbox = mbox_chan_to_omap_mbox(chan);
  636 + int ret;
  637 +
  638 + if (!mbox)
  639 + return -EINVAL;
  640 +
  641 + if (mbox->send_no_irq)
  642 + ret = omap_mbox_chan_send_noirq(mbox, data);
  643 + else
  644 + ret = omap_mbox_chan_send(mbox, data);
  645 +
  646 + return ret;
  647 +}
  648 +
607 649 static struct mbox_chan_ops omap_mbox_chan_ops = {
608 650 .startup = omap_mbox_chan_startup,
609 651 .send_data = omap_mbox_chan_send_data,
... ... @@ -732,6 +774,9 @@
732 774 finfo->rx_usr = tmp[2];
733 775  
734 776 finfo->name = child->name;
  777 +
  778 + if (of_find_property(child, "ti,mbox-send-noirq", NULL))
  779 + finfo->send_no_irq = true;
735 780 } else {
736 781 finfo->tx_id = info->tx_id;
737 782 finfo->rx_id = info->rx_id;
... ... @@ -791,6 +836,7 @@
791 836 fifo->irqstatus = MAILBOX_IRQSTATUS(intr_type, finfo->rx_usr);
792 837 fifo->irqdisable = MAILBOX_IRQDISABLE(intr_type, finfo->rx_usr);
793 838  
  839 + mbox->send_no_irq = finfo->send_no_irq;
794 840 mbox->intr_type = intr_type;
795 841  
796 842 mbox->parent = mdev;