/* rtc.c */
extern int get_epoch_rtc(unsigned long *epoch, int silent);
extern int set_epoch_rtc(unsigned long epoch);
+extern char *rtc_dev_name;
.PP
.B "[\-u|\-\-utc] \-\-localtime \-\-noadjfile \-\-directisa"
.B "\-\-test [\-D|\-\-debug]"
+.B "\-\-rtc=filename"
.PP
and arcane options for DEC Alpha:
.PP
.B \-\-localtime
must be specified when using this option.
+.TP
+.B \-\-rtc=filename
+overrides the default /dev file name, which is
+.IR /dev/rtc
+on many platforms but may be
+.IR /dev/rtc0 ,
+.IR /dev/rtc1 ,
+and so on.
+
.TP
.B \-\-directisa
is meaningful only on an ISA machine or an Alpha (which implements enough
because all of the other names are inappropriate to the point of being
misleading.
.PP
+So for example, some non-ISA systems have a few real time clocks with
+only one of them having its own power domain.
+A very low power external I2C or SPI clock chip might be used with a
+backup battery as the hardware clock to initialize a more functional
+integrated real-time clock which is used for most other purposes.
+.PP
.B The System Time:
This is the time kept by a clock inside the Linux kernel and driven by
a timer interrupt. (On an ISA machine, the timer interrupt is part of
Also, though there are versions of the rtc driver that work on DEC
Alphas, there appear to be plenty of Alphas on which the rtc driver
does not work (a common symptom is hwclock hanging).
+Moreover, recent Linux systems have more generic support for RTCs,
+even systems that have more than one, so you might need to override
+the default by specifying
+.I /dev/rtc0
+or
+.I /dev/rtc1
+instead.
.PP
On older systems, the method of accessing the Hardware Clock depends on
the system hardware.
.PP
.B hwclock
tries to use /dev/rtc. If it is compiled for a kernel that doesn't have
-that function or it is unable to open /dev/rtc,
+that function or it is unable to open /dev/rtc
+(or the alternative special file you've defined on the command line)
.B hwclock
will fall back to another method, if available. On an ISA or Alpha
machine, you can force
Note that this section is only relevant when you are using the "direct
ISA" method of accessing the Hardware Clock.
-
-
+ACPI provides a standard way to access century values, when they
+are supported by the hardware.
.SH "ENVIRONMENT VARIABLES"
.I TZ
.RI ( /usr/lib/zoneinfo
on old systems)
.I /dev/rtc
+.I /dev/rtc0
.I /dev/port
.I /dev/tty1
.I /proc/cpuinfo
"\nOptions: \n"
" --utc the hardware clock is kept in coordinated universal time\n"
" --localtime the hardware clock is kept in local time\n"
+ " --rtc=path special /dev/... file to use instead of default\n"
" --directisa access the ISA bus directly instead of %s\n"
" --badyear ignore rtc's year because the bios is broken\n"
" --date specifies the time to which to set the hardware clock\n"
{ "test", 0, 0, 135 },
{ "date", 1, 0, 136 },
{ "epoch", 1, 0, 137 },
+ { "rtc", 1, 0, 'f' },
{ NULL, 0, 0, 0 }
};
ARCconsole = Jensen = SRM = funky_toy = directisa = badyear = FALSE;
date_opt = NULL;
- while ((c = getopt_long (argc, argv, "?hvVDarsuwAJSF", longopts, NULL))
+ while ((c = getopt_long (argc, argv, "?hvVDarsuwAJSFf:", longopts, NULL))
!= -1) {
switch (c) {
case 'D':
case 137:
epoch_option = atoi(optarg); /* --epoch */
break;
+ case 'f':
+ rtc_dev_name = optarg; /* --rtc */
+ break;
case 'v': /* --version */
case 'V':
out_version();
#define RTC_EPOCH_SET _IOW('p', 0x0e, unsigned long) /* Set epoch */
#endif
+/* /dev/rtc is conventionally chardev 10/135
+ * ia64 uses /dev/efirtc, chardev 10/136
+ * devfs (obsolete) used /dev/misc/... for miscdev
+ * new RTC framework + udev uses dynamic major and /dev/rtc0.../dev/rtcN
+ * ... so we need an overridable default
+ */
-/* ia64 uses /dev/efirtc (char 10,136) */
-/* devfs uses /dev/misc/rtc */
-#ifdef __ia64__
-#define RTC_DEVN "efirtc"
-#else
-#define RTC_DEVN "rtc"
-#endif
-
-static char *rtc_dev_name;
+/* default or user defined dev (by hwclock --rtc=<path>) */
+char *rtc_dev_name;
static int
open_rtc(void) {
- int rtc_fd;
-
- rtc_dev_name = "/dev/" RTC_DEVN;
- rtc_fd = open(rtc_dev_name, O_RDONLY);
- if (rtc_fd < 0 && errno == ENOENT) {
- rtc_dev_name = "/dev/misc/" RTC_DEVN;
- rtc_fd = open(rtc_dev_name, O_RDONLY);
- if (rtc_fd < 0 && errno == ENOENT)
- rtc_dev_name = "/dev/" RTC_DEVN;
- }
- return rtc_fd;
+ char *fls[] = {
+#ifdef __ia64__
+ "/dev/efirtc",
+ "/dev/misc/efirtc",
+#endif
+ "/dev/rtc",
+ "/dev/rtc0",
+ "/dev/misc/rtc",
+ NULL
+ };
+ char **p = fls;
+ char *fname = rtc_dev_name ? : *p;
+
+ do {
+ int fd = open(fname, O_RDONLY);
+
+ if (fd < 0 && errno == ENOENT) {
+ if (fname == rtc_dev_name)
+ break;
+ fname = *++p;
+ } else {
+ rtc_dev_name = *p;
+ return fd;
+ }
+ } while(fname);
+
+ if (!rtc_dev_name)
+ rtc_dev_name = *fls;
+ return -1;
}
static int
}
static struct clock_ops rtc = {
- "/dev/" RTC_DEVN " interface to clock",
+ "/dev interface to clock",
get_permissions_rtc,
read_hardware_clock_rtc,
set_hardware_clock_rtc,