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 /* Set the current date and time in the real time clock. */
180 int mc146818_set_time(struct rtc_time *time)
181 {
182 	unsigned long flags;
183 	unsigned char mon, day, hrs, min, sec;
184 	unsigned char save_control, save_freq_select;
185 	unsigned int yrs;
186 #ifdef CONFIG_MACH_DECSTATION
187 	unsigned int real_yrs, leap_yr;
188 #endif
189 	unsigned char century = 0;
190 
191 	yrs = time->tm_year;
192 	mon = time->tm_mon + 1;   /* tm_mon starts at zero */
193 	day = time->tm_mday;
194 	hrs = time->tm_hour;
195 	min = time->tm_min;
196 	sec = time->tm_sec;
197 
198 	if (yrs > 255)	/* They are unsigned */
199 		return -EINVAL;
200 
201 #ifdef CONFIG_MACH_DECSTATION
202 	real_yrs = yrs;
203 	leap_yr = ((!((yrs + 1900) % 4) && ((yrs + 1900) % 100)) ||
204 			!((yrs + 1900) % 400));
205 	yrs = 72;
206 
207 	/*
208 	 * We want to keep the year set to 73 until March
209 	 * for non-leap years, so that Feb, 29th is handled
210 	 * correctly.
211 	 */
212 	if (!leap_yr && mon < 3) {
213 		real_yrs--;
214 		yrs = 73;
215 	}
216 #endif
217 
218 #ifdef CONFIG_ACPI
219 	if (acpi_gbl_FADT.header.revision >= FADT2_REVISION_ID &&
220 	    acpi_gbl_FADT.century) {
221 		century = (yrs + 1900) / 100;
222 		yrs %= 100;
223 	}
224 #endif
225 
226 	/* These limits and adjustments are independent of
227 	 * whether the chip is in binary mode or not.
228 	 */
229 	if (yrs > 169)
230 		return -EINVAL;
231 
232 	if (yrs >= 100)
233 		yrs -= 100;
234 
235 	if (!(CMOS_READ(RTC_CONTROL) & RTC_DM_BINARY)
236 	    || RTC_ALWAYS_BCD) {
237 		sec = bin2bcd(sec);
238 		min = bin2bcd(min);
239 		hrs = bin2bcd(hrs);
240 		day = bin2bcd(day);
241 		mon = bin2bcd(mon);
242 		yrs = bin2bcd(yrs);
243 		century = bin2bcd(century);
244 	}
245 
246 	spin_lock_irqsave(&rtc_lock, flags);
247 	save_control = CMOS_READ(RTC_CONTROL);
248 	CMOS_WRITE((save_control|RTC_SET), RTC_CONTROL);
249 	save_freq_select = CMOS_READ(RTC_FREQ_SELECT);
250 	CMOS_WRITE((save_freq_select|RTC_DIV_RESET2), RTC_FREQ_SELECT);
251 
252 #ifdef CONFIG_MACH_DECSTATION
253 	CMOS_WRITE(real_yrs, RTC_DEC_YEAR);
254 #endif
255 	CMOS_WRITE(yrs, RTC_YEAR);
256 	CMOS_WRITE(mon, RTC_MONTH);
257 	CMOS_WRITE(day, RTC_DAY_OF_MONTH);
258 	CMOS_WRITE(hrs, RTC_HOURS);
259 	CMOS_WRITE(min, RTC_MINUTES);
260 	CMOS_WRITE(sec, RTC_SECONDS);
261 #ifdef CONFIG_ACPI
262 	if (acpi_gbl_FADT.header.revision >= FADT2_REVISION_ID &&
263 	    acpi_gbl_FADT.century)
264 		CMOS_WRITE(century, acpi_gbl_FADT.century);
265 #endif
266 
267 	CMOS_WRITE(save_control, RTC_CONTROL);
268 	CMOS_WRITE(save_freq_select, RTC_FREQ_SELECT);
269 
270 	spin_unlock_irqrestore(&rtc_lock, flags);
271 
272 	return 0;
273 }
274 EXPORT_SYMBOL_GPL(mc146818_set_time);
275