aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/rtc
diff options
context:
space:
mode:
authorArnd Bergmann <arnd@arndb.de>2016-06-01 10:46:23 -0400
committerAlexandre Belloni <alexandre.belloni@free-electrons.com>2016-06-25 19:20:08 -0400
commitd6faca40f40b62aca8ea8c29289c7bf7456172bb (patch)
treefd7194661cd730e7adc304e5921ebc157d5d611d /drivers/rtc
parent5ee98ab3a8ea94fe24e288dc02c6b489889cf06a (diff)
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 <arnd@arndb.de> Signed-off-by: Alexandre Belloni <alexandre.belloni@free-electrons.com>
Diffstat (limited to 'drivers/rtc')
-rw-r--r--drivers/rtc/Kconfig6
-rw-r--r--drivers/rtc/Makefile1
-rw-r--r--drivers/rtc/rtc-mc146818-lib.c198
3 files changed, 205 insertions, 0 deletions
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 @@
5config RTC_LIB 5config RTC_LIB
6 bool 6 bool
7 7
8config RTC_MC146818_LIB
9 bool
10 select RTC_LIB
11
8menuconfig RTC_CLASS 12menuconfig RTC_CLASS
9 bool "Real Time Clock" 13 bool "Real Time Clock"
10 default n 14 default n
@@ -809,6 +813,7 @@ config RTC_DRV_CMOS
809 tristate "PC-style 'CMOS'" 813 tristate "PC-style 'CMOS'"
810 depends on X86 || ARM || M32R || PPC || MIPS || SPARC64 || MN10300 814 depends on X86 || ARM || M32R || PPC || MIPS || SPARC64 || MN10300
811 default y if X86 815 default y if X86
816 select RTC_MC146818_LIB
812 help 817 help
813 Say "yes" here to get direct support for the real time clock 818 Say "yes" here to get direct support for the real time clock
814 found in every PC or ACPI-based system, and some other boards. 819 found in every PC or ACPI-based system, and some other boards.
@@ -827,6 +832,7 @@ config RTC_DRV_CMOS
827config RTC_DRV_ALPHA 832config RTC_DRV_ALPHA
828 bool "Alpha PC-style CMOS" 833 bool "Alpha PC-style CMOS"
829 depends on ALPHA 834 depends on ALPHA
835 select RTC_MC146818_LIB
830 default y 836 default y
831 help 837 help
832 Direct support for the real-time clock found on every Alpha 838 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
8obj-$(CONFIG_RTC_HCTOSYS) += hctosys.o 8obj-$(CONFIG_RTC_HCTOSYS) += hctosys.o
9obj-$(CONFIG_RTC_SYSTOHC) += systohc.o 9obj-$(CONFIG_RTC_SYSTOHC) += systohc.o
10obj-$(CONFIG_RTC_CLASS) += rtc-core.o 10obj-$(CONFIG_RTC_CLASS) += rtc-core.o
11obj-$(CONFIG_RTC_MC146818_LIB) += rtc-mc146818-lib.o
11rtc-core-y := class.o interface.o 12rtc-core-y := class.o interface.o
12 13
13ifdef CONFIG_RTC_DRV_EFI 14ifdef 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 @@
1#include <linux/bcd.h>
2#include <linux/delay.h>
3#include <linux/export.h>
4#include <linux/mc146818rtc.h>
5
6#ifdef CONFIG_ACPI
7#include <linux/acpi.h>
8#endif
9
10/*
11 * Returns true if a clock update is in progress
12 */
13static inline unsigned char mc146818_is_updating(void)
14{
15 unsigned char uip;
16 unsigned long flags;
17
18 spin_lock_irqsave(&rtc_lock, flags);
19 uip = (CMOS_READ(RTC_FREQ_SELECT) & RTC_UIP);
20 spin_unlock_irqrestore(&rtc_lock, flags);
21 return uip;
22}
23
24unsigned int mc146818_get_time(struct rtc_time *time)
25{
26 unsigned char ctrl;
27 unsigned long flags;
28 unsigned char century = 0;
29
30#ifdef CONFIG_MACH_DECSTATION
31 unsigned int real_year;
32#endif
33
34 /*
35 * read RTC once any update in progress is done. The update
36 * can take just over 2ms. We wait 20ms. There is no need to
37 * to poll-wait (up to 1s - eeccch) for the falling edge of RTC_UIP.
38 * If you need to know *exactly* when a second has started, enable
39 * periodic update complete interrupts, (via ioctl) and then
40 * immediately read /dev/rtc which will block until you get the IRQ.
41 * Once the read clears, read the RTC time (again via ioctl). Easy.
42 */
43 if (mc146818_is_updating())
44 mdelay(20);
45
46 /*
47 * Only the values that we read from the RTC are set. We leave
48 * tm_wday, tm_yday and tm_isdst untouched. Even though the
49 * RTC has RTC_DAY_OF_WEEK, we ignore it, as it is only updated
50 * by the RTC when initially set to a non-zero value.
51 */
52 spin_lock_irqsave(&rtc_lock, flags);
53 time->tm_sec = CMOS_READ(RTC_SECONDS);
54 time->tm_min = CMOS_READ(RTC_MINUTES);
55 time->tm_hour = CMOS_READ(RTC_HOURS);
56 time->tm_mday = CMOS_READ(RTC_DAY_OF_MONTH);
57 time->tm_mon = CMOS_READ(RTC_MONTH);
58 time->tm_year = CMOS_READ(RTC_YEAR);
59#ifdef CONFIG_MACH_DECSTATION
60 real_year = CMOS_READ(RTC_DEC_YEAR);
61#endif
62#ifdef CONFIG_ACPI
63 if (acpi_gbl_FADT.header.revision >= FADT2_REVISION_ID &&
64 acpi_gbl_FADT.century)
65 century = CMOS_READ(acpi_gbl_FADT.century);
66#endif
67 ctrl = CMOS_READ(RTC_CONTROL);
68 spin_unlock_irqrestore(&rtc_lock, flags);
69
70 if (!(ctrl & RTC_DM_BINARY) || RTC_ALWAYS_BCD)
71 {
72 time->tm_sec = bcd2bin(time->tm_sec);
73 time->tm_min = bcd2bin(time->tm_min);
74 time->tm_hour = bcd2bin(time->tm_hour);
75 time->tm_mday = bcd2bin(time->tm_mday);
76 time->tm_mon = bcd2bin(time->tm_mon);
77 time->tm_year = bcd2bin(time->tm_year);
78 century = bcd2bin(century);
79 }
80
81#ifdef CONFIG_MACH_DECSTATION
82 time->tm_year += real_year - 72;
83#endif
84
85 if (century)
86 time->tm_year += (century - 19) * 100;
87
88 /*
89 * Account for differences between how the RTC uses the values
90 * and how they are defined in a struct rtc_time;
91 */
92 if (time->tm_year <= 69)
93 time->tm_year += 100;
94
95 time->tm_mon--;
96
97 return RTC_24H;
98}
99EXPORT_SYMBOL_GPL(mc146818_get_time);
100
101/* Set the current date and time in the real time clock. */
102int mc146818_set_time(struct rtc_time *time)
103{
104 unsigned long flags;
105 unsigned char mon, day, hrs, min, sec;
106 unsigned char save_control, save_freq_select;
107 unsigned int yrs;
108#ifdef CONFIG_MACH_DECSTATION
109 unsigned int real_yrs, leap_yr;
110#endif
111 unsigned char century = 0;
112
113 yrs = time->tm_year;
114 mon = time->tm_mon + 1; /* tm_mon starts at zero */
115 day = time->tm_mday;
116 hrs = time->tm_hour;
117 min = time->tm_min;
118 sec = time->tm_sec;
119
120 if (yrs > 255) /* They are unsigned */
121 return -EINVAL;
122
123 spin_lock_irqsave(&rtc_lock, flags);
124#ifdef CONFIG_MACH_DECSTATION
125 real_yrs = yrs;
126 leap_yr = ((!((yrs + 1900) % 4) && ((yrs + 1900) % 100)) ||
127 !((yrs + 1900) % 400));
128 yrs = 72;
129
130 /*
131 * We want to keep the year set to 73 until March
132 * for non-leap years, so that Feb, 29th is handled
133 * correctly.
134 */
135 if (!leap_yr && mon < 3) {
136 real_yrs--;
137 yrs = 73;
138 }
139#endif
140
141#ifdef CONFIG_ACPI
142 if (acpi_gbl_FADT.header.revision >= FADT2_REVISION_ID &&
143 acpi_gbl_FADT.century) {
144 century = (yrs + 1900) / 100;
145 yrs %= 100;
146 }
147#endif
148
149 /* These limits and adjustments are independent of
150 * whether the chip is in binary mode or not.
151 */
152 if (yrs > 169) {
153 spin_unlock_irqrestore(&rtc_lock, flags);
154 return -EINVAL;
155 }
156
157 if (yrs >= 100)
158 yrs -= 100;
159
160 if (!(CMOS_READ(RTC_CONTROL) & RTC_DM_BINARY)
161 || RTC_ALWAYS_BCD) {
162 sec = bin2bcd(sec);
163 min = bin2bcd(min);
164 hrs = bin2bcd(hrs);
165 day = bin2bcd(day);
166 mon = bin2bcd(mon);
167 yrs = bin2bcd(yrs);
168 century = bin2bcd(century);
169 }
170
171 save_control = CMOS_READ(RTC_CONTROL);
172 CMOS_WRITE((save_control|RTC_SET), RTC_CONTROL);
173 save_freq_select = CMOS_READ(RTC_FREQ_SELECT);
174 CMOS_WRITE((save_freq_select|RTC_DIV_RESET2), RTC_FREQ_SELECT);
175
176#ifdef CONFIG_MACH_DECSTATION
177 CMOS_WRITE(real_yrs, RTC_DEC_YEAR);
178#endif
179 CMOS_WRITE(yrs, RTC_YEAR);
180 CMOS_WRITE(mon, RTC_MONTH);
181 CMOS_WRITE(day, RTC_DAY_OF_MONTH);
182 CMOS_WRITE(hrs, RTC_HOURS);
183 CMOS_WRITE(min, RTC_MINUTES);
184 CMOS_WRITE(sec, RTC_SECONDS);
185#ifdef CONFIG_ACPI
186 if (acpi_gbl_FADT.header.revision >= FADT2_REVISION_ID &&
187 acpi_gbl_FADT.century)
188 CMOS_WRITE(century, acpi_gbl_FADT.century);
189#endif
190
191 CMOS_WRITE(save_control, RTC_CONTROL);
192 CMOS_WRITE(save_freq_select, RTC_FREQ_SELECT);
193
194 spin_unlock_irqrestore(&rtc_lock, flags);
195
196 return 0;
197}
198EXPORT_SYMBOL_GPL(mc146818_set_time);