Alexandre,
this is the second version of apatch set to be able to adjust the
clock on a pcf2123, but with a big addition. I am also proposing
a couple of new rtc api functions and a new sysfs file.
Patches 1-5 are very much v2 patches that address All of the
concerns you had with v1. It is my hope to get them merged without
too much more trouble.
Patches 6-8 are attemping to add a new function to the rtc class
to adjust the clock rate. I hope I am going about this the right way,
But here goes.
A number of rtc devices, such as the NXP pcf2123 include a facility
to adjust the clock in order to compensate for temperature or a
crystal, capacitor, etc, that results in the rtc clock not running
at exactly 32.768 kHz.
This patchset adds kernel and sysfs hooks to access that ability.
One datasheet suggests it might be adjusted based on input from
a temperature sensor. I could also potentially see it being set
as part of ntp calibration.
Data sheets I have seen refer to this as a clock offset, and measure it
in parts per million (ppm), however they often reference ppm to 2 digits
of precision, which makes integer ppm less than ideal. I use parts per
billion, which more than covers the precision needed and works nicely
within 32 bits
The name "offset" came from the pcf-2123 datasheet and is used by at
least some other data sheets. I would be happy to use a different term
if someone else comes up with something more concise.
Changes since v1:
- Use the BIT() macro for all register bits
- Remove unneeded range checks from read/write functions
- Merge patch 3 (replace magic numbers with defines) into patch 2
- Add a proper commit message to patch 5, now patch 4
- Fix a function alignment bug.
- Move OSC_HAS_STOPPED check into pcf2123_rtc_read_time, and get rid of
pcf2123_time_valid()
- Drop patches refactoring pcf2123 sysfs.
- Add rtc interface and rtc sysfs file for clock offset
Joshua Clayton (8):
rtc-pcf2123: define registers and bit macros
rtc-pcf2123: clean up reads from the chip
rtc-pcf2123: clean up writes to the rtc chip
rtc-pcf2123: refactor chip reset into a function
rtc-pcf2123: avoid resetting the clock if possible
rtc: Add functions to set and read clock offset
rtc: implement a sysfs interface for clock offset
rtc-pcf2123: implement read_offset and set_offset
drivers/rtc/interface.c | 57 ++++++++++
drivers/rtc/rtc-pcf2123.c | 271 +++++++++++++++++++++++++++++++++-------------
drivers/rtc/rtc-sysfs.c | 29 +++++
include/linux/rtc.h | 4 +
4 files changed, 284 insertions(+), 77 deletions(-)
--
2.5.0
--
--
You received this message because you are subscribed to "rtc-linux".
Membership options at http://groups.google.com/group/rtc-linux .
Please read http://groups.google.com/group/rtc-linux/web/checklist
before submitting a driver.
---
You received this message because you are subscribed to the Google Groups "rtc-linux" group.
To unsubscribe from this group and stop receiving emails from it, send an email to rtc-linux+unsubscribe@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.
@@ -297,16 +303,12 @@ static int pcf2123_probe(struct spi_device *spi)pcf2123_delay_trec();/* See if the counter was actually stopped */-txbuf[0]=PCF2123_READ|PCF2123_REG_CTRL1;-dev_dbg(&spi->dev,"checking for presence of RTC (0x%02X)\n",-txbuf[0]);-ret=spi_write_then_read(spi,txbuf,1*sizeof(u8),-rxbuf,2*sizeof(u8));+dev_dbg(&spi->dev,"checking for presence of RTC\n");+ret=pcf2123_read(&spi->dev,PCF2123_REG_CTRL1,rxbuf,sizeof(rxbuf));dev_dbg(&spi->dev,"received data from RTC (0x%02X 0x%02X)\n",rxbuf[0],rxbuf[1]);if(ret<0)gotokfree_exit;-pcf2123_delay_trec();if(!(rxbuf[0]&0x20)){dev_err(&spi->dev,"chip not found\n");
--
2.5.0
--
--
You received this message because you are subscribed to "rtc-linux".
Membership options at http://groups.google.com/group/rtc-linux .
Please read http://groups.google.com/group/rtc-linux/web/checklist
before submitting a driver.
---
You received this message because you are subscribed to the Google Groups "rtc-linux" group.
To unsubscribe from this group and stop receiving emails from it, send an email to rtc-linux+unsubscribe@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.
pcf2123 data sheet recommends a software reset when the chip
is first powered on. This change avoids resetting the chip
every time the driver is loaded, which has some negative effects.
There are several registers including a clock rate adjustment that really
should survive a reload of the driver (or reboot).
In addition, stopping and restarting the clock to verify the chip is
there is not a good thing once the time is set.
According to the data sheet, the seconds register has a 1 in
the high bit when the voltage has gotten low. We check for this
condition, as well as whether the time retrieved from the chip is
valid. We reset the rtc only if the time is not reliable and valid.
This is sufficient for checking for the presence of the chip,
as either all zeros or all 0xff will result in an invalid time/date
Signed-off-by: Joshua Clayton <redacted>
---
drivers/rtc/rtc-pcf2123.c | 15 ++++++++++++---
1 file changed, 12 insertions(+), 3 deletions(-)
@@ -215,6 +215,11 @@ static int pcf2123_rtc_read_time(struct device *dev, struct rtc_time *tm)if(ret<0)returnret;+if(rxbuf[0]&OSC_HAS_STOPPED){+dev_info(dev,"clock was stopped. Time is not valid\n");+return-EINVAL;+}+tm->tm_sec=bcd2bin(rxbuf[0]&0x7F);tm->tm_min=bcd2bin(rxbuf[1]&0x7F);tm->tm_hour=bcd2bin(rxbuf[2]&0x3F);/* rtc hr 0-23 */
@@ -323,10 +329,13 @@ static int pcf2123_probe(struct spi_device *spi)return-ENOMEM;spi->dev.platform_data=pdata;-ret=pcf2123_reset(&spi->dev);+ret=pcf2123_rtc_read_time(&spi->dev,&tm);if(ret<0){-dev_err(&spi->dev,"chip not found\n");-gotokfree_exit;+ret=pcf2123_reset(&spi->dev);+if(ret<0){+dev_err(&spi->dev,"chip not found\n");+gotokfree_exit;+}}dev_info(&spi->dev,"chip found, driver version "DRV_VERSION"\n");
--
2.5.0
--
--
You received this message because you are subscribed to "rtc-linux".
Membership options at http://groups.google.com/group/rtc-linux .
Please read http://groups.google.com/group/rtc-linux/web/checklist
before submitting a driver.
---
You received this message because you are subscribed to the Google Groups "rtc-linux" group.
To unsubscribe from this group and stop receiving emails from it, send an email to rtc-linux+unsubscribe@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.
The file is called "offset", and may be set and read in decimal.
For rtcs that do not have read_offset or set_offset implemented,
read always returns zero and write will return -EINVAL.
Signed-off-by: Joshua Clayton <redacted>
---
drivers/rtc/interface.c | 2 +-
drivers/rtc/rtc-sysfs.c | 29 +++++++++++++++++++++++++++++
2 files changed, 30 insertions(+), 1 deletion(-)
--
2.5.0
--
--
You received this message because you are subscribed to "rtc-linux".
Membership options at http://groups.google.com/group/rtc-linux .
Please read http://groups.google.com/group/rtc-linux/web/checklist
before submitting a driver.
---
You received this message because you are subscribed to the Google Groups "rtc-linux" group.
To unsubscribe from this group and stop receiving emails from it, send an email to rtc-linux+unsubscribe@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.
pcf2123 has an offset register, which can be used to make minor
adjustments to the clock rate to compensate for temperature or
a crystal that is not exactly right.
Expose the offset register to sysfs
Signed-off-by: Joshua Clayton <redacted>
---
drivers/rtc/rtc-pcf2123.c | 57 +++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 57 insertions(+)
@@ -100,6 +100,7 @@/* PCF2123_REG_OFFSET BITS */#define OFFSET_SIGN_BIT BIT(6) /* 2's complement sign bit */#define OFFSET_COARSE BIT(7) /* Coarse mode offset */+#define OFFSET_STEP (2170) /* Offset step in parts per billion *//* READ/WRITE ADDRESS BITS */#define PCF2123_WRITE BIT(4)
@@ -206,6 +207,59 @@ static ssize_t pcf2123_store(struct device *dev, struct device_attribute *attr,returncount;}+staticintpcf2123_read_offset(structdevice*dev,long*offset)+{+intret;+s8reg;++ret=pcf2123_read(dev,PCF2123_REG_OFFSET,®,1);+if(ret<0)+returnret;++if(reg&OFFSET_COARSE)+reg<<=1;/* multiply by 2 and sign extend */+else+reg|=(reg&OFFSET_SIGN_BIT)<<1;/* sign extend only */++*offset=((long)reg)*OFFSET_STEP;++return0;+}++/*+*Theoffsetregisterisa7bitsignedvaluewithacoarsebitinbit7.+*Themaindifferencebetweenthetwoisnormaloffsetadjuststhefirst+*secondofnminuteseveryotherhour,with61,62and63beingshoved+*intothe60thminute.+*Thecoarseadjustmentdoesthesame,buteveryhour.+*thetwooverlap,witheveryevennormaloffsetvaluecorresponding+*toacoarseoffset.Basedonthisalgorithm,itseemsthatdespitethe+*name,coarseoffsetisabetterfitforoverlappingvalues.+*/+staticintpcf2123_set_offset(structdevice*dev,longoffset)+{+s8reg;++if(offset>OFFSET_STEP*127)+reg=127;+elseif(offset<OFFSET_STEP*-128)+reg=-128;+else+reg=(s8)((offset+(OFFSET_STEP>>1))/OFFSET_STEP);++/* choose fine offset only for odd values in the normal range */+if(reg&1&®<=63&®>=-64){+/* Normal offset. Clear the coarse bit */+reg&=~OFFSET_COARSE;+}else{+/* Coarse offset. Divide by 2 and set the coarse bit */+reg>>=1;+reg|=OFFSET_COARSE;+}++returnpcf2123_write_reg(dev,PCF2123_REG_OFFSET,reg);+}+staticintpcf2123_rtc_read_time(structdevice*dev,structrtc_time*tm){u8rxbuf[7];
@@ -314,6 +368,9 @@ static int pcf2123_reset(struct device *dev)staticconststructrtc_class_opspcf2123_rtc_ops={.read_time=pcf2123_rtc_read_time,.set_time=pcf2123_rtc_set_time,+.read_offset=pcf2123_read_offset,+.set_offset=pcf2123_set_offset,+};staticintpcf2123_probe(structspi_device*spi)
--
2.5.0
--
--
You received this message because you are subscribed to "rtc-linux".
Membership options at http://groups.google.com/group/rtc-linux .
Please read http://groups.google.com/group/rtc-linux/web/checklist
before submitting a driver.
---
You received this message because you are subscribed to the Google Groups "rtc-linux" group.
To unsubscribe from this group and stop receiving emails from it, send an email to rtc-linux+unsubscribe@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.
A number of rtc devices, such as the NXP pcf2123 include a facility
to adjust the clock in order to compensate for temperature or a
crystal, capacitor, etc, that results in the rtc clock not running
at exactly 32.768 kHz.
Data sheets I have seen refer to this as a clock offset, and measure it
in parts per million (ppm), however they often reference ppm to 2 digits
of precision, which makes integer ppm less than ideal.
We use parts per billion, which more than covers the precision needed
and works nicely within 32 bits
Signed-off-by: Joshua Clayton <redacted>
---
drivers/rtc/interface.c | 57 +++++++++++++++++++++++++++++++++++++++++++++++++
include/linux/rtc.h | 4 ++++
2 files changed, 61 insertions(+)
--
2.5.0
--
--
You received this message because you are subscribed to "rtc-linux".
Membership options at http://groups.google.com/group/rtc-linux .
Please read http://groups.google.com/group/rtc-linux/web/checklist
before submitting a driver.
---
You received this message because you are subscribed to the Google Groups "rtc-linux" group.
To unsubscribe from this group and stop receiving emails from it, send an email to rtc-linux+unsubscribe@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.
Refactor chip reset items into its own function, isolating it from
the rest of the device probe.
Subsequent commits will avoid calling this code.
Signed-off-by: Joshua Clayton <redacted>
---
drivers/rtc/rtc-pcf2123.c | 64 ++++++++++++++++++++++++++---------------------
1 file changed, 36 insertions(+), 28 deletions(-)
@@ -272,6 +272,40 @@ static int pcf2123_rtc_set_time(struct device *dev, struct rtc_time *tm)return0;}+staticintpcf2123_reset(structdevice*dev)+{+intret;+u8rxbuf[2];++ret=pcf2123_write_reg(dev,PCF2123_REG_CTRL1,CTRL1_SW_RESET);+if(ret<0)+returnret;++/* Stop the counter */+dev_dbg(dev,"stopping RTC\n");+ret=pcf2123_write_reg(dev,PCF2123_REG_CTRL1,CTRL1_STOP);+if(ret<0)+returnret;++/* See if the counter was actually stopped */+dev_dbg(dev,"checking for presence of RTC\n");+ret=pcf2123_read(dev,PCF2123_REG_CTRL1,rxbuf,sizeof(rxbuf));+if(ret<0)+returnret;++dev_dbg(dev,"received data from RTC (0x%02X 0x%02X)\n",+rxbuf[0],rxbuf[1]);+if(!(rxbuf[0]&CTRL1_STOP))+return-ENODEV;++/* Start the counter */+ret=pcf2123_write_reg(dev,PCF2123_REG_CTRL1,CTRL1_CLEAR);+if(ret<0)+returnret;++return0;+}+staticconststructrtc_class_opspcf2123_rtc_ops={.read_time=pcf2123_rtc_read_time,.set_time=pcf2123_rtc_set_time,
@@ -281,7 +315,6 @@ static int pcf2123_probe(struct spi_device *spi){structrtc_device*rtc;structpcf2123_plat_data*pdata;-u8rxbuf[2];intret,i;pdata=devm_kzalloc(&spi->dev,sizeof(structpcf2123_plat_data),
@@ -290,29 +323,9 @@ static int pcf2123_probe(struct spi_device *spi)return-ENOMEM;spi->dev.platform_data=pdata;-/* Send a software reset command */-dev_dbg(&spi->dev,"resetting RTC\n");-ret=pcf2123_write_reg(&spi->dev,PCF2123_REG_CTRL1,CTRL1_SW_RESET);-if(ret<0)-gotokfree_exit;--/* Stop the counter */-dev_dbg(&spi->dev,"stopping RTC\n");-ret=pcf2123_write_reg(&spi->dev,PCF2123_REG_CTRL1,CTRL1_STOP);-if(ret<0)-gotokfree_exit;--/* See if the counter was actually stopped */-dev_dbg(&spi->dev,"checking for presence of RTC\n");-ret=pcf2123_read(&spi->dev,PCF2123_REG_CTRL1,rxbuf,sizeof(rxbuf));-dev_dbg(&spi->dev,"received data from RTC (0x%02X 0x%02X)\n",-rxbuf[0],rxbuf[1]);-if(ret<0)-gotokfree_exit;--if(!(rxbuf[0]&0x20)){+ret=pcf2123_reset(&spi->dev);+if(ret<0){dev_err(&spi->dev,"chip not found\n");-ret=-ENODEV;gotokfree_exit;}
@@ -320,11 +333,6 @@ static int pcf2123_probe(struct spi_device *spi)dev_info(&spi->dev,"spiclk %u KHz.\n",(spi->max_speed_hz+500)/1000);-/* Start the counter */-ret=pcf2123_write_reg(&spi->dev,PCF2123_REG_CTRL1,CTRL1_CLEAR);-if(ret<0)-gotokfree_exit;-/* Finalize the initialization */rtc=devm_rtc_device_register(&spi->dev,pcf2123_driver.driver.name,&pcf2123_rtc_ops,THIS_MODULE);
--
2.5.0
--
--
You received this message because you are subscribed to "rtc-linux".
Membership options at http://groups.google.com/group/rtc-linux .
Please read http://groups.google.com/group/rtc-linux/web/checklist
before submitting a driver.
---
You received this message because you are subscribed to the Google Groups "rtc-linux" group.
To unsubscribe from this group and stop receiving emails from it, send an email to rtc-linux+unsubscribe@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.
Add new functions pcf2123_write(), and pcf2123_write_reg().
Use named defines for the values being written.
This improves modularity and readability, and reduces lines of code.
Signed-off-by: Joshua Clayton <redacted>
---
drivers/rtc/rtc-pcf2123.c | 67 ++++++++++++++++++++++-------------------------
1 file changed, 32 insertions(+), 35 deletions(-)
@@ -231,15 +246,12 @@ static int pcf2123_rtc_set_time(struct device *dev, struct rtc_time *tm)tm->tm_mday,tm->tm_mon,tm->tm_year,tm->tm_wday);/* Stop the counter first */-txbuf[0]=PCF2123_WRITE|PCF2123_REG_CTRL1;-txbuf[1]=0x20;-ret=spi_write(spi,txbuf,2);+ret=pcf2123_write_reg(dev,PCF2123_REG_CTRL1,CTRL1_STOP);if(ret<0)returnret;-pcf2123_delay_trec();/* Set the new time */-txbuf[0]=PCF2123_WRITE|PCF2123_REG_SC;+txbuf[0]=PCF2123_REG_SC;txbuf[1]=bin2bcd(tm->tm_sec&0x7F);txbuf[2]=bin2bcd(tm->tm_min&0x7F);txbuf[3]=bin2bcd(tm->tm_hour&0x3F);
@@ -248,18 +260,14 @@ static int pcf2123_rtc_set_time(struct device *dev, struct rtc_time *tm)txbuf[6]=bin2bcd((tm->tm_mon+1)&0x1F);/* rtc mn 1-12 */txbuf[7]=bin2bcd(tm->tm_year<100?tm->tm_year:tm->tm_year-100);-ret=spi_write(spi,txbuf,sizeof(txbuf));+ret=pcf2123_write(dev,txbuf,sizeof(txbuf));if(ret<0)returnret;-pcf2123_delay_trec();/* Start the counter */-txbuf[0]=PCF2123_WRITE|PCF2123_REG_CTRL1;-txbuf[1]=0x00;-ret=spi_write(spi,txbuf,2);+ret=pcf2123_write_reg(dev,PCF2123_REG_CTRL1,CTRL1_CLEAR);if(ret<0)returnret;-pcf2123_delay_trec();return0;}
@@ -273,7 +281,7 @@ static int pcf2123_probe(struct spi_device *spi){structrtc_device*rtc;structpcf2123_plat_data*pdata;-u8txbuf[2],rxbuf[2];+u8rxbuf[2];intret,i;pdata=devm_kzalloc(&spi->dev,sizeof(structpcf2123_plat_data),
@@ -283,24 +291,16 @@ static int pcf2123_probe(struct spi_device *spi)spi->dev.platform_data=pdata;/* Send a software reset command */-txbuf[0]=PCF2123_WRITE|PCF2123_REG_CTRL1;-txbuf[1]=0x58;-dev_dbg(&spi->dev,"resetting RTC (0x%02X 0x%02X)\n",-txbuf[0],txbuf[1]);-ret=spi_write(spi,txbuf,2*sizeof(u8));+dev_dbg(&spi->dev,"resetting RTC\n");+ret=pcf2123_write_reg(&spi->dev,PCF2123_REG_CTRL1,CTRL1_SW_RESET);if(ret<0)gotokfree_exit;-pcf2123_delay_trec();/* Stop the counter */-txbuf[0]=PCF2123_WRITE|PCF2123_REG_CTRL1;-txbuf[1]=0x20;-dev_dbg(&spi->dev,"stopping RTC (0x%02X 0x%02X)\n",-txbuf[0],txbuf[1]);-ret=spi_write(spi,txbuf,2*sizeof(u8));+dev_dbg(&spi->dev,"stopping RTC\n");+ret=pcf2123_write_reg(&spi->dev,PCF2123_REG_CTRL1,CTRL1_STOP);if(ret<0)gotokfree_exit;-pcf2123_delay_trec();/* See if the counter was actually stopped */dev_dbg(&spi->dev,"checking for presence of RTC\n");
@@ -321,12 +321,9 @@ static int pcf2123_probe(struct spi_device *spi)(spi->max_speed_hz+500)/1000);/* Start the counter */-txbuf[0]=PCF2123_WRITE|PCF2123_REG_CTRL1;-txbuf[1]=0x00;-ret=spi_write(spi,txbuf,sizeof(txbuf));+ret=pcf2123_write_reg(&spi->dev,PCF2123_REG_CTRL1,CTRL1_CLEAR);if(ret<0)gotokfree_exit;-pcf2123_delay_trec();/* Finalize the initialization */rtc=devm_rtc_device_register(&spi->dev,pcf2123_driver.driver.name,
--
2.5.0
--
--
You received this message because you are subscribed to "rtc-linux".
Membership options at http://groups.google.com/group/rtc-linux .
Please read http://groups.google.com/group/rtc-linux/web/checklist
before submitting a driver.
---
You received this message because you are subscribed to the Google Groups "rtc-linux" group.
To unsubscribe from this group and stop receiving emails from it, send an email to rtc-linux+unsubscribe@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.
Add defines for all 16 registers in the pcf2123.
Add defines for useful bits from several registers
I've tried to document all the registers, and
as best as possible, all the special bits they employ
Use BIT() wherever possible in the bit definitions
Signed-off-by: Joshua Clayton <redacted>
---
drivers/rtc/rtc-pcf2123.c | 50 ++++++++++++++++++++++++++++++++++++++++++++---
1 file changed, 47 insertions(+), 3 deletions(-)
--
2.5.0
--
--
You received this message because you are subscribed to "rtc-linux".
Membership options at http://groups.google.com/group/rtc-linux .
Please read http://groups.google.com/group/rtc-linux/web/checklist
before submitting a driver.
---
You received this message because you are subscribed to the Google Groups "rtc-linux" group.
To unsubscribe from this group and stop receiving emails from it, send an email to rtc-linux+unsubscribe@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.
Ping?
On Monday, January 04, 2016 10:31:18 AM Joshua Clayton wrote:
Alexandre,
this is the second version of apatch set to be able to adjust the
clock on a pcf2123, but with a big addition. I am also proposing
a couple of new rtc api functions and a new sysfs file.
Patches 1-5 are very much v2 patches that address All of the
concerns you had with v1. It is my hope to get them merged without
too much more trouble.
The rtc _needs_ patches 1-5 in order to use the clock offset
adjustment at all (current upstream code resets it to zero during
device probe, so it doesn't survive a reboot)
Should I split out patches 1-5 to make them easier to review?
Patches 6-8 are attemping to add a new function to the rtc class
to adjust the clock rate. I hope I am going about this the right way,
But here goes.
I am hoping to have some discussion about 6, 7 and 8.
Particularly whether parts per billion is the right unit (I think it is)
and whether "offset" is the best name for the attribute (not as sure).
A number of rtc devices, such as the NXP pcf2123 include a facility
to adjust the clock in order to compensate for temperature or a
crystal, capacitor, etc, that results in the rtc clock not running
at exactly 32.768 kHz.
This patchset adds kernel and sysfs hooks to access that ability.
One datasheet suggests it might be adjusted based on input from
a temperature sensor. I could also potentially see it being set
as part of ntp calibration.
Data sheets I have seen refer to this as a clock offset, and measure it
in parts per million (ppm), however they often reference ppm to 2 digits
of precision, which makes integer ppm less than ideal. I use parts per
billion, which more than covers the precision needed and works nicely
within 32 bits
The name "offset" came from the pcf-2123 datasheet and is used by at
least some other data sheets. I would be happy to use a different term
if someone else comes up with something more concise.
Changes since v1:
- Use the BIT() macro for all register bits
- Remove unneeded range checks from read/write functions
- Merge patch 3 (replace magic numbers with defines) into patch 2
- Add a proper commit message to patch 5, now patch 4
- Fix a function alignment bug.
- Move OSC_HAS_STOPPED check into pcf2123_rtc_read_time, and get rid of
pcf2123_time_valid()
- Drop patches refactoring pcf2123 sysfs.
- Add rtc interface and rtc sysfs file for clock offset
Joshua Clayton (8):
rtc-pcf2123: define registers and bit macros
rtc-pcf2123: clean up reads from the chip
rtc-pcf2123: clean up writes to the rtc chip
rtc-pcf2123: refactor chip reset into a function
rtc-pcf2123: avoid resetting the clock if possible
rtc: Add functions to set and read clock offset
rtc: implement a sysfs interface for clock offset
rtc-pcf2123: implement read_offset and set_offset
drivers/rtc/interface.c | 57 ++++++++++
drivers/rtc/rtc-pcf2123.c | 271 +++++++++++++++++++++++++++++++++-------------
drivers/rtc/rtc-sysfs.c | 29 +++++
include/linux/rtc.h | 4 +
4 files changed, 284 insertions(+), 77 deletions(-)
Thanks again,
Joshua Clayton
--
--
You received this message because you are subscribed to "rtc-linux".
Membership options at http://groups.google.com/group/rtc-linux .
Please read http://groups.google.com/group/rtc-linux/web/checklist
before submitting a driver.
---
You received this message because you are subscribed to the Google Groups "rtc-linux" group.
To unsubscribe from this group and stop receiving emails from it, send an email to rtc-linux+unsubscribe@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.
On 26/01/2016 at 06:56:40 -0800, Joshua Clayton wrote :
Ping?
On Monday, January 04, 2016 10:31:18 AM Joshua Clayton wrote:
quoted
Alexandre,
this is the second version of apatch set to be able to adjust the
clock on a pcf2123, but with a big addition. I am also proposing
a couple of new rtc api functions and a new sysfs file.
Patches 1-5 are very much v2 patches that address All of the
concerns you had with v1. It is my hope to get them merged without
too much more trouble.
The rtc _needs_ patches 1-5 in order to use the clock offset
adjustment at all (current upstream code resets it to zero during
device probe, so it doesn't survive a reboot)
Should I split out patches 1-5 to make them easier to review?
The merge widows just closed so I've started to collect a few patches
since monday. This is a big series and I didn't have time to review
everything yet.
quoted
Patches 6-8 are attemping to add a new function to the rtc class
to adjust the clock rate. I hope I am going about this the right way,
But here goes.
I am hoping to have some discussion about 6, 7 and 8.
Particularly whether parts per billion is the right unit (I think it is)
and whether "offset" is the best name for the attribute (not as sure).
Yeah, My plan was to take 1 to 5 and leave out 6-8 for discussion, I'm
not yet sure what the correct api should look like.
quoted
A number of rtc devices, such as the NXP pcf2123 include a facility
to adjust the clock in order to compensate for temperature or a
crystal, capacitor, etc, that results in the rtc clock not running
at exactly 32.768 kHz.
This patchset adds kernel and sysfs hooks to access that ability.
One datasheet suggests it might be adjusted based on input from
a temperature sensor. I could also potentially see it being set
as part of ntp calibration.
Data sheets I have seen refer to this as a clock offset, and measure it
in parts per million (ppm), however they often reference ppm to 2 digits
of precision, which makes integer ppm less than ideal. I use parts per
billion, which more than covers the precision needed and works nicely
within 32 bits
The name "offset" came from the pcf-2123 datasheet and is used by at
least some other data sheets. I would be happy to use a different term
if someone else comes up with something more concise.
Changes since v1:
- Use the BIT() macro for all register bits
- Remove unneeded range checks from read/write functions
- Merge patch 3 (replace magic numbers with defines) into patch 2
- Add a proper commit message to patch 5, now patch 4
- Fix a function alignment bug.
- Move OSC_HAS_STOPPED check into pcf2123_rtc_read_time, and get rid of
pcf2123_time_valid()
- Drop patches refactoring pcf2123 sysfs.
- Add rtc interface and rtc sysfs file for clock offset
Joshua Clayton (8):
rtc-pcf2123: define registers and bit macros
rtc-pcf2123: clean up reads from the chip
rtc-pcf2123: clean up writes to the rtc chip
rtc-pcf2123: refactor chip reset into a function
rtc-pcf2123: avoid resetting the clock if possible
rtc: Add functions to set and read clock offset
rtc: implement a sysfs interface for clock offset
rtc-pcf2123: implement read_offset and set_offset
drivers/rtc/interface.c | 57 ++++++++++
drivers/rtc/rtc-pcf2123.c | 271 +++++++++++++++++++++++++++++++++-------------
drivers/rtc/rtc-sysfs.c | 29 +++++
include/linux/rtc.h | 4 +
4 files changed, 284 insertions(+), 77 deletions(-)
Thanks again,
Joshua Clayton
--
Alexandre Belloni, Free Electrons
Embedded Linux, Kernel and Android engineering
http://free-electrons.com
--
--
You received this message because you are subscribed to "rtc-linux".
Membership options at http://groups.google.com/group/rtc-linux .
Please read http://groups.google.com/group/rtc-linux/web/checklist
before submitting a driver.
---
You received this message because you are subscribed to the Google Groups "rtc-linux" group.
To unsubscribe from this group and stop receiving emails from it, send an email to rtc-linux+unsubscribe@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.
Hi,
On 26/01/2016 at 17:00:31 +0100, Alexandre Belloni wrote :
On 26/01/2016 at 06:56:40 -0800, Joshua Clayton wrote :
quoted
Ping?
On Monday, January 04, 2016 10:31:18 AM Joshua Clayton wrote:
quoted
Alexandre,
this is the second version of apatch set to be able to adjust the
clock on a pcf2123, but with a big addition. I am also proposing
a couple of new rtc api functions and a new sysfs file.
Patches 1-5 are very much v2 patches that address All of the
concerns you had with v1. It is my hope to get them merged without
too much more trouble.
The rtc _needs_ patches 1-5 in order to use the clock offset
adjustment at all (current upstream code resets it to zero during
device probe, so it doesn't survive a reboot)
Should I split out patches 1-5 to make them easier to review?
The merge widows just closed so I've started to collect a few patches
since monday. This is a big series and I didn't have time to review
everything yet.
Patches 1-5 are applied and pushed to rtc-next.
--
Alexandre Belloni, Free Electrons
Embedded Linux, Kernel and Android engineering
http://free-electrons.com
--
--
You received this message because you are subscribed to "rtc-linux".
Membership options at http://groups.google.com/group/rtc-linux .
Please read http://groups.google.com/group/rtc-linux/web/checklist
before submitting a driver.
---
You received this message because you are subscribed to the Google Groups "rtc-linux" group.
To unsubscribe from this group and stop receiving emails from it, send an email to rtc-linux+unsubscribe@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.
Hi,
On 04/01/2016 at 10:31:25 -0800, Joshua Clayton wrote :
The file is called "offset", and may be set and read in decimal.
For rtcs that do not have read_offset or set_offset implemented,
read always returns zero and write will return -EINVAL.
Can you expand rtc_attr_is_visible() instead of having the offset file
always present?
Also, you need to expand Documentation/rtc.txt, section SYSFS INTERFACE.
I'm fine with having parts per billion as the unit and I hope we won't
ever need anything more precise :)
--
Alexandre Belloni, Free Electrons
Embedded Linux, Kernel and Android engineering
http://free-electrons.com
--
--
You received this message because you are subscribed to "rtc-linux".
Membership options at http://groups.google.com/group/rtc-linux .
Please read http://groups.google.com/group/rtc-linux/web/checklist
before submitting a driver.
---
You received this message because you are subscribed to the Google Groups "rtc-linux" group.
To unsubscribe from this group and stop receiving emails from it, send an email to rtc-linux+unsubscribe@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.
On Sun, 31 Jan 2016 12:41:15 +0100
Alexandre Belloni [off-list ref] wrote:
Hi,
On 04/01/2016 at 10:31:25 -0800, Joshua Clayton wrote :
quoted
The file is called "offset", and may be set and read in decimal.
For rtcs that do not have read_offset or set_offset implemented,
read always returns zero and write will return -EINVAL.
Can you expand rtc_attr_is_visible() instead of having the offset file
always present?
Yes, Absolutely.
I wanted to do something like this, but didn't know is_visible
existed... and no wonder. Its in attribute_group
Also, you need to expand Documentation/rtc.txt, section SYSFS
INTERFACE.
OK. Will do.
I'm fine with having parts per billion as the unit and I hope we won't
ever need anything more precise :)
It is orders of magnitude more than needed at present
...and no will ever need more than 640k of memory... right?
--
--
You received this message because you are subscribed to "rtc-linux".
Membership options at http://groups.google.com/group/rtc-linux .
Please read http://groups.google.com/group/rtc-linux/web/checklist
before submitting a driver.
---
You received this message because you are subscribed to the Google Groups "rtc-linux" group.
To unsubscribe from this group and stop receiving emails from it, send an email to rtc-linux+unsubscribe@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.
On 01/02/2016 at 12:56:48 -0800, Joshua Clayton wrote :
quoted
I'm fine with having parts per billion as the unit and I hope we won't
ever need anything more precise :)
It is orders of magnitude more than needed at present
Yeah, until we get an RTC with an offset precision that has 4 decimals in ppm.
...and no will ever need more than 640k of memory... right?
Right :)
--
Alexandre Belloni, Free Electrons
Embedded Linux, Kernel and Android engineering
http://free-electrons.com
--
--
You received this message because you are subscribed to "rtc-linux".
Membership options at http://groups.google.com/group/rtc-linux .
Please read http://groups.google.com/group/rtc-linux/web/checklist
before submitting a driver.
---
You received this message because you are subscribed to the Google Groups "rtc-linux" group.
To unsubscribe from this group and stop receiving emails from it, send an email to rtc-linux+unsubscribe@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.
A number of rtc devices, such as the NXP pcf2123 include a facility
to adjust the clock in order to compensate for temperature or a
crystal, capacitor, etc, that results in the rtc clock not running
at exactly 32.768 kHz.
Data sheets I have seen refer to this as a clock offset, and measure it
in parts per million, however they often reference ppm to 2 digits of
precision, which makes integer ppm less than ideal.
We use parts per billion, which more than covers the precision needed
and works nicely within 32 bits
Signed-off-by: Joshua Clayton <redacted>
---
Changes since v2:
- patches 1 - 5 from v2 were merged, so 6, 7 , and 8 become 1, 2, 3
- Added documentation of the sysfs interface in Documenbtation/rtc.txt
- Added code so that the offset attrbute does not appear on rtcs that
do not support it.
drivers/rtc/interface.c | 57 +++++++++++++++++++++++++++++++++++++++++++++++++
include/linux/rtc.h | 4 ++++
2 files changed, 61 insertions(+)
--
2.5.0
--
--
You received this message because you are subscribed to "rtc-linux".
Membership options at http://groups.google.com/group/rtc-linux .
Please read http://groups.google.com/group/rtc-linux/web/checklist
before submitting a driver.
---
You received this message because you are subscribed to the Google Groups "rtc-linux" group.
To unsubscribe from this group and stop receiving emails from it, send an email to rtc-linux+unsubscribe@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.
clock offset may be set and read in decimal parts per billion
attribute is /sys/class/rtc/rtcN/offset
The attribute is only visible for rtcs that have set_offset implemented.
Signed-off-by: Joshua Clayton <redacted>
---
Documentation/rtc.txt | 6 ++++++
drivers/rtc/rtc-sysfs.c | 35 ++++++++++++++++++++++++++++++++++-
2 files changed, 40 insertions(+), 1 deletion(-)
@@ -157,6 +157,12 @@ wakealarm: The time at which the clock will generate a system wakeup the epoch by default, or if there's a leading +, seconds in the future, or if there is a leading +=, seconds ahead of the current alarm.+offset: The amount which the rtc clock has been adjusted in firmware.+ Visible only if the driver supports clock offset adjustment.+ The unit is parts per billion, i.e. The number of clock ticks+ which are added to or removed from the rtc's base clock per+ billion ticks. A positive value makes a day pass more slowly,+ longer, and a negative value makes a day pass more quickly. IOCTL INTERFACE ---------------
--
2.5.0
--
--
You received this message because you are subscribed to "rtc-linux".
Membership options at http://groups.google.com/group/rtc-linux .
Please read http://groups.google.com/group/rtc-linux/web/checklist
before submitting a driver.
---
You received this message because you are subscribed to the Google Groups "rtc-linux" group.
To unsubscribe from this group and stop receiving emails from it, send an email to rtc-linux+unsubscribe@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.
pcf2123 has an offset register, which can be used to make minor
adjustments to the clock rate to compensate for temperature or
a crystal that is not exactly right.
Signed-off-by: Joshua Clayton <redacted>
---
drivers/rtc/rtc-pcf2123.c | 57 +++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 57 insertions(+)
@@ -100,6 +100,7 @@/* PCF2123_REG_OFFSET BITS */#define OFFSET_SIGN_BIT BIT(6) /* 2's complement sign bit */#define OFFSET_COARSE BIT(7) /* Coarse mode offset */+#define OFFSET_STEP (2170) /* Offset step in parts per billion *//* READ/WRITE ADDRESS BITS */#define PCF2123_WRITE BIT(4)
@@ -206,6 +207,59 @@ static ssize_t pcf2123_store(struct device *dev, struct device_attribute *attr,returncount;}+staticintpcf2123_read_offset(structdevice*dev,long*offset)+{+intret;+s8reg;++ret=pcf2123_read(dev,PCF2123_REG_OFFSET,®,1);+if(ret<0)+returnret;++if(reg&OFFSET_COARSE)+reg<<=1;/* multiply by 2 and sign extend */+else+reg|=(reg&OFFSET_SIGN_BIT)<<1;/* sign extend only */++*offset=((long)reg)*OFFSET_STEP;++return0;+}++/*+*Theoffsetregisterisa7bitsignedvaluewithacoarsebitinbit7.+*Themaindifferencebetweenthetwoisnormaloffsetadjuststhefirst+*secondofnminuteseveryotherhour,with61,62and63beingshoved+*intothe60thminute.+*Thecoarseadjustmentdoesthesame,buteveryhour.+*thetwooverlap,witheveryevennormaloffsetvaluecorresponding+*toacoarseoffset.Basedonthisalgorithm,itseemsthatdespitethe+*name,coarseoffsetisabetterfitforoverlappingvalues.+*/+staticintpcf2123_set_offset(structdevice*dev,longoffset)+{+s8reg;++if(offset>OFFSET_STEP*127)+reg=127;+elseif(offset<OFFSET_STEP*-128)+reg=-128;+else+reg=(s8)((offset+(OFFSET_STEP>>1))/OFFSET_STEP);++/* choose fine offset only for odd values in the normal range */+if(reg&1&®<=63&®>=-64){+/* Normal offset. Clear the coarse bit */+reg&=~OFFSET_COARSE;+}else{+/* Coarse offset. Divide by 2 and set the coarse bit */+reg>>=1;+reg|=OFFSET_COARSE;+}++returnpcf2123_write_reg(dev,PCF2123_REG_OFFSET,reg);+}+staticintpcf2123_rtc_read_time(structdevice*dev,structrtc_time*tm){u8rxbuf[7];
@@ -314,6 +368,9 @@ static int pcf2123_reset(struct device *dev)staticconststructrtc_class_opspcf2123_rtc_ops={.read_time=pcf2123_rtc_read_time,.set_time=pcf2123_rtc_set_time,+.read_offset=pcf2123_read_offset,+.set_offset=pcf2123_set_offset,+};staticintpcf2123_probe(structspi_device*spi)
--
2.5.0
--
--
You received this message because you are subscribed to "rtc-linux".
Membership options at http://groups.google.com/group/rtc-linux .
Please read http://groups.google.com/group/rtc-linux/web/checklist
before submitting a driver.
---
You received this message because you are subscribed to the Google Groups "rtc-linux" group.
To unsubscribe from this group and stop receiving emails from it, send an email to rtc-linux+unsubscribe@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.
I should have been clearer but this is not necessary anymore since the
sysfs interface will not always be present but you
should probably test rtc->ops->read_offset instead.
quoted hunk
+ mutex_lock(&rtc->ops_lock);+ ret = rtc->ops->read_offset(rtc->dev.parent, offset);+ mutex_unlock(&rtc->ops_lock);+ return ret;+}+/**+ * rtc_set_offset - Adjusts the duration of the average second+ * @ rtc: rtc device to be used+ * @ offset: the offset in parts per billion+ *+ * Some rtc's allow an adjustment to the average duration of a second+ * to compensate for differences in the actual clock rate due to temperature,+ * the crystal, capacitor, etc.+ *+ * Kernel interface to adjust an rtc clock offset.+ * Return 0 on success, or a negative number on error.+ * If the rtc offset is not setable (or not implemented), return -EINVAL+ */+int rtc_set_offset(struct rtc_device *rtc, long offset)+{+ int ret = 0;++ if (!rtc->ops)+ return -ENODEV;++ if (!rtc->ops->set_offset)+ return -EINVAL;++ mutex_lock(&rtc->ops_lock);+ ret = rtc->ops->set_offset(rtc->dev.parent, offset);+ mutex_unlock(&rtc->ops_lock);+ return ret;+}
--
Alexandre Belloni, Free Electrons
Embedded Linux, Kernel and Android engineering
http://free-electrons.com
--
--
You received this message because you are subscribed to "rtc-linux".
Membership options at http://groups.google.com/group/rtc-linux .
Please read http://groups.google.com/group/rtc-linux/web/checklist
before submitting a driver.
---
You received this message because you are subscribed to the Google Groups "rtc-linux" group.
To unsubscribe from this group and stop receiving emails from it, send an email to rtc-linux+unsubscribe@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.
A really small nitpick below
On 03/02/2016 at 09:16:43 -0800, Joshua Clayton wrote :
quoted hunk
clock offset may be set and read in decimal parts per billion
attribute is /sys/class/rtc/rtcN/offset
The attribute is only visible for rtcs that have set_offset implemented.
Signed-off-by: Joshua Clayton <redacted>
---
Documentation/rtc.txt | 6 ++++++
drivers/rtc/rtc-sysfs.c | 35 ++++++++++++++++++++++++++++++++++-
2 files changed, 40 insertions(+), 1 deletion(-)
@@ -157,6 +157,12 @@ wakealarm: The time at which the clock will generate a system wakeup the epoch by default, or if there's a leading +, seconds in the future, or if there is a leading +=, seconds ahead of the current alarm.+offset: The amount which the rtc clock has been adjusted in firmware.+ Visible only if the driver supports clock offset adjustment.+ The unit is parts per billion, i.e. The number of clock ticks+ which are added to or removed from the rtc's base clock per+ billion ticks. A positive value makes a day pass more slowly,+ longer, and a negative value makes a day pass more quickly. IOCTL INTERFACE ---------------
@@ -249,9 +278,13 @@ static umode_t rtc_attr_is_visible(struct kobject *kobj, struct rtc_device *rtc = to_rtc_device(dev); umode_t mode = attr->mode;- if (attr == &dev_attr_wakealarm.attr)+ if (attr == &dev_attr_wakealarm.attr) { if (!rtc_does_wakealarm(rtc)) mode = 0;+ } else if (attr == &dev_attr_offset.attr) {+ if (!rtc->ops->set_offset)+ mode = 0;+ } return mode; }
--
2.5.0
--
Alexandre Belloni, Free Electrons
Embedded Linux, Kernel and Android engineering
http://free-electrons.com
--
--
You received this message because you are subscribed to "rtc-linux".
Membership options at http://groups.google.com/group/rtc-linux .
Please read http://groups.google.com/group/rtc-linux/web/checklist
before submitting a driver.
---
You received this message because you are subscribed to the Google Groups "rtc-linux" group.
To unsubscribe from this group and stop receiving emails from it, send an email to rtc-linux+unsubscribe@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.
struct rtc_timer *timer) mutex_unlock(&rtc->ops_lock);
}
+/**
+ * rtc_read_offset - Read the amount of rtc offset in parts per
billion
+ * @ rtc: rtc device to be used
+ * @ offset: the offset in parts per billion
+ *
+ * see below for details.
+ *
+ * Kernel interface to read rtc clock offset
+ * Returns 0 on success, or a negative number on error.
+ * If the rtc offset is not setable (or not implemented), return 0
and put
+ * 0 in the offset value;
+ */
+int rtc_read_offset(struct rtc_device *rtc, long *offset)
+{
+ int ret = 0;
+
+ if (!rtc->ops)
+ return -ENODEV;
+
+ if (!rtc->ops->set_offset) {
+ *offset = 0;
+ return 0;
+ }
+
I should have been clearer but this is not necessary anymore since the
sysfs interface will not always be present but you
should probably test rtc->ops->read_offset instead.
I left it because the kernel API is still there even if the sysfs
file is not...
but yeah, you are right. I'll fix the check, and the formatting
in the other patch.
quoted
+ mutex_lock(&rtc->ops_lock);
+ ret = rtc->ops->read_offset(rtc->dev.parent, offset);
+ mutex_unlock(&rtc->ops_lock);
+ return ret;
+}
+/**
+ * rtc_set_offset - Adjusts the duration of the average second
+ * @ rtc: rtc device to be used
+ * @ offset: the offset in parts per billion
+ *
+ * Some rtc's allow an adjustment to the average duration of a
second
+ * to compensate for differences in the actual clock rate due to
temperature,
+ * the crystal, capacitor, etc.
+ *
+ * Kernel interface to adjust an rtc clock offset.
+ * Return 0 on success, or a negative number on error.
+ * If the rtc offset is not setable (or not implemented), return
-EINVAL
+ */
+int rtc_set_offset(struct rtc_device *rtc, long offset)
+{
+ int ret = 0;
+
+ if (!rtc->ops)
+ return -ENODEV;
+
+ if (!rtc->ops->set_offset)
+ return -EINVAL;
+
+ mutex_lock(&rtc->ops_lock);
+ ret = rtc->ops->set_offset(rtc->dev.parent, offset);
+ mutex_unlock(&rtc->ops_lock);
+ return ret;
+}
--
--
You received this message because you are subscribed to "rtc-linux".
Membership options at http://groups.google.com/group/rtc-linux .
Please read http://groups.google.com/group/rtc-linux/web/checklist
before submitting a driver.
---
You received this message because you are subscribed to the Google Groups "rtc-linux" group.
To unsubscribe from this group and stop receiving emails from it, send an email to rtc-linux+unsubscribe@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.
On 04/02/2016 at 15:32:42 -0800, Joshua Clayton wrote :
quoted
quoted
+int rtc_read_offset(struct rtc_device *rtc, long *offset)+{+ int ret = 0;++ if (!rtc->ops)+ return -ENODEV;++ if (!rtc->ops->set_offset) {+ *offset = 0;+ return 0;+ }+
I should have been clearer but this is not necessary anymore since the
sysfs interface will not always be present but you
should probably test rtc->ops->read_offset instead.
I left it because the kernel API is still there even if the sysfs
file is not...
but yeah, you are right. I'll fix the check, and the formatting
in the other patch.
Yeah but from inside the kernel, I feel that it is more useful to know
that the value doesn't exist instead of having 0.
--
Alexandre Belloni, Free Electrons
Embedded Linux, Kernel and Android engineering
http://free-electrons.com
--
--
You received this message because you are subscribed to "rtc-linux".
Membership options at http://groups.google.com/group/rtc-linux .
Please read http://groups.google.com/group/rtc-linux/web/checklist
before submitting a driver.
---
You received this message because you are subscribed to the Google Groups "rtc-linux" group.
To unsubscribe from this group and stop receiving emails from it, send an email to rtc-linux+unsubscribe@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.
A number of rtc devices, such as the NXP pcf2123 include a facility
to adjust the clock in order to compensate for temperature or a
crystal, capacitor, etc, that results in the rtc clock not running
at exactly 32.768 kHz.
Data sheets I have seen refer to this as a clock offset, and measure it
in parts per million, however they often reference ppm to 2 digits of
precision, which makes integer ppm less than ideal.
We use parts per billion, which more than covers the precision needed
and works nicely within 32 bits
Signed-off-by: Joshua Clayton <redacted>
---
drivers/rtc/interface.c | 54 +++++++++++++++++++++++++++++++++++++++++++++++++
include/linux/rtc.h | 4 ++++
2 files changed, 58 insertions(+)
--
2.5.0
--
--
You received this message because you are subscribed to "rtc-linux".
Membership options at http://groups.google.com/group/rtc-linux .
Please read http://groups.google.com/group/rtc-linux/web/checklist
before submitting a driver.
---
You received this message because you are subscribed to the Google Groups "rtc-linux" group.
To unsubscribe from this group and stop receiving emails from it, send an email to rtc-linux+unsubscribe@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.
pcf2123 has an offset register, which can be used to make minor
adjustments to the clock rate to compensate for temperature or
a crystal that is not exactly right.
Signed-off-by: Joshua Clayton <redacted>
---
drivers/rtc/rtc-pcf2123.c | 57 +++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 57 insertions(+)
@@ -100,6 +100,7 @@/* PCF2123_REG_OFFSET BITS */#define OFFSET_SIGN_BIT BIT(6) /* 2's complement sign bit */#define OFFSET_COARSE BIT(7) /* Coarse mode offset */+#define OFFSET_STEP (2170) /* Offset step in parts per billion *//* READ/WRITE ADDRESS BITS */#define PCF2123_WRITE BIT(4)
@@ -206,6 +207,59 @@ static ssize_t pcf2123_store(struct device *dev, struct device_attribute *attr,returncount;}+staticintpcf2123_read_offset(structdevice*dev,long*offset)+{+intret;+s8reg;++ret=pcf2123_read(dev,PCF2123_REG_OFFSET,®,1);+if(ret<0)+returnret;++if(reg&OFFSET_COARSE)+reg<<=1;/* multiply by 2 and sign extend */+else+reg|=(reg&OFFSET_SIGN_BIT)<<1;/* sign extend only */++*offset=((long)reg)*OFFSET_STEP;++return0;+}++/*+*Theoffsetregisterisa7bitsignedvaluewithacoarsebitinbit7.+*Themaindifferencebetweenthetwoisnormaloffsetadjuststhefirst+*secondofnminuteseveryotherhour,with61,62and63beingshoved+*intothe60thminute.+*Thecoarseadjustmentdoesthesame,buteveryhour.+*thetwooverlap,witheveryevennormaloffsetvaluecorresponding+*toacoarseoffset.Basedonthisalgorithm,itseemsthatdespitethe+*name,coarseoffsetisabetterfitforoverlappingvalues.+*/+staticintpcf2123_set_offset(structdevice*dev,longoffset)+{+s8reg;++if(offset>OFFSET_STEP*127)+reg=127;+elseif(offset<OFFSET_STEP*-128)+reg=-128;+else+reg=(s8)((offset+(OFFSET_STEP>>1))/OFFSET_STEP);++/* choose fine offset only for odd values in the normal range */+if(reg&1&®<=63&®>=-64){+/* Normal offset. Clear the coarse bit */+reg&=~OFFSET_COARSE;+}else{+/* Coarse offset. Divide by 2 and set the coarse bit */+reg>>=1;+reg|=OFFSET_COARSE;+}++returnpcf2123_write_reg(dev,PCF2123_REG_OFFSET,reg);+}+staticintpcf2123_rtc_read_time(structdevice*dev,structrtc_time*tm){u8rxbuf[7];
@@ -314,6 +368,9 @@ static int pcf2123_reset(struct device *dev)staticconststructrtc_class_opspcf2123_rtc_ops={.read_time=pcf2123_rtc_read_time,.set_time=pcf2123_rtc_set_time,+.read_offset=pcf2123_read_offset,+.set_offset=pcf2123_set_offset,+};staticintpcf2123_probe(structspi_device*spi)
--
2.5.0
--
--
You received this message because you are subscribed to "rtc-linux".
Membership options at http://groups.google.com/group/rtc-linux .
Please read http://groups.google.com/group/rtc-linux/web/checklist
before submitting a driver.
---
You received this message because you are subscribed to the Google Groups "rtc-linux" group.
To unsubscribe from this group and stop receiving emails from it, send an email to rtc-linux+unsubscribe@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.
clock offset may be set and read in decimal parts per billion
attribute is /sys/class/rtc/rtcN/offset
The attribute is only visible for rtcs that have set_offset implemented.
Signed-off-by: Joshua Clayton <redacted>
---
Documentation/rtc.txt | 6 ++++++
drivers/rtc/rtc-sysfs.c | 35 ++++++++++++++++++++++++++++++++++-
2 files changed, 40 insertions(+), 1 deletion(-)
@@ -157,6 +157,12 @@ wakealarm: The time at which the clock will generate a system wakeup the epoch by default, or if there's a leading +, seconds in the future, or if there is a leading +=, seconds ahead of the current alarm.+offset: The amount which the rtc clock has been adjusted in firmware.+ Visible only if the driver supports clock offset adjustment.+ The unit is parts per billion, i.e. The number of clock ticks+ which are added to or removed from the rtc's base clock per+ billion ticks. A positive value makes a day pass more slowly,+ longer, and a negative value makes a day pass more quickly. IOCTL INTERFACE ---------------
--
2.5.0
--
--
You received this message because you are subscribed to "rtc-linux".
Membership options at http://groups.google.com/group/rtc-linux .
Please read http://groups.google.com/group/rtc-linux/web/checklist
before submitting a driver.
---
You received this message because you are subscribed to the Google Groups "rtc-linux" group.
To unsubscribe from this group and stop receiving emails from it, send an email to rtc-linux+unsubscribe@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.
On Fri, 5 Feb 2016 12:41:11 -0800
Joshua Clayton [off-list ref] wrote:
Alexandre,
in case you didn't see, I made the change you requested.
The rtc_read_offset function checks for a read_offset function
and returns -EINVAL if not there, instead of an offset of 0.
I just didn't put together a cover letter this time around.
quoted hunk
A number of rtc devices, such as the NXP pcf2123 include a facility
to adjust the clock in order to compensate for temperature or a
crystal, capacitor, etc, that results in the rtc clock not running
at exactly 32.768 kHz.
Data sheets I have seen refer to this as a clock offset, and measure
it in parts per million, however they often reference ppm to 2 digits
of precision, which makes integer ppm less than ideal.
We use parts per billion, which more than covers the precision needed
and works nicely within 32 bits
Signed-off-by: Joshua Clayton <redacted>
---
drivers/rtc/interface.c | 54
+++++++++++++++++++++++++++++++++++++++++++++++++
include/linux/rtc.h | 4 ++++ 2 files changed, 58 insertions(+)
rtc_t4e40602412d61b7ef4162621a1a15be32126baeeimer_cancel(struct
rtc_device *rtc, struct rtc_timer *timer)
mutex_unlock(&rtc->ops_lock); }
+/**
+ * rtc_read_offset - Read the amount of rtc offset in parts per
billion
+ * @ rtc: rtc device to be used
+ * @ offset: the offset in parts per billion
+ *
+ * see below for details.
+ *
+ * Kernel interface to read rtc clock offset
+ * Returns 0 on success, or a negative number on error.
+ * If read_offset() is not implemented for the rtc, return -EINVAL
+ */
+int rtc_read_offset(struct rtc_device *rtc, long *offset)
+{
+ int ret;
+
+ if (!rtc->ops)
+ return -ENODEV;
+
+ if (!rtc->ops->read_offset)
+ return -EINVAL;
+
+ mutex_lock(&rtc->ops_lock);
+ ret = rtc->ops->read_offset(rtc->dev.parent, offset);
+ mutex_unlock(&rtc->ops_lock);
+ return ret;
+}
+/**
+ * rtc_set_offset - Adjusts the duration of the average second
+ * @ rtc: rtc device to be used
+ * @ offset: the offset in parts per billion
+ *
+ * Some rtc's allow an adjustment to the average duration of a second
+ * to compensate for differences in the actual clock rate due to
temperature,
+ * the crystal, capacitor, etc.
+ *
+ * Kernel interface to adjust an rtc clock offset.
+ * Return 0 on success, or a negative number on error.
+ * If the rtc offset is not setable (or not implemented), return
-EINVAL
+ */
+int rtc_set_offset(struct rtc_device *rtc, long offset)
+{
+ int ret;
+
+ if (!rtc->ops)
+ return -ENODEV;
+
+ if (!rtc->ops->set_offset)
+ return -EINVAL;
+
+ mutex_lock(&rtc->ops_lock);
+ ret = rtc->ops->set_offset(rtc->dev.parent, offset);
+ mutex_unlock(&rtc->ops_lock);
+ return ret;
+}
Thanks,
Joshua
--
--
You received this message because you are subscribed to "rtc-linux".
Membership options at http://groups.google.com/group/rtc-linux .
Please read http://groups.google.com/group/rtc-linux/web/checklist
before submitting a driver.
---
You received this message because you are subscribed to the Google Groups "rtc-linux" group.
To unsubscribe from this group and stop receiving emails from it, send an email to rtc-linux+unsubscribe@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.
Hi,
On 23/02/2016 at 10:47:13 -0800, Joshua Clayton wrote :
On Fri, 5 Feb 2016 12:41:11 -0800
Joshua Clayton [off-list ref] wrote:
Alexandre,
in case you didn't see, I made the change you requested.
The rtc_read_offset function checks for a read_offset function
and returns -EINVAL if not there, instead of an offset of 0.
I just didn't put together a cover letter this time around.
Sure, I was planning to review them tonight anyway.
All applied, thanks!
--
Alexandre Belloni, Free Electrons
Embedded Linux, Kernel and Android engineering
http://free-electrons.com
--
--
You received this message because you are subscribed to "rtc-linux".
Membership options at http://groups.google.com/group/rtc-linux .
Please read http://groups.google.com/group/rtc-linux/web/checklist
before submitting a driver.
---
You received this message because you are subscribed to the Google Groups "rtc-linux" group.
To unsubscribe from this group and stop receiving emails from it, send an email to rtc-linux+unsubscribe@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.