Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]
Groups > linux.kernel > #1262377 > unrolled thread
| Started by | Joshua Clayton <stillcompiling@gmail.com> |
|---|---|
| First post | 2015-11-04 16:40 +0100 |
| Last post | 2015-11-04 16:40 +0100 |
| Articles | 5 — 1 participant |
Back to article view | Back to linux.kernel
[PATCH 0/9] rtc-2123: access the clock offset feature Joshua Clayton <stillcompiling@gmail.com> - 2015-11-04 16:40 +0100
[PATCH 2/9] rtc-pcf2123: clean up reads from the chip Joshua Clayton <stillcompiling@gmail.com> - 2015-11-04 16:40 +0100
[PATCH 5/9] rtc-pcf2123: put the chip reset into a function Joshua Clayton <stillcompiling@gmail.com> - 2015-11-04 16:40 +0100
[PATCH 7/9] rtc-pcf2123: allow sysfs to accept hexidecimal Joshua Clayton <stillcompiling@gmail.com> - 2015-11-04 16:40 +0100
[PATCH 9/9] rtc-pcf2123: adjust the clock rate via sysfs Joshua Clayton <stillcompiling@gmail.com> - 2015-11-04 16:40 +0100
| From | Joshua Clayton <stillcompiling@gmail.com> |
|---|---|
| Date | 2015-11-04 16:40 +0100 |
| Subject | [PATCH 0/9] rtc-2123: access the clock offset feature |
| Message-ID | <qr8kh-2go-9@gated-at.bofh.it> |
Greetings, This series was prompted by a need to adjust the clock rate of the rtc The existing code performs a soft reset during probe, which wipes out several registers including the offset register, which performs adjustments to the clock rate. The first several patches are cleanup, with patch 5 and 6 avoiding the reset, and patch 9 adding a nice sysfs interface to the clock offset. I know that this is not the only rtc to provide a programmable clock offset I wonder if this interface would make a good addition to the rtc api? The rtc chips I have seen list their clock adjustments in parts per million. I went with parts per billion, since the ppm listed was listed with a fractional component. Joshua Clayton (9): rtc-pcf2123: Document all registers and useful bits rtc-pcf2123: clean up reads from the chip rtc-pcf2123: clean up writes to the rtc chip rtc-pcf2123: replace magic numbers with defines rtc-pcf2123: put the chip reset into a function rtc-pcf2123: avoid resetting the clock if possible rtc-pcf2123: allow sysfs to accept hexidecimal rtc-pcf2123: use sysfs groups rtc-pcf2123: adjust the clock rate via sysfs drivers/rtc/rtc-pcf2123.c | 391 ++++++++++++++++++++++++++++++---------------- 1 file changed, 257 insertions(+), 134 deletions(-) -- 2.5.0 -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[toc] | [next] | [standalone]
| From | Joshua Clayton <stillcompiling@gmail.com> |
|---|---|
| Date | 2015-11-04 16:40 +0100 |
| Subject | [PATCH 2/9] rtc-pcf2123: clean up reads from the chip |
| Message-ID | <qr8kj-2go-57@gated-at.bofh.it> |
| In reply to | #1262377 |
put read operations into a function.
This makes the starting register more prominent and hides the delay.
Signed-off-by: Joshua Clayton <stillcompiling@gmail.com>
---
drivers/rtc/rtc-pcf2123.c | 39 ++++++++++++++++++++++-----------------
1 file changed, 22 insertions(+), 17 deletions(-)
diff --git a/drivers/rtc/rtc-pcf2123.c b/drivers/rtc/rtc-pcf2123.c
index 7756210..648cb74 100644
--- a/drivers/rtc/rtc-pcf2123.c
+++ b/drivers/rtc/rtc-pcf2123.c
@@ -104,12 +104,26 @@ static inline void pcf2123_delay_trec(void)
ndelay(30);
}
+static int pcf2123_read(struct device *dev, u8 reg, u8 *rxbuf, size_t size)
+{
+ struct spi_device *spi = to_spi_device(dev);
+ int ret;
+
+ if (reg > PCF2123_REG_MAX)
+ return -EFAULT;
+
+ reg |= PCF2123_READ;
+ ret = spi_write_then_read(spi, ®, 1, rxbuf, size);
+ pcf2123_delay_trec();
+
+ return ret;
+}
+
static ssize_t pcf2123_show(struct device *dev, struct device_attribute *attr,
char *buffer)
{
- struct spi_device *spi = to_spi_device(dev);
struct pcf2123_sysfs_reg *r;
- u8 txbuf[1], rxbuf[1];
+ u8 rxbuf[1];
unsigned long reg;
int ret;
@@ -119,11 +133,10 @@ static ssize_t pcf2123_show(struct device *dev, struct device_attribute *attr,
if (ret)
return ret;
- txbuf[0] = PCF2123_READ | reg;
- ret = spi_write_then_read(spi, txbuf, 1, rxbuf, 1);
+ ret = pcf2123_read(dev, reg, rxbuf, 1);
if (ret < 0)
return -EIO;
- pcf2123_delay_trec();
+
return sprintf(buffer, "0x%x\n", rxbuf[0]);
}
@@ -158,16 +171,12 @@ static ssize_t pcf2123_store(struct device *dev, struct device_attribute *attr,
static int pcf2123_rtc_read_time(struct device *dev, struct rtc_time *tm)
{
- struct spi_device *spi = to_spi_device(dev);
- u8 txbuf[1], rxbuf[7];
+ u8 rxbuf[7];
int ret;
- txbuf[0] = PCF2123_READ | PCF2123_REG_SC;
- ret = spi_write_then_read(spi, txbuf, sizeof(txbuf),
- rxbuf, sizeof(rxbuf));
+ ret = pcf2123_read(dev, PCF2123_REG_SC, rxbuf, sizeof(rxbuf));
if (ret < 0)
return ret;
- pcf2123_delay_trec();
tm->tm_sec = bcd2bin(rxbuf[0] & 0x7F);
tm->tm_min = bcd2bin(rxbuf[1] & 0x7F);
@@ -279,16 +288,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)
goto kfree_exit;
- pcf2123_delay_trec();
if (!(rxbuf[0] & 0x20)) {
dev_err(&spi->dev, "chip not found\n");
--
2.5.0
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/
[toc] | [prev] | [next] | [standalone]
| From | Joshua Clayton <stillcompiling@gmail.com> |
|---|---|
| Date | 2015-11-04 16:40 +0100 |
| Subject | [PATCH 5/9] rtc-pcf2123: put the chip reset into a function |
| Message-ID | <qr8kj-2go-65@gated-at.bofh.it> |
| In reply to | #1262377 |
Signed-off-by: Joshua Clayton <stillcompiling@gmail.com>
---
drivers/rtc/rtc-pcf2123.c | 64 ++++++++++++++++++++++++++---------------------
1 file changed, 36 insertions(+), 28 deletions(-)
diff --git a/drivers/rtc/rtc-pcf2123.c b/drivers/rtc/rtc-pcf2123.c
index 257ce7d..d3c1447 100644
--- a/drivers/rtc/rtc-pcf2123.c
+++ b/drivers/rtc/rtc-pcf2123.c
@@ -260,6 +260,40 @@ static int pcf2123_rtc_set_time(struct device *dev, struct rtc_time *tm)
return 0;
}
+static int pcf2123_reset(struct device *dev)
+{
+ int ret;
+ u8 rxbuf[2];
+
+ ret = pcf2123_write_reg(dev, PCF2123_REG_CTRL1, CTRL1_SW_RESET);
+ if (ret < 0)
+ return ret;
+
+ /* Stop the counter */
+ dev_dbg(dev, "stopping RTC\n");
+ ret = pcf2123_write_reg(dev, PCF2123_REG_CTRL1, CTRL1_STOP);
+ if (ret < 0)
+ return ret;
+
+ /* 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)
+ return ret;
+
+ 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)
+ return ret;
+
+ return 0;
+}
+
static const struct rtc_class_ops pcf2123_rtc_ops = {
.read_time = pcf2123_rtc_read_time,
.set_time = pcf2123_rtc_set_time,
@@ -269,7 +303,6 @@ static int pcf2123_probe(struct spi_device *spi)
{
struct rtc_device *rtc;
struct pcf2123_plat_data *pdata;
- u8 rxbuf[2];
int ret, i;
pdata = devm_kzalloc(&spi->dev, sizeof(struct pcf2123_plat_data),
@@ -278,29 +311,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)
- goto kfree_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)
- goto kfree_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)
- goto kfree_exit;
-
- if (!(rxbuf[0] & CTRL1_STOP)) {
+ ret = pcf2123_reset(&spi->dev);
+ if (ret < 0) {
dev_err(&spi->dev, "chip not found\n");
- ret = -ENODEV;
goto kfree_exit;
}
@@ -308,11 +321,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)
- goto kfree_exit;
-
/* Finalize the initialization */
rtc = devm_rtc_device_register(&spi->dev, pcf2123_driver.driver.name,
&pcf2123_rtc_ops, THIS_MODULE);
--
2.5.0
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/
[toc] | [prev] | [next] | [standalone]
| From | Joshua Clayton <stillcompiling@gmail.com> |
|---|---|
| Date | 2015-11-04 16:40 +0100 |
| Subject | [PATCH 7/9] rtc-pcf2123: allow sysfs to accept hexidecimal |
| Message-ID | <qr8kk-2go-67@gated-at.bofh.it> |
| In reply to | #1262377 |
pcf2123 registers store their values in bcd. sysfs sensibly displays them in hexidecimal. Up to now, the sysfs store functions only accept base 10, which makes no sense. Add support for hexidecimal without removing base10 support. Signed-off-by: Joshua Clayton <stillcompiling@gmail.com> --- drivers/rtc/rtc-pcf2123.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/rtc/rtc-pcf2123.c b/drivers/rtc/rtc-pcf2123.c index 4964d5c..6701e6d 100644 --- a/drivers/rtc/rtc-pcf2123.c +++ b/drivers/rtc/rtc-pcf2123.c @@ -178,7 +178,7 @@ static ssize_t pcf2123_store(struct device *dev, struct device_attribute *attr, if (ret) return ret; - ret = kstrtoul(buffer, 10, &val); + ret = kstrtoul(buffer, 0, &val); if (ret) return ret; -- 2.5.0 -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[toc] | [prev] | [next] | [standalone]
| From | Joshua Clayton <stillcompiling@gmail.com> |
|---|---|
| Date | 2015-11-04 16:40 +0100 |
| Subject | [PATCH 9/9] rtc-pcf2123: adjust the clock rate via sysfs |
| Message-ID | <qr8kk-2go-71@gated-at.bofh.it> |
| In reply to | #1262377 |
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.
The adjustment is calculated in parts per billion. The data sheet
uses parts per million (as do some others), but with 2 digits of
precision. Since floating point is forbidden, parts per billion is
a better fit.
Add a pair of sysfs files to seetand retrieve the offset in ppm.
Signed-off-by: Joshua Clayton <stillcompiling@gmail.com>
---
drivers/rtc/rtc-pcf2123.c | 68 +++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 68 insertions(+)
diff --git a/drivers/rtc/rtc-pcf2123.c b/drivers/rtc/rtc-pcf2123.c
index d494638..6d70860 100644
--- a/drivers/rtc/rtc-pcf2123.c
+++ b/drivers/rtc/rtc-pcf2123.c
@@ -77,11 +77,17 @@
/* PCF2123_REG_SC BITS */
#define OSC_HAS_STOPPED (0x80) /* Clock has been stopped */
+/* PCF2123_REG_OFFSET BITS */
+#define OFFSET_COARSE (0x80) /* Coarse Mode Offset */
+
/* READ/WRITE ADDRESS BITS */
#define PCF2123_SUBADDR (1 << 4)
#define PCF2123_WRITE ((0 << 7) | PCF2123_SUBADDR)
#define PCF2123_READ ((1 << 7) | PCF2123_SUBADDR)
+/* offset granularity in parts per billion in fine mode */
+#define OFFSET_STEP (2170)
+
static struct spi_driver pcf2123_driver;
/*
@@ -166,6 +172,65 @@ static ssize_t pcf2123_store(struct device *dev, struct device_attribute *attr,
return count;
}
+static ssize_t pcf2123_adjust_show(struct device *dev,
+ struct device_attribute *attr, char *buffer)
+{
+ ssize_t ret;
+ s8 reg;
+
+ ret = pcf2123_read(dev, PCF2123_REG_OFFSET, ®, 1);
+ if (ret < 0)
+ return -EIO;
+
+ if (reg & OFFSET_COARSE) {
+ reg <<= 1;
+ } else {
+ reg &= ~OFFSET_COARSE;
+ reg |= (reg & 0x40) << 1; /* sign extend */
+ }
+
+ return sprintf(buffer, "%ld\n", ((long)reg) * OFFSET_STEP);
+}
+
+static ssize_t pcf2123_adjust_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buffer, size_t count)
+{
+ ssize_t ret;
+ long val;
+ s8 reg;
+
+ ret = kstrtol(buffer, 10, &val);
+ if (ret)
+ return ret;
+
+ if (val > OFFSET_STEP * 127)
+ reg = 127;
+ else if (val < OFFSET_STEP * -128)
+ reg = -128;
+ else
+ reg = (s8)((val + (OFFSET_STEP >> 1)) / OFFSET_STEP);
+
+/*
+ * Each even value of the fine adjust overlaps with a value of the coarse
+ * adjustment, and since the coarse adjsutment will spread the adjustments
+ * over both hours, we use coarse for all even values, as well as values
+ * that are beyond the range of fine adjustment
+ */
+ if (reg <= 63 && reg >= -64 && reg & 1) {
+ reg &= ~OFFSET_COARSE;
+ } else {
+ reg >>= 1;
+ reg |= OFFSET_COARSE;
+ }
+
+ pcf2123_write_reg(dev, PCF2123_REG_OFFSET, reg);
+ if (ret < 0)
+ return -EIO;
+
+ return count;
+}
+
static int pcf2123_rtc_read_time(struct device *dev, struct rtc_time *tm)
{
u8 rxbuf[7];
@@ -320,6 +385,8 @@ static DEVICE_ATTR(c, S_IRUGO | S_IWUSR, pcf2123_show, pcf2123_store);
static DEVICE_ATTR(d, S_IRUGO | S_IWUSR, pcf2123_show, pcf2123_store);
static DEVICE_ATTR(e, S_IRUGO | S_IWUSR, pcf2123_show, pcf2123_store);
static DEVICE_ATTR(f, S_IRUGO | S_IWUSR, pcf2123_show, pcf2123_store);
+static DEVICE_ATTR(adjust, S_IRUGO | S_IWUSR, pcf2123_adjust_show,
+ pcf2123_adjust_store);
static struct attribute *pcf2123_attrs[] = {
&dev_attr_0.attr,
@@ -338,6 +405,7 @@ static struct attribute *pcf2123_attrs[] = {
&dev_attr_d.attr,
&dev_attr_e.attr,
&dev_attr_f.attr,
+ &dev_attr_adjust.attr,
NULL
};
--
2.5.0
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/
[toc] | [prev] | [standalone]
Back to top | Article view | linux.kernel
csiph-web