Add qemu 2.4.0
[kvmfornfv.git] / qemu / roms / u-boot / board / etin / debris / phantom.c
diff --git a/qemu/roms/u-boot/board/etin/debris/phantom.c b/qemu/roms/u-boot/board/etin/debris/phantom.c
new file mode 100644 (file)
index 0000000..3d5aa14
--- /dev/null
@@ -0,0 +1,301 @@
+/*
+ * board/eva/phantom.c
+ *
+ * Phantom RTC device driver for EVA
+ *
+ * Author: Sangmoon Kim
+ *         dogoil@etinsys.com
+ *
+ * Copyright 2002 Etinsys Inc.
+ *
+ * SPDX-License-Identifier:    GPL-2.0+
+ */
+
+#include <common.h>
+#include <command.h>
+#include <rtc.h>
+
+#if defined(CONFIG_CMD_DATE)
+
+#define RTC_BASE (CONFIG_SYS_NVRAM_BASE_ADDR + 0x7fff8)
+
+#define RTC_YEAR                ( RTC_BASE + 7 )
+#define RTC_MONTH               ( RTC_BASE + 6 )
+#define RTC_DAY_OF_MONTH        ( RTC_BASE + 5 )
+#define RTC_DAY_OF_WEEK         ( RTC_BASE + 4 )
+#define RTC_HOURS               ( RTC_BASE + 3 )
+#define RTC_MINUTES             ( RTC_BASE + 2 )
+#define RTC_SECONDS             ( RTC_BASE + 1 )
+#define RTC_CENTURY             ( RTC_BASE + 0 )
+
+#define RTC_CONTROLA            RTC_CENTURY
+#define RTC_CONTROLB            RTC_SECONDS
+#define RTC_CONTROLC            RTC_DAY_OF_WEEK
+
+#define RTC_CA_WRITE            0x80
+#define RTC_CA_READ             0x40
+
+#define RTC_CB_OSC_DISABLE      0x80
+
+#define RTC_CC_BATTERY_FLAG     0x80
+#define RTC_CC_FREQ_TEST        0x40
+
+
+static int phantom_flag = -1;
+static int century_flag = -1;
+
+static uchar rtc_read(unsigned int addr)
+{
+       return *(volatile unsigned char *)(addr);
+}
+
+static void rtc_write(unsigned int addr, uchar val)
+{
+       *(volatile unsigned char *)(addr) = val;
+}
+
+static unsigned char phantom_rtc_sequence[] = {
+       0xc5, 0x3a, 0xa3, 0x5c, 0xc5, 0x3a, 0xa3, 0x5c
+};
+
+static unsigned char* phantom_rtc_read(int addr, unsigned char rtc[8])
+{
+       int i, j;
+       unsigned char v;
+       unsigned char save = rtc_read(addr);
+
+       for (j = 0; j < 8; j++) {
+               v = phantom_rtc_sequence[j];
+               for (i = 0; i < 8; i++) {
+                       rtc_write(addr, v & 1);
+                       v >>= 1;
+               }
+       }
+       for (j = 0; j < 8; j++) {
+               v = 0;
+               for (i = 0; i < 8; i++) {
+                       if(rtc_read(addr) & 1)
+                               v |= 1 << i;
+               }
+               rtc[j] = v;
+       }
+       rtc_write(addr, save);
+       return rtc;
+}
+
+static void phantom_rtc_write(int addr, unsigned char rtc[8])
+{
+       int i, j;
+       unsigned char v;
+       unsigned char save = rtc_read(addr);
+       for (j = 0; j < 8; j++) {
+               v = phantom_rtc_sequence[j];
+               for (i = 0; i < 8; i++) {
+                       rtc_write(addr, v & 1);
+                       v >>= 1;
+               }
+       }
+       for (j = 0; j < 8; j++) {
+               v = rtc[j];
+               for (i = 0; i < 8; i++) {
+                       rtc_write(addr, v & 1);
+                       v >>= 1;
+               }
+       }
+       rtc_write(addr, save);
+}
+
+static int get_phantom_flag(void)
+{
+       int i;
+       unsigned char rtc[8];
+
+       phantom_rtc_read(RTC_BASE, rtc);
+
+       for(i = 1; i < 8; i++) {
+               if (rtc[i] != rtc[0])
+                       return 1;
+       }
+       return 0;
+}
+
+void rtc_reset(void)
+{
+       if (phantom_flag < 0)
+               phantom_flag = get_phantom_flag();
+
+       if (phantom_flag) {
+               unsigned char rtc[8];
+               phantom_rtc_read(RTC_BASE, rtc);
+               if(rtc[4] & 0x30) {
+                       printf( "real-time-clock was stopped. Now starting...\n" );
+                       rtc[4] &= 0x07;
+                       phantom_rtc_write(RTC_BASE, rtc);
+               }
+       } else {
+               uchar reg_a, reg_b, reg_c;
+               reg_a = rtc_read( RTC_CONTROLA );
+               reg_b = rtc_read( RTC_CONTROLB );
+
+               if ( reg_b & RTC_CB_OSC_DISABLE )
+               {
+                       printf( "real-time-clock was stopped. Now starting...\n" );
+                       reg_a |= RTC_CA_WRITE;
+                       reg_b &= ~RTC_CB_OSC_DISABLE;
+                       rtc_write( RTC_CONTROLA, reg_a );
+                       rtc_write( RTC_CONTROLB, reg_b );
+               }
+
+               /* make sure read/write clock register bits are cleared */
+               reg_a &= ~( RTC_CA_WRITE | RTC_CA_READ );
+               rtc_write( RTC_CONTROLA, reg_a );
+
+               reg_c = rtc_read( RTC_CONTROLC );
+               if (( reg_c & RTC_CC_BATTERY_FLAG ) == 0 )
+                       printf( "RTC battery low. Clock setting may not be reliable.\n");
+       }
+}
+
+static int get_century_flag(void)
+{
+       int flag = 0;
+       int bcd, century;
+       bcd = rtc_read( RTC_CENTURY );
+       century = bcd2bin( bcd & 0x3F );
+       rtc_write( RTC_CENTURY, bin2bcd(century+1));
+       if (bcd == rtc_read( RTC_CENTURY ))
+               flag = 1;
+       rtc_write( RTC_CENTURY, bcd);
+       return flag;
+}
+
+int rtc_get( struct rtc_time *tmp)
+{
+       if (phantom_flag < 0)
+               phantom_flag = get_phantom_flag();
+
+       if (phantom_flag)
+       {
+               unsigned char rtc[8];
+
+               phantom_rtc_read(RTC_BASE, rtc);
+
+               tmp->tm_sec     = bcd2bin(rtc[1] & 0x7f);
+               tmp->tm_min     = bcd2bin(rtc[2] & 0x7f);
+               tmp->tm_hour    = bcd2bin(rtc[3] & 0x1f);
+               tmp->tm_wday    = bcd2bin(rtc[4] & 0x7);
+               tmp->tm_mday    = bcd2bin(rtc[5] & 0x3f);
+               tmp->tm_mon     = bcd2bin(rtc[6] & 0x1f);
+               tmp->tm_year    = bcd2bin(rtc[7]) + 1900;
+               tmp->tm_yday = 0;
+               tmp->tm_isdst = 0;
+
+               if( (rtc[3] & 0x80)  && (rtc[3] & 0x40) ) tmp->tm_hour += 12;
+               if (tmp->tm_year < 1970) tmp->tm_year += 100;
+       } else {
+               uchar sec, min, hour;
+               uchar mday, wday, mon, year;
+
+               int century;
+
+               uchar reg_a;
+
+               if (century_flag < 0)
+                       century_flag = get_century_flag();
+
+               reg_a = rtc_read( RTC_CONTROLA );
+               /* lock clock registers for read */
+               rtc_write( RTC_CONTROLA, ( reg_a | RTC_CA_READ ));
+
+               sec     = rtc_read( RTC_SECONDS );
+               min     = rtc_read( RTC_MINUTES );
+               hour    = rtc_read( RTC_HOURS );
+               mday    = rtc_read( RTC_DAY_OF_MONTH );
+               wday    = rtc_read( RTC_DAY_OF_WEEK );
+               mon     = rtc_read( RTC_MONTH );
+               year    = rtc_read( RTC_YEAR );
+               century = rtc_read( RTC_CENTURY );
+
+               /* unlock clock registers after read */
+               rtc_write( RTC_CONTROLA, ( reg_a & ~RTC_CA_READ ));
+
+               tmp->tm_sec  = bcd2bin( sec  & 0x7F );
+               tmp->tm_min  = bcd2bin( min  & 0x7F );
+               tmp->tm_hour = bcd2bin( hour & 0x3F );
+               tmp->tm_mday = bcd2bin( mday & 0x3F );
+               tmp->tm_mon  = bcd2bin( mon & 0x1F );
+               tmp->tm_wday = bcd2bin( wday & 0x07 );
+
+               if (century_flag) {
+                       tmp->tm_year = bcd2bin( year ) +
+                               ( bcd2bin( century & 0x3F ) * 100 );
+               } else {
+                       tmp->tm_year = bcd2bin( year ) + 1900;
+                       if (tmp->tm_year < 1970) tmp->tm_year += 100;
+               }
+
+               tmp->tm_yday = 0;
+               tmp->tm_isdst= 0;
+       }
+
+       return 0;
+}
+
+int rtc_set( struct rtc_time *tmp )
+{
+       if (phantom_flag < 0)
+               phantom_flag = get_phantom_flag();
+
+       if (phantom_flag) {
+               uint year;
+               unsigned char rtc[8];
+
+               year = tmp->tm_year;
+               year -= (year < 2000) ? 1900 : 2000;
+
+               rtc[0] = bin2bcd(0);
+               rtc[1] = bin2bcd(tmp->tm_sec);
+               rtc[2] = bin2bcd(tmp->tm_min);
+               rtc[3] = bin2bcd(tmp->tm_hour);
+               rtc[4] = bin2bcd(tmp->tm_wday);
+               rtc[5] = bin2bcd(tmp->tm_mday);
+               rtc[6] = bin2bcd(tmp->tm_mon);
+               rtc[7] = bin2bcd(year);
+
+               phantom_rtc_write(RTC_BASE, rtc);
+       } else {
+               uchar reg_a;
+               if (century_flag < 0)
+                       century_flag = get_century_flag();
+
+               /* lock clock registers for write */
+               reg_a = rtc_read( RTC_CONTROLA );
+               rtc_write( RTC_CONTROLA, ( reg_a | RTC_CA_WRITE ));
+
+               rtc_write( RTC_MONTH, bin2bcd( tmp->tm_mon ));
+
+               rtc_write( RTC_DAY_OF_WEEK, bin2bcd( tmp->tm_wday ));
+               rtc_write( RTC_DAY_OF_MONTH, bin2bcd( tmp->tm_mday ));
+               rtc_write( RTC_HOURS, bin2bcd( tmp->tm_hour ));
+               rtc_write( RTC_MINUTES, bin2bcd( tmp->tm_min ));
+               rtc_write( RTC_SECONDS, bin2bcd( tmp->tm_sec ));
+
+               /* break year up into century and year in century */
+               if (century_flag) {
+                       rtc_write( RTC_YEAR, bin2bcd( tmp->tm_year % 100 ));
+                       rtc_write( RTC_CENTURY, bin2bcd( tmp->tm_year / 100 ));
+                       reg_a &= 0xc0;
+                       reg_a |= bin2bcd( tmp->tm_year / 100 );
+               } else {
+                       rtc_write(RTC_YEAR, bin2bcd(tmp->tm_year -
+                               ((tmp->tm_year < 2000) ? 1900 : 2000)));
+               }
+
+               /* unlock clock registers after read */
+               rtc_write( RTC_CONTROLA, ( reg_a  & ~RTC_CA_WRITE ));
+       }
+
+       return 0;
+}
+
+#endif