uboot/board/etin/debris/phantom.c
<<
>>
Prefs
   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
  44static int phantom_flag = -1;
  45static int century_flag = -1;
  46
  47static uchar rtc_read(unsigned int addr)
  48{
  49        return *(volatile unsigned char *)(addr);
  50}
  51
  52static void rtc_write(unsigned int addr, uchar val)
  53{
  54        *(volatile unsigned char *)(addr) = val;
  55}
  56
  57static unsigned char phantom_rtc_sequence[] = {
  58        0xc5, 0x3a, 0xa3, 0x5c, 0xc5, 0x3a, 0xa3, 0x5c
  59};
  60
  61static 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
  86static 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
 108static 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
 122void 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
 159static 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
 172int 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
 244int 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
 302