1 /***************************************************************************
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
10 * Copyright (C) 2008 by Maurus Cuelenaere
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
17 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
18 * KIND, either express or implied.
20 ****************************************************************************/
23 * Jz OnChip Real Time Clock interface for Linux
30 #include "timefuncs.h"
33 static const unsigned int yearday
[5] = {0, 366, 366+365, 366+365*2, 366+365*3};
34 static const unsigned int sweekday
= 6;
35 static const unsigned int sum_monthday
[13] = {
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,
51 static unsigned int jz_mktime(int year
, int mon
, int day
, int hour
, int min
,
54 unsigned int seccounter
;
59 seccounter
= (year
/4)*(365*3+366);
60 seccounter
+= yearday
[year
%4];
62 seccounter
+= sum_monthday
[mon
-1];
65 seccounter
+= sum_monthday
[mon
-1]+1;
67 seccounter
+= sum_monthday
[mon
-1];
79 static void jz_gettime(unsigned int rtc
, int *year
, int *mon
, int *day
,
80 int *hour
, int *min
, int *sec
, int *weekday
)
82 unsigned int tday
, tsec
, i
, tmp
;
85 *weekday
= ((tday
% 7) + sweekday
) % 7;
86 *year
= (tday
/(366+365*3)) * 4;
87 tday
= tday
%(366+365*3);
99 tmp
= sum_monthday
[i
];
100 if (((*year
%4) == 0) && (i
>=2))
105 tmp
= sum_monthday
[i
-1];
106 if (((*year
%4) == 0) && ((i
-1)>=2))
108 *day
= tday
- tmp
+ 1;
112 tsec
= rtc
% (24 * 3600);
114 *min
= (tsec
/ 60) % 60;
115 *sec
= tsec
- *hour
*3600 - *min
*60;
119 int rtc_read_datetime(unsigned char* buf
)
122 unsigned int sec
,mon
,mday
,wday
,year
,hour
,min
;
125 * Only the values that we read from the RTC are set. We leave
126 * tm_wday, tm_yday and tm_isdst untouched. Even though the
127 * RTC has RTC_DAY_OF_WEEK, we ignore it, as it is only updated
128 * by the RTC when initially set to a non-zero value.
130 jz_gettime(REG_RTC_RSR
, &year
, &mon
, &mday
, &hour
, &min
, &sec
, &wday
);
136 rtc_tm
.tm_hour
= hour
;
137 rtc_tm
.tm_mday
= mday
;
138 rtc_tm
.tm_wday
= wday
;
139 /* Don't use centry, but start from year 1970 */
143 rtc_tm
.tm_year
= year
;
145 rtc_tm
.tm_yday
= 0; /* Not implemented for now */
146 rtc_tm
.tm_isdst
= -1; /* Not implemented for now */
148 (*((struct tm
*)buf
)) = rtc_tm
;
152 int rtc_write_datetime(unsigned char* buf
)
154 struct tm
*rtc_tm
= (struct tm
*)buf
;
155 unsigned int year
, lval
;
157 year
= rtc_tm
->tm_year
;
158 /* Don't use centry, but start from year 1970 */
163 lval
= jz_mktime(year
, rtc_tm
->tm_mon
, rtc_tm
->tm_mday
, rtc_tm
->tm_hour
,
164 rtc_tm
->tm_min
, rtc_tm
->tm_sec
);
175 void get_rtc_alm_time(struct rtc_time
*alm_tm
)
177 unsigned int sec
,mon
,mday
,wday
,year
,hour
,min
;
181 * Only the values that we read from the RTC are set. That
182 * means only tm_hour, tm_min, and tm_sec.
185 jz_gettime(lval
, &year
, &mon
, &mday
, &hour
, &min
, &sec
, &wday
);
187 alm_tm
->tm_sec
= sec
;
188 alm_tm
->tm_min
= min
;
189 alm_tm
->tm_hour
= hour
;
193 int rtc_ioctl(unsigned int cmd
,struct rtc_time
*val
,unsigned int epo
)
195 struct rtc_time wtime
;
197 case RTC_ALM_READ
: /* Read the present alarm time */
199 * This returns a struct rtc_time. Reading >= 0xc0
200 * means "don't care" or "match all". Only the tm_hour,
201 * tm_min, and tm_sec values are filled in.
203 get_rtc_alm_time(val
);
205 case RTC_ALM_SET
: /* Store a time into the alarm */
207 unsigned char ahrs
, amin
, asec
;
208 unsigned int sec
,mon
,mday
,wday
,year
,hour
,min
;
211 struct rtc_time alm_tm
;
214 ahrs
= alm_tm
.tm_hour
;
215 amin
= alm_tm
.tm_min
;
216 asec
= alm_tm
.tm_sec
;
229 flags
= spin_lock_irqsave();
231 jz_gettime(lval
, &year
, &mon
, &mday
, &hour
, &min
, &sec
, &wday
);
235 lval
= jz_mktime(year
, mon
, mday
, hour
, min
, sec
);
237 spin_unlock_irqrestore(flags
);
240 case RTC_RD_TIME
: /* Read the time/date from RTC */
243 case RTC_SET_TIME
: /* Set the RTC */
245 struct rtc_time rtc_tm
;
246 unsigned int mon
, day
, hrs
, min
, sec
, leap_yr
, date
;
252 yrs
= rtc_tm
.tm_year
;// + 1900;
253 mon
= rtc_tm
.tm_mon
+ 1; /* tm_mon starts at zero */
254 day
= rtc_tm
.tm_wday
;
255 date
= rtc_tm
.tm_mday
;
256 hrs
= rtc_tm
.tm_hour
;
263 leap_yr
= ((!(yrs
% 4) && (yrs
% 100)) || !(yrs
% 400));
265 if ((mon
> 12) || (date
== 0))
268 if (date
> (days_in_mo
[mon
] + ((mon
== 2) && leap_yr
)))
271 if ((hrs
>= 24) || (min
>= 60) || (sec
>= 60))
274 if ((yrs
-= epoch
) > 255) /* They are unsigned */
277 flags
= spin_lock_irqsave();
278 /* These limits and adjustments are independant of
279 * whether the chip is in binary mode or not.
283 spin_unlock_irqrestore(flags
);
288 lval
= jz_mktime(yrs
, mon
, date
, hrs
, min
, sec
);
290 /* FIXME: maybe we need to write alarm register here. */
291 spin_unlock_irqrestore(flags
);
296 case RTC_EPOCH_READ
: /* Read the epoch. */
299 case RTC_EPOCH_SET
: /* Set the epoch. */
301 * There were no RTC clocks before 1900.
318 REG_RTC_RCR
= RTC_RCR_RTCE
;
320 while( !(REG_RTC_RCR
& RTC_RCR_WRDY
) );
321 REG_RTC_RGR
= (0x7fff | RTC_RGR_LOCK
);