summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorArun Murthy <arun.murthy@stericsson.com>2011-09-30 14:21:55 +0530
committerMathieu J. Poirier <mathieu.poirier@linaro.org>2011-11-10 11:12:19 -0700
commitb2d1f46c3cf65a49af1d59a2ba5274305364976e (patch)
tree0a805f39e55eeeee82bf549c001f2aebfb425093
parent17c646a9195757faad8dcd901a5026bc29171c6d (diff)
ux500-mbox: Proper shutdown of mailbox
Implement clean shutdown of mailbox, which includes, unmapping the io mapped memory, free the requested interrupt, reset all state machine and remove from list. A function has been added to reset the mailbox which will be used in case of MSR. ST-Ericsson Linux next: NA ST-Ericsson ID: 341807 ST-Ericsson FOSS-OUT ID: Trivial Change-Id: I1435345d155717a5276a7a5d74da84d3eeef7f61 Signed-off-by: Arun Murthy <arun.murthy@stericsson.com> Reviewed-on: http://gerrit.lud.stericsson.com/gerrit/32680 Reviewed-by: Srinidhi KASAGAR <srinidhi.kasagar@stericsson.com>
-rw-r--r--arch/arm/mach-ux500/include/mach/mbox-db5500.h5
-rw-r--r--drivers/misc/mbox.c79
2 files changed, 77 insertions, 7 deletions
diff --git a/arch/arm/mach-ux500/include/mach/mbox-db5500.h b/arch/arm/mach-ux500/include/mach/mbox-db5500.h
index 7f9da4d2fbd..24af854befe 100644
--- a/arch/arm/mach-ux500/include/mach/mbox-db5500.h
+++ b/arch/arm/mach-ux500/include/mach/mbox-db5500.h
@@ -40,6 +40,7 @@ typedef void mbox_recv_cb_t (u32 mbox_msg, void *priv);
* @lock: Spinlock to protect this mailbox instance.
* @write_index: Index in internal buffer to write to.
* @read_index: Index in internal buffer to read from.
+ * @irq: mailbox interrupt.
* @allocated: Indicates whether this particular mailbox
* id has been allocated by someone.
*/
@@ -57,7 +58,11 @@ struct mbox {
spinlock_t lock;
u8 write_index;
u8 read_index;
+ int irq;
bool allocated;
+#if defined(CONFIG_DEBUG_FS)
+ struct dentry *dentry;
+#endif
};
/**
diff --git a/drivers/misc/mbox.c b/drivers/misc/mbox.c
index 73f34069d84..9bd5db9b23c 100644
--- a/drivers/misc/mbox.c
+++ b/drivers/misc/mbox.c
@@ -380,11 +380,35 @@ exit:
return IRQ_HANDLED;
}
+static void mbox_shutdown(struct mbox *mbox)
+{
+#if defined(CONFIG_DEBUG_FS)
+ debugfs_remove(mbox->dentry);
+ device_remove_file(&mbox->pdev->dev, &dev_attr_fifo);
+#endif
+ writel(MBOX_DISABLE_IRQ, mbox->virtbase_local + MBOX_FIFO_THRES_OCCUP);
+ writel(MBOX_DISABLE_IRQ, mbox->virtbase_peer + MBOX_FIFO_THRES_FREE);
+ free_irq(mbox->irq, NULL);
+ mbox->client_blocked = 0;
+ iounmap(mbox->virtbase_local);
+ iounmap(mbox->virtbase_peer);
+ mbox->cb = NULL;
+ mbox->client_data = NULL;
+ mbox->allocated = false;
+}
+
+void mbox_reset_state(struct mbox *mbox)
+{
+ list_for_each_entry(mbox, &mboxs, list) {
+ mbox_shutdown(mbox);
+ }
+}
+
+
/* Setup is executed once for each mbox pair */
struct mbox *mbox_setup(u8 mbox_id, mbox_recv_cb_t *mbox_cb, void *priv)
{
struct resource *resource;
- int irq;
int res;
struct mbox *mbox;
@@ -463,21 +487,21 @@ struct mbox *mbox_setup(u8 mbox_id, mbox_recv_cb_t *mbox_cb, void *priv)
mbox->client_blocked = 0;
/* Get IRQ for mailbox and allocate it */
- irq = platform_get_irq_byname(mbox->pdev, "mbox_irq");
- if (irq < 0) {
+ mbox->irq = platform_get_irq_byname(mbox->pdev, "mbox_irq");
+ if (mbox->irq < 0) {
dev_err(&(mbox->pdev->dev),
"Unable to retrieve mbox irq resource\n");
mbox = NULL;
goto exit;
}
- dev_dbg(&(mbox->pdev->dev), "Allocating irq %d...\n", irq);
- res = request_threaded_irq(irq, NULL, mbox_irq,
+ dev_dbg(&(mbox->pdev->dev), "Allocating irq %d...\n", mbox->irq);
+ res = request_threaded_irq(mbox->irq, NULL, mbox_irq,
IRQF_NO_SUSPEND | IRQF_ONESHOT,
mbox->name, (void *) mbox);
if (res < 0) {
dev_err(&(mbox->pdev->dev),
- "Unable to allocate mbox irq %d\n", irq);
+ "Unable to allocate mbox irq %d\n", mbox->irq);
mbox = NULL;
goto exit;
}
@@ -503,7 +527,7 @@ struct mbox *mbox_setup(u8 mbox_id, mbox_recv_cb_t *mbox_cb, void *priv)
dev_warn(&(mbox->pdev->dev),
"Unable to create mbox sysfs entry");
- (void) debugfs_create_file("mbox", S_IFREG | S_IRUGO, NULL,
+ mbox->dentry = debugfs_create_file("mbox", S_IFREG | S_IRUGO, NULL,
NULL, &mbox_operations);
#endif
@@ -550,16 +574,57 @@ static int __exit mbox_remove(struct platform_device *pdev)
{
struct mbox *mbox = platform_get_drvdata(pdev);
+ mbox_shutdown(mbox);
list_del(&mbox->list);
kfree(mbox);
return 0;
}
+#ifdef CONFIG_PM
+int mbox_suspend(struct device *dev)
+{
+ struct platform_device *pdev = to_platform_device(dev);
+ struct mbox *mbox = platform_get_drvdata(pdev);
+
+ /*
+ * Nothing to be done for now, once APE-Modem power management is
+ * in place communication will have to be stopped.
+ */
+
+ list_for_each_entry(mbox, &mboxs, list) {
+ if (mbox->client_blocked)
+ return -EBUSY;
+ }
+ return 0;
+}
+
+int mbox_resume(struct device *dev)
+{
+ struct platform_device *pdev = to_platform_device(dev);
+ struct mbox *mbox = platform_get_drvdata(pdev);
+
+ /*
+ * Nothing to be done for now, once APE-Modem power management is
+ * in place communication will have to be resumed.
+ */
+
+ return 0;
+}
+
+static const struct dev_pm_ops mbox_dev_pm_ops = {
+ .suspend_noirq = mbox_suspend,
+ .resume_noirq = mbox_resume,
+};
+#endif
+
static struct platform_driver mbox_driver = {
.remove = __exit_p(mbox_remove),
.driver = {
.name = MBOX_NAME,
.owner = THIS_MODULE,
+#ifdef CONFIG_PM
+ .pm = &mbox_dev_pm_ops,
+#endif
},
};