/*************************************************************************** * __________ __ ___. * Open \______ \ ____ ____ | | _\_ |__ _______ ___ * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ * \/ \/ \/ \/ \/ * $Id$ * * Copyright (C) 2002 by Linus Nielsen Feltzing, Uwe Freese, Laurent Baum, * Przemyslaw Holubowski * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY * KIND, either express or implied. * ****************************************************************************/ #include "config.h" #include "i2c.h" #include "rtc.h" #include "kernel.h" #include "system.h" #include "i2c-pp.h" #include /* RTC registers */ #define RTC_CTRL1 0x00 #define RTC_CTRL2 0x01 #define RTC_ALARM_MINUTES 0x09 #define RTC_ALARM_HOURS 0x0A #define RTC_ALARM_DAY 0x0B #define RTC_ALARM_WDAY 0x0C #define RTC_TIMER_CTRL 0x0E #define RTC_TIMER 0x0F /* Control 2 register flags */ #define RTC_TIE 0x01 #define RTC_AIE 0x02 #define RTC_TF 0x04 #define RTC_AF 0x08 #define RTC_TI_TP 0x10 /* Alarm registers flags */ #define RTC_AE 0x80 /* Timer register flags */ #define RTC_TE 0x80 bool rtc_lock_alarm_clear=true; void rtc_init(void) { unsigned char tmp; int rv; /* initialize Control 1 register */ tmp = 0; pp_i2c_send(0x51, RTC_CTRL1,tmp); /* read value of the Control 2 register - we'll need it to preserve alarm and timer interrupt assertion flags */ rv = i2c_readbytes(0x51,RTC_CTRL2,1,&tmp); /* preserve alarm and timer interrupt flags */ tmp &= (RTC_TF | RTC_AF | RTC_TIE | RTC_AIE); pp_i2c_send(0x51, RTC_CTRL2,tmp); } int rtc_read_datetime(unsigned char* buf) { unsigned char tmp; int read; /*RTC_E8564's slave address is 0x51*/ read = i2c_readbytes(0x51,0x02,7,buf); /* swap wday and mday to be compatible with * get_time() from firmware/common/timefuncs.c */ tmp=buf[3]; buf[3]=buf[4]; buf[4]=tmp; return read; } int rtc_write_datetime(unsigned char* buf) { int i; unsigned char tmp; /* swap wday and mday to be compatible with * set_time() in firmware/common/timefuncs.c */ tmp=buf[3]; buf[3]=buf[4]; buf[4]=tmp; for (i=0;i<7;i++){ pp_i2c_send(0x51, 0x02+i,buf[i]); } return 1; } void rtc_set_alarm(int h, int m) { unsigned char buf[4]={0}; int rv=0; int i=0; /* clear alarm interrupt */ rv = i2c_readbytes(0x51,RTC_CTRL2,1,buf); buf[0] &= RTC_AF; pp_i2c_send(0x51, RTC_CTRL2,buf[0]); /* prepare new alarm */ if( m >= 0 ) buf[0] = (((m/10) << 4) | m%10); else /* ignore minutes comparison query */ buf[0] = RTC_AE; if( h >= 0 ) buf[1] = (((h/10) << 4) | h%10); else /* ignore hours comparison query */ buf[1] = RTC_AE; /* ignore day and wday */ buf[2] = RTC_AE; buf[3] = RTC_AE; /* write new alarm */ for(;i<4;i++) pp_i2c_send(0x51, RTC_ALARM_MINUTES+i,buf[i]); /* note: alarm is not enabled at the point */ } void rtc_get_alarm(int *h, int *m) { unsigned char buf[4]={0}; /* get alarm preset */ i2c_readbytes(0x51, RTC_ALARM_MINUTES,4,buf); *m = ((buf[0] >> 4) & 0x7)*10 + (buf[0] & 0x0f); *h = ((buf[1] >> 4) & 0x3)*10 + (buf[1] & 0x0f); } bool rtc_enable_alarm(bool enable) { unsigned char tmp=0; int rv=0; if(enable) { /* enable alarm interrupt */ rv = i2c_readbytes(0x51,RTC_CTRL2,1,&tmp); tmp |= RTC_AIE; tmp &= ~RTC_AF; pp_i2c_send(0x51, RTC_CTRL2,tmp); } else { /* disable alarm interrupt */ if(rtc_lock_alarm_clear) /* lock disabling alarm before it was checked whether or not the unit was started by RTC alarm */ return false; rv = i2c_readbytes(0x51,RTC_CTRL2,1,&tmp); tmp &= ~(RTC_AIE | RTC_AF); pp_i2c_send(0x51, RTC_CTRL2,tmp); } return false; } bool rtc_check_alarm_started(bool release_alarm) { static bool alarm_state, run_before = false; unsigned char tmp=0; bool started; int rv=0; if (run_before) { started = alarm_state; alarm_state &= ~release_alarm; } else { /* read Control 2 register which contains alarm flag */ rv = i2c_readbytes(0x51,RTC_CTRL2,1,&tmp); alarm_state = started = ( (tmp & RTC_AF) && (tmp & RTC_AIE) ); if(release_alarm && started) { rv = i2c_readbytes(0x51,RTC_CTRL2,1,&tmp); /* clear alarm interrupt enable and alarm flag */ tmp &= ~(RTC_AF | RTC_AIE); pp_i2c_send(0x51, RTC_CTRL2,tmp); } run_before = true; rtc_lock_alarm_clear = false; } return started; } bool rtc_check_alarm_flag(void) { unsigned char tmp=0; int rv=0; /* read Control 2 register which contains alarm flag */ rv = i2c_readbytes(0x51,RTC_CTRL2,1,&tmp); return (tmp & RTC_AF); }