summaryrefslogtreecommitdiff
path: root/firmware
diff options
context:
space:
mode:
authorMichael Sevakis <jethead71@rockbox.org>2008-04-24 09:22:39 +0000
committerMichael Sevakis <jethead71@rockbox.org>2008-04-24 09:22:39 +0000
commitac387d4d5cb7b71fc5d3b566988b55020b3d3c51 (patch)
tree0864cd8d317898fc0d7339985119b93187dbf42c /firmware
parent5f3356b942a23e8dd0907b416848439f1445cb17 (diff)
downloadrockbox-ac387d4d5cb7b71fc5d3b566988b55020b3d3c51.tar.gz
rockbox-ac387d4d5cb7b71fc5d3b566988b55020b3d3c51.zip
Add a PMIC-based RTC driver for Gigabeat S.
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@17236 a1c6a512-1295-4272-9138-f99709370657
Diffstat (limited to 'firmware')
-rw-r--r--firmware/SOURCES2
-rw-r--r--firmware/drivers/rtc/rtc_mc13783.c238
-rw-r--r--firmware/export/config-gigabeat-s.h2
-rw-r--r--firmware/export/config.h1
4 files changed, 242 insertions, 1 deletions
diff --git a/firmware/SOURCES b/firmware/SOURCES
index bf4fb86af4..0acfdd5bf9 100644
--- a/firmware/SOURCES
+++ b/firmware/SOURCES
@@ -149,6 +149,8 @@ drivers/rtc/rtc_as3514.c
149drivers/rtc/rtc_rx5x348ab.c 149drivers/rtc/rtc_rx5x348ab.c
150#elif (CONFIG_RTC == RTC_MR100) 150#elif (CONFIG_RTC == RTC_MR100)
151drivers/rtc/rtc_mr100.c 151drivers/rtc/rtc_mr100.c
152#elif (CONFIG_RTC == RTC_MC13783)
153drivers/rtc/rtc_mc13783.c
152#endif /* (CONFIG_RTC == RTC_) */ 154#endif /* (CONFIG_RTC == RTC_) */
153#endif /* SIMULATOR */ 155#endif /* SIMULATOR */
154 156
diff --git a/firmware/drivers/rtc/rtc_mc13783.c b/firmware/drivers/rtc/rtc_mc13783.c
new file mode 100644
index 0000000000..2494e5ece5
--- /dev/null
+++ b/firmware/drivers/rtc/rtc_mc13783.c
@@ -0,0 +1,238 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * Copyright (C) 2008 by Michael Sevakis
11 *
12 * All files in this archive are subject to the GNU General Public License.
13 * See the file COPYING in the source tree root for full license agreement.
14 *
15 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
16 * KIND, either express or implied.
17 *
18 ****************************************************************************/
19#include "config.h"
20#include "system.h"
21#include "rtc.h"
22#include "mc13783.h"
23
24/* NOTE: Defined the base to be original firmware compatible if needed -
25 * ie. the day and year as it would interpret a DAY register value of zero. */
26
27/* Days passed since midnight 01 Jan, 1601 to midnight on the base date. */
28#ifdef TOSHIBA_GIGABEAT_S
29 /* Gigabeat S seems to be 1 day behind the ususual - this will
30 * make the RTC match file dates created by retailos. */
31 #define RTC_BASE_DAY_COUNT 138425
32 #define RTC_BASE_MONTH 12
33 #define RTC_BASE_DAY 31
34 #define RTC_BASE_YEAR 1979
35#elif 1
36 #define RTC_BASE_DAY_COUNT 138426
37 #define RTC_BASE_MONTH 1
38 #define RTC_BASE_DAY 1
39 #define RTC_BASE_YEAR 1980
40#else
41 #define RTC_BASE_DAY_COUNT 134774
42 #define RTC_BASE_MONTH 1
43 #define RTC_BASE_DAY 1
44 #define RTC_BASE_YEAR 1970
45#endif
46
47enum rtc_buffer_field_indexes
48{
49 RTC_I_SECONDS = 0,
50 RTC_I_MINUTES,
51 RTC_I_HOURS,
52 RTC_I_WEEKDAY,
53 RTC_I_DAY,
54 RTC_I_MONTH,
55 RTC_I_YEAR,
56 RTC_NUM_FIELDS,
57};
58
59enum rtc_registers_indexes
60{
61 RTC_REG_TIME = 0,
62 RTC_REG_DAY,
63 RTC_REG_TIME2,
64 RTC_NUM_REGS,
65};
66
67static const unsigned char rtc_registers[RTC_NUM_REGS] =
68{
69 [RTC_REG_TIME] = MC13783_RTC_TIME,
70 [RTC_REG_DAY] = MC13783_RTC_DAY,
71 [RTC_REG_TIME2] = MC13783_RTC_TIME,
72};
73
74static const unsigned char month_table[2][12] =
75{
76 { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 },
77 { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 },
78};
79
80static inline void to_bcd(unsigned char *bcd, const unsigned char *buf,
81 int len)
82{
83 while (len-- > 0)
84 {
85 unsigned char d = *buf++;
86 *bcd++ = ((d / 10) << 4) | (d % 10);
87 }
88}
89
90static inline void from_bcd(unsigned char *buf, const unsigned char *bcd,
91 int len)
92{
93 while (len-- > 0)
94 {
95 unsigned char d = *bcd++;
96 *buf++ = ((d >> 4) & 0x0f) * 10 + (d & 0xf);
97 }
98}
99
100/* Get number of leaps since the reference date of 1601/01/01 */
101static int get_leap_count(int d)
102{
103 int lm = (d + 1) / 146097;
104 int lc = (d + 1 - lm) / 36524;
105 int ly = (d + 1 - lm + lc) / 1461;
106 return ly - lc + lm;
107}
108
109static int is_leap_year(int y)
110{
111 return (y % 4) == 0 && ((y % 100) != 0 || (y % 400) == 0) ? 1 : 0;
112}
113
114/** Public APIs **/
115void rtc_init(void)
116{
117 /* Nothing to do */
118}
119
120int rtc_read_datetime(unsigned char* buf)
121{
122 uint32_t regs[RTC_NUM_REGS];
123 int year, leap, month, day;
124
125 /* Read time, day, time - 2nd read of time should be the same or
126 * greater */
127 do
128 {
129 if (mc13783_read_regset(rtc_registers, regs,
130 RTC_NUM_REGS) < RTC_NUM_REGS)
131 {
132 /* Couldn't read registers */
133 return 0;
134 }
135 }
136 /* If TOD counter turned over - reread */
137 while (regs[RTC_REG_TIME2] < regs[RTC_REG_TIME]);
138
139 /* TOD: = 0 to 86399 */
140 buf[RTC_I_HOURS] = regs[RTC_REG_TIME] / 3600;
141 regs[RTC_REG_TIME] -= buf[RTC_I_HOURS]*3600;
142
143 buf[RTC_I_MINUTES] = regs[RTC_REG_TIME] / 60;
144 regs[RTC_REG_TIME] -= buf[RTC_I_MINUTES]*60;
145
146 buf[RTC_I_SECONDS] = regs[RTC_REG_TIME];
147
148 /* DAY: 0 to 32767 */
149 day = regs[RTC_REG_DAY] + RTC_BASE_DAY_COUNT;
150
151 /* Weekday */
152 buf[RTC_I_WEEKDAY] = (day + 1) % 7; /* 1601/01/01 = Monday */
153
154 /* Get number of leaps for today */
155 leap = get_leap_count(day);
156 year = (day - leap) / 365;
157
158 /* Get number of leaps for yesterday */
159 leap = get_leap_count(day - 1);
160
161 /* Get day number for year 0-364|365 */
162 day = day - leap - year * 365;
163
164 year += 1601;
165
166 /* Get the current month */
167 leap = is_leap_year(year);
168
169 for (month = 0; month < 12; month++)
170 {
171 int days = month_table[leap][month];
172
173 if (day < days)
174 break;
175
176 day -= days;
177 }
178
179 buf[RTC_I_DAY] = day + 1; /* 1 to 31 */
180 buf[RTC_I_MONTH] = month + 1; /* 1 to 12 */
181 buf[RTC_I_YEAR] = year % 100;
182
183 to_bcd(buf, buf, RTC_NUM_FIELDS);
184
185 return 7;
186}
187
188int rtc_write_datetime(unsigned char* buf)
189{
190 uint32_t regs[2];
191 unsigned char fld[RTC_NUM_FIELDS];
192 int year, leap, month, day, i, base_yearday;
193
194 from_bcd(fld, buf, RTC_NUM_FIELDS);
195
196 regs[RTC_REG_TIME] = fld[RTC_I_SECONDS] +
197 fld[RTC_I_MINUTES]*60 +
198 fld[RTC_I_HOURS]*3600;
199
200 year = fld[RTC_I_YEAR];
201
202 if (year < RTC_BASE_YEAR - 1900)
203 year += 2000;
204 else
205 year += 1900;
206
207 /* Get number of leaps for day before base */
208 leap = get_leap_count(RTC_BASE_DAY_COUNT - 1);
209
210 /* Get day number for base year 0-364|365 */
211 base_yearday = RTC_BASE_DAY_COUNT - leap -
212 (RTC_BASE_YEAR - 1601) * 365;
213
214 /* Get the number of days elapsed from reference */
215 for (i = RTC_BASE_YEAR, day = 0; i < year; i++)
216 {
217 day += is_leap_year(i) ? 366 : 365;
218 }
219
220 /* Find the number of days passed this year up to the 1st of the
221 * month. */
222 leap = is_leap_year(year);
223 month = fld[RTC_I_MONTH] - 1;
224
225 for (i = 0; i < month; i++)
226 {
227 day += month_table[leap][i];
228 }
229
230 regs[RTC_REG_DAY] = day + fld[RTC_I_DAY] - 1 - base_yearday;
231
232 if (mc13783_write_regset(rtc_registers, regs, 2) == 2)
233 {
234 return RTC_NUM_FIELDS;
235 }
236
237 return 0;
238}
diff --git a/firmware/export/config-gigabeat-s.h b/firmware/export/config-gigabeat-s.h
index bc70956ced..6eb57b219c 100644
--- a/firmware/export/config-gigabeat-s.h
+++ b/firmware/export/config-gigabeat-s.h
@@ -43,7 +43,7 @@
43#define CONFIG_CODEC SWCODEC 43#define CONFIG_CODEC SWCODEC
44 44
45/* define this if you have a real-time clock */ 45/* define this if you have a real-time clock */
46//#define CONFIG_RTC RTC_IMX31L 46#define CONFIG_RTC RTC_MC13783
47 47
48/* Define this for LCD backlight available */ 48/* Define this for LCD backlight available */
49#define HAVE_BACKLIGHT 49#define HAVE_BACKLIGHT
diff --git a/firmware/export/config.h b/firmware/export/config.h
index c108171d37..e502043844 100644
--- a/firmware/export/config.h
+++ b/firmware/export/config.h
@@ -165,6 +165,7 @@
165#define RTC_TCC77X 10 165#define RTC_TCC77X 10
166#define RTC_TCC780X 11 166#define RTC_TCC780X 11
167#define RTC_MR100 12 167#define RTC_MR100 12
168#define RTC_MC13783 13 /* Freescale MC13783 PMIC */
168 169
169/* USB On-the-go */ 170/* USB On-the-go */
170#define USBOTG_ISP1362 1362 /* iriver H300 */ 171#define USBOTG_ISP1362 1362 /* iriver H300 */