aboutsummaryrefslogtreecommitdiffstats
path: root/arch/x86/kernel/time_64.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/x86/kernel/time_64.c')
-rw-r--r--arch/x86/kernel/time_64.c41
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 /*