RTC: system suspend, RTC can auto wake up the system
author许盛飞 <xsf@rock-chips.com>
Wed, 4 Jan 2012 11:51:31 +0000 (19:51 +0800)
committer许盛飞 <xsf@rock-chips.com>
Wed, 4 Jan 2012 11:54:08 +0000 (19:54 +0800)
drivers/rtc/Kconfig
drivers/rtc/Makefile
drivers/rtc/auto-wake.c [new file with mode: 0755]

index 68a0c106eb6a981e0de7db8a397d525f215ac796..a567a8e131e7f87aa0f0b2896ecbd279608b04a0 100755 (executable)
@@ -123,6 +123,14 @@ config RTC_INTF_ALARM_DEV
        help
          Exports the alarm interface to user-space.
 
+config AUTO_WAKE_UP
+       tristate "Support auto wake up"
+       depends on RTC_INTF_ALARM_DEV
+
+config AUTO_WAKE_UP_PERIOD
+       int "auto wake up period(sec)"
+       depends on AUTO_WAKE_UP
+       default 3600
 
 config RTC_DRV_TEST
        tristate "Test driver/device"
index a488d45cf72f38e8007f2618b61a08760244a52a..3f5e0685673bfc2abafdef611d6a49ca88542b50 100755 (executable)
@@ -15,6 +15,8 @@ rtc-core-$(CONFIG_RTC_INTF_DEV)       += rtc-dev.o
 rtc-core-$(CONFIG_RTC_INTF_PROC) += rtc-proc.o
 rtc-core-$(CONFIG_RTC_INTF_SYSFS) += rtc-sysfs.o
 
+obj-$(CONFIG_AUTO_WAKE_UP) += auto-wake.o
+
 # Keep the list ordered.
 
 obj-$(CONFIG_RTC_DRV_88PM860X)  += rtc-88pm860x.o
diff --git a/drivers/rtc/auto-wake.c b/drivers/rtc/auto-wake.c
new file mode 100755 (executable)
index 0000000..4642867
--- /dev/null
@@ -0,0 +1,128 @@
+#include <linux/android_alarm.h>
+#include <linux/device.h>
+#include <linux/miscdevice.h>
+#include <linux/platform_device.h>
+#include <linux/rtc.h>
+#include <linux/sched.h>
+#include <linux/spinlock.h>
+#include <linux/sysdev.h>
+#include <linux/wakelock.h>
+#include <linux/power_supply.h>
+#include <linux/suspend.h>
+
+#include <asm/mach/time.h>
+
+struct auto_wake
+{
+       struct alarm alarm;
+       struct timespec timer;
+       //struct notifier_block pm_nb;
+};
+
+static struct auto_wake auto_wake;
+struct timespec set_atuo_wake_time( struct timespec timer)
+{
+       struct timespec new_time;
+       struct timespec tmp_time;
+       
+       tmp_time =ktime_to_timespec(alarm_get_elapsed_realtime());
+
+       printk("nowtime = %ld \n",tmp_time.tv_sec);
+       
+       new_time.tv_nsec = timer.tv_nsec+ tmp_time.tv_nsec;
+       new_time.tv_sec =  timer.tv_sec+ tmp_time.tv_sec;
+
+       return new_time;
+}
+
+static void auto_wake_update(struct auto_wake *auto_wake)
+{
+
+       struct timespec new_alarm_time;
+       
+//     printk("auto_wake_update\n");
+       new_alarm_time = set_atuo_wake_time(auto_wake->timer);
+       alarm_start_range(&auto_wake->alarm,
+                       timespec_to_ktime(new_alarm_time),
+                       timespec_to_ktime(new_alarm_time));
+}
+
+static void atuo_wake_trigger(struct alarm *alarm)
+{
+
+       struct auto_wake *auto_wake = container_of(alarm, struct auto_wake,
+                                                   alarm);
+
+       auto_wake_update(auto_wake);
+}
+
+
+#if 0
+static void auto_wake_cancel(struct auto_wake *auto_wake)
+{
+       alarm_cancel(&auto_wake->alarm);
+}
+
+
+
+static int auto_wake_callback(struct notifier_block *nfb,
+                                       unsigned long action,
+                                       void *ignored)
+{
+
+       struct auto_wake *auto_wake = container_of(nfb, struct auto_wake,
+                                                   pm_nb);
+
+       switch (action)
+       {
+               case PM_SUSPEND_PREPARE:
+               {
+                       printk("PM_SUSPEND_PREPARExsf \n");
+                       auto_wake_update(auto_wake);
+                       return NOTIFY_OK;
+               }
+               case PM_POST_SUSPEND:
+               {
+                       printk("PM_POST_SUSPENDxsf \n");
+               //      auto_wake_cancel(auto_wake);
+                       return NOTIFY_OK;
+               }
+       }
+
+       return NOTIFY_DONE;
+}
+
+
+static struct notifier_block auto_wake_pm_notifier = {
+       .notifier_call = auto_wake_callback,
+       .priority = 0,
+};
+
+#endif
+
+void auto_wake_init(struct auto_wake *auto_wake,struct timespec timer)
+{
+//     auto_wake->pm_nb = auto_wake_pm_notifier;
+       auto_wake->timer = timer;
+       
+       alarm_init(&auto_wake->alarm,   ANDROID_ALARM_ELAPSED_REALTIME_WAKEUP, atuo_wake_trigger);
+
+       //register_pm_notifier(&auto_wake->pm_nb);// xsf
+
+}
+
+static int  __init start_auto_wake(void)
+{
+   
+       struct timespec timer;
+
+       printk("CONFIG_AUTO_WAKE_UP_PERIOD = %d\n", CONFIG_AUTO_WAKE_UP_PERIOD);
+       timer.tv_sec =   CONFIG_AUTO_WAKE_UP_PERIOD;
+       timer.tv_nsec = 0;
+       
+       auto_wake_init(&auto_wake,timer);
+       auto_wake_update(&auto_wake);
+       return 0;
+} 
+
+late_initcall_sync(start_auto_wake);