summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--firmware/drivers/rtc/rtc_jz4740.c291
1 files changed, 39 insertions, 252 deletions
diff --git a/firmware/drivers/rtc/rtc_jz4740.c b/firmware/drivers/rtc/rtc_jz4740.c
index a73f300aa8..b82978ed21 100644
--- a/firmware/drivers/rtc/rtc_jz4740.c
+++ b/firmware/drivers/rtc/rtc_jz4740.c
@@ -30,281 +30,68 @@
30#include "timefuncs.h" 30#include "timefuncs.h"
31#include "logf.h" 31#include "logf.h"
32 32
33static const unsigned int yearday[5] = {0, 366, 366+365, 366+365*2, 366+365*3}; 33/* Stolen from dietlibc-0.29/libugly/gmtime_r.c (GPLv2) */
34static const unsigned int sweekday = 6; 34#define SPD (24*60*60)
35static const unsigned int sum_monthday[13] = { 35#define ISLEAP(year) (!(year%4) && ((year%100) || !(year%400)))
36 0, 36static void _localtime(const time_t t, struct tm *r)
37 31,
38 31+28,
39 31+28+31,
40 31+28+31+30,
41 31+28+31+30+31,
42 31+28+31+30+31+30,
43 31+28+31+30+31+30+31,
44 31+28+31+30+31+30+31+31,
45 31+28+31+30+31+30+31+31+30,
46 31+28+31+30+31+30+31+31+30+31,
47 31+28+31+30+31+30+31+31+30+31+30,
48 365
49};
50
51static unsigned int jz_mktime(int year, int mon, int day, int hour, int min,
52 int sec)
53{ 37{
54 unsigned int seccounter; 38 time_t i;
39 register time_t work = t % SPD;
40 static int m_to_d[12] = /* This could be shared with mktime() */
41 {0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334};
42
43 r->tm_sec = work % 60;
44 work /= 60;
45 r->tm_min = work % 60;
46 r->tm_hour = work / 60;
47 work = t / SPD;
48 r->tm_wday = (4 + work) % 7;
49
50 for (i=1970; ; ++i)
51 {
52 register time_t k = ISLEAP(i) ? 366 : 365;
55 53
56 if (year < 2000) 54 if (work >= k)
57 year = 2000; 55 work -= k;
58 year -= 2000;
59 seccounter = (year/4)*(365*3+366);
60 seccounter += yearday[year%4];
61 if (year%4)
62 seccounter += sum_monthday[mon-1];
63 else
64 if (mon >= 3)
65 seccounter += sum_monthday[mon-1]+1;
66 else 56 else
67 seccounter += sum_monthday[mon-1];
68 seccounter += day-1;
69 seccounter *= 24;
70 seccounter += hour;
71 seccounter *= 60;
72 seccounter += min;
73 seccounter *= 60;
74 seccounter += sec;
75
76 return seccounter;
77}
78
79static void jz_gettime(unsigned int rtc, int *year, int *mon, int *day,
80 int *hour, int *min, int *sec, int *weekday)
81{
82 unsigned int tday, tsec, i, tmp;
83
84 tday = rtc/(24*3600);
85 *weekday = ((tday % 7) + sweekday) % 7;
86 *year = (tday/(366+365*3)) * 4;
87 tday = tday%(366+365*3);
88 for (i=0;i<5;i++)
89 {
90 if (tday<yearday[i])
91 {
92 *year += i-1;
93 tday -= yearday[i-1];
94 break; 57 break;
95 }
96 } 58 }
97 for (i=0;i<13;i++) 59
60 r->tm_year = i - 1900;
61 r->tm_yday = work;
62
63 r->tm_mday = 1;
64 if (ISLEAP(i) && (work>58))
98 { 65 {
99 tmp = sum_monthday[i]; 66 if (work==59)
100 if (((*year%4) == 0) && (i>=2)) 67 r->tm_mday=2; /* 29.2. */
101 tmp += 1; 68
102 if (tday<tmp) 69 work-=1;
103 {
104 *mon = i;
105 tmp = sum_monthday[i-1];
106 if (((*year%4) == 0) && ((i-1)>=2))
107 tmp += 1;
108 *day = tday - tmp + 1;
109 break;
110 }
111 } 70 }
112 tsec = rtc % (24 * 3600); 71
113 *hour = tsec / 3600; 72 for (i=11; i && (m_to_d[i] > work); --i);
114 *min = (tsec / 60) % 60; 73 r->tm_mon = i;
115 *sec = tsec - *hour*3600 - *min*60; 74 r->tm_mday += work - m_to_d[i];
116 *year += 2000;
117} 75}
118 76
119int rtc_read_datetime(struct tm *tm) 77int rtc_read_datetime(struct tm *tm)
120{ 78{
121 unsigned int sec,mon,mday,wday,year,hour,min; 79 _localtime(REG_RTC_RSR, tm);
122
123 /*
124 * Only the values that we read from the RTC are set. We leave
125 * tm_wday, tm_yday and tm_isdst untouched. Even though the
126 * RTC has RTC_DAY_OF_WEEK, we ignore it, as it is only updated
127 * by the RTC when initially set to a non-zero value.
128 */
129 jz_gettime(REG_RTC_RSR, &year, &mon, &mday, &hour, &min, &sec, &wday);
130
131 year -= 2000;
132
133 tm->tm_sec = sec;
134 tm->tm_min = min;
135 tm->tm_hour = hour;
136 tm->tm_mday = mday;
137 tm->tm_wday = wday;
138 /* Don't use centry, but start from year 1970 */
139 tm->tm_mon = mon;
140 if (year <= 69)
141 year += 100;
142 tm->tm_year = year;
143 80
144 return 1; 81 return 1;
145} 82}
146 83
147int rtc_write_datetime(const struct tm *tm) 84int rtc_write_datetime(const struct tm *tm)
148{ 85{
149 unsigned int year, lval; 86 time_t val = mktime((struct tm*)tm);
150
151 year = tm->tm_year;
152 /* Don't use centry, but start from year 1970 */
153 if (year > 69)
154 year -= 100;
155 year += 2000;
156
157 lval = jz_mktime(year, tm->tm_mon, tm->tm_mday, tm->tm_hour,
158 tm->tm_min, tm->tm_sec);
159 87
160 __cpm_start_rtc(); 88 __cpm_start_rtc();
161 udelay(100); 89 udelay(100);
162 REG_RTC_RSR = lval; 90 REG_RTC_RSR = val;
163 __cpm_stop_rtc(); 91 __cpm_stop_rtc();
164
165 return 0;
166}
167 92
168#if 0 93 return 0;
169void get_rtc_alm_time(struct rtc_time *alm_tm)
170{
171 unsigned int sec,mon,mday,wday,year,hour,min;
172 unsigned int lval;
173 unsigned long flags;
174 /*
175 * Only the values that we read from the RTC are set. That
176 * means only tm_hour, tm_min, and tm_sec.
177 */
178 lval = REG_RTC_RSAR;
179 jz_gettime(lval, &year, &mon, &mday, &hour, &min, &sec, &wday);
180
181 alm_tm->tm_sec = sec;
182 alm_tm->tm_min = min;
183 alm_tm->tm_hour = hour;
184}
185
186
187int rtc_ioctl(unsigned int cmd,struct rtc_time *val,unsigned int epo)
188{
189 struct rtc_time wtime;
190 switch (cmd) {
191 case RTC_ALM_READ: /* Read the present alarm time */
192 /*
193 * This returns a struct rtc_time. Reading >= 0xc0
194 * means "don't care" or "match all". Only the tm_hour,
195 * tm_min, and tm_sec values are filled in.
196 */
197 get_rtc_alm_time(val);
198 break;
199 case RTC_ALM_SET: /* Store a time into the alarm */
200 {
201 unsigned char ahrs, amin, asec;
202 unsigned int sec,mon,mday,wday,year,hour,min;
203 unsigned int lval;
204 unsigned long flags;
205 struct rtc_time alm_tm;
206
207 alm_tm = *val;
208 ahrs = alm_tm.tm_hour;
209 amin = alm_tm.tm_min;
210 asec = alm_tm.tm_sec;
211
212
213
214 if (ahrs >= 24)
215 return -1;
216
217 if (amin >= 60)
218 return -1;
219
220 if (asec >= 60)
221 return -1;
222
223 flags = spin_lock_irqsave();
224 lval = REG_RTC_RSR;
225 jz_gettime(lval, &year, &mon, &mday, &hour, &min, &sec, &wday);
226 hour = ahrs;
227 min = amin;
228 sec = asec;
229 lval = jz_mktime(year, mon, mday, hour, min, sec);
230 REG_RTC_RSAR = lval;
231 spin_unlock_irqrestore(flags);
232 break;
233 }
234 case RTC_RD_TIME: /* Read the time/date from RTC */
235 get_rtc_time(val);
236 break;
237 case RTC_SET_TIME: /* Set the RTC */
238 {
239 struct rtc_time rtc_tm;
240 unsigned int mon, day, hrs, min, sec, leap_yr, date;
241 unsigned int yrs;
242 unsigned int lval;
243 unsigned long flags;
244
245 rtc_tm = *val;
246 yrs = rtc_tm.tm_year;// + 1900;
247 mon = rtc_tm.tm_mon + 1; /* tm_mon starts at zero */
248 day = rtc_tm.tm_wday;
249 date = rtc_tm.tm_mday;
250 hrs = rtc_tm.tm_hour;
251 min = rtc_tm.tm_min;
252 sec = rtc_tm.tm_sec;
253
254
255 if (yrs < 1970)
256 return -EINVAL;
257 leap_yr = ((!(yrs % 4) && (yrs % 100)) || !(yrs % 400));
258
259 if ((mon > 12) || (date == 0))
260 return -EINVAL;
261
262 if (date > (days_in_mo[mon] + ((mon == 2) && leap_yr)))
263 return -EINVAL;
264
265 if ((hrs >= 24) || (min >= 60) || (sec >= 60))
266 return -EINVAL;
267
268 if ((yrs -= epoch) > 255) /* They are unsigned */
269 return -EINVAL;
270
271 flags = spin_lock_irqsave();
272 /* These limits and adjustments are independant of
273 * whether the chip is in binary mode or not.
274 */
275
276 if (yrs > 169) {
277 spin_unlock_irqrestore(flags);
278 return -EINVAL;
279 }
280
281 yrs += epoch;
282 lval = jz_mktime(yrs, mon, date, hrs, min, sec);
283 REG_RTC_RSR = lval;
284 /* FIXME: maybe we need to write alarm register here. */
285 spin_unlock_irqrestore(flags);
286
287 return 0;
288 }
289 break;
290 case RTC_EPOCH_READ: /* Read the epoch. */
291 epo = epoch;
292 return 0;
293 case RTC_EPOCH_SET: /* Set the epoch. */
294 /*
295 * There were no RTC clocks before 1900.
296 */
297 if (epo < 1900)
298 return -EINVAL;
299
300 epoch = epo;
301 return 0;
302 default:
303 return -EINVAL;
304 }
305 return -EINVAL;
306} 94}
307#endif
308 95
309void rtc_init(void) 96void rtc_init(void)
310{ 97{