diff options
author | kogiidena <kogiidena@eggplant.ddo.jp> | 2007-05-11 01:22:57 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@woody.linux-foundation.org> | 2007-05-11 11:29:35 -0400 |
commit | 4ac24b3ba9016881b11646114bb5cd12cf23edd9 (patch) | |
tree | 8930ca592ade8b0ce0407eb1a4c93b6749c7eb0e /drivers/rtc | |
parent | 5a6a078950d769ff211c1cbd9468e31162481f8d (diff) |
rtc-rs5c313.c: add error handling to avoid hardware hangup
Add error processing. Hanging up by an infinite loop is evaded.
Signed-off-by: kogiidena <kogiidena@eggplant.ddo.jp>
Cc: Alessandro Zummo <a.zummo@towertech.it>
Cc: David Brownell <david-b@pacbell.net>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'drivers/rtc')
-rw-r--r-- | drivers/rtc/rtc-rs5c313.c | 19 |
1 files changed, 18 insertions, 1 deletions
diff --git a/drivers/rtc/rtc-rs5c313.c b/drivers/rtc/rtc-rs5c313.c index f964d1d33c04..66eb133bf5fd 100644 --- a/drivers/rtc/rtc-rs5c313.c +++ b/drivers/rtc/rtc-rs5c313.c | |||
@@ -212,7 +212,9 @@ static inline void rs5c313_write_intintvreg(unsigned char data) | |||
212 | static int rs5c313_rtc_read_time(struct device *dev, struct rtc_time *tm) | 212 | static int rs5c313_rtc_read_time(struct device *dev, struct rtc_time *tm) |
213 | { | 213 | { |
214 | int data; | 214 | int data; |
215 | int cnt; | ||
215 | 216 | ||
217 | cnt = 0; | ||
216 | while (1) { | 218 | while (1) { |
217 | RS5C313_CEENABLE; /* CE:H */ | 219 | RS5C313_CEENABLE; /* CE:H */ |
218 | 220 | ||
@@ -225,6 +227,10 @@ static int rs5c313_rtc_read_time(struct device *dev, struct rtc_time *tm) | |||
225 | RS5C313_CEDISABLE; | 227 | RS5C313_CEDISABLE; |
226 | ndelay(700); /* CE:L */ | 228 | ndelay(700); /* CE:L */ |
227 | 229 | ||
230 | if (cnt++ > 100) { | ||
231 | dev_err(dev, "%s: timeout error\n", __FUNCTION__); | ||
232 | return -EIO; | ||
233 | } | ||
228 | } | 234 | } |
229 | 235 | ||
230 | data = rs5c313_read_reg(RS5C313_ADDR_SEC); | 236 | data = rs5c313_read_reg(RS5C313_ADDR_SEC); |
@@ -266,7 +272,9 @@ static int rs5c313_rtc_read_time(struct device *dev, struct rtc_time *tm) | |||
266 | static int rs5c313_rtc_set_time(struct device *dev, struct rtc_time *tm) | 272 | static int rs5c313_rtc_set_time(struct device *dev, struct rtc_time *tm) |
267 | { | 273 | { |
268 | int data; | 274 | int data; |
275 | int cnt; | ||
269 | 276 | ||
277 | cnt = 0; | ||
270 | /* busy check. */ | 278 | /* busy check. */ |
271 | while (1) { | 279 | while (1) { |
272 | RS5C313_CEENABLE; /* CE:H */ | 280 | RS5C313_CEENABLE; /* CE:H */ |
@@ -279,6 +287,11 @@ static int rs5c313_rtc_set_time(struct device *dev, struct rtc_time *tm) | |||
279 | RS5C313_MISCOP; | 287 | RS5C313_MISCOP; |
280 | RS5C313_CEDISABLE; | 288 | RS5C313_CEDISABLE; |
281 | ndelay(700); /* CE:L */ | 289 | ndelay(700); /* CE:L */ |
290 | |||
291 | if (cnt++ > 100) { | ||
292 | dev_err(dev, "%s: timeout error\n", __FUNCTION__); | ||
293 | return -EIO; | ||
294 | } | ||
282 | } | 295 | } |
283 | 296 | ||
284 | data = BIN2BCD(tm->tm_sec); | 297 | data = BIN2BCD(tm->tm_sec); |
@@ -317,6 +330,7 @@ static int rs5c313_rtc_set_time(struct device *dev, struct rtc_time *tm) | |||
317 | static void rs5c313_check_xstp_bit(void) | 330 | static void rs5c313_check_xstp_bit(void) |
318 | { | 331 | { |
319 | struct rtc_time tm; | 332 | struct rtc_time tm; |
333 | int cnt; | ||
320 | 334 | ||
321 | RS5C313_CEENABLE; /* CE:H */ | 335 | RS5C313_CEENABLE; /* CE:H */ |
322 | if (rs5c313_read_cntreg() & RS5C313_CNTREG_WTEN_XSTP) { | 336 | if (rs5c313_read_cntreg() & RS5C313_CNTREG_WTEN_XSTP) { |
@@ -326,8 +340,11 @@ static void rs5c313_check_xstp_bit(void) | |||
326 | rs5c313_write_cntreg(0x07); | 340 | rs5c313_write_cntreg(0x07); |
327 | 341 | ||
328 | /* busy check. */ | 342 | /* busy check. */ |
329 | while (rs5c313_read_cntreg() & RS5C313_CNTREG_ADJ_BSY) | 343 | for (cnt = 0; cnt < 100; cnt++) { |
344 | if (!(rs5c313_read_cntreg() & RS5C313_CNTREG_ADJ_BSY)) | ||
345 | break; | ||
330 | RS5C313_MISCOP; | 346 | RS5C313_MISCOP; |
347 | } | ||
331 | 348 | ||
332 | memset(&tm, 0, sizeof(struct rtc_time)); | 349 | memset(&tm, 0, sizeof(struct rtc_time)); |
333 | tm.tm_mday = 1; | 350 | tm.tm_mday = 1; |