summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBruno Thomsen <bruno.thomsen@gmail.com>2019-08-22 09:19:36 -0400
committerAlexandre Belloni <alexandre.belloni@bootlin.com>2019-08-27 12:24:15 -0400
commit03623b4b041cde396641399c343f52ce840d349d (patch)
treec48de78afacfb4b94acf2f9fb603e51ab47ae7f6
parent0e735eaae1650a2e26835cc776f496e06a87be9f (diff)
rtc: pcf2127: add tamper detection support
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> Link: https://lore.kernel.org/r/20190822131936.18772-5-bruno.thomsen@gmail.com Signed-off-by: Alexandre Belloni <alexandre.belloni@bootlin.com>
-rw-r--r--drivers/rtc/rtc-pcf2127.c160
1 files changed, 160 insertions, 0 deletions
diff --git a/drivers/rtc/rtc-pcf2127.c b/drivers/rtc/rtc-pcf2127.c
index 8d6eda455d81..3ec87d320766 100644
--- a/drivers/rtc/rtc-pcf2127.c
+++ b/drivers/rtc/rtc-pcf2127.c
@@ -25,11 +25,18 @@
25 25
26/* Control register 1 */ 26/* Control register 1 */
27#define PCF2127_REG_CTRL1 0x00 27#define PCF2127_REG_CTRL1 0x00
28#define PCF2127_BIT_CTRL1_TSF1 BIT(4)
28/* Control register 2 */ 29/* Control register 2 */
29#define PCF2127_REG_CTRL2 0x01 30#define PCF2127_REG_CTRL2 0x01
31#define PCF2127_BIT_CTRL2_TSIE BIT(2)
32#define PCF2127_BIT_CTRL2_TSF2 BIT(5)
30/* Control register 3 */ 33/* Control register 3 */
31#define PCF2127_REG_CTRL3 0x02 34#define PCF2127_REG_CTRL3 0x02
35#define PCF2127_BIT_CTRL3_BLIE BIT(0)
36#define PCF2127_BIT_CTRL3_BIE BIT(1)
32#define PCF2127_BIT_CTRL3_BLF BIT(2) 37#define PCF2127_BIT_CTRL3_BLF BIT(2)
38#define PCF2127_BIT_CTRL3_BF BIT(3)
39#define PCF2127_BIT_CTRL3_BTSE BIT(4)
33/* Time and date registers */ 40/* Time and date registers */
34#define PCF2127_REG_SC 0x03 41#define PCF2127_REG_SC 0x03
35#define PCF2127_BIT_SC_OSF BIT(7) 42#define PCF2127_BIT_SC_OSF BIT(7)
@@ -46,6 +53,16 @@
46#define PCF2127_BIT_WD_CTL_CD0 BIT(6) 53#define PCF2127_BIT_WD_CTL_CD0 BIT(6)
47#define PCF2127_BIT_WD_CTL_CD1 BIT(7) 54#define PCF2127_BIT_WD_CTL_CD1 BIT(7)
48#define PCF2127_REG_WD_VAL 0x11 55#define PCF2127_REG_WD_VAL 0x11
56/* Tamper timestamp registers */
57#define PCF2127_REG_TS_CTRL 0x12
58#define PCF2127_BIT_TS_CTRL_TSOFF BIT(6)
59#define PCF2127_BIT_TS_CTRL_TSM BIT(7)
60#define PCF2127_REG_TS_SC 0x13
61#define PCF2127_REG_TS_MN 0x14
62#define PCF2127_REG_TS_HR 0x15
63#define PCF2127_REG_TS_DM 0x16
64#define PCF2127_REG_TS_MO 0x17
65#define PCF2127_REG_TS_YR 0x18
49/* 66/*
50 * RAM registers 67 * RAM registers
51 * PCF2127 has 512 bytes general-purpose static RAM (SRAM) that is 68 * PCF2127 has 512 bytes general-purpose static RAM (SRAM) that is
@@ -305,6 +322,97 @@ static const struct watchdog_ops pcf2127_watchdog_ops = {
305 .set_timeout = pcf2127_wdt_set_timeout, 322 .set_timeout = pcf2127_wdt_set_timeout,
306}; 323};
307 324
325/* sysfs interface */
326
327static ssize_t timestamp0_store(struct device *dev,
328 struct device_attribute *attr,
329 const char *buf, size_t count)
330{
331 struct pcf2127 *pcf2127 = dev_get_drvdata(dev->parent);
332 int ret;
333
334 ret = regmap_update_bits(pcf2127->regmap, PCF2127_REG_CTRL1,
335 PCF2127_BIT_CTRL1_TSF1, 0);
336 if (ret) {
337 dev_err(dev, "%s: update ctrl1 ret=%d\n", __func__, ret);
338 return ret;
339 }
340
341 ret = regmap_update_bits(pcf2127->regmap, PCF2127_REG_CTRL2,
342 PCF2127_BIT_CTRL2_TSF2, 0);
343 if (ret) {
344 dev_err(dev, "%s: update ctrl2 ret=%d\n", __func__, ret);
345 return ret;
346 }
347
348 ret = pcf2127_wdt_active_ping(&pcf2127->wdd);
349 if (ret)
350 return ret;
351
352 return count;
353};
354
355static ssize_t timestamp0_show(struct device *dev,
356 struct device_attribute *attr, char *buf)
357{
358 struct pcf2127 *pcf2127 = dev_get_drvdata(dev->parent);
359 struct rtc_time tm;
360 int ret;
361 unsigned char data[25];
362
363 ret = regmap_bulk_read(pcf2127->regmap, PCF2127_REG_CTRL1, data,
364 sizeof(data));
365 if (ret) {
366 dev_err(dev, "%s: read error ret=%d\n", __func__, ret);
367 return ret;
368 }
369
370 dev_dbg(dev,
371 "%s: raw data is cr1=%02x, cr2=%02x, cr3=%02x, ts_sc=%02x, "
372 "ts_mn=%02x, ts_hr=%02x, ts_dm=%02x, ts_mo=%02x, ts_yr=%02x\n",
373 __func__, data[PCF2127_REG_CTRL1], data[PCF2127_REG_CTRL2],
374 data[PCF2127_REG_CTRL3], data[PCF2127_REG_TS_SC],
375 data[PCF2127_REG_TS_MN], data[PCF2127_REG_TS_HR],
376 data[PCF2127_REG_TS_DM], data[PCF2127_REG_TS_MO],
377 data[PCF2127_REG_TS_YR]);
378
379 ret = pcf2127_wdt_active_ping(&pcf2127->wdd);
380 if (ret)
381 return ret;
382
383 if (!(data[PCF2127_REG_CTRL1] & PCF2127_BIT_CTRL1_TSF1) &&
384 !(data[PCF2127_REG_CTRL2] & PCF2127_BIT_CTRL2_TSF2))
385 return 0;
386
387 tm.tm_sec = bcd2bin(data[PCF2127_REG_TS_SC] & 0x7F);
388 tm.tm_min = bcd2bin(data[PCF2127_REG_TS_MN] & 0x7F);
389 tm.tm_hour = bcd2bin(data[PCF2127_REG_TS_HR] & 0x3F);
390 tm.tm_mday = bcd2bin(data[PCF2127_REG_TS_DM] & 0x3F);
391 /* TS_MO register (month) value range: 1-12 */
392 tm.tm_mon = bcd2bin(data[PCF2127_REG_TS_MO] & 0x1F) - 1;
393 tm.tm_year = bcd2bin(data[PCF2127_REG_TS_YR]);
394 if (tm.tm_year < 70)
395 tm.tm_year += 100; /* assume we are in 1970...2069 */
396
397 ret = rtc_valid_tm(&tm);
398 if (ret)
399 return ret;
400
401 return sprintf(buf, "%llu\n",
402 (unsigned long long)rtc_tm_to_time64(&tm));
403};
404
405static DEVICE_ATTR_RW(timestamp0);
406
407static struct attribute *pcf2127_attrs[] = {
408 &dev_attr_timestamp0.attr,
409 NULL
410};
411
412static const struct attribute_group pcf2127_attr_group = {
413 .attrs = pcf2127_attrs,
414};
415
308static int pcf2127_probe(struct device *dev, struct regmap *regmap, 416static int pcf2127_probe(struct device *dev, struct regmap *regmap,
309 const char *name, bool has_nvmem) 417 const char *name, bool has_nvmem)
310{ 418{
@@ -371,6 +479,58 @@ static int pcf2127_probe(struct device *dev, struct regmap *regmap,
371 if (ret) 479 if (ret)
372 return ret; 480 return ret;
373 481
482 /*
483 * Disable battery low/switch-over timestamp and interrupts.
484 * Clear battery interrupt flags which can block new trigger events.
485 * Note: This is the default chip behaviour but added to ensure
486 * correct tamper timestamp and interrupt function.
487 */
488 ret = regmap_update_bits(pcf2127->regmap, PCF2127_REG_CTRL3,
489 PCF2127_BIT_CTRL3_BTSE |
490 PCF2127_BIT_CTRL3_BF |
491 PCF2127_BIT_CTRL3_BIE |
492 PCF2127_BIT_CTRL3_BLIE, 0);
493 if (ret) {
494 dev_err(dev, "%s: interrupt config (ctrl3) failed\n",
495 __func__);
496 return ret;
497 }
498
499 /*
500 * Enable timestamp function and store timestamp of first trigger
501 * event until TSF1 and TFS2 interrupt flags are cleared.
502 */
503 ret = regmap_update_bits(pcf2127->regmap, PCF2127_REG_TS_CTRL,
504 PCF2127_BIT_TS_CTRL_TSOFF |
505 PCF2127_BIT_TS_CTRL_TSM,
506 PCF2127_BIT_TS_CTRL_TSM);
507 if (ret) {
508 dev_err(dev, "%s: tamper detection config (ts_ctrl) failed\n",
509 __func__);
510 return ret;
511 }
512
513 /*
514 * Enable interrupt generation when TSF1 or TSF2 timestamp flags
515 * are set. Interrupt signal is an open-drain output and can be
516 * left floating if unused.
517 */
518 ret = regmap_update_bits(pcf2127->regmap, PCF2127_REG_CTRL2,
519 PCF2127_BIT_CTRL2_TSIE,
520 PCF2127_BIT_CTRL2_TSIE);
521 if (ret) {
522 dev_err(dev, "%s: tamper detection config (ctrl2) failed\n",
523 __func__);
524 return ret;
525 }
526
527 ret = rtc_add_group(pcf2127->rtc, &pcf2127_attr_group);
528 if (ret) {
529 dev_err(dev, "%s: tamper sysfs registering failed\n",
530 __func__);
531 return ret;
532 }
533
374 return rtc_register_device(pcf2127->rtc); 534 return rtc_register_device(pcf2127->rtc);
375} 535}
376 536