xref: /OK3568_Linux_fs/u-boot/drivers/rtc/x1205.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
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