diff options
Diffstat (limited to 'arch/x86/kernel/time_64.c')
-rw-r--r-- | arch/x86/kernel/time_64.c | 41 |
1 files changed, 22 insertions, 19 deletions
diff --git a/arch/x86/kernel/time_64.c b/arch/x86/kernel/time_64.c index c821edc32216..368b1942b39a 100644 --- a/arch/x86/kernel/time_64.c +++ b/arch/x86/kernel/time_64.c | |||
@@ -82,18 +82,15 @@ static int set_rtc_mmss(unsigned long nowtime) | |||
82 | int retval = 0; | 82 | int retval = 0; |
83 | int real_seconds, real_minutes, cmos_minutes; | 83 | int real_seconds, real_minutes, cmos_minutes; |
84 | unsigned char control, freq_select; | 84 | unsigned char control, freq_select; |
85 | unsigned long flags; | ||
85 | 86 | ||
86 | /* | 87 | /* |
87 | * IRQs are disabled when we're called from the timer interrupt, | 88 | * set_rtc_mmss is called when irqs are enabled, so disable irqs here |
88 | * no need for spin_lock_irqsave() | ||
89 | */ | 89 | */ |
90 | 90 | spin_lock_irqsave(&rtc_lock, flags); | |
91 | spin_lock(&rtc_lock); | ||
92 | |||
93 | /* | 91 | /* |
94 | * Tell the clock it's being set and stop it. | 92 | * Tell the clock it's being set and stop it. |
95 | */ | 93 | */ |
96 | |||
97 | control = CMOS_READ(RTC_CONTROL); | 94 | control = CMOS_READ(RTC_CONTROL); |
98 | CMOS_WRITE(control | RTC_SET, RTC_CONTROL); | 95 | CMOS_WRITE(control | RTC_SET, RTC_CONTROL); |
99 | 96 | ||
@@ -138,7 +135,7 @@ static int set_rtc_mmss(unsigned long nowtime) | |||
138 | CMOS_WRITE(control, RTC_CONTROL); | 135 | CMOS_WRITE(control, RTC_CONTROL); |
139 | CMOS_WRITE(freq_select, RTC_FREQ_SELECT); | 136 | CMOS_WRITE(freq_select, RTC_FREQ_SELECT); |
140 | 137 | ||
141 | spin_unlock(&rtc_lock); | 138 | spin_unlock_irqrestore(&rtc_lock, flags); |
142 | 139 | ||
143 | return retval; | 140 | return retval; |
144 | } | 141 | } |
@@ -164,21 +161,27 @@ unsigned long read_persistent_clock(void) | |||
164 | unsigned century = 0; | 161 | unsigned century = 0; |
165 | 162 | ||
166 | spin_lock_irqsave(&rtc_lock, flags); | 163 | spin_lock_irqsave(&rtc_lock, flags); |
164 | /* | ||
165 | * if UIP is clear, then we have >= 244 microseconds before RTC | ||
166 | * registers will be updated. Spec sheet says that this is the | ||
167 | * reliable way to read RTC - registers invalid (off bus) during update | ||
168 | */ | ||
169 | while ((CMOS_READ(RTC_FREQ_SELECT) & RTC_UIP)) | ||
170 | cpu_relax(); | ||
167 | 171 | ||
168 | do { | 172 | |
169 | sec = CMOS_READ(RTC_SECONDS); | 173 | /* now read all RTC registers while stable with interrupts disabled */ |
170 | min = CMOS_READ(RTC_MINUTES); | 174 | sec = CMOS_READ(RTC_SECONDS); |
171 | hour = CMOS_READ(RTC_HOURS); | 175 | min = CMOS_READ(RTC_MINUTES); |
172 | day = CMOS_READ(RTC_DAY_OF_MONTH); | 176 | hour = CMOS_READ(RTC_HOURS); |
173 | mon = CMOS_READ(RTC_MONTH); | 177 | day = CMOS_READ(RTC_DAY_OF_MONTH); |
174 | year = CMOS_READ(RTC_YEAR); | 178 | mon = CMOS_READ(RTC_MONTH); |
179 | year = CMOS_READ(RTC_YEAR); | ||
175 | #ifdef CONFIG_ACPI | 180 | #ifdef CONFIG_ACPI |
176 | if (acpi_gbl_FADT.header.revision >= FADT2_REVISION_ID && | 181 | if (acpi_gbl_FADT.header.revision >= FADT2_REVISION_ID && |
177 | acpi_gbl_FADT.century) | 182 | acpi_gbl_FADT.century) |
178 | century = CMOS_READ(acpi_gbl_FADT.century); | 183 | century = CMOS_READ(acpi_gbl_FADT.century); |
179 | #endif | 184 | #endif |
180 | } while (sec != CMOS_READ(RTC_SECONDS)); | ||
181 | |||
182 | spin_unlock_irqrestore(&rtc_lock, flags); | 185 | spin_unlock_irqrestore(&rtc_lock, flags); |
183 | 186 | ||
184 | /* | 187 | /* |