All of lore.kernel.org
 help / color / mirror / Atom feed
From: Sean Nyekjaer <sean.nyekjaer@prevas.dk>
To: rtc-linux@googlegroups.com
Cc: Sean Nyekjaer <sean.nyekjaer@prevas.dk>
Subject: [rtc-linux] [PATCH 2/2] rtc: pcf2127: add support for pcf2127 tamper functionality
Date: Fri, 20 Jan 2017 13:36:44 +0100	[thread overview]
Message-ID: <20170120123644.118612-2-sean.nyekjaer@prevas.dk> (raw)
In-Reply-To: <20170120123644.118612-1-sean.nyekjaer@prevas.dk>

Signed-off-by: Sean Nyekjaer <sean.nyekjaer@prevas.dk>
---
 drivers/rtc/Kconfig       |   7 +++
 drivers/rtc/rtc-pcf2127.c | 128 +++++++++++++++++++++++++++++++++++++++++++---
 2 files changed, 129 insertions(+), 6 deletions(-)

diff --git a/drivers/rtc/Kconfig b/drivers/rtc/Kconfig
index c8985be81d83..e8d7944a4018 100644
--- a/drivers/rtc/Kconfig
+++ b/drivers/rtc/Kconfig
@@ -806,6 +806,13 @@ config RTC_DRV_PCF2127_WDT
 	  If you say Y here you will get support for the
 	  watchdog timer in the NXP PCF2127 chip real-time clock chips.
 
+config RTC_DRV_PCF2127_TAMPER
+	bool "NXP PCF2127 tamper"
+	depends on RTC_DRV_PCF2127
+	help
+	  If you say Y here you will get support for the
+	  tamper device in the NXP PCF2127 chip real-time clock chips.
+
 config RTC_DRV_RV3029C2
 	tristate "Micro Crystal RV3029/3049"
 	depends on RTC_I2C_AND_SPI
diff --git a/drivers/rtc/rtc-pcf2127.c b/drivers/rtc/rtc-pcf2127.c
index 31627c59c44d..5f96cff9ebd5 100644
--- a/drivers/rtc/rtc-pcf2127.c
+++ b/drivers/rtc/rtc-pcf2127.c
@@ -30,7 +30,10 @@
 #endif
 
 #define PCF2127_REG_CTRL1       (0x00)  /* Control Register 1 */
+#define PCF2127_TSF1		BIT(4)
 #define PCF2127_REG_CTRL2       (0x01)  /* Control Register 2 */
+#define PCF2127_TSIE		BIT(2)
+#define PCF2127_TSF2		BIT(5)
 
 #define PCF2127_REG_CTRL3       (0x02)  /* Control Register 3 */
 #define PCF2127_REG_CTRL3_BLF		BIT(2)
@@ -42,6 +45,17 @@
 #define PCF2127_REG_WDG_T_TF_1HZ	BIT(1)	/* Timer clock source */
 #define PCF2127_REG_WDG_TIMVAL		(0x11)
 
+#define PCF2127_REG_TIMSTP_CTL		(0x12)
+#define PCF2127_TSM			BIT(7)
+#define PCF2127_TSOFF			BIT(6)
+
+#define PCF2127_REG_TIMSTP_SC		(0x01)
+#define PCF2127_REG_TIMSTP_MN		(0x02)
+#define PCF2127_REG_TIMSTP_HR		(0x03)
+#define PCF2127_REG_TIMSTP_DM		(0x04)
+#define PCF2127_REG_TIMSTP_MO		(0x05)
+#define PCF2127_REG_TIMSTP_YR		(0x06)
+
 #define PCF2127_REG_SC          (0x03)  /* datetime */
 #define PCF2127_REG_MN          (0x04)
 #define PCF2127_REG_HR          (0x05)
@@ -55,10 +69,84 @@
 struct pcf2127 {
 	struct rtc_device *rtc;
 	struct regmap *regmap;
+	struct rtc_time tamper_event;
+	bool tamper_enabled;
+	int irq;
 };
 
-#ifdef CONFIG_RTC_DRV_PCF2127_WDT
+#if defined(CONFIG_RTC_DRV_PCF2127_TAMPER) || defined(CONFIG_RTC_DRV_PCF2127_WDT)
 static struct pcf2127 *save_pcf2127;
+#endif
+
+#ifdef CONFIG_RTC_DRV_PCF2127_TAMPER
+static int pcf2127_tamper_event_print(struct device *dev)
+{
+	int err;
+	unsigned char buf[7];
+	struct rtc_time *tm;
+
+	err = regmap_bulk_read(save_pcf2127->regmap, PCF2127_REG_TIMSTP_CTL,
+			       buf, sizeof(buf));
+	if (err)
+		return err;
+
+	tm = &save_pcf2127->tamper_event;
+
+	tm->tm_sec = bcd2bin(buf[PCF2127_REG_TIMSTP_SC] & 0x7F);
+	tm->tm_min = bcd2bin(buf[PCF2127_REG_TIMSTP_MN] & 0x7F);
+	tm->tm_hour = bcd2bin(buf[PCF2127_REG_TIMSTP_HR] & 0x3F);
+	tm->tm_mday = bcd2bin(buf[PCF2127_REG_TIMSTP_DM] & 0x3F);
+	tm->tm_mon = bcd2bin(buf[PCF2127_REG_TIMSTP_MO] & 0x1F) - 1;
+	tm->tm_year = bcd2bin(buf[PCF2127_REG_TIMSTP_YR]);
+
+	dev_emerg(dev, "%s: Tamper detected at secs=%d, mins=%d, hours=%d, "
+		  "mday=%d, mon=%d, year=%d\n",
+		  __func__,
+		  tm->tm_sec, tm->tm_min, tm->tm_hour,
+		  tm->tm_mday, tm->tm_mon, tm->tm_year);
+
+	return 0;
+}
+
+static int pcf2127_tamper_enable(void)
+{
+	int err;
+
+	/* Enable interrupt on tamper event */
+	err = regmap_write_bits(save_pcf2127->regmap, PCF2127_REG_CTRL2,
+				PCF2127_TSIE, PCF2127_TSIE);
+	if (err)
+		return err;
+
+	/* Enable timestamp function */
+	err = regmap_write_bits(save_pcf2127->regmap, PCF2127_REG_TIMSTP_CTL,
+				PCF2127_TSM | PCF2127_TSOFF, PCF2127_TSM);
+	if (err)
+		return err;
+
+	save_pcf2127->tamper_enabled = true;
+
+	return 0;
+}
+
+static irqreturn_t pcf2127_tamper_event_irq(int irq, void *data)
+{
+	struct device *dev = data;
+	struct pcf2127 *pcf2127 = dev_get_drvdata(dev);
+
+	pcf2127_tamper_event_print(dev);
+
+	/* Clear interrupt pin */
+	regmap_write_bits(pcf2127->regmap, PCF2127_REG_CTRL1,
+			PCF2127_TSF1, 0);
+	regmap_write_bits(pcf2127->regmap, PCF2127_REG_CTRL2,
+			PCF2127_TSF2, 0);
+
+	return IRQ_HANDLED;
+}
+#endif
+
+#ifdef CONFIG_RTC_DRV_PCF2127_WDT
 
 /* default 32 sec timeout */
 #define WD_TIMO 32
@@ -219,6 +307,11 @@ static int pcf2127_rtc_read_time(struct device *dev, struct rtc_time *tm)
 			 "oscillator stop detected, date/time is not reliable\n");
 		return -EINVAL;
 	}
+#ifdef CONFIG_RTC_DRV_PCF2127_TAMPER
+	if (buf[PCF2127_REG_CTRL1] & PCF2127_TSF1) {
+		pcf2127_tamper_event_print(dev);
+	}
+#endif
 
 	dev_dbg(dev,
 		"%s: raw data is cr1=%02x, cr2=%02x, cr3=%02x, "
@@ -319,9 +412,9 @@ static const struct rtc_class_ops pcf2127_rtc_ops = {
 };
 
 static int pcf2127_probe(struct device *dev, struct regmap *regmap,
-			const char *name)
+			 const char *name, int irq)
 {
-#ifdef CONFIG_RTC_DRV_PCF2127_WDT
+#if defined(CONFIG_RTC_DRV_PCF2127_TAMPER) || defined(CONFIG_RTC_DRV_PCF2127_WDT)
 	int ret;
 #endif
 	struct pcf2127 *pcf2127;
@@ -332,7 +425,7 @@ static int pcf2127_probe(struct device *dev, struct regmap *regmap,
 	if (!pcf2127)
 		return -ENOMEM;
 
-#ifdef CONFIG_RTC_DRV_PCF2127_WDT
+#if defined(CONFIG_RTC_DRV_PCF2127_TAMPER) || defined(CONFIG_RTC_DRV_PCF2127_WDT)
 	save_pcf2127 = pcf2127;
 #endif
 
@@ -358,6 +451,28 @@ static int pcf2127_probe(struct device *dev, struct regmap *regmap,
 	pcf2127_wdt_settimeout(32);
 #endif
 
+#ifdef CONFIG_RTC_DRV_PCF2127_TAMPER
+	pcf2127->tamper_enabled = false;
+
+	if (!of_device_is_compatible(dev->of_node, "nxp,pcf2127"))
+		return 0;
+
+	if (of_property_read_bool(dev->of_node, "tamper")) {
+		pcf2127_tamper_enable();
+
+		ret = devm_request_threaded_irq(dev, irq, NULL,
+						pcf2127_tamper_event_irq,
+						IRQF_ONESHOT | IRQF_TRIGGER_FALLING, dev_name(dev),
+						dev);
+		if (ret < 0) {
+			dev_err(dev, "IRQ is not free.\n");
+			return ret;
+		}
+
+		pcf2127->irq = irq;
+	}
+#endif
+
 	return 0;
 }
 
@@ -466,7 +581,7 @@ static int pcf2127_i2c_probe(struct i2c_client *client,
 	}
 
 	return pcf2127_probe(&client->dev, regmap,
-				pcf2127_i2c_driver.driver.name);
+				pcf2127_i2c_driver.driver.name, client->irq);
 }
 
 static const struct i2c_device_id pcf2127_i2c_id[] = {
@@ -529,7 +644,8 @@ static int pcf2127_spi_probe(struct spi_device *spi)
 		return PTR_ERR(regmap);
 	}
 
-	return pcf2127_probe(&spi->dev, regmap, pcf2127_spi_driver.driver.name);
+	return pcf2127_probe(&spi->dev, regmap, pcf2127_spi_driver.driver.name,
+			     spi->irq);
 }
 
 static const struct spi_device_id pcf2127_spi_id[] = {
-- 
2.11.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.

  reply	other threads:[~2017-01-20 12:37 UTC|newest]

Thread overview: 5+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2017-01-20 12:36 [rtc-linux] [PATCH 1/2] rtc: pcf2127: add support for pcf2127 watchdog functionality Sean Nyekjaer
2017-01-20 12:36 ` Sean Nyekjaer [this message]
2017-08-29 15:07 ` Alexandre Belloni
2017-08-30  7:45   ` Sean Nyekjær
2017-08-30  7:52     ` Alexandre Belloni

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20170120123644.118612-2-sean.nyekjaer@prevas.dk \
    --to=sean.nyekjaer@prevas.dk \
    --cc=rtc-linux@googlegroups.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.