static ssize_t test_irq_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { int retval; struct platform_device *plat_dev = to_platform_device(dev); struct rtc_device *rtc = platform_get_drvdata(plat_dev); retval = count; if (strncmp(buf, "tick", 4) == 0 && rtc->pie_enabled) rtc_update_irq(rtc, 1, RTC_PF | RTC_IRQF); else if (strncmp(buf, "alarm", 5) == 0) { struct rtc_wkalrm alrm; int err = rtc_read_alarm(rtc, &alrm); if (!err && alrm.enabled) rtc_update_irq(rtc, 1, RTC_AF | RTC_IRQF); } else if (strncmp(buf, "update", 6) == 0 && rtc->uie_rtctimer.enabled) rtc_update_irq(rtc, 1, RTC_UF | RTC_IRQF); else retval = -EINVAL; return retval; }
static ssize_t rtc_sysfs_show_wakealarm(struct device *dev, struct device_attribute *attr, char *buf) { ssize_t retval; unsigned long alarm; struct rtc_wkalrm alm; printk("%s \n", __func__); /* Don't show disabled alarms. For uniformity, RTC alarms are * conceptually one-shot, even though some common RTCs (on PCs) * don't actually work that way. * * NOTE: RTC implementations where the alarm doesn't match an * exact YYYY-MM-DD HH:MM[:SS] date *must* disable their RTC * alarms after they trigger, to ensure one-shot semantics. */ alm.enabled=1; retval = rtc_read_alarm(to_rtc_device(dev), &alm); printk("show_alarm retval: %d\n",retval); if (retval == 0 && alm.enabled) { rtc_tm_to_time(&alm.time, &alarm); retval = sprintf(buf, "%lu \n", alarm); printk("alarm buf: %s \n",buf); } return retval; }
static int suspend_autotest_suspend(struct device *dev) { unsigned long now; struct rtc_wkalrm alm; int status; int need_test = 0; unsigned long alarm_time; /* if test isn't enabled, no need to proceed below code */ if ((!test_enable) || (test_mode != SUSPEND)) return 0; /* read alarm time */ status = rtc_read_alarm(rtc, &alm); if (status) { pr_info("%s: rtc_read_alarm fail\n", __func__); return status; } rtc_tm_to_time(&alm.time, &alarm_time); /* if alarm is set already, alarm time should be compared. * if no alarm is set, test alarm can be done. */ if (alm.enabled) need_test = 0; else need_test = 1; status = rtc_read_time(rtc, &alm.time); if (status < 0) { pr_info("%s: rtc_read_time fail\n", __func__); return status; } rtc_tm_to_time(&alm.time, &now); /* if alarm will be expired in TEST_SUSPEND_SECONDS, * don't set test alarm time */ if (!need_test && alarm_time < (now + TEST_SUSPEND_SECONDS)) { pr_info("%s: no setting of test alarm\n", __func__); return 0; } memset(&alm, 0, sizeof alm); rtc_time_to_tm(now + TEST_SUSPEND_SECONDS, &alm.time); alm.enabled = true; status = rtc_set_alarm(rtc, &alm); if (status < 0) { pr_info("%s: rtc_set_alarm fail\n",__func__); return status; } test_alarm_set = 1; pr_info("%s: test alarm will be envoked after about %d sec.\n", __func__, TEST_SUSPEND_SECONDS); return 0; }
static int rtc_proc_show(struct seq_file *seq, void *offset) { int err; struct class_device *class_dev = seq->private; const struct rtc_class_ops *ops = to_rtc_device(class_dev)->ops; struct rtc_wkalrm alrm; struct rtc_time tm; err = rtc_read_time(class_dev, &tm); if (err == 0) { seq_printf(seq, "rtc_time\t: %02d:%02d:%02d\n" "rtc_date\t: %04d-%02d-%02d\n", tm.tm_hour, tm.tm_min, tm.tm_sec, tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday); } err = rtc_read_alarm(class_dev, &alrm); if (err == 0) { seq_printf(seq, "alrm_time\t: "); if ((unsigned int)alrm.time.tm_hour <= 24) seq_printf(seq, "%02d:", alrm.time.tm_hour); else seq_printf(seq, "**:"); if ((unsigned int)alrm.time.tm_min <= 59) seq_printf(seq, "%02d:", alrm.time.tm_min); else seq_printf(seq, "**:"); if ((unsigned int)alrm.time.tm_sec <= 59) seq_printf(seq, "%02d\n", alrm.time.tm_sec); else seq_printf(seq, "**\n"); seq_printf(seq, "alrm_date\t: "); if ((unsigned int)alrm.time.tm_year <= 200) seq_printf(seq, "%04d-", alrm.time.tm_year + 1900); else seq_printf(seq, "****-"); if ((unsigned int)alrm.time.tm_mon <= 11) seq_printf(seq, "%02d-", alrm.time.tm_mon + 1); else seq_printf(seq, "**-"); if (alrm.time.tm_mday && (unsigned int)alrm.time.tm_mday <= 31) seq_printf(seq, "%02d\n", alrm.time.tm_mday); else seq_printf(seq, "**\n"); seq_printf(seq, "alarm_IRQ\t: %s\n", alrm.enabled ? "yes" : "no"); seq_printf(seq, "alrm_pending\t: %s\n", alrm.pending ? "yes" : "no"); } seq_printf(seq, "24hr\t\t: yes\n"); if (ops->proc) ops->proc(class_dev->dev, seq); return 0; }
static int rtc_read_proc(char *page, char **start, off_t off, int count, int *eof, void *data) { struct rtc_ops *ops = data; struct rtc_wkalrm alrm; struct rtc_time tm; char *p = page; if (rtc_read_time(ops, &tm) == 0) { p += sprintf(p, "rtc_time\t: %02d:%02d:%02d\n" "rtc_date\t: %04d-%02d-%02d\n" "rtc_epoch\t: %04lu\n", tm.tm_hour, tm.tm_min, tm.tm_sec, tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday, rtc_epoch); } if (rtc_read_alarm(ops, &alrm) == 0) { p += sprintf(p, "alrm_time\t: "); if ((unsigned int)alrm.time.tm_hour <= 24) p += sprintf(p, "%02d:", alrm.time.tm_hour); else p += sprintf(p, "**:"); if ((unsigned int)alrm.time.tm_min <= 59) p += sprintf(p, "%02d:", alrm.time.tm_min); else p += sprintf(p, "**:"); if ((unsigned int)alrm.time.tm_sec <= 59) p += sprintf(p, "%02d\n", alrm.time.tm_sec); else p += sprintf(p, "**\n"); p += sprintf(p, "alrm_date\t: "); if ((unsigned int)alrm.time.tm_year <= 200) p += sprintf(p, "%04d-", alrm.time.tm_year + 1900); else p += sprintf(p, "****-"); if ((unsigned int)alrm.time.tm_mon <= 11) p += sprintf(p, "%02d-", alrm.time.tm_mon + 1); else p += sprintf(p, "**-"); if ((unsigned int)alrm.time.tm_mday <= 31) p += sprintf(p, "%02d\n", alrm.time.tm_mday); else p += sprintf(p, "**\n"); p += sprintf(p, "alrm_wakeup\t: %s\n", alrm.enabled ? "yes" : "no"); p += sprintf(p, "alrm_pending\t: %s\n", alrm.pending ? "yes" : "no"); } if (ops->proc) p += ops->proc(p); return p - page; }
static ssize_t rtc_sysfs_set_wakealarm(struct device *dev, struct device_attribute *attr, const char *buf, size_t n) { ssize_t retval; unsigned long now, alarm; struct rtc_wkalrm alm; struct rtc_device *rtc = to_rtc_device(dev); char *buf_ptr; int adjust = 0; printk("%s \n", __func__); /* Only request alarms that trigger in the future. Disable them * by writing another time, e.g. 0 meaning Jan 1 1970 UTC. */ retval = rtc_read_time(rtc, &alm.time); sys_out("retval is %d \n", retval); if (retval < 0) return retval; rtc_tm_to_time(&alm.time, &now); buf_ptr = (char *)buf; if (*buf_ptr == '+') { buf_ptr++; adjust = 1; } alarm = simple_strtoul(buf_ptr, NULL, 0); if (adjust) { alarm += now; } if (alarm > now) { /* Avoid accidentally clobbering active alarms; we can't * entirely prevent that here, without even the minimal * locking from the /dev/rtcN api. */ retval = rtc_read_alarm(rtc, &alm); if (retval < 0) return retval; if (alm.enabled) return -EBUSY; alm.enabled = 1; } else { alm.enabled = 0; /* Provide a valid future alarm time. Linux isn't EFI, * this time won't be ignored when disabling the alarm. */ alarm = now + 300; } rtc_time_to_tm(alarm, &alm.time); retval = rtc_set_alarm(rtc, &alm); printk("set_alarm retval: %d\n",retval); return (retval < 0) ? retval : n; }
static int set_wakealarm(void) { int retval = 0; unsigned long now, alarm; struct rtc_wkalrm alm; struct rtc_device *rtc; rtc = rtc_class_open(CONFIG_WAKEALARM_RTC); if (!rtc) { return -1; } /* Only request alarms that trigger in the future. Disable them * by writing another time, e.g. 0 meaning Jan 1 1970 UTC. */ retval = rtc_read_time(rtc, &alm.time); if (retval < 0) goto close_rtc; rtc_tm_to_time(&alm.time, &now); alarm = now + sleep_time; if (alarm > now) { /* Avoid accidentally clobbering active alarms; we can't * entirely prevent that here, without even the minimal * locking from the /dev/rtcN api. */ retval = rtc_read_alarm(rtc, &alm); if (retval < 0) goto close_rtc; alm.enabled = 1; } else { alm.enabled = 0; /* Provide a valid future alarm time. Linux isn't EFI, * this time won't be ignored when disabling the alarm. */ alarm = now + 300; } rtc_time_to_tm(alarm, &alm.time); retval = rtc_set_alarm(rtc, &alm); close_rtc: rtc_class_close(rtc); return retval; }
static ssize_t rtc_sysfs_set_wakealarm(struct device *dev, struct device_attribute *attr, const char *buf, size_t n) { ssize_t retval; unsigned long now, alarm; struct rtc_wkalrm alm; struct rtc_device *rtc = to_rtc_device(dev); char *buf_ptr; int adjust = 0; retval = rtc_read_time(rtc, &alm.time); if (retval < 0) return retval; rtc_tm_to_time(&alm.time, &now); buf_ptr = (char *)buf; if (*buf_ptr == '+') { buf_ptr++; adjust = 1; } alarm = simple_strtoul(buf_ptr, NULL, 0); if (adjust) { alarm += now; } if (alarm > now) { retval = rtc_read_alarm(rtc, &alm); if (retval < 0) return retval; if (alm.enabled) return -EBUSY; alm.enabled = 1; } else { alm.enabled = 0; alarm = now + 300; } rtc_time_to_tm(alarm, &alm.time); retval = rtc_set_alarm(rtc, &alm); return (retval < 0) ? retval : n; }
static ssize_t rtc_sysfs_show_wakealarm(struct device *dev, struct device_attribute *attr, char *buf) { ssize_t retval; unsigned long alarm; struct rtc_wkalrm alm; retval = rtc_read_alarm(to_rtc_device(dev), &alm); if (retval == 0 && alm.enabled) { rtc_tm_to_time(&alm.time, &alarm); retval = sprintf(buf, "%lu\n", alarm); } return retval; }
int alarm_read_rtc_ring(int *flag, unsigned long *alarm_time) { struct rtc_wkalrm rtc_alarm; int ret = 0; if (pwr_rtc_dev != NULL) { if (pwr_rtc_dev->dev.platform_data) *flag = *(int *)(pwr_rtc_dev->dev.platform_data); ret = rtc_read_alarm(pwr_rtc_dev, &rtc_alarm); if (ret < 0) goto out; rtc_tm_to_time(&rtc_alarm.time, alarm_time); pr_alarm(INT, "%s, flag: %d, alarm time: %lu\n", __func__, *flag, *alarm_time); } out: return ret; }
static ssize_t rtc_sysfs_set_wakealarm(struct class_device *dev, const char *buf, size_t n) { ssize_t retval; unsigned long now, alarm; struct rtc_wkalrm alm; /* Only request alarms that trigger in the future. Disable them * by writing another time, e.g. 0 meaning Jan 1 1970 UTC. */ retval = rtc_read_time(dev, &alm.time); if (retval < 0) return retval; rtc_tm_to_time(&alm.time, &now); alarm = simple_strtoul(buf, NULL, 0); if (alarm > now) { /* Avoid accidentally clobbering active alarms; we can't * entirely prevent that here, without even the minimal * locking from the /dev/rtcN api. */ retval = rtc_read_alarm(dev, &alm); if (retval < 0) return retval; if (alm.enabled) return -EBUSY; alm.enabled = 1; } else { alm.enabled = 0; /* Provide a valid future alarm time. Linux isn't EFI, * this time won't be ignored when disabling the alarm. */ alarm = now + 300; } rtc_time_to_tm(alarm, &alm.time); retval = rtc_set_alarm(dev, &alm); return (retval < 0) ? retval : n; }
void power_on_alarm_init(void) { struct rtc_wkalrm rtc_alarm; struct rtc_time rt; unsigned long alarm_time; struct rtc_device *rtc; rtc = alarmtimer_get_rtcdev(); /* If we have no rtcdev, just return */ if (!rtc) return; rtc_read_alarm(rtc, &rtc_alarm); rt = rtc_alarm.time; rtc_tm_to_time(&rt, &alarm_time); if (alarm_time) power_on_alarm = alarm_time; else power_on_alarm = 0; }
static ssize_t rtc_sysfs_show_wakealarm(struct class_device *dev, char *buf) { ssize_t retval; unsigned long alarm; struct rtc_wkalrm alm; /* Don't show disabled alarms; but the RTC could leave the * alarm enabled after it's already triggered. Alarms are * conceptually one-shot, even though some common hardware * (PCs) doesn't actually work that way. * * REVISIT maybe we should require RTC implementations to * disable the RTC alarm after it triggers, for uniformity. */ retval = rtc_read_alarm(dev, &alm); if (retval == 0 && alm.enabled) { rtc_tm_to_time(&alm.time, &alarm); retval = sprintf(buf, "%lu\n", alarm); } return retval; }
static ssize_t wakealarm_show(struct device *dev, struct device_attribute *attr, char *buf) { ssize_t retval; time64_t alarm; struct rtc_wkalrm alm; /* Don't show disabled alarms. For uniformity, RTC alarms are * conceptually one-shot, even though some common RTCs (on PCs) * don't actually work that way. * * NOTE: RTC implementations where the alarm doesn't match an * exact YYYY-MM-DD HH:MM[:SS] date *must* disable their RTC * alarms after they trigger, to ensure one-shot semantics. */ retval = rtc_read_alarm(to_rtc_device(dev), &alm); if (retval == 0 && alm.enabled) { alarm = rtc_tm_to_time64(&alm.time); retval = sprintf(buf, "%lld\n", alarm); } return retval; }
static ssize_t rtc_sysfs_set_wakealarm(struct device *dev, struct device_attribute *attr, const char *buf, size_t n) { ssize_t retval; unsigned long now, alarm; struct rtc_wkalrm alm; struct rtc_device *rtc = to_rtc_device(dev); char *buf_ptr; int adjust = 0; /* Only request alarms that trigger in the future. Disable them * by writing another time, e.g. 0 meaning Jan 1 1970 UTC. */ printk("rtc_sysfs_set_wakealarm is enter,buf=%s,n=%d,zte_rtc_alarm_en=%d\n",buf,n,zte_rtc_alarm_en); zte_rtc_alarm_en=0; retval = rtc_read_time(rtc, &alm.time); if (retval < 0) { printk("rtc_sysfs_set_wakealarm is error1 return=%d\n",retval); return retval; } rtc_tm_to_time(&alm.time, &now); buf_ptr = (char *)buf; if (*buf_ptr == '+') { buf_ptr++; adjust = 1; } alarm = simple_strtoul(buf_ptr, NULL, 0); if (adjust) { alarm /= MSEC_PER_SEC; alarm += now; } printk("rtc_sysfs_set_wakealarm:alarm=%ld,now=%ld\n",alarm,now); if (alarm > now) { /* Avoid accidentally clobbering active alarms; we can't * entirely prevent that here, without even the minimal * locking from the /dev/rtcN api. */ retval = rtc_read_alarm(rtc, &alm); if (retval < 0) { printk("rtc_sysfs_set_wakealarm is error2 return=%d\n",retval); return retval; } #if 0 if (alm.enabled) { printk("rtc_sysfs_set_wakealarm is error3 return=-EBUSY\n"); return -EBUSY; } #endif zte_rtc_alarm_en=1; alm.enabled = 1; setup_hibernate_alarm(rtc, (alarm - now)); } else { alm.enabled = 0; /* Provide a valid future alarm time. Linux isn't EFI, * this time won't be ignored when disabling the alarm. */ alarm = now + 300; setup_hibernate_alarm(rtc, 0); } rtc_time_to_tm(alarm, &alm.time); retval = rtc_set_alarm(rtc, &alm); printk("rtc_sysfs_set_wakealarm is ok return=%d,zte_rtc_alarm_en=%d\n",retval,zte_rtc_alarm_en); return (retval < 0) ? retval : n; }
static int rtc_proc_show(struct seq_file *seq, void *offset) { int err; struct rtc_device *rtc = seq->private; const struct rtc_class_ops *ops = rtc->ops; struct rtc_wkalrm alrm; struct rtc_time tm; err = rtc_read_time(rtc, &tm); if (err == 0) { seq_printf(seq, "rtc_time\t: %02d:%02d:%02d\n" "rtc_date\t: %04d-%02d-%02d\n", tm.tm_hour, tm.tm_min, tm.tm_sec, tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday); } err = rtc_read_alarm(rtc, &alrm); if (err == 0) { seq_printf(seq, "alrm_time\t: "); if ((unsigned int)alrm.time.tm_hour <= 24) seq_printf(seq, "%02d:", alrm.time.tm_hour); else seq_printf(seq, "**:"); if ((unsigned int)alrm.time.tm_min <= 59) seq_printf(seq, "%02d:", alrm.time.tm_min); else seq_printf(seq, "**:"); if ((unsigned int)alrm.time.tm_sec <= 59) seq_printf(seq, "%02d\n", alrm.time.tm_sec); else seq_printf(seq, "**\n"); seq_printf(seq, "alrm_date\t: "); if ((unsigned int)alrm.time.tm_year <= 200) seq_printf(seq, "%04d-", alrm.time.tm_year + 1900); else seq_printf(seq, "****-"); if ((unsigned int)alrm.time.tm_mon <= 11) seq_printf(seq, "%02d-", alrm.time.tm_mon + 1); else seq_printf(seq, "**-"); if (alrm.time.tm_mday && (unsigned int)alrm.time.tm_mday <= 31) seq_printf(seq, "%02d\n", alrm.time.tm_mday); else seq_printf(seq, "**\n"); seq_printf(seq, "alarm_IRQ\t: %s\n", alrm.enabled ? "yes" : "no"); seq_printf(seq, "alrm_pending\t: %s\n", alrm.pending ? "yes" : "no"); seq_printf(seq, "update IRQ enabled\t: %s\n", (rtc->uie_rtctimer.enabled) ? "yes" : "no"); seq_printf(seq, "periodic IRQ enabled\t: %s\n", (rtc->pie_enabled) ? "yes" : "no"); seq_printf(seq, "periodic IRQ frequency\t: %d\n", rtc->irq_freq); seq_printf(seq, "max user IRQ frequency\t: %d\n", rtc->max_user_freq); } seq_printf(seq, "24hr\t\t: yes\n"); if (ops->proc) ops->proc(rtc->dev.parent, seq); return 0; }
static int rtc_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) { struct rtc_ops *ops = file->private_data; struct rtc_time tm; struct rtc_wkalrm alrm; void __user *uarg = (void __user *)arg; int ret = -EINVAL; switch (cmd) { case RTC_ALM_READ: ret = rtc_read_alarm(ops, &alrm); if (ret) break; ret = copy_to_user(uarg, &alrm.time, sizeof(tm)); if (ret) ret = -EFAULT; break; case RTC_ALM_SET: ret = copy_from_user(&alrm.time, uarg, sizeof(tm)); if (ret) { ret = -EFAULT; break; } alrm.enabled = 0; alrm.pending = 0; alrm.time.tm_mday = -1; alrm.time.tm_mon = -1; alrm.time.tm_year = -1; alrm.time.tm_wday = -1; alrm.time.tm_yday = -1; alrm.time.tm_isdst = -1; ret = rtc_set_alarm(ops, &alrm); break; case RTC_RD_TIME: ret = rtc_read_time(ops, &tm); if (ret) break; ret = copy_to_user(uarg, &tm, sizeof(tm)); if (ret) ret = -EFAULT; break; case RTC_SET_TIME: if (!capable(CAP_SYS_TIME)) { ret = -EACCES; break; } ret = copy_from_user(&tm, uarg, sizeof(tm)); if (ret) { ret = -EFAULT; break; } ret = rtc_set_time(ops, &tm); break; case RTC_EPOCH_SET: #ifndef rtc_epoch /* * There were no RTC clocks before 1900. */ if (arg < 1900) { ret = -EINVAL; break; } if (!capable(CAP_SYS_TIME)) { ret = -EACCES; break; } rtc_epoch = arg; ret = 0; #endif break; case RTC_EPOCH_READ: ret = put_user(rtc_epoch, (unsigned long __user *)uarg); break; case RTC_WKALM_SET: ret = copy_from_user(&alrm, uarg, sizeof(alrm)); if (ret) { ret = -EFAULT; break; } ret = rtc_set_alarm(ops, &alrm); break; case RTC_WKALM_RD: ret = rtc_read_alarm(ops, &alrm); if (ret) break; ret = copy_to_user(uarg, &alrm, sizeof(alrm)); if (ret) ret = -EFAULT; break; default: if (ops->ioctl) ret = ops->ioctl(cmd, arg); break; } return ret; }
static ssize_t wakealarm_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t n) { ssize_t retval; unsigned long now, alarm; unsigned long push = 0; struct rtc_wkalrm alm; struct rtc_device *rtc = to_rtc_device(dev); const char *buf_ptr; int adjust = 0; /* Only request alarms that trigger in the future. Disable them * by writing another time, e.g. 0 meaning Jan 1 1970 UTC. */ retval = rtc_read_time(rtc, &alm.time); if (retval < 0) return retval; rtc_tm_to_time(&alm.time, &now); buf_ptr = buf; if (*buf_ptr == '+') { buf_ptr++; if (*buf_ptr == '=') { buf_ptr++; push = 1; } else adjust = 1; } retval = kstrtoul(buf_ptr, 0, &alarm); if (retval) return retval; if (adjust) { alarm += now; } if (alarm > now || push) { /* Avoid accidentally clobbering active alarms; we can't * entirely prevent that here, without even the minimal * locking from the /dev/rtcN api. */ retval = rtc_read_alarm(rtc, &alm); if (retval < 0) return retval; if (alm.enabled) { if (push) { rtc_tm_to_time(&alm.time, &push); alarm += push; } else return -EBUSY; } else if (push) return -EINVAL; alm.enabled = 1; } else { alm.enabled = 0; /* Provide a valid future alarm time. Linux isn't EFI, * this time won't be ignored when disabling the alarm. */ alarm = now + 300; } rtc_time_to_tm(alarm, &alm.time); retval = rtc_set_alarm(rtc, &alm); return (retval < 0) ? retval : n; }