GNU Linux-libre 5.19-rc6-gnu
[releases.git] / drivers / rtc / rtc-mc146818-lib.c
1 // SPDX-License-Identifier: GPL-2.0-only
2 #include <linux/bcd.h>
3 #include <linux/delay.h>
4 #include <linux/export.h>
5 #include <linux/mc146818rtc.h>
6
7 #ifdef CONFIG_ACPI
8 #include <linux/acpi.h>
9 #endif
10
11 /*
12  * Execute a function while the UIP (Update-in-progress) bit of the RTC is
13  * unset.
14  *
15  * Warning: callback may be executed more then once.
16  */
17 bool mc146818_avoid_UIP(void (*callback)(unsigned char seconds, void *param),
18                         void *param)
19 {
20         int i;
21         unsigned long flags;
22         unsigned char seconds;
23
24         for (i = 0; i < 10; i++) {
25                 spin_lock_irqsave(&rtc_lock, flags);
26
27                 /*
28                  * Check whether there is an update in progress during which the
29                  * readout is unspecified. The maximum update time is ~2ms. Poll
30                  * every msec for completion.
31                  *
32                  * Store the second value before checking UIP so a long lasting
33                  * NMI which happens to hit after the UIP check cannot make
34                  * an update cycle invisible.
35                  */
36                 seconds = CMOS_READ(RTC_SECONDS);
37
38                 if (CMOS_READ(RTC_FREQ_SELECT) & RTC_UIP) {
39                         spin_unlock_irqrestore(&rtc_lock, flags);
40                         mdelay(1);
41                         continue;
42                 }
43
44                 /* Revalidate the above readout */
45                 if (seconds != CMOS_READ(RTC_SECONDS)) {
46                         spin_unlock_irqrestore(&rtc_lock, flags);
47                         continue;
48                 }
49
50                 if (callback)
51                         callback(seconds, param);
52
53                 /*
54                  * Check for the UIP bit again. If it is set now then
55                  * the above values may contain garbage.
56                  */
57                 if (CMOS_READ(RTC_FREQ_SELECT) & RTC_UIP) {
58                         spin_unlock_irqrestore(&rtc_lock, flags);
59                         mdelay(1);
60                         continue;
61                 }
62
63                 /*
64                  * A NMI might have interrupted the above sequence so check
65                  * whether the seconds value has changed which indicates that
66                  * the NMI took longer than the UIP bit was set. Unlikely, but
67                  * possible and there is also virt...
68                  */
69                 if (seconds != CMOS_READ(RTC_SECONDS)) {
70                         spin_unlock_irqrestore(&rtc_lock, flags);
71                         continue;
72                 }
73                 spin_unlock_irqrestore(&rtc_lock, flags);
74
75                 return true;
76         }
77         return false;
78 }
79 EXPORT_SYMBOL_GPL(mc146818_avoid_UIP);
80
81 /*
82  * If the UIP (Update-in-progress) bit of the RTC is set for more then
83  * 10ms, the RTC is apparently broken or not present.
84  */
85 bool mc146818_does_rtc_work(void)
86 {
87         return mc146818_avoid_UIP(NULL, NULL);
88 }
89 EXPORT_SYMBOL_GPL(mc146818_does_rtc_work);
90
91 struct mc146818_get_time_callback_param {
92         struct rtc_time *time;
93         unsigned char ctrl;
94 #ifdef CONFIG_ACPI
95         unsigned char century;
96 #endif
97 #ifdef CONFIG_MACH_DECSTATION
98         unsigned int real_year;
99 #endif
100 };
101
102 static void mc146818_get_time_callback(unsigned char seconds, void *param_in)
103 {
104         struct mc146818_get_time_callback_param *p = param_in;
105
106         /*
107          * Only the values that we read from the RTC are set. We leave
108          * tm_wday, tm_yday and tm_isdst untouched. Even though the
109          * RTC has RTC_DAY_OF_WEEK, we ignore it, as it is only updated
110          * by the RTC when initially set to a non-zero value.
111          */
112         p->time->tm_sec = seconds;
113         p->time->tm_min = CMOS_READ(RTC_MINUTES);
114         p->time->tm_hour = CMOS_READ(RTC_HOURS);
115         p->time->tm_mday = CMOS_READ(RTC_DAY_OF_MONTH);
116         p->time->tm_mon = CMOS_READ(RTC_MONTH);
117         p->time->tm_year = CMOS_READ(RTC_YEAR);
118 #ifdef CONFIG_MACH_DECSTATION
119         p->real_year = CMOS_READ(RTC_DEC_YEAR);
120 #endif
121 #ifdef CONFIG_ACPI
122         if (acpi_gbl_FADT.header.revision >= FADT2_REVISION_ID &&
123             acpi_gbl_FADT.century) {
124                 p->century = CMOS_READ(acpi_gbl_FADT.century);
125         } else {
126                 p->century = 0;
127         }
128 #endif
129
130         p->ctrl = CMOS_READ(RTC_CONTROL);
131 }
132
133 int mc146818_get_time(struct rtc_time *time)
134 {
135         struct mc146818_get_time_callback_param p = {
136                 .time = time
137         };
138
139         if (!mc146818_avoid_UIP(mc146818_get_time_callback, &p)) {
140                 memset(time, 0, sizeof(*time));
141                 return -EIO;
142         }
143
144         if (!(p.ctrl & RTC_DM_BINARY) || RTC_ALWAYS_BCD)
145         {
146                 time->tm_sec = bcd2bin(time->tm_sec);
147                 time->tm_min = bcd2bin(time->tm_min);
148                 time->tm_hour = bcd2bin(time->tm_hour);
149                 time->tm_mday = bcd2bin(time->tm_mday);
150                 time->tm_mon = bcd2bin(time->tm_mon);
151                 time->tm_year = bcd2bin(time->tm_year);
152 #ifdef CONFIG_ACPI
153                 p.century = bcd2bin(p.century);
154 #endif
155         }
156
157 #ifdef CONFIG_MACH_DECSTATION
158         time->tm_year += p.real_year - 72;
159 #endif
160
161 #ifdef CONFIG_ACPI
162         if (p.century > 19)
163                 time->tm_year += (p.century - 19) * 100;
164 #endif
165
166         /*
167          * Account for differences between how the RTC uses the values
168          * and how they are defined in a struct rtc_time;
169          */
170         if (time->tm_year <= 69)
171                 time->tm_year += 100;
172
173         time->tm_mon--;
174
175         return 0;
176 }
177 EXPORT_SYMBOL_GPL(mc146818_get_time);
178
179 /* AMD systems don't allow access to AltCentury with DV1 */
180 static bool apply_amd_register_a_behavior(void)
181 {
182 #ifdef CONFIG_X86
183         if (boot_cpu_data.x86_vendor == X86_VENDOR_AMD ||
184             boot_cpu_data.x86_vendor == X86_VENDOR_HYGON)
185                 return true;
186 #endif
187         return false;
188 }
189
190 /* Set the current date and time in the real time clock. */
191 int mc146818_set_time(struct rtc_time *time)
192 {
193         unsigned long flags;
194         unsigned char mon, day, hrs, min, sec;
195         unsigned char save_control, save_freq_select;
196         unsigned int yrs;
197 #ifdef CONFIG_MACH_DECSTATION
198         unsigned int real_yrs, leap_yr;
199 #endif
200         unsigned char century = 0;
201
202         yrs = time->tm_year;
203         mon = time->tm_mon + 1;   /* tm_mon starts at zero */
204         day = time->tm_mday;
205         hrs = time->tm_hour;
206         min = time->tm_min;
207         sec = time->tm_sec;
208
209         if (yrs > 255)  /* They are unsigned */
210                 return -EINVAL;
211
212 #ifdef CONFIG_MACH_DECSTATION
213         real_yrs = yrs;
214         leap_yr = ((!((yrs + 1900) % 4) && ((yrs + 1900) % 100)) ||
215                         !((yrs + 1900) % 400));
216         yrs = 72;
217
218         /*
219          * We want to keep the year set to 73 until March
220          * for non-leap years, so that Feb, 29th is handled
221          * correctly.
222          */
223         if (!leap_yr && mon < 3) {
224                 real_yrs--;
225                 yrs = 73;
226         }
227 #endif
228
229 #ifdef CONFIG_ACPI
230         if (acpi_gbl_FADT.header.revision >= FADT2_REVISION_ID &&
231             acpi_gbl_FADT.century) {
232                 century = (yrs + 1900) / 100;
233                 yrs %= 100;
234         }
235 #endif
236
237         /* These limits and adjustments are independent of
238          * whether the chip is in binary mode or not.
239          */
240         if (yrs > 169)
241                 return -EINVAL;
242
243         if (yrs >= 100)
244                 yrs -= 100;
245
246         spin_lock_irqsave(&rtc_lock, flags);
247         save_control = CMOS_READ(RTC_CONTROL);
248         spin_unlock_irqrestore(&rtc_lock, flags);
249         if (!(save_control & RTC_DM_BINARY) || RTC_ALWAYS_BCD) {
250                 sec = bin2bcd(sec);
251                 min = bin2bcd(min);
252                 hrs = bin2bcd(hrs);
253                 day = bin2bcd(day);
254                 mon = bin2bcd(mon);
255                 yrs = bin2bcd(yrs);
256                 century = bin2bcd(century);
257         }
258
259         spin_lock_irqsave(&rtc_lock, flags);
260         save_control = CMOS_READ(RTC_CONTROL);
261         CMOS_WRITE((save_control|RTC_SET), RTC_CONTROL);
262         save_freq_select = CMOS_READ(RTC_FREQ_SELECT);
263         if (apply_amd_register_a_behavior())
264                 CMOS_WRITE((save_freq_select & ~RTC_AMD_BANK_SELECT), RTC_FREQ_SELECT);
265         else
266                 CMOS_WRITE((save_freq_select|RTC_DIV_RESET2), RTC_FREQ_SELECT);
267
268 #ifdef CONFIG_MACH_DECSTATION
269         CMOS_WRITE(real_yrs, RTC_DEC_YEAR);
270 #endif
271         CMOS_WRITE(yrs, RTC_YEAR);
272         CMOS_WRITE(mon, RTC_MONTH);
273         CMOS_WRITE(day, RTC_DAY_OF_MONTH);
274         CMOS_WRITE(hrs, RTC_HOURS);
275         CMOS_WRITE(min, RTC_MINUTES);
276         CMOS_WRITE(sec, RTC_SECONDS);
277 #ifdef CONFIG_ACPI
278         if (acpi_gbl_FADT.header.revision >= FADT2_REVISION_ID &&
279             acpi_gbl_FADT.century)
280                 CMOS_WRITE(century, acpi_gbl_FADT.century);
281 #endif
282
283         CMOS_WRITE(save_control, RTC_CONTROL);
284         CMOS_WRITE(save_freq_select, RTC_FREQ_SELECT);
285
286         spin_unlock_irqrestore(&rtc_lock, flags);
287
288         return 0;
289 }
290 EXPORT_SYMBOL_GPL(mc146818_set_time);