diff options
author | David Lin <dtwlin@google.com> | 2016-04-16 01:15:15 +0530 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@google.com> | 2016-04-15 14:42:53 -0700 |
commit | 9160b7c7652a80f48250bbdc151fa0af3ccf024f (patch) | |
tree | bc36b14862404205c5cb59cf9fce12e93bb4a7fb /drivers/staging/greybus/arche-platform.c | |
parent | greybus: Fixup __u64, __u32 to __le64, __le32 in timesync declarations (diff) | |
download | linux-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.c | 35 |
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); |