PM/sleep: fine-tune meson legacy early_suspend/late_resume flow
authorQiufang Dai <qiufang.dai@amlogic.com>
Fri, 21 Jul 2017 12:07:20 +0000 (20:07 +0800)
committerQiufang Dai <qiufang.dai@amlogic.com>
Tue, 25 Jul 2017 02:11:44 +0000 (19:11 -0700)
PD#147988: PM / sleep: meson: fine-tune legacy early_suspend/late_resume flow
1. early_suspend/late_resume could be call via sysfs or pm notify.
2. enable remote wakesource irq for wakeup freeze mode.

Change-Id: Ic667e19b9262af2a2a5c3534bd3ab4e240a868be
Signed-off-by: Qiufang Dai <qiufang.dai@amlogic.com>
arch/arm64/boot/dts/amlogic/mesonaxg.dtsi
drivers/amlogic/input/remote/remote_meson.c
drivers/amlogic/pm/gx_pm.c
drivers/amlogic/pm/lgcy_early_suspend.c
drivers/amlogic/pm/m8b_pm.c
include/linux/amlogic/pm.h

index 131efec..f07fa3a 100644 (file)
                method = "smc";
        };
 
+       meson_suspend:pm {
+               compatible = "amlogic, pm";
+               device_name = "aml_pm";
+               status = "okay";
+               reg = <0x0 0xff80023c 0x0 0x4>;
+       };
+
+
        secmon {
                compatible = "amlogic, secmon";
                memory-region = <&secmon_reserved>;
index 02c7f59..6ffbd73 100644 (file)
 #include <linux/amlogic/cpu_version.h>
 #include <linux/amlogic/pm.h>
 #include <linux/of_address.h>
-
-
 #include "remote_meson.h"
-
 #include <linux/amlogic/iomap.h>
 #include <linux/pm_wakeup.h>
+#include <linux/pm_wakeirq.h>
 
 static void amlremote_tasklet(unsigned long data);
 
@@ -564,6 +562,7 @@ static int remote_probe(struct platform_device *pdev)
                goto error_register_remote;
 
        device_init_wakeup(&pdev->dev, 1);
+       dev_pm_set_wake_irq(&pdev->dev, chip->irqno);
 
        return 0;
 
index 76dde03..d4c82b9 100644 (file)
@@ -185,7 +185,7 @@ static int __init meson_pm_probe(struct platform_device *pdev)
        exit_reg = of_iomap(pdev->dev.of_node, 0);
        device_create_file(&pdev->dev, &dev_attr_suspend_reason);
 #ifdef CONFIG_AMLOGIC_LEGACY_EARLY_SUSPEND
-       if (create_early_suspend_sysfs())
+       if (lgcy_early_suspend_init())
                return -1;
 #endif
        pr_info("meson_pm_probe done\n");
index 529082e..4cc4b09 100644 (file)
 #include <../kernel/power/power.h>
 
 static DEFINE_MUTEX(early_suspend_lock);
+static DEFINE_MUTEX(sysfs_trigger_lock);
 static LIST_HEAD(early_suspend_handlers);
 
+/* In order to handle legacy early_suspend driver,
+ * here we export sysfs interface
+ * for user space to write /sys/power/early_suspend_trigger to trigger
+ * early_suspend/late resume call back. If user space do not trigger
+ * early_suspend/late_resume, this op will be done
+ * by PM_SUSPEND_PREPARE notify.
+ */
+unsigned int sysfs_trigger;
+unsigned int early_suspend_state;
+/*
+ * Avoid run early_suspend/late_resume repeatly.
+ */
+unsigned int already_early_suspend;
+
 void register_early_suspend(struct early_suspend *handler)
 {
        struct list_head *pos;
@@ -66,31 +81,43 @@ void unregister_early_suspend(struct early_suspend *handler)
 }
 EXPORT_SYMBOL(unregister_early_suspend);
 
-static void early_suspend(void)
+static inline void early_suspend(void)
 {
        struct early_suspend *pos;
 
        mutex_lock(&early_suspend_lock);
 
+       if (!already_early_suspend)
+               already_early_suspend = 1;
+       else
+               goto end_early_suspend;
+
        pr_info("early_suspend: call handlers\n");
-       list_for_each_entry(pos, &early_suspend_handlers, link) {
+       list_for_each_entry(pos, &early_suspend_handlers, link)
                if (pos->suspend != NULL) {
                        pr_info("early_suspend: %pf\n", pos->suspend);
                        pos->suspend(pos);
                }
-       }
-       mutex_unlock(&early_suspend_lock);
 
        pr_info("early_suspend: done\n");
 
+end_early_suspend:
+       mutex_unlock(&early_suspend_lock);
+
+
 }
 
-static void late_resume(void)
+static inline void late_resume(void)
 {
        struct early_suspend *pos;
 
        mutex_lock(&early_suspend_lock);
 
+       if (already_early_suspend)
+               already_early_suspend = 0;
+       else
+               goto end_late_resume;
+
        pr_info("late_resume: call handlers\n");
        list_for_each_entry_reverse(pos, &early_suspend_handlers, link)
                if (pos->resume != NULL) {
@@ -99,10 +126,10 @@ static void late_resume(void)
                }
        pr_info("late_resume: done\n");
 
+end_late_resume:
        mutex_unlock(&early_suspend_lock);
 }
 
-unsigned int early_suspend_state;
 static ssize_t early_suspend_trigger_show(struct kobject *kobj,
                                struct kobj_attribute *attr,
                                char *buf)
@@ -125,10 +152,14 @@ static ssize_t early_suspend_trigger_store(struct kobject *kobj,
        if (ret)
                return -EINVAL;
 
+       mutex_lock(&sysfs_trigger_lock);
+       sysfs_trigger = 1;
+
        if (early_suspend_state == 0)
                late_resume();
        else if (early_suspend_state == 1)
                early_suspend();
+       mutex_unlock(&sysfs_trigger_lock);
 
        return n;
 }
@@ -143,11 +174,51 @@ static struct attribute_group attr_group = {
        .attrs = g,
 };
 
-unsigned int create_early_suspend_sysfs(void)
+void lgcy_early_suspend(void)
+{
+       mutex_lock(&sysfs_trigger_lock);
+
+       if (!sysfs_trigger)
+               early_suspend();
+
+       mutex_unlock(&sysfs_trigger_lock);
+}
+
+void lgcy_late_resume(void)
+{
+       mutex_lock(&sysfs_trigger_lock);
+
+       if (!sysfs_trigger)
+               late_resume();
+
+       mutex_unlock(&sysfs_trigger_lock);
+}
+
+
+static int lgcy_early_suspend_notify(struct notifier_block *nb,
+       unsigned long event, void *dummy)
 {
-       if (sysfs_create_group(power_kobj, &attr_group))
-               return -1;
+       if (event == PM_SUSPEND_PREPARE)
+               lgcy_early_suspend();
 
-       return 0;
+       if (event == PM_POST_SUSPEND)
+               lgcy_late_resume();
+
+       return NOTIFY_OK;
 }
 
+static struct notifier_block lgcy_early_suspend_notifier = {
+       .notifier_call = lgcy_early_suspend_notify,
+};
+
+unsigned int lgcy_early_suspend_init(void)
+{
+       int ret;
+
+       ret = sysfs_create_group(power_kobj, &attr_group);
+       if (ret)
+               return ret;
+
+       ret = register_pm_notifier(&lgcy_early_suspend_notifier);
+       return ret;
+}
index de1ca1d..9a905fb 100644 (file)
@@ -279,7 +279,7 @@ static int __init meson_pm_probe(struct platform_device *pdev)
 
        suspend_set_ops(&meson_pm_ops);
 #ifdef CONFIG_AMLOGIC_LEGACY_EARLY_SUSPEND
-       if (create_early_suspend_sysfs())
+       if (lgcy_early_suspend_init())
                return -1;
 #endif
        pr_info("meson_pm_probe done !\n");
index bc76cf6..85eea17 100644 (file)
@@ -49,7 +49,8 @@ struct early_suspend {
 };
 extern void register_early_suspend(struct early_suspend *handler);
 extern void unregister_early_suspend(struct early_suspend *handler);
-extern unsigned int create_early_suspend_sysfs(void);
+extern unsigned int lgcy_early_suspend_init(void);
+
 #endif //CONFIG_AMLOGIC_LEGACY_EARLY_SUSPEND
 
 #ifdef CONFIG_AMLOGIC_M8B_SUSPEND