18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only
28c2ecf20Sopenharmony_ci#include <linux/bcd.h>
38c2ecf20Sopenharmony_ci#include <linux/delay.h>
48c2ecf20Sopenharmony_ci#include <linux/export.h>
58c2ecf20Sopenharmony_ci#include <linux/mc146818rtc.h>
68c2ecf20Sopenharmony_ci
78c2ecf20Sopenharmony_ci#ifdef CONFIG_ACPI
88c2ecf20Sopenharmony_ci#include <linux/acpi.h>
98c2ecf20Sopenharmony_ci#endif
108c2ecf20Sopenharmony_ci
118c2ecf20Sopenharmony_ci/*
128c2ecf20Sopenharmony_ci * Execute a function while the UIP (Update-in-progress) bit of the RTC is
138c2ecf20Sopenharmony_ci * unset.
148c2ecf20Sopenharmony_ci *
158c2ecf20Sopenharmony_ci * Warning: callback may be executed more then once.
168c2ecf20Sopenharmony_ci */
178c2ecf20Sopenharmony_cibool mc146818_avoid_UIP(void (*callback)(unsigned char seconds, void *param),
188c2ecf20Sopenharmony_ci			void *param)
198c2ecf20Sopenharmony_ci{
208c2ecf20Sopenharmony_ci	int i;
218c2ecf20Sopenharmony_ci	unsigned long flags;
228c2ecf20Sopenharmony_ci	unsigned char seconds;
238c2ecf20Sopenharmony_ci
248c2ecf20Sopenharmony_ci	for (i = 0; i < 10; i++) {
258c2ecf20Sopenharmony_ci		spin_lock_irqsave(&rtc_lock, flags);
268c2ecf20Sopenharmony_ci
278c2ecf20Sopenharmony_ci		/*
288c2ecf20Sopenharmony_ci		 * Check whether there is an update in progress during which the
298c2ecf20Sopenharmony_ci		 * readout is unspecified. The maximum update time is ~2ms. Poll
308c2ecf20Sopenharmony_ci		 * every msec for completion.
318c2ecf20Sopenharmony_ci		 *
328c2ecf20Sopenharmony_ci		 * Store the second value before checking UIP so a long lasting
338c2ecf20Sopenharmony_ci		 * NMI which happens to hit after the UIP check cannot make
348c2ecf20Sopenharmony_ci		 * an update cycle invisible.
358c2ecf20Sopenharmony_ci		 */
368c2ecf20Sopenharmony_ci		seconds = CMOS_READ(RTC_SECONDS);
378c2ecf20Sopenharmony_ci
388c2ecf20Sopenharmony_ci		if (CMOS_READ(RTC_FREQ_SELECT) & RTC_UIP) {
398c2ecf20Sopenharmony_ci			spin_unlock_irqrestore(&rtc_lock, flags);
408c2ecf20Sopenharmony_ci			mdelay(1);
418c2ecf20Sopenharmony_ci			continue;
428c2ecf20Sopenharmony_ci		}
438c2ecf20Sopenharmony_ci
448c2ecf20Sopenharmony_ci		/* Revalidate the above readout */
458c2ecf20Sopenharmony_ci		if (seconds != CMOS_READ(RTC_SECONDS)) {
468c2ecf20Sopenharmony_ci			spin_unlock_irqrestore(&rtc_lock, flags);
478c2ecf20Sopenharmony_ci			continue;
488c2ecf20Sopenharmony_ci		}
498c2ecf20Sopenharmony_ci
508c2ecf20Sopenharmony_ci		if (callback)
518c2ecf20Sopenharmony_ci			callback(seconds, param);
528c2ecf20Sopenharmony_ci
538c2ecf20Sopenharmony_ci		/*
548c2ecf20Sopenharmony_ci		 * Check for the UIP bit again. If it is set now then
558c2ecf20Sopenharmony_ci		 * the above values may contain garbage.
568c2ecf20Sopenharmony_ci		 */
578c2ecf20Sopenharmony_ci		if (CMOS_READ(RTC_FREQ_SELECT) & RTC_UIP) {
588c2ecf20Sopenharmony_ci			spin_unlock_irqrestore(&rtc_lock, flags);
598c2ecf20Sopenharmony_ci			mdelay(1);
608c2ecf20Sopenharmony_ci			continue;
618c2ecf20Sopenharmony_ci		}
628c2ecf20Sopenharmony_ci
638c2ecf20Sopenharmony_ci		/*
648c2ecf20Sopenharmony_ci		 * A NMI might have interrupted the above sequence so check
658c2ecf20Sopenharmony_ci		 * whether the seconds value has changed which indicates that
668c2ecf20Sopenharmony_ci		 * the NMI took longer than the UIP bit was set. Unlikely, but
678c2ecf20Sopenharmony_ci		 * possible and there is also virt...
688c2ecf20Sopenharmony_ci		 */
698c2ecf20Sopenharmony_ci		if (seconds != CMOS_READ(RTC_SECONDS)) {
708c2ecf20Sopenharmony_ci			spin_unlock_irqrestore(&rtc_lock, flags);
718c2ecf20Sopenharmony_ci			continue;
728c2ecf20Sopenharmony_ci		}
738c2ecf20Sopenharmony_ci		spin_unlock_irqrestore(&rtc_lock, flags);
748c2ecf20Sopenharmony_ci
758c2ecf20Sopenharmony_ci		return true;
768c2ecf20Sopenharmony_ci	}
778c2ecf20Sopenharmony_ci	return false;
788c2ecf20Sopenharmony_ci}
798c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(mc146818_avoid_UIP);
808c2ecf20Sopenharmony_ci
818c2ecf20Sopenharmony_ci/*
828c2ecf20Sopenharmony_ci * If the UIP (Update-in-progress) bit of the RTC is set for more then
838c2ecf20Sopenharmony_ci * 10ms, the RTC is apparently broken or not present.
848c2ecf20Sopenharmony_ci */
858c2ecf20Sopenharmony_cibool mc146818_does_rtc_work(void)
868c2ecf20Sopenharmony_ci{
878c2ecf20Sopenharmony_ci	int i;
888c2ecf20Sopenharmony_ci	unsigned char val;
898c2ecf20Sopenharmony_ci	unsigned long flags;
908c2ecf20Sopenharmony_ci
918c2ecf20Sopenharmony_ci	for (i = 0; i < 10; i++) {
928c2ecf20Sopenharmony_ci		spin_lock_irqsave(&rtc_lock, flags);
938c2ecf20Sopenharmony_ci		val = CMOS_READ(RTC_FREQ_SELECT);
948c2ecf20Sopenharmony_ci		spin_unlock_irqrestore(&rtc_lock, flags);
958c2ecf20Sopenharmony_ci
968c2ecf20Sopenharmony_ci		if ((val & RTC_UIP) == 0)
978c2ecf20Sopenharmony_ci			return true;
988c2ecf20Sopenharmony_ci
998c2ecf20Sopenharmony_ci		mdelay(1);
1008c2ecf20Sopenharmony_ci	}
1018c2ecf20Sopenharmony_ci
1028c2ecf20Sopenharmony_ci	return false;
1038c2ecf20Sopenharmony_ci}
1048c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(mc146818_does_rtc_work);
1058c2ecf20Sopenharmony_ci
1068c2ecf20Sopenharmony_ciint mc146818_get_time(struct rtc_time *time)
1078c2ecf20Sopenharmony_ci{
1088c2ecf20Sopenharmony_ci	unsigned char ctrl;
1098c2ecf20Sopenharmony_ci	unsigned long flags;
1108c2ecf20Sopenharmony_ci	unsigned int iter_count = 0;
1118c2ecf20Sopenharmony_ci	unsigned char century = 0;
1128c2ecf20Sopenharmony_ci	bool retry;
1138c2ecf20Sopenharmony_ci
1148c2ecf20Sopenharmony_ci#ifdef CONFIG_MACH_DECSTATION
1158c2ecf20Sopenharmony_ci	unsigned int real_year;
1168c2ecf20Sopenharmony_ci#endif
1178c2ecf20Sopenharmony_ci
1188c2ecf20Sopenharmony_ciagain:
1198c2ecf20Sopenharmony_ci	if (iter_count > 10) {
1208c2ecf20Sopenharmony_ci		memset(time, 0, sizeof(*time));
1218c2ecf20Sopenharmony_ci		return -EIO;
1228c2ecf20Sopenharmony_ci	}
1238c2ecf20Sopenharmony_ci	iter_count++;
1248c2ecf20Sopenharmony_ci
1258c2ecf20Sopenharmony_ci	spin_lock_irqsave(&rtc_lock, flags);
1268c2ecf20Sopenharmony_ci
1278c2ecf20Sopenharmony_ci	/*
1288c2ecf20Sopenharmony_ci	 * Check whether there is an update in progress during which the
1298c2ecf20Sopenharmony_ci	 * readout is unspecified. The maximum update time is ~2ms. Poll
1308c2ecf20Sopenharmony_ci	 * every msec for completion.
1318c2ecf20Sopenharmony_ci	 *
1328c2ecf20Sopenharmony_ci	 * Store the second value before checking UIP so a long lasting NMI
1338c2ecf20Sopenharmony_ci	 * which happens to hit after the UIP check cannot make an update
1348c2ecf20Sopenharmony_ci	 * cycle invisible.
1358c2ecf20Sopenharmony_ci	 */
1368c2ecf20Sopenharmony_ci	time->tm_sec = CMOS_READ(RTC_SECONDS);
1378c2ecf20Sopenharmony_ci
1388c2ecf20Sopenharmony_ci	if (CMOS_READ(RTC_FREQ_SELECT) & RTC_UIP) {
1398c2ecf20Sopenharmony_ci		spin_unlock_irqrestore(&rtc_lock, flags);
1408c2ecf20Sopenharmony_ci		mdelay(1);
1418c2ecf20Sopenharmony_ci		goto again;
1428c2ecf20Sopenharmony_ci	}
1438c2ecf20Sopenharmony_ci
1448c2ecf20Sopenharmony_ci	/* Revalidate the above readout */
1458c2ecf20Sopenharmony_ci	if (time->tm_sec != CMOS_READ(RTC_SECONDS)) {
1468c2ecf20Sopenharmony_ci		spin_unlock_irqrestore(&rtc_lock, flags);
1478c2ecf20Sopenharmony_ci		goto again;
1488c2ecf20Sopenharmony_ci	}
1498c2ecf20Sopenharmony_ci
1508c2ecf20Sopenharmony_ci	/*
1518c2ecf20Sopenharmony_ci	 * Only the values that we read from the RTC are set. We leave
1528c2ecf20Sopenharmony_ci	 * tm_wday, tm_yday and tm_isdst untouched. Even though the
1538c2ecf20Sopenharmony_ci	 * RTC has RTC_DAY_OF_WEEK, we ignore it, as it is only updated
1548c2ecf20Sopenharmony_ci	 * by the RTC when initially set to a non-zero value.
1558c2ecf20Sopenharmony_ci	 */
1568c2ecf20Sopenharmony_ci	time->tm_min = CMOS_READ(RTC_MINUTES);
1578c2ecf20Sopenharmony_ci	time->tm_hour = CMOS_READ(RTC_HOURS);
1588c2ecf20Sopenharmony_ci	time->tm_mday = CMOS_READ(RTC_DAY_OF_MONTH);
1598c2ecf20Sopenharmony_ci	time->tm_mon = CMOS_READ(RTC_MONTH);
1608c2ecf20Sopenharmony_ci	time->tm_year = CMOS_READ(RTC_YEAR);
1618c2ecf20Sopenharmony_ci#ifdef CONFIG_MACH_DECSTATION
1628c2ecf20Sopenharmony_ci	real_year = CMOS_READ(RTC_DEC_YEAR);
1638c2ecf20Sopenharmony_ci#endif
1648c2ecf20Sopenharmony_ci#ifdef CONFIG_ACPI
1658c2ecf20Sopenharmony_ci	if (acpi_gbl_FADT.header.revision >= FADT2_REVISION_ID &&
1668c2ecf20Sopenharmony_ci	    acpi_gbl_FADT.century)
1678c2ecf20Sopenharmony_ci		century = CMOS_READ(acpi_gbl_FADT.century);
1688c2ecf20Sopenharmony_ci#endif
1698c2ecf20Sopenharmony_ci	ctrl = CMOS_READ(RTC_CONTROL);
1708c2ecf20Sopenharmony_ci	/*
1718c2ecf20Sopenharmony_ci	 * Check for the UIP bit again. If it is set now then
1728c2ecf20Sopenharmony_ci	 * the above values may contain garbage.
1738c2ecf20Sopenharmony_ci	 */
1748c2ecf20Sopenharmony_ci	retry = CMOS_READ(RTC_FREQ_SELECT) & RTC_UIP;
1758c2ecf20Sopenharmony_ci	/*
1768c2ecf20Sopenharmony_ci	 * A NMI might have interrupted the above sequence so check whether
1778c2ecf20Sopenharmony_ci	 * the seconds value has changed which indicates that the NMI took
1788c2ecf20Sopenharmony_ci	 * longer than the UIP bit was set. Unlikely, but possible and
1798c2ecf20Sopenharmony_ci	 * there is also virt...
1808c2ecf20Sopenharmony_ci	 */
1818c2ecf20Sopenharmony_ci	retry |= time->tm_sec != CMOS_READ(RTC_SECONDS);
1828c2ecf20Sopenharmony_ci
1838c2ecf20Sopenharmony_ci	spin_unlock_irqrestore(&rtc_lock, flags);
1848c2ecf20Sopenharmony_ci
1858c2ecf20Sopenharmony_ci	if (retry)
1868c2ecf20Sopenharmony_ci		goto again;
1878c2ecf20Sopenharmony_ci
1888c2ecf20Sopenharmony_ci	if (!(ctrl & RTC_DM_BINARY) || RTC_ALWAYS_BCD)
1898c2ecf20Sopenharmony_ci	{
1908c2ecf20Sopenharmony_ci		time->tm_sec = bcd2bin(time->tm_sec);
1918c2ecf20Sopenharmony_ci		time->tm_min = bcd2bin(time->tm_min);
1928c2ecf20Sopenharmony_ci		time->tm_hour = bcd2bin(time->tm_hour);
1938c2ecf20Sopenharmony_ci		time->tm_mday = bcd2bin(time->tm_mday);
1948c2ecf20Sopenharmony_ci		time->tm_mon = bcd2bin(time->tm_mon);
1958c2ecf20Sopenharmony_ci		time->tm_year = bcd2bin(time->tm_year);
1968c2ecf20Sopenharmony_ci		century = bcd2bin(century);
1978c2ecf20Sopenharmony_ci	}
1988c2ecf20Sopenharmony_ci
1998c2ecf20Sopenharmony_ci#ifdef CONFIG_MACH_DECSTATION
2008c2ecf20Sopenharmony_ci	time->tm_year += real_year - 72;
2018c2ecf20Sopenharmony_ci#endif
2028c2ecf20Sopenharmony_ci
2038c2ecf20Sopenharmony_ci	if (century > 19)
2048c2ecf20Sopenharmony_ci		time->tm_year += (century - 19) * 100;
2058c2ecf20Sopenharmony_ci
2068c2ecf20Sopenharmony_ci	/*
2078c2ecf20Sopenharmony_ci	 * Account for differences between how the RTC uses the values
2088c2ecf20Sopenharmony_ci	 * and how they are defined in a struct rtc_time;
2098c2ecf20Sopenharmony_ci	 */
2108c2ecf20Sopenharmony_ci	if (time->tm_year <= 69)
2118c2ecf20Sopenharmony_ci		time->tm_year += 100;
2128c2ecf20Sopenharmony_ci
2138c2ecf20Sopenharmony_ci	time->tm_mon--;
2148c2ecf20Sopenharmony_ci
2158c2ecf20Sopenharmony_ci	return 0;
2168c2ecf20Sopenharmony_ci}
2178c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(mc146818_get_time);
2188c2ecf20Sopenharmony_ci
2198c2ecf20Sopenharmony_ci/* AMD systems don't allow access to AltCentury with DV1 */
2208c2ecf20Sopenharmony_cistatic bool apply_amd_register_a_behavior(void)
2218c2ecf20Sopenharmony_ci{
2228c2ecf20Sopenharmony_ci#ifdef CONFIG_X86
2238c2ecf20Sopenharmony_ci	if (boot_cpu_data.x86_vendor == X86_VENDOR_AMD ||
2248c2ecf20Sopenharmony_ci	    boot_cpu_data.x86_vendor == X86_VENDOR_HYGON)
2258c2ecf20Sopenharmony_ci		return true;
2268c2ecf20Sopenharmony_ci#endif
2278c2ecf20Sopenharmony_ci	return false;
2288c2ecf20Sopenharmony_ci}
2298c2ecf20Sopenharmony_ci
2308c2ecf20Sopenharmony_ci/* Set the current date and time in the real time clock. */
2318c2ecf20Sopenharmony_ciint mc146818_set_time(struct rtc_time *time)
2328c2ecf20Sopenharmony_ci{
2338c2ecf20Sopenharmony_ci	unsigned long flags;
2348c2ecf20Sopenharmony_ci	unsigned char mon, day, hrs, min, sec;
2358c2ecf20Sopenharmony_ci	unsigned char save_control, save_freq_select;
2368c2ecf20Sopenharmony_ci	unsigned int yrs;
2378c2ecf20Sopenharmony_ci#ifdef CONFIG_MACH_DECSTATION
2388c2ecf20Sopenharmony_ci	unsigned int real_yrs, leap_yr;
2398c2ecf20Sopenharmony_ci#endif
2408c2ecf20Sopenharmony_ci	unsigned char century = 0;
2418c2ecf20Sopenharmony_ci
2428c2ecf20Sopenharmony_ci	yrs = time->tm_year;
2438c2ecf20Sopenharmony_ci	mon = time->tm_mon + 1;   /* tm_mon starts at zero */
2448c2ecf20Sopenharmony_ci	day = time->tm_mday;
2458c2ecf20Sopenharmony_ci	hrs = time->tm_hour;
2468c2ecf20Sopenharmony_ci	min = time->tm_min;
2478c2ecf20Sopenharmony_ci	sec = time->tm_sec;
2488c2ecf20Sopenharmony_ci
2498c2ecf20Sopenharmony_ci	if (yrs > 255)	/* They are unsigned */
2508c2ecf20Sopenharmony_ci		return -EINVAL;
2518c2ecf20Sopenharmony_ci
2528c2ecf20Sopenharmony_ci#ifdef CONFIG_MACH_DECSTATION
2538c2ecf20Sopenharmony_ci	real_yrs = yrs;
2548c2ecf20Sopenharmony_ci	leap_yr = ((!((yrs + 1900) % 4) && ((yrs + 1900) % 100)) ||
2558c2ecf20Sopenharmony_ci			!((yrs + 1900) % 400));
2568c2ecf20Sopenharmony_ci	yrs = 72;
2578c2ecf20Sopenharmony_ci
2588c2ecf20Sopenharmony_ci	/*
2598c2ecf20Sopenharmony_ci	 * We want to keep the year set to 73 until March
2608c2ecf20Sopenharmony_ci	 * for non-leap years, so that Feb, 29th is handled
2618c2ecf20Sopenharmony_ci	 * correctly.
2628c2ecf20Sopenharmony_ci	 */
2638c2ecf20Sopenharmony_ci	if (!leap_yr && mon < 3) {
2648c2ecf20Sopenharmony_ci		real_yrs--;
2658c2ecf20Sopenharmony_ci		yrs = 73;
2668c2ecf20Sopenharmony_ci	}
2678c2ecf20Sopenharmony_ci#endif
2688c2ecf20Sopenharmony_ci
2698c2ecf20Sopenharmony_ci#ifdef CONFIG_ACPI
2708c2ecf20Sopenharmony_ci	if (acpi_gbl_FADT.header.revision >= FADT2_REVISION_ID &&
2718c2ecf20Sopenharmony_ci	    acpi_gbl_FADT.century) {
2728c2ecf20Sopenharmony_ci		century = (yrs + 1900) / 100;
2738c2ecf20Sopenharmony_ci		yrs %= 100;
2748c2ecf20Sopenharmony_ci	}
2758c2ecf20Sopenharmony_ci#endif
2768c2ecf20Sopenharmony_ci
2778c2ecf20Sopenharmony_ci	/* These limits and adjustments are independent of
2788c2ecf20Sopenharmony_ci	 * whether the chip is in binary mode or not.
2798c2ecf20Sopenharmony_ci	 */
2808c2ecf20Sopenharmony_ci	if (yrs > 169)
2818c2ecf20Sopenharmony_ci		return -EINVAL;
2828c2ecf20Sopenharmony_ci
2838c2ecf20Sopenharmony_ci	if (yrs >= 100)
2848c2ecf20Sopenharmony_ci		yrs -= 100;
2858c2ecf20Sopenharmony_ci
2868c2ecf20Sopenharmony_ci	spin_lock_irqsave(&rtc_lock, flags);
2878c2ecf20Sopenharmony_ci	save_control = CMOS_READ(RTC_CONTROL);
2888c2ecf20Sopenharmony_ci	spin_unlock_irqrestore(&rtc_lock, flags);
2898c2ecf20Sopenharmony_ci	if (!(save_control & RTC_DM_BINARY) || RTC_ALWAYS_BCD) {
2908c2ecf20Sopenharmony_ci		sec = bin2bcd(sec);
2918c2ecf20Sopenharmony_ci		min = bin2bcd(min);
2928c2ecf20Sopenharmony_ci		hrs = bin2bcd(hrs);
2938c2ecf20Sopenharmony_ci		day = bin2bcd(day);
2948c2ecf20Sopenharmony_ci		mon = bin2bcd(mon);
2958c2ecf20Sopenharmony_ci		yrs = bin2bcd(yrs);
2968c2ecf20Sopenharmony_ci		century = bin2bcd(century);
2978c2ecf20Sopenharmony_ci	}
2988c2ecf20Sopenharmony_ci
2998c2ecf20Sopenharmony_ci	spin_lock_irqsave(&rtc_lock, flags);
3008c2ecf20Sopenharmony_ci	save_control = CMOS_READ(RTC_CONTROL);
3018c2ecf20Sopenharmony_ci	CMOS_WRITE((save_control|RTC_SET), RTC_CONTROL);
3028c2ecf20Sopenharmony_ci	save_freq_select = CMOS_READ(RTC_FREQ_SELECT);
3038c2ecf20Sopenharmony_ci	if (apply_amd_register_a_behavior())
3048c2ecf20Sopenharmony_ci		CMOS_WRITE((save_freq_select & ~RTC_AMD_BANK_SELECT), RTC_FREQ_SELECT);
3058c2ecf20Sopenharmony_ci	else
3068c2ecf20Sopenharmony_ci		CMOS_WRITE((save_freq_select|RTC_DIV_RESET2), RTC_FREQ_SELECT);
3078c2ecf20Sopenharmony_ci
3088c2ecf20Sopenharmony_ci#ifdef CONFIG_MACH_DECSTATION
3098c2ecf20Sopenharmony_ci	CMOS_WRITE(real_yrs, RTC_DEC_YEAR);
3108c2ecf20Sopenharmony_ci#endif
3118c2ecf20Sopenharmony_ci	CMOS_WRITE(yrs, RTC_YEAR);
3128c2ecf20Sopenharmony_ci	CMOS_WRITE(mon, RTC_MONTH);
3138c2ecf20Sopenharmony_ci	CMOS_WRITE(day, RTC_DAY_OF_MONTH);
3148c2ecf20Sopenharmony_ci	CMOS_WRITE(hrs, RTC_HOURS);
3158c2ecf20Sopenharmony_ci	CMOS_WRITE(min, RTC_MINUTES);
3168c2ecf20Sopenharmony_ci	CMOS_WRITE(sec, RTC_SECONDS);
3178c2ecf20Sopenharmony_ci#ifdef CONFIG_ACPI
3188c2ecf20Sopenharmony_ci	if (acpi_gbl_FADT.header.revision >= FADT2_REVISION_ID &&
3198c2ecf20Sopenharmony_ci	    acpi_gbl_FADT.century)
3208c2ecf20Sopenharmony_ci		CMOS_WRITE(century, acpi_gbl_FADT.century);
3218c2ecf20Sopenharmony_ci#endif
3228c2ecf20Sopenharmony_ci
3238c2ecf20Sopenharmony_ci	CMOS_WRITE(save_control, RTC_CONTROL);
3248c2ecf20Sopenharmony_ci	CMOS_WRITE(save_freq_select, RTC_FREQ_SELECT);
3258c2ecf20Sopenharmony_ci
3268c2ecf20Sopenharmony_ci	spin_unlock_irqrestore(&rtc_lock, flags);
3278c2ecf20Sopenharmony_ci
3288c2ecf20Sopenharmony_ci	return 0;
3298c2ecf20Sopenharmony_ci}
3308c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(mc146818_set_time);
331