aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/staging/greybus/arche-platform.c
diff options
context:
space:
mode:
authorDavid Lin <dtwlin@google.com>2016-04-16 01:15:15 +0530
committerGreg Kroah-Hartman <gregkh@google.com>2016-04-15 14:42:53 -0700
commit9160b7c7652a80f48250bbdc151fa0af3ccf024f (patch)
treebc36b14862404205c5cb59cf9fce12e93bb4a7fb /drivers/staging/greybus/arche-platform.c
parentgreybus: Fixup __u64, __u32 to __le64, __le32 in timesync declarations (diff)
downloadlinux-dev-9160b7c7652a80f48250bbdc151fa0af3ccf024f.tar.xz
linux-dev-9160b7c7652a80f48250bbdc151fa0af3ccf024f.zip
greybus: arche-platform: Power-off unipro subsystem upon suspend
Switch off APBs/SVC/Switch in the suspend call notifier. Note that this is an interim solution to enable fishfooding. Testing done: - Passed QA sanity test on EVT1.5 - Suspend current measured at ~70mW Signed-off-by: David Lin <dtwlin@google.com> Signed-off-by: Vaibhav Hiremath <vaibhav.hiremath@linaro.org> [vaibhav.hiremath@linaro.org: Updated commit description] Tested-by: Sandeep Patil <sspatil@google.com> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com>
Diffstat (limited to 'drivers/staging/greybus/arche-platform.c')
-rw-r--r--drivers/staging/greybus/arche-platform.c35
1 files changed, 35 insertions, 0 deletions
diff --git a/drivers/staging/greybus/arche-platform.c b/drivers/staging/greybus/arche-platform.c
index 48cdb0fffcfc..3ff4f69685bd 100644
--- a/drivers/staging/greybus/arche-platform.c
+++ b/drivers/staging/greybus/arche-platform.c
@@ -19,6 +19,7 @@
#include <linux/pm.h>
#include <linux/interrupt.h>
#include <linux/irq.h>
+#include <linux/suspend.h>
#include <linux/time.h>
#include "arche_platform.h"
@@ -56,6 +57,7 @@ struct arche_platform_drvdata {
int wake_detect_irq;
spinlock_t lock;
unsigned long wake_detect_start;
+ struct notifier_block pm_notifier;
struct device *dev;
};
@@ -339,6 +341,31 @@ static ssize_t state_show(struct device *dev,
static DEVICE_ATTR_RW(state);
+static int arche_platform_pm_notifier(struct notifier_block *notifier,
+ unsigned long pm_event, void *unused)
+{
+ struct arche_platform_drvdata *arche_pdata =
+ container_of(notifier, struct arche_platform_drvdata,
+ pm_notifier);
+
+ switch (pm_event) {
+ case PM_SUSPEND_PREPARE:
+ if (arche_pdata->state != ARCHE_PLATFORM_STATE_ACTIVE)
+ return NOTIFY_STOP;
+ device_for_each_child(arche_pdata->dev, NULL, apb_poweroff);
+ arche_platform_poweroff_seq(arche_pdata);
+ break;
+ case PM_POST_SUSPEND:
+ arche_platform_coldboot_seq(arche_pdata);
+ assert_wakedetect(arche_pdata);
+ break;
+ default:
+ break;
+ }
+
+ return NOTIFY_DONE;
+}
+
static int arche_platform_probe(struct platform_device *pdev)
{
struct arche_platform_drvdata *arche_pdata;
@@ -474,6 +501,13 @@ static int arche_platform_probe(struct platform_device *pdev)
assert_wakedetect(arche_pdata);
+ arche_pdata->pm_notifier.notifier_call = arche_platform_pm_notifier;
+ ret = register_pm_notifier(&arche_pdata->pm_notifier);
+ if (ret) {
+ dev_err(dev, "failed to register pm notifier %d\n", ret);
+ goto err_populate;
+ }
+
dev_info(dev, "Device registered successfully\n");
return 0;
@@ -497,6 +531,7 @@ static int arche_platform_remove(struct platform_device *pdev)
{
struct arche_platform_drvdata *arche_pdata = platform_get_drvdata(pdev);
+ unregister_pm_notifier(&arche_pdata->pm_notifier);
device_remove_file(&pdev->dev, &dev_attr_state);
device_for_each_child(&pdev->dev, NULL, arche_remove_child);
arche_platform_poweroff_seq(arche_pdata);