diff options
Diffstat (limited to 'drivers/rtc')
-rw-r--r-- | drivers/rtc/rtc-ds1307.c | 66 |
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, |
317 | no_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)) { |