From 5ab788d7383289bfc141ab357767bc6c11bbf77f Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Mon, 30 May 2016 20:57:50 +0200 Subject: rtc: cmos: move mc146818rtc code out of asm-generic/rtc.h Drivers should not really include stuff from asm-generic directly, and the PC-style cmos rtc driver does this in order to reuse the mc146818 implementation of get_rtc_time/set_rtc_time rather than the architecture specific one for the architecture it gets built for. To make it more obvious what is going on, this moves and renames the two functions into include/linux/mc146818rtc.h, which holds the other mc146818 specific code. Ideally it would be in a .c file, but that would require extra infrastructure as the functions are called by multiple drivers with conflicting dependencies. With this change, the asm-generic/rtc.h header also becomes much more generic, so it can be reused more easily across any architecture that still relies on the genrtc driver. The only caller of the internal __get_rtc_time/__set_rtc_time functions is in arch/alpha/kernel/rtc.c, and we just change those over to the new naming. Signed-off-by: Arnd Bergmann Acked-by: Geert Uytterhoeven Signed-off-by: Alexandre Belloni --- arch/x86/include/asm/mc146818rtc.h | 1 - arch/x86/platform/efi/efi_64.c | 1 + arch/x86/platform/intel-mid/intel_mid_vrtc.c | 1 + 3 files changed, 2 insertions(+), 1 deletion(-) (limited to 'arch/x86') diff --git a/arch/x86/include/asm/mc146818rtc.h b/arch/x86/include/asm/mc146818rtc.h index 0f555cc31984..24acd9ba7837 100644 --- a/arch/x86/include/asm/mc146818rtc.h +++ b/arch/x86/include/asm/mc146818rtc.h @@ -6,7 +6,6 @@ #include #include -#include #ifndef RTC_PORT #define RTC_PORT(x) (0x70 + (x)) diff --git a/arch/x86/platform/efi/efi_64.c b/arch/x86/platform/efi/efi_64.c index 6e7242be1c87..663c282801f3 100644 --- a/arch/x86/platform/efi/efi_64.c +++ b/arch/x86/platform/efi/efi_64.c @@ -25,6 +25,7 @@ #include #include #include +#include #include #include #include diff --git a/arch/x86/platform/intel-mid/intel_mid_vrtc.c b/arch/x86/platform/intel-mid/intel_mid_vrtc.c index ee40fcb6e54d..58024862a7eb 100644 --- a/arch/x86/platform/intel-mid/intel_mid_vrtc.c +++ b/arch/x86/platform/intel-mid/intel_mid_vrtc.c @@ -22,6 +22,7 @@ #include #include #include +#include #include #include -- cgit v1.2.3 From 463a86304cae92e10277b47180ac59cf93982e5b Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Mon, 30 May 2016 20:57:51 +0200 Subject: char/genrtc: x86: remove remnants of asm/rtc.h Commit 3195ef59cb42 ("x86: Do full rtc synchronization with ntp") had the side-effect of unconditionally enabling the RTC_LIB symbol on x86, which in turn disables the selection of the CONFIG_RTC and CONFIG_GEN_RTC drivers that contain a two older implementations of the CONFIG_RTC_DRV_CMOS driver. This removes x86 from the list for genrtc, and changes all references to the asm/rtc.h header to instead point to the interfaces from linux/mc146818rtc.h. Signed-off-by: Arnd Bergmann Acked-by: Geert Uytterhoeven Signed-off-by: Alexandre Belloni --- arch/x86/include/asm/rtc.h | 1 - arch/x86/kernel/hpet.c | 3 +-- arch/x86/kernel/rtc.c | 3 +-- arch/x86/platform/efi/efi.c | 1 - drivers/acpi/acpi_cmos_rtc.c | 2 +- drivers/base/power/trace.c | 6 +++--- drivers/char/Kconfig | 2 +- drivers/rtc/rtc-mrst.c | 2 +- 8 files changed, 8 insertions(+), 12 deletions(-) delete mode 100644 arch/x86/include/asm/rtc.h (limited to 'arch/x86') diff --git a/arch/x86/include/asm/rtc.h b/arch/x86/include/asm/rtc.h deleted file mode 100644 index f71c3b0ed360..000000000000 --- a/arch/x86/include/asm/rtc.h +++ /dev/null @@ -1 +0,0 @@ -#include diff --git a/arch/x86/kernel/hpet.c b/arch/x86/kernel/hpet.c index f112af7aa62e..357900aad62c 100644 --- a/arch/x86/kernel/hpet.c +++ b/arch/x86/kernel/hpet.c @@ -1020,7 +1020,6 @@ void hpet_disable(void) */ #include #include -#include #define DEFAULT_RTC_INT_FREQ 64 #define DEFAULT_RTC_SHIFT 6 @@ -1244,7 +1243,7 @@ irqreturn_t hpet_rtc_interrupt(int irq, void *dev_id) memset(&curr_time, 0, sizeof(struct rtc_time)); if (hpet_rtc_flags & (RTC_UIE | RTC_AIE)) - get_rtc_time(&curr_time); + mc146818_set_time(&curr_time); if (hpet_rtc_flags & RTC_UIE && curr_time.tm_sec != hpet_prev_update_sec) { diff --git a/arch/x86/kernel/rtc.c b/arch/x86/kernel/rtc.c index eceaa082ec3f..79c6311cd912 100644 --- a/arch/x86/kernel/rtc.c +++ b/arch/x86/kernel/rtc.c @@ -13,7 +13,6 @@ #include #include #include -#include #include #ifdef CONFIG_X86_32 @@ -47,7 +46,7 @@ int mach_set_rtc_mmss(const struct timespec *now) rtc_time_to_tm(nowtime, &tm); if (!rtc_valid_tm(&tm)) { - retval = set_rtc_time(&tm); + retval = mc146818_set_time(&tm); if (retval) printk(KERN_ERR "%s: RTC write failed with error %d\n", __func__, retval); diff --git a/arch/x86/platform/efi/efi.c b/arch/x86/platform/efi/efi.c index f93545e7dc54..56400d03409f 100644 --- a/arch/x86/platform/efi/efi.c +++ b/arch/x86/platform/efi/efi.c @@ -51,7 +51,6 @@ #include #include #include -#include #include static struct efi efi_phys __initdata; diff --git a/drivers/acpi/acpi_cmos_rtc.c b/drivers/acpi/acpi_cmos_rtc.c index 81dc75033f15..0980a133916f 100644 --- a/drivers/acpi/acpi_cmos_rtc.c +++ b/drivers/acpi/acpi_cmos_rtc.c @@ -14,7 +14,7 @@ #include #include #include -#include +#include #include "internal.h" diff --git a/drivers/base/power/trace.c b/drivers/base/power/trace.c index a6975795e7f3..efec10b49d59 100644 --- a/drivers/base/power/trace.c +++ b/drivers/base/power/trace.c @@ -11,7 +11,7 @@ #include #include -#include +#include #include "power.h" @@ -103,7 +103,7 @@ static int set_magic_time(unsigned int user, unsigned int file, unsigned int dev n /= 24; time.tm_min = (n % 20) * 3; n /= 20; - set_rtc_time(&time); + mc146818_set_time(&time); return n ? -1 : 0; } @@ -112,7 +112,7 @@ static unsigned int read_magic_time(void) struct rtc_time time; unsigned int val; - get_rtc_time(&time); + mc146818_get_time(&time); pr_info("RTC time: %2d:%02d:%02d, date: %02d/%02d/%02d\n", time.tm_hour, time.tm_min, time.tm_sec, time.tm_mon + 1, time.tm_mday, time.tm_year % 100); diff --git a/drivers/char/Kconfig b/drivers/char/Kconfig index 601f64fcc890..31b5861649ee 100644 --- a/drivers/char/Kconfig +++ b/drivers/char/Kconfig @@ -328,7 +328,7 @@ config JS_RTC config GEN_RTC tristate "Generic /dev/rtc emulation" depends on RTC!=y - depends on ALPHA || M68K || MN10300 || PARISC || PPC || X86 + depends on ALPHA || M68K || MN10300 || PARISC || PPC ---help--- If you say Y here and create a character special file /dev/rtc with major number 10 and minor number 135 using mknod ("man mknod"), you diff --git a/drivers/rtc/rtc-mrst.c b/drivers/rtc/rtc-mrst.c index 0094d9bdd1e6..fe840c0edfef 100644 --- a/drivers/rtc/rtc-mrst.c +++ b/drivers/rtc/rtc-mrst.c @@ -32,11 +32,11 @@ #include #include #include +#include #include #include #include -#include #include #include #include -- cgit v1.2.3 From c361db5c2c64f1b7ffed5e9cc42e5062432238f2 Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Mon, 6 Jun 2016 16:09:52 +0200 Subject: x86: include linux/ratelimit.h in nmi.c When building random configurations, we now occasionally get a new build error: In file included from include/linux/kernel.h:13:0, from include/linux/list.h:8, from include/linux/preempt.h:10, from include/linux/spinlock.h:50, from arch/x86/kernel/nmi.c:13: arch/x86/kernel/nmi.c: In function 'nmi_max_handler': include/linux/printk.h:375:9: error: type defaults to 'int' in declaration of 'DEFINE_RATELIMIT_STATE' [-Werror=implicit-int] static DEFINE_RATELIMIT_STATE(_rs, \ ^ arch/x86/kernel/nmi.c:110:2: note: in expansion of macro 'printk_ratelimited' printk_ratelimited(KERN_INFO ^~~~~~~~~~~~~~~~~~ This was working before the rtc rework series because linux/ratelimit.h was included implictly through asm/mach_traps.h -> asm/mc146818rtc.h -> linux/mc146818rtc.h -> linux/rtc.h -> linux/device.h. We clearly shouldn't rely on this indirect inclusion, so this adds an explicit #include in the file that needs it. Signed-off-by: Arnd Bergmann Reported-by: kbuild test robot Acked-by: Thomas Gleixner Fixes: 5ab788d73832 ("rtc: cmos: move mc146818rtc code out of asm-generic/rtc.h") Signed-off-by: Alexandre Belloni --- arch/x86/kernel/nmi.c | 1 + 1 file changed, 1 insertion(+) (limited to 'arch/x86') diff --git a/arch/x86/kernel/nmi.c b/arch/x86/kernel/nmi.c index 04b132a767f1..bfe4d6c96fbd 100644 --- a/arch/x86/kernel/nmi.c +++ b/arch/x86/kernel/nmi.c @@ -17,6 +17,7 @@ #include #include #include +#include #include #include -- cgit v1.2.3 From d6faca40f40b62aca8ea8c29289c7bf7456172bb Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Wed, 1 Jun 2016 16:46:23 +0200 Subject: rtc: move mc146818 helper functions out-of-line The mc146818_get_time/mc146818_set_time functions are rather large inline functions in a global header file and are used in several drivers and in x86 specific code. Here we move them into a separate .c file that is compiled whenever any of the users require it. This also lets us remove the linux/acpi.h header inclusion from mc146818rtc.h, which in turn avoids some warnings about duplicate definition of the TRUE/FALSE macros. Signed-off-by: Arnd Bergmann Signed-off-by: Alexandre Belloni --- arch/x86/Kconfig | 1 + drivers/rtc/Kconfig | 6 ++ drivers/rtc/Makefile | 1 + drivers/rtc/rtc-mc146818-lib.c | 198 +++++++++++++++++++++++++++++++++++++++++ include/linux/mc146818rtc.h | 193 +-------------------------------------- 5 files changed, 208 insertions(+), 191 deletions(-) create mode 100644 drivers/rtc/rtc-mc146818-lib.c (limited to 'arch/x86') diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig index 0a7b885964ba..54d46c5c04d0 100644 --- a/arch/x86/Kconfig +++ b/arch/x86/Kconfig @@ -151,6 +151,7 @@ config X86 select OLD_SIGSUSPEND3 if X86_32 || IA32_EMULATION select PERF_EVENTS select RTC_LIB + select RTC_MC146818_LIB select SPARSE_IRQ select SRCU select SYSCTL_EXCEPTION_TRACE diff --git a/drivers/rtc/Kconfig b/drivers/rtc/Kconfig index 13128a89657b..8526f1cded08 100644 --- a/drivers/rtc/Kconfig +++ b/drivers/rtc/Kconfig @@ -5,6 +5,10 @@ config RTC_LIB bool +config RTC_MC146818_LIB + bool + select RTC_LIB + menuconfig RTC_CLASS bool "Real Time Clock" default n @@ -809,6 +813,7 @@ config RTC_DRV_CMOS tristate "PC-style 'CMOS'" depends on X86 || ARM || M32R || PPC || MIPS || SPARC64 || MN10300 default y if X86 + select RTC_MC146818_LIB help Say "yes" here to get direct support for the real time clock found in every PC or ACPI-based system, and some other boards. @@ -827,6 +832,7 @@ config RTC_DRV_CMOS config RTC_DRV_ALPHA bool "Alpha PC-style CMOS" depends on ALPHA + select RTC_MC146818_LIB default y help Direct support for the real-time clock found on every Alpha diff --git a/drivers/rtc/Makefile b/drivers/rtc/Makefile index 024da2723d86..7cf7ad559c79 100644 --- a/drivers/rtc/Makefile +++ b/drivers/rtc/Makefile @@ -8,6 +8,7 @@ obj-$(CONFIG_RTC_LIB) += rtc-lib.o obj-$(CONFIG_RTC_HCTOSYS) += hctosys.o obj-$(CONFIG_RTC_SYSTOHC) += systohc.o obj-$(CONFIG_RTC_CLASS) += rtc-core.o +obj-$(CONFIG_RTC_MC146818_LIB) += rtc-mc146818-lib.o rtc-core-y := class.o interface.o ifdef CONFIG_RTC_DRV_EFI diff --git a/drivers/rtc/rtc-mc146818-lib.c b/drivers/rtc/rtc-mc146818-lib.c new file mode 100644 index 000000000000..2f1772a358ca --- /dev/null +++ b/drivers/rtc/rtc-mc146818-lib.c @@ -0,0 +1,198 @@ +#include +#include +#include +#include + +#ifdef CONFIG_ACPI +#include +#endif + +/* + * Returns true if a clock update is in progress + */ +static inline unsigned char mc146818_is_updating(void) +{ + unsigned char uip; + unsigned long flags; + + spin_lock_irqsave(&rtc_lock, flags); + uip = (CMOS_READ(RTC_FREQ_SELECT) & RTC_UIP); + spin_unlock_irqrestore(&rtc_lock, flags); + return uip; +} + +unsigned int mc146818_get_time(struct rtc_time *time) +{ + unsigned char ctrl; + unsigned long flags; + unsigned char century = 0; + +#ifdef CONFIG_MACH_DECSTATION + unsigned int real_year; +#endif + + /* + * read RTC once any update in progress is done. The update + * can take just over 2ms. We wait 20ms. There is no need to + * to poll-wait (up to 1s - eeccch) for the falling edge of RTC_UIP. + * If you need to know *exactly* when a second has started, enable + * periodic update complete interrupts, (via ioctl) and then + * immediately read /dev/rtc which will block until you get the IRQ. + * Once the read clears, read the RTC time (again via ioctl). Easy. + */ + if (mc146818_is_updating()) + mdelay(20); + + /* + * Only the values that we read from the RTC are set. We leave + * tm_wday, tm_yday and tm_isdst untouched. Even though the + * RTC has RTC_DAY_OF_WEEK, we ignore it, as it is only updated + * by the RTC when initially set to a non-zero value. + */ + spin_lock_irqsave(&rtc_lock, flags); + time->tm_sec = CMOS_READ(RTC_SECONDS); + time->tm_min = CMOS_READ(RTC_MINUTES); + time->tm_hour = CMOS_READ(RTC_HOURS); + time->tm_mday = CMOS_READ(RTC_DAY_OF_MONTH); + time->tm_mon = CMOS_READ(RTC_MONTH); + time->tm_year = CMOS_READ(RTC_YEAR); +#ifdef CONFIG_MACH_DECSTATION + real_year = CMOS_READ(RTC_DEC_YEAR); +#endif +#ifdef CONFIG_ACPI + if (acpi_gbl_FADT.header.revision >= FADT2_REVISION_ID && + acpi_gbl_FADT.century) + century = CMOS_READ(acpi_gbl_FADT.century); +#endif + ctrl = CMOS_READ(RTC_CONTROL); + spin_unlock_irqrestore(&rtc_lock, flags); + + if (!(ctrl & RTC_DM_BINARY) || RTC_ALWAYS_BCD) + { + time->tm_sec = bcd2bin(time->tm_sec); + time->tm_min = bcd2bin(time->tm_min); + time->tm_hour = bcd2bin(time->tm_hour); + time->tm_mday = bcd2bin(time->tm_mday); + time->tm_mon = bcd2bin(time->tm_mon); + time->tm_year = bcd2bin(time->tm_year); + century = bcd2bin(century); + } + +#ifdef CONFIG_MACH_DECSTATION + time->tm_year += real_year - 72; +#endif + + if (century) + time->tm_year += (century - 19) * 100; + + /* + * Account for differences between how the RTC uses the values + * and how they are defined in a struct rtc_time; + */ + if (time->tm_year <= 69) + time->tm_year += 100; + + time->tm_mon--; + + return RTC_24H; +} +EXPORT_SYMBOL_GPL(mc146818_get_time); + +/* Set the current date and time in the real time clock. */ +int mc146818_set_time(struct rtc_time *time) +{ + unsigned long flags; + unsigned char mon, day, hrs, min, sec; + unsigned char save_control, save_freq_select; + unsigned int yrs; +#ifdef CONFIG_MACH_DECSTATION + unsigned int real_yrs, leap_yr; +#endif + unsigned char century = 0; + + yrs = time->tm_year; + mon = time->tm_mon + 1; /* tm_mon starts at zero */ + day = time->tm_mday; + hrs = time->tm_hour; + min = time->tm_min; + sec = time->tm_sec; + + if (yrs > 255) /* They are unsigned */ + return -EINVAL; + + spin_lock_irqsave(&rtc_lock, flags); +#ifdef CONFIG_MACH_DECSTATION + real_yrs = yrs; + leap_yr = ((!((yrs + 1900) % 4) && ((yrs + 1900) % 100)) || + !((yrs + 1900) % 400)); + yrs = 72; + + /* + * We want to keep the year set to 73 until March + * for non-leap years, so that Feb, 29th is handled + * correctly. + */ + if (!leap_yr && mon < 3) { + real_yrs--; + yrs = 73; + } +#endif + +#ifdef CONFIG_ACPI + if (acpi_gbl_FADT.header.revision >= FADT2_REVISION_ID && + acpi_gbl_FADT.century) { + century = (yrs + 1900) / 100; + yrs %= 100; + } +#endif + + /* These limits and adjustments are independent of + * whether the chip is in binary mode or not. + */ + if (yrs > 169) { + spin_unlock_irqrestore(&rtc_lock, flags); + return -EINVAL; + } + + if (yrs >= 100) + yrs -= 100; + + if (!(CMOS_READ(RTC_CONTROL) & RTC_DM_BINARY) + || RTC_ALWAYS_BCD) { + sec = bin2bcd(sec); + min = bin2bcd(min); + hrs = bin2bcd(hrs); + day = bin2bcd(day); + mon = bin2bcd(mon); + yrs = bin2bcd(yrs); + century = bin2bcd(century); + } + + save_control = CMOS_READ(RTC_CONTROL); + CMOS_WRITE((save_control|RTC_SET), RTC_CONTROL); + save_freq_select = CMOS_READ(RTC_FREQ_SELECT); + CMOS_WRITE((save_freq_select|RTC_DIV_RESET2), RTC_FREQ_SELECT); + +#ifdef CONFIG_MACH_DECSTATION + CMOS_WRITE(real_yrs, RTC_DEC_YEAR); +#endif + CMOS_WRITE(yrs, RTC_YEAR); + CMOS_WRITE(mon, RTC_MONTH); + CMOS_WRITE(day, RTC_DAY_OF_MONTH); + CMOS_WRITE(hrs, RTC_HOURS); + CMOS_WRITE(min, RTC_MINUTES); + CMOS_WRITE(sec, RTC_SECONDS); +#ifdef CONFIG_ACPI + if (acpi_gbl_FADT.header.revision >= FADT2_REVISION_ID && + acpi_gbl_FADT.century) + CMOS_WRITE(century, acpi_gbl_FADT.century); +#endif + + CMOS_WRITE(save_control, RTC_CONTROL); + CMOS_WRITE(save_freq_select, RTC_FREQ_SELECT); + + spin_unlock_irqrestore(&rtc_lock, flags); + + return 0; +} +EXPORT_SYMBOL_GPL(mc146818_set_time); diff --git a/include/linux/mc146818rtc.h b/include/linux/mc146818rtc.h index e9e346b37846..a585b4b5fa0e 100644 --- a/include/linux/mc146818rtc.h +++ b/include/linux/mc146818rtc.h @@ -17,10 +17,6 @@ #include #include -#ifdef CONFIG_ACPI -#include -#endif - #ifdef __KERNEL__ #include /* spinlock_t */ extern spinlock_t rtc_lock; /* serialize CMOS RAM access */ @@ -126,192 +122,7 @@ struct cmos_rtc_board_info { #define RTC_IO_EXTENT_USED RTC_IO_EXTENT #endif /* ARCH_RTC_LOCATION */ -/* - * Returns true if a clock update is in progress - */ -static inline unsigned char mc146818_is_updating(void) -{ - unsigned char uip; - unsigned long flags; - - spin_lock_irqsave(&rtc_lock, flags); - uip = (CMOS_READ(RTC_FREQ_SELECT) & RTC_UIP); - spin_unlock_irqrestore(&rtc_lock, flags); - return uip; -} - -static inline unsigned int mc146818_get_time(struct rtc_time *time) -{ - unsigned char ctrl; - unsigned long flags; - unsigned char century = 0; - -#ifdef CONFIG_MACH_DECSTATION - unsigned int real_year; -#endif - - /* - * read RTC once any update in progress is done. The update - * can take just over 2ms. We wait 20ms. There is no need to - * to poll-wait (up to 1s - eeccch) for the falling edge of RTC_UIP. - * If you need to know *exactly* when a second has started, enable - * periodic update complete interrupts, (via ioctl) and then - * immediately read /dev/rtc which will block until you get the IRQ. - * Once the read clears, read the RTC time (again via ioctl). Easy. - */ - if (mc146818_is_updating()) - mdelay(20); - - /* - * Only the values that we read from the RTC are set. We leave - * tm_wday, tm_yday and tm_isdst untouched. Even though the - * RTC has RTC_DAY_OF_WEEK, we ignore it, as it is only updated - * by the RTC when initially set to a non-zero value. - */ - spin_lock_irqsave(&rtc_lock, flags); - time->tm_sec = CMOS_READ(RTC_SECONDS); - time->tm_min = CMOS_READ(RTC_MINUTES); - time->tm_hour = CMOS_READ(RTC_HOURS); - time->tm_mday = CMOS_READ(RTC_DAY_OF_MONTH); - time->tm_mon = CMOS_READ(RTC_MONTH); - time->tm_year = CMOS_READ(RTC_YEAR); -#ifdef CONFIG_MACH_DECSTATION - real_year = CMOS_READ(RTC_DEC_YEAR); -#endif -#ifdef CONFIG_ACPI - if (acpi_gbl_FADT.header.revision >= FADT2_REVISION_ID && - acpi_gbl_FADT.century) - century = CMOS_READ(acpi_gbl_FADT.century); -#endif - ctrl = CMOS_READ(RTC_CONTROL); - spin_unlock_irqrestore(&rtc_lock, flags); - - if (!(ctrl & RTC_DM_BINARY) || RTC_ALWAYS_BCD) - { - time->tm_sec = bcd2bin(time->tm_sec); - time->tm_min = bcd2bin(time->tm_min); - time->tm_hour = bcd2bin(time->tm_hour); - time->tm_mday = bcd2bin(time->tm_mday); - time->tm_mon = bcd2bin(time->tm_mon); - time->tm_year = bcd2bin(time->tm_year); - century = bcd2bin(century); - } - -#ifdef CONFIG_MACH_DECSTATION - time->tm_year += real_year - 72; -#endif - - if (century) - time->tm_year += (century - 19) * 100; - - /* - * Account for differences between how the RTC uses the values - * and how they are defined in a struct rtc_time; - */ - if (time->tm_year <= 69) - time->tm_year += 100; - - time->tm_mon--; - - return RTC_24H; -} - -/* Set the current date and time in the real time clock. */ -static inline int mc146818_set_time(struct rtc_time *time) -{ - unsigned long flags; - unsigned char mon, day, hrs, min, sec; - unsigned char save_control, save_freq_select; - unsigned int yrs; -#ifdef CONFIG_MACH_DECSTATION - unsigned int real_yrs, leap_yr; -#endif - unsigned char century = 0; - - yrs = time->tm_year; - mon = time->tm_mon + 1; /* tm_mon starts at zero */ - day = time->tm_mday; - hrs = time->tm_hour; - min = time->tm_min; - sec = time->tm_sec; - - if (yrs > 255) /* They are unsigned */ - return -EINVAL; - - spin_lock_irqsave(&rtc_lock, flags); -#ifdef CONFIG_MACH_DECSTATION - real_yrs = yrs; - leap_yr = ((!((yrs + 1900) % 4) && ((yrs + 1900) % 100)) || - !((yrs + 1900) % 400)); - yrs = 72; - - /* - * We want to keep the year set to 73 until March - * for non-leap years, so that Feb, 29th is handled - * correctly. - */ - if (!leap_yr && mon < 3) { - real_yrs--; - yrs = 73; - } -#endif - -#ifdef CONFIG_ACPI - if (acpi_gbl_FADT.header.revision >= FADT2_REVISION_ID && - acpi_gbl_FADT.century) { - century = (yrs + 1900) / 100; - yrs %= 100; - } -#endif - - /* These limits and adjustments are independent of - * whether the chip is in binary mode or not. - */ - if (yrs > 169) { - spin_unlock_irqrestore(&rtc_lock, flags); - return -EINVAL; - } - - if (yrs >= 100) - yrs -= 100; - - if (!(CMOS_READ(RTC_CONTROL) & RTC_DM_BINARY) - || RTC_ALWAYS_BCD) { - sec = bin2bcd(sec); - min = bin2bcd(min); - hrs = bin2bcd(hrs); - day = bin2bcd(day); - mon = bin2bcd(mon); - yrs = bin2bcd(yrs); - century = bin2bcd(century); - } - - save_control = CMOS_READ(RTC_CONTROL); - CMOS_WRITE((save_control|RTC_SET), RTC_CONTROL); - save_freq_select = CMOS_READ(RTC_FREQ_SELECT); - CMOS_WRITE((save_freq_select|RTC_DIV_RESET2), RTC_FREQ_SELECT); - -#ifdef CONFIG_MACH_DECSTATION - CMOS_WRITE(real_yrs, RTC_DEC_YEAR); -#endif - CMOS_WRITE(yrs, RTC_YEAR); - CMOS_WRITE(mon, RTC_MONTH); - CMOS_WRITE(day, RTC_DAY_OF_MONTH); - CMOS_WRITE(hrs, RTC_HOURS); - CMOS_WRITE(min, RTC_MINUTES); - CMOS_WRITE(sec, RTC_SECONDS); -#ifdef CONFIG_ACPI - if (acpi_gbl_FADT.header.revision >= FADT2_REVISION_ID && - acpi_gbl_FADT.century) - CMOS_WRITE(century, acpi_gbl_FADT.century); -#endif - - CMOS_WRITE(save_control, RTC_CONTROL); - CMOS_WRITE(save_freq_select, RTC_FREQ_SELECT); - - spin_unlock_irqrestore(&rtc_lock, flags); - - return 0; -} +unsigned int mc146818_get_time(struct rtc_time *time); +int mc146818_set_time(struct rtc_time *time); #endif /* _MC146818RTC_H */ -- cgit v1.2.3