From patchwork Fri Jan 20 12:36:44 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: =?utf-8?q?Sean_Nyekj=C3=A6r?= X-Patchwork-Id: 717625 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from mail-wm0-x23c.google.com (mail-wm0-x23c.google.com [IPv6:2a00:1450:400c:c09::23c]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 3v4gGn0xbHz9sDF for ; Fri, 20 Jan 2017 23:38:08 +1100 (AEDT) Authentication-Results: ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=googlegroups.com header.i=@googlegroups.com header.b="R4pfgGMP"; dkim-atps=neutral Received: by mail-wm0-x23c.google.com with SMTP id f73sf10450699wmf.1 for ; Fri, 20 Jan 2017 04:38:08 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=googlegroups.com; s=20161025; h=sender:mime-version:from:to:cc:subject:date:message-id:in-reply-to :references:x-original-sender:x-original-authentication-results :reply-to:precedence:mailing-list:list-id:x-spam-checked-in-group :list-post:list-help:list-archive:list-subscribe:list-unsubscribe; bh=DfvpWSfpPzTFvMSKP+wQw0YlvQ2RbTCe+Oq5H5zD9k4=; b=R4pfgGMPHRfCwU+jjfAjo5Zg8qrexrF9L0A5NpSbTPn1YWCmZn8EcxnyHN0bvsuGsk yg8YZhcEss4fr1SRtSJ0hFHTNTqfUXtW2zMLDGVdVmWjC/7CynxLUA12ldfpAI9OGO+D k7ZKZyfO0JWoHLj3T9gxTxcG9j1nTK3iaJmg80FYq4S/Xq2ilRyWGooJi/YtUnNZHfrI CusEi3x8uhpw8vpI0Hclu0q5HFfYAXCO4MJz6jxjmnKHVvBE+P3k2CfO/4+669xCackM UfjKNEsgD4Xjr4xKyRNOo/3fjAWANI6MhbpdPT97RtCTeOhpVj/1vbLEnZnjCdtxEdVU XPyA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=sender:x-gm-message-state:mime-version:from:to:cc:subject:date :message-id:in-reply-to:references:x-original-sender :x-original-authentication-results:reply-to:precedence:mailing-list :list-id:x-spam-checked-in-group:list-post:list-help:list-archive :list-subscribe:list-unsubscribe; bh=DfvpWSfpPzTFvMSKP+wQw0YlvQ2RbTCe+Oq5H5zD9k4=; b=WEqjgkPLZXZRz3Y73kPtSvlJR2vpaIwS3LcBSReU+xp06rLOsdWEMgVHMJHvnjeuZ6 9x286yX3HqnXROX3+0X3YX02AqcPe3iIX0zwXOgHx6T1HmwWJHcETAq73ul6u+EsFiwM gNI0C5NKbnChsKrMWbm2N2JFgxoLUdB5+ExUBIk7VP5x1j7JVSaeaHBSfsjpThyEH2x8 6V8E136NhQVig2kesYaNu/6N4tT5l6EOGOMUMdn4/kx2EXWFC8WeTB2x6Pfsg9pe8xax 617qBDu7jlM5Iu7QUMlMDlmkCXt51VWgqcI5bY/GwPlip9rzml1TqOWQptjEoMxCop1j NVMQ== Sender: rtc-linux@googlegroups.com X-Gm-Message-State: AIkVDXLh3bjEtG8O7MvGWKGSP+ZH21B7mS9tEgLWIYYORl+QQWRIgvgevC7wTLeGxnM/hg== X-Received: by 10.46.74.2 with SMTP id x2mr16244lja.15.1484915874229; Fri, 20 Jan 2017 04:37:54 -0800 (PST) MIME-Version: 1.0 X-BeenThere: rtc-linux@googlegroups.com Received: by 10.46.75.18 with SMTP id y18ls510046lja.12.gmail; Fri, 20 Jan 2017 04:37:53 -0800 (PST) X-Received: by 10.25.40.17 with SMTP id o17mr1090749lfo.25.1484915873782; Fri, 20 Jan 2017 04:37:53 -0800 (PST) Received: from mail02.prevas.se (mail02.prevas.se. [62.95.78.10]) by gmr-mx.google.com with ESMTPS id h62si105086wme.2.2017.01.20.04.37.53 for (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Fri, 20 Jan 2017 04:37:53 -0800 (PST) Received-SPF: pass (google.com: domain of prvs=186a45687=sean.nyekjaer@prevas.dk designates 62.95.78.10 as permitted sender) client-ip=62.95.78.10; X-IronPort-Anti-Spam-Filtered: true X-IronPort-Anti-Spam-Result: =?us-ascii?q?A2HcAwCQA4JY/4nQil9eHQEFAQsBgz0BA?= =?us-ascii?q?QEBAR+BaYMFhVaFAKUigg+CDBqGCAIMggE/FAECAQEBAQEBAQNgKIRqBidSEBg?= =?us-ascii?q?nElcZiQixDTomAooeAQEBByiGS4wFDIMMBY8rjB2BfI9eDYpHhieSdB85gSiFJ?= =?us-ascii?q?RyBYT01iRQBAQE?= X-IPAS-Result: =?us-ascii?q?A2HcAwCQA4JY/4nQil9eHQEFAQsBgz0BAQEBAR+BaYMFhVa?= =?us-ascii?q?FAKUigg+CDBqGCAIMggE/FAECAQEBAQEBAQNgKIRqBidSEBgnElcZiQixDTomA?= =?us-ascii?q?ooeAQEBByiGS4wFDIMMBY8rjB2BfI9eDYpHhieSdB85gSiFJRyBYT01iRQBAQE?= X-IronPort-AV: E=Sophos;i="5.33,258,1477954800"; d="scan'208";a="1666495" Received: from unknown (HELO skn.kamstrup.dk) ([95.138.208.137]) by mail02.prevas.se with ESMTP/TLS/AES128-SHA256; 20 Jan 2017 13:37:52 +0100 From: Sean Nyekjaer To: rtc-linux@googlegroups.com Cc: Sean Nyekjaer Subject: [rtc-linux] [PATCH 2/2] rtc: pcf2127: add support for pcf2127 tamper functionality Date: Fri, 20 Jan 2017 13:36:44 +0100 Message-Id: <20170120123644.118612-2-sean.nyekjaer@prevas.dk> X-Mailer: git-send-email 2.11.0 In-Reply-To: <20170120123644.118612-1-sean.nyekjaer@prevas.dk> References: <20170120123644.118612-1-sean.nyekjaer@prevas.dk> X-Original-Sender: sean.nyekjaer@prevas.dk X-Original-Authentication-Results: gmr-mx.google.com; dkim=pass header.i=@prevas.dk; spf=pass (google.com: domain of prvs=186a45687=sean.nyekjaer@prevas.dk designates 62.95.78.10 as permitted sender) smtp.mailfrom=prvs=186a45687=sean.nyekjaer@prevas.dk Reply-To: rtc-linux@googlegroups.com Precedence: list Mailing-list: list rtc-linux@googlegroups.com; contact rtc-linux+owners@googlegroups.com List-ID: X-Spam-Checked-In-Group: rtc-linux@googlegroups.com X-Google-Group-Id: 712029733259 List-Post: , List-Help: , List-Archive: , List-Unsubscribe: , Signed-off-by: Sean Nyekjaer --- 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[] = {