.. | .. |
---|
| 1 | +// SPDX-License-Identifier: GPL-2.0-only |
---|
1 | 2 | #include <linux/bcd.h> |
---|
2 | 3 | #include <linux/delay.h> |
---|
3 | 4 | #include <linux/export.h> |
---|
.. | .. |
---|
8 | 9 | #endif |
---|
9 | 10 | |
---|
10 | 11 | /* |
---|
11 | | - * Returns true if a clock update is in progress |
---|
| 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. |
---|
12 | 16 | */ |
---|
13 | | -static inline unsigned char mc146818_is_updating(void) |
---|
| 17 | +bool mc146818_avoid_UIP(void (*callback)(unsigned char seconds, void *param), |
---|
| 18 | + void *param) |
---|
14 | 19 | { |
---|
15 | | - unsigned char uip; |
---|
| 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 | + int i; |
---|
| 88 | + unsigned char val; |
---|
16 | 89 | unsigned long flags; |
---|
17 | 90 | |
---|
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 | | -} |
---|
| 91 | + for (i = 0; i < 10; i++) { |
---|
| 92 | + spin_lock_irqsave(&rtc_lock, flags); |
---|
| 93 | + val = CMOS_READ(RTC_FREQ_SELECT); |
---|
| 94 | + spin_unlock_irqrestore(&rtc_lock, flags); |
---|
23 | 95 | |
---|
24 | | -unsigned int mc146818_get_time(struct rtc_time *time) |
---|
| 96 | + if ((val & RTC_UIP) == 0) |
---|
| 97 | + return true; |
---|
| 98 | + |
---|
| 99 | + mdelay(1); |
---|
| 100 | + } |
---|
| 101 | + |
---|
| 102 | + return false; |
---|
| 103 | +} |
---|
| 104 | +EXPORT_SYMBOL_GPL(mc146818_does_rtc_work); |
---|
| 105 | + |
---|
| 106 | +int mc146818_get_time(struct rtc_time *time) |
---|
25 | 107 | { |
---|
26 | 108 | unsigned char ctrl; |
---|
27 | 109 | unsigned long flags; |
---|
| 110 | + unsigned int iter_count = 0; |
---|
28 | 111 | unsigned char century = 0; |
---|
| 112 | + bool retry; |
---|
29 | 113 | |
---|
30 | 114 | #ifdef CONFIG_MACH_DECSTATION |
---|
31 | 115 | unsigned int real_year; |
---|
32 | 116 | #endif |
---|
33 | 117 | |
---|
| 118 | +again: |
---|
| 119 | + if (iter_count > 10) { |
---|
| 120 | + memset(time, 0, sizeof(*time)); |
---|
| 121 | + return -EIO; |
---|
| 122 | + } |
---|
| 123 | + iter_count++; |
---|
| 124 | + |
---|
| 125 | + spin_lock_irqsave(&rtc_lock, flags); |
---|
| 126 | + |
---|
34 | 127 | /* |
---|
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. |
---|
| 128 | + * Check whether there is an update in progress during which the |
---|
| 129 | + * readout is unspecified. The maximum update time is ~2ms. Poll |
---|
| 130 | + * every msec for completion. |
---|
| 131 | + * |
---|
| 132 | + * Store the second value before checking UIP so a long lasting NMI |
---|
| 133 | + * which happens to hit after the UIP check cannot make an update |
---|
| 134 | + * cycle invisible. |
---|
42 | 135 | */ |
---|
43 | | - if (mc146818_is_updating()) |
---|
44 | | - mdelay(20); |
---|
| 136 | + time->tm_sec = CMOS_READ(RTC_SECONDS); |
---|
| 137 | + |
---|
| 138 | + if (CMOS_READ(RTC_FREQ_SELECT) & RTC_UIP) { |
---|
| 139 | + spin_unlock_irqrestore(&rtc_lock, flags); |
---|
| 140 | + mdelay(1); |
---|
| 141 | + goto again; |
---|
| 142 | + } |
---|
| 143 | + |
---|
| 144 | + /* Revalidate the above readout */ |
---|
| 145 | + if (time->tm_sec != CMOS_READ(RTC_SECONDS)) { |
---|
| 146 | + spin_unlock_irqrestore(&rtc_lock, flags); |
---|
| 147 | + goto again; |
---|
| 148 | + } |
---|
45 | 149 | |
---|
46 | 150 | /* |
---|
47 | 151 | * Only the values that we read from the RTC are set. We leave |
---|
.. | .. |
---|
49 | 153 | * RTC has RTC_DAY_OF_WEEK, we ignore it, as it is only updated |
---|
50 | 154 | * by the RTC when initially set to a non-zero value. |
---|
51 | 155 | */ |
---|
52 | | - spin_lock_irqsave(&rtc_lock, flags); |
---|
53 | | - time->tm_sec = CMOS_READ(RTC_SECONDS); |
---|
54 | 156 | time->tm_min = CMOS_READ(RTC_MINUTES); |
---|
55 | 157 | time->tm_hour = CMOS_READ(RTC_HOURS); |
---|
56 | 158 | time->tm_mday = CMOS_READ(RTC_DAY_OF_MONTH); |
---|
.. | .. |
---|
65 | 167 | century = CMOS_READ(acpi_gbl_FADT.century); |
---|
66 | 168 | #endif |
---|
67 | 169 | ctrl = CMOS_READ(RTC_CONTROL); |
---|
| 170 | + /* |
---|
| 171 | + * Check for the UIP bit again. If it is set now then |
---|
| 172 | + * the above values may contain garbage. |
---|
| 173 | + */ |
---|
| 174 | + retry = CMOS_READ(RTC_FREQ_SELECT) & RTC_UIP; |
---|
| 175 | + /* |
---|
| 176 | + * A NMI might have interrupted the above sequence so check whether |
---|
| 177 | + * the seconds value has changed which indicates that the NMI took |
---|
| 178 | + * longer than the UIP bit was set. Unlikely, but possible and |
---|
| 179 | + * there is also virt... |
---|
| 180 | + */ |
---|
| 181 | + retry |= time->tm_sec != CMOS_READ(RTC_SECONDS); |
---|
| 182 | + |
---|
68 | 183 | spin_unlock_irqrestore(&rtc_lock, flags); |
---|
| 184 | + |
---|
| 185 | + if (retry) |
---|
| 186 | + goto again; |
---|
69 | 187 | |
---|
70 | 188 | if (!(ctrl & RTC_DM_BINARY) || RTC_ALWAYS_BCD) |
---|
71 | 189 | { |
---|
.. | .. |
---|
94 | 212 | |
---|
95 | 213 | time->tm_mon--; |
---|
96 | 214 | |
---|
97 | | - return RTC_24H; |
---|
| 215 | + return 0; |
---|
98 | 216 | } |
---|
99 | 217 | EXPORT_SYMBOL_GPL(mc146818_get_time); |
---|
| 218 | + |
---|
| 219 | +/* AMD systems don't allow access to AltCentury with DV1 */ |
---|
| 220 | +static bool apply_amd_register_a_behavior(void) |
---|
| 221 | +{ |
---|
| 222 | +#ifdef CONFIG_X86 |
---|
| 223 | + if (boot_cpu_data.x86_vendor == X86_VENDOR_AMD || |
---|
| 224 | + boot_cpu_data.x86_vendor == X86_VENDOR_HYGON) |
---|
| 225 | + return true; |
---|
| 226 | +#endif |
---|
| 227 | + return false; |
---|
| 228 | +} |
---|
100 | 229 | |
---|
101 | 230 | /* Set the current date and time in the real time clock. */ |
---|
102 | 231 | int mc146818_set_time(struct rtc_time *time) |
---|
.. | .. |
---|
120 | 249 | if (yrs > 255) /* They are unsigned */ |
---|
121 | 250 | return -EINVAL; |
---|
122 | 251 | |
---|
123 | | - spin_lock_irqsave(&rtc_lock, flags); |
---|
124 | 252 | #ifdef CONFIG_MACH_DECSTATION |
---|
125 | 253 | real_yrs = yrs; |
---|
126 | 254 | leap_yr = ((!((yrs + 1900) % 4) && ((yrs + 1900) % 100)) || |
---|
.. | .. |
---|
149 | 277 | /* These limits and adjustments are independent of |
---|
150 | 278 | * whether the chip is in binary mode or not. |
---|
151 | 279 | */ |
---|
152 | | - if (yrs > 169) { |
---|
153 | | - spin_unlock_irqrestore(&rtc_lock, flags); |
---|
| 280 | + if (yrs > 169) |
---|
154 | 281 | return -EINVAL; |
---|
155 | | - } |
---|
156 | 282 | |
---|
157 | 283 | if (yrs >= 100) |
---|
158 | 284 | yrs -= 100; |
---|
159 | 285 | |
---|
160 | | - if (!(CMOS_READ(RTC_CONTROL) & RTC_DM_BINARY) |
---|
161 | | - || RTC_ALWAYS_BCD) { |
---|
| 286 | + spin_lock_irqsave(&rtc_lock, flags); |
---|
| 287 | + save_control = CMOS_READ(RTC_CONTROL); |
---|
| 288 | + spin_unlock_irqrestore(&rtc_lock, flags); |
---|
| 289 | + if (!(save_control & RTC_DM_BINARY) || RTC_ALWAYS_BCD) { |
---|
162 | 290 | sec = bin2bcd(sec); |
---|
163 | 291 | min = bin2bcd(min); |
---|
164 | 292 | hrs = bin2bcd(hrs); |
---|
.. | .. |
---|
168 | 296 | century = bin2bcd(century); |
---|
169 | 297 | } |
---|
170 | 298 | |
---|
| 299 | + spin_lock_irqsave(&rtc_lock, flags); |
---|
171 | 300 | save_control = CMOS_READ(RTC_CONTROL); |
---|
172 | 301 | CMOS_WRITE((save_control|RTC_SET), RTC_CONTROL); |
---|
173 | 302 | save_freq_select = CMOS_READ(RTC_FREQ_SELECT); |
---|
174 | | - CMOS_WRITE((save_freq_select|RTC_DIV_RESET2), RTC_FREQ_SELECT); |
---|
| 303 | + if (apply_amd_register_a_behavior()) |
---|
| 304 | + CMOS_WRITE((save_freq_select & ~RTC_AMD_BANK_SELECT), RTC_FREQ_SELECT); |
---|
| 305 | + else |
---|
| 306 | + CMOS_WRITE((save_freq_select|RTC_DIV_RESET2), RTC_FREQ_SELECT); |
---|
175 | 307 | |
---|
176 | 308 | #ifdef CONFIG_MACH_DECSTATION |
---|
177 | 309 | CMOS_WRITE(real_yrs, RTC_DEC_YEAR); |
---|