Skip to content

Commit 676f23e

Browse files
Anson-HuangJassiBrar
authored andcommitted
mailbox: imx: Support runtime PM
Some power hungry sub-systems like VPU has its own MUs which also use mailbox driver, current mailbox driver uses platform driver model and MU's power will be ON after driver probed and left ON there, it may cause the whole sub-system can NOT enter lower power mode, take VPU driver for example, it has runtime PM support, but due to its MU always ON, the VPU sub-system will be always ON and consume many power during kernel idle. To save power in kernel idle, mailbox driver needs to support runtime PM in order to power off MU when it is unused. However, the runtime suspend/resume can ONLY be implemented in mailbox's .shutdown/.startup callback, so its consumer needs to call mbox_request_channel()/mbox_free_channel() in consumer driver's runtime PM callback, then the MU's power will be ON/OFF along with consumer's runtime PM status. Signed-off-by: Anson Huang <[email protected]> Signed-off-by: Jassi Brar <[email protected]>
1 parent 00d9990 commit 676f23e

File tree

1 file changed

+26
-1
lines changed

1 file changed

+26
-1
lines changed

drivers/mailbox/imx-mailbox.c

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
#include <linux/mailbox_controller.h>
1313
#include <linux/module.h>
1414
#include <linux/of_device.h>
15+
#include <linux/pm_runtime.h>
1516
#include <linux/slab.h>
1617

1718
#define IMX_MU_xSR_GIPn(x) BIT(28 + (3 - (x)))
@@ -287,6 +288,7 @@ static int imx_mu_startup(struct mbox_chan *chan)
287288
struct imx_mu_con_priv *cp = chan->con_priv;
288289
int ret;
289290

291+
pm_runtime_get_sync(priv->dev);
290292
if (cp->type == IMX_MU_TYPE_TXDB) {
291293
/* Tx doorbell don't have ACK support */
292294
tasklet_init(&cp->txdb_tasklet, imx_mu_txdb_tasklet,
@@ -323,6 +325,7 @@ static void imx_mu_shutdown(struct mbox_chan *chan)
323325

324326
if (cp->type == IMX_MU_TYPE_TXDB) {
325327
tasklet_kill(&cp->txdb_tasklet);
328+
pm_runtime_put_sync(priv->dev);
326329
return;
327330
}
328331

@@ -341,6 +344,7 @@ static void imx_mu_shutdown(struct mbox_chan *chan)
341344
}
342345

343346
free_irq(priv->irq, chan);
347+
pm_runtime_put_sync(priv->dev);
344348
}
345349

346350
static const struct mbox_chan_ops imx_mu_ops = {
@@ -508,14 +512,35 @@ static int imx_mu_probe(struct platform_device *pdev)
508512

509513
platform_set_drvdata(pdev, priv);
510514

511-
return devm_mbox_controller_register(dev, &priv->mbox);
515+
ret = devm_mbox_controller_register(dev, &priv->mbox);
516+
if (ret)
517+
return ret;
518+
519+
pm_runtime_enable(dev);
520+
521+
ret = pm_runtime_get_sync(dev);
522+
if (ret < 0) {
523+
pm_runtime_put_noidle(dev);
524+
goto disable_runtime_pm;
525+
}
526+
527+
ret = pm_runtime_put_sync(dev);
528+
if (ret < 0)
529+
goto disable_runtime_pm;
530+
531+
return 0;
532+
533+
disable_runtime_pm:
534+
pm_runtime_disable(dev);
535+
return ret;
512536
}
513537

514538
static int imx_mu_remove(struct platform_device *pdev)
515539
{
516540
struct imx_mu_priv *priv = platform_get_drvdata(pdev);
517541

518542
clk_disable_unprepare(priv->clk);
543+
pm_runtime_disable(priv->dev);
519544

520545
return 0;
521546
}

0 commit comments

Comments
 (0)