summaryrefslogtreecommitdiff
path: root/firmware/drivers/rtc/rtc_jz4760.c
diff options
context:
space:
mode:
Diffstat (limited to 'firmware/drivers/rtc/rtc_jz4760.c')
-rw-r--r--firmware/drivers/rtc/rtc_jz4760.c124
1 files changed, 124 insertions, 0 deletions
diff --git a/firmware/drivers/rtc/rtc_jz4760.c b/firmware/drivers/rtc/rtc_jz4760.c
new file mode 100644
index 0000000000..cda618d617
--- /dev/null
+++ b/firmware/drivers/rtc/rtc_jz4760.c
@@ -0,0 +1,124 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * Copyright (C) 2016 by Roman Stolyarov
11 *
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.
16 *
17 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
18 * KIND, either express or implied.
19 *
20 ****************************************************************************/
21
22/*
23 * Real Time Clock interface for Jz4760.
24 *
25 */
26
27#include "config.h"
28#include "cpu.h"
29#include "rtc.h"
30#include "timefuncs.h"
31#include "logf.h"
32
33#define RTC_FREQ_DIVIDER (32768 - 1)
34
35/* Stolen from dietlibc-0.29/libugly/gmtime_r.c (GPLv2) */
36#define SPD (24*60*60)
37#define ISLEAP(year) (!(year%4) && ((year%100) || !(year%400)))
38static void _localtime(const time_t t, struct tm *r)
39{
40 time_t i;
41 register time_t work = t % SPD;
42 static int m_to_d[12] = /* This could be shared with mktime() */
43 {0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334};
44
45 r->tm_sec = work % 60;
46 work /= 60;
47 r->tm_min = work % 60;
48 r->tm_hour = work / 60;
49 work = t / SPD;
50 r->tm_wday = (4 + work) % 7;
51
52 for (i=1970; ; ++i)
53 {
54 register time_t k = ISLEAP(i) ? 366 : 365;
55
56 if (work >= k)
57 work -= k;
58 else
59 break;
60 }
61
62 r->tm_year = i - 1900;
63 r->tm_yday = work;
64
65 r->tm_mday = 1;
66 if (ISLEAP(i) && (work>58))
67 {
68 if (work==59)
69 r->tm_mday=2; /* 29.2. */
70
71 work-=1;
72 }
73
74 for (i=11; i && (m_to_d[i] > work); --i);
75 r->tm_mon = i;
76 r->tm_mday += work - m_to_d[i];
77}
78
79int rtc_read_datetime(struct tm *tm)
80{
81 _localtime(rtc_read_reg(RTC_RTCSR), tm);
82
83 return 1;
84}
85
86int rtc_write_datetime(const struct tm *tm)
87{
88 rtc_write_reg(RTC_RTCSR, mktime((struct tm*)tm));
89
90 return 0;
91}
92
93void rtc_init(void)
94{
95 unsigned int cfc,hspr,rgr_1hz;
96
97 __cpm_select_rtcclk_rtc();
98
99 cfc = HSPR_RTCV;
100 hspr = rtc_read_reg(RTC_HSPR);
101 rgr_1hz = rtc_read_reg(RTC_RTCGR) & RTCGR_NC1HZ_MASK;
102
103 if((hspr != cfc) || (rgr_1hz != RTC_FREQ_DIVIDER))
104 {
105 /* We are powered on for the first time !!! */
106
107 /* Set 32768 rtc clocks per seconds */
108 rtc_write_reg(RTC_RTCGR, RTC_FREQ_DIVIDER);
109
110 /* Set minimum wakeup_n pin low-level assertion time for wakeup: 100ms */
111 rtc_write_reg(RTC_HWFCR, HWFCR_WAIT_TIME(100));
112 rtc_write_reg(RTC_HRCR, HRCR_WAIT_TIME(60));
113
114 /* Reset to the default time */
115 rtc_write_reg(RTC_RTCSR, 946681200); /* 01/01/2000 */
116
117 /* start rtc */
118 rtc_write_reg(RTC_RTCCR, RTCCR_RTCE);
119 rtc_write_reg(RTC_HSPR, cfc);
120 }
121
122 /* clear all rtc flags */
123 rtc_write_reg(RTC_HWRSR, 0);
124}