summaryrefslogtreecommitdiffstats
path: root/drivers/mailbox/omap-mailbox.c
diff options
context:
space:
mode:
authorSuman Anna <s-anna@ti.com>2016-04-07 01:37:18 +0200
committerJassi Brar <jaswinder.singh@linaro.org>2016-04-26 06:49:38 +0200
commitaf1d2f5cb9d24f0e477158dada6baf893a32ee04 (patch)
treed88c0fd9404e510c205a535f1c329bdba6a68b36 /drivers/mailbox/omap-mailbox.c
parentmailbox/omap: store mailbox interrupt type in omap_mbox_device (diff)
downloadlinux-af1d2f5cb9d24f0e477158dada6baf893a32ee04.tar.xz
linux-af1d2f5cb9d24f0e477158dada6baf893a32ee04.zip
mailbox/omap: add support for suspend/resume
Support has been added to the OMAP mailbox driver to allow it to work across a system suspend/resume. The OMAP mailbox driver requires only the interrupt configuration registers to be saved and restored, and this is done in the suspend/resume callbacks. The registers need to be saved only if there are active clients at the time of suspend. The enabling and disabling of the mailbox clocks is done automatically by the omap_device layer. Signed-off-by: Suman Anna <s-anna@ti.com> Signed-off-by: Jassi Brar <jaswinder.singh@linaro.org>
Diffstat (limited to 'drivers/mailbox/omap-mailbox.c')
-rw-r--r--drivers/mailbox/omap-mailbox.c45
1 files changed, 45 insertions, 0 deletions
diff --git a/drivers/mailbox/omap-mailbox.c b/drivers/mailbox/omap-mailbox.c
index d837def4c390..e402aa23226d 100644
--- a/drivers/mailbox/omap-mailbox.c
+++ b/drivers/mailbox/omap-mailbox.c
@@ -88,6 +88,7 @@ struct omap_mbox_device {
struct device *dev;
struct mutex cfg_lock;
void __iomem *mbox_base;
+ u32 *irq_ctx;
u32 num_users;
u32 num_fifos;
u32 intr_type;
@@ -650,6 +651,44 @@ static const struct mbox_chan_ops omap_mbox_chan_ops = {
.shutdown = omap_mbox_chan_shutdown,
};
+#ifdef CONFIG_PM_SLEEP
+static int omap_mbox_suspend(struct device *dev)
+{
+ struct omap_mbox_device *mdev = dev_get_drvdata(dev);
+ u32 usr, reg;
+
+ if (pm_runtime_status_suspended(dev))
+ return 0;
+
+ for (usr = 0; usr < mdev->num_users; usr++) {
+ reg = MAILBOX_IRQENABLE(mdev->intr_type, usr);
+ mdev->irq_ctx[usr] = mbox_read_reg(mdev, reg);
+ }
+
+ return 0;
+}
+
+static int omap_mbox_resume(struct device *dev)
+{
+ struct omap_mbox_device *mdev = dev_get_drvdata(dev);
+ u32 usr, reg;
+
+ if (pm_runtime_status_suspended(dev))
+ return 0;
+
+ for (usr = 0; usr < mdev->num_users; usr++) {
+ reg = MAILBOX_IRQENABLE(mdev->intr_type, usr);
+ mbox_write_reg(mdev, mdev->irq_ctx[usr], reg);
+ }
+
+ return 0;
+}
+#endif
+
+static const struct dev_pm_ops omap_mbox_pm_ops = {
+ SET_SYSTEM_SLEEP_PM_OPS(omap_mbox_suspend, omap_mbox_resume)
+};
+
static const struct of_device_id omap_mailbox_of_match[] = {
{
.compatible = "ti,omap2-mailbox",
@@ -777,6 +816,11 @@ static int omap_mbox_probe(struct platform_device *pdev)
if (IS_ERR(mdev->mbox_base))
return PTR_ERR(mdev->mbox_base);
+ mdev->irq_ctx = devm_kzalloc(&pdev->dev, num_users * sizeof(u32),
+ GFP_KERNEL);
+ if (!mdev->irq_ctx)
+ return -ENOMEM;
+
/* allocate one extra for marking end of list */
list = devm_kzalloc(&pdev->dev, (info_count + 1) * sizeof(*list),
GFP_KERNEL);
@@ -887,6 +931,7 @@ static struct platform_driver omap_mbox_driver = {
.remove = omap_mbox_remove,
.driver = {
.name = "omap-mailbox",
+ .pm = &omap_mbox_pm_ops,
.of_match_table = of_match_ptr(omap_mailbox_of_match),
},
};