1*4882a593Smuzhiyun /*
2*4882a593Smuzhiyun * (C) Copyright 2007
3*4882a593Smuzhiyun * Stefan Roese, DENX Software Engineering, sr@denx.de.
4*4882a593Smuzhiyun *
5*4882a593Smuzhiyun * based on a the Linux rtc-x1207.c driver which is:
6*4882a593Smuzhiyun * Copyright 2004 Karen Spearel
7*4882a593Smuzhiyun * Copyright 2005 Alessandro Zummo
8*4882a593Smuzhiyun *
9*4882a593Smuzhiyun * Information and datasheet:
10*4882a593Smuzhiyun * http://www.intersil.com/cda/deviceinfo/0,1477,X1205,00.html
11*4882a593Smuzhiyun *
12*4882a593Smuzhiyun * SPDX-License-Identifier: GPL-2.0+
13*4882a593Smuzhiyun */
14*4882a593Smuzhiyun
15*4882a593Smuzhiyun /*
16*4882a593Smuzhiyun * Date & Time support for Xicor/Intersil X1205 RTC
17*4882a593Smuzhiyun */
18*4882a593Smuzhiyun
19*4882a593Smuzhiyun /* #define DEBUG */
20*4882a593Smuzhiyun
21*4882a593Smuzhiyun #include <common.h>
22*4882a593Smuzhiyun #include <command.h>
23*4882a593Smuzhiyun #include <rtc.h>
24*4882a593Smuzhiyun #include <i2c.h>
25*4882a593Smuzhiyun
26*4882a593Smuzhiyun #if defined(CONFIG_CMD_DATE)
27*4882a593Smuzhiyun
28*4882a593Smuzhiyun #define CCR_SEC 0
29*4882a593Smuzhiyun #define CCR_MIN 1
30*4882a593Smuzhiyun #define CCR_HOUR 2
31*4882a593Smuzhiyun #define CCR_MDAY 3
32*4882a593Smuzhiyun #define CCR_MONTH 4
33*4882a593Smuzhiyun #define CCR_YEAR 5
34*4882a593Smuzhiyun #define CCR_WDAY 6
35*4882a593Smuzhiyun #define CCR_Y2K 7
36*4882a593Smuzhiyun
37*4882a593Smuzhiyun #define X1205_REG_SR 0x3F /* status register */
38*4882a593Smuzhiyun #define X1205_REG_Y2K 0x37
39*4882a593Smuzhiyun #define X1205_REG_DW 0x36
40*4882a593Smuzhiyun #define X1205_REG_YR 0x35
41*4882a593Smuzhiyun #define X1205_REG_MO 0x34
42*4882a593Smuzhiyun #define X1205_REG_DT 0x33
43*4882a593Smuzhiyun #define X1205_REG_HR 0x32
44*4882a593Smuzhiyun #define X1205_REG_MN 0x31
45*4882a593Smuzhiyun #define X1205_REG_SC 0x30
46*4882a593Smuzhiyun #define X1205_REG_DTR 0x13
47*4882a593Smuzhiyun #define X1205_REG_ATR 0x12
48*4882a593Smuzhiyun #define X1205_REG_INT 0x11
49*4882a593Smuzhiyun #define X1205_REG_0 0x10
50*4882a593Smuzhiyun #define X1205_REG_Y2K1 0x0F
51*4882a593Smuzhiyun #define X1205_REG_DWA1 0x0E
52*4882a593Smuzhiyun #define X1205_REG_YRA1 0x0D
53*4882a593Smuzhiyun #define X1205_REG_MOA1 0x0C
54*4882a593Smuzhiyun #define X1205_REG_DTA1 0x0B
55*4882a593Smuzhiyun #define X1205_REG_HRA1 0x0A
56*4882a593Smuzhiyun #define X1205_REG_MNA1 0x09
57*4882a593Smuzhiyun #define X1205_REG_SCA1 0x08
58*4882a593Smuzhiyun #define X1205_REG_Y2K0 0x07
59*4882a593Smuzhiyun #define X1205_REG_DWA0 0x06
60*4882a593Smuzhiyun #define X1205_REG_YRA0 0x05
61*4882a593Smuzhiyun #define X1205_REG_MOA0 0x04
62*4882a593Smuzhiyun #define X1205_REG_DTA0 0x03
63*4882a593Smuzhiyun #define X1205_REG_HRA0 0x02
64*4882a593Smuzhiyun #define X1205_REG_MNA0 0x01
65*4882a593Smuzhiyun #define X1205_REG_SCA0 0x00
66*4882a593Smuzhiyun
67*4882a593Smuzhiyun #define X1205_CCR_BASE 0x30 /* Base address of CCR */
68*4882a593Smuzhiyun #define X1205_ALM0_BASE 0x00 /* Base address of ALARM0 */
69*4882a593Smuzhiyun
70*4882a593Smuzhiyun #define X1205_SR_RTCF 0x01 /* Clock failure */
71*4882a593Smuzhiyun #define X1205_SR_WEL 0x02 /* Write Enable Latch */
72*4882a593Smuzhiyun #define X1205_SR_RWEL 0x04 /* Register Write Enable */
73*4882a593Smuzhiyun
74*4882a593Smuzhiyun #define X1205_DTR_DTR0 0x01
75*4882a593Smuzhiyun #define X1205_DTR_DTR1 0x02
76*4882a593Smuzhiyun #define X1205_DTR_DTR2 0x04
77*4882a593Smuzhiyun
78*4882a593Smuzhiyun #define X1205_HR_MIL 0x80 /* Set in ccr.hour for 24 hr mode */
79*4882a593Smuzhiyun
rtc_write(int reg,u8 val)80*4882a593Smuzhiyun static void rtc_write(int reg, u8 val)
81*4882a593Smuzhiyun {
82*4882a593Smuzhiyun i2c_write(CONFIG_SYS_I2C_RTC_ADDR, reg, 2, &val, 1);
83*4882a593Smuzhiyun }
84*4882a593Smuzhiyun
85*4882a593Smuzhiyun /*
86*4882a593Smuzhiyun * In the routines that deal directly with the x1205 hardware, we use
87*4882a593Smuzhiyun * rtc_time -- month 0-11, hour 0-23, yr = calendar year-epoch
88*4882a593Smuzhiyun * Epoch is initialized as 2000. Time is set to UTC.
89*4882a593Smuzhiyun */
rtc_get(struct rtc_time * tm)90*4882a593Smuzhiyun int rtc_get(struct rtc_time *tm)
91*4882a593Smuzhiyun {
92*4882a593Smuzhiyun u8 buf[8];
93*4882a593Smuzhiyun
94*4882a593Smuzhiyun i2c_read(CONFIG_SYS_I2C_RTC_ADDR, X1205_CCR_BASE, 2, buf, 8);
95*4882a593Smuzhiyun
96*4882a593Smuzhiyun debug("%s: raw read data - sec=%02x, min=%02x, hr=%02x, "
97*4882a593Smuzhiyun "mday=%02x, mon=%02x, year=%02x, wday=%02x, y2k=%02x\n",
98*4882a593Smuzhiyun __FUNCTION__,
99*4882a593Smuzhiyun buf[0], buf[1], buf[2], buf[3],
100*4882a593Smuzhiyun buf[4], buf[5], buf[6], buf[7]);
101*4882a593Smuzhiyun
102*4882a593Smuzhiyun tm->tm_sec = bcd2bin(buf[CCR_SEC]);
103*4882a593Smuzhiyun tm->tm_min = bcd2bin(buf[CCR_MIN]);
104*4882a593Smuzhiyun tm->tm_hour = bcd2bin(buf[CCR_HOUR] & 0x3F); /* hr is 0-23 */
105*4882a593Smuzhiyun tm->tm_mday = bcd2bin(buf[CCR_MDAY]);
106*4882a593Smuzhiyun tm->tm_mon = bcd2bin(buf[CCR_MONTH]); /* mon is 0-11 */
107*4882a593Smuzhiyun tm->tm_year = bcd2bin(buf[CCR_YEAR])
108*4882a593Smuzhiyun + (bcd2bin(buf[CCR_Y2K]) * 100);
109*4882a593Smuzhiyun tm->tm_wday = buf[CCR_WDAY];
110*4882a593Smuzhiyun
111*4882a593Smuzhiyun debug("%s: tm is secs=%d, mins=%d, hours=%d, "
112*4882a593Smuzhiyun "mday=%d, mon=%d, year=%d, wday=%d\n",
113*4882a593Smuzhiyun __FUNCTION__,
114*4882a593Smuzhiyun tm->tm_sec, tm->tm_min, tm->tm_hour,
115*4882a593Smuzhiyun tm->tm_mday, tm->tm_mon, tm->tm_year, tm->tm_wday);
116*4882a593Smuzhiyun
117*4882a593Smuzhiyun return 0;
118*4882a593Smuzhiyun }
119*4882a593Smuzhiyun
rtc_set(struct rtc_time * tm)120*4882a593Smuzhiyun int rtc_set(struct rtc_time *tm)
121*4882a593Smuzhiyun {
122*4882a593Smuzhiyun int i;
123*4882a593Smuzhiyun u8 buf[8];
124*4882a593Smuzhiyun
125*4882a593Smuzhiyun debug("Set DATE: %4d-%02d-%02d (wday=%d) TIME: %2d:%02d:%02d\n",
126*4882a593Smuzhiyun tm->tm_year, tm->tm_mon, tm->tm_mday, tm->tm_wday,
127*4882a593Smuzhiyun tm->tm_hour, tm->tm_min, tm->tm_sec);
128*4882a593Smuzhiyun
129*4882a593Smuzhiyun buf[CCR_SEC] = bin2bcd(tm->tm_sec);
130*4882a593Smuzhiyun buf[CCR_MIN] = bin2bcd(tm->tm_min);
131*4882a593Smuzhiyun
132*4882a593Smuzhiyun /* set hour and 24hr bit */
133*4882a593Smuzhiyun buf[CCR_HOUR] = bin2bcd(tm->tm_hour) | X1205_HR_MIL;
134*4882a593Smuzhiyun
135*4882a593Smuzhiyun buf[CCR_MDAY] = bin2bcd(tm->tm_mday);
136*4882a593Smuzhiyun
137*4882a593Smuzhiyun /* month, 1 - 12 */
138*4882a593Smuzhiyun buf[CCR_MONTH] = bin2bcd(tm->tm_mon);
139*4882a593Smuzhiyun
140*4882a593Smuzhiyun /* year, since the rtc epoch*/
141*4882a593Smuzhiyun buf[CCR_YEAR] = bin2bcd(tm->tm_year % 100);
142*4882a593Smuzhiyun buf[CCR_WDAY] = tm->tm_wday & 0x07;
143*4882a593Smuzhiyun buf[CCR_Y2K] = bin2bcd(tm->tm_year / 100);
144*4882a593Smuzhiyun
145*4882a593Smuzhiyun /* this sequence is required to unlock the chip */
146*4882a593Smuzhiyun rtc_write(X1205_REG_SR, X1205_SR_WEL);
147*4882a593Smuzhiyun rtc_write(X1205_REG_SR, X1205_SR_WEL | X1205_SR_RWEL);
148*4882a593Smuzhiyun
149*4882a593Smuzhiyun /* write register's data */
150*4882a593Smuzhiyun for (i = 0; i < 8; i++)
151*4882a593Smuzhiyun rtc_write(X1205_CCR_BASE + i, buf[i]);
152*4882a593Smuzhiyun
153*4882a593Smuzhiyun rtc_write(X1205_REG_SR, 0);
154*4882a593Smuzhiyun
155*4882a593Smuzhiyun return 0;
156*4882a593Smuzhiyun }
157*4882a593Smuzhiyun
rtc_reset(void)158*4882a593Smuzhiyun void rtc_reset(void)
159*4882a593Smuzhiyun {
160*4882a593Smuzhiyun /*
161*4882a593Smuzhiyun * Nothing to do
162*4882a593Smuzhiyun */
163*4882a593Smuzhiyun }
164*4882a593Smuzhiyun
165*4882a593Smuzhiyun #endif
166