diff options
author | Michael Sevakis <jethead71@rockbox.org> | 2008-04-24 09:22:39 +0000 |
---|---|---|
committer | Michael Sevakis <jethead71@rockbox.org> | 2008-04-24 09:22:39 +0000 |
commit | ac387d4d5cb7b71fc5d3b566988b55020b3d3c51 (patch) | |
tree | 0864cd8d317898fc0d7339985119b93187dbf42c | |
parent | 5f3356b942a23e8dd0907b416848439f1445cb17 (diff) | |
download | rockbox-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
-rw-r--r-- | firmware/SOURCES | 2 | ||||
-rw-r--r-- | firmware/drivers/rtc/rtc_mc13783.c | 238 | ||||
-rw-r--r-- | firmware/export/config-gigabeat-s.h | 2 | ||||
-rw-r--r-- | firmware/export/config.h | 1 |
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 | |||
149 | drivers/rtc/rtc_rx5x348ab.c | 149 | drivers/rtc/rtc_rx5x348ab.c |
150 | #elif (CONFIG_RTC == RTC_MR100) | 150 | #elif (CONFIG_RTC == RTC_MR100) |
151 | drivers/rtc/rtc_mr100.c | 151 | drivers/rtc/rtc_mr100.c |
152 | #elif (CONFIG_RTC == RTC_MC13783) | ||
153 | drivers/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 | |||
47 | enum 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 | |||
59 | enum rtc_registers_indexes | ||
60 | { | ||
61 | RTC_REG_TIME = 0, | ||
62 | RTC_REG_DAY, | ||
63 | RTC_REG_TIME2, | ||
64 | RTC_NUM_REGS, | ||
65 | }; | ||
66 | |||
67 | static 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 | |||
74 | static 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 | |||
80 | static 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 | |||
90 | static 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 */ | ||
101 | static 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 | |||
109 | static 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 **/ | ||
115 | void rtc_init(void) | ||
116 | { | ||
117 | /* Nothing to do */ | ||
118 | } | ||
119 | |||
120 | int 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 | |||
188 | int 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 */ |