add the correct input file to makeindex call
[Rockbox.git] / firmware / drivers / rtc.c
blobc911dabbb1103381d9576a87d8215430c42361f5
1 /***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
10 * Copyright (C) 2002 by Linus Nielsen Feltzing, Uwe Freese, Laurent Baum
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.
15 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
16 * KIND, either express or implied.
18 ****************************************************************************/
19 #include "config.h"
20 #ifdef CONFIG_RTC
21 #include "i2c.h"
22 #include "rtc.h"
23 #include "kernel.h"
24 #include "system.h"
25 #include "pcf50606.h"
26 #include "pcf50605.h"
27 #if CONFIG_RTC == RTC_E8564
28 #include "i2c-pp5020.h"
29 #endif /*CONFIG_RTC == RTC_E8564*/
30 #include <stdbool.h>
32 #define RTC_ADR 0xd0
33 #define RTC_DEV_WRITE (RTC_ADR | 0x00)
34 #define RTC_DEV_READ (RTC_ADR | 0x01)
36 #if CONFIG_RTC == RTC_E8564
37 void rtc_init(void)
41 int rtc_read_datetime(unsigned char* buf)
43 unsigned char tmp;
44 int read;
46 /*RTC_E8564's slave address is 0x51*/
47 read = i2c_readbytes(0x51,0x02,7,buf);
49 /* swap wday and mday to be compatible with
50 * get_time() from firmware/common/timefuncs.c */
51 tmp=buf[3];
52 buf[3]=buf[4];
53 buf[4]=tmp;
55 return read;
58 int rtc_write_datetime(unsigned char* buf)
60 int i;
61 unsigned char tmp;
63 /* swap wday and mday to be compatible with
64 * set_time() in firmware/common/timefuncs.c */
65 tmp=buf[3];
66 buf[3]=buf[4];
67 buf[4]=tmp;
69 for (i=0;i<7;i++){
70 ipod_i2c_send(0x51, 0x02+i,buf[i]);
72 return 1;
75 #elif CONFIG_RTC == RTC_PCF50605
76 void rtc_init(void)
80 int rtc_read_datetime(unsigned char* buf)
82 return pcf50605_read_multiple(0x0a, buf, 7);
85 int rtc_write_datetime(unsigned char* buf)
87 int i;
89 for (i=0;i<7;i++) {
90 pcf50605_write(0x0a+i, buf[i]);
93 return 1;
95 #elif CONFIG_RTC == RTC_PCF50606
96 void rtc_init(void)
100 int rtc_read_datetime(unsigned char* buf) {
101 int rc;
102 int oldlevel = set_irq_level(HIGHEST_IRQ_LEVEL);
104 rc = pcf50606_read_multiple(0x0a, buf, 7);
106 set_irq_level(oldlevel);
107 return rc;
110 int rtc_write_datetime(unsigned char* buf) {
111 int rc;
112 int oldlevel = set_irq_level(HIGHEST_IRQ_LEVEL);
114 rc = pcf50606_write_multiple(0x0a, buf, 7);
116 set_irq_level(oldlevel);
118 return rc;
121 #else
122 void rtc_init(void)
124 unsigned char data;
126 #ifdef HAVE_ALARM_MOD
127 /* Check + save alarm bit first, before the power thread starts watching */
128 rtc_check_alarm_started(false);
129 #endif
131 rtc_write(0x13, 0x10); /* 32 kHz square wave */
133 /* Clear the Stop bit if it is set */
134 data = rtc_read(0x01);
135 if(data & 0x80)
136 rtc_write(0x01, 0x00);
138 /* Clear the HT bit if it is set */
139 data = rtc_read(0x0c);
141 if(data & 0x40)
143 data &= ~0x40;
144 rtc_write(0x0c,data);
147 #ifdef HAVE_ALARM_MOD
149 /* Clear Trec bit, write-protecting the RTC for 200ms when shutting off */
150 /* without this, the alarm won't work! */
152 data = rtc_read(0x04);
153 if (data & 0x80)
155 data &= ~0x80;
156 rtc_write(0x04, data);
159 /* Also, make sure that the OUT bit in register 8 is 1,
160 otherwise the player can't be turned off. */
161 rtc_write(8, rtc_read(8) | 0x80);
163 #endif
166 #ifdef HAVE_ALARM_MOD
168 /* check whether the unit has been started by the RTC alarm function */
169 /* (check for AF, which => started using wakeup alarm) */
170 bool rtc_check_alarm_started(bool release_alarm)
172 static bool alarm_state, run_before;
173 bool rc;
175 if (run_before) {
176 rc = alarm_state;
177 alarm_state &= ~release_alarm;
178 } else {
179 /* This call resets AF, so we store the state for later recall */
180 rc = alarm_state = rtc_check_alarm_flag();
181 run_before = true;
184 return rc;
187 * Checks the AL register. This call resets AL once read.
189 * We're only interested if ABE is set. AL is still raised regardless
190 * even if the unit is off when the alarm occurs.
192 bool rtc_check_alarm_flag(void)
194 return ( ( (rtc_read(0x0f) & 0x40) != 0) &&
195 (rtc_read(0x0a) & 0x20) );
198 /* set alarm time registers to the given time (repeat once per day) */
199 void rtc_set_alarm(int h, int m)
201 unsigned char data;
203 /* for daily alarm, RPT5=RPT4=on, RPT1=RPT2=RPT3=off */
205 rtc_write(0x0e, 0x00); /* seconds 0 and RTP1 */
206 rtc_write(0x0d, ((m / 10) << 4) | (m % 10)); /* minutes and RPT2 */
207 rtc_write(0x0c, ((h / 10) << 4) | (h % 10)); /* hour and RPT3 */
208 rtc_write(0x0b, 0xc1); /* set date 01 and RPT4 and RTP5 */
210 /* set month to 1, if it's invalid, the rtc does an alarm every second instead */
211 data = rtc_read(0x0a);
212 data &= 0xe0;
213 data |= 0x01;
214 rtc_write(0x0a, data);
217 /* read out the current alarm time */
218 void rtc_get_alarm(int *h, int *m)
220 unsigned char data;
222 data = rtc_read(0x0c);
223 *h = ((data & 0x30) >> 4) * 10 + (data & 0x0f);
225 data = rtc_read(0x0d);
226 *m = ((data & 0x70) >> 4) * 10 + (data & 0x0f);
229 /* turn alarm on or off by setting the alarm flag enable */
230 /* the alarm is automatically disabled when the RTC gets Vcc power at startup */
231 /* avoid that an alarm occurs when the device is on because this locks the ON key forever */
232 /* returns false if alarm was set and alarm flag (output) is off */
233 /* returns true if alarm flag went on, which would lock the device, so the alarm was disabled again */
234 bool rtc_enable_alarm(bool enable)
236 unsigned char data = rtc_read(0x0a);
237 if (enable)
239 data |= 0xa0; /* turn bit d7=AFE and d5=ABE on */
241 else
242 data &= 0x5f; /* turn bit d7=AFE and d5=ABE off */
243 rtc_write(0x0a, data);
245 /* check if alarm flag AF is off (as it should be) */
246 /* in some cases enabling the alarm results in an activated AF flag */
247 /* this should not happen, but it does */
248 /* if you know why, tell me! */
249 /* for now, we try again forever in this case */
250 while (rtc_check_alarm_flag()) /* on */
252 data &= 0x5f; /* turn bit d7=AFE and d5=ABE off */
253 rtc_write(0x0a, data);
254 sleep(HZ / 10);
255 rtc_check_alarm_flag();
256 data |= 0xa0; /* turn bit d7=AFE and d5=ABE on */
257 rtc_write(0x0a, data);
260 return false; /* all ok */
263 #endif /* HAVE_ALARM_MOD */
265 int rtc_write(unsigned char address, unsigned char value)
267 int ret = 0;
268 unsigned char buf[2];
270 i2c_begin();
272 buf[0] = address;
273 buf[1] = value;
275 /* send run command */
276 if (i2c_write(RTC_DEV_WRITE,buf,2))
278 ret = -1;
281 i2c_end();
282 return ret;
285 int rtc_read(unsigned char address)
287 int value = -1;
288 unsigned char buf[1];
290 i2c_begin();
292 buf[0] = address;
294 /* send read command */
295 if (i2c_write(RTC_DEV_READ,buf,1) >= 0)
297 i2c_start();
298 i2c_outb(RTC_DEV_READ);
299 if (i2c_getack())
301 value = i2c_inb(1);
305 i2c_stop();
307 i2c_end();
308 return value;
311 int rtc_read_multiple(unsigned char address, unsigned char *buf, int numbytes)
313 int ret = 0;
314 unsigned char obuf[1];
315 int i;
317 i2c_begin();
319 obuf[0] = address;
321 /* send read command */
322 if (i2c_write(RTC_DEV_READ, obuf, 1) >= 0)
324 i2c_start();
325 i2c_outb(RTC_DEV_READ);
326 if (i2c_getack())
328 for(i = 0;i < numbytes-1;i++)
329 buf[i] = i2c_inb(0);
331 buf[i] = i2c_inb(1);
333 else
335 ret = -1;
339 i2c_stop();
341 i2c_end();
342 return ret;
345 int rtc_read_datetime(unsigned char* buf) {
346 int rc;
348 rc = rtc_read_multiple(1, buf, 7);
350 /* Adjust weekday */
351 if(buf[3] == 7)
352 buf[3]=0;
354 return rc;
357 int rtc_write_datetime(unsigned char* buf) {
358 int i;
359 int rc = 0;
361 /* Adjust weekday */
362 if(buf[3] == 0)
363 buf[3] = 7;
365 for (i = 0; i < 7 ; i++)
367 rc |= rtc_write(i+1, buf[i]);
369 rc |= rtc_write(8, 0x80); /* Out=1, calibration = 0 */
371 return rc;
373 #endif /* CONFIG_RTC == RTC_PCF50606 */
375 #endif /* CONFIG_RTC */