diff options
author | Benjamin Herrenschmidt <benh@kernel.crashing.org> | 2005-11-13 23:49:48 -0500 |
---|---|---|
committer | Paul Mackerras <paulus@samba.org> | 2005-11-14 00:36:08 -0500 |
commit | 3136254ca5dfaf53486f7032c674f9b6d7fd1d53 (patch) | |
tree | 101934218e83511dc2783e02d1a458ec85d98da9 /arch/powerpc/kernel/rtas-rtc.c | |
parent | 0c37ec2aa88bd8a6aaeb284ff5c86f4c6d8e8469 (diff) |
[PATCH] powerpc: kill ppc64 rtc.c, use genrtc instead
This moves the rtas RTC callbacks to rtas-rtc.c in arch/powerpc/kernel,
and kills the rest of arch/ppc64/kernel/rtc.c which was just a duplicate
of the genrtc functionality. Also enable build of genrtc for
CONFIG_PPC64 (it just works are we already have the required callbacks)
and enable it in all defconfigs.
Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Signed-off-by: Paul Mackerras <paulus@samba.org>
Diffstat (limited to 'arch/powerpc/kernel/rtas-rtc.c')
-rw-r--r-- | arch/powerpc/kernel/rtas-rtc.c | 105 |
1 files changed, 105 insertions, 0 deletions
diff --git a/arch/powerpc/kernel/rtas-rtc.c b/arch/powerpc/kernel/rtas-rtc.c new file mode 100644 index 000000000000..7b948662704c --- /dev/null +++ b/arch/powerpc/kernel/rtas-rtc.c | |||
@@ -0,0 +1,105 @@ | |||
1 | #include <linux/kernel.h> | ||
2 | #include <linux/time.h> | ||
3 | #include <linux/timer.h> | ||
4 | #include <linux/init.h> | ||
5 | #include <linux/rtc.h> | ||
6 | #include <linux/delay.h> | ||
7 | #include <asm/prom.h> | ||
8 | #include <asm/rtas.h> | ||
9 | #include <asm/time.h> | ||
10 | |||
11 | |||
12 | #define MAX_RTC_WAIT 5000 /* 5 sec */ | ||
13 | #define RTAS_CLOCK_BUSY (-2) | ||
14 | unsigned long __init rtas_get_boot_time(void) | ||
15 | { | ||
16 | int ret[8]; | ||
17 | int error, wait_time; | ||
18 | unsigned long max_wait_tb; | ||
19 | |||
20 | max_wait_tb = get_tb() + tb_ticks_per_usec * 1000 * MAX_RTC_WAIT; | ||
21 | do { | ||
22 | error = rtas_call(rtas_token("get-time-of-day"), 0, 8, ret); | ||
23 | if (error == RTAS_CLOCK_BUSY || rtas_is_extended_busy(error)) { | ||
24 | wait_time = rtas_extended_busy_delay_time(error); | ||
25 | /* This is boot time so we spin. */ | ||
26 | udelay(wait_time*1000); | ||
27 | error = RTAS_CLOCK_BUSY; | ||
28 | } | ||
29 | } while (error == RTAS_CLOCK_BUSY && (get_tb() < max_wait_tb)); | ||
30 | |||
31 | if (error != 0 && printk_ratelimit()) { | ||
32 | printk(KERN_WARNING "error: reading the clock failed (%d)\n", | ||
33 | error); | ||
34 | return 0; | ||
35 | } | ||
36 | |||
37 | return mktime(ret[0], ret[1], ret[2], ret[3], ret[4], ret[5]); | ||
38 | } | ||
39 | |||
40 | /* NOTE: get_rtc_time will get an error if executed in interrupt context | ||
41 | * and if a delay is needed to read the clock. In this case we just | ||
42 | * silently return without updating rtc_tm. | ||
43 | */ | ||
44 | void rtas_get_rtc_time(struct rtc_time *rtc_tm) | ||
45 | { | ||
46 | int ret[8]; | ||
47 | int error, wait_time; | ||
48 | unsigned long max_wait_tb; | ||
49 | |||
50 | max_wait_tb = get_tb() + tb_ticks_per_usec * 1000 * MAX_RTC_WAIT; | ||
51 | do { | ||
52 | error = rtas_call(rtas_token("get-time-of-day"), 0, 8, ret); | ||
53 | if (error == RTAS_CLOCK_BUSY || rtas_is_extended_busy(error)) { | ||
54 | if (in_interrupt() && printk_ratelimit()) { | ||
55 | memset(&rtc_tm, 0, sizeof(struct rtc_time)); | ||
56 | printk(KERN_WARNING "error: reading clock" | ||
57 | " would delay interrupt\n"); | ||
58 | return; /* delay not allowed */ | ||
59 | } | ||
60 | wait_time = rtas_extended_busy_delay_time(error); | ||
61 | msleep(wait_time); | ||
62 | error = RTAS_CLOCK_BUSY; | ||
63 | } | ||
64 | } while (error == RTAS_CLOCK_BUSY && (get_tb() < max_wait_tb)); | ||
65 | |||
66 | if (error != 0 && printk_ratelimit()) { | ||
67 | printk(KERN_WARNING "error: reading the clock failed (%d)\n", | ||
68 | error); | ||
69 | return; | ||
70 | } | ||
71 | |||
72 | rtc_tm->tm_sec = ret[5]; | ||
73 | rtc_tm->tm_min = ret[4]; | ||
74 | rtc_tm->tm_hour = ret[3]; | ||
75 | rtc_tm->tm_mday = ret[2]; | ||
76 | rtc_tm->tm_mon = ret[1] - 1; | ||
77 | rtc_tm->tm_year = ret[0] - 1900; | ||
78 | } | ||
79 | |||
80 | int rtas_set_rtc_time(struct rtc_time *tm) | ||
81 | { | ||
82 | int error, wait_time; | ||
83 | unsigned long max_wait_tb; | ||
84 | |||
85 | max_wait_tb = get_tb() + tb_ticks_per_usec * 1000 * MAX_RTC_WAIT; | ||
86 | do { | ||
87 | error = rtas_call(rtas_token("set-time-of-day"), 7, 1, NULL, | ||
88 | tm->tm_year + 1900, tm->tm_mon + 1, | ||
89 | tm->tm_mday, tm->tm_hour, tm->tm_min, | ||
90 | tm->tm_sec, 0); | ||
91 | if (error == RTAS_CLOCK_BUSY || rtas_is_extended_busy(error)) { | ||
92 | if (in_interrupt()) | ||
93 | return 1; /* probably decrementer */ | ||
94 | wait_time = rtas_extended_busy_delay_time(error); | ||
95 | msleep(wait_time); | ||
96 | error = RTAS_CLOCK_BUSY; | ||
97 | } | ||
98 | } while (error == RTAS_CLOCK_BUSY && (get_tb() < max_wait_tb)); | ||
99 | |||
100 | if (error != 0 && printk_ratelimit()) | ||
101 | printk(KERN_WARNING "error: setting the clock failed (%d)\n", | ||
102 | error); | ||
103 | |||
104 | return 0; | ||
105 | } | ||