diff options
author | Thomas Gleixner <tglx@linutronix.de> | 2008-01-30 07:30:27 -0500 |
---|---|---|
committer | Ingo Molnar <mingo@elte.hu> | 2008-01-30 07:30:27 -0500 |
commit | 1122b134bcd6e77c5a4117952b8cbc55c8d018bc (patch) | |
tree | e4b0df9c7fb4686357a33c00d037898725ab5b82 /arch/x86/kernel/time_64.c | |
parent | fe599f9fbc5d470ec5b55d08f2bbb991ddecbbc8 (diff) |
x86: share rtc code
Remove the rtc code from time_64.c and add the extra bits to the
i386 path. The ACPI century check is probably valid for i386 as
well, but this is material for a separate patch.
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Signed-off-by: Ingo Molnar <mingo@elte.hu>
Diffstat (limited to 'arch/x86/kernel/time_64.c')
-rw-r--r-- | arch/x86/kernel/time_64.c | 157 |
1 files changed, 0 insertions, 157 deletions
diff --git a/arch/x86/kernel/time_64.c b/arch/x86/kernel/time_64.c index 0a01504586a5..64cd03ed9bfc 100644 --- a/arch/x86/kernel/time_64.c +++ b/arch/x86/kernel/time_64.c | |||
@@ -46,9 +46,6 @@ | |||
46 | #include <asm/nmi.h> | 46 | #include <asm/nmi.h> |
47 | #include <asm/vgtod.h> | 47 | #include <asm/vgtod.h> |
48 | 48 | ||
49 | DEFINE_SPINLOCK(rtc_lock); | ||
50 | EXPORT_SYMBOL(rtc_lock); | ||
51 | |||
52 | volatile unsigned long __jiffies __section_jiffies = INITIAL_JIFFIES; | 49 | volatile unsigned long __jiffies __section_jiffies = INITIAL_JIFFIES; |
53 | 50 | ||
54 | unsigned long profile_pc(struct pt_regs *regs) | 51 | unsigned long profile_pc(struct pt_regs *regs) |
@@ -69,103 +66,6 @@ unsigned long profile_pc(struct pt_regs *regs) | |||
69 | } | 66 | } |
70 | EXPORT_SYMBOL(profile_pc); | 67 | EXPORT_SYMBOL(profile_pc); |
71 | 68 | ||
72 | /* Routines for accessing the CMOS RAM/RTC. */ | ||
73 | unsigned char rtc_cmos_read(unsigned char addr) | ||
74 | { | ||
75 | unsigned char val; | ||
76 | lock_cmos_prefix(addr); | ||
77 | outb_p(addr, RTC_PORT(0)); | ||
78 | val = inb_p(RTC_PORT(1)); | ||
79 | lock_cmos_suffix(addr); | ||
80 | return val; | ||
81 | } | ||
82 | EXPORT_SYMBOL(rtc_cmos_read); | ||
83 | |||
84 | void rtc_cmos_write(unsigned char val, unsigned char addr) | ||
85 | { | ||
86 | lock_cmos_prefix(addr); | ||
87 | outb_p(addr, RTC_PORT(0)); | ||
88 | outb_p(val, RTC_PORT(1)); | ||
89 | lock_cmos_suffix(addr); | ||
90 | } | ||
91 | EXPORT_SYMBOL(rtc_cmos_write); | ||
92 | |||
93 | /* | ||
94 | * In order to set the CMOS clock precisely, set_rtc_mmss has to be called 500 | ||
95 | * ms after the second nowtime has started, because when nowtime is written | ||
96 | * into the registers of the CMOS clock, it will jump to the next second | ||
97 | * precisely 500 ms later. Check the Motorola MC146818A or Dallas DS12887 data | ||
98 | * sheet for details. | ||
99 | */ | ||
100 | |||
101 | static int set_rtc_mmss(unsigned long nowtime) | ||
102 | { | ||
103 | int retval = 0; | ||
104 | int real_seconds, real_minutes, cmos_minutes; | ||
105 | unsigned char control, freq_select; | ||
106 | unsigned long flags; | ||
107 | |||
108 | /* | ||
109 | * set_rtc_mmss is called when irqs are enabled, so disable irqs here | ||
110 | */ | ||
111 | spin_lock_irqsave(&rtc_lock, flags); | ||
112 | /* | ||
113 | * Tell the clock it's being set and stop it. | ||
114 | */ | ||
115 | control = CMOS_READ(RTC_CONTROL); | ||
116 | CMOS_WRITE(control | RTC_SET, RTC_CONTROL); | ||
117 | |||
118 | freq_select = CMOS_READ(RTC_FREQ_SELECT); | ||
119 | CMOS_WRITE(freq_select | RTC_DIV_RESET2, RTC_FREQ_SELECT); | ||
120 | |||
121 | cmos_minutes = CMOS_READ(RTC_MINUTES); | ||
122 | BCD_TO_BIN(cmos_minutes); | ||
123 | |||
124 | /* | ||
125 | * since we're only adjusting minutes and seconds, don't interfere with hour | ||
126 | * overflow. This avoids messing with unknown time zones but requires your RTC | ||
127 | * not to be off by more than 15 minutes. Since we're calling it only when | ||
128 | * our clock is externally synchronized using NTP, this shouldn't be a problem. | ||
129 | */ | ||
130 | |||
131 | real_seconds = nowtime % 60; | ||
132 | real_minutes = nowtime / 60; | ||
133 | if (((abs(real_minutes - cmos_minutes) + 15) / 30) & 1) | ||
134 | real_minutes += 30; /* correct for half hour time zone */ | ||
135 | real_minutes %= 60; | ||
136 | |||
137 | if (abs(real_minutes - cmos_minutes) >= 30) { | ||
138 | printk(KERN_WARNING "time.c: can't update CMOS clock " | ||
139 | "from %d to %d\n", cmos_minutes, real_minutes); | ||
140 | retval = -1; | ||
141 | } else { | ||
142 | BIN_TO_BCD(real_seconds); | ||
143 | BIN_TO_BCD(real_minutes); | ||
144 | CMOS_WRITE(real_seconds, RTC_SECONDS); | ||
145 | CMOS_WRITE(real_minutes, RTC_MINUTES); | ||
146 | } | ||
147 | |||
148 | /* | ||
149 | * The following flags have to be released exactly in this order, otherwise the | ||
150 | * DS12887 (popular MC146818A clone with integrated battery and quartz) will | ||
151 | * not reset the oscillator and will not update precisely 500 ms later. You | ||
152 | * won't find this mentioned in the Dallas Semiconductor data sheets, but who | ||
153 | * believes data sheets anyway ... -- Markus Kuhn | ||
154 | */ | ||
155 | |||
156 | CMOS_WRITE(control, RTC_CONTROL); | ||
157 | CMOS_WRITE(freq_select, RTC_FREQ_SELECT); | ||
158 | |||
159 | spin_unlock_irqrestore(&rtc_lock, flags); | ||
160 | |||
161 | return retval; | ||
162 | } | ||
163 | |||
164 | int update_persistent_clock(struct timespec now) | ||
165 | { | ||
166 | return set_rtc_mmss(now.tv_sec); | ||
167 | } | ||
168 | |||
169 | static irqreturn_t timer_event_interrupt(int irq, void *dev_id) | 69 | static irqreturn_t timer_event_interrupt(int irq, void *dev_id) |
170 | { | 70 | { |
171 | add_pda(irq0_irqs, 1); | 71 | add_pda(irq0_irqs, 1); |
@@ -175,63 +75,6 @@ static irqreturn_t timer_event_interrupt(int irq, void *dev_id) | |||
175 | return IRQ_HANDLED; | 75 | return IRQ_HANDLED; |
176 | } | 76 | } |
177 | 77 | ||
178 | unsigned long read_persistent_clock(void) | ||
179 | { | ||
180 | unsigned int year, mon, day, hour, min, sec; | ||
181 | unsigned long flags; | ||
182 | unsigned century = 0; | ||
183 | |||
184 | spin_lock_irqsave(&rtc_lock, flags); | ||
185 | /* | ||
186 | * if UIP is clear, then we have >= 244 microseconds before RTC | ||
187 | * registers will be updated. Spec sheet says that this is the | ||
188 | * reliable way to read RTC - registers invalid (off bus) during update | ||
189 | */ | ||
190 | while ((CMOS_READ(RTC_FREQ_SELECT) & RTC_UIP)) | ||
191 | cpu_relax(); | ||
192 | |||
193 | |||
194 | /* now read all RTC registers while stable with interrupts disabled */ | ||
195 | sec = CMOS_READ(RTC_SECONDS); | ||
196 | min = CMOS_READ(RTC_MINUTES); | ||
197 | hour = CMOS_READ(RTC_HOURS); | ||
198 | day = CMOS_READ(RTC_DAY_OF_MONTH); | ||
199 | mon = CMOS_READ(RTC_MONTH); | ||
200 | year = CMOS_READ(RTC_YEAR); | ||
201 | #ifdef CONFIG_ACPI | ||
202 | if (acpi_gbl_FADT.header.revision >= FADT2_REVISION_ID && | ||
203 | acpi_gbl_FADT.century) | ||
204 | century = CMOS_READ(acpi_gbl_FADT.century); | ||
205 | #endif | ||
206 | spin_unlock_irqrestore(&rtc_lock, flags); | ||
207 | |||
208 | /* | ||
209 | * We know that x86-64 always uses BCD format, no need to check the | ||
210 | * config register. | ||
211 | */ | ||
212 | |||
213 | BCD_TO_BIN(sec); | ||
214 | BCD_TO_BIN(min); | ||
215 | BCD_TO_BIN(hour); | ||
216 | BCD_TO_BIN(day); | ||
217 | BCD_TO_BIN(mon); | ||
218 | BCD_TO_BIN(year); | ||
219 | |||
220 | if (century) { | ||
221 | BCD_TO_BIN(century); | ||
222 | year += century * 100; | ||
223 | printk(KERN_INFO "Extended CMOS year: %d\n", century * 100); | ||
224 | } else { | ||
225 | /* | ||
226 | * x86-64 systems only exists since 2002. | ||
227 | * This will work up to Dec 31, 2100 | ||
228 | */ | ||
229 | year += 2000; | ||
230 | } | ||
231 | |||
232 | return mktime(year, mon, day, hour, min, sec); | ||
233 | } | ||
234 | |||
235 | /* calibrate_cpu is used on systems with fixed rate TSCs to determine | 78 | /* calibrate_cpu is used on systems with fixed rate TSCs to determine |
236 | * processor frequency */ | 79 | * processor frequency */ |
237 | #define TICK_COUNT 100000000 | 80 | #define TICK_COUNT 100000000 |