aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/rtc
diff options
context:
space:
mode:
authorRodolfo Giometti <giometti@enneenne.com>2007-07-17 07:05:06 -0400
committerLinus Torvalds <torvalds@woody.linux-foundation.org>2007-07-17 13:23:09 -0400
commitbe5f59f4b67fbd4de26802a291bbcc2c623302b7 (patch)
treed8f47fb1c8740443623cda82fc82eb47a4a5c6d4 /drivers/rtc
parent537739dee52cb9bb4f9ba080a59795d5c4c306ba (diff)
rtc-ds1307: oscillator restart for ds13{37,38,39,40}
When we find a ds1337 or ds1339 with the oscillator powered off, turn it on. If the oscillator fault flag was set, clear it and warn that the clock needs to be set. David Brownell: Bugfixes; provide corresponding update for ds1338, and the core of the fix for ds1340. Use a common warning message ("SET TIME!") whenever the clock needs to be set after oscillator fault (or oscillator enable, if fault is not a separate status). Signed-off-by: Rodolfo Giometti <giometti@linux.it> Signed-off-by: David Brownell <dbrownell@users.sourceforge.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-ds1307.c66
1 files changed, 45 insertions, 21 deletions
diff --git a/drivers/rtc/rtc-ds1307.c b/drivers/rtc/rtc-ds1307.c
index 75e30c6a7d5d..5306a1a5b873 100644
--- a/drivers/rtc/rtc-ds1307.c
+++ b/drivers/rtc/rtc-ds1307.c
@@ -52,6 +52,7 @@ I2C_CLIENT_INSMOD;
52/* RTC registers don't differ much, except for the century flag */ 52/* RTC registers don't differ much, except for the century flag */
53#define DS1307_REG_SECS 0x00 /* 00-59 */ 53#define DS1307_REG_SECS 0x00 /* 00-59 */
54# define DS1307_BIT_CH 0x80 54# define DS1307_BIT_CH 0x80
55# define DS1340_BIT_nEOSC 0x80
55#define DS1307_REG_MIN 0x01 /* 00-59 */ 56#define DS1307_REG_MIN 0x01 /* 00-59 */
56#define DS1307_REG_HOUR 0x02 /* 00-23, or 1-12{am,pm} */ 57#define DS1307_REG_HOUR 0x02 /* 00-23, or 1-12{am,pm} */
57# define DS1340_BIT_CENTURY_EN 0x80 /* in REG_HOUR */ 58# define DS1340_BIT_CENTURY_EN 0x80 /* in REG_HOUR */
@@ -68,7 +69,7 @@ I2C_CLIENT_INSMOD;
68 */ 69 */
69#define DS1307_REG_CONTROL 0x07 /* or ds1338 */ 70#define DS1307_REG_CONTROL 0x07 /* or ds1338 */
70# define DS1307_BIT_OUT 0x80 71# define DS1307_BIT_OUT 0x80
71# define DS1338_BIT_STOP 0x20 72# define DS1338_BIT_OSF 0x20
72# define DS1307_BIT_SQWE 0x10 73# define DS1307_BIT_SQWE 0x10
73# define DS1307_BIT_RS1 0x02 74# define DS1307_BIT_RS1 0x02
74# define DS1307_BIT_RS0 0x01 75# define DS1307_BIT_RS0 0x01
@@ -84,8 +85,8 @@ I2C_CLIENT_INSMOD;
84# define DS1340_BIT_FT 0x40 85# define DS1340_BIT_FT 0x40
85# define DS1340_BIT_CALIB_SIGN 0x20 86# define DS1340_BIT_CALIB_SIGN 0x20
86# define DS1340_M_CALIBRATION 0x1f 87# define DS1340_M_CALIBRATION 0x1f
87#define DS1338_REG_FLAG 0x09 88#define DS1340_REG_FLAG 0x09
88# define DS1338_BIT_OSF 0x80 89# define DS1340_BIT_OSF 0x80
89#define DS1337_REG_STATUS 0x0f 90#define DS1337_REG_STATUS 0x0f
90# define DS1337_BIT_OSF 0x80 91# define DS1337_BIT_OSF 0x80
91# define DS1337_BIT_A2I 0x02 92# define DS1337_BIT_A2I 0x02
@@ -215,11 +216,18 @@ static int ds1307_set_time(struct device *dev, struct rtc_time *t)
215 tmp = t->tm_year - 100; 216 tmp = t->tm_year - 100;
216 buf[DS1307_REG_YEAR] = BIN2BCD(tmp); 217 buf[DS1307_REG_YEAR] = BIN2BCD(tmp);
217 218
218 if (ds1307->type == ds_1337) 219 switch (ds1307->type) {
220 case ds_1337:
221 case ds_1339:
219 buf[DS1307_REG_MONTH] |= DS1337_BIT_CENTURY; 222 buf[DS1307_REG_MONTH] |= DS1337_BIT_CENTURY;
220 else if (ds1307->type == ds_1340) 223 break;
224 case ds_1340:
221 buf[DS1307_REG_HOUR] |= DS1340_BIT_CENTURY_EN 225 buf[DS1307_REG_HOUR] |= DS1340_BIT_CENTURY_EN
222 | DS1340_BIT_CENTURY; 226 | DS1340_BIT_CENTURY;
227 break;
228 default:
229 break;
230 }
223 231
224 ds1307->msg[1].flags = 0; 232 ds1307->msg[1].flags = 0;
225 ds1307->msg[1].len = 8; 233 ds1307->msg[1].len = 8;
@@ -296,11 +304,10 @@ ds1307_detect(struct i2c_adapter *adapter, int address, int kind)
296 switch (ds1307->type) { 304 switch (ds1307->type) {
297 case ds_1337: 305 case ds_1337:
298 case ds_1339: 306 case ds_1339:
299 ds1307->type = ds_1337;
300
301 ds1307->reg_addr = DS1337_REG_CONTROL; 307 ds1307->reg_addr = DS1337_REG_CONTROL;
302 ds1307->msg[1].len = 2; 308 ds1307->msg[1].len = 2;
303 309
310 /* get registers that the "rtc" read below won't read... */
304 tmp = i2c_transfer(adapter, ds1307->msg, 2); 311 tmp = i2c_transfer(adapter, ds1307->msg, 2);
305 if (tmp != 2) { 312 if (tmp != 2) {
306 pr_debug("read error %d\n", tmp); 313 pr_debug("read error %d\n", tmp);
@@ -311,13 +318,16 @@ ds1307_detect(struct i2c_adapter *adapter, int address, int kind)
311 ds1307->reg_addr = 0; 318 ds1307->reg_addr = 0;
312 ds1307->msg[1].len = sizeof(ds1307->regs); 319 ds1307->msg[1].len = sizeof(ds1307->regs);
313 320
314 /* oscillator is off; need to turn it on */ 321 /* oscillator off? turn it on, so clock can tick. */
315 if ((ds1307->regs[0] & DS1337_BIT_nEOSC) 322 if (ds1307->regs[0] & DS1337_BIT_nEOSC)
316 || (ds1307->regs[1] & DS1337_BIT_OSF)) { 323 i2c_smbus_write_byte_data(client, DS1337_REG_CONTROL,
317no_osc_start: 324 ds1307->regs[0] & ~DS1337_BIT_nEOSC);
318 printk(KERN_ERR "no %s oscillator code\n", 325
319 chip->name); 326 /* oscillator fault? clear flag, and warn */
320 goto exit_free; 327 if (ds1307->regs[1] & DS1337_BIT_OSF) {
328 i2c_smbus_write_byte_data(client, DS1337_REG_STATUS,
329 ds1307->regs[1] & ~DS1337_BIT_OSF);
330 dev_warn(&client->dev, "SET TIME!\n");
321 } 331 }
322 break; 332 break;
323 default: 333 default:
@@ -340,20 +350,33 @@ read_rtc:
340 */ 350 */
341 tmp = ds1307->regs[DS1307_REG_SECS]; 351 tmp = ds1307->regs[DS1307_REG_SECS];
342 switch (ds1307->type) { 352 switch (ds1307->type) {
353 case ds_1340:
354 /* FIXME read register with DS1340_BIT_OSF, use that to
355 * trigger the "set time" warning (*after* restarting the
356 * oscillator!) instead of this weaker ds1307/m41t00 test.
357 */
343 case ds_1307: 358 case ds_1307:
344 case ds_1338:
345 case m41t00: 359 case m41t00:
360 /* clock halted? turn it on, so clock can tick. */
346 if (tmp & DS1307_BIT_CH) { 361 if (tmp & DS1307_BIT_CH) {
347 i2c_smbus_write_byte_data(client, 0, 0); 362 i2c_smbus_write_byte_data(client, DS1307_REG_SECS, 0);
348 dev_warn(&client->dev, 363 dev_warn(&client->dev, "SET TIME!\n");
349 "oscillator started; SET TIME!\n");
350 goto read_rtc; 364 goto read_rtc;
351 } 365 }
352 break; 366 break;
353 case ds_1340: 367 case ds_1338:
354 /* FIXME write code to start the oscillator */ 368 /* clock halted? turn it on, so clock can tick. */
355 if (tmp & DS1307_BIT_CH) 369 if (tmp & DS1307_BIT_CH)
356 goto no_osc_start; 370 i2c_smbus_write_byte_data(client, DS1307_REG_SECS, 0);
371
372 /* oscillator fault? clear flag, and warn */
373 if (ds1307->regs[DS1307_REG_CONTROL] & DS1338_BIT_OSF) {
374 i2c_smbus_write_byte_data(client, DS1307_REG_CONTROL,
375 ds1307->regs[DS1337_REG_CONTROL]
376 & ~DS1338_BIT_OSF);
377 dev_warn(&client->dev, "SET TIME!\n");
378 goto read_rtc;
379 }
357 break; 380 break;
358 default: 381 default:
359 break; 382 break;
@@ -380,6 +403,7 @@ read_rtc:
380 * 403 *
381 * REVISIT forcing 24 hour mode can prevent multi-master 404 * REVISIT forcing 24 hour mode can prevent multi-master
382 * configs from sharing this RTC ... don't do this. 405 * configs from sharing this RTC ... don't do this.
406 * The clock needs to be reset after changing it, too...
383 */ 407 */
384 tmp = ds1307->regs[DS1307_REG_HOUR]; 408 tmp = ds1307->regs[DS1307_REG_HOUR];
385 if (tmp & (1 << 6)) { 409 if (tmp & (1 << 6)) {