Merge tag 'v3.10.56' into update
[GitHub/mt8127/android_kernel_alcatel_ttab.git] / kernel / time / alarmtimer.c
index 7d19fca0617e94649ac3161ca6443da201ab70cd..1303df8ab3bd2de8e5adf1c5637d55dc2f0ca4bb 100644 (file)
 #include <linux/posix-timers.h>
 #include <linux/workqueue.h>
 #include <linux/freezer.h>
+#include <linux/xlog.h>
+#include <linux/module.h>
+#include <mach/mtk_rtc.h>
+
+#define XLOG_MYTAG     "Power/Alarm"
+
+#define ANDROID_ALARM_PRINT_INFO (1U << 0)
+#define ANDROID_ALARM_PRINT_IO (1U << 1)
+#define ANDROID_ALARM_PRINT_INT (1U << 2)
+
+static int debug_mask = ANDROID_ALARM_PRINT_INFO;
+module_param_named(debug_mask, debug_mask, int, S_IRUGO | S_IWUSR | S_IWGRP);
+
+#define alarm_dbg(debug_level_mask, fmt, args...)                              \
+do {                                                                   \
+       if (debug_mask & ANDROID_ALARM_PRINT_##debug_level_mask)        \
+               xlog_printk(ANDROID_LOG_INFO, XLOG_MYTAG, fmt, ##args); \
+} while (0)
 
 /**
  * struct alarm_base - Alarm timer bases
@@ -84,8 +102,8 @@ static int alarmtimer_rtc_add_device(struct device *dev,
 
        if (!rtc->ops->set_alarm)
                return -1;
-       if (!device_may_wakeup(rtc->dev.parent))
-               return -1;
+       //if (!device_may_wakeup(rtc->dev.parent))
+       //      return -1;
 
        spin_lock_irqsave(&rtcdev_lock, flags);
        if (!rtcdev) {
@@ -126,6 +144,52 @@ static inline void alarmtimer_rtc_interface_remove(void) { }
 static inline void alarmtimer_rtc_timer_init(void) { }
 #endif
 
+void alarm_set_power_on(struct timespec new_pwron_time, bool logo)
+{
+       unsigned long pwron_time;
+       struct rtc_wkalrm alm;
+       struct rtc_device *alarm_rtc_dev;
+//     ktime_t now;
+       
+       printk("alarm set power on\n");
+       
+#ifdef RTC_PWRON_SEC
+       /* round down the second */
+       new_pwron_time.tv_sec = (new_pwron_time.tv_sec / 60) * 60;
+#endif
+       if (new_pwron_time.tv_sec > 0) {
+               pwron_time = new_pwron_time.tv_sec;
+#ifdef RTC_PWRON_SEC
+               pwron_time += RTC_PWRON_SEC;
+#endif
+               alm.enabled = (logo ? 3 : 2);
+       } else {
+               pwron_time = 0;
+               alm.enabled = 4;
+       }
+       alarm_rtc_dev = alarmtimer_get_rtcdev();
+       rtc_time_to_tm(pwron_time, &alm.time);
+/*     
+       rtc_timer_cancel(alarm_rtc_dev, &rtctimer);
+       now = rtc_tm_to_ktime(alm.time);
+       rtc_timer_start(alarm_rtc_dev, &rtctimer, now, ktime_set(0, 0));
+*/
+       rtc_timer_cancel(alarm_rtc_dev, &rtctimer);
+       rtc_set_alarm(alarm_rtc_dev, &alm);
+       rtc_set_alarm_poweron(alarm_rtc_dev, &alm);
+}
+
+void alarm_get_power_on(struct rtc_wkalrm *alm)
+{
+       if (!alm)
+               return;
+
+       memset(alm, 0, sizeof(struct rtc_wkalrm));
+#ifndef CONFIG_MTK_FPGA
+       rtc_read_pwron_alarm(alm);
+#endif
+}
+
 /**
  * alarmtimer_enqueue - Adds an alarm timer to an alarm_base timerqueue
  * @base: pointer to the base where the timer is being run
@@ -180,6 +244,8 @@ static enum hrtimer_restart alarmtimer_fired(struct hrtimer *timer)
        int ret = HRTIMER_NORESTART;
        int restart = ALARMTIMER_NORESTART;
 
+       alarm_dbg(INT, "alarmtimer_fired \n");
+       
        spin_lock_irqsave(&base->lock, flags);
        alarmtimer_dequeue(base, alarm);
        spin_unlock_irqrestore(&base->lock, flags);
@@ -199,6 +265,12 @@ static enum hrtimer_restart alarmtimer_fired(struct hrtimer *timer)
 
 }
 
+ktime_t alarm_expires_remaining(const struct alarm *alarm)
+{
+       struct alarm_base *base = &alarm_bases[alarm->type];
+       return ktime_sub(alarm->node.expires, base->gettime());
+}
+
 #ifdef CONFIG_RTC_CLASS
 /**
  * alarmtimer_suspend - Suspend time callback
@@ -244,10 +316,12 @@ static int alarmtimer_suspend(struct device *dev)
                if (!min.tv64 || (delta.tv64 < min.tv64))
                        min = delta;
        }
-       if (min.tv64 == 0)
+       if (min.tv64 == 0) {
+               alarm_dbg(INT,  "min.tv64 == 0\n");
                return 0;
-
+       }
        if (ktime_to_ns(min) < 2 * NSEC_PER_SEC) {
+               alarm_dbg(INT, "min.tv64 < 2S, give up suspend\n");
                __pm_wakeup_event(ws, 2 * MSEC_PER_SEC);
                return -EBUSY;
        }
@@ -258,6 +332,11 @@ static int alarmtimer_suspend(struct device *dev)
        now = rtc_tm_to_ktime(tm);
        now = ktime_add(now, min);
 
+       alarm_dbg(INFO, "now:%02d=%02d:%02d %02d/%02d/%04d. min.tv64=%lld\n",
+               tm.tm_hour, tm.tm_min,
+               tm.tm_sec, tm.tm_mon + 1,
+               tm.tm_mday,
+               tm.tm_year + 1900, min.tv64);
        /* Set alarm, if in the past reject suspend briefly to handle */
        ret = rtc_timer_start(rtc, &rtctimer, now, ktime_set(0, 0));
        if (ret < 0)
@@ -305,7 +384,7 @@ void alarm_init(struct alarm *alarm, enum alarmtimer_type type,
 }
 
 /**
- * alarm_start - Sets an alarm to fire
+ * alarm_start - Sets an absolute alarm to fire
  * @alarm: ptr to alarm to set
  * @start: time to run the alarm
  */
@@ -324,6 +403,31 @@ int alarm_start(struct alarm *alarm, ktime_t start)
        return ret;
 }
 
+/**
+ * alarm_start_relative - Sets a relative alarm to fire
+ * @alarm: ptr to alarm to set
+ * @start: time relative to now to run the alarm
+ */
+int alarm_start_relative(struct alarm *alarm, ktime_t start)
+{
+       struct alarm_base *base = &alarm_bases[alarm->type];
+
+       start = ktime_add(start, base->gettime());
+       return alarm_start(alarm, start);
+}
+
+void alarm_restart(struct alarm *alarm)
+{
+       struct alarm_base *base = &alarm_bases[alarm->type];
+       unsigned long flags;
+
+       spin_lock_irqsave(&base->lock, flags);
+       hrtimer_set_expires(&alarm->timer, alarm->node.expires);
+       hrtimer_restart(&alarm->timer);
+       alarmtimer_enqueue(base, alarm);
+       spin_unlock_irqrestore(&base->lock, flags);
+}
+
 /**
  * alarm_try_to_cancel - Tries to cancel an alarm timer
  * @alarm: ptr to alarm to be canceled
@@ -394,6 +498,12 @@ u64 alarm_forward(struct alarm *alarm, ktime_t now, ktime_t interval)
        return overrun;
 }
 
+u64 alarm_forward_now(struct alarm *alarm, ktime_t interval)
+{
+       struct alarm_base *base = &alarm_bases[alarm->type];
+
+       return alarm_forward(alarm, base->gettime(), interval);
+}