From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1756838AbcBEUlp (ORCPT ); Fri, 5 Feb 2016 15:41:45 -0500 Received: from mail-pf0-f193.google.com ([209.85.192.193]:35299 "EHLO mail-pf0-f193.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1753926AbcBEUll (ORCPT ); Fri, 5 Feb 2016 15:41:41 -0500 From: Joshua Clayton To: Alessandro Zummo , Alexandre Belloni Cc: Jonathan Corbet , rtc-linux@googlegroups.com, linux-doc@vger.kernel.org, linux-kernel@vger.kernel.org, Joshua Clayton Subject: [PATCH v4 3/3] rtc-pcf2123: implement read_offset and set_offset Date: Fri, 5 Feb 2016 12:41:13 -0800 Message-Id: <1454704873-31066-3-git-send-email-stillcompiling@gmail.com> X-Mailer: git-send-email 2.5.0 In-Reply-To: <1454704873-31066-1-git-send-email-stillcompiling@gmail.com> References: <20160205143908.GJ4782@piout.net> <1454704873-31066-1-git-send-email-stillcompiling@gmail.com> Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org 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 --- drivers/rtc/rtc-pcf2123.c | 57 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 57 insertions(+) diff --git a/drivers/rtc/rtc-pcf2123.c b/drivers/rtc/rtc-pcf2123.c index d9a44ad..da27738 100644 --- a/drivers/rtc/rtc-pcf2123.c +++ b/drivers/rtc/rtc-pcf2123.c @@ -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, return count; } +static int pcf2123_read_offset(struct device *dev, long *offset) +{ + int ret; + s8 reg; + + ret = pcf2123_read(dev, PCF2123_REG_OFFSET, ®, 1); + if (ret < 0) + return ret; + + 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; + + return 0; +} + +/* + * The offset register is a 7 bit signed value with a coarse bit in bit 7. + * The main difference between the two is normal offset adjusts the first + * second of n minutes every other hour, with 61, 62 and 63 being shoved + * into the 60th minute. + * The coarse adjustment does the same, but every hour. + * the two overlap, with every even normal offset value corresponding + * to a coarse offset. Based on this algorithm, it seems that despite the + * name, coarse offset is a better fit for overlapping values. + */ +static int pcf2123_set_offset(struct device *dev, long offset) +{ + s8 reg; + + if (offset > OFFSET_STEP * 127) + reg = 127; + else if (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 && reg <= 63 && reg >= -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; + } + + return pcf2123_write_reg(dev, PCF2123_REG_OFFSET, reg); +} + static int pcf2123_rtc_read_time(struct device *dev, struct rtc_time *tm) { u8 rxbuf[7]; @@ -314,6 +368,9 @@ static int pcf2123_reset(struct device *dev) static const struct rtc_class_ops pcf2123_rtc_ops = { .read_time = pcf2123_rtc_read_time, .set_time = pcf2123_rtc_set_time, + .read_offset = pcf2123_read_offset, + .set_offset = pcf2123_set_offset, + }; static int pcf2123_probe(struct spi_device *spi) -- 2.5.0 From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: MIME-Version: 1.0 Received: from mail-pf0-x243.google.com (mail-pf0-x243.google.com. [2607:f8b0:400e:c00::243]) by gmr-mx.google.com with ESMTPS id r2si2462936pfr.0.2016.02.05.12.41.41 for (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Fri, 05 Feb 2016 12:41:41 -0800 (PST) Received: by mail-pf0-x243.google.com with SMTP id 71so614720pfv.1 for ; Fri, 05 Feb 2016 12:41:41 -0800 (PST) From: Joshua Clayton To: Alessandro Zummo , Alexandre Belloni Cc: Jonathan Corbet , rtc-linux@googlegroups.com, linux-doc@vger.kernel.org, linux-kernel@vger.kernel.org, Joshua Clayton Subject: [rtc-linux] [PATCH v4 3/3] rtc-pcf2123: implement read_offset and set_offset Date: Fri, 5 Feb 2016 12:41:13 -0800 Message-Id: <1454704873-31066-3-git-send-email-stillcompiling@gmail.com> In-Reply-To: <1454704873-31066-1-git-send-email-stillcompiling@gmail.com> References: <20160205143908.GJ4782@piout.net> <1454704873-31066-1-git-send-email-stillcompiling@gmail.com> Reply-To: rtc-linux@googlegroups.com Content-Type: text/plain; charset=UTF-8 List-ID: List-Post: , List-Help: , List-Archive: , List-Unsubscribe: , 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 --- drivers/rtc/rtc-pcf2123.c | 57 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 57 insertions(+) diff --git a/drivers/rtc/rtc-pcf2123.c b/drivers/rtc/rtc-pcf2123.c index d9a44ad..da27738 100644 --- a/drivers/rtc/rtc-pcf2123.c +++ b/drivers/rtc/rtc-pcf2123.c @@ -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, return count; } +static int pcf2123_read_offset(struct device *dev, long *offset) +{ + int ret; + s8 reg; + + ret = pcf2123_read(dev, PCF2123_REG_OFFSET, ®, 1); + if (ret < 0) + return ret; + + 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; + + return 0; +} + +/* + * The offset register is a 7 bit signed value with a coarse bit in bit 7. + * The main difference between the two is normal offset adjusts the first + * second of n minutes every other hour, with 61, 62 and 63 being shoved + * into the 60th minute. + * The coarse adjustment does the same, but every hour. + * the two overlap, with every even normal offset value corresponding + * to a coarse offset. Based on this algorithm, it seems that despite the + * name, coarse offset is a better fit for overlapping values. + */ +static int pcf2123_set_offset(struct device *dev, long offset) +{ + s8 reg; + + if (offset > OFFSET_STEP * 127) + reg = 127; + else if (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 && reg <= 63 && reg >= -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; + } + + return pcf2123_write_reg(dev, PCF2123_REG_OFFSET, reg); +} + static int pcf2123_rtc_read_time(struct device *dev, struct rtc_time *tm) { u8 rxbuf[7]; @@ -314,6 +368,9 @@ static int pcf2123_reset(struct device *dev) static const struct rtc_class_ops pcf2123_rtc_ops = { .read_time = pcf2123_rtc_read_time, .set_time = pcf2123_rtc_set_time, + .read_offset = pcf2123_read_offset, + .set_offset = pcf2123_set_offset, + }; static int pcf2123_probe(struct spi_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.