summaryrefslogtreecommitdiff
path: root/firmware/drivers/rtc
diff options
context:
space:
mode:
authorMaurus Cuelenaere <mcuelenaere@gmail.com>2010-01-08 14:52:15 +0000
committerMaurus Cuelenaere <mcuelenaere@gmail.com>2010-01-08 14:52:15 +0000
commit537bea5faca5b77ae325da1fe4306aaa9b6bfa60 (patch)
treeea26687860a3e5467938da4f148e4ea5b248e872 /firmware/drivers/rtc
parent13ef677d152b1de0f6d4c581770a8daa173cb9e4 (diff)
Ingenic Jz4740: simplify RTC driver (you will need to re-set the clock)
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@24201 a1c6a512-1295-4272-9138-f99709370657
Diffstat (limited to 'firmware/drivers/rtc')
-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 @@
#include "timefuncs.h"
#include "logf.h"
-static const unsigned int yearday[5] = {0, 366, 366+365, 366+365*2, 366+365*3};
-static const unsigned int sweekday = 6;
-static const unsigned int sum_monthday[13] = {
- 0,
- 31,
- 31+28,
- 31+28+31,
- 31+28+31+30,
- 31+28+31+30+31,
- 31+28+31+30+31+30,
- 31+28+31+30+31+30+31,
- 31+28+31+30+31+30+31+31,
- 31+28+31+30+31+30+31+31+30,
- 31+28+31+30+31+30+31+31+30+31,
- 31+28+31+30+31+30+31+31+30+31+30,
- 365
-};
-
-static unsigned int jz_mktime(int year, int mon, int day, int hour, int min,
- int sec)
+/* Stolen from dietlibc-0.29/libugly/gmtime_r.c (GPLv2) */
+#define SPD (24*60*60)
+#define ISLEAP(year) (!(year%4) && ((year%100) || !(year%400)))
+static void _localtime(const time_t t, struct tm *r)
{
- unsigned int seccounter;
+ time_t i;
+ register time_t work = t % SPD;
+ static int m_to_d[12] = /* This could be shared with mktime() */
+ {0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334};
+
+ r->tm_sec = work % 60;
+ work /= 60;
+ r->tm_min = work % 60;
+ r->tm_hour = work / 60;
+ work = t / SPD;
+ r->tm_wday = (4 + work) % 7;
+
+ for (i=1970; ; ++i)
+ {
+ register time_t k = ISLEAP(i) ? 366 : 365;
- if (year < 2000)
- year = 2000;
- year -= 2000;
- seccounter = (year/4)*(365*3+366);
- seccounter += yearday[year%4];
- if (year%4)
- seccounter += sum_monthday[mon-1];
- else
- if (mon >= 3)
- seccounter += sum_monthday[mon-1]+1;
+ if (work >= k)
+ work -= k;
else
- seccounter += sum_monthday[mon-1];
- seccounter += day-1;
- seccounter *= 24;
- seccounter += hour;
- seccounter *= 60;
- seccounter += min;
- seccounter *= 60;
- seccounter += sec;
-
- return seccounter;
-}
-
-static void jz_gettime(unsigned int rtc, int *year, int *mon, int *day,
- int *hour, int *min, int *sec, int *weekday)
-{
- unsigned int tday, tsec, i, tmp;
-
- tday = rtc/(24*3600);
- *weekday = ((tday % 7) + sweekday) % 7;
- *year = (tday/(366+365*3)) * 4;
- tday = tday%(366+365*3);
- for (i=0;i<5;i++)
- {
- if (tday<yearday[i])
- {
- *year += i-1;
- tday -= yearday[i-1];
break;
- }
}
- for (i=0;i<13;i++)
+
+ r->tm_year = i - 1900;
+ r->tm_yday = work;
+
+ r->tm_mday = 1;
+ if (ISLEAP(i) && (work>58))
{
- tmp = sum_monthday[i];
- if (((*year%4) == 0) && (i>=2))
- tmp += 1;
- if (tday<tmp)
- {
- *mon = i;
- tmp = sum_monthday[i-1];
- if (((*year%4) == 0) && ((i-1)>=2))
- tmp += 1;
- *day = tday - tmp + 1;
- break;
- }
+ if (work==59)
+ r->tm_mday=2; /* 29.2. */
+
+ work-=1;
}
- tsec = rtc % (24 * 3600);
- *hour = tsec / 3600;
- *min = (tsec / 60) % 60;
- *sec = tsec - *hour*3600 - *min*60;
- *year += 2000;
+
+ for (i=11; i && (m_to_d[i] > work); --i);
+ r->tm_mon = i;
+ r->tm_mday += work - m_to_d[i];
}
int rtc_read_datetime(struct tm *tm)
{
- unsigned int sec,mon,mday,wday,year,hour,min;
-
- /*
- * Only the values that we read from the RTC are set. We leave
- * tm_wday, tm_yday and tm_isdst untouched. Even though the
- * RTC has RTC_DAY_OF_WEEK, we ignore it, as it is only updated
- * by the RTC when initially set to a non-zero value.
- */
- jz_gettime(REG_RTC_RSR, &year, &mon, &mday, &hour, &min, &sec, &wday);
-
- year -= 2000;
-
- tm->tm_sec = sec;
- tm->tm_min = min;
- tm->tm_hour = hour;
- tm->tm_mday = mday;
- tm->tm_wday = wday;
- /* Don't use centry, but start from year 1970 */
- tm->tm_mon = mon;
- if (year <= 69)
- year += 100;
- tm->tm_year = year;
+ _localtime(REG_RTC_RSR, tm);
return 1;
}
int rtc_write_datetime(const struct tm *tm)
{
- unsigned int year, lval;
-
- year = tm->tm_year;
- /* Don't use centry, but start from year 1970 */
- if (year > 69)
- year -= 100;
- year += 2000;
-
- lval = jz_mktime(year, tm->tm_mon, tm->tm_mday, tm->tm_hour,
- tm->tm_min, tm->tm_sec);
+ time_t val = mktime((struct tm*)tm);
__cpm_start_rtc();
udelay(100);
- REG_RTC_RSR = lval;
+ REG_RTC_RSR = val;
__cpm_stop_rtc();
-
- return 0;
-}
-#if 0
-void get_rtc_alm_time(struct rtc_time *alm_tm)
-{
- unsigned int sec,mon,mday,wday,year,hour,min;
- unsigned int lval;
- unsigned long flags;
- /*
- * Only the values that we read from the RTC are set. That
- * means only tm_hour, tm_min, and tm_sec.
- */
- lval = REG_RTC_RSAR;
- jz_gettime(lval, &year, &mon, &mday, &hour, &min, &sec, &wday);
-
- alm_tm->tm_sec = sec;
- alm_tm->tm_min = min;
- alm_tm->tm_hour = hour;
-}
-
-
-int rtc_ioctl(unsigned int cmd,struct rtc_time *val,unsigned int epo)
-{
- struct rtc_time wtime;
- switch (cmd) {
- case RTC_ALM_READ: /* Read the present alarm time */
- /*
- * This returns a struct rtc_time. Reading >= 0xc0
- * means "don't care" or "match all". Only the tm_hour,
- * tm_min, and tm_sec values are filled in.
- */
- get_rtc_alm_time(val);
- break;
- case RTC_ALM_SET: /* Store a time into the alarm */
- {
- unsigned char ahrs, amin, asec;
- unsigned int sec,mon,mday,wday,year,hour,min;
- unsigned int lval;
- unsigned long flags;
- struct rtc_time alm_tm;
-
- alm_tm = *val;
- ahrs = alm_tm.tm_hour;
- amin = alm_tm.tm_min;
- asec = alm_tm.tm_sec;
-
-
-
- if (ahrs >= 24)
- return -1;
-
- if (amin >= 60)
- return -1;
-
- if (asec >= 60)
- return -1;
-
- flags = spin_lock_irqsave();
- lval = REG_RTC_RSR;
- jz_gettime(lval, &year, &mon, &mday, &hour, &min, &sec, &wday);
- hour = ahrs;
- min = amin;
- sec = asec;
- lval = jz_mktime(year, mon, mday, hour, min, sec);
- REG_RTC_RSAR = lval;
- spin_unlock_irqrestore(flags);
- break;
- }
- case RTC_RD_TIME: /* Read the time/date from RTC */
- get_rtc_time(val);
- break;
- case RTC_SET_TIME: /* Set the RTC */
- {
- struct rtc_time rtc_tm;
- unsigned int mon, day, hrs, min, sec, leap_yr, date;
- unsigned int yrs;
- unsigned int lval;
- unsigned long flags;
-
- rtc_tm = *val;
- yrs = rtc_tm.tm_year;// + 1900;
- mon = rtc_tm.tm_mon + 1; /* tm_mon starts at zero */
- day = rtc_tm.tm_wday;
- date = rtc_tm.tm_mday;
- hrs = rtc_tm.tm_hour;
- min = rtc_tm.tm_min;
- sec = rtc_tm.tm_sec;
-
-
- if (yrs < 1970)
- return -EINVAL;
- leap_yr = ((!(yrs % 4) && (yrs % 100)) || !(yrs % 400));
-
- if ((mon > 12) || (date == 0))
- return -EINVAL;
-
- if (date > (days_in_mo[mon] + ((mon == 2) && leap_yr)))
- return -EINVAL;
-
- if ((hrs >= 24) || (min >= 60) || (sec >= 60))
- return -EINVAL;
-
- if ((yrs -= epoch) > 255) /* They are unsigned */
- return -EINVAL;
-
- flags = spin_lock_irqsave();
- /* These limits and adjustments are independant of
- * whether the chip is in binary mode or not.
- */
-
- if (yrs > 169) {
- spin_unlock_irqrestore(flags);
- return -EINVAL;
- }
-
- yrs += epoch;
- lval = jz_mktime(yrs, mon, date, hrs, min, sec);
- REG_RTC_RSR = lval;
- /* FIXME: maybe we need to write alarm register here. */
- spin_unlock_irqrestore(flags);
-
- return 0;
- }
- break;
- case RTC_EPOCH_READ: /* Read the epoch. */
- epo = epoch;
- return 0;
- case RTC_EPOCH_SET: /* Set the epoch. */
- /*
- * There were no RTC clocks before 1900.
- */
- if (epo < 1900)
- return -EINVAL;
-
- epoch = epo;
- return 0;
- default:
- return -EINVAL;
- }
- return -EINVAL;
+ return 0;
}
-#endif
void rtc_init(void)
{