ST M41T00 I2C RTC chip driver
PATCH 1/1 ST M41T00 I2C RTC chip driver
This patch adds support for the ST M41T00 RTC chip.
You will likely notice that it implements a PPC-specific interface (/dev/rtc->drivers/char/genrtc.h->include/asm-ppc/rtc.h->this file). This was necessary to support a subset of ppc platforms that need to hook up the rtc support at runtime. If I implemented /dev/rtc directly or interfaced to genrtc.c directly, those platforms couldn't use this driver. Eventually, I hope to work on more uniform rtc support across all the processor architectures.
Also, on ppc at least, the hw clock can be set from a timer interrupt if STA_UNSYNC is not set (e.g., ntpd is running). To handle this, a tasklet is used to set the clock if in_interrupt() is true.
I'd appreciate an comments or to have it pushed into the kernel.org tree if its acceptable.
Thanks,
Mark
--
drivers/i2c/chips/Kconfig +9 -0
@@ -371,4 +371,13 @@ This driver can also be built as a module. If so, the module will be called isp1301_omap. +config SENSORS_M41T00 + tristate "ST M41T00 RTC chip" + depends on I2C && PPC32 + help + If you say yes here you get support for the ST M41T00 RTC chip. + + This driver can also be built as a module. If so, the module + will be called i2c-m41t00. + endmenu
drivers/i2c/chips/Makefile +1 -0
@@ -26,6 +26,7 @@ obj-$(CONFIG_SENSORS_LM87) += lm87.o obj-$(CONFIG_SENSORS_LM90) += lm90.o obj-$(CONFIG_SENSORS_MAX1619) += max1619.o +obj-$(CONFIG_SENSORS_M41T00) += m41t00.o obj-$(CONFIG_SENSORS_PC87360) += pc87360.o obj-$(CONFIG_SENSORS_PCF8574) += pcf8574.o obj-$(CONFIG_SENSORS_PCF8591) += pcf8591.o
drivers/i2c/chips/m41t00.c new file +224 -0
224 lines not on this page · raw message
On ix86 machines, it is appropriate to read the RTC clock
several times in a row until nothing changes. This protects
against getting bad readings when some values wrap (like
seconds). You can't stop the clock when you read it
or you will lose time. I don't see anything like this in your code. Also, when setting the clock it is necessary to stop the clock so its settings don't
change while you are writing a new time. I also don't
see anything like this in your code either.
Also ix86 machines have a spin-lock, rtc_lock, so that other procedures, even interrupts can access its registers. I see you using a semaphore that can't be used in interrupt context.
Notice: the RTC clock is used for high-precision timing via interrupt in some ix86 drivers. If you modify the RTC code on all platforms as you propose, you cannot "keep" the RTC all to your self. Its interrupt must be available to drivers and access to the hardware needs to be locked with the existing spin-lock.
I note that on 2.6.9 on somebody broke it so that, the interrupt is used for something only ONCE during startup and ONCE during shut-down.
CPU0
0: 6225448 IO-APIC-edge timer 1: 14002 IO-APIC-edge i8042 8: 1 IO-APIC-edge rtc <--- bingo 9: 0 IO-APIC-level acpi
[snipped...]
I don't have a clue why anybody would grab that interrupt. Fortunately, the interrupt-grabbing code can be loaded as a module and then unloaded so that other drivers can use that device and its interrupt. Any changes to the RTC code need to consider these things.
Quoted 6 lines · Mark A. Greer
This patch adds support for the ST M41T00 RTC chip.
You will likely notice that it implements a PPC-specific interface (/dev/rtc->drivers/char/genrtc.h->include/asm-ppc/rtc.h->this file). This was necessary to support a subset of ppc platforms that need to hook up the rtc support at runtime. If I implemented
/dev/rtcdirectly or interfaced togenrtc.cdirectly, those platforms couldn't use this driver. Eventually, I hope to work on more uniform rtc support across all the processor architectures.Also, on ppc at least, the hw clock can be set from a timer interrupt if
STA_UNSYNCis not set (e.g., ntpd is running). To handle this, a tasklet is used to set the clock ifin_interrupt()is true.
Quoted 10 lines
I'd appreciate an comments or to have it pushed into the kernel.org tree if its acceptable.
Thanks,
Mark
Signed-off-by Mark A. Greer <[email protected]>--
Cheers,
Dick Johnson
Penguin : Linux version 2.6.9 on an i686 machine (5537.79 BogoMips).
Notice : All mail here is now cached for review by Dictator Bush.
98.36% of all statistics are fiction.
Hi Mark,
Quoted 1 line
This patch adds support for the ST M41T00 RTC chip.
As for your other driver, I lack the device-specific knowledge to comment on the functionality, but still have some technical comments on the code itself:
drivers/i2c/chips/Kconfig line 381
Quoted 2 lines
drivers/i2c/chips/Kconfig +2
-0+ This driver can also be built as a module. If so, the module + will be called i2c-m41t00.
It'll actually be called m41t00, according to the Makefile.
drivers/i2c/chips/m41t00.c line 35
Quoted 3 lines
drivers/i2c/chips/m41t00.c new file +3
-0+struct m41t00_data { +struct i2c_client client; +};
You don't have to do that. Including the i2c_client stucture in the data structure is a trick which let us get both allocated with a single kmalloc (and freed with a single kfree) while still respecting the arch-dependent alignment requirements. If you have no private data to carry around, you can do the kmalloc on the i2c_client structure directly, and have client->data point to NULL (which it actually already does thanks to memset). This will save some code in both the detection and the detach functions.
However, if you know that, in a future update of this driver, you *will* have to store client-private data, then I guess you can keep it this way.
drivers/i2c/chips/m41t00.c line 191
Quoted 1 line
drivers/i2c/chips/m41t00.c new file +1
-0+i2c_detach_client (client);
This one supposedly can fail.
drivers/i2c/chips/m41t00.c line 199
Quoted 1 line
drivers/i2c/chips/m41t00.c new file +1
-0+ .name = "M41T00",
No caps in name please (will be used in sysfs).
drivers/i2c/chips/m41t00.c line 217
Quoted 12 lines
drivers/i2c/chips/m41t00.c new file +11
-0+static int __devinit +m41t00_init (void ) +{ +return i2c_add_driver (&m41t00_driver); +} +static void __devexit +m41t00_exit (void ) +{ +i2c_del_driver (&m41t00_driver); +return ; +}
Should be __init and __exit, respectively, unless I am mistaken. And the last return is usless.
I'm also suspicious about the other __devexit and __devinit you used. No other i2c chip drivers has them.
Thanks,
Signature · 1 line
Jean Delvare
Quoted 9 lines · linux-os
On ix86 machines, it is appropriate to read the RTC clock
several times in a row until nothing changes. This protects
against getting bad readings when some values wrap (like
seconds). You can't stop the clock when you read it
or you will lose time. I don't see anything like this in your code. Also, when setting the clock it is necessary to stop the clock so its settings don't
change while you are writing a new time. I also don't
see anything like this in your code either.
This particular RTC chip provide no mechanism to manually stop the clock for reading or writing. However, when you begin reading the clock registers, it delays updating the externally visible register values for 250ms but contiues to keep time internally so time isn't lost. I can't find anything in the manual WRT updating the clock.
There is a problem that if all the register reads don't happen within the 250ms window, it could return a bad value if a register wraps. Unless someone else points out why this is a bad idea, I'll add a loop to ensure the same values were read twice in a row.
Quoted 6 lines
Also ix86 machines have a spin-lock,
rtc_lock, so that other procedures, even interrupts can access its registers. I see you using a semaphore that can't be used in interrupt context.
This is an I2C based RTC chip and the I2C subsystem used to access it assumes (AFAICT) that its not called from an interrupt handler (e.g., drivers/i2c/i2c-core.c:i2c_transfer calls() calls down()/up()). So I need to handle an interrupt handler calling this driver which then calls into code that assumes its not in an interrupt handler. That's why the 'set' routine schedules a tasklet if its in an interrupt handler. In ppc, at least, the 'get' routine isn't called from an interrupt so its not an issue.
Quoted 8 lines
Notice: the RTC clock is used for high-precision timing via interrupt in some ix86 drivers. If you modify the RTC code on all platforms as you propose, you cannot "keep" the RTC all to your self. Its interrupt must be available to drivers and access to the hardware needs to be locked with the existing spin-lock.
Hmm, interesting. Note that this RTC doesn't generate an interrupt/initiate an i2c transaction.
Quoted 10 lines
I note that on 2.6.9 on somebody broke it so that, the interrupt is used for something only ONCE during startup and ONCE during shut-down.
CPU0
0: 6225448 IO-APIC-edge timer 1: 14002 IO-APIC-edge i8042 8: 1 IO-APIC-edge rtc <--- bingo 9: 0 IO-APIC-level acpi
Quoted 6 lines
[snipped...]
I don't have a clue why anybody would grab that interrupt. Fortunately, the interrupt-grabbing code can be loaded as a module and then unloaded so that other drivers can use that device and its interrupt. Any changes to the RTC code need to consider these things.
Okay, thanks for the insight.
Mark
Thank you for your comments, Jean.
Quoted 11 lines · Jean Delvare
Hi Mark,
Review
Quoted 4 lines
(quoted diff) +2
-0+ This driver can also be built as a module. If so, the module + will be called i2c-m41t00.It'll actually be called m41t00, according to the
Makefile.
Good catch.
Quoted 17 lines
Review
Quoted 7 lines
(quoted diff) +3
-0+struct m41t00_data { + struct i2c_client client; +};You don't have to do that. Including the
i2c_clientstucture in the data structure is a trick which let us get both allocated with a single kmalloc (and freed with a single kfree) while still respecting the arch-dependent alignment requirements. If you have no private data to carry around, you can do the kmalloc on thei2c_clientstructure directly, and haveclient->datapoint to NULL (which it actually already does thanks to memset). This will save some code in both the detection and the detach functions.
Quoted 3 lines
However, if you know that, in a future update of this driver, you *will* have to store client-private data, then I guess you can keep it this way.
Its gone.
Quoted 6 lines
Review
Quoted 3 lines
(quoted diff) +1
-0+ i2c_detach_client(client);This one supposedly can fail.
Okay, I'll check.
Quoted 8 lines
Review
Quoted 5 lines
(quoted diff) +1
-0+ .name = "M41T00",No caps in name please (will be used in sysfs).
Done.
Quoted 9 lines
Quoted 9 lines
(quoted diff) +5
-0+static int __devinit +m41t00_init(void) +{ + return i2c_add_driver(&m41t00_driver); +}
Quoted 12 lines
Review
Quoted 8 lines
(quoted diff) +6
-0+static void __devexit +m41t00_exit(void) +{ + i2c_del_driver(&m41t00_driver); + return; +}Should be
__initand__exit, respectively, unless I am mistaken. And the last return is usless.
I thought the __devxxx ones were the best ones to use but I don't know for sure. I'll change them to __init/__exit.
Quoted 5 lines
I'm also suspicious about the other
__devexitand__devinityou used. No other i2c chip drivers has them.
Done.
Here is a replacement patch that should address Jean Delvare and Dick Johnson's issues. Please let me know if there are any more issues.
Thanks,
Mark
--
drivers/i2c/chips/Kconfig +9 -0
@@ -371,4 +371,13 @@ This driver can also be built as a module. If so, the module will be called isp1301_omap. +config SENSORS_M41T00 + tristate "ST M41T00 RTC chip" + depends on I2C && PPC32 + help + If you say yes here you get support for the ST M41T00 RTC chip. + + This driver can also be built as a module. If so, the module + will be called m41t00. + endmenu
drivers/i2c/chips/Makefile +1 -0
@@ -26,6 +26,7 @@ obj-$(CONFIG_SENSORS_LM87) += lm87.o obj-$(CONFIG_SENSORS_LM90) += lm90.o obj-$(CONFIG_SENSORS_MAX1619) += max1619.o +obj-$(CONFIG_SENSORS_M41T00) += m41t00.o obj-$(CONFIG_SENSORS_PC87360) += pc87360.o obj-$(CONFIG_SENSORS_PCF8574) += pcf8574.o obj-$(CONFIG_SENSORS_PCF8591) += pcf8591.o
drivers/i2c/chips/m41t00.c new file +247 -0
247 lines not on this page · raw message
From http://archives.andrew.net.au/lm-sensors/msg29319.html:
Quoted 10 lines · Mark A. Greer
<snip>
Here is a replacement patch that should address Jean Delvare and Dick Johnson's issues. Please let me know if there are any more issues.
Thanks,
Mark
Signed-off-by Mark A. Greer <[email protected]>
I haven't heard of any more problems so can I get this patch applied?
Thanks,
Mark
Quoted 11 lines · Mark A. Greer
From http://archives.andrew.net.au/lm-sensors/msg29319.html:
Quoted 7 lines · Mark A. Greer
<snip>
Here is a replacement patch that should address Jean Delvare and Dick Johnson's issues. Please let me know if there are any more issues.
Thanks,
Quoted 7 lines
Quoted 4 lines
Mark
Signed-off-by Mark A. Greer <[email protected]>I haven't heard of any more problems so can I get this patch applied?
Can you resend it with a proper Changelog description in the top of the email and the signed-off-by line? thanks,
greg k-h
Quoted 7 lines · Greg KH
Can you resend it with a proper Changelog description in the top of the email and the signed-off-by line? thanks,
greg k-h
Certainly.
--
This patch adds support for the ST M41T00 I2C RTC chip.
This rtc chip has no mechanism to freeze it's registers while being read; however, it will delay updating the external values of the registers for 250ms after a register is read. To ensure that a sane time value is read, the driver verifies that the same registers values were read twice before returning.
Also, when setting the rtc from an interrupt handler, a tasklet is used to provide the context required by the i2c core code.
Please apply.
--
drivers/i2c/chips/Kconfig +9 -0
@@ -371,4 +371,13 @@ This driver can also be built as a module. If so, the module will be called isp1301_omap. +config SENSORS_M41T00 + tristate "ST M41T00 RTC chip" + depends on I2C && PPC32 + help + If you say yes here you get support for the ST M41T00 RTC chip. + + This driver can also be built as a module. If so, the module + will be called m41t00. + endmenu
drivers/i2c/chips/Makefile +1 -0
@@ -26,6 +26,7 @@ obj-$(CONFIG_SENSORS_LM87) += lm87.o obj-$(CONFIG_SENSORS_LM90) += lm90.o obj-$(CONFIG_SENSORS_MAX1619) += max1619.o +obj-$(CONFIG_SENSORS_M41T00) += m41t00.o obj-$(CONFIG_SENSORS_PC87360) += pc87360.o obj-$(CONFIG_SENSORS_PCF8574) += pcf8574.o obj-$(CONFIG_SENSORS_PCF8591) += pcf8591.o
drivers/i2c/chips/m41t00.c new file +247 -0
247 lines not on this page · raw message
Greg KH
AppliedQuoted 20 lines · Mark A. Greer
Quoted 7 lines · Greg KH
Can you resend it with a proper Changelog description in the top of the email and the signed-off-by line? thanks,
greg k-h
Certainly.
--This patch adds support for the ST M41T00 I2C RTC chip.
This rtc chip has no mechanism to freeze it's registers while being read; however, it will delay updating the external values of the registers for 250ms after a register is read. To ensure that a sane time value is read, the driver verifies that the same registers values were read twice before returning.
Quoted 4 lines
Also, when setting the rtc from an interrupt handler, a tasklet is used to provide the context required by the i2c core code.
Please apply.
Applied, thanks.
greg k-h
PATCH 1/1 ST M41T00 I2C RTC chip driver
In reply to Mark A. Greerthanks for the contribution.
the ST M41xx product line is a good one, lots of variants, I've used the 41T80 which adds an interrupt output but unfortunately has a slightly different register layout.
The reason for using smbus calls instead of i2c_transfer is that now you will work with any bus master rather than just
the pure i2c bit-bangers. So no matter what the hardware setup the driver will work. That's why the smbus calls are "preferred". You could use smbus_i2c_read_i2c_block_data() to get the efficiency back, but most smbus drivers don't support that. So you did it right to design for maximum flexibility.
mds
Quoted 100 lines · Mark A. Greer
Thank you for your comments, Jean.
Quoted 11 lines · Jean Delvare
Hi Mark,
drivers/i2c/chips/Kconfig line 381
Quoted 3 lines
drivers/i2c/chips/Kconfig +2
-0+ This driver can also be built as a module. If so, the module + will be called i2c-m41t00.It'll actually be called m41t00, according to the
Makefile.Good catch.
Quoted 17 lines
drivers/i2c/chips/m41t00.c line 35
Quoted 6 lines
drivers/i2c/chips/m41t00.c new file +3
-0+struct m41t00_data { +struct i2c_client client; +};You don't have to do that. Including the
i2c_clientstucture in the data structure is a trick which let us get both allocated with a single kmalloc (and freed with a single kfree) while still respecting the arch-dependent alignment requirements. If you have no private data to carry around, you can do the kmalloc on thei2c_clientstructure directly, and haveclient->datapoint to NULL (which it actually already does thanks to memset). This will save some code in both the detection and the detach functions.Quoted 3 lines
However, if you know that, in a future update of this driver, you *will* have to store client-private data, then I guess you can keep it this way.
Its gone.
Quoted 6 lines
Quoted 2 lines
+
i2c_detach_client(client);This one supposedly can fail.
Okay, I'll check.
Quoted 8 lines
Quoted 4 lines
+ .name = "M41T00",
No caps in name please (will be used in sysfs).
Done.
Quoted 9 lines
Quoted 9 lines
drivers/i2c/chips/m41t00.c new file +5
-0+static int __devinit +m41t00_init (void ) +{ +return i2c_add_driver (&m41t00_driver); +}Quoted 12 lines
drivers/i2c/chips/m41t00.c line 217
Quoted 7 lines
drivers/i2c/chips/m41t00.c new file +6
-0+static void __devexit +m41t00_exit (void ) +{ +i2c_del_driver (&m41t00_driver); +return ; +}Should be
__initand__exit, respectively, unless I am mistaken. And the last return is usless.I thought the
__devxxxones were the best ones to use but I don't know for sure. I'll change them to __init/__exit.Quoted 5 lines
I'm also suspicious about the other
__devexitand__devinityou used. No other i2c chip drivers has them.Done.
Here is a replacement patch that should address Jean Delvare and Dick Johnson's issues. Please let me know if there are any more issues.
Thanks,
Mark