import PULS_20160108
[GitHub/mt8127/android_kernel_alcatel_ttab.git] / drivers / staging / android / alarm-dev.c
index 6dc27dac679d9133052b7aca2ad2ea06cf1d3486..86c141337543ff934ad351802e8a3bd5f813fe18 100644 (file)
  *
  */
 
+#ifdef pr_fmt
+#undef pr_fmt 
+#endif
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
 #include <linux/time.h>
 #include <linux/module.h>
 #include <linux/device.h>
@@ -24,6 +28,9 @@
 #include <linux/uaccess.h>
 #include <linux/alarmtimer.h>
 #include "android_alarm.h"
+#include <linux/xlog.h>
+#include <linux/ioctl.h>
+#define LOG_MYTAG      "Power/Alarm"
 
 #define ANDROID_ALARM_PRINT_INFO (1U << 0)
 #define ANDROID_ALARM_PRINT_IO (1U << 1)
 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, ...)                          \
+#define alarm_dbg(debug_level_mask, fmt, args...)                              \
 do {                                                                   \
        if (debug_mask & ANDROID_ALARM_PRINT_##debug_level_mask)        \
-               pr_info(fmt, ##__VA_ARGS__);                            \
+                       xlog_printk(ANDROID_LOG_INFO, LOG_MYTAG, fmt, ##args); \
 } while (0)
 
 #define ANDROID_ALARM_WAKEUP_MASK ( \
@@ -92,13 +99,21 @@ static void devalarm_cancel(struct devalarm *alrm)
                hrtimer_cancel(&alrm->u.hrt);
 }
 
-static void alarm_clear(enum android_alarm_type alarm_type)
+static void alarm_clear(enum android_alarm_type alarm_type,
+                                                       struct timespec *ts)
 {
        uint32_t alarm_type_mask = 1U << alarm_type;
        unsigned long flags;
-
-       spin_lock_irqsave(&alarm_slock, flags);
+       
+       
        alarm_dbg(IO, "alarm %d clear\n", alarm_type);
+       if (alarm_type == ANDROID_ALARM_POWER_ON ||
+               alarm_type == ANDROID_ALARM_POWER_ON_LOGO) {
+               ts->tv_sec = 0;
+               alarm_set_power_on(*ts, false);
+               return;
+       }
+       spin_lock_irqsave(&alarm_slock, flags);
        devalarm_try_to_cancel(&alarms[alarm_type]);
        if (alarm_pending) {
                alarm_pending &= ~alarm_type_mask;
@@ -116,9 +131,18 @@ static void alarm_set(enum android_alarm_type alarm_type,
        uint32_t alarm_type_mask = 1U << alarm_type;
        unsigned long flags;
 
-       spin_lock_irqsave(&alarm_slock, flags);
-       alarm_dbg(IO, "alarm %d set %ld.%09ld\n",
+       alarm_dbg(INFO, "alarm %d set %ld.%09ld\n",
                        alarm_type, ts->tv_sec, ts->tv_nsec);
+       if (alarm_type == ANDROID_ALARM_POWER_ON) {
+               alarm_set_power_on(*ts, false);
+               return;
+       }
+       if (alarm_type == ANDROID_ALARM_POWER_ON_LOGO) {
+               alarm_set_power_on(*ts, true);
+               return;
+       }
+
+       spin_lock_irqsave(&alarm_slock, flags);
        alarm_enabled |= alarm_type_mask;
        devalarm_start(&alarms[alarm_type], timespec_to_ktime(*ts));
        spin_unlock_irqrestore(&alarm_slock, flags);
@@ -158,6 +182,12 @@ static int alarm_set_rtc(struct timespec *ts)
        int rv = 0;
 
        rtc_time_to_tm(ts->tv_sec, &new_rtc_tm);
+       alarm_dbg(INFO, "set rtc %ld %ld - rtc %02d:%02d:%02d %02d/%02d/%04d\n",
+       ts->tv_sec, ts->tv_nsec,
+       new_rtc_tm.tm_hour, new_rtc_tm.tm_min,
+       new_rtc_tm.tm_sec, new_rtc_tm.tm_mon + 1,
+       new_rtc_tm.tm_mday,
+       new_rtc_tm.tm_year + 1900);
        rtc_dev = alarmtimer_get_rtcdev();
        rv = do_settimeofday(ts);
        if (rv < 0)
@@ -190,6 +220,9 @@ static int alarm_get_time(enum android_alarm_type alarm_type,
        case ANDROID_ALARM_SYSTEMTIME:
                ktime_get_ts(ts);
                break;
+       case ANDROID_ALARM_POWER_ON:
+       case ANDROID_ALARM_POWER_ON_LOGO:
+               break;
        default:
                rv = -EINVAL;
        }
@@ -197,16 +230,20 @@ static int alarm_get_time(enum android_alarm_type alarm_type,
 }
 
 static long alarm_do_ioctl(struct file *file, unsigned int cmd,
-                                                       struct timespec *ts)
+                                                       struct timespec *ts, struct rtc_wkalrm *alm)
 {
        int rv = 0;
        unsigned long flags;
        enum android_alarm_type alarm_type = ANDROID_ALARM_IOCTL_TO_TYPE(cmd);
 
-       if (alarm_type >= ANDROID_ALARM_TYPE_COUNT)
+       if (alarm_type >= ANDROID_ALARM_TYPE_COUNT &&
+               alarm_type != ANDROID_ALARM_POWER_ON &&
+               alarm_type != ANDROID_ALARM_POWER_ON_LOGO) {
                return -EINVAL;
-
-       if (ANDROID_ALARM_BASE_CMD(cmd) != ANDROID_ALARM_GET_TIME(0)) {
+       }
+       if (ANDROID_ALARM_BASE_CMD(cmd) != ANDROID_ALARM_GET_TIME(0) 
+               && ANDROID_ALARM_BASE_CMD(cmd) != ANDROID_ALARM_SET_IPO(0)
+                               && ANDROID_ALARM_BASE_CMD(cmd) != ANDROID_ALARM_GET_POWER_ON_IPO) {
                if ((file->f_flags & O_ACCMODE) == O_RDONLY)
                        return -EPERM;
                if (file->private_data == NULL &&
@@ -224,7 +261,7 @@ static long alarm_do_ioctl(struct file *file, unsigned int cmd,
 
        switch (ANDROID_ALARM_BASE_CMD(cmd)) {
        case ANDROID_ALARM_CLEAR(0):
-               alarm_clear(alarm_type);
+               alarm_clear(alarm_type, ts);
                break;
        case ANDROID_ALARM_SET(0):
                alarm_set(alarm_type, ts);
@@ -235,13 +272,28 @@ static long alarm_do_ioctl(struct file *file, unsigned int cmd,
        case ANDROID_ALARM_WAIT:
                rv = alarm_wait();
                break;
+       case ANDROID_ALARM_SET_IPO(0):
+               alarm_set(alarm_type, ts);
+               break;
+       case ANDROID_ALARM_SET_AND_WAIT_IPO(0):
+               alarm_set(alarm_type, ts);
+               /* fall though */
+       case ANDROID_ALARM_WAIT_IPO:
+               rv = alarm_wait();
+               break;
        case ANDROID_ALARM_SET_RTC:
                rv = alarm_set_rtc(ts);
                break;
        case ANDROID_ALARM_GET_TIME(0):
                rv = alarm_get_time(alarm_type, ts);
                break;
-
+       case ANDROID_ALARM_GET_POWER_ON:
+               alarm_get_power_on(alm);
+               break;
+       case ANDROID_ALARM_GET_POWER_ON_IPO:
+               alarm_get_power_on(alm);
+               break;
+               
        default:
                rv = -EINVAL;
        }
@@ -252,18 +304,21 @@ static long alarm_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
 {
 
        struct timespec ts;
+       struct rtc_wkalrm pwron_alm;
+
        int rv;
 
        switch (ANDROID_ALARM_BASE_CMD(cmd)) {
        case ANDROID_ALARM_SET_AND_WAIT(0):
        case ANDROID_ALARM_SET(0):
        case ANDROID_ALARM_SET_RTC:
+       case ANDROID_ALARM_SET_IPO(0):
                if (copy_from_user(&ts, (void __user *)arg, sizeof(ts)))
                        return -EFAULT;
                break;
        }
 
-       rv = alarm_do_ioctl(file, cmd, &ts);
+       rv = alarm_do_ioctl(file, cmd, &ts, &pwron_alm);
        if (rv)
                return rv;
 
@@ -272,6 +327,16 @@ static long alarm_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
                if (copy_to_user((void __user *)arg, &ts, sizeof(ts)))
                        return -EFAULT;
                break;
+       case ANDROID_ALARM_GET_POWER_ON:
+       case ANDROID_ALARM_GET_POWER_ON_IPO:
+               if (copy_to_user((void __user *)arg, &pwron_alm,
+                           sizeof(struct rtc_wkalrm))) {
+                       rv = -EFAULT;
+                       return rv;
+               }
+               break;
+       default :
+               break;
        }
 
        return 0;
@@ -282,12 +347,14 @@ static long alarm_compat_ioctl(struct file *file, unsigned int cmd,
 {
 
        struct timespec ts;
+       struct rtc_wkalrm pwron_alm;
        int rv;
 
        switch (ANDROID_ALARM_BASE_CMD(cmd)) {
        case ANDROID_ALARM_SET_AND_WAIT_COMPAT(0):
        case ANDROID_ALARM_SET_COMPAT(0):
        case ANDROID_ALARM_SET_RTC_COMPAT:
+       case ANDROID_ALARM_SET_IPO_COMPAT(0):
                if (compat_get_timespec(&ts, (void __user *)arg))
                        return -EFAULT;
                /* fall through */
@@ -296,7 +363,7 @@ static long alarm_compat_ioctl(struct file *file, unsigned int cmd,
                break;
        }
 
-       rv = alarm_do_ioctl(file, cmd, &ts);
+       rv = alarm_do_ioctl(file, cmd, &ts, &pwron_alm);
        if (rv)
                return rv;
 
@@ -305,8 +372,17 @@ static long alarm_compat_ioctl(struct file *file, unsigned int cmd,
                if (compat_put_timespec(&ts, (void __user *)arg))
                        return -EFAULT;
                break;
-       }
+       
+       case ANDROID_ALARM_GET_POWER_ON:
+       case ANDROID_ALARM_GET_POWER_ON_IPO:
+               if (copy_to_user((void __user *)arg, &pwron_alm,
+                           sizeof(struct rtc_wkalrm))) {
+                       rv = -EFAULT;
+                       return rv;
+               }
+               break;
 
+       }
        return 0;
 }
 #endif
@@ -314,6 +390,7 @@ static long alarm_compat_ioctl(struct file *file, unsigned int cmd,
 static int alarm_open(struct inode *inode, struct file *file)
 {
        file->private_data = NULL;
+       alarm_dbg(INFO, "alarm_open (%d:%d)\n", current->tgid, current->pid);
        return 0;
 }
 
@@ -348,6 +425,8 @@ static int alarm_release(struct inode *inode, struct file *file)
                alarm_opened = 0;
        }
        spin_unlock_irqrestore(&alarm_slock, flags);
+       alarm_dbg(INFO, "alarm_release (%d:%d)(%lu)\n",
+               current->tgid, current->pid, (uintptr_t)file->private_data);
        return 0;
 }
 
@@ -372,6 +451,7 @@ static enum hrtimer_restart devalarm_hrthandler(struct hrtimer *hrt)
 {
        struct devalarm *devalrm = container_of(hrt, struct devalarm, u.hrt);
 
+       alarm_dbg(INT,  "devalarm_hrthandler\n");
        devalarm_triggered(devalrm);
        return HRTIMER_NORESTART;
 }
@@ -381,6 +461,7 @@ static enum alarmtimer_restart devalarm_alarmhandler(struct alarm *alrm,
 {
        struct devalarm *devalrm = container_of(alrm, struct devalarm, u.alrm);
 
+       alarm_dbg(INT, "devalarm_alarmhandler\n");
        devalarm_triggered(devalrm);
        return ALARMTIMER_NORESTART;
 }