RTC + DS1337

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Matthieu TORRES wrote:
> 
> - the option "Enhanced Real Time Clock Support" (config RTC)  does not 
> provide generic access to a RTC chip via /dev/rtc as I belevied. The 
> access to the chip in driver/char/rtc.c are made with CMOS_READ() and 
> CMOS_WRITE(),  defined in Linux/include/asm-arm/mc146818rtc.h. It is a 
> combination of outb_p() and inb_p() : no chance to access my I2C chip 
> that way...
> So I added ioct() support in /drivers/i2c/chips/ds1337.c.
> 

I remember having fixed that the same way some time ago - but people
told me that I shouldn't add that code to ds1337.c and to look for a
"generic way" instead.

As I haven't found a better way yet, I decided to write some glue code
(drivers/char/ds1337glue.c) till the issue can be resolved.

http://www.kernel.org/git/?p=linux/kernel/git/mburian/linux-2.6-ep93xx.git;a=blob;h=c7d168b7ea488676106a363311dc6119e61519a2;hb=e16e2f3f0a126eccf47d4d338b3b1a9281b7cd87;f=drivers/char/ds1337glue.c

I doubt that this will be acceptable for mainline, so I'm still waiting
for somebody (Jean?) to show me the "one true way" to get /dev/rtc
access for that chip.

> - the driver (/drivers/i2c/chips/ds1337.c) has two problems (I'm not 
> sure it is bugs, but at least on my system it does not work).
> First, ds1337_detect() reads some values in the chip registers that are 
> assumed to be wrong, but in my chip they do exist (I swear I have a 
> DS1339). I commented out these checks.
> Then, the part that enables the RTC after first power up in 
> ds1337_init_client() fails to write a status bit in the chip, so we fall 
> into the same reset code (that writes zeros in the RTC regs) after each 
> reboot.
> I corrected this and that's OK for me.
> 
> I can post code if it is usefull for someone.

I've already sent a patch that should fix this in February :(
http://lists.lm-sensors.org/pipermail/lm-sensors/2006-February/015369.html

I'm sending a "re-diffed against 2.6.17" version of that patch that,
please review and test.

To Matthieu: If your fix looks completely different, is better, ... or
you'd just like to discuss it, please show us your version.

I can live with whatever i2c folks here prefer, as long as it fixes the
problem.

This patch no longer overwrites the the complete RTC in case it detects
inconsistencies - instead it does just what's absolutely necessary to
enable userspace to fix the problem.


--- linux-2.6.17.old/drivers/i2c/chips/ds1337.c 2006-06-18
03:49:35.000000000 +0200
+++ linux-2.6.17/drivers/i2c/chips/ds1337.c     2006-06-29
10:49:48.000000000 +0200
@@ -337,38 +337,36 @@ exit:

 static void ds1337_init_client(struct i2c_client *client)
 {
+       s32 val;
        u8 status, control;

        /* On some boards, the RTC isn't configured by boot firmware.
         * Handle that case by starting/configuring the RTC now.
         */
-       status = i2c_smbus_read_byte_data(client, DS1337_REG_STATUS);
        control = i2c_smbus_read_byte_data(client, DS1337_REG_CONTROL);
-
-       if ((status & 0x80) || (control & 0x80)) {
+       if (control & 0x80) {
                /* RTC not running */
-               u8 buf[16];
-               struct i2c_msg msg[1];
-
                dev_dbg(&client->dev, "%s: RTC not running!\n",
__FUNCTION__);
+               /* reset EOSC to start RTC */
+               i2c_smbus_write_byte_data(client, DS1337_REG_CONTROL,
+                               control & 0x7f);
+       }

-               /* Initialize all, including STATUS and CONTROL to zero */
-               memset(buf, 0, sizeof(buf));
-               msg[0].addr = client->addr;
-               msg[0].flags = 0;
-               msg[0].len = sizeof(buf);
-               msg[0].buf = &buf[0];
-
-               i2c_transfer(client->adapter, msg, 1);
-       } else {
-               /* Running: ensure that device is set in 24-hour mode */
-               s32 val;
-
-               val = i2c_smbus_read_byte_data(client, DS1337_REG_HOUR);
-               if ((val >= 0) && (val & (1 << 6)))
-                       i2c_smbus_write_byte_data(client, DS1337_REG_HOUR,
-                                                 val & 0x3f);
+       /* Check if the oscillator was stopped due to power failure, ... */
+       status = i2c_smbus_read_byte_data(client, DS1337_REG_STATUS);
+       if (status & 0x80) {
+               dev_dbg(&client->dev, "%s: oscillator was stopped, RTC data"
+                               " unreliable!\n", __FUNCTION__);
+               /* reset OSF */
+               i2c_smbus_write_byte_data(client, DS1337_REG_STATUS,
+                               status & 0x7f);
        }
+
+       /* Ensure that device is set in 24-hour mode */
+       val = i2c_smbus_read_byte_data(client, DS1337_REG_HOUR);
+       if ((val >= 0) && (val & (1 << 6)))
+               i2c_smbus_write_byte_data(client, DS1337_REG_HOUR,
+                                         val & 0x3f);
 }

 static int ds1337_detach_client(struct i2c_client *client)





[Index of Archives]     [Linux Kernel]     [Linux Hardware Monitoring]     [Linux USB Devel]     [Linux Audio Users]     [Linux Kernel]     [Linux SCSI]     [Yosemite Backpacking]

  Powered by Linux