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