summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-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