static int __init rtc_hctosys(void) { int err; struct rtc_time tm; struct rtc_device *rtc = rtc_class_open(CONFIG_RTC_HCTOSYS_DEVICE); if (rtc == NULL) { printk("%s: unable to open rtc device (%s)\n", __FILE__, CONFIG_RTC_HCTOSYS_DEVICE); return -ENODEV; } err = rtc_read_time(rtc, &tm); if (err == 0) { err = rtc_valid_tm(&tm); if (err == 0) { struct timespec tv; tv.tv_nsec = NSEC_PER_SEC >> 1; rtc_tm_to_time(&tm, &tv.tv_sec); // 110 = 2010 - 1900 if( tm.tm_year < 110 && tm.tm_year > 0 ) { tm.tm_year = 110; tm.tm_mon = 11; rtc_set_time(rtc,&tm); tv.tv_nsec = NSEC_PER_SEC >> 1; rtc_tm_to_time(&tm, &tv.tv_sec); } else if( tm.tm_year == 110 && tm.tm_mon < 11 ){
/* * this function syncs system time with RTC when startup * if there is valid time store in RTC static int rtc_hctosys(void) */ static int rtc_hctosys(void) { int err; struct rtc_time tm; struct rtc_device *rtc = rtc_class_open("rtc1"); if (rtc == NULL) { printk("%s: unable to open rtc device (rtc1) for rtc_hctosys\n", __FILE__); return -ENODEV; } err = rtc_read_time(rtc, &tm); if (err == 0) { err = rtc_valid_tm(&tm); if (err == 0) { struct timespec tv; tv.tv_nsec = NSEC_PER_SEC >> 1; rtc_tm_to_time(&tm, &tv.tv_sec); do_settimeofday(&tv); dev_info(rtc->dev.parent, "setting system clock to " "%d-%02d-%02d %02d:%02d:%02d UTC (%u)\n", tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday, tm.tm_hour, tm.tm_min, tm.tm_sec, (unsigned int) tv.tv_sec); } else {
static int bq2419x_wakealarm(struct bq2419x_chip *bq2419x, int time_sec) { int ret; unsigned long now; struct rtc_wkalrm alm; int alarm_time = time_sec; if (!alarm_time) return 0; alm.enabled = true; ret = rtc_read_time(bq2419x->rtc, &alm.time); if (ret < 0) { dev_err(bq2419x->dev, "RTC read time failed %d\n", ret); return ret; } rtc_tm_to_time(&alm.time, &now); rtc_time_to_tm(now + alarm_time, &alm.time); ret = rtc_set_alarm(bq2419x->rtc, &alm); if (ret < 0) { dev_err(bq2419x->dev, "RTC set alarm failed %d\n", ret); alm.enabled = false; return ret; } alm.enabled = false; return 0; }
void set_power_on_alarm(long secs, bool enable) { int rc; struct timespec wall_time; long rtc_secs, alarm_time, alarm_delta; struct rtc_time rtc_time; struct rtc_wkalrm alarm; rc = mutex_lock_interruptible(&power_on_alarm_lock); if (rc != 0) return; if (enable) { power_on_alarm = secs; } else { if (power_on_alarm == secs) power_on_alarm = 0; else goto exit; } if (!power_on_alarm) goto disable_alarm; rtc_read_time(rtcdev, &rtc_time); getnstimeofday(&wall_time); rtc_tm_to_time(&rtc_time, &rtc_secs); alarm_delta = wall_time.tv_sec - rtc_secs; alarm_time = power_on_alarm - alarm_delta; /* *Substract ALARM_DELTA from actual alarm time *to power up the device before actual alarm *expiration */ #ifdef CONFIG_ZTEMT_PON_ALARM_DELTA if ((alarm_time - ALARM_DELTA) > rtc_secs) alarm_time -= ALARM_DELTA; else goto disable_alarm; #else if (alarm_time <= rtc_secs) goto disable_alarm; #endif rtc_time_to_tm(alarm_time, &alarm.time); alarm.enabled = 1; rc = rtc_set_alarm(rtcdev, &alarm); if (rc) goto disable_alarm; mutex_unlock(&power_on_alarm_lock); return; disable_alarm: power_on_alarm = 0; rtc_alarm_irq_enable(rtcdev, 0); exit: mutex_unlock(&power_on_alarm_lock); }
/* Called once per device from rtc_device_register */ int rtc_initialize_alarm(struct rtc_device *rtc, struct rtc_wkalrm *alarm) { int err; struct rtc_time now; err = rtc_valid_tm(&alarm->time); if (err != 0) return err; err = rtc_read_time(rtc, &now); if (err) return err; err = mutex_lock_interruptible(&rtc->ops_lock); if (err) return err; rtc->aie_timer.node.expires = rtc_tm_to_ktime(alarm->time); rtc->aie_timer.period = 0; /* Alarm has to be enabled & in the future for us to enqueue it */ if (alarm->enabled && (rtc_tm_to_ktime(now) < rtc->aie_timer.node.expires)) { rtc->aie_timer.enabled = 1; timerqueue_add(&rtc->timerqueue, &rtc->aie_timer.node); trace_rtc_timer_enqueue(&rtc->aie_timer); } mutex_unlock(&rtc->ops_lock); return err; }
static int rtc_suspend(struct device *dev, pm_message_t mesg) { struct rtc_device *rtc = to_rtc_device(dev); struct rtc_time tm; struct timespec delta, delta_delta; if (strcmp(dev_name(&rtc->dev), CONFIG_RTC_HCTOSYS_DEVICE) != 0) return 0; /* snapshot the current RTC and system time at suspend*/ rtc_read_time(rtc, &tm); getnstimeofday(&old_system); rtc_tm_to_time(&tm, &old_rtc.tv_sec); /* * To avoid drift caused by repeated suspend/resumes, * which each can add ~1 second drift error, * try to compensate so the difference in system time * and rtc time stays close to constant. */ delta = timespec_sub(old_system, old_rtc); delta_delta = timespec_sub(delta, old_delta); if (delta_delta.tv_sec < -2 || delta_delta.tv_sec >= 2) { /* * if delta_delta is too large, assume time correction * has occured and set old_delta to the current delta. */ old_delta = delta; } else { /* Otherwise try to adjust old_system to compensate */ old_system = timespec_sub(old_system, delta_delta); } return 0; }
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 read_rtc0_time(struct msm_rpc_server *server, struct rpc_request_hdr *req, unsigned len) { int err; unsigned long tm_sec; uint32_t size = 0; void *reply; uint32_t output_valid; uint32_t rpc_status = RPC_ACCEPTSTAT_SYSTEM_ERR; struct rtc_time tm; struct rtc_device *rtc = rtc_class_open(CONFIG_RTC_HCTOSYS_DEVICE); if (rtc == NULL) { pr_err("%s: unable to open rtc device (%s)\n", __FILE__, CONFIG_RTC_HCTOSYS_DEVICE); goto send_reply; } err = rtc_read_time(rtc, &tm); if (err) { pr_err("%s: Error reading rtc device (%s) : %d\n", __FILE__, CONFIG_RTC_HCTOSYS_DEVICE, err); goto close_dev; } err = rtc_valid_tm(&tm); if (err) { pr_err("%s: Invalid RTC time (%s)\n", __FILE__, CONFIG_RTC_HCTOSYS_DEVICE); goto close_dev; } rtc_tm_to_time(&tm, &tm_sec); rpc_status = RPC_ACCEPTSTAT_SUCCESS; close_dev: rtc_class_close(rtc); send_reply: reply = msm_rpc_server_start_accepted_reply(server, req->xid, rpc_status); if (rpc_status == RPC_ACCEPTSTAT_SUCCESS) { output_valid = *((uint32_t *)(req + 1)); *(uint32_t *)reply = output_valid; size = sizeof(uint32_t); if (be32_to_cpu(output_valid)) { reply += sizeof(uint32_t); *(uint32_t *)reply = cpu_to_be32(tm_sec); size += sizeof(uint32_t); } } err = msm_rpc_server_send_accepted_reply(server, size); if (err) pr_err("%s: send accepted reply failed: %d\n", __func__, err); return 1; }
int rtc_hctosys(void) { int err = -ENODEV; struct rtc_time tm; struct timespec tv = { .tv_nsec = NSEC_PER_SEC >> 1, }; struct rtc_device *rtc = rtc_class_open(CONFIG_RTC_HCTOSYS_DEVICE); if (rtc == NULL) { pr_err("%s: unable to open rtc device (%s)\n", __FILE__, CONFIG_RTC_HCTOSYS_DEVICE); goto err_open; } err = rtc_read_time(rtc, &tm); if (err) { dev_err(rtc->dev.parent, "hctosys: unable to read the hardware clock\n"); goto err_read; } /* * Force update rtc year time to 2014 * (The release year of device) */ tm.tm_year = 114; err = rtc_valid_tm(&tm); if (err) { dev_err(rtc->dev.parent, "hctosys: invalid date/time\n"); goto err_invalid; } rtc_tm_to_time(&tm, &tv.tv_sec); err = do_settimeofday(&tv); dev_info(rtc->dev.parent, "setting system clock to " "%d-%02d-%02d %02d:%02d:%02d UTC (%u)\n", tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday, tm.tm_hour, tm.tm_min, tm.tm_sec, (unsigned int) tv.tv_sec); err_invalid: err_read: rtc_class_close(rtc); err_open: rtc_hctosys_ret = err; return err; } late_initcall(rtc_hctosys);
static int rtc_resume(struct device *dev) { struct rtc_device *rtc = to_rtc_device(dev); struct rtc_time tm; struct timespec new_system, new_rtc; struct timespec sleep_time; if (strcmp(dev_name(&rtc->dev), CONFIG_RTC_HCTOSYS_DEVICE) != 0) return 0; #if defined(ADJUST_KERNEL_TIME) printk("%s [RTC] ==================================== \n", __func__); #endif /* snapshot the current rtc and system time at resume */ getnstimeofday(&new_system); rtc_read_time(rtc, &tm); if (rtc_valid_tm(&tm) != 0) { pr_debug("%s: bogus resume time\n", dev_name(&rtc->dev)); return 0; } rtc_tm_to_time(&tm, &new_rtc.tv_sec); new_rtc.tv_nsec = 0; if (new_rtc.tv_sec < old_rtc.tv_sec) { pr_debug("%s: time travel!\n", dev_name(&rtc->dev)); return 0; } /* calculate the RTC time delta (sleep time)*/ sleep_time = timespec_sub(new_rtc, old_rtc); /* * Since these RTC suspend/resume handlers are not called * at the very end of suspend or the start of resume, * some run-time may pass on either sides of the sleep time * so subtract kernel run-time between rtc_suspend to rtc_resume * to keep things accurate. */ sleep_time = timespec_sub(sleep_time, timespec_sub(new_system, old_system)); if (sleep_time.tv_sec >= 0) timekeeping_inject_sleeptime(&sleep_time); #ifdef ADJUST_KERNEL_TIME schedule_delayed_work(&rtc_work, RTC_WORK_CHECK_TIMEOUT); #endif #if defined(ADJUST_KERNEL_TIME) printk("%s [RTC] sleep_time = %ld \n", __func__,sleep_time.tv_sec); printk("%s [RTC] time now = %ld\n", __func__,new_rtc.tv_sec); printk("%s [RTC] ==================================== \n", __func__); #endif return 0; }
int rtc_hctosys(void) { int err = -ENODEV; struct rtc_time tm; struct timespec tv = { .tv_nsec = NSEC_PER_SEC >> 1, }; struct rtc_device *rtc = rtc_class_open(CONFIG_RTC_HCTOSYS_DEVICE); if (rtc == NULL) { pr_err("%s: unable to open rtc device (%s)\n", __FILE__, CONFIG_RTC_HCTOSYS_DEVICE); goto err_open; } err = rtc_read_time(rtc, &tm); if (err) { dev_err(rtc->dev.parent, "hctosys: unable to read the hardware clock\n"); goto err_read; } err = rtc_valid_tm(&tm); if (err) { dev_err(rtc->dev.parent, "hctosys: invalid date/time\n"); goto err_invalid; } rtc_tm_to_time(&tm, &tv.tv_sec); if (tv.tv_sec < 86400) { tv.tv_sec = 86400; pr_info("%s: Make sure the boot time starts from 86400 or more to avoid system server crash due to alarm trigger immediately\n", __FILE__); } do_settimeofday(&tv); dev_info(rtc->dev.parent, "setting system clock to " "%d-%02d-%02d %02d:%02d:%02d UTC (%u)\n", tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday, tm.tm_hour, tm.tm_min, tm.tm_sec, (unsigned int) tv.tv_sec); err_invalid: err_read: rtc_class_close(rtc); err_open: rtc_hctosys_ret = err; return err; } late_initcall(rtc_hctosys);
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 rtc_work_check() { struct device *dev; struct rtc_device *rtc = NULL; struct timespec ktime, adjust_ktime; struct timespec check_delta; struct rtc_time tm; struct timespec rtime; printk(KERN_ERR "%s\n", __func__); rtc = rtc_class_open(CONFIG_RTC_HCTOSYS_DEVICE); if (rtc!=NULL){ getnstimeofday(&ktime); // kernel_time rtc_read_time(rtc, &tm); rtc_tm_to_time(&tm, &rtime.tv_sec); // rtc_time rtc_tm_to_time(&tm, &adjust_ktime.tv_sec); /* RTC precision is 1 second; adjust delta for avg 1/2 sec err */ set_normalized_timespec(&check_delta, ktime.tv_sec - rtime.tv_sec, ktime.tv_nsec - (NSEC_PER_SEC >> 1)); if(abs(check_delta.tv_sec) >= 3) { printk(KERN_ERR "%s: 1 k_t: %10d\n", __func__, ktime.tv_sec); printk(KERN_ERR "%s: 2 r_t: %10d\n", __func__, rtime.tv_sec); printk(KERN_ERR "%s: 3 check_delta s: %3d, s: %10d \n", __func__, check_delta.tv_sec, check_delta.tv_nsec); printk(KERN_ERR "%s: 4 old_delta s: %3d, s: %10d \n", __func__, old_delta.tv_sec, old_delta.tv_nsec); adjust_ktime.tv_nsec = 0; do_settimeofday(&adjust_ktime); rtc_read_time(rtc, &tm); //request by QC getnstimeofday(&adjust_ktime); printk(KERN_ERR "%s: 5 adjust k time is set as: %10d\n", __func__, adjust_ktime.tv_sec); set_normalized_timespec(&old_delta, adjust_ktime.tv_sec - rtime.tv_sec, adjust_ktime.tv_nsec - (NSEC_PER_SEC >> 1)); printk(KERN_ERR "%s: 5 re-set delta, s:%3d, n:%10d\n", __func__, old_delta.tv_sec,old_delta.tv_nsec); }
static void __init test_wakealarm(struct rtc_device *rtc, suspend_state_t state) { static char err_readtime[] __initdata = KERN_ERR "PM: can't read %s time, err %d\n"; static char err_wakealarm [] __initdata = KERN_ERR "PM: can't set %s wakealarm, err %d\n"; static char err_suspend[] __initdata = KERN_ERR "PM: suspend test failed, error %d\n"; static char info_test[] __initdata = KERN_INFO "PM: test RTC wakeup from '%s' suspend\n"; unsigned long now; struct rtc_wkalrm alm; int status; /* this may fail if the RTC hasn't been initialized */ status = rtc_read_time(rtc, &alm.time); if (status < 0) { printk(err_readtime, dev_name(&rtc->dev), status); return; } rtc_tm_to_time(&alm.time, &now); 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) { printk(err_wakealarm, dev_name(&rtc->dev), status); return; } if (state == PM_SUSPEND_MEM) { printk(info_test, pm_states[state]); status = pm_suspend(state); if (status == -ENODEV) state = PM_SUSPEND_STANDBY; } if (state == PM_SUSPEND_STANDBY) { printk(info_test, pm_states[state]); status = pm_suspend(state); } if (status < 0) printk(err_suspend, status); /* Some platforms can't detect that the alarm triggered the * wakeup, or (accordingly) disable it after it afterwards. * It's supposed to give oneshot behavior; cope. */ alm.enabled = false; rtc_set_alarm(rtc, &alm); }
/** * tegra_get_linear_age - helper function to return linear age * from Jan 2012. * * @return * 1 - Jan 2012, * 2 - Feb 2012, * ..... * 13 - Jan 2013 */ int tegra_get_linear_age(void) { struct rtc_time tm; int year, month, linear_age; struct rtc_device *rtc_dev = NULL; const char *name = NULL; int ret; struct device *dev = NULL; linear_age = -1; year = month = 0; dev = class_find_device(rtc_class, NULL, &name, has_readtime); if (!dev) { pr_err("DVFS: No device with readtime capability\n"); goto done; } name = dev_name(dev); pr_info("DVFS: Got RTC device name:%s\n", name); if (name) rtc_dev = rtc_class_open((char *)name); if (!rtc_dev) { pr_err("DVFS: No RTC device\n"); goto error_dev; } ret = rtc_read_time(rtc_dev, &tm); if (ret < 0) { pr_err("DVFS: Can't read RTC time\n"); goto error_rtc; } year = tm.tm_year; /*Normalize it to 2012*/ year -= 112; month = tm.tm_mon + 1; if (year >= 0) linear_age = year * 12 + month; error_rtc: rtc_class_close(rtc_dev); error_dev: put_device(dev); done: return linear_age; }
static int dump_thread(void *data) { struct rtc_device *rtc; struct rtc_time tm; int err = 0; char log_file_name[100]; char backup_log_file_name[100]; pr_at_info("%s: Enter into dump_thread\n", __func__); /* Dump the last kernel log */ /* MX have two rtc devices */ rtc = rtc_class_open("rtc0"); if (rtc == NULL) { rtc = rtc_class_open("rtc1"); if (rtc == NULL) { pr_err(ATP "%s: can not open rtc devices\n", __func__); err = -ENODEV; } } if (!err) { err = rtc_read_time(rtc, &tm); if (err) pr_err(ATP "%s: unable to read the hardware clock\n", __func__); } sprintf(log_file_name, "%s-%d%02d%02d_%02d%02d%02d", CONFIG_LAST_KMSG_LOG_FILE, tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday, tm.tm_hour + 8, tm.tm_min, tm.tm_sec); pr_at_info("%s: Get log file name: %s\n", __func__, log_file_name); err = dump_last_kmsg(log_file_name); if (err) { pr_err(ATP "%s: Failed dump kernel log to %s\n", __func__, log_file_name); sprintf(backup_log_file_name, "%s-%d%02d%02d_%02d%02d%02d", CONFIG_BACKUP_LAST_KMSG_LOG_FILE, tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday, tm.tm_hour + 8, tm.tm_min, tm.tm_sec); pr_at_info("%s: Get backup log file name: %s\n", __func__, backup_log_file_name); err = dump_last_kmsg(backup_log_file_name); if (err) { pr_err(ATP "%s: Failed dump kernel log to %s\n", __func__, backup_log_file_name); goto out; } else { pr_at_info("%s: kernel log file dumped to %s\n", __func__, backup_log_file_name); } } else { pr_at_info("%s: kernel log file dumped to %s\n", __func__, log_file_name); } out: complete_and_exit(&dump, 0); return err; }
static ssize_t rtc_sysfs_show_date(struct class_device *dev, char *buf) { ssize_t retval; struct rtc_time tm; retval = rtc_read_time(dev, &tm); if (retval == 0) { retval = sprintf(buf, "%04d-%02d-%02d\n", tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday); } return retval; }
static ssize_t rtc_sysfs_show_time(struct class_device *dev, char *buf) { ssize_t retval; struct rtc_time tm; retval = rtc_read_time(dev, &tm); if (retval == 0) { retval = sprintf(buf, "%02d:%02d:%02d\n", tm.tm_hour, tm.tm_min, tm.tm_sec); } return retval; }
static ssize_t time_show(struct device *dev, struct device_attribute *attr, char *buf) { ssize_t retval; struct rtc_time tm; retval = rtc_read_time(to_rtc_device(dev), &tm); if (retval == 0) { retval = sprintf(buf, "%02d:%02d:%02d\n", tm.tm_hour, tm.tm_min, tm.tm_sec); } return retval; }
static ssize_t date_show(struct device *dev, struct device_attribute *attr, char *buf) { ssize_t retval; struct rtc_time tm; retval = rtc_read_time(to_rtc_device(dev), &tm); if (retval == 0) { retval = sprintf(buf, "%04d-%02d-%02d\n", tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday); } return retval; }
static ssize_t rtc_sysfs_show_since_epoch(struct class_device *dev, char *buf) { ssize_t retval; struct rtc_time tm; retval = rtc_read_time(dev, &tm); if (retval == 0) { unsigned long time; rtc_tm_to_time(&tm, &time); retval = sprintf(buf, "%lu\n", time); } return retval; }
static void __init test_wakealarm(struct rtc_device *rtc, suspend_state_t state) { static char err_readtime[] __initdata = KERN_ERR "PM: can't read %s time, err %d\n"; static char err_wakealarm [] __initdata = KERN_ERR "PM: can't set %s wakealarm, err %d\n"; static char err_suspend[] __initdata = KERN_ERR "PM: suspend test failed, error %d\n"; static char info_test[] __initdata = KERN_INFO "PM: test RTC wakeup from '%s' suspend\n"; unsigned long now; struct rtc_wkalrm alm; int status; status = rtc_read_time(rtc, &alm.time); if (status < 0) { printk(err_readtime, dev_name(&rtc->dev), status); return; } rtc_tm_to_time(&alm.time, &now); 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) { printk(err_wakealarm, dev_name(&rtc->dev), status); return; } if (state == PM_SUSPEND_MEM) { printk(info_test, pm_states[state]); status = pm_suspend(state); if (status == -ENODEV) state = PM_SUSPEND_STANDBY; } if (state == PM_SUSPEND_STANDBY) { printk(info_test, pm_states[state]); status = pm_suspend(state); } if (status < 0) printk(err_suspend, status); alm.enabled = false; rtc_set_alarm(rtc, &alm); }
/** * alarmtimer_suspend - Suspend time callback * @dev: unused * @state: unused * * When we are going into suspend, we look through the bases * to see which is the soonest timer to expire. We then * set an rtc timer to fire that far into the future, which * will wake us from suspend. */ static int alarmtimer_suspend(struct device *dev) { struct rtc_time tm; ktime_t min, now; unsigned long flags; struct rtc_device *rtc; int i; spin_lock_irqsave(&freezer_delta_lock, flags); min = freezer_delta; freezer_delta = ktime_set(0, 0); spin_unlock_irqrestore(&freezer_delta_lock, flags); rtc = rtcdev; /* If we have no rtcdev, just return */ if (!rtc) return 0; /* Find the soonest timer to expire*/ for (i = 0; i < ALARM_NUMTYPE; i++) { struct alarm_base *base = &alarm_bases[i]; struct timerqueue_node *next; ktime_t delta; spin_lock_irqsave(&base->lock, flags); next = timerqueue_getnext(&base->timerqueue); spin_unlock_irqrestore(&base->lock, flags); if (!next) continue; delta = ktime_sub(next->expires, base->gettime()); if (!min.tv64 || (delta.tv64 < min.tv64)) min = delta; } if (min.tv64 == 0) return 0; /* XXX - Should we enforce a minimum sleep time? */ WARN_ON(min.tv64 < NSEC_PER_SEC); /* Setup an rtc timer to fire that far in the future */ rtc_timer_cancel(rtc, &rtctimer); rtc_read_time(rtc, &tm); now = rtc_tm_to_ktime(tm); now = ktime_add(now, min); rtc_timer_start(rtc, &rtctimer, now, ktime_set(0, 0)); return 0; }
static int __init rtc_hctosys(void) { int err = -ENODEV; struct rtc_time tm; struct timespec64 tv64 = { .tv_nsec = NSEC_PER_SEC >> 1, }; struct rtc_device *rtc = rtc_class_open(CONFIG_RTC_HCTOSYS_DEVICE); if (rtc == NULL) { pr_info("unable to open rtc device (%s)\n", CONFIG_RTC_HCTOSYS_DEVICE); goto err_open; } err = rtc_read_time(rtc, &tm); if (err) { dev_err(rtc->dev.parent, "hctosys: unable to read the hardware clock\n"); goto err_read; } tv64.tv_sec = rtc_tm_to_time64(&tm); #if BITS_PER_LONG == 32 if (tv64.tv_sec > INT_MAX) goto err_read; #endif err = do_settimeofday64(&tv64); dev_info(rtc->dev.parent, "setting system clock to " "%d-%02d-%02d %02d:%02d:%02d UTC (%lld)\n", tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday, tm.tm_hour, tm.tm_min, tm.tm_sec, (long long) tv64.tv_sec); err_read: rtc_class_close(rtc); err_open: rtc_hctosys_ret = err; return err; } late_initcall(rtc_hctosys);
static ssize_t since_epoch_show(struct device *dev, struct device_attribute *attr, char *buf) { ssize_t retval; struct rtc_time tm; retval = rtc_read_time(to_rtc_device(dev), &tm); if (retval == 0) { unsigned long time; rtc_tm_to_time(&tm, &time); retval = sprintf(buf, "%lu\n", time); } return retval; }
static void rtc_reg_write(void *opaque, uint32_t addr, uint32_t value) { SysPortState *s = opaque; if ((s->rtc_reg & RTC_STROBE) && !(value & RTC_STROBE)) { s->rtc_cmd = s->rtc_reg & 0x07; if (s->rtc_cmd == RTC_CMD_READ) { rtc_read_time(s); } else if (s->rtc_cmd == RTC_CMD_EXMODE) { s->rtc_cmd = s->rtc_shift_cmd & 0x0f; if (s->rtc_cmd == RTC_CMD_READ) { rtc_read_time(s); } } } if ((s->rtc_reg & RTC_CLOCK) && !(value & RTC_CLOCK)) { uint8_t din = ((s->rtc_reg & RTC_DIN) != 0); // if ((s->rtc_reg & 0x07) == RTC_CMD_EXMODE) { s->rtc_shift_cmd |= din << 4; s->rtc_shift_cmd >>= 1; // } else if (s->rtc_cmd == RTC_CMD_SHIFT) { s->rtc_shift_out >>= 1; // } }
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; }
int rtc_hctosys(void) { int err; struct rtc_time tm; struct rtc_device *rtc = rtc_class_open(CONFIG_RTC_HCTOSYS_DEVICE); if (rtc == NULL) { printk("%s: unable to open rtc device (%s)\n", __FILE__, CONFIG_RTC_HCTOSYS_DEVICE); return -ENODEV; } err = rtc_read_time(rtc, &tm); if (err == 0) { err = rtc_valid_tm(&tm); if (err == 0) { struct timespec tv; #ifdef CONFIG_RTC_DRV_MSM struct timeval curtv; #endif tv.tv_nsec = NSEC_PER_SEC >> 1; rtc_tm_to_time(&tm, &tv.tv_sec); #ifdef CONFIG_RTC_DRV_MSM /* Only update kernel time if seconds changed.. otherwise this causes confusion with A2DP. RTC time is in seconds.. so every invocation of do_settimeofday() will cause cur ms to skip.. */ do_gettimeofday(&curtv); if ((tv.tv_sec > (curtv.tv_sec + 1)) || ((tv.tv_sec + 1) < curtv.tv_sec)) { #endif do_settimeofday(&tv); dev_info(rtc->dev.parent, "setting system clock to " "%d-%02d-%02d %02d:%02d:%02d UTC (%u)\n", tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday, tm.tm_hour, tm.tm_min, tm.tm_sec, (unsigned int) tv.tv_sec); #ifdef CONFIG_RTC_DRV_MSM } #endif } else