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(struct tm
*tm
)
121 unsigned int sec
,mon
,mday
,wday
,year
,hour
,min
;
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.
129 jz_gettime(REG_RTC_RSR
, &year
, &mon
, &mday
, &hour
, &min
, &sec
, &wday
);
138 /* Don't use centry, but start from year 1970 */
147 int rtc_write_datetime(const struct tm
*tm
)
149 unsigned int year
, lval
;
152 /* Don't use centry, but start from year 1970 */
157 lval
= jz_mktime(year
, tm
->tm_mon
, tm
->tm_mday
, tm
->tm_hour
,
158 tm
->tm_min
, tm
->tm_sec
);
169 void get_rtc_alm_time(struct rtc_time
*alm_tm
)
171 unsigned int sec
,mon
,mday
,wday
,year
,hour
,min
;
175 * Only the values that we read from the RTC are set. That
176 * means only tm_hour, tm_min, and tm_sec.
179 jz_gettime(lval
, &year
, &mon
, &mday
, &hour
, &min
, &sec
, &wday
);
181 alm_tm
->tm_sec
= sec
;
182 alm_tm
->tm_min
= min
;
183 alm_tm
->tm_hour
= hour
;
187 int rtc_ioctl(unsigned int cmd
,struct rtc_time
*val
,unsigned int epo
)
189 struct rtc_time wtime
;
191 case RTC_ALM_READ
: /* Read the present alarm time */
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.
197 get_rtc_alm_time(val
);
199 case RTC_ALM_SET
: /* Store a time into the alarm */
201 unsigned char ahrs
, amin
, asec
;
202 unsigned int sec
,mon
,mday
,wday
,year
,hour
,min
;
205 struct rtc_time alm_tm
;
208 ahrs
= alm_tm
.tm_hour
;
209 amin
= alm_tm
.tm_min
;
210 asec
= alm_tm
.tm_sec
;
223 flags
= spin_lock_irqsave();
225 jz_gettime(lval
, &year
, &mon
, &mday
, &hour
, &min
, &sec
, &wday
);
229 lval
= jz_mktime(year
, mon
, mday
, hour
, min
, sec
);
231 spin_unlock_irqrestore(flags
);
234 case RTC_RD_TIME
: /* Read the time/date from RTC */
237 case RTC_SET_TIME
: /* Set the RTC */
239 struct rtc_time rtc_tm
;
240 unsigned int mon
, day
, hrs
, min
, sec
, leap_yr
, date
;
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
;
257 leap_yr
= ((!(yrs
% 4) && (yrs
% 100)) || !(yrs
% 400));
259 if ((mon
> 12) || (date
== 0))
262 if (date
> (days_in_mo
[mon
] + ((mon
== 2) && leap_yr
)))
265 if ((hrs
>= 24) || (min
>= 60) || (sec
>= 60))
268 if ((yrs
-= epoch
) > 255) /* They are unsigned */
271 flags
= spin_lock_irqsave();
272 /* These limits and adjustments are independant of
273 * whether the chip is in binary mode or not.
277 spin_unlock_irqrestore(flags
);
282 lval
= jz_mktime(yrs
, mon
, date
, hrs
, min
, sec
);
284 /* FIXME: maybe we need to write alarm register here. */
285 spin_unlock_irqrestore(flags
);
290 case RTC_EPOCH_READ
: /* Read the epoch. */
293 case RTC_EPOCH_SET
: /* Set the epoch. */
295 * There were no RTC clocks before 1900.
312 REG_RTC_RCR
= RTC_RCR_RTCE
;
314 while( !(REG_RTC_RCR
& RTC_RCR_WRDY
) );
315 REG_RTC_RGR
= (0x7fff | RTC_RGR_LOCK
);