summaryrefslogtreecommitdiff
path: root/arch/arm/mach-tegra/tegra_bb.c
diff options
context:
space:
mode:
authorVinayak Pane <vpane@nvidia.com>2013-06-11 17:06:19 -0700
committerDan Willemsen <dwillemsen@nvidia.com>2013-09-14 13:37:38 -0700
commitaaf09c83ebd1dd6eb9930324177c8aa9fb0f3d0c (patch)
treefd56b5e72d558f2d375a618e92ab4bdbabebe47a /arch/arm/mach-tegra/tegra_bb.c
parented905c196c283e8d9b474b3ad669e9bd732a387e (diff)
arm: tegra14: bb: abort suspend when IPC is pending
If BBC has asserted IPC interrupt then abort the system suspend. This is to reduce the wakeup latency for BBC requests. Also, add function to check for pending BB IPC interrupt. Bug 1304608 Change-Id: Ie3766ab82c9e7f359cc9866dcf7ee163ab1aabc6 Signed-off-by: Vinayak Pane <vpane@nvidia.com> Reviewed-on: http://git-master/r/237796 (cherry picked from commit 7d65d264cae1810faa3e8193125a0da61da8dfce) Reviewed-on: http://git-master/r/254492 Reviewed-by: Automatic_Commit_Validation_User Reviewed-by: Steve Lin <stlin@nvidia.com>
Diffstat (limited to 'arch/arm/mach-tegra/tegra_bb.c')
-rw-r--r--arch/arm/mach-tegra/tegra_bb.c64
1 files changed, 50 insertions, 14 deletions
diff --git a/arch/arm/mach-tegra/tegra_bb.c b/arch/arm/mach-tegra/tegra_bb.c
index 3fc0aab6bbdb..889247c82f73 100644
--- a/arch/arm/mach-tegra/tegra_bb.c
+++ b/arch/arm/mach-tegra/tegra_bb.c
@@ -277,6 +277,25 @@ int tegra_bb_check_ipc(struct platform_device *dev)
}
EXPORT_SYMBOL_GPL(tegra_bb_check_ipc);
+int tegra_bb_check_bb2ap_ipc(void)
+{
+ void __iomem *fctrl = IO_ADDRESS(TEGRA_FLOW_CTRL_BASE);
+ void __iomem *pmc = IO_ADDRESS(TEGRA_PMC_BASE);
+ int sts;
+
+ sts = readl(pmc + APBDEV_PMC_IPC_PMC_IPC_STS_0);
+ sts = sts >> APBDEV_PMC_IPC_PMC_IPC_STS_0_AP2BB_RESET_SHIFT;
+ sts &= APBDEV_PMC_IPC_PMC_IPC_STS_0_AP2BB_RESET_DEFAULT_MASK;
+ if (!sts)
+ return 0;
+
+ sts = readl(fctrl + FLOW_CTLR_IPC_FLOW_IPC_STS_0);
+ if (sts & (1 << FLOW_CTLR_IPC_FLOW_IPC_STS_0_BB2AP_INT0_STS_SHIFT))
+ return 1;
+ return 0;
+}
+EXPORT_SYMBOL_GPL(tegra_bb_check_bb2ap_ipc);
+
static int tegra_bb_open(struct inode *inode, struct file *filp)
{
int ret;
@@ -1291,12 +1310,12 @@ static int tegra_bb_probe(struct platform_device *pdev)
}
#ifdef CONFIG_PM
-static int tegra_bb_suspend(struct platform_device *pdev, pm_message_t state)
+static int tegra_bb_suspend(struct device *dev)
{
void __iomem *fctrl = IO_ADDRESS(TEGRA_FLOW_CTRL_BASE);
int sts;
- dev_dbg(&pdev->dev, "%s\n", __func__);
+ dev_dbg(dev, "%s\n", __func__);
/* Be sure to ack any pending irq from BB */
sts = readl(fctrl + FLOW_CTLR_IPC_FLOW_IPC_STS_0);
@@ -1307,22 +1326,18 @@ static int tegra_bb_suspend(struct platform_device *pdev, pm_message_t state)
return 0;
}
-static int tegra_bb_resume(struct platform_device *pdev)
+static int tegra_bb_resume(struct device *dev)
{
#ifndef CONFIG_TEGRA_BASEBAND_SIMU
struct tegra_bb *bb;
struct tegra_bb_platform_data *pdata;
#endif
- if (!pdev) {
- pr_err("%s platform device is NULL!\n", __func__);
- return -EINVAL;
- }
- dev_dbg(&pdev->dev, "%s\n", __func__);
+ dev_dbg(dev, "%s\n", __func__);
#ifndef CONFIG_TEGRA_BASEBAND_SIMU
- pdata = pdev->dev.platform_data;
+ pdata = dev->platform_data;
if (!pdata) {
- dev_err(&pdev->dev, "%s platform dev not found!\n", __func__);
+ dev_err(dev, "%s platform dev not found!\n", __func__);
return -EINVAL;
}
bb = (struct tegra_bb *)pdata->bb_handle;
@@ -1335,18 +1350,39 @@ static int tegra_bb_resume(struct platform_device *pdev)
#endif
return 0;
}
+
+static int tegra_bb_suspend_noirq(struct device *dev)
+{
+ dev_dbg(dev, "%s\n", __func__);
+
+ /* abort suspend if IPC interrupt is pending*/
+ if (tegra_bb_check_bb2ap_ipc())
+ return -EBUSY;
+ return 0;
+}
+
+static int tegra_bb_resume_noirq(struct device *dev)
+{
+ return 0;
+}
+
+static const struct dev_pm_ops tegra_bb_pm_ops = {
+ .suspend_noirq = tegra_bb_suspend_noirq,
+ .resume_noirq = tegra_bb_resume_noirq,
+ .suspend = tegra_bb_suspend,
+ .resume = tegra_bb_resume,
+};
#endif
static struct platform_driver tegra_bb_driver = {
.driver = {
.name = "tegra_bb",
.owner = THIS_MODULE,
- },
- .probe = tegra_bb_probe,
#ifdef CONFIG_PM
- .suspend = tegra_bb_suspend,
- .resume = tegra_bb_resume,
+ .pm = &tegra_bb_pm_ops,
#endif
+ },
+ .probe = tegra_bb_probe,
};
static int __init tegra_bb_init(void)