summaryrefslogtreecommitdiffstats
path: root/sys-utils/hwclock-rtc.c
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--sys-utils/hwclock-rtc.c93
1 files changed, 92 insertions, 1 deletions
diff --git a/sys-utils/hwclock-rtc.c b/sys-utils/hwclock-rtc.c
index 7094cd0..113d4e8 100644
--- a/sys-utils/hwclock-rtc.c
+++ b/sys-utils/hwclock-rtc.c
@@ -1,6 +1,11 @@
/*
* SPDX-License-Identifier: GPL-2.0-or-later
*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
* rtc.c - Use /dev/rtc for clock access
*/
#include <asm/ioctl.h>
@@ -424,7 +429,7 @@ static int resolve_rtc_param_alias(const char *alias, __u64 *value)
/* kernel uapi __u64 can be defined differently than uint64_t */
static int strtoku64(const char *str, __u64 *num, int base)
{
- return ul_strtou64(str, (uint64_t *) &num, base);
+ return ul_strtou64(str, (uint64_t *) num, base);
}
/*
@@ -518,3 +523,89 @@ done:
free(opt);
return rc;
}
+
+#ifndef RTC_VL_DATA_INVALID
+#define RTC_VL_DATA_INVALID 0x1
+#endif
+#ifndef RTC_VL_BACKUP_LOW
+#define RTC_VL_BACKUP_LOW 0x2
+#endif
+#ifndef RTC_VL_BACKUP_EMPTY
+#define RTC_VL_BACKUP_EMPTY 0x4
+#endif
+#ifndef RTC_VL_ACCURACY_LOW
+#define RTC_VL_ACCURACY_LOW 0x8
+#endif
+#ifndef RTC_VL_BACKUP_SWITCH
+#define RTC_VL_BACKUP_SWITCH 0x10
+#endif
+
+int rtc_vl_read(const struct hwclock_control *ctl)
+{
+ unsigned int vl;
+ int rtc_fd;
+ size_t i;
+ static const struct vl_bit {
+ unsigned int bit;
+ const char *desc;
+ } vl_bits[] = {
+ { RTC_VL_DATA_INVALID, N_("Voltage too low, RTC data is invalid") },
+ { RTC_VL_BACKUP_LOW, N_("Backup voltage is low") },
+ { RTC_VL_BACKUP_EMPTY, N_("Backup empty or not present") },
+ { RTC_VL_ACCURACY_LOW, N_("Voltage is low, RTC accuracy is reduced") },
+ { RTC_VL_BACKUP_SWITCH, N_("Backup switchover happened") },
+ };
+
+ rtc_fd = open_rtc(ctl);
+ if (rtc_fd < 0) {
+ warnx(_("cannot open %s"), rtc_dev_name);
+ return 1;
+ }
+
+ if (ioctl(rtc_fd, RTC_VL_READ, &vl) == -1) {
+ warn(_("ioctl(%d, RTC_VL_READ) on %s failed"),
+ rtc_fd, rtc_dev_name);
+ return 1;
+ }
+
+ if (ctl->verbose) {
+ printf(_("ioctl(%d, RTC_VL_READ) on %s returned 0x%x\n"),
+ rtc_fd, rtc_dev_name, vl);
+ }
+
+ for (i = 0; i < ARRAY_SIZE(vl_bits); ++i) {
+ const struct vl_bit *vlb = &vl_bits[i];
+
+ if (vl & vlb->bit) {
+ printf("0x%02x - %s\n", vlb->bit, vlb->desc);
+ vl &= ~vlb->bit;
+ }
+ }
+ if (vl)
+ printf("0x%02x - unknown bit(s)\n", vl);
+
+ return 0;
+}
+
+int rtc_vl_clear(const struct hwclock_control *ctl)
+{
+ int rtc_fd;
+
+ rtc_fd = open_rtc(ctl);
+ if (rtc_fd < 0) {
+ warnx(_("cannot open %s"), rtc_dev_name);
+ return 1;
+ }
+
+ if (ioctl(rtc_fd, RTC_VL_CLR) == -1) {
+ warn(_("ioctl(%d, RTC_VL_CLEAR) on %s failed"),
+ rtc_fd, rtc_dev_name);
+ return 1;
+ }
+
+ if (ctl->verbose)
+ printf(_("ioctl(%d, RTC_VL_CLEAR) on %s succeeded.\n"),
+ rtc_fd, rtc_dev_name);
+
+ return 0;
+}