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