From b65085130aed33584d95502c20317ad4379c1ca6 Mon Sep 17 00:00:00 2001 From: wdenk Date: Sun, 10 Oct 2004 18:03:33 +0000 Subject: Code Cleanup Patch by Gary Jennejohn, 04 Oct 2004: - fix I2C on at91rm9200 - add support for Ricoh RS5C372A RTC diff --git a/CHANGELOG b/CHANGELOG index acc800e..db8cc8b 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -2,6 +2,10 @@ Changes since U-Boot 1.1.1: ====================================================================== +* Patch by Gary Jennejohn, 04 Oct 2004: + - fix I2C on at91rm9200 + - add support for Ricoh RS5C372A RTC + * Patch by Gary Jennejohn, 01 Oct 2004: - add support for CMC PU2 board - add support for I2C on at91rm9200 diff --git a/board/cmc_pu2/memsetup.S b/board/cmc_pu2/memsetup.S index 168cd6b..2d0e1d7 100644 --- a/board/cmc_pu2/memsetup.S +++ b/board/cmc_pu2/memsetup.S @@ -2,7 +2,7 @@ * Memory Setup stuff - taken from blob memsetup.S * * Copyright (C) 1999 2000 2001 Erik Mouw (J.A.K.Mouw@its.tudelft.nl) and - * Jan-Derk Bakker (J.D.Bakker@its.tudelft.nl) + * Jan-Derk Bakker (J.D.Bakker@its.tudelft.nl) * * Modified for the at91rm9200dk board by * (C) Copyright 2004 @@ -18,7 +18,7 @@ * * 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 + * 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 @@ -92,36 +92,36 @@ _TEXT_BASE: .globl memsetup memsetup: /* memory control configuration */ - /* this isn't very elegant, but what the heck */ - ldr r0, =SMRDATA + /* this isn't very elegant, but what the heck */ + ldr r0, =SMRDATA ldr r1, _TEXT_BASE sub r0, r0, r1 - add r2, r0, #80 + add r2, r0, #80 0: /* the address */ - ldr r1, [r0], #4 + ldr r1, [r0], #4 /* the value */ - ldr r3, [r0], #4 - str r3, [r1] - cmp r2, r0 - bne 0b + ldr r3, [r0], #4 + str r3, [r1] + cmp r2, r0 + bne 0b /* delay - this is all done by guess */ - ldr r0, =0x00001000 + ldr r0, =0x00001000 1: - subs r0, r0, #1 - bhi 1b - ldr r0, =SMRDATA1 + subs r0, r0, #1 + bhi 1b + ldr r0, =SMRDATA1 ldr r1, _TEXT_BASE sub r0, r0, r1 - add r2, r0, #176 + add r2, r0, #176 2: /* the address */ - ldr r1, [r0], #4 + ldr r1, [r0], #4 /* the value */ - ldr r3, [r0], #4 - str r3, [r1] - cmp r2, r0 - bne 2b + ldr r3, [r0], #4 + str r3, [r1] + cmp r2, r0 + bne 2b /* everything is fine now */ mov pc, lr diff --git a/cpu/at91rm9200/i2c.c b/cpu/at91rm9200/i2c.c index d5d6268d..515792c 100644 --- a/cpu/at91rm9200/i2c.c +++ b/cpu/at91rm9200/i2c.c @@ -60,7 +60,6 @@ at91_xfer(unsigned char chip, unsigned int addr, int alen, AT91PS_TWI twi = (AT91PS_TWI) AT91_TWI_BASE; int length; unsigned char *buf; - /* Set the TWI Master Mode Register */ twi->TWI_MMR = (chip << 16) | (alen << 8) | ((rw == 1) ? AT91C_TWI_MREAD : 0); @@ -126,13 +125,15 @@ int i2c_read(unsigned char chip, unsigned int addr, int alen, unsigned char *buffer, int len) { +#ifdef CFG_I2C_EEPROM_ADDR_OVERFLOW /* we only allow one address byte */ if (alen > 1) return 1; -#ifdef CFG_I2C_EEPROM_ADDR_OVERFLOW /* XXX assume an ATMEL AT24C16 */ if (alen == 1) { +#if 0 /* EEPROM code already sets this correctly */ chip |= (addr >> 8) & 0xff; +#endif addr = addr & 0xff; } #endif @@ -146,22 +147,25 @@ i2c_write(unsigned char chip, unsigned int addr, int alen, int i; unsigned char *buf; +#ifdef CFG_I2C_EEPROM_ADDR_OVERFLOW /* we only allow one address byte */ if (alen > 1) return 1; -#ifdef CFG_I2C_EEPROM_ADDR_OVERFLOW /* XXX assume an ATMEL AT24C16 */ if (alen == 1) { buf = buffer; /* do single byte writes */ for (i = 0; i < len; i++) { +#if 0 /* EEPROM code already sets this correctly */ chip |= (addr >> 8) & 0xff; +#endif addr = addr & 0xff; if (at91_xfer(chip, addr, alen, buf++, 1, 0)) return 1; + addr++; } + return 0; } - return 0; #endif return at91_xfer(chip, addr, alen, buffer, len, 0); } diff --git a/include/at91rm9200_i2c.h b/include/at91rm9200_i2c.h index cb13d9d..c2ec2f1 100644 --- a/include/at91rm9200_i2c.h +++ b/include/at91rm9200_i2c.h @@ -1,90 +1,90 @@ -// ---------------------------------------------------------------------------- -// ATMEL Microcontroller Software Support - ROUSSET - -// ---------------------------------------------------------------------------- -// The software is delivered "AS IS" without warranty or condition of any -// kind, either express, implied or statutory. This includes without -// limitation any warranty or condition with respect to merchantability or -// fitness for any particular purpose, or against the infringements of -// intellectual property rights of others. -// ---------------------------------------------------------------------------- -// File Name : at91rm9200_i2c.h -// Object : AT91RM9200 / TWI definitions -// Generated : AT91 SW Application Group 12/03/2002 (10:48:02) -// -// ---------------------------------------------------------------------------- +/* ---------------------------------------------------------------------------- */ +/* ATMEL Microcontroller Software Support - ROUSSET - */ +/* ---------------------------------------------------------------------------- */ +/* The software is delivered "AS IS" without warranty or condition of any */ +/* kind, either express, implied or statutory. This includes without */ +/* limitation any warranty or condition with respect to merchantability or */ +/* fitness for any particular purpose, or against the infringements of */ +/* intellectual property rights of others. */ +/* ---------------------------------------------------------------------------- */ +/* File Name : at91rm9200_i2c.h */ +/* Object : AT91RM9200 / TWI definitions */ +/* Generated : AT91 SW Application Group 12/03/2002 (10:48:02) */ +/* */ +/* ---------------------------------------------------------------------------- */ #ifndef AT91RM9200_TWI_H #define AT91RM9200_TWI_H -// ***************************************************************************** -// SOFTWARE API DEFINITION FOR Two-wire Interface -// ***************************************************************************** +/* ******************************************************************************/ +/* SOFTWARE API DEFINITION FOR Two-wire Interface */ +/* ******************************************************************************/ #ifndef __ASSEMBLY__ typedef struct _AT91S_TWI { - AT91_REG TWI_CR; // Control Register - AT91_REG TWI_MMR; // Master Mode Register - AT91_REG TWI_SMR; // Slave Mode Register - AT91_REG TWI_IADR; // Internal Address Register - AT91_REG TWI_CWGR; // Clock Waveform Generator Register - AT91_REG Reserved0[3]; // - AT91_REG TWI_SR; // Status Register - AT91_REG TWI_IER; // Interrupt Enable Register - AT91_REG TWI_IDR; // Interrupt Disable Register - AT91_REG TWI_IMR; // Interrupt Mask Register - AT91_REG TWI_RHR; // Receive Holding Register - AT91_REG TWI_THR; // Transmit Holding Register - AT91_REG Reserved1[50]; // - AT91_REG TWI_RPR; // Receive Pointer Register - AT91_REG TWI_RCR; // Receive Counter Register - AT91_REG TWI_TPR; // Transmit Pointer Register - AT91_REG TWI_TCR; // Transmit Counter Register - AT91_REG TWI_RNPR; // Receive Next Pointer Register - AT91_REG TWI_RNCR; // Receive Next Counter Register - AT91_REG TWI_TNPR; // Transmit Next Pointer Register - AT91_REG TWI_TNCR; // Transmit Next Counter Register - AT91_REG TWI_PTCR; // PDC Transfer Control Register - AT91_REG TWI_PTSR; // PDC Transfer Status Register + AT91_REG TWI_CR; /* Control Register */ + AT91_REG TWI_MMR; /* Master Mode Register */ + AT91_REG TWI_SMR; /* Slave Mode Register */ + AT91_REG TWI_IADR; /* Internal Address Register */ + AT91_REG TWI_CWGR; /* Clock Waveform Generator Register */ + AT91_REG Reserved0[3]; + AT91_REG TWI_SR; /* Status Register */ + AT91_REG TWI_IER; /* Interrupt Enable Register */ + AT91_REG TWI_IDR; /* Interrupt Disable Register */ + AT91_REG TWI_IMR; /* Interrupt Mask Register */ + AT91_REG TWI_RHR; /* Receive Holding Register */ + AT91_REG TWI_THR; /* Transmit Holding Register */ + AT91_REG Reserved1[50]; + AT91_REG TWI_RPR; /* Receive Pointer Register */ + AT91_REG TWI_RCR; /* Receive Counter Register */ + AT91_REG TWI_TPR; /* Transmit Pointer Register */ + AT91_REG TWI_TCR; /* Transmit Counter Register */ + AT91_REG TWI_RNPR; /* Receive Next Pointer Register */ + AT91_REG TWI_RNCR; /* Receive Next Counter Register */ + AT91_REG TWI_TNPR; /* Transmit Next Pointer Register */ + AT91_REG TWI_TNCR; /* Transmit Next Counter Register */ + AT91_REG TWI_PTCR; /* PDC Transfer Control Register */ + AT91_REG TWI_PTSR; /* PDC Transfer Status Register */ } AT91S_TWI, *AT91PS_TWI; #endif -// -------- TWI_CR : (TWI Offset: 0x0) TWI Control Register -------- -#define AT91C_TWI_START ( 0x1 << 0) // (TWI) Send a START Condition -#define AT91C_TWI_STOP ( 0x1 << 1) // (TWI) Send a STOP Condition -#define AT91C_TWI_MSEN ( 0x1 << 2) // (TWI) TWI Master Transfer Enabled -#define AT91C_TWI_MSDIS ( 0x1 << 3) // (TWI) TWI Master Transfer Disabled -#define AT91C_TWI_SVEN ( 0x1 << 4) // (TWI) TWI Slave Transfer Enabled -#define AT91C_TWI_SVDIS ( 0x1 << 5) // (TWI) TWI Slave Transfer Disabled -#define AT91C_TWI_SWRST ( 0x1 << 7) // (TWI) Software Reset -// -------- TWI_MMR : (TWI Offset: 0x4) TWI Master Mode Register -------- -#define AT91C_TWI_IADRSZ ( 0x3 << 8) // (TWI) Internal Device Address Size -#define AT91C_TWI_IADRSZ_NO ( 0x0 << 8) // (TWI) No internal device address -#define AT91C_TWI_IADRSZ_1_BYTE ( 0x1 << 8) // (TWI) One-byte internal device address -#define AT91C_TWI_IADRSZ_2_BYTE ( 0x2 << 8) // (TWI) Two-byte internal device address -#define AT91C_TWI_IADRSZ_3_BYTE ( 0x3 << 8) // (TWI) Three-byte internal device address -#define AT91C_TWI_MREAD ( 0x1 << 12) // (TWI) Master Read Direction -#define AT91C_TWI_DADR ( 0x7F << 6) // (TWI) Device Address -// -------- TWI_SMR : (TWI Offset: 0x8) TWI Slave Mode Register -------- -#define AT91C_TWI_SADR ( 0x7F << 16) // (TWI) Slave Device Address -// -------- TWI_CWGR : (TWI Offset: 0x10) TWI Clock Waveform Generator Register -------- -#define AT91C_TWI_CLDIV ( 0xFF << 0) // (TWI) Clock Low Divider -#define AT91C_TWI_CHDIV ( 0xFF << 8) // (TWI) Clock High Divider -#define AT91C_TWI_CKDIV ( 0x7 << 16) // (TWI) Clock Divider -// -------- TWI_SR : (TWI Offset: 0x20) TWI Status Register -------- -#define AT91C_TWI_TXCOMP ( 0x1 << 0) // (TWI) Transmission Completed -#define AT91C_TWI_RXRDY ( 0x1 << 1) // (TWI) Receive holding register ReaDY -#define AT91C_TWI_TXRDY ( 0x1 << 2) // (TWI) Transmit holding register ReaDY -#define AT91C_TWI_SVREAD ( 0x1 << 3) // (TWI) Slave Read -#define AT91C_TWI_SVACC ( 0x1 << 4) // (TWI) Slave Access -#define AT91C_TWI_GCACC ( 0x1 << 5) // (TWI) General Call Access -#define AT91C_TWI_OVRE ( 0x1 << 6) // (TWI) Overrun Error -#define AT91C_TWI_UNRE ( 0x1 << 7) // (TWI) Underrun Error -#define AT91C_TWI_NACK ( 0x1 << 8) // (TWI) Not Acknowledged -#define AT91C_TWI_ARBLST ( 0x1 << 9) // (TWI) Arbitration Lost -// -------- TWI_IER : (TWI Offset: 0x24) TWI Interrupt Enable Register -------- -// -------- TWI_IDR : (TWI Offset: 0x28) TWI Interrupt Disable Register -------- -// -------- TWI_IMR : (TWI Offset: 0x2c) TWI Interrupt Mask Register -------- +/* -------- TWI_CR : (TWI Offset: 0x0) TWI Control Register -------- */ +#define AT91C_TWI_START (0x1 << 0) /* (TWI) Send a START Condition */ +#define AT91C_TWI_STOP (0x1 << 1) /* (TWI) Send a STOP Condition */ +#define AT91C_TWI_MSEN (0x1 << 2) /* (TWI) TWI Master Transfer Enabled */ +#define AT91C_TWI_MSDIS (0x1 << 3) /* (TWI) TWI Master Transfer Disabled */ +#define AT91C_TWI_SVEN (0x1 << 4) /* (TWI) TWI Slave Transfer Enabled */ +#define AT91C_TWI_SVDIS (0x1 << 5) /* (TWI) TWI Slave Transfer Disabled */ +#define AT91C_TWI_SWRST (0x1 << 7) /* (TWI) Software Reset */ +/* -------- TWI_MMR : (TWI Offset: 0x4) TWI Master Mode Register -------- */ +#define AT91C_TWI_IADRSZ (0x3 << 8) /* (TWI) Internal Device Address Size */ +#define AT91C_TWI_IADRSZ_NO (0x0 << 8) /* (TWI) No internal device address */ +#define AT91C_TWI_IADRSZ_1_BYTE (0x1 << 8) /* (TWI) One-byte internal device address */ +#define AT91C_TWI_IADRSZ_2_BYTE (0x2 << 8) /* (TWI) Two-byte internal device address */ +#define AT91C_TWI_IADRSZ_3_BYTE (0x3 << 8) /* (TWI) Three-byte internal device address */ +#define AT91C_TWI_MREAD (0x1 << 12) /* (TWI) Master Read Direction */ +#define AT91C_TWI_DADR (0x7F << 6) /* (TWI) Device Address */ +/* -------- TWI_SMR : (TWI Offset: 0x8) TWI Slave Mode Register -------- */ +#define AT91C_TWI_SADR (0x7F << 16) /* (TWI) Slave Device Address */ +/* -------- TWI_CWGR : (TWI Offset: 0x10) TWI Clock Waveform Generator Register -------- */ +#define AT91C_TWI_CLDIV (0xFF << 0) /* (TWI) Clock Low Divider */ +#define AT91C_TWI_CHDIV (0xFF << 8) /* (TWI) Clock High Divider */ +#define AT91C_TWI_CKDIV (0x7 << 16) /* (TWI) Clock Divider */ +/* -------- TWI_SR : (TWI Offset: 0x20) TWI Status Register -------- */ +#define AT91C_TWI_TXCOMP (0x1 << 0) /* (TWI) Transmission Completed */ +#define AT91C_TWI_RXRDY (0x1 << 1) /* (TWI) Receive holding register ReaDY */ +#define AT91C_TWI_TXRDY (0x1 << 2) /* (TWI) Transmit holding register ReaDY*/ +#define AT91C_TWI_SVREAD (0x1 << 3) /* (TWI) Slave Read */ +#define AT91C_TWI_SVACC (0x1 << 4) /* (TWI) Slave Access */ +#define AT91C_TWI_GCACC (0x1 << 5) /* (TWI) General Call Access */ +#define AT91C_TWI_OVRE (0x1 << 6) /* (TWI) Overrun Error */ +#define AT91C_TWI_UNRE (0x1 << 7) /* (TWI) Underrun Error */ +#define AT91C_TWI_NACK (0x1 << 8) /* (TWI) Not Acknowledged */ +#define AT91C_TWI_ARBLST (0x1 << 9) /* (TWI) Arbitration Lost */ +/* -------- TWI_IER : (TWI Offset: 0x24) TWI Interrupt Enable Register -------- */ +/* -------- TWI_IDR : (TWI Offset: 0x28) TWI Interrupt Disable Register ------- */ +/* -------- TWI_IMR : (TWI Offset: 0x2c) TWI Interrupt Mask Register -------- */ /* i2c Support for Atmel's AT91RM9200 Two-Wire Interface @@ -120,7 +120,7 @@ typedef struct _AT91S_TWI { #endif #define AT91C_TWI_CLDIV3 ((AT91C_TWI_CLDIV2 + (4 - AT91C_TWI_CLDIV2 % 4)) >> 2) -#define AT91C_EEPROM_I2C_ADDRESS (0x50 << 16) +#define AT91C_EEPROM_I2C_ADDRESS (0x50 << 16) -#endif -#endif +#endif /* __ASSEMBLY__ */ +#endif /* AT91RM9200_TWI_H */ diff --git a/rtc/Makefile b/rtc/Makefile index 71fadea..4ceac76 100644 --- a/rtc/Makefile +++ b/rtc/Makefile @@ -31,7 +31,7 @@ OBJS = date.o \ ds12887.o ds1302.o ds1306.o ds1307.o ds1337.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 + mpc5xxx.o mpc8xx.o pcf8563.o s3c24x0_rtc.o rs5c372.o all: $(LIB) diff --git a/rtc/rs5c372.c b/rtc/rs5c372.c new file mode 100644 index 0000000..0f8ec62 --- /dev/null +++ b/rtc/rs5c372.c @@ -0,0 +1,303 @@ +/* + * rs5c372.c + * + * Device driver for Ricoh's Real Time Controller RS5C372A. + * + * Copyright (C) 2004 Gary Jennejohn garyj@denx.de + * + * Based in part in ds1307.c - + * (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 version 2 as + * published by the Free Software Foundation. + * + * 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 + */ + +#include +#include +#include +#include + +#if defined(CONFIG_RTC_RS5C372A) && (CONFIG_COMMANDS & CFG_CMD_DATE) +/* + * Reads are always done starting with register 15, which requires some + * jumping-through-hoops to access the data correctly. + * + * Writes are always done starting with register 0. + */ + +#define DEBUG 0 + +#if DEBUG +static unsigned int rtc_debug = DEBUG; +#else +#define rtc_debug 0 /* gcc will remove all the debug code for us */ +#endif + +#ifndef CFG_I2C_RTC_ADDR +#define CFG_I2C_RTC_ADDR 0x32 +#endif + +#define RS5C372_RAM_SIZE 0x10 +#define RATE_32000HZ 0x80 /* Rate Select 32.000KHz */ +#define RATE_32768HZ 0x00 /* Rate Select 32.768KHz */ + +#define STATUS_XPT 0x10 /* data invalid because voltage was 0 */ + +#define USE_24HOUR_MODE 0x20 +#define TWELVE_HOUR_MODE(n) ((((n) >> 5) & 1) == 0) +#define HOURS_AP(n) (((n) >> 5) & 1) +#define HOURS_12(n) bcd2bin((n) & 0x1F) +#define HOURS_24(n) bcd2bin((n) & 0x3F) + + +static uchar bin2bcd (unsigned int n); +static unsigned bcd2bin (uchar c); + +static int setup_done = 0; + +static int +rs5c372_readram(char *buf, int len) +{ + int ret; + + ret = i2c_read(CFG_I2C_RTC_ADDR, 0, 0, buf, len); + if (ret != 0) { + printf("%s: failed to read\n", __FUNCTION__); + return ret; + } + + if (buf[0] & STATUS_XPT) + printf("### Warning: RTC lost power\n"); + + return ret; +} + +static void +rs5c372_enable(void) +{ + unsigned char buf[RS5C372_RAM_SIZE + 1]; + int ret; + + + /* note that this returns reg. 15 in buf[1] */ + ret = rs5c372_readram(&buf[1], RS5C372_RAM_SIZE); + if (ret != 0) { + printf("%s: failed\n", __FUNCTION__); + return; + } + + buf[0] = 0; + /* we want to start writing at register 0 so we have to copy the */ + /* register contents up one slot */ + for (ret = 2; ret < 9; ret++) + buf[ret - 1] = buf[ret]; + /* registers 0 to 6 (time values) are not touched */ + buf[8] = RATE_32768HZ; /* reg. 7 */ + buf[9] = 0; /* reg. 8 */ + buf[10] = 0; /* reg. 9 */ + buf[11] = 0; /* reg. 10 */ + buf[12] = 0; /* reg. 11 */ + buf[13] = 0; /* reg. 12 */ + buf[14] = 0; /* reg. 13 */ + buf[15] = 0; /* reg. 14 */ + buf[16] = USE_24HOUR_MODE; /* reg. 15 */ + ret = i2c_write(CFG_I2C_RTC_ADDR, 0, 0, buf, RS5C372_RAM_SIZE+1); + if (ret != 0) { + printf("%s: failed\n", __FUNCTION__); + return; + } + setup_done = 1; + + return; +} + +static void +rs5c372_convert_to_time(struct rtc_time *dt, char *buf) +{ + /* buf[0] is register 15 */ + dt->tm_sec = bcd2bin(buf[1]); + dt->tm_min = bcd2bin(buf[2]); + + if (TWELVE_HOUR_MODE(buf[0])) { + dt->tm_hour = HOURS_12(buf[3]); + if (HOURS_AP(buf[3])) /* PM */ + dt->tm_hour += 12; + } else /* 24-hour-mode */ + dt->tm_hour = HOURS_24(buf[3]); + + dt->tm_mday = bcd2bin(buf[5]); + dt->tm_mon = bcd2bin(buf[6]); + dt->tm_year = bcd2bin(buf[7]); + if (dt->tm_year >= 70) + dt->tm_year += 1900; + else + dt->tm_year += 2000; + /* 0 is Sunday */ + dt->tm_wday = bcd2bin(buf[4] & 0x07); + dt->tm_yday = 0; + dt->tm_isdst= 0; + + if(rtc_debug > 2) { + printf("rs5c372_convert_to_time: year = %d\n", dt->tm_year); + printf("rs5c372_convert_to_time: mon = %d\n", dt->tm_mon); + printf("rs5c372_convert_to_time: mday = %d\n", dt->tm_mday); + printf("rs5c372_convert_to_time: hour = %d\n", dt->tm_hour); + printf("rs5c372_convert_to_time: min = %d\n", dt->tm_min); + printf("rs5c372_convert_to_time: sec = %d\n", dt->tm_sec); + } +} + +/* + * Get the current time from the RTC + */ +void +rtc_get (struct rtc_time *tmp) +{ + unsigned char buf[RS5C372_RAM_SIZE]; + int ret; + + if (!setup_done) + rs5c372_enable(); + + if (!setup_done) + return; + + memset(buf, 0, sizeof(buf)); + + /* note that this returns reg. 15 in buf[0] */ + ret = rs5c372_readram(buf, RS5C372_RAM_SIZE); + if (ret != 0) { + printf("%s: failed\n", __FUNCTION__); + return; + } + + rs5c372_convert_to_time(tmp, buf); + + return; +} + +/* + * Set the RTC + */ +void +rtc_set (struct rtc_time *tmp) +{ + unsigned char buf[8], reg15; + int ret; + + if (!setup_done) + rs5c372_enable(); + + if (!setup_done) + return; + + if(rtc_debug > 2) { + printf("rtc_set: tm_year = %d\n", tmp->tm_year); + printf("rtc_set: tm_mon = %d\n", tmp->tm_mon); + printf("rtc_set: tm_mday = %d\n", tmp->tm_mday); + printf("rtc_set: tm_hour = %d\n", tmp->tm_hour); + printf("rtc_set: tm_min = %d\n", tmp->tm_min); + printf("rtc_set: tm_sec = %d\n", tmp->tm_sec); + } + + memset(buf, 0, sizeof(buf)); + + /* only read register 15 */ + ret = i2c_read(CFG_I2C_RTC_ADDR, 0, 0, buf, 1); + + if (ret == 0) { + /* need to save register 15 */ + reg15 = buf[0]; + buf[0] = 0; /* register address on RS5C372 */ + buf[1] = bin2bcd(tmp->tm_sec); + buf[2] = bin2bcd(tmp->tm_min); + /* need to handle 12 hour mode */ + if (TWELVE_HOUR_MODE(reg15)) { + if (tmp->tm_hour >= 12) { /* PM */ + /* 12 PM is a special case */ + if (tmp->tm_hour == 12) + buf[3] = bin2bcd(tmp->tm_hour); + else + buf[3] = bin2bcd(tmp->tm_hour - 12); + buf[3] |= 0x20; + } + } else { + buf[3] = bin2bcd(tmp->tm_hour); + } + + buf[4] = bin2bcd(tmp->tm_wday); + buf[5] = bin2bcd(tmp->tm_mday); + buf[6] = bin2bcd(tmp->tm_mon); + if (tmp->tm_year < 1970 || tmp->tm_year > 2069) + printf("WARNING: year should be between 1970 and 2069!\n"); + buf[7] = bin2bcd(tmp->tm_year % 100); + + ret = i2c_write(CFG_I2C_RTC_ADDR, 0, 0, buf, 8); + if (ret != 0) + printf("rs5c372_set_datetime(), i2c_master_send() returned %d\n",ret); + } + + return; +} + +/* + * Reset the RTC. We set the date back to 1970-01-01. + */ +void +rtc_reset (void) +{ + struct rtc_time tmp; + + if (!setup_done) + rs5c372_enable(); + + if (!setup_done) + return; + + tmp.tm_year = 1970; + tmp.tm_mon = 1; + /* Jan. 1, 1970 was a Thursday */ + tmp.tm_wday= 4; + 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); + + return; +} + +static unsigned int +bcd2bin (unsigned char n) +{ + return ((((n >> 4) & 0x0F) * 10) + (n & 0x0F)); +} + +static unsigned char +bin2bcd (unsigned int n) +{ + return (((n / 10) << 4) | (n % 10)); +} +#endif /* defined(CONFIG_RTC_RS5C372A) && (CONFIG_COMMANDS & CFG_CMD_DATE) */ -- cgit v0.10.2