rtc.c 2.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293
  1. /*
  2. * arch/sh/boards/landisk/rtc.c -- RTC support
  3. *
  4. * Copyright (C) 2000 Philipp Rumpf <prumpf@tux.org>
  5. * Copyright (C) 1999 Tetsuya Okada & Niibe Yutaka
  6. */
  7. /*
  8. * modifed by kogiidena
  9. * 2005.09.16
  10. */
  11. #include <linux/config.h>
  12. #include <linux/init.h>
  13. #include <linux/kernel.h>
  14. #include <linux/sched.h>
  15. #include <linux/time.h>
  16. #include <linux/delay.h>
  17. #include <linux/spinlock.h>
  18. #include <linux/bcd.h>
  19. #include <asm/rtc.h>
  20. extern spinlock_t rtc_lock;
  21. extern void
  22. rs5c313_set_cmos_time(unsigned int BCD_yr, unsigned int BCD_mon,
  23. unsigned int BCD_day, unsigned int BCD_hr,
  24. unsigned int BCD_min, unsigned int BCD_sec);
  25. extern unsigned long
  26. rs5c313_get_cmos_time(unsigned int *BCD_yr, unsigned int *BCD_mon,
  27. unsigned int *BCD_day, unsigned int *BCD_hr,
  28. unsigned int *BCD_min, unsigned int *BCD_sec);
  29. void landisk_rtc_gettimeofday(struct timespec *tv)
  30. {
  31. unsigned int BCD_yr, BCD_mon, BCD_day, BCD_hr, BCD_min, BCD_sec;
  32. unsigned long flags;
  33. spin_lock_irqsave(&rtc_lock, flags);
  34. tv->tv_sec = rs5c313_get_cmos_time
  35. (&BCD_yr, &BCD_mon, &BCD_day, &BCD_hr, &BCD_min, &BCD_sec);
  36. tv->tv_nsec = 0;
  37. spin_unlock_irqrestore(&rtc_lock, flags);
  38. }
  39. int landisk_rtc_settimeofday(const time_t secs)
  40. {
  41. int retval = 0;
  42. int real_seconds, real_minutes, cmos_minutes;
  43. unsigned long flags;
  44. unsigned long nowtime = secs;
  45. unsigned int BCD_yr, BCD_mon, BCD_day, BCD_hr, BCD_min, BCD_sec;
  46. spin_lock_irqsave(&rtc_lock, flags);
  47. rs5c313_get_cmos_time
  48. (&BCD_yr, &BCD_mon, &BCD_day, &BCD_hr, &BCD_min, &BCD_sec);
  49. cmos_minutes = BCD_min;
  50. BCD_TO_BIN(cmos_minutes);
  51. /*
  52. * since we're only adjusting minutes and seconds,
  53. * don't interfere with hour overflow. This avoids
  54. * messing with unknown time zones but requires your
  55. * RTC not to be off by more than 15 minutes
  56. */
  57. real_seconds = nowtime % 60;
  58. real_minutes = nowtime / 60;
  59. if (((abs(real_minutes - cmos_minutes) + 15) / 30) & 1)
  60. real_minutes += 30; /* correct for half hour time zone */
  61. real_minutes %= 60;
  62. if (abs(real_minutes - cmos_minutes) < 30) {
  63. BIN_TO_BCD(real_seconds);
  64. BIN_TO_BCD(real_minutes);
  65. rs5c313_set_cmos_time(BCD_yr, BCD_mon, BCD_day, BCD_hr,
  66. real_minutes, real_seconds);
  67. } else {
  68. printk(KERN_WARNING
  69. "set_rtc_time: can't update from %d to %d\n",
  70. cmos_minutes, real_minutes);
  71. retval = -1;
  72. }
  73. spin_unlock_irqrestore(&rtc_lock, flags);
  74. return retval;
  75. }
  76. void landisk_time_init(void)
  77. {
  78. rtc_sh_get_time = landisk_rtc_gettimeofday;
  79. rtc_sh_set_time = landisk_rtc_settimeofday;
  80. }