18809a271SStefan Roese /* 28809a271SStefan Roese * (C) Copyright 2007 38809a271SStefan Roese * Stefan Roese, DENX Software Engineering, sr@denx.de. 48809a271SStefan Roese * 58809a271SStefan Roese * based on a the Linux rtc-x1207.c driver which is: 68809a271SStefan Roese * Copyright 2004 Karen Spearel 78809a271SStefan Roese * Copyright 2005 Alessandro Zummo 88809a271SStefan Roese * 98809a271SStefan Roese * Information and datasheet: 108809a271SStefan Roese * http://www.intersil.com/cda/deviceinfo/0,1477,X1205,00.html 118809a271SStefan Roese * 128809a271SStefan Roese * See file CREDITS for list of people who contributed to this 138809a271SStefan Roese * project. 148809a271SStefan Roese * 158809a271SStefan Roese * This program is free software; you can redistribute it and/or 168809a271SStefan Roese * modify it under the terms of the GNU General Public License as 178809a271SStefan Roese * published by the Free Software Foundation; either version 2 of 188809a271SStefan Roese * the License, or (at your option) any later version. 198809a271SStefan Roese * 208809a271SStefan Roese * This program is distributed in the hope that it will be useful, 218809a271SStefan Roese * but WITHOUT ANY WARRANTY; without even the implied warranty of 228809a271SStefan Roese * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 238809a271SStefan Roese * GNU General Public License for more details. 248809a271SStefan Roese * 258809a271SStefan Roese * You should have received a copy of the GNU General Public License 268809a271SStefan Roese * along with this program; if not, write to the Free Software 278809a271SStefan Roese * Foundation, Inc., 59 Temple Place, Suite 330, Boston, 288809a271SStefan Roese * MA 02111-1307 USA 298809a271SStefan Roese */ 308809a271SStefan Roese 318809a271SStefan Roese /* 328809a271SStefan Roese * Date & Time support for Xicor/Intersil X1205 RTC 338809a271SStefan Roese */ 348809a271SStefan Roese 358809a271SStefan Roese /* #define DEBUG */ 368809a271SStefan Roese 378809a271SStefan Roese #include <common.h> 388809a271SStefan Roese #include <command.h> 398809a271SStefan Roese #include <rtc.h> 408809a271SStefan Roese #include <i2c.h> 418809a271SStefan Roese #include <bcd.h> 428809a271SStefan Roese 438809a271SStefan Roese #if defined(CONFIG_RTC_X1205) && defined(CONFIG_CMD_DATE) 448809a271SStefan Roese 458809a271SStefan Roese #define CCR_SEC 0 468809a271SStefan Roese #define CCR_MIN 1 478809a271SStefan Roese #define CCR_HOUR 2 488809a271SStefan Roese #define CCR_MDAY 3 498809a271SStefan Roese #define CCR_MONTH 4 508809a271SStefan Roese #define CCR_YEAR 5 518809a271SStefan Roese #define CCR_WDAY 6 528809a271SStefan Roese #define CCR_Y2K 7 538809a271SStefan Roese 548809a271SStefan Roese #define X1205_REG_SR 0x3F /* status register */ 558809a271SStefan Roese #define X1205_REG_Y2K 0x37 568809a271SStefan Roese #define X1205_REG_DW 0x36 578809a271SStefan Roese #define X1205_REG_YR 0x35 588809a271SStefan Roese #define X1205_REG_MO 0x34 598809a271SStefan Roese #define X1205_REG_DT 0x33 608809a271SStefan Roese #define X1205_REG_HR 0x32 618809a271SStefan Roese #define X1205_REG_MN 0x31 628809a271SStefan Roese #define X1205_REG_SC 0x30 638809a271SStefan Roese #define X1205_REG_DTR 0x13 648809a271SStefan Roese #define X1205_REG_ATR 0x12 658809a271SStefan Roese #define X1205_REG_INT 0x11 668809a271SStefan Roese #define X1205_REG_0 0x10 678809a271SStefan Roese #define X1205_REG_Y2K1 0x0F 688809a271SStefan Roese #define X1205_REG_DWA1 0x0E 698809a271SStefan Roese #define X1205_REG_YRA1 0x0D 708809a271SStefan Roese #define X1205_REG_MOA1 0x0C 718809a271SStefan Roese #define X1205_REG_DTA1 0x0B 728809a271SStefan Roese #define X1205_REG_HRA1 0x0A 738809a271SStefan Roese #define X1205_REG_MNA1 0x09 748809a271SStefan Roese #define X1205_REG_SCA1 0x08 758809a271SStefan Roese #define X1205_REG_Y2K0 0x07 768809a271SStefan Roese #define X1205_REG_DWA0 0x06 778809a271SStefan Roese #define X1205_REG_YRA0 0x05 788809a271SStefan Roese #define X1205_REG_MOA0 0x04 798809a271SStefan Roese #define X1205_REG_DTA0 0x03 808809a271SStefan Roese #define X1205_REG_HRA0 0x02 818809a271SStefan Roese #define X1205_REG_MNA0 0x01 828809a271SStefan Roese #define X1205_REG_SCA0 0x00 838809a271SStefan Roese 848809a271SStefan Roese #define X1205_CCR_BASE 0x30 /* Base address of CCR */ 858809a271SStefan Roese #define X1205_ALM0_BASE 0x00 /* Base address of ALARM0 */ 868809a271SStefan Roese 878809a271SStefan Roese #define X1205_SR_RTCF 0x01 /* Clock failure */ 888809a271SStefan Roese #define X1205_SR_WEL 0x02 /* Write Enable Latch */ 898809a271SStefan Roese #define X1205_SR_RWEL 0x04 /* Register Write Enable */ 908809a271SStefan Roese 918809a271SStefan Roese #define X1205_DTR_DTR0 0x01 928809a271SStefan Roese #define X1205_DTR_DTR1 0x02 938809a271SStefan Roese #define X1205_DTR_DTR2 0x04 948809a271SStefan Roese 958809a271SStefan Roese #define X1205_HR_MIL 0x80 /* Set in ccr.hour for 24 hr mode */ 968809a271SStefan Roese 978809a271SStefan Roese static void rtc_write(int reg, u8 val) 988809a271SStefan Roese { 998809a271SStefan Roese i2c_write(CFG_I2C_RTC_ADDR, reg, 2, &val, 1); 1008809a271SStefan Roese } 1018809a271SStefan Roese 1028809a271SStefan Roese /* 1038809a271SStefan Roese * In the routines that deal directly with the x1205 hardware, we use 1048809a271SStefan Roese * rtc_time -- month 0-11, hour 0-23, yr = calendar year-epoch 1058809a271SStefan Roese * Epoch is initialized as 2000. Time is set to UTC. 1068809a271SStefan Roese */ 107*b73a19e1SYuri Tikhonov int rtc_get(struct rtc_time *tm) 1088809a271SStefan Roese { 1098809a271SStefan Roese u8 buf[8]; 1108809a271SStefan Roese 1118809a271SStefan Roese i2c_read(CFG_I2C_RTC_ADDR, X1205_CCR_BASE, 2, buf, 8); 1128809a271SStefan Roese 1138809a271SStefan Roese debug("%s: raw read data - sec=%02x, min=%02x, hr=%02x, " 1148809a271SStefan Roese "mday=%02x, mon=%02x, year=%02x, wday=%02x, y2k=%02x\n", 1158809a271SStefan Roese __FUNCTION__, 1168809a271SStefan Roese buf[0], buf[1], buf[2], buf[3], 1178809a271SStefan Roese buf[4], buf[5], buf[6], buf[7]); 1188809a271SStefan Roese 1198809a271SStefan Roese tm->tm_sec = BCD2BIN(buf[CCR_SEC]); 1208809a271SStefan Roese tm->tm_min = BCD2BIN(buf[CCR_MIN]); 1218809a271SStefan Roese tm->tm_hour = BCD2BIN(buf[CCR_HOUR] & 0x3F); /* hr is 0-23 */ 1228809a271SStefan Roese tm->tm_mday = BCD2BIN(buf[CCR_MDAY]); 1238809a271SStefan Roese tm->tm_mon = BCD2BIN(buf[CCR_MONTH]); /* mon is 0-11 */ 1248809a271SStefan Roese tm->tm_year = BCD2BIN(buf[CCR_YEAR]) 1258809a271SStefan Roese + (BCD2BIN(buf[CCR_Y2K]) * 100); 1268809a271SStefan Roese tm->tm_wday = buf[CCR_WDAY]; 1278809a271SStefan Roese 1288809a271SStefan Roese debug("%s: tm is secs=%d, mins=%d, hours=%d, " 1298809a271SStefan Roese "mday=%d, mon=%d, year=%d, wday=%d\n", 1308809a271SStefan Roese __FUNCTION__, 1318809a271SStefan Roese tm->tm_sec, tm->tm_min, tm->tm_hour, 1328809a271SStefan Roese tm->tm_mday, tm->tm_mon, tm->tm_year, tm->tm_wday); 133*b73a19e1SYuri Tikhonov 134*b73a19e1SYuri Tikhonov return 0; 1358809a271SStefan Roese } 1368809a271SStefan Roese 1378809a271SStefan Roese void rtc_set(struct rtc_time *tm) 1388809a271SStefan Roese { 1398809a271SStefan Roese int i; 1408809a271SStefan Roese u8 buf[8]; 1418809a271SStefan Roese 1428809a271SStefan Roese debug("Set DATE: %4d-%02d-%02d (wday=%d) TIME: %2d:%02d:%02d\n", 1438809a271SStefan Roese tm->tm_year, tm->tm_mon, tm->tm_mday, tm->tm_wday, 1448809a271SStefan Roese tm->tm_hour, tm->tm_min, tm->tm_sec); 1458809a271SStefan Roese 1468809a271SStefan Roese buf[CCR_SEC] = BIN2BCD(tm->tm_sec); 1478809a271SStefan Roese buf[CCR_MIN] = BIN2BCD(tm->tm_min); 1488809a271SStefan Roese 1498809a271SStefan Roese /* set hour and 24hr bit */ 1508809a271SStefan Roese buf[CCR_HOUR] = BIN2BCD(tm->tm_hour) | X1205_HR_MIL; 1518809a271SStefan Roese 1528809a271SStefan Roese buf[CCR_MDAY] = BIN2BCD(tm->tm_mday); 1538809a271SStefan Roese 1548809a271SStefan Roese /* month, 1 - 12 */ 1558809a271SStefan Roese buf[CCR_MONTH] = BIN2BCD(tm->tm_mon); 1568809a271SStefan Roese 1578809a271SStefan Roese /* year, since the rtc epoch*/ 1588809a271SStefan Roese buf[CCR_YEAR] = BIN2BCD(tm->tm_year % 100); 1598809a271SStefan Roese buf[CCR_WDAY] = tm->tm_wday & 0x07; 1608809a271SStefan Roese buf[CCR_Y2K] = BIN2BCD(tm->tm_year / 100); 1618809a271SStefan Roese 1628809a271SStefan Roese /* this sequence is required to unlock the chip */ 1638809a271SStefan Roese rtc_write(X1205_REG_SR, X1205_SR_WEL); 1648809a271SStefan Roese rtc_write(X1205_REG_SR, X1205_SR_WEL | X1205_SR_RWEL); 1658809a271SStefan Roese 1668809a271SStefan Roese /* write register's data */ 1678809a271SStefan Roese for (i = 0; i < 8; i++) 1688809a271SStefan Roese rtc_write(X1205_CCR_BASE + i, buf[i]); 1698809a271SStefan Roese 1708809a271SStefan Roese rtc_write(X1205_REG_SR, 0); 1718809a271SStefan Roese } 1728809a271SStefan Roese 1738809a271SStefan Roese void rtc_reset(void) 1748809a271SStefan Roese { 1758809a271SStefan Roese /* 1768809a271SStefan Roese * Nothing to do 1778809a271SStefan Roese */ 1788809a271SStefan Roese } 1798809a271SStefan Roese 1808809a271SStefan Roese #endif 181