xref: /openbmc/u-boot/drivers/rtc/mcfrtc.c (revision 406fd7e207d3593f150079514a371dccdc651ce7)
1*83d290c5STom Rini // SPDX-License-Identifier: GPL-2.0+
20c698dcaSJean-Christophe PLAGNIOL-VILLARD /*
30c698dcaSJean-Christophe PLAGNIOL-VILLARD  * Copyright (C) 2004-2007 Freescale Semiconductor, Inc.
40c698dcaSJean-Christophe PLAGNIOL-VILLARD  * TsiChung Liew (Tsi-Chung.Liew@freescale.com)
50c698dcaSJean-Christophe PLAGNIOL-VILLARD  */
60c698dcaSJean-Christophe PLAGNIOL-VILLARD 
70c698dcaSJean-Christophe PLAGNIOL-VILLARD #include <common.h>
80c698dcaSJean-Christophe PLAGNIOL-VILLARD 
90c698dcaSJean-Christophe PLAGNIOL-VILLARD #include <command.h>
100c698dcaSJean-Christophe PLAGNIOL-VILLARD #include <rtc.h>
110c698dcaSJean-Christophe PLAGNIOL-VILLARD #include <asm/immap.h>
120c698dcaSJean-Christophe PLAGNIOL-VILLARD #include <asm/rtc.h>
130c698dcaSJean-Christophe PLAGNIOL-VILLARD 
140c698dcaSJean-Christophe PLAGNIOL-VILLARD #undef RTC_DEBUG
150c698dcaSJean-Christophe PLAGNIOL-VILLARD 
166d0f6bcfSJean-Christophe PLAGNIOL-VILLARD #ifndef CONFIG_SYS_MCFRTC_BASE
170c698dcaSJean-Christophe PLAGNIOL-VILLARD #error RTC_BASE is not defined!
180c698dcaSJean-Christophe PLAGNIOL-VILLARD #endif
190c698dcaSJean-Christophe PLAGNIOL-VILLARD 
200c698dcaSJean-Christophe PLAGNIOL-VILLARD #define isleap(y) ((((y) % 4) == 0 && ((y) % 100) != 0) || ((y) % 400) == 0)
210c698dcaSJean-Christophe PLAGNIOL-VILLARD #define	STARTOFTIME		1970
220c698dcaSJean-Christophe PLAGNIOL-VILLARD 
rtc_get(struct rtc_time * tmp)23b73a19e1SYuri Tikhonov int rtc_get(struct rtc_time *tmp)
240c698dcaSJean-Christophe PLAGNIOL-VILLARD {
256d0f6bcfSJean-Christophe PLAGNIOL-VILLARD 	volatile rtc_t *rtc = (rtc_t *) (CONFIG_SYS_MCFRTC_BASE);
260c698dcaSJean-Christophe PLAGNIOL-VILLARD 
270c698dcaSJean-Christophe PLAGNIOL-VILLARD 	int rtc_days, rtc_hrs, rtc_mins;
280c698dcaSJean-Christophe PLAGNIOL-VILLARD 	int tim;
290c698dcaSJean-Christophe PLAGNIOL-VILLARD 
300c698dcaSJean-Christophe PLAGNIOL-VILLARD 	rtc_days = rtc->days;
310c698dcaSJean-Christophe PLAGNIOL-VILLARD 	rtc_hrs = rtc->hourmin >> 8;
320c698dcaSJean-Christophe PLAGNIOL-VILLARD 	rtc_mins = RTC_HOURMIN_MINUTES(rtc->hourmin);
330c698dcaSJean-Christophe PLAGNIOL-VILLARD 
340c698dcaSJean-Christophe PLAGNIOL-VILLARD 	tim = (rtc_days * 24) + rtc_hrs;
350c698dcaSJean-Christophe PLAGNIOL-VILLARD 	tim = (tim * 60) + rtc_mins;
360c698dcaSJean-Christophe PLAGNIOL-VILLARD 	tim = (tim * 60) + rtc->seconds;
370c698dcaSJean-Christophe PLAGNIOL-VILLARD 
389f9276c3SSimon Glass 	rtc_to_tm(tim, tmp);
390c698dcaSJean-Christophe PLAGNIOL-VILLARD 
400c698dcaSJean-Christophe PLAGNIOL-VILLARD 	tmp->tm_yday = 0;
410c698dcaSJean-Christophe PLAGNIOL-VILLARD 	tmp->tm_isdst = 0;
420c698dcaSJean-Christophe PLAGNIOL-VILLARD 
430c698dcaSJean-Christophe PLAGNIOL-VILLARD #ifdef RTC_DEBUG
440c698dcaSJean-Christophe PLAGNIOL-VILLARD 	printf("Get DATE: %4d-%02d-%02d (wday=%d)  TIME: %2d:%02d:%02d\n",
450c698dcaSJean-Christophe PLAGNIOL-VILLARD 	       tmp->tm_year, tmp->tm_mon, tmp->tm_mday, tmp->tm_wday,
460c698dcaSJean-Christophe PLAGNIOL-VILLARD 	       tmp->tm_hour, tmp->tm_min, tmp->tm_sec);
470c698dcaSJean-Christophe PLAGNIOL-VILLARD #endif
48b73a19e1SYuri Tikhonov 
49b73a19e1SYuri Tikhonov 	return 0;
500c698dcaSJean-Christophe PLAGNIOL-VILLARD }
510c698dcaSJean-Christophe PLAGNIOL-VILLARD 
rtc_set(struct rtc_time * tmp)52d1e23194SJean-Christophe PLAGNIOL-VILLARD int rtc_set(struct rtc_time *tmp)
530c698dcaSJean-Christophe PLAGNIOL-VILLARD {
546d0f6bcfSJean-Christophe PLAGNIOL-VILLARD 	volatile rtc_t *rtc = (rtc_t *) (CONFIG_SYS_MCFRTC_BASE);
550c698dcaSJean-Christophe PLAGNIOL-VILLARD 
560c698dcaSJean-Christophe PLAGNIOL-VILLARD 	static int month_days[12] = {
570c698dcaSJean-Christophe PLAGNIOL-VILLARD 		31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
580c698dcaSJean-Christophe PLAGNIOL-VILLARD 	};
590c698dcaSJean-Christophe PLAGNIOL-VILLARD 	int days, i, months;
600c698dcaSJean-Christophe PLAGNIOL-VILLARD 
610c698dcaSJean-Christophe PLAGNIOL-VILLARD 	if (tmp->tm_year > 2037) {
620c698dcaSJean-Christophe PLAGNIOL-VILLARD 		printf("Unable to handle. Exceeding integer limitation!\n");
630c698dcaSJean-Christophe PLAGNIOL-VILLARD 		tmp->tm_year = 2027;
640c698dcaSJean-Christophe PLAGNIOL-VILLARD 	}
650c698dcaSJean-Christophe PLAGNIOL-VILLARD #ifdef RTC_DEBUG
660c698dcaSJean-Christophe PLAGNIOL-VILLARD 	printf("Set DATE: %4d-%02d-%02d (wday=%d)  TIME: %2d:%02d:%02d\n",
670c698dcaSJean-Christophe PLAGNIOL-VILLARD 	       tmp->tm_year, tmp->tm_mon, tmp->tm_mday, tmp->tm_wday,
680c698dcaSJean-Christophe PLAGNIOL-VILLARD 	       tmp->tm_hour, tmp->tm_min, tmp->tm_sec);
690c698dcaSJean-Christophe PLAGNIOL-VILLARD #endif
700c698dcaSJean-Christophe PLAGNIOL-VILLARD 
710c698dcaSJean-Christophe PLAGNIOL-VILLARD 	/* calculate days by years */
720c698dcaSJean-Christophe PLAGNIOL-VILLARD 	for (i = STARTOFTIME, days = 0; i < tmp->tm_year; i++) {
730c698dcaSJean-Christophe PLAGNIOL-VILLARD 		days += 365 + isleap(i);
740c698dcaSJean-Christophe PLAGNIOL-VILLARD 	}
750c698dcaSJean-Christophe PLAGNIOL-VILLARD 
760c698dcaSJean-Christophe PLAGNIOL-VILLARD 	/* calculate days by months */
770c698dcaSJean-Christophe PLAGNIOL-VILLARD 	months = tmp->tm_mon - 1;
780c698dcaSJean-Christophe PLAGNIOL-VILLARD 	for (i = 0; i < months; i++) {
790c698dcaSJean-Christophe PLAGNIOL-VILLARD 		days += month_days[i];
800c698dcaSJean-Christophe PLAGNIOL-VILLARD 
810c698dcaSJean-Christophe PLAGNIOL-VILLARD 		if (i == 1)
820c698dcaSJean-Christophe PLAGNIOL-VILLARD 			days += isleap(i);
830c698dcaSJean-Christophe PLAGNIOL-VILLARD 	}
840c698dcaSJean-Christophe PLAGNIOL-VILLARD 
850c698dcaSJean-Christophe PLAGNIOL-VILLARD 	days += tmp->tm_mday - 1;
860c698dcaSJean-Christophe PLAGNIOL-VILLARD 
870c698dcaSJean-Christophe PLAGNIOL-VILLARD 	rtc->days = days;
880c698dcaSJean-Christophe PLAGNIOL-VILLARD 	rtc->hourmin = (tmp->tm_hour << 8) | tmp->tm_min;
890c698dcaSJean-Christophe PLAGNIOL-VILLARD 	rtc->seconds = tmp->tm_sec;
90d1e23194SJean-Christophe PLAGNIOL-VILLARD 
91d1e23194SJean-Christophe PLAGNIOL-VILLARD 	return 0;
920c698dcaSJean-Christophe PLAGNIOL-VILLARD }
930c698dcaSJean-Christophe PLAGNIOL-VILLARD 
rtc_reset(void)940c698dcaSJean-Christophe PLAGNIOL-VILLARD void rtc_reset(void)
950c698dcaSJean-Christophe PLAGNIOL-VILLARD {
966d0f6bcfSJean-Christophe PLAGNIOL-VILLARD 	volatile rtc_t *rtc = (rtc_t *) (CONFIG_SYS_MCFRTC_BASE);
970c698dcaSJean-Christophe PLAGNIOL-VILLARD 
980c698dcaSJean-Christophe PLAGNIOL-VILLARD 	if ((rtc->cr & RTC_CR_EN) == 0) {
990c698dcaSJean-Christophe PLAGNIOL-VILLARD 		printf("real-time-clock was stopped. Now starting...\n");
1000c698dcaSJean-Christophe PLAGNIOL-VILLARD 		rtc->cr |= RTC_CR_EN;
1010c698dcaSJean-Christophe PLAGNIOL-VILLARD 	}
1020c698dcaSJean-Christophe PLAGNIOL-VILLARD 
1030c698dcaSJean-Christophe PLAGNIOL-VILLARD 	rtc->cr |= RTC_CR_SWR;
1040c698dcaSJean-Christophe PLAGNIOL-VILLARD }
105