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