aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--arch/mips/ddb5xxx/common/rtc_ds1386.c6
-rw-r--r--arch/mips/dec/time.c24
-rw-r--r--arch/mips/jmr3927/common/rtc_ds1742.c6
-rw-r--r--arch/mips/lasat/ds1603.c9
-rw-r--r--arch/mips/momentum/jaguar_atx/setup.c6
-rw-r--r--arch/mips/momentum/ocelot_3/setup.c6
-rw-r--r--arch/mips/momentum/ocelot_c/setup.c6
-rw-r--r--arch/mips/pmc-sierra/yosemite/setup.c6
-rw-r--r--arch/mips/sgi-ip22/ip22-time.c6
-rw-r--r--arch/mips/sibyte/swarm/rtc_m41t81.c7
-rw-r--r--arch/mips/sibyte/swarm/rtc_xicor1241.c6
-rw-r--r--include/asm-mips/mc146818-time.h24
-rw-r--r--include/asm-mips/time.h3
13 files changed, 111 insertions, 4 deletions
diff --git a/arch/mips/ddb5xxx/common/rtc_ds1386.c b/arch/mips/ddb5xxx/common/rtc_ds1386.c
index f5b11508ff2f..995896ac0e39 100644
--- a/arch/mips/ddb5xxx/common/rtc_ds1386.c
+++ b/arch/mips/ddb5xxx/common/rtc_ds1386.c
@@ -41,7 +41,9 @@ rtc_ds1386_get_time(void)
41 u8 byte; 41 u8 byte;
42 u8 temp; 42 u8 temp;
43 unsigned int year, month, day, hour, minute, second; 43 unsigned int year, month, day, hour, minute, second;
44 unsigned long flags;
44 45
46 spin_lock_irqsave(&rtc_lock, flags);
45 /* let us freeze external registers */ 47 /* let us freeze external registers */
46 byte = READ_RTC(0xB); 48 byte = READ_RTC(0xB);
47 byte &= 0x3f; 49 byte &= 0x3f;
@@ -60,6 +62,7 @@ rtc_ds1386_get_time(void)
60 /* enable time transfer */ 62 /* enable time transfer */
61 byte |= 0x80; 63 byte |= 0x80;
62 WRITE_RTC(0xB, byte); 64 WRITE_RTC(0xB, byte);
65 spin_unlock_irqrestore(&rtc_lock, flags);
63 66
64 /* calc hour */ 67 /* calc hour */
65 if (temp & 0x40) { 68 if (temp & 0x40) {
@@ -81,7 +84,9 @@ rtc_ds1386_set_time(unsigned long t)
81 u8 byte; 84 u8 byte;
82 u8 temp; 85 u8 temp;
83 u8 year, month, day, hour, minute, second; 86 u8 year, month, day, hour, minute, second;
87 unsigned long flags;
84 88
89 spin_lock_irqsave(&rtc_lock, flags);
85 /* let us freeze external registers */ 90 /* let us freeze external registers */
86 byte = READ_RTC(0xB); 91 byte = READ_RTC(0xB);
87 byte &= 0x3f; 92 byte &= 0x3f;
@@ -133,6 +138,7 @@ rtc_ds1386_set_time(unsigned long t)
133 if (second != READ_RTC(0x1)) { 138 if (second != READ_RTC(0x1)) {
134 WRITE_RTC(0x1, second); 139 WRITE_RTC(0x1, second);
135 } 140 }
141 spin_unlock_irqrestore(&rtc_lock, flags);
136 142
137 return 0; 143 return 0;
138} 144}
diff --git a/arch/mips/dec/time.c b/arch/mips/dec/time.c
index dc7091caa7aa..174822344131 100644
--- a/arch/mips/dec/time.c
+++ b/arch/mips/dec/time.c
@@ -37,10 +37,25 @@
37#include <asm/dec/machtype.h> 37#include <asm/dec/machtype.h>
38 38
39 39
40/*
41 * Returns true if a clock update is in progress
42 */
43static 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
40static unsigned long dec_rtc_get_time(void) 54static unsigned long dec_rtc_get_time(void)
41{ 55{
42 unsigned int year, mon, day, hour, min, sec, real_year; 56 unsigned int year, mon, day, hour, min, sec, real_year;
43 int i; 57 int i;
58 unsigned long flags;
44 59
45 /* The Linux interpretation of the DS1287 clock register contents: 60 /* The Linux interpretation of the DS1287 clock register contents:
46 * When the Update-In-Progress (UIP) flag goes from 1 to 0, the 61 * 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)
49 */ 64 */
50 /* read RTC exactly on falling edge of update flag */ 65 /* read RTC exactly on falling edge of update flag */
51 for (i = 0; i < 1000000; i++) /* may take up to 1 second... */ 66 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())
53 break; 68 break;
54 for (i = 0; i < 1000000; i++) /* must try at least 2.228 ms */ 69 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())
56 break; 71 break;
72 spin_lock_irqsave(&rtc_lock, flags);
57 /* Isn't this overkill? UIP above should guarantee consistency */ 73 /* Isn't this overkill? UIP above should guarantee consistency */
58 do { 74 do {
59 sec = CMOS_READ(RTC_SECONDS); 75 sec = CMOS_READ(RTC_SECONDS);
@@ -77,6 +93,7 @@ static unsigned long dec_rtc_get_time(void)
77 * of unused BBU RAM locations. 93 * of unused BBU RAM locations.
78 */ 94 */
79 real_year = CMOS_READ(RTC_DEC_YEAR); 95 real_year = CMOS_READ(RTC_DEC_YEAR);
96 spin_unlock_irqrestore(&rtc_lock, flags);
80 year += real_year - 72 + 2000; 97 year += real_year - 72 + 2000;
81 98
82 return mktime(year, mon, day, hour, min, sec); 99 return mktime(year, mon, day, hour, min, sec);
@@ -95,6 +112,8 @@ static int dec_rtc_set_mmss(unsigned long nowtime)
95 int real_seconds, real_minutes, cmos_minutes; 112 int real_seconds, real_minutes, cmos_minutes;
96 unsigned char save_control, save_freq_select; 113 unsigned char save_control, save_freq_select;
97 114
115 /* irq are locally disabled here */
116 spin_lock(&rtc_lock);
98 /* tell the clock it's being set */ 117 /* tell the clock it's being set */
99 save_control = CMOS_READ(RTC_CONTROL); 118 save_control = CMOS_READ(RTC_CONTROL);
100 CMOS_WRITE((save_control | RTC_SET), RTC_CONTROL); 119 CMOS_WRITE((save_control | RTC_SET), RTC_CONTROL);
@@ -141,6 +160,7 @@ static int dec_rtc_set_mmss(unsigned long nowtime)
141 */ 160 */
142 CMOS_WRITE(save_control, RTC_CONTROL); 161 CMOS_WRITE(save_control, RTC_CONTROL);
143 CMOS_WRITE(save_freq_select, RTC_FREQ_SELECT); 162 CMOS_WRITE(save_freq_select, RTC_FREQ_SELECT);
163 spin_unlock(&rtc_lock);
144 164
145 return retval; 165 return retval;
146} 166}
diff --git a/arch/mips/jmr3927/common/rtc_ds1742.c b/arch/mips/jmr3927/common/rtc_ds1742.c
index 1ae4318e1358..8b407d7dc460 100644
--- a/arch/mips/jmr3927/common/rtc_ds1742.c
+++ b/arch/mips/jmr3927/common/rtc_ds1742.c
@@ -57,7 +57,9 @@ rtc_ds1742_get_time(void)
57{ 57{
58 unsigned int year, month, day, hour, minute, second; 58 unsigned int year, month, day, hour, minute, second;
59 unsigned int century; 59 unsigned int century;
60 unsigned long flags;
60 61
62 spin_lock_irqsave(&rtc_lock, flags);
61 CMOS_WRITE(RTC_READ, RTC_CONTROL); 63 CMOS_WRITE(RTC_READ, RTC_CONTROL);
62 second = BCD2BIN(CMOS_READ(RTC_SECONDS) & RTC_SECONDS_MASK); 64 second = BCD2BIN(CMOS_READ(RTC_SECONDS) & RTC_SECONDS_MASK);
63 minute = BCD2BIN(CMOS_READ(RTC_MINUTES)); 65 minute = BCD2BIN(CMOS_READ(RTC_MINUTES));
@@ -67,6 +69,7 @@ rtc_ds1742_get_time(void)
67 year = BCD2BIN(CMOS_READ(RTC_YEAR)); 69 year = BCD2BIN(CMOS_READ(RTC_YEAR));
68 century = BCD2BIN(CMOS_READ(RTC_CENTURY) & RTC_CENTURY_MASK); 70 century = BCD2BIN(CMOS_READ(RTC_CENTURY) & RTC_CENTURY_MASK);
69 CMOS_WRITE(0, RTC_CONTROL); 71 CMOS_WRITE(0, RTC_CONTROL);
72 spin_unlock_irqrestore(&rtc_lock, flags);
70 73
71 year += century * 100; 74 year += century * 100;
72 75
@@ -81,7 +84,9 @@ rtc_ds1742_set_time(unsigned long t)
81 u8 year, month, day, hour, minute, second; 84 u8 year, month, day, hour, minute, second;
82 u8 cmos_year, cmos_month, cmos_day, cmos_hour, cmos_minute, cmos_second; 85 u8 cmos_year, cmos_month, cmos_day, cmos_hour, cmos_minute, cmos_second;
83 int cmos_century; 86 int cmos_century;
87 unsigned long flags;
84 88
89 spin_lock_irqsave(&rtc_lock, flags);
85 CMOS_WRITE(RTC_READ, RTC_CONTROL); 90 CMOS_WRITE(RTC_READ, RTC_CONTROL);
86 cmos_second = (u8)(CMOS_READ(RTC_SECONDS) & RTC_SECONDS_MASK); 91 cmos_second = (u8)(CMOS_READ(RTC_SECONDS) & RTC_SECONDS_MASK);
87 cmos_minute = (u8)CMOS_READ(RTC_MINUTES); 92 cmos_minute = (u8)CMOS_READ(RTC_MINUTES);
@@ -139,6 +144,7 @@ rtc_ds1742_set_time(unsigned long t)
139 144
140 /* RTC_CENTURY and RTC_CONTROL share same address... */ 145 /* RTC_CENTURY and RTC_CONTROL share same address... */
141 CMOS_WRITE(cmos_century, RTC_CONTROL); 146 CMOS_WRITE(cmos_century, RTC_CONTROL);
147 spin_unlock_irqrestore(&rtc_lock, flags);
142 148
143 return 0; 149 return 0;
144} 150}
diff --git a/arch/mips/lasat/ds1603.c b/arch/mips/lasat/ds1603.c
index 9d7812e03dcd..7dced67c55eb 100644
--- a/arch/mips/lasat/ds1603.c
+++ b/arch/mips/lasat/ds1603.c
@@ -8,6 +8,7 @@
8#include <asm/lasat/lasat.h> 8#include <asm/lasat/lasat.h>
9#include <linux/delay.h> 9#include <linux/delay.h>
10#include <asm/lasat/ds1603.h> 10#include <asm/lasat/ds1603.h>
11#include <asm/time.h>
11 12
12#include "ds1603.h" 13#include "ds1603.h"
13 14
@@ -138,19 +139,27 @@ static void rtc_end_op(void)
138unsigned long ds1603_read(void) 139unsigned long ds1603_read(void)
139{ 140{
140 unsigned long word; 141 unsigned long word;
142 unsigned long flags;
143
144 spin_lock_irqsave(&rtc_lock, flags);
141 rtc_init_op(); 145 rtc_init_op();
142 rtc_write_byte(READ_TIME_CMD); 146 rtc_write_byte(READ_TIME_CMD);
143 word = rtc_read_word(); 147 word = rtc_read_word();
144 rtc_end_op(); 148 rtc_end_op();
149 spin_unlock_irqrestore(&rtc_lock, flags);
145 return word; 150 return word;
146} 151}
147 152
148int ds1603_set(unsigned long time) 153int ds1603_set(unsigned long time)
149{ 154{
155 unsigned long flags;
156
157 spin_lock_irqsave(&rtc_lock, flags);
150 rtc_init_op(); 158 rtc_init_op();
151 rtc_write_byte(SET_TIME_CMD); 159 rtc_write_byte(SET_TIME_CMD);
152 rtc_write_word(time); 160 rtc_write_word(time);
153 rtc_end_op(); 161 rtc_end_op();
162 spin_unlock_irqrestore(&rtc_lock, flags);
154 163
155 return 0; 164 return 0;
156} 165}
diff --git a/arch/mips/momentum/jaguar_atx/setup.c b/arch/mips/momentum/jaguar_atx/setup.c
index 768bf4406452..bab192ddc185 100644
--- a/arch/mips/momentum/jaguar_atx/setup.c
+++ b/arch/mips/momentum/jaguar_atx/setup.c
@@ -149,7 +149,9 @@ arch_initcall(per_cpu_mappings);
149unsigned long m48t37y_get_time(void) 149unsigned long m48t37y_get_time(void)
150{ 150{
151 unsigned int year, month, day, hour, min, sec; 151 unsigned int year, month, day, hour, min, sec;
152 unsigned long flags;
152 153
154 spin_lock_irqsave(&rtc_lock, flags);
153 /* stop the update */ 155 /* stop the update */
154 rtc_base[0x7ff8] = 0x40; 156 rtc_base[0x7ff8] = 0x40;
155 157
@@ -166,6 +168,7 @@ unsigned long m48t37y_get_time(void)
166 168
167 /* start the update */ 169 /* start the update */
168 rtc_base[0x7ff8] = 0x00; 170 rtc_base[0x7ff8] = 0x00;
171 spin_unlock_irqrestore(&rtc_lock, flags);
169 172
170 return mktime(year, month, day, hour, min, sec); 173 return mktime(year, month, day, hour, min, sec);
171} 174}
@@ -173,11 +176,13 @@ unsigned long m48t37y_get_time(void)
173int m48t37y_set_time(unsigned long sec) 176int m48t37y_set_time(unsigned long sec)
174{ 177{
175 struct rtc_time tm; 178 struct rtc_time tm;
179 unsigned long flags;
176 180
177 /* convert to a more useful format -- note months count from 0 */ 181 /* convert to a more useful format -- note months count from 0 */
178 to_tm(sec, &tm); 182 to_tm(sec, &tm);
179 tm.tm_mon += 1; 183 tm.tm_mon += 1;
180 184
185 spin_lock_irqsave(&rtc_lock, flags);
181 /* enable writing */ 186 /* enable writing */
182 rtc_base[0x7ff8] = 0x80; 187 rtc_base[0x7ff8] = 0x80;
183 188
@@ -201,6 +206,7 @@ int m48t37y_set_time(unsigned long sec)
201 206
202 /* disable writing */ 207 /* disable writing */
203 rtc_base[0x7ff8] = 0x00; 208 rtc_base[0x7ff8] = 0x00;
209 spin_unlock_irqrestore(&rtc_lock, flags);
204 210
205 return 0; 211 return 0;
206} 212}
diff --git a/arch/mips/momentum/ocelot_3/setup.c b/arch/mips/momentum/ocelot_3/setup.c
index a7803e08f9db..c9b7ff8148ec 100644
--- a/arch/mips/momentum/ocelot_3/setup.c
+++ b/arch/mips/momentum/ocelot_3/setup.c
@@ -135,7 +135,9 @@ void setup_wired_tlb_entries(void)
135unsigned long m48t37y_get_time(void) 135unsigned long m48t37y_get_time(void)
136{ 136{
137 unsigned int year, month, day, hour, min, sec; 137 unsigned int year, month, day, hour, min, sec;
138 unsigned long flags;
138 139
140 spin_lock_irqsave(&rtc_lock, flags);
139 /* stop the update */ 141 /* stop the update */
140 rtc_base[0x7ff8] = 0x40; 142 rtc_base[0x7ff8] = 0x40;
141 143
@@ -152,6 +154,7 @@ unsigned long m48t37y_get_time(void)
152 154
153 /* start the update */ 155 /* start the update */
154 rtc_base[0x7ff8] = 0x00; 156 rtc_base[0x7ff8] = 0x00;
157 spin_unlock_irqrestore(&rtc_lock, flags);
155 158
156 return mktime(year, month, day, hour, min, sec); 159 return mktime(year, month, day, hour, min, sec);
157} 160}
@@ -159,11 +162,13 @@ unsigned long m48t37y_get_time(void)
159int m48t37y_set_time(unsigned long sec) 162int m48t37y_set_time(unsigned long sec)
160{ 163{
161 struct rtc_time tm; 164 struct rtc_time tm;
165 unsigned long flags;
162 166
163 /* convert to a more useful format -- note months count from 0 */ 167 /* convert to a more useful format -- note months count from 0 */
164 to_tm(sec, &tm); 168 to_tm(sec, &tm);
165 tm.tm_mon += 1; 169 tm.tm_mon += 1;
166 170
171 spin_lock_irqsave(&rtc_lock, flags);
167 /* enable writing */ 172 /* enable writing */
168 rtc_base[0x7ff8] = 0x80; 173 rtc_base[0x7ff8] = 0x80;
169 174
@@ -187,6 +192,7 @@ int m48t37y_set_time(unsigned long sec)
187 192
188 /* disable writing */ 193 /* disable writing */
189 rtc_base[0x7ff8] = 0x00; 194 rtc_base[0x7ff8] = 0x00;
195 spin_unlock_irqrestore(&rtc_lock, flags);
190 196
191 return 0; 197 return 0;
192} 198}
diff --git a/arch/mips/momentum/ocelot_c/setup.c b/arch/mips/momentum/ocelot_c/setup.c
index ce70fc96f160..2755c1547473 100644
--- a/arch/mips/momentum/ocelot_c/setup.c
+++ b/arch/mips/momentum/ocelot_c/setup.c
@@ -140,7 +140,9 @@ unsigned long m48t37y_get_time(void)
140 unsigned char* rtc_base = (unsigned char*)0xfc800000; 140 unsigned char* rtc_base = (unsigned char*)0xfc800000;
141#endif 141#endif
142 unsigned int year, month, day, hour, min, sec; 142 unsigned int year, month, day, hour, min, sec;
143 unsigned long flags;
143 144
145 spin_lock_irqsave(&rtc_lock, flags);
144 /* stop the update */ 146 /* stop the update */
145 rtc_base[0x7ff8] = 0x40; 147 rtc_base[0x7ff8] = 0x40;
146 148
@@ -157,6 +159,7 @@ unsigned long m48t37y_get_time(void)
157 159
158 /* start the update */ 160 /* start the update */
159 rtc_base[0x7ff8] = 0x00; 161 rtc_base[0x7ff8] = 0x00;
162 spin_unlock_irqrestore(&rtc_lock, flags);
160 163
161 return mktime(year, month, day, hour, min, sec); 164 return mktime(year, month, day, hour, min, sec);
162} 165}
@@ -169,11 +172,13 @@ int m48t37y_set_time(unsigned long sec)
169 unsigned char* rtc_base = (unsigned char*)0xfc800000; 172 unsigned char* rtc_base = (unsigned char*)0xfc800000;
170#endif 173#endif
171 struct rtc_time tm; 174 struct rtc_time tm;
175 unsigned long flags;
172 176
173 /* convert to a more useful format -- note months count from 0 */ 177 /* convert to a more useful format -- note months count from 0 */
174 to_tm(sec, &tm); 178 to_tm(sec, &tm);
175 tm.tm_mon += 1; 179 tm.tm_mon += 1;
176 180
181 spin_lock_irqsave(&rtc_lock, flags);
177 /* enable writing */ 182 /* enable writing */
178 rtc_base[0x7ff8] = 0x80; 183 rtc_base[0x7ff8] = 0x80;
179 184
@@ -197,6 +202,7 @@ int m48t37y_set_time(unsigned long sec)
197 202
198 /* disable writing */ 203 /* disable writing */
199 rtc_base[0x7ff8] = 0x00; 204 rtc_base[0x7ff8] = 0x00;
205 spin_unlock_irqrestore(&rtc_lock, flags);
200 206
201 return 0; 207 return 0;
202} 208}
diff --git a/arch/mips/pmc-sierra/yosemite/setup.c b/arch/mips/pmc-sierra/yosemite/setup.c
index bdc2ab55bed6..059755b5ed57 100644
--- a/arch/mips/pmc-sierra/yosemite/setup.c
+++ b/arch/mips/pmc-sierra/yosemite/setup.c
@@ -73,7 +73,9 @@ void __init bus_error_init(void)
73unsigned long m48t37y_get_time(void) 73unsigned long m48t37y_get_time(void)
74{ 74{
75 unsigned int year, month, day, hour, min, sec; 75 unsigned int year, month, day, hour, min, sec;
76 unsigned long flags;
76 77
78 spin_lock_irqsave(&rtc_lock, flags);
77 /* Stop the update to the time */ 79 /* Stop the update to the time */
78 m48t37_base->control = 0x40; 80 m48t37_base->control = 0x40;
79 81
@@ -88,6 +90,7 @@ unsigned long m48t37y_get_time(void)
88 90
89 /* Start the update to the time again */ 91 /* Start the update to the time again */
90 m48t37_base->control = 0x00; 92 m48t37_base->control = 0x00;
93 spin_unlock_irqrestore(&rtc_lock, flags);
91 94
92 return mktime(year, month, day, hour, min, sec); 95 return mktime(year, month, day, hour, min, sec);
93} 96}
@@ -95,11 +98,13 @@ unsigned long m48t37y_get_time(void)
95int m48t37y_set_time(unsigned long sec) 98int m48t37y_set_time(unsigned long sec)
96{ 99{
97 struct rtc_time tm; 100 struct rtc_time tm;
101 unsigned long flags;
98 102
99 /* convert to a more useful format -- note months count from 0 */ 103 /* convert to a more useful format -- note months count from 0 */
100 to_tm(sec, &tm); 104 to_tm(sec, &tm);
101 tm.tm_mon += 1; 105 tm.tm_mon += 1;
102 106
107 spin_lock_irqsave(&rtc_lock, flags);
103 /* enable writing */ 108 /* enable writing */
104 m48t37_base->control = 0x80; 109 m48t37_base->control = 0x80;
105 110
@@ -123,6 +128,7 @@ int m48t37y_set_time(unsigned long sec)
123 128
124 /* disable writing */ 129 /* disable writing */
125 m48t37_base->control = 0x00; 130 m48t37_base->control = 0x00;
131 spin_unlock_irqrestore(&rtc_lock, flags);
126 132
127 return 0; 133 return 0;
128} 134}
diff --git a/arch/mips/sgi-ip22/ip22-time.c b/arch/mips/sgi-ip22/ip22-time.c
index df9b5694328a..b7300cc5c5ad 100644
--- a/arch/mips/sgi-ip22/ip22-time.c
+++ b/arch/mips/sgi-ip22/ip22-time.c
@@ -35,7 +35,9 @@ static unsigned long indy_rtc_get_time(void)
35{ 35{
36 unsigned int yrs, mon, day, hrs, min, sec; 36 unsigned int yrs, mon, day, hrs, min, sec;
37 unsigned int save_control; 37 unsigned int save_control;
38 unsigned long flags;
38 39
40 spin_lock_irqsave(&rtc_lock, flags);
39 save_control = hpc3c0->rtcregs[RTC_CMD] & 0xff; 41 save_control = hpc3c0->rtcregs[RTC_CMD] & 0xff;
40 hpc3c0->rtcregs[RTC_CMD] = save_control | RTC_TE; 42 hpc3c0->rtcregs[RTC_CMD] = save_control | RTC_TE;
41 43
@@ -47,6 +49,7 @@ static unsigned long indy_rtc_get_time(void)
47 yrs = BCD2BIN(hpc3c0->rtcregs[RTC_YEAR] & 0xff); 49 yrs = BCD2BIN(hpc3c0->rtcregs[RTC_YEAR] & 0xff);
48 50
49 hpc3c0->rtcregs[RTC_CMD] = save_control; 51 hpc3c0->rtcregs[RTC_CMD] = save_control;
52 spin_unlock_irqrestore(&rtc_lock, flags);
50 53
51 if (yrs < 45) 54 if (yrs < 45)
52 yrs += 30; 55 yrs += 30;
@@ -60,6 +63,7 @@ static int indy_rtc_set_time(unsigned long tim)
60{ 63{
61 struct rtc_time tm; 64 struct rtc_time tm;
62 unsigned int save_control; 65 unsigned int save_control;
66 unsigned long flags;
63 67
64 to_tm(tim, &tm); 68 to_tm(tim, &tm);
65 69
@@ -68,6 +72,7 @@ static int indy_rtc_set_time(unsigned long tim)
68 if (tm.tm_year >= 100) 72 if (tm.tm_year >= 100)
69 tm.tm_year -= 100; 73 tm.tm_year -= 100;
70 74
75 spin_lock_irqsave(&rtc_lock, flags);
71 save_control = hpc3c0->rtcregs[RTC_CMD] & 0xff; 76 save_control = hpc3c0->rtcregs[RTC_CMD] & 0xff;
72 hpc3c0->rtcregs[RTC_CMD] = save_control | RTC_TE; 77 hpc3c0->rtcregs[RTC_CMD] = save_control | RTC_TE;
73 78
@@ -80,6 +85,7 @@ static int indy_rtc_set_time(unsigned long tim)
80 hpc3c0->rtcregs[RTC_HUNDREDTH_SECOND] = 0; 85 hpc3c0->rtcregs[RTC_HUNDREDTH_SECOND] = 0;
81 86
82 hpc3c0->rtcregs[RTC_CMD] = save_control; 87 hpc3c0->rtcregs[RTC_CMD] = save_control;
88 spin_unlock_irqrestore(&rtc_lock, flags);
83 89
84 return 0; 90 return 0;
85} 91}
diff --git a/arch/mips/sibyte/swarm/rtc_m41t81.c b/arch/mips/sibyte/swarm/rtc_m41t81.c
index 5b4fc26c1b36..c13914bdda59 100644
--- a/arch/mips/sibyte/swarm/rtc_m41t81.c
+++ b/arch/mips/sibyte/swarm/rtc_m41t81.c
@@ -144,6 +144,7 @@ static int m41t81_write(uint8_t addr, int b)
144int m41t81_set_time(unsigned long t) 144int m41t81_set_time(unsigned long t)
145{ 145{
146 struct rtc_time tm; 146 struct rtc_time tm;
147 unsigned long flags;
147 148
148 to_tm(t, &tm); 149 to_tm(t, &tm);
149 150
@@ -153,6 +154,7 @@ int m41t81_set_time(unsigned long t)
153 * believe we should finish writing min within a second. 154 * believe we should finish writing min within a second.
154 */ 155 */
155 156
157 spin_lock_irqsave(&rtc_lock, flags);
156 tm.tm_sec = BIN2BCD(tm.tm_sec); 158 tm.tm_sec = BIN2BCD(tm.tm_sec);
157 m41t81_write(M41T81REG_SC, tm.tm_sec); 159 m41t81_write(M41T81REG_SC, tm.tm_sec);
158 160
@@ -180,6 +182,7 @@ int m41t81_set_time(unsigned long t)
180 tm.tm_year %= 100; 182 tm.tm_year %= 100;
181 tm.tm_year = BIN2BCD(tm.tm_year); 183 tm.tm_year = BIN2BCD(tm.tm_year);
182 m41t81_write(M41T81REG_YR, tm.tm_year); 184 m41t81_write(M41T81REG_YR, tm.tm_year);
185 spin_unlock_irqrestore(&rtc_lock, flags);
183 186
184 return 0; 187 return 0;
185} 188}
@@ -187,19 +190,23 @@ int m41t81_set_time(unsigned long t)
187unsigned long m41t81_get_time(void) 190unsigned long m41t81_get_time(void)
188{ 191{
189 unsigned int year, mon, day, hour, min, sec; 192 unsigned int year, mon, day, hour, min, sec;
193 unsigned long flags;
190 194
191 /* 195 /*
192 * min is valid if two reads of sec are the same. 196 * min is valid if two reads of sec are the same.
193 */ 197 */
194 for (;;) { 198 for (;;) {
199 spin_lock_irqsave(&rtc_lock, flags);
195 sec = m41t81_read(M41T81REG_SC); 200 sec = m41t81_read(M41T81REG_SC);
196 min = m41t81_read(M41T81REG_MN); 201 min = m41t81_read(M41T81REG_MN);
197 if (sec == m41t81_read(M41T81REG_SC)) break; 202 if (sec == m41t81_read(M41T81REG_SC)) break;
203 spin_unlock_irqrestore(&rtc_lock, flags);
198 } 204 }
199 hour = m41t81_read(M41T81REG_HR) & 0x3f; 205 hour = m41t81_read(M41T81REG_HR) & 0x3f;
200 day = m41t81_read(M41T81REG_DT); 206 day = m41t81_read(M41T81REG_DT);
201 mon = m41t81_read(M41T81REG_MO); 207 mon = m41t81_read(M41T81REG_MO);
202 year = m41t81_read(M41T81REG_YR); 208 year = m41t81_read(M41T81REG_YR);
209 spin_unlock_irqrestore(&rtc_lock, flags);
203 210
204 sec = BCD2BIN(sec); 211 sec = BCD2BIN(sec);
205 min = BCD2BIN(min); 212 min = BCD2BIN(min);
diff --git a/arch/mips/sibyte/swarm/rtc_xicor1241.c b/arch/mips/sibyte/swarm/rtc_xicor1241.c
index d9ff9323f24e..f4a178836415 100644
--- a/arch/mips/sibyte/swarm/rtc_xicor1241.c
+++ b/arch/mips/sibyte/swarm/rtc_xicor1241.c
@@ -113,9 +113,11 @@ int xicor_set_time(unsigned long t)
113{ 113{
114 struct rtc_time tm; 114 struct rtc_time tm;
115 int tmp; 115 int tmp;
116 unsigned long flags;
116 117
117 to_tm(t, &tm); 118 to_tm(t, &tm);
118 119
120 spin_lock_irqsave(&rtc_lock, flags);
119 /* unlock writes to the CCR */ 121 /* unlock writes to the CCR */
120 xicor_write(X1241REG_SR, X1241REG_SR_WEL); 122 xicor_write(X1241REG_SR, X1241REG_SR_WEL);
121 xicor_write(X1241REG_SR, X1241REG_SR_WEL | X1241REG_SR_RWEL); 123 xicor_write(X1241REG_SR, X1241REG_SR_WEL | X1241REG_SR_RWEL);
@@ -160,6 +162,7 @@ int xicor_set_time(unsigned long t)
160 xicor_write(X1241REG_HR, tmp); 162 xicor_write(X1241REG_HR, tmp);
161 163
162 xicor_write(X1241REG_SR, 0); 164 xicor_write(X1241REG_SR, 0);
165 spin_unlock_irqrestore(&rtc_lock, flags);
163 166
164 return 0; 167 return 0;
165} 168}
@@ -167,7 +170,9 @@ int xicor_set_time(unsigned long t)
167unsigned long xicor_get_time(void) 170unsigned long xicor_get_time(void)
168{ 171{
169 unsigned int year, mon, day, hour, min, sec, y2k; 172 unsigned int year, mon, day, hour, min, sec, y2k;
173 unsigned long flags;
170 174
175 spin_lock_irqsave(&rtc_lock, flags);
171 sec = xicor_read(X1241REG_SC); 176 sec = xicor_read(X1241REG_SC);
172 min = xicor_read(X1241REG_MN); 177 min = xicor_read(X1241REG_MN);
173 hour = xicor_read(X1241REG_HR); 178 hour = xicor_read(X1241REG_HR);
@@ -183,6 +188,7 @@ unsigned long xicor_get_time(void)
183 mon = xicor_read(X1241REG_MO); 188 mon = xicor_read(X1241REG_MO);
184 year = xicor_read(X1241REG_YR); 189 year = xicor_read(X1241REG_YR);
185 y2k = xicor_read(X1241REG_Y2K); 190 y2k = xicor_read(X1241REG_Y2K);
191 spin_unlock_irqrestore(&rtc_lock, flags);
186 192
187 sec = BCD2BIN(sec); 193 sec = BCD2BIN(sec);
188 min = BCD2BIN(min); 194 min = BCD2BIN(min);
diff --git a/include/asm-mips/mc146818-time.h b/include/asm-mips/mc146818-time.h
index a2c2d2c24303..47214861093b 100644
--- a/include/asm-mips/mc146818-time.h
+++ b/include/asm-mips/mc146818-time.h
@@ -33,7 +33,9 @@ static inline int mc146818_set_rtc_mmss(unsigned long nowtime)
33 int real_seconds, real_minutes, cmos_minutes; 33 int real_seconds, real_minutes, cmos_minutes;
34 unsigned char save_control, save_freq_select; 34 unsigned char save_control, save_freq_select;
35 int retval = 0; 35 int retval = 0;
36 unsigned long flags;
36 37
38 spin_lock_irqsave(&rtc_lock, flags);
37 save_control = CMOS_READ(RTC_CONTROL); /* tell the clock it's being set */ 39 save_control = CMOS_READ(RTC_CONTROL); /* tell the clock it's being set */
38 CMOS_WRITE((save_control|RTC_SET), RTC_CONTROL); 40 CMOS_WRITE((save_control|RTC_SET), RTC_CONTROL);
39 41
@@ -79,14 +81,30 @@ static inline int mc146818_set_rtc_mmss(unsigned long nowtime)
79 */ 81 */
80 CMOS_WRITE(save_control, RTC_CONTROL); 82 CMOS_WRITE(save_control, RTC_CONTROL);
81 CMOS_WRITE(save_freq_select, RTC_FREQ_SELECT); 83 CMOS_WRITE(save_freq_select, RTC_FREQ_SELECT);
84 spin_unlock_irqrestore(&rtc_lock, flags);
82 85
83 return retval; 86 return retval;
84} 87}
85 88
89/*
90 * Returns true if a clock update is in progress
91 */
92static inline unsigned char rtc_is_updating(void)
93{
94 unsigned char uip;
95 unsigned long flags;
96
97 spin_lock_irqsave(&rtc_lock, flags);
98 uip = (CMOS_READ(RTC_FREQ_SELECT) & RTC_UIP);
99 spin_unlock_irqrestore(&rtc_lock, flags);
100 return uip;
101}
102
86static inline unsigned long mc146818_get_cmos_time(void) 103static inline unsigned long mc146818_get_cmos_time(void)
87{ 104{
88 unsigned int year, mon, day, hour, min, sec; 105 unsigned int year, mon, day, hour, min, sec;
89 int i; 106 int i;
107 unsigned long flags;
90 108
91 /* 109 /*
92 * The Linux interpretation of the CMOS clock register contents: 110 * The Linux interpretation of the CMOS clock register contents:
@@ -97,12 +115,13 @@ static inline unsigned long mc146818_get_cmos_time(void)
97 115
98 /* read RTC exactly on falling edge of update flag */ 116 /* read RTC exactly on falling edge of update flag */
99 for (i = 0 ; i < 1000000 ; i++) /* may take up to 1 second... */ 117 for (i = 0 ; i < 1000000 ; i++) /* may take up to 1 second... */
100 if (CMOS_READ(RTC_FREQ_SELECT) & RTC_UIP) 118 if (rtc_is_updating())
101 break; 119 break;
102 for (i = 0 ; i < 1000000 ; i++) /* must try at least 2.228 ms */ 120 for (i = 0 ; i < 1000000 ; i++) /* must try at least 2.228 ms */
103 if (!(CMOS_READ(RTC_FREQ_SELECT) & RTC_UIP)) 121 if (!rtc_is_updating())
104 break; 122 break;
105 123
124 spin_lock_irqsave(&rtc_lock, flags);
106 do { /* Isn't this overkill ? UIP above should guarantee consistency */ 125 do { /* Isn't this overkill ? UIP above should guarantee consistency */
107 sec = CMOS_READ(RTC_SECONDS); 126 sec = CMOS_READ(RTC_SECONDS);
108 min = CMOS_READ(RTC_MINUTES); 127 min = CMOS_READ(RTC_MINUTES);
@@ -120,6 +139,7 @@ static inline unsigned long mc146818_get_cmos_time(void)
120 BCD_TO_BIN(mon); 139 BCD_TO_BIN(mon);
121 BCD_TO_BIN(year); 140 BCD_TO_BIN(year);
122 } 141 }
142 spin_unlock_irqrestore(&rtc_lock, flags);
123 year = mc146818_decode_year(year); 143 year = mc146818_decode_year(year);
124 144
125 return mktime(year, mon, day, hour, min, sec); 145 return mktime(year, mon, day, hour, min, sec);
diff --git a/include/asm-mips/time.h b/include/asm-mips/time.h
index e22a20665871..9cc3564cc2c9 100644
--- a/include/asm-mips/time.h
+++ b/include/asm-mips/time.h
@@ -20,6 +20,9 @@
20#include <linux/linkage.h> 20#include <linux/linkage.h>
21#include <linux/ptrace.h> 21#include <linux/ptrace.h>
22#include <linux/rtc.h> 22#include <linux/rtc.h>
23#include <linux/spinlock.h>
24
25extern spinlock_t rtc_lock;
23 26
24/* 27/*
25 * RTC ops. By default, they point to no-RTC functions. 28 * RTC ops. By default, they point to no-RTC functions.