1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3  * Copyright (C) 2004-2007 Freescale Semiconductor, Inc.
4  * TsiChung Liew (Tsi-Chung.Liew@freescale.com)
5  */
6 
7 #include <command.h>
8 #include <rtc.h>
9 #include <asm/immap.h>
10 #include <asm/rtc.h>
11 
12 #undef RTC_DEBUG
13 
14 #define isleap(y) ((((y) % 4) == 0 && ((y) % 100) != 0) || ((y) % 400) == 0)
15 #define	STARTOFTIME		1970
16 
rtc_get(struct rtc_time * tmp)17 int rtc_get(struct rtc_time *tmp)
18 {
19 	volatile rtc_t *rtc = (rtc_t *) (CONFIG_SYS_MCFRTC_BASE);
20 
21 	int rtc_days, rtc_hrs, rtc_mins;
22 	int tim;
23 
24 	rtc_days = rtc->days;
25 	rtc_hrs = rtc->hourmin >> 8;
26 	rtc_mins = RTC_HOURMIN_MINUTES(rtc->hourmin);
27 
28 	tim = (rtc_days * 24) + rtc_hrs;
29 	tim = (tim * 60) + rtc_mins;
30 	tim = (tim * 60) + rtc->seconds;
31 
32 	rtc_to_tm(tim, tmp);
33 
34 	tmp->tm_yday = 0;
35 	tmp->tm_isdst = 0;
36 
37 #ifdef RTC_DEBUG
38 	printf("Get DATE: %4d-%02d-%02d (wday=%d)  TIME: %2d:%02d:%02d\n",
39 	       tmp->tm_year, tmp->tm_mon, tmp->tm_mday, tmp->tm_wday,
40 	       tmp->tm_hour, tmp->tm_min, tmp->tm_sec);
41 #endif
42 
43 	return 0;
44 }
45 
rtc_set(struct rtc_time * tmp)46 int rtc_set(struct rtc_time *tmp)
47 {
48 	volatile rtc_t *rtc = (rtc_t *) (CONFIG_SYS_MCFRTC_BASE);
49 
50 	static int month_days[12] = {
51 		31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
52 	};
53 	int days, i, months;
54 
55 	if (tmp->tm_year > 2037) {
56 		printf("Unable to handle. Exceeding integer limitation!\n");
57 		tmp->tm_year = 2027;
58 	}
59 #ifdef RTC_DEBUG
60 	printf("Set DATE: %4d-%02d-%02d (wday=%d)  TIME: %2d:%02d:%02d\n",
61 	       tmp->tm_year, tmp->tm_mon, tmp->tm_mday, tmp->tm_wday,
62 	       tmp->tm_hour, tmp->tm_min, tmp->tm_sec);
63 #endif
64 
65 	/* calculate days by years */
66 	for (i = STARTOFTIME, days = 0; i < tmp->tm_year; i++) {
67 		days += 365 + isleap(i);
68 	}
69 
70 	/* calculate days by months */
71 	months = tmp->tm_mon - 1;
72 	for (i = 0; i < months; i++) {
73 		days += month_days[i];
74 
75 		if (i == 1)
76 			days += isleap(i);
77 	}
78 
79 	days += tmp->tm_mday - 1;
80 
81 	rtc->days = days;
82 	rtc->hourmin = (tmp->tm_hour << 8) | tmp->tm_min;
83 	rtc->seconds = tmp->tm_sec;
84 
85 	return 0;
86 }
87 
rtc_reset(void)88 void rtc_reset(void)
89 {
90 	volatile rtc_t *rtc = (rtc_t *) (CONFIG_SYS_MCFRTC_BASE);
91 
92 	if ((rtc->cr & RTC_CR_EN) == 0) {
93 		printf("real-time-clock was stopped. Now starting...\n");
94 		rtc->cr |= RTC_CR_EN;
95 	}
96 
97 	rtc->cr |= RTC_CR_SWR;
98 }
99