9494#define PCF2127_WD_VAL_MAX 255
9595#define PCF2127_WD_VAL_DEFAULT 60
9696
97+ /* Mask for currently enabled interrupts */
98+ #define PCF2127_CTRL1_IRQ_MASK (PCF2127_BIT_CTRL1_TSF1)
99+ #define PCF2127_CTRL2_IRQ_MASK ( \
100+ PCF2127_BIT_CTRL2_AF | \
101+ PCF2127_BIT_CTRL2_WDTF | \
102+ PCF2127_BIT_CTRL2_TSF2)
103+
97104struct pcf2127 {
98105 struct rtc_device * rtc ;
99106 struct watchdog_device wdd ;
100107 struct regmap * regmap ;
108+ time64_t ts ;
109+ bool ts_valid ;
110+ bool irq_enabled ;
101111};
102112
103113/*
@@ -434,23 +444,96 @@ static int pcf2127_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm)
434444 return pcf2127_rtc_alarm_irq_enable (dev , alrm -> enabled );
435445}
436446
447+ /*
448+ * This function reads ctrl2 register, caller is responsible for calling
449+ * pcf2127_wdt_active_ping()
450+ */
451+ static int pcf2127_rtc_ts_read (struct device * dev , time64_t * ts )
452+ {
453+ struct pcf2127 * pcf2127 = dev_get_drvdata (dev );
454+ struct rtc_time tm ;
455+ int ret ;
456+ unsigned char data [25 ];
457+
458+ ret = regmap_bulk_read (pcf2127 -> regmap , PCF2127_REG_CTRL1 , data ,
459+ sizeof (data ));
460+ if (ret ) {
461+ dev_err (dev , "%s: read error ret=%d\n" , __func__ , ret );
462+ return ret ;
463+ }
464+
465+ dev_dbg (dev ,
466+ "%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" ,
467+ __func__ , data [PCF2127_REG_CTRL1 ], data [PCF2127_REG_CTRL2 ],
468+ data [PCF2127_REG_CTRL3 ], data [PCF2127_REG_TS_SC ],
469+ data [PCF2127_REG_TS_MN ], data [PCF2127_REG_TS_HR ],
470+ data [PCF2127_REG_TS_DM ], data [PCF2127_REG_TS_MO ],
471+ data [PCF2127_REG_TS_YR ]);
472+
473+ tm .tm_sec = bcd2bin (data [PCF2127_REG_TS_SC ] & 0x7F );
474+ tm .tm_min = bcd2bin (data [PCF2127_REG_TS_MN ] & 0x7F );
475+ tm .tm_hour = bcd2bin (data [PCF2127_REG_TS_HR ] & 0x3F );
476+ tm .tm_mday = bcd2bin (data [PCF2127_REG_TS_DM ] & 0x3F );
477+ /* TS_MO register (month) value range: 1-12 */
478+ tm .tm_mon = bcd2bin (data [PCF2127_REG_TS_MO ] & 0x1F ) - 1 ;
479+ tm .tm_year = bcd2bin (data [PCF2127_REG_TS_YR ]);
480+ if (tm .tm_year < 70 )
481+ tm .tm_year += 100 ; /* assume we are in 1970...2069 */
482+
483+ ret = rtc_valid_tm (& tm );
484+ if (ret ) {
485+ dev_err (dev , "Invalid timestamp. ret=%d\n" , ret );
486+ return ret ;
487+ }
488+
489+ * ts = rtc_tm_to_time64 (& tm );
490+ return 0 ;
491+ };
492+
493+ static void pcf2127_rtc_ts_snapshot (struct device * dev )
494+ {
495+ struct pcf2127 * pcf2127 = dev_get_drvdata (dev );
496+ int ret ;
497+
498+ /* Let userspace read the first timestamp */
499+ if (pcf2127 -> ts_valid )
500+ return ;
501+
502+ ret = pcf2127_rtc_ts_read (dev , & pcf2127 -> ts );
503+ if (!ret )
504+ pcf2127 -> ts_valid = true;
505+ }
506+
437507static irqreturn_t pcf2127_rtc_irq (int irq , void * dev )
438508{
439509 struct pcf2127 * pcf2127 = dev_get_drvdata (dev );
440- unsigned int ctrl2 = 0 ;
510+ unsigned int ctrl1 , ctrl2 ;
441511 int ret = 0 ;
442512
513+ ret = regmap_read (pcf2127 -> regmap , PCF2127_REG_CTRL1 , & ctrl1 );
514+ if (ret )
515+ return IRQ_NONE ;
516+
443517 ret = regmap_read (pcf2127 -> regmap , PCF2127_REG_CTRL2 , & ctrl2 );
444518 if (ret )
445519 return IRQ_NONE ;
446520
447- if (!(ctrl2 & PCF2127_BIT_CTRL2_AF ))
521+ if (!(ctrl1 & PCF2127_CTRL1_IRQ_MASK || ctrl2 & PCF2127_CTRL2_IRQ_MASK ))
448522 return IRQ_NONE ;
449523
450- regmap_write (pcf2127 -> regmap , PCF2127_REG_CTRL2 ,
451- ctrl2 & ~(PCF2127_BIT_CTRL2_AF | PCF2127_BIT_CTRL2_WDTF ));
524+ if (ctrl1 & PCF2127_BIT_CTRL1_TSF1 || ctrl2 & PCF2127_BIT_CTRL2_TSF2 )
525+ pcf2127_rtc_ts_snapshot (dev );
526+
527+ if (ctrl1 & PCF2127_CTRL1_IRQ_MASK )
528+ regmap_write (pcf2127 -> regmap , PCF2127_REG_CTRL1 ,
529+ ctrl1 & ~PCF2127_CTRL1_IRQ_MASK );
530+
531+ if (ctrl2 & PCF2127_CTRL2_IRQ_MASK )
532+ regmap_write (pcf2127 -> regmap , PCF2127_REG_CTRL2 ,
533+ ctrl2 & ~PCF2127_CTRL2_IRQ_MASK );
452534
453- rtc_update_irq (pcf2127 -> rtc , 1 , RTC_IRQF | RTC_AF );
535+ if (ctrl2 & PCF2127_BIT_CTRL2_AF )
536+ rtc_update_irq (pcf2127 -> rtc , 1 , RTC_IRQF | RTC_AF );
454537
455538 pcf2127_wdt_active_ping (& pcf2127 -> wdd );
456539
@@ -475,23 +558,27 @@ static ssize_t timestamp0_store(struct device *dev,
475558 struct pcf2127 * pcf2127 = dev_get_drvdata (dev -> parent );
476559 int ret ;
477560
478- ret = regmap_update_bits (pcf2127 -> regmap , PCF2127_REG_CTRL1 ,
479- PCF2127_BIT_CTRL1_TSF1 , 0 );
480- if (ret ) {
481- dev_err (dev , "%s: update ctrl1 ret=%d\n" , __func__ , ret );
482- return ret ;
483- }
561+ if (pcf2127 -> irq_enabled ) {
562+ pcf2127 -> ts_valid = false;
563+ } else {
564+ ret = regmap_update_bits (pcf2127 -> regmap , PCF2127_REG_CTRL1 ,
565+ PCF2127_BIT_CTRL1_TSF1 , 0 );
566+ if (ret ) {
567+ dev_err (dev , "%s: update ctrl1 ret=%d\n" , __func__ , ret );
568+ return ret ;
569+ }
484570
485- ret = regmap_update_bits (pcf2127 -> regmap , PCF2127_REG_CTRL2 ,
486- PCF2127_BIT_CTRL2_TSF2 , 0 );
487- if (ret ) {
488- dev_err (dev , "%s: update ctrl2 ret=%d\n" , __func__ , ret );
489- return ret ;
490- }
571+ ret = regmap_update_bits (pcf2127 -> regmap , PCF2127_REG_CTRL2 ,
572+ PCF2127_BIT_CTRL2_TSF2 , 0 );
573+ if (ret ) {
574+ dev_err (dev , "%s: update ctrl2 ret=%d\n" , __func__ , ret );
575+ return ret ;
576+ }
491577
492- ret = pcf2127_wdt_active_ping (& pcf2127 -> wdd );
493- if (ret )
494- return ret ;
578+ ret = pcf2127_wdt_active_ping (& pcf2127 -> wdd );
579+ if (ret )
580+ return ret ;
581+ }
495582
496583 return count ;
497584};
@@ -500,50 +587,36 @@ static ssize_t timestamp0_show(struct device *dev,
500587 struct device_attribute * attr , char * buf )
501588{
502589 struct pcf2127 * pcf2127 = dev_get_drvdata (dev -> parent );
503- struct rtc_time tm ;
590+ unsigned int ctrl1 , ctrl2 ;
504591 int ret ;
505- unsigned char data [25 ];
506-
507- ret = regmap_bulk_read (pcf2127 -> regmap , PCF2127_REG_CTRL1 , data ,
508- sizeof (data ));
509- if (ret ) {
510- dev_err (dev , "%s: read error ret=%d\n" , __func__ , ret );
511- return ret ;
512- }
513-
514- dev_dbg (dev ,
515- "%s: raw data is cr1=%02x, cr2=%02x, cr3=%02x, ts_sc=%02x, "
516- "ts_mn=%02x, ts_hr=%02x, ts_dm=%02x, ts_mo=%02x, ts_yr=%02x\n" ,
517- __func__ , data [PCF2127_REG_CTRL1 ], data [PCF2127_REG_CTRL2 ],
518- data [PCF2127_REG_CTRL3 ], data [PCF2127_REG_TS_SC ],
519- data [PCF2127_REG_TS_MN ], data [PCF2127_REG_TS_HR ],
520- data [PCF2127_REG_TS_DM ], data [PCF2127_REG_TS_MO ],
521- data [PCF2127_REG_TS_YR ]);
592+ time64_t ts ;
593+
594+ if (pcf2127 -> irq_enabled ) {
595+ if (!pcf2127 -> ts_valid )
596+ return 0 ;
597+ ts = pcf2127 -> ts ;
598+ } else {
599+ ret = regmap_read (pcf2127 -> regmap , PCF2127_REG_CTRL1 , & ctrl1 );
600+ if (ret )
601+ return 0 ;
522602
523- ret = pcf2127_wdt_active_ping ( & pcf2127 -> wdd );
524- if (ret )
525- return ret ;
603+ ret = regmap_read ( pcf2127 -> regmap , PCF2127_REG_CTRL2 , & ctrl2 );
604+ if (ret )
605+ return 0 ;
526606
527- if (!(data [ PCF2127_REG_CTRL1 ] & PCF2127_BIT_CTRL1_TSF1 ) &&
528- !(data [ PCF2127_REG_CTRL2 ] & PCF2127_BIT_CTRL2_TSF2 ))
529- return 0 ;
607+ if (!(ctrl1 & PCF2127_BIT_CTRL1_TSF1 ) &&
608+ !(ctrl2 & PCF2127_BIT_CTRL2_TSF2 ))
609+ return 0 ;
530610
531- tm .tm_sec = bcd2bin (data [PCF2127_REG_TS_SC ] & 0x7F );
532- tm .tm_min = bcd2bin (data [PCF2127_REG_TS_MN ] & 0x7F );
533- tm .tm_hour = bcd2bin (data [PCF2127_REG_TS_HR ] & 0x3F );
534- tm .tm_mday = bcd2bin (data [PCF2127_REG_TS_DM ] & 0x3F );
535- /* TS_MO register (month) value range: 1-12 */
536- tm .tm_mon = bcd2bin (data [PCF2127_REG_TS_MO ] & 0x1F ) - 1 ;
537- tm .tm_year = bcd2bin (data [PCF2127_REG_TS_YR ]);
538- if (tm .tm_year < 70 )
539- tm .tm_year += 100 ; /* assume we are in 1970...2069 */
540-
541- ret = rtc_valid_tm (& tm );
542- if (ret )
543- return ret ;
611+ ret = pcf2127_rtc_ts_read (dev -> parent , & ts );
612+ if (ret )
613+ return 0 ;
544614
545- return sprintf (buf , "%llu\n" ,
546- (unsigned long long )rtc_tm_to_time64 (& tm ));
615+ ret = pcf2127_wdt_active_ping (& pcf2127 -> wdd );
616+ if (ret )
617+ return ret ;
618+ }
619+ return sprintf (buf , "%llu\n" , (unsigned long long )ts );
547620};
548621
549622static DEVICE_ATTR_RW (timestamp0 );
@@ -594,6 +667,7 @@ static int pcf2127_probe(struct device *dev, struct regmap *regmap,
594667 dev_err (dev , "failed to request alarm irq\n" );
595668 return ret ;
596669 }
670+ pcf2127 -> irq_enabled = true;
597671 }
598672
599673 if (alarm_irq > 0 || device_property_read_bool (dev , "wakeup-source" )) {
0 commit comments