tizen 2.4 release
[kernel/u-boot-tm1.git] / board / etin / debris / phantom.c
1 /*
2  * board/eva/phantom.c
3  *
4  * Phantom RTC device driver for EVA
5  *
6  * Author: Sangmoon Kim
7  *         dogoil@etinsys.com
8  *
9  * Copyright 2002 Etinsys Inc.
10  *
11  * This program is free software; you can redistribute  it and/or modify it
12  * under  the terms of  the GNU General  Public License as published by the
13  * Free Software Foundation;  either version 2 of the  License, or (at your
14  * option) any later version.
15  */
16
17 #include <common.h>
18 #include <command.h>
19 #include <rtc.h>
20
21 #if defined(CONFIG_CMD_DATE)
22
23 #define RTC_BASE (CONFIG_SYS_NVRAM_BASE_ADDR + 0x7fff8)
24
25 #define RTC_YEAR                ( RTC_BASE + 7 )
26 #define RTC_MONTH               ( RTC_BASE + 6 )
27 #define RTC_DAY_OF_MONTH        ( RTC_BASE + 5 )
28 #define RTC_DAY_OF_WEEK         ( RTC_BASE + 4 )
29 #define RTC_HOURS               ( RTC_BASE + 3 )
30 #define RTC_MINUTES             ( RTC_BASE + 2 )
31 #define RTC_SECONDS             ( RTC_BASE + 1 )
32 #define RTC_CENTURY             ( RTC_BASE + 0 )
33
34 #define RTC_CONTROLA            RTC_CENTURY
35 #define RTC_CONTROLB            RTC_SECONDS
36 #define RTC_CONTROLC            RTC_DAY_OF_WEEK
37
38 #define RTC_CA_WRITE            0x80
39 #define RTC_CA_READ             0x40
40
41 #define RTC_CB_OSC_DISABLE      0x80
42
43 #define RTC_CC_BATTERY_FLAG     0x80
44 #define RTC_CC_FREQ_TEST        0x40
45
46
47 static int phantom_flag = -1;
48 static int century_flag = -1;
49
50 static uchar rtc_read(unsigned int addr)
51 {
52         return *(volatile unsigned char *)(addr);
53 }
54
55 static void rtc_write(unsigned int addr, uchar val)
56 {
57         *(volatile unsigned char *)(addr) = val;
58 }
59
60 static unsigned char phantom_rtc_sequence[] = {
61         0xc5, 0x3a, 0xa3, 0x5c, 0xc5, 0x3a, 0xa3, 0x5c
62 };
63
64 static unsigned char* phantom_rtc_read(int addr, unsigned char rtc[8])
65 {
66         int i, j;
67         unsigned char v;
68         unsigned char save = rtc_read(addr);
69
70         for (j = 0; j < 8; j++) {
71                 v = phantom_rtc_sequence[j];
72                 for (i = 0; i < 8; i++) {
73                         rtc_write(addr, v & 1);
74                         v >>= 1;
75                 }
76         }
77         for (j = 0; j < 8; j++) {
78                 v = 0;
79                 for (i = 0; i < 8; i++) {
80                         if(rtc_read(addr) & 1)
81                                 v |= 1 << i;
82                 }
83                 rtc[j] = v;
84         }
85         rtc_write(addr, save);
86         return rtc;
87 }
88
89 static void phantom_rtc_write(int addr, unsigned char rtc[8])
90 {
91         int i, j;
92         unsigned char v;
93         unsigned char save = rtc_read(addr);
94         for (j = 0; j < 8; j++) {
95                 v = phantom_rtc_sequence[j];
96                 for (i = 0; i < 8; i++) {
97                         rtc_write(addr, v & 1);
98                         v >>= 1;
99                 }
100         }
101         for (j = 0; j < 8; j++) {
102                 v = rtc[j];
103                 for (i = 0; i < 8; i++) {
104                         rtc_write(addr, v & 1);
105                         v >>= 1;
106                 }
107         }
108         rtc_write(addr, save);
109 }
110
111 static int get_phantom_flag(void)
112 {
113         int i;
114         unsigned char rtc[8];
115
116         phantom_rtc_read(RTC_BASE, rtc);
117
118         for(i = 1; i < 8; i++) {
119                 if (rtc[i] != rtc[0])
120                         return 1;
121         }
122         return 0;
123 }
124
125 void rtc_reset(void)
126 {
127         if (phantom_flag < 0)
128                 phantom_flag = get_phantom_flag();
129
130         if (phantom_flag) {
131                 unsigned char rtc[8];
132                 phantom_rtc_read(RTC_BASE, rtc);
133                 if(rtc[4] & 0x30) {
134                         printf( "real-time-clock was stopped. Now starting...\n" );
135                         rtc[4] &= 0x07;
136                         phantom_rtc_write(RTC_BASE, rtc);
137                 }
138         } else {
139                 uchar reg_a, reg_b, reg_c;
140                 reg_a = rtc_read( RTC_CONTROLA );
141                 reg_b = rtc_read( RTC_CONTROLB );
142
143                 if ( reg_b & RTC_CB_OSC_DISABLE )
144                 {
145                         printf( "real-time-clock was stopped. Now starting...\n" );
146                         reg_a |= RTC_CA_WRITE;
147                         reg_b &= ~RTC_CB_OSC_DISABLE;
148                         rtc_write( RTC_CONTROLA, reg_a );
149                         rtc_write( RTC_CONTROLB, reg_b );
150                 }
151
152                 /* make sure read/write clock register bits are cleared */
153                 reg_a &= ~( RTC_CA_WRITE | RTC_CA_READ );
154                 rtc_write( RTC_CONTROLA, reg_a );
155
156                 reg_c = rtc_read( RTC_CONTROLC );
157                 if (( reg_c & RTC_CC_BATTERY_FLAG ) == 0 )
158                         printf( "RTC battery low. Clock setting may not be reliable.\n");
159         }
160 }
161
162 static int get_century_flag(void)
163 {
164         int flag = 0;
165         int bcd, century;
166         bcd = rtc_read( RTC_CENTURY );
167         century = bcd2bin( bcd & 0x3F );
168         rtc_write( RTC_CENTURY, bin2bcd(century+1));
169         if (bcd == rtc_read( RTC_CENTURY ))
170                 flag = 1;
171         rtc_write( RTC_CENTURY, bcd);
172         return flag;
173 }
174
175 int rtc_get( struct rtc_time *tmp)
176 {
177         if (phantom_flag < 0)
178                 phantom_flag = get_phantom_flag();
179
180         if (phantom_flag)
181         {
182                 unsigned char rtc[8];
183
184                 phantom_rtc_read(RTC_BASE, rtc);
185
186                 tmp->tm_sec     = bcd2bin(rtc[1] & 0x7f);
187                 tmp->tm_min     = bcd2bin(rtc[2] & 0x7f);
188                 tmp->tm_hour    = bcd2bin(rtc[3] & 0x1f);
189                 tmp->tm_wday    = bcd2bin(rtc[4] & 0x7);
190                 tmp->tm_mday    = bcd2bin(rtc[5] & 0x3f);
191                 tmp->tm_mon     = bcd2bin(rtc[6] & 0x1f);
192                 tmp->tm_year    = bcd2bin(rtc[7]) + 1900;
193                 tmp->tm_yday = 0;
194                 tmp->tm_isdst = 0;
195
196                 if( (rtc[3] & 0x80)  && (rtc[3] & 0x40) ) tmp->tm_hour += 12;
197                 if (tmp->tm_year < 1970) tmp->tm_year += 100;
198         } else {
199                 uchar sec, min, hour;
200                 uchar mday, wday, mon, year;
201
202                 int century;
203
204                 uchar reg_a;
205
206                 if (century_flag < 0)
207                         century_flag = get_century_flag();
208
209                 reg_a = rtc_read( RTC_CONTROLA );
210                 /* lock clock registers for read */
211                 rtc_write( RTC_CONTROLA, ( reg_a | RTC_CA_READ ));
212
213                 sec     = rtc_read( RTC_SECONDS );
214                 min     = rtc_read( RTC_MINUTES );
215                 hour    = rtc_read( RTC_HOURS );
216                 mday    = rtc_read( RTC_DAY_OF_MONTH );
217                 wday    = rtc_read( RTC_DAY_OF_WEEK );
218                 mon     = rtc_read( RTC_MONTH );
219                 year    = rtc_read( RTC_YEAR );
220                 century = rtc_read( RTC_CENTURY );
221
222                 /* unlock clock registers after read */
223                 rtc_write( RTC_CONTROLA, ( reg_a & ~RTC_CA_READ ));
224
225                 tmp->tm_sec  = bcd2bin( sec  & 0x7F );
226                 tmp->tm_min  = bcd2bin( min  & 0x7F );
227                 tmp->tm_hour = bcd2bin( hour & 0x3F );
228                 tmp->tm_mday = bcd2bin( mday & 0x3F );
229                 tmp->tm_mon  = bcd2bin( mon & 0x1F );
230                 tmp->tm_wday = bcd2bin( wday & 0x07 );
231
232                 if (century_flag) {
233                         tmp->tm_year = bcd2bin( year ) +
234                                 ( bcd2bin( century & 0x3F ) * 100 );
235                 } else {
236                         tmp->tm_year = bcd2bin( year ) + 1900;
237                         if (tmp->tm_year < 1970) tmp->tm_year += 100;
238                 }
239
240                 tmp->tm_yday = 0;
241                 tmp->tm_isdst= 0;
242         }
243
244         return 0;
245 }
246
247 int rtc_set( struct rtc_time *tmp )
248 {
249         if (phantom_flag < 0)
250                 phantom_flag = get_phantom_flag();
251
252         if (phantom_flag) {
253                 uint year;
254                 unsigned char rtc[8];
255
256                 year = tmp->tm_year;
257                 year -= (year < 2000) ? 1900 : 2000;
258
259                 rtc[0] = bin2bcd(0);
260                 rtc[1] = bin2bcd(tmp->tm_sec);
261                 rtc[2] = bin2bcd(tmp->tm_min);
262                 rtc[3] = bin2bcd(tmp->tm_hour);
263                 rtc[4] = bin2bcd(tmp->tm_wday);
264                 rtc[5] = bin2bcd(tmp->tm_mday);
265                 rtc[6] = bin2bcd(tmp->tm_mon);
266                 rtc[7] = bin2bcd(year);
267
268                 phantom_rtc_write(RTC_BASE, rtc);
269         } else {
270                 uchar reg_a;
271                 if (century_flag < 0)
272                         century_flag = get_century_flag();
273
274                 /* lock clock registers for write */
275                 reg_a = rtc_read( RTC_CONTROLA );
276                 rtc_write( RTC_CONTROLA, ( reg_a | RTC_CA_WRITE ));
277
278                 rtc_write( RTC_MONTH, bin2bcd( tmp->tm_mon ));
279
280                 rtc_write( RTC_DAY_OF_WEEK, bin2bcd( tmp->tm_wday ));
281                 rtc_write( RTC_DAY_OF_MONTH, bin2bcd( tmp->tm_mday ));
282                 rtc_write( RTC_HOURS, bin2bcd( tmp->tm_hour ));
283                 rtc_write( RTC_MINUTES, bin2bcd( tmp->tm_min ));
284                 rtc_write( RTC_SECONDS, bin2bcd( tmp->tm_sec ));
285
286                 /* break year up into century and year in century */
287                 if (century_flag) {
288                         rtc_write( RTC_YEAR, bin2bcd( tmp->tm_year % 100 ));
289                         rtc_write( RTC_CENTURY, bin2bcd( tmp->tm_year / 100 ));
290                         reg_a &= 0xc0;
291                         reg_a |= bin2bcd( tmp->tm_year / 100 );
292                 } else {
293                         rtc_write(RTC_YEAR, bin2bcd(tmp->tm_year -
294                                 ((tmp->tm_year < 2000) ? 1900 : 2000)));
295                 }
296
297                 /* unlock clock registers after read */
298                 rtc_write( RTC_CONTROLA, ( reg_a  & ~RTC_CA_WRITE ));
299         }
300
301         return 0;
302 }
303
304 #endif