diff options
author | Maurus Cuelenaere <mcuelenaere@gmail.com> | 2010-01-08 14:52:15 +0000 |
---|---|---|
committer | Maurus Cuelenaere <mcuelenaere@gmail.com> | 2010-01-08 14:52:15 +0000 |
commit | 537bea5faca5b77ae325da1fe4306aaa9b6bfa60 (patch) | |
tree | ea26687860a3e5467938da4f148e4ea5b248e872 /firmware/drivers/rtc | |
parent | 13ef677d152b1de0f6d4c581770a8daa173cb9e4 (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.c | 291 |
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) { |