diff options
Diffstat (limited to 'rtc')
-rw-r--r-- | rtc/Makefile | 4 | ||||
-rw-r--r-- | rtc/bf533_rtc.c | 145 | ||||
-rw-r--r-- | rtc/ds1374.c | 253 | ||||
-rw-r--r-- | rtc/rs5c372.c | 4 |
4 files changed, 402 insertions, 4 deletions
diff --git a/rtc/Makefile b/rtc/Makefile index 4ceac76..2c5d099 100644 --- a/rtc/Makefile +++ b/rtc/Makefile @@ -28,8 +28,8 @@ include $(TOPDIR)/config.mk LIB = librtc.a OBJS = date.o \ - ds12887.o ds1302.o ds1306.o ds1307.o ds1337.o \ - ds1556.o ds164x.o ds174x.o \ + bf533_rtc.o ds12887.o ds1302.o ds1306.o ds1307.o \ + ds1337.o ds1374.o ds1556.o ds164x.o ds174x.o \ m41t11.o max6900.o m48t35ax.o mc146818.o mk48t59.o \ mpc5xxx.o mpc8xx.o pcf8563.o s3c24x0_rtc.o rs5c372.o diff --git a/rtc/bf533_rtc.c b/rtc/bf533_rtc.c new file mode 100644 index 0000000..948be64 --- /dev/null +++ b/rtc/bf533_rtc.c @@ -0,0 +1,145 @@ +/* + * (C) Copyright 2001 + * Wolfgang Denk, DENX Software Engineering, wd@denx.de. + * + * See file CREDITS for list of people who contributed to this + * project. + * + * 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 program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + * Real Time Clock interface of ADI21535 (Blackfin) for uCLinux + * + * Copyright (C) 2003 Motorola Corporation. All rights reserved. + * Richard Xiao (A2590C@email.mot.com) + * + * Copyright (C) 1996 Paul Gortmaker + * + * + * Based on other minimal char device drivers, like Alan's + * watchdog, Ted's random, etc. etc. + * + * 1.07 Paul Gortmaker. + * 1.08 Miquel van Smoorenburg: disallow certain things on the + * DEC Alpha as the CMOS clock is also used for other things. + * 1.09 Nikita Schmidt: epoch support and some Alpha cleanup. + * 1.09a Pete Zaitcev: Sun SPARC + * 1.09b Jeff Garzik: Modularize, init cleanup + * 1.09c Jeff Garzik: SMP cleanup + * 1.10 Paul Barton-Davis: add support for async I/O + * 1.10a Andrea Arcangeli: Alpha updates + * 1.10b Andrew Morton: SMP lock fix + * 1.10c Cesar Barros: SMP locking fixes and cleanup + * 1.10d Paul Gortmaker: delete paranoia check in rtc_exit + * 1.10e LG Soft India: Register access is different in BF533. + */ + +#include <common.h> +#include <command.h> +#include <rtc.h> + +#if defined(CONFIG_RTC_BF533) && (CONFIG_COMMANDS & CFG_CMD_DATE) + +#include <asm/blackfin.h> +#include <asm/cpu/bf533_rtc.h> + +void rtc_reset (void) +{ + return; /* nothing to do */ +} + +/* Wait for pending writes to complete */ +void wait_for_complete (void) +{ + while (!(*(volatile unsigned short *) RTC_ISTAT & 0x8000)) { + printf (""); + } + *(volatile unsigned short *) RTC_ISTAT = 0x8000; +} + +/* Enable the RTC prescaler enable register */ +void rtc_init () +{ + *(volatile unsigned short *) RTC_PREN = 0x1; + wait_for_complete (); +} + +/* Set the time. Get the time_in_secs which is the number of seconds since Jan 1970 and set the RTC registers + * based on this value. + */ +void rtc_set (struct rtc_time *tmp) +{ + unsigned long n_days_1970 = 0; + unsigned long n_secs_rem = 0; + unsigned long n_hrs = 0; + unsigned long n_mins = 0; + unsigned long n_secs = 0; + unsigned long time_in_secs; + + if (tmp == NULL) { + printf ("Error setting the date/time \n"); + return; + } + + time_in_secs = + mktime (tmp->tm_year, tmp->tm_mon, tmp->tm_mday, tmp->tm_hour, + tmp->tm_min, tmp->tm_sec); + + /* Compute no. of days since 1970 */ + n_days_1970 = (unsigned long) (time_in_secs / (NUM_SECS_IN_DAY)); + + /* From the remining secs, compute the hrs(0-23), mins(0-59) and secs(0-59) */ + n_secs_rem = (unsigned long) (time_in_secs % (NUM_SECS_IN_DAY)); + n_hrs = n_secs_rem / (NUM_SECS_IN_HOUR); + n_secs_rem = n_secs_rem % (NUM_SECS_IN_HOUR); + n_mins = n_secs_rem / (NUM_SECS_IN_MIN); + n_secs = n_secs_rem % (NUM_SECS_IN_MIN); + + /* Store the new time in the RTC_STAT register */ + *(volatile unsigned long *) RTC_STAT = + ((n_days_1970 << DAY_BITS_OFF) | (n_hrs << HOUR_BITS_OFF) | + (n_mins << MIN_BITS_OFF) | (n_secs << SEC_BITS_OFF)); + + wait_for_complete (); +} + +/* Read the time from the RTC_STAT. time_in_seconds is seconds since Jan 1970 */ +void rtc_get (struct rtc_time *tmp) +{ + unsigned long cur_rtc_stat = 0; + unsigned long time_in_sec; + unsigned long tm_sec = 0, tm_min = 0, tm_hour = 0, tm_day = 0; + + if (tmp == NULL) { + printf ("Error getting the date/time \n"); + return; + } + + /* Read the RTC_STAT register */ + cur_rtc_stat = *(volatile unsigned long *) RTC_STAT; + + /* Get the secs (0-59), mins (0-59), hrs (0-23) and the days since Jan 1970 */ + tm_sec = (cur_rtc_stat >> SEC_BITS_OFF) & 0x3f; + tm_min = (cur_rtc_stat >> MIN_BITS_OFF) & 0x3f; + tm_hour = (cur_rtc_stat >> HOUR_BITS_OFF) & 0x1f; + tm_day = (cur_rtc_stat >> DAY_BITS_OFF) & 0x7fff; + + /* Calculate the total number of seconds since Jan 1970 */ + time_in_sec = (tm_sec) + + MIN_TO_SECS (tm_min) + + HRS_TO_SECS (tm_hour) + + DAYS_TO_SECS (tm_day); + to_tm (time_in_sec, tmp); +} +#endif /* CONFIG_RTC_BF533 && CFG_CMD_DATE */ diff --git a/rtc/ds1374.c b/rtc/ds1374.c new file mode 100644 index 0000000..31f06e5 --- /dev/null +++ b/rtc/ds1374.c @@ -0,0 +1,253 @@ +/* + * (C) Copyright 2001, 2002, 2003 + * Wolfgang Denk, DENX Software Engineering, wd@denx.de. + * Keith Outwater, keith_outwater@mvis.com` + * Steven Scholz, steven.scholz@imc-berlin.de + * + * See file CREDITS for list of people who contributed to this + * project. + * + * 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 program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +/* + * Date & Time support (no alarms) for Dallas Semiconductor (now Maxim) + * DS1374 Real Time Clock (RTC). + * + * based on ds1337.c + */ + +#include <common.h> +#include <command.h> +#include <rtc.h> +#include <i2c.h> + +#if (defined(CONFIG_RTC_DS1374)) && (CONFIG_COMMANDS & CFG_CMD_DATE) + +/*---------------------------------------------------------------------*/ +#undef DEBUG_RTC +#define DEBUG_RTC + +#ifdef DEBUG_RTC +#define DEBUGR(fmt,args...) printf(fmt ,##args) +#else +#define DEBUGR(fmt,args...) +#endif +/*---------------------------------------------------------------------*/ + +#ifndef CFG_I2C_RTC_ADDR +# define CFG_I2C_RTC_ADDR 0x68 +#endif + +#if defined(CONFIG_RTC_DS1374) && (CFG_I2C_SPEED > 400000) +# error The DS1374 is specified up to 400kHz in fast mode! +#endif + +/* + * RTC register addresses + */ +#define RTC_TOD_CNT_BYTE0_ADDR 0x00 /* TimeOfDay */ +#define RTC_TOD_CNT_BYTE1_ADDR 0x01 +#define RTC_TOD_CNT_BYTE2_ADDR 0x02 +#define RTC_TOD_CNT_BYTE3_ADDR 0x03 + +#define RTC_WD_ALM_CNT_BYTE0_ADDR 0x04 +#define RTC_WD_ALM_CNT_BYTE1_ADDR 0x05 +#define RTC_WD_ALM_CNT_BYTE2_ADDR 0x06 + +#define RTC_CTL_ADDR 0x07 /* RTC-CoNTrol-register */ +#define RTC_SR_ADDR 0x08 /* RTC-StatusRegister */ +#define RTC_TCS_DS_ADDR 0x09 /* RTC-TrickleChargeSelect DiodeSelect-register */ + +#define RTC_CTL_BIT_AIE (1<<0) /* Bit 0 - Alarm Interrupt enable */ +#define RTC_CTL_BIT_RS1 (1<<1) /* Bit 1/2 - Rate Select square wave output */ +#define RTC_CTL_BIT_RS2 (1<<2) /* Bit 2/2 - Rate Select square wave output */ +#define RTC_CTL_BIT_WDSTR (1<<3) /* Bit 3 - Watchdog Reset Steering */ +#define RTC_CTL_BIT_BBSQW (1<<4) /* Bit 4 - Battery-Backed Square-Wave */ +#define RTC_CTL_BIT_WD_ALM (1<<5) /* Bit 5 - Watchdoc/Alarm Counter Select */ +#define RTC_CTL_BIT_WACE (1<<6) /* Bit 6 - Watchdog/Alarm Counter Enable WACE*/ +#define RTC_CTL_BIT_EN_OSC (1<<7) /* Bit 7 - Enable Oscilator */ + +#define RTC_SR_BIT_AF 0x01 /* Bit 0 = Alarm Flag */ +#define RTC_SR_BIT_OSF 0x80 /* Bit 7 - Osc Stop Flag */ + +typedef unsigned char boolean_t; + +#ifndef TRUE +#define TRUE ((boolean_t)(0==0)) +#endif +#ifndef FALSE +#define FALSE (!TRUE) +#endif + +const char RtcTodAddr[] = { + RTC_TOD_CNT_BYTE0_ADDR, + RTC_TOD_CNT_BYTE1_ADDR, + RTC_TOD_CNT_BYTE2_ADDR, + RTC_TOD_CNT_BYTE3_ADDR +}; + +static uchar rtc_read (uchar reg); +static void rtc_write (uchar reg, uchar val, boolean_t set); +static void rtc_write_raw (uchar reg, uchar val); + +/* + * Get the current time from the RTC + */ +void rtc_get (struct rtc_time *tm){ + + unsigned long time1, time2; + unsigned int limit; + unsigned char tmp; + unsigned int i; + + /* + * Since the reads are being performed one byte at a time, + * there is a chance that a carry will occur during the read. + * To detect this, 2 reads are performed and compared. + */ + limit = 10; + do { + i = 4; + time1 = 0; + while (i--) { + tmp = rtc_read(RtcTodAddr[i]); + time1 = (time1 << 8) | (tmp & 0xff); + } + + i = 4; + time2 = 0; + while (i--) { + tmp = rtc_read(RtcTodAddr[i]); + time2 = (time2 << 8) | (tmp & 0xff); + } + } while ((time1 != time2) && limit--); + + if (time1 != time2) { + printf("can't get consistent time from rtc chip\n"); + } + + DEBUGR ("Get RTC s since 1.1.1970: %d\n", time1); + + to_tm(time1, tm); /* To Gregorian Date */ + + if (rtc_read(RTC_SR_ADDR) & RTC_SR_BIT_OSF) + printf ("### Warning: RTC oscillator has stopped\n"); + + DEBUGR ("Get DATE: %4d-%02d-%02d (wday=%d) TIME: %2d:%02d:%02d\n", + tm->tm_year, tm->tm_mon, tm->tm_mday, tm->tm_wday, + tm->tm_hour, tm->tm_min, tm->tm_sec); +} + +/* + * Set the RTC + */ +void rtc_set (struct rtc_time *tmp){ + + unsigned long time; + unsigned i; + + DEBUGR ("Set DATE: %4d-%02d-%02d (wday=%d) TIME: %2d:%02d:%02d\n", + tmp->tm_year, tmp->tm_mon, tmp->tm_mday, tmp->tm_wday, + tmp->tm_hour, tmp->tm_min, tmp->tm_sec); + + if (tmp->tm_year < 1970 || tmp->tm_year > 2069) + printf("WARNING: year should be between 1970 and 2069!\n"); + + time = mktime(tmp->tm_year, tmp->tm_mon, + tmp->tm_mday, tmp->tm_hour, + tmp->tm_min, tmp->tm_sec); + + DEBUGR ("Set RTC s since 1.1.1970: %d (0x%02x)\n", time, time); + + /* write to RTC_TOD_CNT_BYTEn_ADDR */ + for (i = 0; i <= 3; i++) { + rtc_write_raw(RtcTodAddr[i], (unsigned char)(time & 0xff)); + time = time >> 8; + } + + /* Start clock */ + rtc_write(RTC_CTL_ADDR, RTC_CTL_BIT_EN_OSC, FALSE); +} + +/* + * Reset the RTC. We setting the date back to 1970-01-01. + * We also enable the oscillator output on the SQW/OUT pin and program + * it for 32,768 Hz output. Note that according to the datasheet, turning + * on the square wave output increases the current drain on the backup + * battery to something between 480nA and 800nA. + */ +void rtc_reset (void){ + + struct rtc_time tmp; + + /* clear status flags */ + rtc_write (RTC_SR_ADDR, (RTC_SR_BIT_AF|RTC_SR_BIT_OSF), FALSE); /* clearing OSF and AF */ + + /* Initialise DS1374 oriented to MPC8349E-ADS */ + rtc_write (RTC_CTL_ADDR, (RTC_CTL_BIT_EN_OSC + |RTC_CTL_BIT_WACE + |RTC_CTL_BIT_AIE), FALSE);/* start osc, disable WACE, clear AIE + - set to 0 */ + rtc_write (RTC_CTL_ADDR, (RTC_CTL_BIT_WD_ALM + |RTC_CTL_BIT_WDSTR + |RTC_CTL_BIT_RS1 + |RTC_CTL_BIT_RS2 + |RTC_CTL_BIT_BBSQW), TRUE);/* disable WD/ALM, WDSTR set to INT-pin, + set BBSQW and SQW to 32k + - set to 1 */ + tmp.tm_year = 1970; + tmp.tm_mon = 1; + tmp.tm_mday= 1; + tmp.tm_hour = 0; + tmp.tm_min = 0; + tmp.tm_sec = 0; + + rtc_set(&tmp); + + printf("RTC: %4d-%02d-%02d %2d:%02d:%02d UTC\n", + tmp.tm_year, tmp.tm_mon, tmp.tm_mday, + tmp.tm_hour, tmp.tm_min, tmp.tm_sec); + + rtc_write(RTC_WD_ALM_CNT_BYTE2_ADDR,0xAC, TRUE); + rtc_write(RTC_WD_ALM_CNT_BYTE1_ADDR,0xDE, TRUE); + rtc_write(RTC_WD_ALM_CNT_BYTE2_ADDR,0xAD, TRUE); +} + +/* + * Helper functions + */ +static uchar rtc_read (uchar reg) +{ + return (i2c_reg_read (CFG_I2C_RTC_ADDR, reg)); +} + +static void rtc_write (uchar reg, uchar val, boolean_t set) +{ + if (set == TRUE) { + val |= i2c_reg_read (CFG_I2C_RTC_ADDR, reg); + i2c_reg_write (CFG_I2C_RTC_ADDR, reg, val); + } else { + val = i2c_reg_read (CFG_I2C_RTC_ADDR, reg) & ~val; + i2c_reg_write (CFG_I2C_RTC_ADDR, reg, val); + } +} + +static void rtc_write_raw (uchar reg, uchar val) +{ + i2c_reg_write (CFG_I2C_RTC_ADDR, reg, val); +} +#endif /* (CONFIG_RTC_DS1374) && (CFG_COMMANDS & CFG_CMD_DATE) */ diff --git a/rtc/rs5c372.c b/rtc/rs5c372.c index 87f38c4..b56808b 100644 --- a/rtc/rs5c372.c +++ b/rtc/rs5c372.c @@ -73,7 +73,7 @@ static unsigned bcd2bin (uchar c); static int setup_done = 0; static int -rs5c372_readram(char *buf, int len) +rs5c372_readram(unsigned char *buf, int len) { int ret; @@ -128,7 +128,7 @@ rs5c372_enable(void) } static void -rs5c372_convert_to_time(struct rtc_time *dt, char *buf) +rs5c372_convert_to_time(struct rtc_time *dt, unsigned char *buf) { /* buf[0] is register 15 */ dt->tm_sec = bcd2bin(buf[1]); |