phantom.c 7.2 KB

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