rtc-aica.c
上传用户:lgb322
上传日期:2013-02-24
资源大小:30529k
文件大小:2k
源码类别:

嵌入式Linux

开发平台:

Unix_Linux

  1. /* arch/sh/kernel/rtc-aica.c
  2.  *
  3.  * Dreamcast AICA RTC routines.
  4.  *
  5.  * Copyright (c) 2001 M. R. Brown <mrbrown@0xd6.org>
  6.  *
  7.  * Released under the terms of the GNU GPL v2.0.
  8.  *
  9.  */
  10. #include <linux/time.h>
  11. #include <asm/io.h>
  12. /* The AICA RTC has an Epoch of 1/1/1950, so we must subtract 20 years (in
  13.    seconds to get the standard Unix Epoch when getting the time, and add 20
  14.    years when setting the time. */
  15. #define TWENTY_YEARS ((20 * 365LU + 5) * 86400)
  16. /* The AICA RTC is represented by a 32-bit seconds counter stored in 2 16-bit
  17.    registers.*/
  18. #define AICA_RTC_SECS_H 0xa0710000
  19. #define AICA_RTC_SECS_L 0xa0710004
  20. /**
  21.  * aica_rtc_gettimeofday - Get the time from the AICA RTC
  22.  * @tv: pointer to resulting timeval
  23.  *
  24.  * Grabs the current RTC seconds counter and adjusts it to the Unix Epoch.
  25.  */
  26. void aica_rtc_gettimeofday(struct timeval *tv) {
  27. unsigned long val1, val2;
  28. do {
  29. val1 = ((ctrl_inl(AICA_RTC_SECS_H) & 0xffff) << 16) |
  30. (ctrl_inl(AICA_RTC_SECS_L) & 0xffff);
  31. val2 = ((ctrl_inl(AICA_RTC_SECS_H) & 0xffff) << 16) |
  32. (ctrl_inl(AICA_RTC_SECS_L) & 0xffff);
  33. } while (val1 != val2);
  34. tv->tv_sec = val1 - TWENTY_YEARS;
  35. /* Can't get microseconds with just a seconds counter. */
  36. tv->tv_usec = 0;
  37. }
  38. /**
  39.  * aica_rtc_settimeofday - Set the AICA RTC to the current time
  40.  * @tv: contains the timeval to set
  41.  *
  42.  * Adjusts the given @tv to the AICA Epoch and sets the RTC seconds counter.
  43.  */
  44. int aica_rtc_settimeofday(const struct timeval *tv) {
  45. unsigned long val1, val2;
  46. unsigned long secs = tv->tv_sec + TWENTY_YEARS;
  47. do {
  48. ctrl_outl((secs & 0xffff0000) >> 16, AICA_RTC_SECS_H);
  49. ctrl_outl((secs & 0xffff), AICA_RTC_SECS_L);
  50. val1 = ((ctrl_inl(AICA_RTC_SECS_H) & 0xffff) << 16) |
  51. (ctrl_inl(AICA_RTC_SECS_L) & 0xffff);
  52. val2 = ((ctrl_inl(AICA_RTC_SECS_H) & 0xffff) << 16) |
  53. (ctrl_inl(AICA_RTC_SECS_L) & 0xffff);
  54. } while (val1 != val2);
  55. return 0;
  56. }