From 88681c5f1afe724ca914a7202225e6e640d37222 Mon Sep 17 00:00:00 2001 From: Karel Zak Date: Mon, 19 Mar 2007 10:14:13 +0100 Subject: [PATCH] hwclock: add --rtc= option and support for /dev/rtc0 The patch to allow "hwclock --rtc /dev/rtc1" and so on, since "/dev/rtc" may not be there and "/dev/rtc0" may not be the right answer either. The "--rtc" is compatible with next Bryan Henderson's hwclock versions. Signed-off-by: David Brownell Signed-off-by: Karel Zak --- hwclock/clock.h | 1 + hwclock/hwclock.8 | 31 ++++++++++++++++++++++--- hwclock/hwclock.c | 7 +++++- hwclock/rtc.c | 59 ++++++++++++++++++++++++++++++----------------- 4 files changed, 73 insertions(+), 25 deletions(-) diff --git a/hwclock/clock.h b/hwclock/clock.h index 91d3df80..f1d00e49 100644 --- a/hwclock/clock.h +++ b/hwclock/clock.h @@ -33,3 +33,4 @@ extern void set_cmos_access(int Jensen, int funky_toy); /* 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; diff --git a/hwclock/hwclock.8 b/hwclock/hwclock.8 index e3fcb414..37d80e79 100644 --- a/hwclock/hwclock.8 +++ b/hwclock/hwclock.8 @@ -22,6 +22,7 @@ other options: .PP .B "[\-u|\-\-utc] \-\-localtime \-\-noadjfile \-\-directisa" .B "\-\-test [\-D|\-\-debug]" +.B "\-\-rtc=filename" .PP and arcane options for DEC Alpha: .PP @@ -181,6 +182,15 @@ or .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 @@ -314,6 +324,12 @@ capitalized form, was coined for use by 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 @@ -381,6 +397,13 @@ a relatively recent addition to Linux. Older systems don't have it. 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. @@ -411,7 +434,8 @@ file /dev/tty1. .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 @@ -569,8 +593,8 @@ maintainer; an option may be appropriate. 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 @@ -581,6 +605,7 @@ ISA" method of accessing the Hardware Clock. .RI ( /usr/lib/zoneinfo on old systems) .I /dev/rtc +.I /dev/rtc0 .I /dev/port .I /dev/tty1 .I /proc/cpuinfo diff --git a/hwclock/hwclock.c b/hwclock/hwclock.c index ec868152..9731dadf 100644 --- a/hwclock/hwclock.c +++ b/hwclock/hwclock.c @@ -1210,6 +1210,7 @@ usage( const char *fmt, ... ) { "\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" @@ -1265,6 +1266,7 @@ static const struct option longopts[] = { { "test", 0, 0, 135 }, { "date", 1, 0, 136 }, { "epoch", 1, 0, 137 }, + { "rtc", 1, 0, 'f' }, { NULL, 0, 0, 0 } }; @@ -1314,7 +1316,7 @@ main(int argc, char **argv) { 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': @@ -1379,6 +1381,9 @@ main(int argc, char **argv) { case 137: epoch_option = atoi(optarg); /* --epoch */ break; + case 'f': + rtc_dev_name = optarg; /* --rtc */ + break; case 'v': /* --version */ case 'V': out_version(); diff --git a/hwclock/rtc.c b/hwclock/rtc.c index 3876da93..33be42bb 100644 --- a/hwclock/rtc.c +++ b/hwclock/rtc.c @@ -82,30 +82,47 @@ struct linux_rtc_time { #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=) */ +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 @@ -346,7 +363,7 @@ get_permissions_rtc(void) { } 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, -- 2.39.5