3737#include <asm/dec/machtype.h>
3838
3939
40+ /*
41+ * Returns true if a clock update is in progress
42+ */
43+ static inline unsigned char dec_rtc_is_updating (void )
44+ {
45+ unsigned char uip ;
46+ unsigned long flags ;
47+
48+ spin_lock_irqsave (& rtc_lock , flags );
49+ uip = (CMOS_READ (RTC_FREQ_SELECT ) & RTC_UIP );
50+ spin_unlock_irqrestore (& rtc_lock , flags );
51+ return uip ;
52+ }
53+
4054static unsigned long dec_rtc_get_time (void )
4155{
4256 unsigned int year , mon , day , hour , min , sec , real_year ;
4357 int i ;
58+ unsigned long flags ;
4459
4560 /* The Linux interpretation of the DS1287 clock register contents:
4661 * When the Update-In-Progress (UIP) flag goes from 1 to 0, the
@@ -49,11 +64,12 @@ static unsigned long dec_rtc_get_time(void)
4964 */
5065 /* read RTC exactly on falling edge of update flag */
5166 for (i = 0 ; i < 1000000 ; i ++ ) /* may take up to 1 second... */
52- if (CMOS_READ ( RTC_FREQ_SELECT ) & RTC_UIP )
67+ if (dec_rtc_is_updating () )
5368 break ;
5469 for (i = 0 ; i < 1000000 ; i ++ ) /* must try at least 2.228 ms */
55- if (!( CMOS_READ ( RTC_FREQ_SELECT ) & RTC_UIP ))
70+ if (!dec_rtc_is_updating ( ))
5671 break ;
72+ spin_lock_irqsave (& rtc_lock , flags );
5773 /* Isn't this overkill? UIP above should guarantee consistency */
5874 do {
5975 sec = CMOS_READ (RTC_SECONDS );
@@ -77,6 +93,7 @@ static unsigned long dec_rtc_get_time(void)
7793 * of unused BBU RAM locations.
7894 */
7995 real_year = CMOS_READ (RTC_DEC_YEAR );
96+ spin_unlock_irqrestore (& rtc_lock , flags );
8097 year += real_year - 72 + 2000 ;
8198
8299 return mktime (year , mon , day , hour , min , sec );
@@ -95,6 +112,8 @@ static int dec_rtc_set_mmss(unsigned long nowtime)
95112 int real_seconds , real_minutes , cmos_minutes ;
96113 unsigned char save_control , save_freq_select ;
97114
115+ /* irq are locally disabled here */
116+ spin_lock (& rtc_lock );
98117 /* tell the clock it's being set */
99118 save_control = CMOS_READ (RTC_CONTROL );
100119 CMOS_WRITE ((save_control | RTC_SET ), RTC_CONTROL );
@@ -141,6 +160,7 @@ static int dec_rtc_set_mmss(unsigned long nowtime)
141160 */
142161 CMOS_WRITE (save_control , RTC_CONTROL );
143162 CMOS_WRITE (save_freq_select , RTC_FREQ_SELECT );
163+ spin_unlock (& rtc_lock );
144164
145165 return retval ;
146166}
0 commit comments