Commit 2e560903e75ef790fd0428dbb53f65a2ee1ad4c6
Committed by
Tero Kristo
1 parent
fbcd049eaa
Exists in
ti-linux-3.14.y
and in
2 other branches
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; |