Gitweb:     
http://git.kernel.org/git/?p=linux/kernel/git/torvalds/linux-2.6.git;a=commit;h=be5f59f4b67fbd4de26802a291bbcc2c623302b7
Commit:     be5f59f4b67fbd4de26802a291bbcc2c623302b7
Parent:     537739dee52cb9bb4f9ba080a59795d5c4c306ba
Author:     Rodolfo Giometti <[EMAIL PROTECTED]>
AuthorDate: Tue Jul 17 04:05:06 2007 -0700
Committer:  Linus Torvalds <[EMAIL PROTECTED]>
CommitDate: Tue Jul 17 10:23:09 2007 -0700

    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 <[EMAIL PROTECTED]>
    Signed-off-by: David Brownell <[EMAIL PROTECTED]>
    Signed-off-by: Andrew Morton <[EMAIL PROTECTED]>
    Signed-off-by: Linus Torvalds <[EMAIL PROTECTED]>
---
 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 75e30c6..5306a1a 100644
--- a/drivers/rtc/rtc-ds1307.c
+++ b/drivers/rtc/rtc-ds1307.c
@@ -52,6 +52,7 @@ I2C_CLIENT_INSMOD;
 /* RTC registers don't differ much, except for the century flag */
 #define DS1307_REG_SECS                0x00    /* 00-59 */
 #      define DS1307_BIT_CH            0x80
+#      define DS1340_BIT_nEOSC         0x80
 #define DS1307_REG_MIN         0x01    /* 00-59 */
 #define DS1307_REG_HOUR                0x02    /* 00-23, or 1-12{am,pm} */
 #      define DS1340_BIT_CENTURY_EN    0x80    /* in REG_HOUR */
@@ -68,7 +69,7 @@ I2C_CLIENT_INSMOD;
  */
 #define DS1307_REG_CONTROL     0x07            /* or ds1338 */
 #      define DS1307_BIT_OUT           0x80
-#      define DS1338_BIT_STOP          0x20
+#      define DS1338_BIT_OSF           0x20
 #      define DS1307_BIT_SQWE          0x10
 #      define DS1307_BIT_RS1           0x02
 #      define DS1307_BIT_RS0           0x01
@@ -84,8 +85,8 @@ I2C_CLIENT_INSMOD;
 #      define DS1340_BIT_FT            0x40
 #      define DS1340_BIT_CALIB_SIGN    0x20
 #      define DS1340_M_CALIBRATION     0x1f
-#define DS1338_REG_FLAG                0x09
-#      define DS1338_BIT_OSF           0x80
+#define DS1340_REG_FLAG                0x09
+#      define DS1340_BIT_OSF           0x80
 #define DS1337_REG_STATUS      0x0f
 #      define DS1337_BIT_OSF           0x80
 #      define DS1337_BIT_A2I           0x02
@@ -215,11 +216,18 @@ static int ds1307_set_time(struct device *dev, struct 
rtc_time *t)
        tmp = t->tm_year - 100;
        buf[DS1307_REG_YEAR] = BIN2BCD(tmp);
 
-       if (ds1307->type == ds_1337)
+       switch (ds1307->type) {
+       case ds_1337:
+       case ds_1339:
                buf[DS1307_REG_MONTH] |= DS1337_BIT_CENTURY;
-       else if (ds1307->type == ds_1340)
+               break;
+       case ds_1340:
                buf[DS1307_REG_HOUR] |= DS1340_BIT_CENTURY_EN
                                | DS1340_BIT_CENTURY;
+               break;
+       default:
+               break;
+       }
 
        ds1307->msg[1].flags = 0;
        ds1307->msg[1].len = 8;
@@ -296,11 +304,10 @@ ds1307_detect(struct i2c_adapter *adapter, int address, 
int kind)
        switch (ds1307->type) {
        case ds_1337:
        case ds_1339:
-               ds1307->type = ds_1337;
-
                ds1307->reg_addr = DS1337_REG_CONTROL;
                ds1307->msg[1].len = 2;
 
+               /* get registers that the "rtc" read below won't read... */
                tmp = i2c_transfer(adapter, ds1307->msg, 2);
                if (tmp != 2) {
                        pr_debug("read error %d\n", tmp);
@@ -311,13 +318,16 @@ ds1307_detect(struct i2c_adapter *adapter, int address, 
int kind)
                ds1307->reg_addr = 0;
                ds1307->msg[1].len = sizeof(ds1307->regs);
 
-               /* oscillator is off; need to turn it on */
-               if ((ds1307->regs[0] & DS1337_BIT_nEOSC)
-                               || (ds1307->regs[1] & DS1337_BIT_OSF)) {
-no_osc_start:
-                       printk(KERN_ERR "no %s oscillator code\n",
-                               chip->name);
-                       goto exit_free;
+               /* oscillator off?  turn it on, so clock can tick. */
+               if (ds1307->regs[0] & DS1337_BIT_nEOSC)
+                       i2c_smbus_write_byte_data(client, DS1337_REG_CONTROL,
+                               ds1307->regs[0] & ~DS1337_BIT_nEOSC);
+
+               /* oscillator fault?  clear flag, and warn */
+               if (ds1307->regs[1] & DS1337_BIT_OSF) {
+                       i2c_smbus_write_byte_data(client, DS1337_REG_STATUS,
+                               ds1307->regs[1] & ~DS1337_BIT_OSF);
+                       dev_warn(&client->dev, "SET TIME!\n");
                }
                break;
        default:
@@ -340,20 +350,33 @@ read_rtc:
         */
        tmp = ds1307->regs[DS1307_REG_SECS];
        switch (ds1307->type) {
+       case ds_1340:
+               /* FIXME read register with DS1340_BIT_OSF, use that to
+                * trigger the "set time" warning (*after* restarting the
+                * oscillator!) instead of this weaker ds1307/m41t00 test.
+                */
        case ds_1307:
-       case ds_1338:
        case m41t00:
+               /* clock halted?  turn it on, so clock can tick. */
                if (tmp & DS1307_BIT_CH) {
-                       i2c_smbus_write_byte_data(client, 0, 0);
-                       dev_warn(&client->dev,
-                               "oscillator started; SET TIME!\n");
+                       i2c_smbus_write_byte_data(client, DS1307_REG_SECS, 0);
+                       dev_warn(&client->dev, "SET TIME!\n");
                        goto read_rtc;
                }
                break;
-       case ds_1340:
-               /* FIXME write code to start the oscillator */
+       case ds_1338:
+               /* clock halted?  turn it on, so clock can tick. */
                if (tmp & DS1307_BIT_CH)
-                       goto no_osc_start;
+                       i2c_smbus_write_byte_data(client, DS1307_REG_SECS, 0);
+
+               /* oscillator fault?  clear flag, and warn */
+               if (ds1307->regs[DS1307_REG_CONTROL] & DS1338_BIT_OSF) {
+                       i2c_smbus_write_byte_data(client, DS1307_REG_CONTROL,
+                                       ds1307->regs[DS1337_REG_CONTROL]
+                                       & ~DS1338_BIT_OSF);
+                       dev_warn(&client->dev, "SET TIME!\n");
+                       goto read_rtc;
+               }
                break;
        default:
                break;
@@ -380,6 +403,7 @@ read_rtc:
         *
         * REVISIT forcing 24 hour mode can prevent multi-master
         * configs from sharing this RTC ... don't do this.
+        * The clock needs to be reset after changing it, too...
         */
        tmp = ds1307->regs[DS1307_REG_HOUR];
        if (tmp & (1 << 6)) {
-
To unsubscribe from this list: send the line "unsubscribe git-commits-head" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to