source: SVN/rincon/u-boot/board/etin/debris/phantom.c @ 55

Last change on this file since 55 was 55, checked in by Tim Harvey, 22 months ago

rincon: added latest u-boot source

restored form server backup

Signed-off-by: Tim Harvey <tharvey@…>

File size: 7.2 KB
Line 
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 (CFG_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
47static int phantom_flag = -1;
48static int century_flag = -1;
49
50static uchar rtc_read(unsigned int addr)
51{
52        return *(volatile unsigned char *)(addr);
53}
54
55static void rtc_write(unsigned int addr, uchar val)
56{
57        *(volatile unsigned char *)(addr) = val;
58}
59
60static unsigned char phantom_rtc_sequence[] = {
61        0xc5, 0x3a, 0xa3, 0x5c, 0xc5, 0x3a, 0xa3, 0x5c
62};
63
64static 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
89static 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
111static 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
125void 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
162inline unsigned bcd2bin (uchar n)
163{
164        return ((((n >> 4) & 0x0F) * 10) + (n & 0x0F));
165}
166
167inline unsigned char bin2bcd (unsigned int n)
168{
169        return (((n / 10) << 4) | (n % 10));
170}
171
172static int get_century_flag(void)
173{
174        int flag = 0;
175        int bcd, century;
176        bcd = rtc_read( RTC_CENTURY );
177        century = bcd2bin( bcd & 0x3F );
178        rtc_write( RTC_CENTURY, bin2bcd(century+1));
179        if (bcd == rtc_read( RTC_CENTURY ))
180                flag = 1;
181        rtc_write( RTC_CENTURY, bcd);
182        return flag;
183}
184
185int rtc_get( struct rtc_time *tmp)
186{
187        if (phantom_flag < 0)
188                phantom_flag = get_phantom_flag();
189
190        if (phantom_flag)
191        {
192                unsigned char rtc[8];
193
194                phantom_rtc_read(RTC_BASE, rtc);
195
196                tmp->tm_sec     = bcd2bin(rtc[1] & 0x7f);
197                tmp->tm_min     = bcd2bin(rtc[2] & 0x7f);
198                tmp->tm_hour    = bcd2bin(rtc[3] & 0x1f);
199                tmp->tm_wday    = bcd2bin(rtc[4] & 0x7);
200                tmp->tm_mday    = bcd2bin(rtc[5] & 0x3f);
201                tmp->tm_mon     = bcd2bin(rtc[6] & 0x1f);
202                tmp->tm_year    = bcd2bin(rtc[7]) + 1900;
203                tmp->tm_yday = 0;
204                tmp->tm_isdst = 0;
205
206                if( (rtc[3] & 0x80)  && (rtc[3] & 0x40) ) tmp->tm_hour += 12;
207                if (tmp->tm_year < 1970) tmp->tm_year += 100;
208        } else {
209                uchar sec, min, hour;
210                uchar mday, wday, mon, year;
211
212                int century;
213
214                uchar reg_a;
215
216                if (century_flag < 0)
217                        century_flag = get_century_flag();
218
219                reg_a = rtc_read( RTC_CONTROLA );
220                /* lock clock registers for read */
221                rtc_write( RTC_CONTROLA, ( reg_a | RTC_CA_READ ));
222
223                sec     = rtc_read( RTC_SECONDS );
224                min     = rtc_read( RTC_MINUTES );
225                hour    = rtc_read( RTC_HOURS );
226                mday    = rtc_read( RTC_DAY_OF_MONTH );
227                wday    = rtc_read( RTC_DAY_OF_WEEK );
228                mon     = rtc_read( RTC_MONTH );
229                year    = rtc_read( RTC_YEAR );
230                century = rtc_read( RTC_CENTURY );
231
232                /* unlock clock registers after read */
233                rtc_write( RTC_CONTROLA, ( reg_a & ~RTC_CA_READ ));
234
235                tmp->tm_sec  = bcd2bin( sec  & 0x7F );
236                tmp->tm_min  = bcd2bin( min  & 0x7F );
237                tmp->tm_hour = bcd2bin( hour & 0x3F );
238                tmp->tm_mday = bcd2bin( mday & 0x3F );
239                tmp->tm_mon  = bcd2bin( mon & 0x1F );
240                tmp->tm_wday = bcd2bin( wday & 0x07 );
241
242                if (century_flag) {
243                        tmp->tm_year = bcd2bin( year ) +
244                                ( bcd2bin( century & 0x3F ) * 100 );
245                } else {
246                        tmp->tm_year = bcd2bin( year ) + 1900;
247                        if (tmp->tm_year < 1970) tmp->tm_year += 100;
248                }
249
250                tmp->tm_yday = 0;
251                tmp->tm_isdst= 0;
252        }
253
254        return 0;
255}
256
257int rtc_set( struct rtc_time *tmp )
258{
259        if (phantom_flag < 0)
260                phantom_flag = get_phantom_flag();
261
262        if (phantom_flag) {
263                uint year;
264                unsigned char rtc[8];
265
266                year = tmp->tm_year;
267                year -= (year < 2000) ? 1900 : 2000;
268
269                rtc[0] = bin2bcd(0);
270                rtc[1] = bin2bcd(tmp->tm_sec);
271                rtc[2] = bin2bcd(tmp->tm_min);
272                rtc[3] = bin2bcd(tmp->tm_hour);
273                rtc[4] = bin2bcd(tmp->tm_wday);
274                rtc[5] = bin2bcd(tmp->tm_mday);
275                rtc[6] = bin2bcd(tmp->tm_mon);
276                rtc[7] = bin2bcd(year);
277
278                phantom_rtc_write(RTC_BASE, rtc);
279        } else {
280                uchar reg_a;
281                if (century_flag < 0)
282                        century_flag = get_century_flag();
283
284                /* lock clock registers for write */
285                reg_a = rtc_read( RTC_CONTROLA );
286                rtc_write( RTC_CONTROLA, ( reg_a | RTC_CA_WRITE ));
287
288                rtc_write( RTC_MONTH, bin2bcd( tmp->tm_mon ));
289
290                rtc_write( RTC_DAY_OF_WEEK, bin2bcd( tmp->tm_wday ));
291                rtc_write( RTC_DAY_OF_MONTH, bin2bcd( tmp->tm_mday ));
292                rtc_write( RTC_HOURS, bin2bcd( tmp->tm_hour ));
293                rtc_write( RTC_MINUTES, bin2bcd( tmp->tm_min ));
294                rtc_write( RTC_SECONDS, bin2bcd( tmp->tm_sec ));
295
296                /* break year up into century and year in century */
297                if (century_flag) {
298                        rtc_write( RTC_YEAR, bin2bcd( tmp->tm_year % 100 ));
299                        rtc_write( RTC_CENTURY, bin2bcd( tmp->tm_year / 100 ));
300                        reg_a &= 0xc0;
301                        reg_a |= bin2bcd( tmp->tm_year / 100 );
302                } else {
303                        rtc_write(RTC_YEAR, bin2bcd(tmp->tm_year -
304                                ((tmp->tm_year < 2000) ? 1900 : 2000)));
305                }
306
307                /* unlock clock registers after read */
308                rtc_write( RTC_CONTROLA, ( reg_a  & ~RTC_CA_WRITE ));
309        }
310
311        return 0;
312}
313
314#endif
Note: See TracBrowser for help on using the repository browser.