rtc.c 2.5 KB

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