linux-rtc.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH v2 0/5] rtc: pcf2127: tamper timestamp and watchdog feature support
@ 2019-08-13 15:35 Bruno Thomsen
  2019-08-13 15:35 ` [PATCH v2 1/5] rtc: pcf2127: convert to devm_rtc_allocate_device Bruno Thomsen
                   ` (4 more replies)
  0 siblings, 5 replies; 9+ messages in thread
From: Bruno Thomsen @ 2019-08-13 15:35 UTC (permalink / raw)
  To: linux-rtc, linux-watchdog
  Cc: alexandre.belloni, a.zummo, wim, linux, u.kleine-koenig,
	sean.nyekjaer, bth, bruno.thomsen

Hi all

This patch series still adds support for 2 chip features; tamper timestamp
and watchdog. Including code cleanup which improves code readability of the
device driver and better aligned with kernel coding style. There is also a
bugfix of pcf2127_rtc_read_time() which causes accidental watchdog disabling,
which was not included in v1.

All review comments from v1 have been handled.
The series now adds watchdog feature before tamper as the later needs to call
pcf2127_wdt_active_ping() as workaround for CTRL2 watchdog issue.

I have also tested if reading the other watchdog control register called WD_CTL
results in disabling of the watchdog feature, but that is luckily not the case.

Test script[1] for tamper function can be used to test the feature and verify
that the pcb circuit is working without issues during EMC immunity tests.

 Starting tamper detection (dev: rtc0, irq: rtc-tamper-irq)!
 event: FALLING EDGE offset: 12 timestamp: [1565695589.907980206]
 Tamper! Tue Aug 13 11:26:31 UTC 2019 (1565695591)
 event: FALLING EDGE offset: 12 timestamp: [1565695595.759132013]
 Tamper! Tue Aug 13 11:26:36 UTC 2019 (1565695596)


Watchdog driver has been tested with systemd version 242 and the following
/etc/systemd/system.conf parameters:

 RuntimeWatchdogSec=30
 ShutdownWatchdogSec=4min


Bug in pcf2127_rtc_read_time() can be reproduced with the following code:

	unsigned char test[10];

	ret = regmap_read(pcf2127->regmap, PCF2127_REG_WD_VAL,
			  (unsigned int *)(test));
	dev_info(dev, "%s: before, wd_val=%02x\n",
		 __func__, test[0]);

 /* "regmap_read/regmap_bulk_read()" */

	ret = regmap_read(pcf2127->regmap, PCF2127_REG_WD_VAL,
			  (unsigned int *)(test));
	dev_info(dev, "%s: after, wd_val=%02x\n",
		 __func__, test[0]);

Which output something like this when using hwclock -r -f /dev/rtc0 in dmesg:

 [ 1407.334031] rtc-pcf2127-spi spi1.0: pcf2127_rtc_read_time: before, wd_val=12
 [ 1407.342521] rtc-pcf2127-spi spi1.0: pcf2127_rtc_read_time: after, wd_val=00
 [ 2104.383726] rtc-pcf2127-spi spi1.0: pcf2127_rtc_read_time: before, wd_val=17
 [ 2104.392212] rtc-pcf2127-spi spi1.0: pcf2127_rtc_read_time: after, wd_val=00
 [ 2800.393418] rtc-pcf2127-spi spi1.0: pcf2127_rtc_read_time: before, wd_val=14
 [ 2800.401950] rtc-pcf2127-spi spi1.0: pcf2127_rtc_read_time: after, wd_val=00

After bugfix patch:

 [  125.095718] rtc-pcf2127-spi spi1.0: pcf2127_rtc_read_time: before, wd_val=16
 [  125.104010] rtc-pcf2127-spi spi1.0: pcf2127_rtc_read_time: after, wd_val=16
 [  128.415844] rtc-pcf2127-spi spi1.0: pcf2127_rtc_read_time: before, wd_val=13
 [  128.424134] rtc-pcf2127-spi spi1.0: pcf2127_rtc_read_time: after, wd_val=13


I also have a battery switch-over mode patch, but I will send it later as
it might need configuration based on hardware design.

/Bruno

[1] https://github.com/baxeno/linux-emc-test/blob/master/tamper/tamper.sh

Bruno Thomsen (5):
  rtc: pcf2127: convert to devm_rtc_allocate_device
  rtc: pcf2127: cleanup register and bit defines
  rtc: pcf2127: bugfix: read rtc disables watchdog
  rtc: pcf2127: add watchdog feature support
  rtc: pcf2127: add tamper detection support

 drivers/rtc/Kconfig       |   7 +-
 drivers/rtc/rtc-pcf2127.c | 387 +++++++++++++++++++++++++++++++++-----
 2 files changed, 343 insertions(+), 51 deletions(-)

-- 
2.21.0


^ permalink raw reply	[flat|nested] 9+ messages in thread

* [PATCH v2 1/5] rtc: pcf2127: convert to devm_rtc_allocate_device
  2019-08-13 15:35 [PATCH v2 0/5] rtc: pcf2127: tamper timestamp and watchdog feature support Bruno Thomsen
@ 2019-08-13 15:35 ` Bruno Thomsen
  2019-08-13 15:35 ` [PATCH v2 2/5] rtc: pcf2127: cleanup register and bit defines Bruno Thomsen
                   ` (3 subsequent siblings)
  4 siblings, 0 replies; 9+ messages in thread
From: Bruno Thomsen @ 2019-08-13 15:35 UTC (permalink / raw)
  To: linux-rtc, linux-watchdog
  Cc: alexandre.belloni, a.zummo, wim, linux, u.kleine-koenig,
	sean.nyekjaer, bth, bruno.thomsen

This allows further improvement of the driver.

Signed-off-by: Bruno Thomsen <bruno.thomsen@gmail.com>
---
 drivers/rtc/rtc-pcf2127.c | 7 ++++---
 1 file changed, 4 insertions(+), 3 deletions(-)

diff --git a/drivers/rtc/rtc-pcf2127.c b/drivers/rtc/rtc-pcf2127.c
index 8632f58fed43..58eb96506e4b 100644
--- a/drivers/rtc/rtc-pcf2127.c
+++ b/drivers/rtc/rtc-pcf2127.c
@@ -237,11 +237,12 @@ static int pcf2127_probe(struct device *dev, struct regmap *regmap,
 
 	dev_set_drvdata(dev, pcf2127);
 
-	pcf2127->rtc = devm_rtc_device_register(dev, name, &pcf2127_rtc_ops,
-						THIS_MODULE);
+	pcf2127->rtc = devm_rtc_allocate_device(dev);
 	if (IS_ERR(pcf2127->rtc))
 		return PTR_ERR(pcf2127->rtc);
 
+	pcf2127->rtc->ops = &pcf2127_rtc_ops;
+
 	if (has_nvmem) {
 		struct nvmem_config nvmem_cfg = {
 			.priv = pcf2127,
@@ -253,7 +254,7 @@ static int pcf2127_probe(struct device *dev, struct regmap *regmap,
 		ret = rtc_nvmem_register(pcf2127->rtc, &nvmem_cfg);
 	}
 
-	return ret;
+	return rtc_register_device(pcf2127->rtc);
 }
 
 #ifdef CONFIG_OF
-- 
2.21.0


^ permalink raw reply related	[flat|nested] 9+ messages in thread

* [PATCH v2 2/5] rtc: pcf2127: cleanup register and bit defines
  2019-08-13 15:35 [PATCH v2 0/5] rtc: pcf2127: tamper timestamp and watchdog feature support Bruno Thomsen
  2019-08-13 15:35 ` [PATCH v2 1/5] rtc: pcf2127: convert to devm_rtc_allocate_device Bruno Thomsen
@ 2019-08-13 15:35 ` Bruno Thomsen
  2019-08-13 15:35 ` [PATCH v2 3/5] rtc: pcf2127: bugfix: read rtc disables watchdog Bruno Thomsen
                   ` (2 subsequent siblings)
  4 siblings, 0 replies; 9+ messages in thread
From: Bruno Thomsen @ 2019-08-13 15:35 UTC (permalink / raw)
  To: linux-rtc, linux-watchdog
  Cc: alexandre.belloni, a.zummo, wim, linux, u.kleine-koenig,
	sean.nyekjaer, bth, bruno.thomsen

Cleanup of defines to follow kernel coding style and increase code
readability by using same register and bit define style.

Change PCF2127_REG_RAM_{addr_MSB,wrt_cmd,rd_cmd} to upper case as
kernel coding guide section 12 'Macros, Enums and RTL' states
"Names of macros defining constants and labels in enums are capitalized".

Improve readability of RAM register comment by making whole sentences.

Remove parentheses from register defines as they are only used
for expressions and not constants.

As there are no clear style for name of registers and bits in the
kernel drivers, I suggest the following for at least this driver,
but hopefully also other RTC drivers.

Register name should follow this convention:
[chip]_REG_[reg name] 0xXX

Bit name should follow this convention, so it clearly states which
chip register it's part of:
[chip]_BIT_[reg name]_[bit name] BIT(X)

Additionally I suggest bit defines are always placed right below
its corresponding register define and using an extra tab indentation
for the BIT(X) part. This will visualt make it easy to see that bit
defines are part of the complete register definition.

Rename PCF2127_OSF to PCF2127_BIT_SC_OSF and move it right below
PCF2127_REG_SC. This will improve readability of bit checks as it's
easy to verify that it uses the correct register.

Move end of line comments above register defines as it's more like
a heading for 1 register define and up to 8 bit defines or a
collection of registers that are close related like timestamp
split across 6 registers.

Signed-off-by: Bruno Thomsen <bruno.thomsen@gmail.com>
---
 drivers/rtc/rtc-pcf2127.c | 59 ++++++++++++++++++++++-----------------
 1 file changed, 33 insertions(+), 26 deletions(-)

diff --git a/drivers/rtc/rtc-pcf2127.c b/drivers/rtc/rtc-pcf2127.c
index 58eb96506e4b..cd8def79b379 100644
--- a/drivers/rtc/rtc-pcf2127.c
+++ b/drivers/rtc/rtc-pcf2127.c
@@ -19,26 +19,32 @@
 #include <linux/of.h>
 #include <linux/regmap.h>
 
-#define PCF2127_REG_CTRL1       (0x00)  /* Control Register 1 */
-#define PCF2127_REG_CTRL2       (0x01)  /* Control Register 2 */
-
-#define PCF2127_REG_CTRL3       (0x02)  /* Control Register 3 */
-#define PCF2127_REG_CTRL3_BLF		BIT(2)
-
-#define PCF2127_REG_SC          (0x03)  /* datetime */
-#define PCF2127_REG_MN          (0x04)
-#define PCF2127_REG_HR          (0x05)
-#define PCF2127_REG_DM          (0x06)
-#define PCF2127_REG_DW          (0x07)
-#define PCF2127_REG_MO          (0x08)
-#define PCF2127_REG_YR          (0x09)
-
-/* the pcf2127 has 512 bytes nvmem, pcf2129 doesn't */
-#define PCF2127_REG_RAM_addr_MSB       0x1a
-#define PCF2127_REG_RAM_wrt_cmd        0x1c
-#define PCF2127_REG_RAM_rd_cmd         0x1d
+/* Control register 1 */
+#define PCF2127_REG_CTRL1		0x00
+/* Control register 2 */
+#define PCF2127_REG_CTRL2		0x01
+/* Control register 3 */
+#define PCF2127_REG_CTRL3		0x02
+#define PCF2127_BIT_CTRL3_BLF			BIT(2)
+/* Time and date registers */
+#define PCF2127_REG_SC			0x03
+#define PCF2127_BIT_SC_OSF			BIT(7)
+#define PCF2127_REG_MN			0x04
+#define PCF2127_REG_HR			0x05
+#define PCF2127_REG_DM			0x06
+#define PCF2127_REG_DW			0x07
+#define PCF2127_REG_MO			0x08
+#define PCF2127_REG_YR			0x09
+/*
+ * RAM registers
+ * PCF2127 has 512 bytes general-purpose static RAM (SRAM) that is
+ * battery backed and can survive a power outage.
+ * PCF2129 doesn't have this feature.
+ */
+#define PCF2127_REG_RAM_ADDR_MSB	0x1A
+#define PCF2127_REG_RAM_WRT_CMD		0x1C
+#define PCF2127_REG_RAM_RD_CMD		0x1D
 
-#define PCF2127_OSF             BIT(7)  /* Oscillator Fail flag */
 
 struct pcf2127 {
 	struct rtc_device *rtc;
@@ -73,11 +79,12 @@ static int pcf2127_rtc_read_time(struct device *dev, struct rtc_time *tm)
 		return ret;
 	}
 
-	if (buf[PCF2127_REG_CTRL3] & PCF2127_REG_CTRL3_BLF)
+	if (buf[PCF2127_REG_CTRL3] & PCF2127_BIT_CTRL3_BLF)
 		dev_info(dev,
 			"low voltage detected, check/replace RTC battery.\n");
 
-	if (buf[PCF2127_REG_SC] & PCF2127_OSF) {
+	/* Clock integrity is not guaranteed when OSF flag is set. */
+	if (buf[PCF2127_REG_SC] & PCF2127_BIT_SC_OSF) {
 		/*
 		 * no need clear the flag here,
 		 * it will be cleared once the new date is saved
@@ -166,7 +173,7 @@ static int pcf2127_rtc_ioctl(struct device *dev,
 		if (ret)
 			return ret;
 
-		touser = touser & PCF2127_REG_CTRL3_BLF ? 1 : 0;
+		touser = touser & PCF2127_BIT_CTRL3_BLF ? 1 : 0;
 
 		if (copy_to_user((void __user *)arg, &touser, sizeof(int)))
 			return -EFAULT;
@@ -192,12 +199,12 @@ static int pcf2127_nvmem_read(void *priv, unsigned int offset,
 	int ret;
 	unsigned char offsetbuf[] = { offset >> 8, offset };
 
-	ret = regmap_bulk_write(pcf2127->regmap, PCF2127_REG_RAM_addr_MSB,
+	ret = regmap_bulk_write(pcf2127->regmap, PCF2127_REG_RAM_ADDR_MSB,
 				offsetbuf, 2);
 	if (ret)
 		return ret;
 
-	ret = regmap_bulk_read(pcf2127->regmap, PCF2127_REG_RAM_rd_cmd,
+	ret = regmap_bulk_read(pcf2127->regmap, PCF2127_REG_RAM_RD_CMD,
 			       val, bytes);
 
 	return ret ?: bytes;
@@ -210,12 +217,12 @@ static int pcf2127_nvmem_write(void *priv, unsigned int offset,
 	int ret;
 	unsigned char offsetbuf[] = { offset >> 8, offset };
 
-	ret = regmap_bulk_write(pcf2127->regmap, PCF2127_REG_RAM_addr_MSB,
+	ret = regmap_bulk_write(pcf2127->regmap, PCF2127_REG_RAM_ADDR_MSB,
 				offsetbuf, 2);
 	if (ret)
 		return ret;
 
-	ret = regmap_bulk_write(pcf2127->regmap, PCF2127_REG_RAM_wrt_cmd,
+	ret = regmap_bulk_write(pcf2127->regmap, PCF2127_REG_RAM_WRT_CMD,
 				val, bytes);
 
 	return ret ?: bytes;
-- 
2.21.0


^ permalink raw reply related	[flat|nested] 9+ messages in thread

* [PATCH v2 3/5] rtc: pcf2127: bugfix: read rtc disables watchdog
  2019-08-13 15:35 [PATCH v2 0/5] rtc: pcf2127: tamper timestamp and watchdog feature support Bruno Thomsen
  2019-08-13 15:35 ` [PATCH v2 1/5] rtc: pcf2127: convert to devm_rtc_allocate_device Bruno Thomsen
  2019-08-13 15:35 ` [PATCH v2 2/5] rtc: pcf2127: cleanup register and bit defines Bruno Thomsen
@ 2019-08-13 15:35 ` Bruno Thomsen
  2019-08-13 15:35 ` [PATCH v2 4/5] rtc: pcf2127: add watchdog feature support Bruno Thomsen
  2019-08-13 15:36 ` [PATCH v2 5/5] rtc: pcf2127: add tamper detection support Bruno Thomsen
  4 siblings, 0 replies; 9+ messages in thread
From: Bruno Thomsen @ 2019-08-13 15:35 UTC (permalink / raw)
  To: linux-rtc, linux-watchdog
  Cc: alexandre.belloni, a.zummo, wim, linux, u.kleine-koenig,
	sean.nyekjaer, bth, bruno.thomsen

The previous fix listed bulk read of registers as root cause of
accendential disabling of watchdog, since the watchdog counter
register (WD_VAL) was zeroed.

Fixes: 3769a375ab83 rtc: pcf2127: bulk read only date and time registers.

Tested with the same PCF2127 chip as Sean reveled root cause
of WD_VAL register value zeroing was caused by reading CTRL2
register which is one of the watchdog feature control registers.

So the solution is to not read the first two control registers
(CTRL1 and CTRL2) in pcf2127_rtc_read_time as they are not
needed anyway. Size of local buf variable is kept to allow
easy usage of register defines to improve readability of code.

Debug trace line was updated after CTRL1 and CTRL2 are no longer
read from the chip. Also replaced magic numbers in buf access
with register defines.

Signed-off-by: Bruno Thomsen <bruno.thomsen@gmail.com>
---
 drivers/rtc/rtc-pcf2127.c | 32 ++++++++++++--------------------
 1 file changed, 12 insertions(+), 20 deletions(-)

diff --git a/drivers/rtc/rtc-pcf2127.c b/drivers/rtc/rtc-pcf2127.c
index cd8def79b379..ee4921e4a47c 100644
--- a/drivers/rtc/rtc-pcf2127.c
+++ b/drivers/rtc/rtc-pcf2127.c
@@ -60,20 +60,14 @@ static int pcf2127_rtc_read_time(struct device *dev, struct rtc_time *tm)
 	struct pcf2127 *pcf2127 = dev_get_drvdata(dev);
 	unsigned char buf[10];
 	int ret;
-	int i;
 
-	for (i = 0; i <= PCF2127_REG_CTRL3; i++) {
-		ret = regmap_read(pcf2127->regmap, PCF2127_REG_CTRL1 + i,
-				  (unsigned int *)(buf + i));
-		if (ret) {
-			dev_err(dev, "%s: read error\n", __func__);
-			return ret;
-		}
-	}
-
-	ret = regmap_bulk_read(pcf2127->regmap, PCF2127_REG_SC,
-			       (buf + PCF2127_REG_SC),
-			       ARRAY_SIZE(buf) - PCF2127_REG_SC);
+	/*
+	 * Avoid reading CTRL2 register as it causes WD_VAL register
+	 * value to reset to 0 which means watchdog is stopped.
+	 */
+	ret = regmap_bulk_read(pcf2127->regmap, PCF2127_REG_CTRL3,
+			       (buf + PCF2127_REG_CTRL3),
+			       ARRAY_SIZE(buf) - PCF2127_REG_CTRL3);
 	if (ret) {
 		dev_err(dev, "%s: read error\n", __func__);
 		return ret;
@@ -95,14 +89,12 @@ static int pcf2127_rtc_read_time(struct device *dev, struct rtc_time *tm)
 	}
 
 	dev_dbg(dev,
-		"%s: raw data is cr1=%02x, cr2=%02x, cr3=%02x, "
-		"sec=%02x, min=%02x, hr=%02x, "
+		"%s: raw data is cr3=%02x, sec=%02x, min=%02x, hr=%02x, "
 		"mday=%02x, wday=%02x, mon=%02x, year=%02x\n",
-		__func__,
-		buf[0], buf[1], buf[2],
-		buf[3], buf[4], buf[5],
-		buf[6], buf[7], buf[8], buf[9]);
-
+		__func__, buf[PCF2127_REG_CTRL3], buf[PCF2127_REG_SC],
+		buf[PCF2127_REG_MN], buf[PCF2127_REG_HR],
+		buf[PCF2127_REG_DM], buf[PCF2127_REG_DW],
+		buf[PCF2127_REG_MO], buf[PCF2127_REG_YR]);
 
 	tm->tm_sec = bcd2bin(buf[PCF2127_REG_SC] & 0x7F);
 	tm->tm_min = bcd2bin(buf[PCF2127_REG_MN] & 0x7F);
-- 
2.21.0


^ permalink raw reply related	[flat|nested] 9+ messages in thread

* [PATCH v2 4/5] rtc: pcf2127: add watchdog feature support
  2019-08-13 15:35 [PATCH v2 0/5] rtc: pcf2127: tamper timestamp and watchdog feature support Bruno Thomsen
                   ` (2 preceding siblings ...)
  2019-08-13 15:35 ` [PATCH v2 3/5] rtc: pcf2127: bugfix: read rtc disables watchdog Bruno Thomsen
@ 2019-08-13 15:35 ` Bruno Thomsen
  2019-08-13 16:19   ` Guenter Roeck
  2019-08-13 15:36 ` [PATCH v2 5/5] rtc: pcf2127: add tamper detection support Bruno Thomsen
  4 siblings, 1 reply; 9+ messages in thread
From: Bruno Thomsen @ 2019-08-13 15:35 UTC (permalink / raw)
  To: linux-rtc, linux-watchdog
  Cc: alexandre.belloni, a.zummo, wim, linux, u.kleine-koenig,
	sean.nyekjaer, bth, bruno.thomsen

Add partial support for the watchdog functionality of
both PCF2127 and PCF2129 chips.

The programmable watchdog timer is currently using a fixed
clock source of 1Hz. This result in a selectable range of
1-255 seconds, which covers most embedded Linux use-cases.

Clock sources of 4096Hz, 64Hz and 1/60Hz is mostly useful
in MCU use-cases.

Countdown timer not available when using watchdog feature.

Signed-off-by: Bruno Thomsen <bruno.thomsen@gmail.com>
---
 drivers/rtc/Kconfig       |   7 ++-
 drivers/rtc/rtc-pcf2127.c | 127 ++++++++++++++++++++++++++++++++++++++
 2 files changed, 133 insertions(+), 1 deletion(-)

diff --git a/drivers/rtc/Kconfig b/drivers/rtc/Kconfig
index e72f65b61176..a3bb58a08879 100644
--- a/drivers/rtc/Kconfig
+++ b/drivers/rtc/Kconfig
@@ -876,7 +876,12 @@ config RTC_DRV_PCF2127
 	depends on RTC_I2C_AND_SPI
 	help
 	  If you say yes here you get support for the NXP PCF2127/29 RTC
-	  chips.
+	  chips with integrated quartz crystal for industrial applications.
+	  Both chips also have watchdog timer and tamper switch detection
+	  features.
+
+	  PCF2127 has an additional feature of 512 bytes battery backed
+	  memory that's accessible using nvmem interface.
 
 	  This driver can also be built as a module. If so, the module
 	  will be called rtc-pcf2127.
diff --git a/drivers/rtc/rtc-pcf2127.c b/drivers/rtc/rtc-pcf2127.c
index ee4921e4a47c..700db7dd3eef 100644
--- a/drivers/rtc/rtc-pcf2127.c
+++ b/drivers/rtc/rtc-pcf2127.c
@@ -5,6 +5,9 @@
  *
  * Author: Renaud Cerrato <r.cerrato@til-technologies.fr>
  *
+ * Watchdog and tamper functions
+ * Author: Bruno Thomsen <bruno.thomsen@gmail.com>
+ *
  * based on the other drivers in this same directory.
  *
  * Datasheet: http://cache.nxp.com/documents/data_sheet/PCF2127.pdf
@@ -18,6 +21,7 @@
 #include <linux/module.h>
 #include <linux/of.h>
 #include <linux/regmap.h>
+#include <linux/watchdog.h>
 
 /* Control register 1 */
 #define PCF2127_REG_CTRL1		0x00
@@ -35,6 +39,13 @@
 #define PCF2127_REG_DW			0x07
 #define PCF2127_REG_MO			0x08
 #define PCF2127_REG_YR			0x09
+/* Watchdog registers */
+#define PCF2127_REG_WD_CTL		0x10
+#define PCF2127_BIT_WD_CTL_TF0			BIT(0)
+#define PCF2127_BIT_WD_CTL_TF1			BIT(1)
+#define PCF2127_BIT_WD_CTL_CD0			BIT(6)
+#define PCF2127_BIT_WD_CTL_CD1			BIT(7)
+#define PCF2127_REG_WD_VAL		0x11
 /*
  * RAM registers
  * PCF2127 has 512 bytes general-purpose static RAM (SRAM) that is
@@ -45,9 +56,15 @@
 #define PCF2127_REG_RAM_WRT_CMD		0x1C
 #define PCF2127_REG_RAM_RD_CMD		0x1D
 
+/* Watchdog timer value constants */
+#define PCF2127_WD_VAL_STOP		0
+#define PCF2127_WD_VAL_MIN		2
+#define PCF2127_WD_VAL_MAX		255
+#define PCF2127_WD_VAL_DEFAULT		60
 
 struct pcf2127 {
 	struct rtc_device *rtc;
+	struct watchdog_device wdd;
 	struct regmap *regmap;
 };
 
@@ -220,6 +237,81 @@ static int pcf2127_nvmem_write(void *priv, unsigned int offset,
 	return ret ?: bytes;
 }
 
+/* watchdog driver */
+
+static int pcf2127_wdt_ping(struct watchdog_device *wdd)
+{
+	struct pcf2127 *pcf2127 = watchdog_get_drvdata(wdd);
+
+	return regmap_write(pcf2127->regmap, PCF2127_REG_WD_VAL, wdd->timeout);
+}
+
+/*
+ * Restart watchdog timer if feature is active.
+ *
+ * Note: Reading CTRL2 register causes watchdog to stop which is unfortunate,
+ * since register also contain control/status flags for other features.
+ * Always call this function after reading CTRL2 register.
+ */
+static int pcf2127_wdt_active_ping(struct watchdog_device *wdd)
+{
+	int ret = 0;
+
+	if (watchdog_active(wdd)) {
+		ret = pcf2127_wdt_ping(wdd);
+		if (ret)
+			dev_err(wdd->parent,
+				"%s: watchdog restart failed, ret=%d\n",
+				__func__, ret);
+	}
+
+	return ret;
+}
+
+static int pcf2127_wdt_start(struct watchdog_device *wdd)
+{
+	dev_info(wdd->parent, "watchdog enabled\n");
+
+	return pcf2127_wdt_ping(wdd);
+}
+
+static int pcf2127_wdt_stop(struct watchdog_device *wdd)
+{
+	struct pcf2127 *pcf2127 = watchdog_get_drvdata(wdd);
+
+	dev_info(wdd->parent, "watchdog disabled\n");
+
+	return regmap_write(pcf2127->regmap, PCF2127_REG_WD_VAL,
+			    PCF2127_WD_VAL_STOP);
+}
+
+static int pcf2127_wdt_set_timeout(struct watchdog_device *wdd,
+				   unsigned int new_timeout)
+{
+	int ret = 0;
+
+	dev_info(wdd->parent, "new watchdog timeout: %is (old: %is)\n",
+		new_timeout, wdd->timeout);
+
+	wdd->timeout = new_timeout;
+	ret = pcf2127_wdt_active_ping(wdd);
+
+	return ret;
+}
+
+static const struct watchdog_info pcf2127_wdt_info = {
+	.identity = "NXP PCF2127/PCF2129 Watchdog",
+	.options = WDIOF_KEEPALIVEPING | WDIOF_SETTIMEOUT,
+};
+
+static const struct watchdog_ops pcf2127_watchdog_ops = {
+	.owner = THIS_MODULE,
+	.start = pcf2127_wdt_start,
+	.stop = pcf2127_wdt_stop,
+	.ping = pcf2127_wdt_ping,
+	.set_timeout = pcf2127_wdt_set_timeout,
+};
+
 static int pcf2127_probe(struct device *dev, struct regmap *regmap,
 			const char *name, bool has_nvmem)
 {
@@ -242,6 +334,16 @@ static int pcf2127_probe(struct device *dev, struct regmap *regmap,
 
 	pcf2127->rtc->ops = &pcf2127_rtc_ops;
 
+	pcf2127->wdd.parent = dev;
+	pcf2127->wdd.info = &pcf2127_wdt_info;
+	pcf2127->wdd.ops = &pcf2127_watchdog_ops;
+	pcf2127->wdd.min_timeout = PCF2127_WD_VAL_MIN;
+	pcf2127->wdd.max_timeout = PCF2127_WD_VAL_MAX;
+	pcf2127->wdd.timeout = PCF2127_WD_VAL_DEFAULT;
+	pcf2127->wdd.min_hw_heartbeat_ms = 500;
+
+	watchdog_set_drvdata(&pcf2127->wdd, pcf2127);
+
 	if (has_nvmem) {
 		struct nvmem_config nvmem_cfg = {
 			.priv = pcf2127,
@@ -253,6 +355,31 @@ static int pcf2127_probe(struct device *dev, struct regmap *regmap,
 		ret = rtc_nvmem_register(pcf2127->rtc, &nvmem_cfg);
 	}
 
+	/*
+	 * Watchdog timer enabled and reset pin /RST activated when timed out.
+	 * Select 1Hz clock source for watchdog timer.
+	 * Timer is not started until WD_VAL is loaded with a valid value.
+	 * Note: Countdown timer disabled and not available.
+	 */
+	ret = regmap_update_bits(pcf2127->regmap, PCF2127_REG_WD_CTL,
+				 PCF2127_BIT_WD_CTL_CD1 |
+				 PCF2127_BIT_WD_CTL_CD0 |
+				 PCF2127_BIT_WD_CTL_TF1 |
+				 PCF2127_BIT_WD_CTL_TF0,
+				 PCF2127_BIT_WD_CTL_CD1 |
+				 PCF2127_BIT_WD_CTL_CD0 |
+				 PCF2127_BIT_WD_CTL_TF1);
+	if (ret) {
+		dev_err(dev, "%s: watchdog config (wd_ctl) failed\n", __func__);
+		return ret;
+	}
+
+	ret = devm_watchdog_register_device(dev, &pcf2127->wdd);
+	if (ret) {
+		dev_err(dev, "%s: watchdog registering failed\n", __func__);
+		return ret;
+	}
+
 	return rtc_register_device(pcf2127->rtc);
 }
 
-- 
2.21.0


^ permalink raw reply related	[flat|nested] 9+ messages in thread

* [PATCH v2 5/5] rtc: pcf2127: add tamper detection support
  2019-08-13 15:35 [PATCH v2 0/5] rtc: pcf2127: tamper timestamp and watchdog feature support Bruno Thomsen
                   ` (3 preceding siblings ...)
  2019-08-13 15:35 ` [PATCH v2 4/5] rtc: pcf2127: add watchdog feature support Bruno Thomsen
@ 2019-08-13 15:36 ` Bruno Thomsen
  4 siblings, 0 replies; 9+ messages in thread
From: Bruno Thomsen @ 2019-08-13 15:36 UTC (permalink / raw)
  To: linux-rtc, linux-watchdog
  Cc: alexandre.belloni, a.zummo, wim, linux, u.kleine-koenig,
	sean.nyekjaer, bth, bruno.thomsen

Add support for integrated tamper detection function in both PCF2127 and
PCF2129 chips. This patch implements the feature by adding an additional
timestamp0 file to sysfs device path. This file contains seconds since
epoch, if an event occurred, or is empty, if none occurred.
Interface should match ISL1208 and RV3028 RTC drivers.

Signed-off-by: Bruno Thomsen <bruno.thomsen@gmail.com>
---
 drivers/rtc/rtc-pcf2127.c | 160 ++++++++++++++++++++++++++++++++++++++
 1 file changed, 160 insertions(+)

diff --git a/drivers/rtc/rtc-pcf2127.c b/drivers/rtc/rtc-pcf2127.c
index 700db7dd3eef..9a5c042cf267 100644
--- a/drivers/rtc/rtc-pcf2127.c
+++ b/drivers/rtc/rtc-pcf2127.c
@@ -25,11 +25,18 @@
 
 /* Control register 1 */
 #define PCF2127_REG_CTRL1		0x00
+#define PCF2127_BIT_CTRL1_TSF1			BIT(4)
 /* Control register 2 */
 #define PCF2127_REG_CTRL2		0x01
+#define PCF2127_BIT_CTRL2_TSIE			BIT(2)
+#define PCF2127_BIT_CTRL2_TSF2			BIT(5)
 /* Control register 3 */
 #define PCF2127_REG_CTRL3		0x02
+#define PCF2127_BIT_CTRL3_BLIE			BIT(0)
+#define PCF2127_BIT_CTRL3_BIE			BIT(1)
 #define PCF2127_BIT_CTRL3_BLF			BIT(2)
+#define PCF2127_BIT_CTRL3_BF			BIT(3)
+#define PCF2127_BIT_CTRL3_BTSE			BIT(4)
 /* Time and date registers */
 #define PCF2127_REG_SC			0x03
 #define PCF2127_BIT_SC_OSF			BIT(7)
@@ -46,6 +53,16 @@
 #define PCF2127_BIT_WD_CTL_CD0			BIT(6)
 #define PCF2127_BIT_WD_CTL_CD1			BIT(7)
 #define PCF2127_REG_WD_VAL		0x11
+/* Tamper timestamp registers */
+#define PCF2127_REG_TS_CTRL		0x12
+#define PCF2127_BIT_TS_CTRL_TSOFF		BIT(6)
+#define PCF2127_BIT_TS_CTRL_TSM			BIT(7)
+#define PCF2127_REG_TS_SC		0x13
+#define PCF2127_REG_TS_MN		0x14
+#define PCF2127_REG_TS_HR		0x15
+#define PCF2127_REG_TS_DM		0x16
+#define PCF2127_REG_TS_MO		0x17
+#define PCF2127_REG_TS_YR		0x18
 /*
  * RAM registers
  * PCF2127 has 512 bytes general-purpose static RAM (SRAM) that is
@@ -312,6 +329,97 @@ static const struct watchdog_ops pcf2127_watchdog_ops = {
 	.set_timeout = pcf2127_wdt_set_timeout,
 };
 
+/* sysfs interface */
+
+static ssize_t timestamp0_store(struct device *dev,
+				struct device_attribute *attr,
+				const char *buf, size_t count)
+{
+	struct pcf2127 *pcf2127 = dev_get_drvdata(dev->parent);
+	int ret;
+
+	ret = regmap_update_bits(pcf2127->regmap, PCF2127_REG_CTRL1,
+				 PCF2127_BIT_CTRL1_TSF1, 0);
+	if (ret) {
+		dev_err(dev, "%s: update ctrl1 ret=%d\n", __func__, ret);
+		return ret;
+	}
+
+	ret = regmap_update_bits(pcf2127->regmap, PCF2127_REG_CTRL2,
+				 PCF2127_BIT_CTRL2_TSF2, 0);
+	if (ret) {
+		dev_err(dev, "%s: update ctrl2 ret=%d\n", __func__, ret);
+		return ret;
+	}
+
+	ret = pcf2127_wdt_active_ping(&pcf2127->wdd);
+	if (ret)
+		return ret;
+
+	return count;
+};
+
+static ssize_t timestamp0_show(struct device *dev,
+			       struct device_attribute *attr, char *buf)
+{
+	struct pcf2127 *pcf2127 = dev_get_drvdata(dev->parent);
+	struct rtc_time tm;
+	int ret;
+	unsigned char data[25];
+
+	ret = regmap_bulk_read(pcf2127->regmap, PCF2127_REG_CTRL1, data,
+			       sizeof(data));
+	if (ret) {
+		dev_err(dev, "%s: read error ret=%d\n", __func__, ret);
+		return ret;
+	}
+
+	dev_dbg(dev,
+		"%s: raw data is cr1=%02x, cr2=%02x, cr3=%02x, ts_sc=%02x, "
+		"ts_mn=%02x, ts_hr=%02x, ts_dm=%02x, ts_mo=%02x, ts_yr=%02x\n",
+		__func__, data[PCF2127_REG_CTRL1], data[PCF2127_REG_CTRL2],
+		data[PCF2127_REG_CTRL3], data[PCF2127_REG_TS_SC],
+		data[PCF2127_REG_TS_MN], data[PCF2127_REG_TS_HR],
+		data[PCF2127_REG_TS_DM], data[PCF2127_REG_TS_MO],
+		data[PCF2127_REG_TS_YR]);
+
+	ret = pcf2127_wdt_active_ping(&pcf2127->wdd);
+	if (ret)
+		return ret;
+
+	if (!(data[PCF2127_REG_CTRL1] & PCF2127_BIT_CTRL1_TSF1) &&
+	    !(data[PCF2127_REG_CTRL2] & PCF2127_BIT_CTRL2_TSF2))
+		return 0;
+
+	tm.tm_sec = bcd2bin(data[PCF2127_REG_TS_SC] & 0x7F);
+	tm.tm_min = bcd2bin(data[PCF2127_REG_TS_MN] & 0x7F);
+	tm.tm_hour = bcd2bin(data[PCF2127_REG_TS_HR] & 0x3F);
+	tm.tm_mday = bcd2bin(data[PCF2127_REG_TS_DM] & 0x3F);
+	/* TS_MO register (month) value range: 1-12 */
+	tm.tm_mon = bcd2bin(data[PCF2127_REG_TS_MO] & 0x1F) - 1;
+	tm.tm_year = bcd2bin(data[PCF2127_REG_TS_YR]);
+	if (tm.tm_year < 70)
+		tm.tm_year += 100; /* assume we are in 1970...2069 */
+
+	ret = rtc_valid_tm(&tm);
+	if (ret)
+		return ret;
+
+	return sprintf(buf, "%llu\n",
+		       (unsigned long long)rtc_tm_to_time64(&tm));
+};
+
+static DEVICE_ATTR_RW(timestamp0);
+
+static struct attribute *pcf2127_attrs[] = {
+	&dev_attr_timestamp0.attr,
+	NULL
+};
+
+static const struct attribute_group pcf2127_attr_group = {
+	.attrs	= pcf2127_attrs,
+};
+
 static int pcf2127_probe(struct device *dev, struct regmap *regmap,
 			const char *name, bool has_nvmem)
 {
@@ -380,6 +488,58 @@ static int pcf2127_probe(struct device *dev, struct regmap *regmap,
 		return ret;
 	}
 
+	/*
+	 * Disable battery low/switch-over timestamp and interrupts.
+	 * Clear battery interrupt flags which can block new trigger events.
+	 * Note: This is the default chip behaviour but added to ensure
+	 * correct tamper timestamp and interrupt function.
+	 */
+	ret = regmap_update_bits(pcf2127->regmap, PCF2127_REG_CTRL3,
+				 PCF2127_BIT_CTRL3_BTSE |
+				 PCF2127_BIT_CTRL3_BF |
+				 PCF2127_BIT_CTRL3_BIE |
+				 PCF2127_BIT_CTRL3_BLIE, 0);
+	if (ret) {
+		dev_err(dev, "%s: interrupt config (ctrl3) failed\n",
+			__func__);
+		return ret;
+	}
+
+	/*
+	 * Enable timestamp function and store timestamp of first trigger
+	 * event until TSF1 and TFS2 interrupt flags are cleared.
+	 */
+	ret = regmap_update_bits(pcf2127->regmap, PCF2127_REG_TS_CTRL,
+				 PCF2127_BIT_TS_CTRL_TSOFF |
+				 PCF2127_BIT_TS_CTRL_TSM,
+				 PCF2127_BIT_TS_CTRL_TSM);
+	if (ret) {
+		dev_err(dev, "%s: tamper detection config (ts_ctrl) failed\n",
+			__func__);
+		return ret;
+	}
+
+	/*
+	 * Enable interrupt generation when TSF1 or TSF2 timestamp flags
+	 * are set. Interrupt signal is an open-drain output and can be
+	 * left floating if unused.
+	 */
+	ret = regmap_update_bits(pcf2127->regmap, PCF2127_REG_CTRL2,
+				 PCF2127_BIT_CTRL2_TSIE,
+				 PCF2127_BIT_CTRL2_TSIE);
+	if (ret) {
+		dev_err(dev, "%s: tamper detection config (ctrl2) failed\n",
+			__func__);
+		return ret;
+	}
+
+	ret = rtc_add_group(pcf2127->rtc, &pcf2127_attr_group);
+	if (ret) {
+		dev_err(dev, "%s: tamper sysfs registering failed\n",
+			__func__);
+		return ret;
+	}
+
 	return rtc_register_device(pcf2127->rtc);
 }
 
-- 
2.21.0


^ permalink raw reply related	[flat|nested] 9+ messages in thread

* Re: [PATCH v2 4/5] rtc: pcf2127: add watchdog feature support
  2019-08-13 15:35 ` [PATCH v2 4/5] rtc: pcf2127: add watchdog feature support Bruno Thomsen
@ 2019-08-13 16:19   ` Guenter Roeck
  2019-08-14 13:25     ` Bruno Thomsen
  0 siblings, 1 reply; 9+ messages in thread
From: Guenter Roeck @ 2019-08-13 16:19 UTC (permalink / raw)
  To: Bruno Thomsen
  Cc: linux-rtc, linux-watchdog, alexandre.belloni, a.zummo, wim,
	u.kleine-koenig, sean.nyekjaer, bth

On Tue, Aug 13, 2019 at 05:35:59PM +0200, Bruno Thomsen wrote:
> Add partial support for the watchdog functionality of
> both PCF2127 and PCF2129 chips.
> 
> The programmable watchdog timer is currently using a fixed
> clock source of 1Hz. This result in a selectable range of
> 1-255 seconds, which covers most embedded Linux use-cases.
> 
> Clock sources of 4096Hz, 64Hz and 1/60Hz is mostly useful
> in MCU use-cases.
> 
> Countdown timer not available when using watchdog feature.
> 
> Signed-off-by: Bruno Thomsen <bruno.thomsen@gmail.com>
> ---
>  drivers/rtc/Kconfig       |   7 ++-
>  drivers/rtc/rtc-pcf2127.c | 127 ++++++++++++++++++++++++++++++++++++++
>  2 files changed, 133 insertions(+), 1 deletion(-)
> 
> diff --git a/drivers/rtc/Kconfig b/drivers/rtc/Kconfig
> index e72f65b61176..a3bb58a08879 100644
> --- a/drivers/rtc/Kconfig
> +++ b/drivers/rtc/Kconfig
> @@ -876,7 +876,12 @@ config RTC_DRV_PCF2127
>  	depends on RTC_I2C_AND_SPI
>  	help
>  	  If you say yes here you get support for the NXP PCF2127/29 RTC
> -	  chips.
> +	  chips with integrated quartz crystal for industrial applications.
> +	  Both chips also have watchdog timer and tamper switch detection
> +	  features.
> +
> +	  PCF2127 has an additional feature of 512 bytes battery backed
> +	  memory that's accessible using nvmem interface.
>  
>  	  This driver can also be built as a module. If so, the module
>  	  will be called rtc-pcf2127.
> diff --git a/drivers/rtc/rtc-pcf2127.c b/drivers/rtc/rtc-pcf2127.c
> index ee4921e4a47c..700db7dd3eef 100644
> --- a/drivers/rtc/rtc-pcf2127.c
> +++ b/drivers/rtc/rtc-pcf2127.c
> @@ -5,6 +5,9 @@
>   *
>   * Author: Renaud Cerrato <r.cerrato@til-technologies.fr>
>   *
> + * Watchdog and tamper functions
> + * Author: Bruno Thomsen <bruno.thomsen@gmail.com>
> + *
>   * based on the other drivers in this same directory.
>   *
>   * Datasheet: http://cache.nxp.com/documents/data_sheet/PCF2127.pdf
> @@ -18,6 +21,7 @@
>  #include <linux/module.h>
>  #include <linux/of.h>
>  #include <linux/regmap.h>
> +#include <linux/watchdog.h>
>  
>  /* Control register 1 */
>  #define PCF2127_REG_CTRL1		0x00
> @@ -35,6 +39,13 @@
>  #define PCF2127_REG_DW			0x07
>  #define PCF2127_REG_MO			0x08
>  #define PCF2127_REG_YR			0x09
> +/* Watchdog registers */
> +#define PCF2127_REG_WD_CTL		0x10
> +#define PCF2127_BIT_WD_CTL_TF0			BIT(0)
> +#define PCF2127_BIT_WD_CTL_TF1			BIT(1)
> +#define PCF2127_BIT_WD_CTL_CD0			BIT(6)
> +#define PCF2127_BIT_WD_CTL_CD1			BIT(7)
> +#define PCF2127_REG_WD_VAL		0x11
>  /*
>   * RAM registers
>   * PCF2127 has 512 bytes general-purpose static RAM (SRAM) that is
> @@ -45,9 +56,15 @@
>  #define PCF2127_REG_RAM_WRT_CMD		0x1C
>  #define PCF2127_REG_RAM_RD_CMD		0x1D
>  
> +/* Watchdog timer value constants */
> +#define PCF2127_WD_VAL_STOP		0
> +#define PCF2127_WD_VAL_MIN		2
> +#define PCF2127_WD_VAL_MAX		255
> +#define PCF2127_WD_VAL_DEFAULT		60
>  
>  struct pcf2127 {
>  	struct rtc_device *rtc;
> +	struct watchdog_device wdd;
>  	struct regmap *regmap;
>  };
>  
> @@ -220,6 +237,81 @@ static int pcf2127_nvmem_write(void *priv, unsigned int offset,
>  	return ret ?: bytes;
>  }
>  
> +/* watchdog driver */
> +
> +static int pcf2127_wdt_ping(struct watchdog_device *wdd)
> +{
> +	struct pcf2127 *pcf2127 = watchdog_get_drvdata(wdd);
> +
> +	return regmap_write(pcf2127->regmap, PCF2127_REG_WD_VAL, wdd->timeout);
> +}
> +
> +/*
> + * Restart watchdog timer if feature is active.
> + *
> + * Note: Reading CTRL2 register causes watchdog to stop which is unfortunate,
> + * since register also contain control/status flags for other features.
> + * Always call this function after reading CTRL2 register.
> + */
> +static int pcf2127_wdt_active_ping(struct watchdog_device *wdd)
> +{
> +	int ret = 0;
> +
> +	if (watchdog_active(wdd)) {
> +		ret = pcf2127_wdt_ping(wdd);
> +		if (ret)
> +			dev_err(wdd->parent,
> +				"%s: watchdog restart failed, ret=%d\n",
> +				__func__, ret);
> +	}
> +
> +	return ret;
> +}
> +
> +static int pcf2127_wdt_start(struct watchdog_device *wdd)
> +{
> +	dev_info(wdd->parent, "watchdog enabled\n");
> +
> +	return pcf2127_wdt_ping(wdd);
> +}
> +
> +static int pcf2127_wdt_stop(struct watchdog_device *wdd)
> +{
> +	struct pcf2127 *pcf2127 = watchdog_get_drvdata(wdd);
> +
> +	dev_info(wdd->parent, "watchdog disabled\n");
> +

There is a lot of noise in this driver. Please reconsider.

Guenter

> +	return regmap_write(pcf2127->regmap, PCF2127_REG_WD_VAL,
> +			    PCF2127_WD_VAL_STOP);
> +}
> +
> +static int pcf2127_wdt_set_timeout(struct watchdog_device *wdd,
> +				   unsigned int new_timeout)
> +{
> +	int ret = 0;
> +
> +	dev_info(wdd->parent, "new watchdog timeout: %is (old: %is)\n",
> +		new_timeout, wdd->timeout);
> +
> +	wdd->timeout = new_timeout;
> +	ret = pcf2127_wdt_active_ping(wdd);
> +
> +	return ret;
> +}
> +
> +static const struct watchdog_info pcf2127_wdt_info = {
> +	.identity = "NXP PCF2127/PCF2129 Watchdog",
> +	.options = WDIOF_KEEPALIVEPING | WDIOF_SETTIMEOUT,
> +};
> +
> +static const struct watchdog_ops pcf2127_watchdog_ops = {
> +	.owner = THIS_MODULE,
> +	.start = pcf2127_wdt_start,
> +	.stop = pcf2127_wdt_stop,
> +	.ping = pcf2127_wdt_ping,
> +	.set_timeout = pcf2127_wdt_set_timeout,
> +};
> +
>  static int pcf2127_probe(struct device *dev, struct regmap *regmap,
>  			const char *name, bool has_nvmem)
>  {
> @@ -242,6 +334,16 @@ static int pcf2127_probe(struct device *dev, struct regmap *regmap,
>  
>  	pcf2127->rtc->ops = &pcf2127_rtc_ops;
>  
> +	pcf2127->wdd.parent = dev;
> +	pcf2127->wdd.info = &pcf2127_wdt_info;
> +	pcf2127->wdd.ops = &pcf2127_watchdog_ops;
> +	pcf2127->wdd.min_timeout = PCF2127_WD_VAL_MIN;
> +	pcf2127->wdd.max_timeout = PCF2127_WD_VAL_MAX;
> +	pcf2127->wdd.timeout = PCF2127_WD_VAL_DEFAULT;
> +	pcf2127->wdd.min_hw_heartbeat_ms = 500;
> +
> +	watchdog_set_drvdata(&pcf2127->wdd, pcf2127);
> +
>  	if (has_nvmem) {
>  		struct nvmem_config nvmem_cfg = {
>  			.priv = pcf2127,
> @@ -253,6 +355,31 @@ static int pcf2127_probe(struct device *dev, struct regmap *regmap,
>  		ret = rtc_nvmem_register(pcf2127->rtc, &nvmem_cfg);
>  	}
>  
> +	/*
> +	 * Watchdog timer enabled and reset pin /RST activated when timed out.
> +	 * Select 1Hz clock source for watchdog timer.
> +	 * Timer is not started until WD_VAL is loaded with a valid value.
> +	 * Note: Countdown timer disabled and not available.
> +	 */
> +	ret = regmap_update_bits(pcf2127->regmap, PCF2127_REG_WD_CTL,
> +				 PCF2127_BIT_WD_CTL_CD1 |
> +				 PCF2127_BIT_WD_CTL_CD0 |
> +				 PCF2127_BIT_WD_CTL_TF1 |
> +				 PCF2127_BIT_WD_CTL_TF0,
> +				 PCF2127_BIT_WD_CTL_CD1 |
> +				 PCF2127_BIT_WD_CTL_CD0 |
> +				 PCF2127_BIT_WD_CTL_TF1);
> +	if (ret) {
> +		dev_err(dev, "%s: watchdog config (wd_ctl) failed\n", __func__);
> +		return ret;
> +	}
> +
> +	ret = devm_watchdog_register_device(dev, &pcf2127->wdd);
> +	if (ret) {
> +		dev_err(dev, "%s: watchdog registering failed\n", __func__);
> +		return ret;
> +	}
> +
>  	return rtc_register_device(pcf2127->rtc);
>  }
>  
> -- 
> 2.21.0
> 

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [PATCH v2 4/5] rtc: pcf2127: add watchdog feature support
  2019-08-13 16:19   ` Guenter Roeck
@ 2019-08-14 13:25     ` Bruno Thomsen
  2019-08-14 13:34       ` Guenter Roeck
  0 siblings, 1 reply; 9+ messages in thread
From: Bruno Thomsen @ 2019-08-14 13:25 UTC (permalink / raw)
  To: Guenter Roeck
  Cc: linux-rtc, linux-watchdog, Alexandre Belloni, a.zummo, wim,
	u.kleine-koenig, bth

Hi Guenter

Thanks for the quick review.

Den tir. 13. aug. 2019 kl. 18.19 skrev Guenter Roeck <linux@roeck-us.net>:
>
> On Tue, Aug 13, 2019 at 05:35:59PM +0200, Bruno Thomsen wrote:
> > +static int pcf2127_wdt_start(struct watchdog_device *wdd)
> > +{
> > +     dev_info(wdd->parent, "watchdog enabled\n");
> > +
> > +     return pcf2127_wdt_ping(wdd);
> > +}
> > +
> > +static int pcf2127_wdt_stop(struct watchdog_device *wdd)
> > +{
> > +     struct pcf2127 *pcf2127 = watchdog_get_drvdata(wdd);
> > +
> > +     dev_info(wdd->parent, "watchdog disabled\n");
> > +
>
> There is a lot of noise in this driver. Please reconsider.

Would it be better if I remove the following lines:

dev_info(wdd->parent, "watchdog enabled\n");
dev_info(wdd->parent, "watchdog disabled\n");
dev_err(dev, "%s: watchdog registering failed\n", __func__);

and change this line to a dev_dbg():

dev_info(wdd->parent, "new watchdog timeout: %is (old: %is)\n",
         new_timeout, wdd->timeout);

?

Just checking so I don't waste your time on v3 review.

/Bruno

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [PATCH v2 4/5] rtc: pcf2127: add watchdog feature support
  2019-08-14 13:25     ` Bruno Thomsen
@ 2019-08-14 13:34       ` Guenter Roeck
  0 siblings, 0 replies; 9+ messages in thread
From: Guenter Roeck @ 2019-08-14 13:34 UTC (permalink / raw)
  To: Bruno Thomsen
  Cc: linux-rtc, linux-watchdog, Alexandre Belloni, a.zummo, wim,
	u.kleine-koenig, bth

On Wed, Aug 14, 2019 at 03:25:55PM +0200, Bruno Thomsen wrote:
> Hi Guenter
> 
> Thanks for the quick review.
> 
> Den tir. 13. aug. 2019 kl. 18.19 skrev Guenter Roeck <linux@roeck-us.net>:
> >
> > On Tue, Aug 13, 2019 at 05:35:59PM +0200, Bruno Thomsen wrote:
> > > +static int pcf2127_wdt_start(struct watchdog_device *wdd)
> > > +{
> > > +     dev_info(wdd->parent, "watchdog enabled\n");
> > > +
> > > +     return pcf2127_wdt_ping(wdd);
> > > +}
> > > +
> > > +static int pcf2127_wdt_stop(struct watchdog_device *wdd)
> > > +{
> > > +     struct pcf2127 *pcf2127 = watchdog_get_drvdata(wdd);
> > > +
> > > +     dev_info(wdd->parent, "watchdog disabled\n");
> > > +
> >
> > There is a lot of noise in this driver. Please reconsider.
> 
> Would it be better if I remove the following lines:
> 
> dev_info(wdd->parent, "watchdog enabled\n");
> dev_info(wdd->parent, "watchdog disabled\n");
> dev_err(dev, "%s: watchdog registering failed\n", __func__);
> 
> and change this line to a dev_dbg():
> 
> dev_info(wdd->parent, "new watchdog timeout: %is (old: %is)\n",
>          new_timeout, wdd->timeout);
> 
> ?
> 
Yes.

Thanks,
Guenter

^ permalink raw reply	[flat|nested] 9+ messages in thread

end of thread, other threads:[~2019-08-14 13:34 UTC | newest]

Thread overview: 9+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2019-08-13 15:35 [PATCH v2 0/5] rtc: pcf2127: tamper timestamp and watchdog feature support Bruno Thomsen
2019-08-13 15:35 ` [PATCH v2 1/5] rtc: pcf2127: convert to devm_rtc_allocate_device Bruno Thomsen
2019-08-13 15:35 ` [PATCH v2 2/5] rtc: pcf2127: cleanup register and bit defines Bruno Thomsen
2019-08-13 15:35 ` [PATCH v2 3/5] rtc: pcf2127: bugfix: read rtc disables watchdog Bruno Thomsen
2019-08-13 15:35 ` [PATCH v2 4/5] rtc: pcf2127: add watchdog feature support Bruno Thomsen
2019-08-13 16:19   ` Guenter Roeck
2019-08-14 13:25     ` Bruno Thomsen
2019-08-14 13:34       ` Guenter Roeck
2019-08-13 15:36 ` [PATCH v2 5/5] rtc: pcf2127: add tamper detection support Bruno Thomsen

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).