linux-omap.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCHv3 7/8] mailbox/omap: add code to support the wkupm3 operations
@ 2013-08-06 21:40 Suman Anna
  2013-08-27  3:50 ` Kevin Hilman
  0 siblings, 1 reply; 9+ messages in thread
From: Suman Anna @ 2013-08-06 21:40 UTC (permalink / raw)
  To: Tony Lindgren, Benoit Cousson
  Cc: Paul Walmsley, Ohad Ben-Cohen, Jassi Brar, linux-omap,
	linux-arm-kernel, devicetree, Suman Anna

The WkupM3 mailbox used for triggering PM operations such as suspend
and resume on AM33x/AM43x is special in that the M3 processor cannot
access the mailbox registers. However, an interrupt is needed to be
sent to request the M3 to perform a desired PM operation. This patch
adds the support for this special mailbox through separate ops for
this mailbox. These ops are designed to have the WkupM3's Rx interrupt
programmed within the driver, during transmission of a message. The
message is immediately read back and the internal mailbox interrupt
acknowledged as well to avoid triggering any spurious interrupts to
the M3.

Signed-off-by: Suman Anna <s-anna@ti.com>
---
 drivers/mailbox/mailbox-omap2.c | 87 ++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 86 insertions(+), 1 deletion(-)

diff --git a/drivers/mailbox/mailbox-omap2.c b/drivers/mailbox/mailbox-omap2.c
index fef18f4..00ac2a2 100644
--- a/drivers/mailbox/mailbox-omap2.c
+++ b/drivers/mailbox/mailbox-omap2.c
@@ -36,6 +36,8 @@
 #define MAILBOX_IRQ_NEWMSG(m)		(1 << (2 * (m)))
 #define MAILBOX_IRQ_NOTFULL(m)		(1 << (2 * (m) + 1))
 
+#define AM33X_MBOX_WKUPM3_USR		3
+
 #define MBOX_REG_SIZE			0x120
 
 #define OMAP4_MBOX_REG_SIZE		0x130
@@ -179,6 +181,57 @@ static int omap2_mbox_is_irq(struct omap_mbox *mbox, omap_mbox_irq_t irq)
 	return (int)(enable & status & bit);
 }
 
+static void wkupm3_mbox_enable_irq(struct omap_mbox *mbox, omap_mbox_irq_t irq)
+{
+	struct omap_mbox2_priv *p = mbox->priv;
+	u32 l, bit = (irq == IRQ_TX) ? p->notfull_bit : p->newmsg_bit;
+	unsigned long irqenable = ((irq == IRQ_RX) ?
+		OMAP4_MAILBOX_IRQENABLE(AM33X_MBOX_WKUPM3_USR) : p->irqenable);
+
+	l = mbox_read_reg(mbox->parent, irqenable);
+	l |= bit;
+	mbox_write_reg(mbox->parent, l, irqenable);
+}
+
+static void wkupm3_mbox_disable_irq(struct omap_mbox *mbox, omap_mbox_irq_t irq)
+{
+	struct omap_mbox2_priv *p = mbox->priv;
+	u32 bit = (irq == IRQ_TX) ? p->notfull_bit : p->newmsg_bit;
+	unsigned long irqdisable = ((irq == IRQ_RX) ?
+	    OMAP4_MAILBOX_IRQENABLE_CLR(AM33X_MBOX_WKUPM3_USR) : p->irqdisable);
+
+	mbox_write_reg(mbox->parent, bit, irqdisable);
+}
+
+static void wkupm3_mbox_ack_irq(struct omap_mbox *mbox, omap_mbox_irq_t irq)
+{
+	struct omap_mbox2_priv *p = mbox->priv;
+	u32 bit = (irq == IRQ_TX) ? p->notfull_bit : p->newmsg_bit;
+	unsigned long irqstatus = ((irq == IRQ_RX) ?
+		OMAP4_MAILBOX_IRQSTATUS(AM33X_MBOX_WKUPM3_USR) : p->irqstatus);
+
+	mbox_write_reg(mbox->parent, bit, irqstatus);
+
+	/* Flush posted write for irq status to avoid spurious interrupts */
+	mbox_read_reg(mbox->parent, irqstatus);
+}
+
+static int wkupm3_mbox_is_irq(struct omap_mbox *mbox, omap_mbox_irq_t irq)
+{
+	struct omap_mbox2_priv *p = mbox->priv;
+	u32 bit = (irq == IRQ_TX) ? p->notfull_bit : p->newmsg_bit;
+	u32 enable, status;
+
+	/* WkupM3 mailbox does not use a receive queue */
+	if (irq == IRQ_RX)
+		return 0;
+
+	enable = mbox_read_reg(mbox->parent, p->irqenable);
+	status = mbox_read_reg(mbox->parent, p->irqstatus);
+
+	return (int)(enable & status & bit);
+}
+
 static void omap2_mbox_save_ctx(struct omap_mbox *mbox)
 {
 	int i;
@@ -215,6 +268,20 @@ static void omap2_mbox_restore_ctx(struct omap_mbox *mbox)
 	}
 }
 
+static void wkupm3_mbox_send_data(struct omap_mbox *mbox, mbox_msg_t msg)
+{
+	mbox_msg_t rmsg;
+
+	/* enable the mbox Rx interrupt for WkupM3 only briefly */
+	wkupm3_mbox_enable_irq(mbox, IRQ_RX);
+	omap2_mbox_fifo_write(mbox, msg);
+	wkupm3_mbox_disable_irq(mbox, IRQ_RX);
+
+	/* read back the message and ack the interrupt on behalf of WkupM3 */
+	rmsg = omap2_mbox_fifo_read(mbox);
+	wkupm3_mbox_ack_irq(mbox, IRQ_RX);
+}
+
 static struct omap_mbox_ops omap2_mbox_ops = {
 	.startup	= omap2_mbox_startup,
 	.shutdown	= omap2_mbox_shutdown,
@@ -230,6 +297,21 @@ static struct omap_mbox_ops omap2_mbox_ops = {
 	.restore_ctx	= omap2_mbox_restore_ctx,
 };
 
+static struct omap_mbox_ops wkupm3_mbox_ops = {
+	.startup	= omap2_mbox_startup,
+	.shutdown	= omap2_mbox_shutdown,
+	.fifo_read	= omap2_mbox_fifo_read,
+	.fifo_write	= wkupm3_mbox_send_data,
+	.fifo_empty	= omap2_mbox_fifo_empty,
+	.poll_for_space	= omap2_mbox_poll_for_space,
+	.enable_irq	= wkupm3_mbox_enable_irq,
+	.disable_irq	= wkupm3_mbox_disable_irq,
+	.ack_irq	= wkupm3_mbox_ack_irq,
+	.is_irq		= wkupm3_mbox_is_irq,
+	.save_ctx	= omap2_mbox_save_ctx,
+	.restore_ctx	= omap2_mbox_restore_ctx,
+};
+
 static const struct of_device_id omap_mailbox_of_match[] = {
 	{
 		.compatible	= "ti,omap2-mailbox",
@@ -387,7 +469,10 @@ static int omap2_mbox_probe(struct platform_device *pdev)
 		mbox->priv = priv;
 		mbox->parent = mdev;
 		mbox->name = info->name;
-		mbox->ops = &omap2_mbox_ops;
+		if (!strcmp(mbox->name, "wkup_m3"))
+			mbox->ops = &wkupm3_mbox_ops;
+		else
+			mbox->ops = &omap2_mbox_ops;
 		mbox->irq = platform_get_irq(pdev, info->irq_id);
 		if (mbox->irq < 0) {
 			ret = mbox->irq;
-- 
1.8.3.3


^ permalink raw reply related	[flat|nested] 9+ messages in thread

end of thread, other threads:[~2013-09-05 20:13 UTC | newest]

Thread overview: 9+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2013-08-06 21:40 [PATCHv3 7/8] mailbox/omap: add code to support the wkupm3 operations Suman Anna
2013-08-27  3:50 ` Kevin Hilman
2013-08-27 16:03   ` Suman Anna
2013-08-27 21:25     ` Kevin Hilman
2013-08-28 16:24       ` Suman Anna
2013-08-29 16:57         ` Kevin Hilman
2013-09-04 20:18           ` Suman Anna
2013-09-04 22:22             ` Kevin Hilman
2013-09-05 20:12               ` Suman Anna

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).