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