FS#8961 - Anti-Aliased Fonts.
[kugel-rb.git] / firmware / drivers / rtc / rtc_jz4740.c
blob479e3591db640b8381022ecfd415abe4eb54611d
1 /***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
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
27 #include "config.h"
28 #include "jz4740.h"
29 #include "rtc.h"
30 #include "timefuncs.h"
31 #include "logf.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] = {
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
51 static unsigned int jz_mktime(int year, int mon, int day, int hour, int min,
52 int sec)
54 unsigned int seccounter;
56 if (year < 2000)
57 year = 2000;
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
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;
76 return seccounter;
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;
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++)
90 if (tday<yearday[i])
92 *year += i-1;
93 tday -= yearday[i-1];
94 break;
97 for (i=0;i<13;i++)
99 tmp = sum_monthday[i];
100 if (((*year%4) == 0) && (i>=2))
101 tmp += 1;
102 if (tday<tmp)
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;
112 tsec = rtc % (24 * 3600);
113 *hour = tsec / 3600;
114 *min = (tsec / 60) % 60;
115 *sec = tsec - *hour*3600 - *min*60;
116 *year += 2000;
119 int rtc_read_datetime(unsigned char* buf)
121 struct tm rtc_tm;
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);
132 year -= 2000;
134 rtc_tm.tm_sec = sec;
135 rtc_tm.tm_min = min;
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 */
140 rtc_tm.tm_mon = mon;
141 if (year <= 69)
142 year += 100;
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;
149 return 1;
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 */
159 if (year > 69)
160 year -= 100;
161 year += 2000;
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);
166 __cpm_start_rtc();
167 udelay(100);
168 REG_RTC_RSR = lval;
169 __cpm_stop_rtc();
171 return 0;
174 #if 0
175 void get_rtc_alm_time(struct rtc_time *alm_tm)
177 unsigned int sec,mon,mday,wday,year,hour,min;
178 unsigned int lval;
179 unsigned long flags;
181 * Only the values that we read from the RTC are set. That
182 * means only tm_hour, tm_min, and tm_sec.
184 lval = REG_RTC_RSAR;
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;
196 switch (cmd) {
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);
204 break;
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;
209 unsigned int lval;
210 unsigned long flags;
211 struct rtc_time alm_tm;
213 alm_tm = *val;
214 ahrs = alm_tm.tm_hour;
215 amin = alm_tm.tm_min;
216 asec = alm_tm.tm_sec;
220 if (ahrs >= 24)
221 return -1;
223 if (amin >= 60)
224 return -1;
226 if (asec >= 60)
227 return -1;
229 flags = spin_lock_irqsave();
230 lval = REG_RTC_RSR;
231 jz_gettime(lval, &year, &mon, &mday, &hour, &min, &sec, &wday);
232 hour = ahrs;
233 min = amin;
234 sec = asec;
235 lval = jz_mktime(year, mon, mday, hour, min, sec);
236 REG_RTC_RSAR = lval;
237 spin_unlock_irqrestore(flags);
238 break;
240 case RTC_RD_TIME: /* Read the time/date from RTC */
241 get_rtc_time(val);
242 break;
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;
247 unsigned int yrs;
248 unsigned int lval;
249 unsigned long flags;
251 rtc_tm = *val;
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;
257 min = rtc_tm.tm_min;
258 sec = rtc_tm.tm_sec;
261 if (yrs < 1970)
262 return -EINVAL;
263 leap_yr = ((!(yrs % 4) && (yrs % 100)) || !(yrs % 400));
265 if ((mon > 12) || (date == 0))
266 return -EINVAL;
268 if (date > (days_in_mo[mon] + ((mon == 2) && leap_yr)))
269 return -EINVAL;
271 if ((hrs >= 24) || (min >= 60) || (sec >= 60))
272 return -EINVAL;
274 if ((yrs -= epoch) > 255) /* They are unsigned */
275 return -EINVAL;
277 flags = spin_lock_irqsave();
278 /* These limits and adjustments are independant of
279 * whether the chip is in binary mode or not.
282 if (yrs > 169) {
283 spin_unlock_irqrestore(flags);
284 return -EINVAL;
287 yrs += epoch;
288 lval = jz_mktime(yrs, mon, date, hrs, min, sec);
289 REG_RTC_RSR = lval;
290 /* FIXME: maybe we need to write alarm register here. */
291 spin_unlock_irqrestore(flags);
293 return 0;
295 break;
296 case RTC_EPOCH_READ: /* Read the epoch. */
297 epo = epoch;
298 return 0;
299 case RTC_EPOCH_SET: /* Set the epoch. */
301 * There were no RTC clocks before 1900.
303 if (epo < 1900)
304 return -EINVAL;
306 epoch = epo;
307 return 0;
308 default:
309 return -EINVAL;
311 return -EINVAL;
313 #endif
315 void rtc_init(void)
317 __cpm_start_rtc();
318 REG_RTC_RCR = RTC_RCR_RTCE;
319 udelay(70);
320 while( !(REG_RTC_RCR & RTC_RCR_WRDY) );
321 REG_RTC_RGR = (0x7fff | RTC_RGR_LOCK);
322 udelay(70);
323 __cpm_stop_rtc();