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