2020#include <linux/slab.h>
2121#include <linux/module.h>
2222#include <linux/of.h>
23+ #include <linux/of_irq.h>
2324#include <linux/regmap.h>
2425#include <linux/watchdog.h>
2526
2829#define PCF2127_BIT_CTRL1_TSF1 BIT(4)
2930/* Control register 2 */
3031#define PCF2127_REG_CTRL2 0x01
32+ #define PCF2127_BIT_CTRL2_AIE BIT(1)
3133#define PCF2127_BIT_CTRL2_TSIE BIT(2)
34+ #define PCF2127_BIT_CTRL2_AF BIT(4)
3235#define PCF2127_BIT_CTRL2_TSF2 BIT(5)
3336/* Control register 3 */
3437#define PCF2127_REG_CTRL3 0x02
4649#define PCF2127_REG_DW 0x07
4750#define PCF2127_REG_MO 0x08
4851#define PCF2127_REG_YR 0x09
52+ /* Alarm registers */
53+ #define PCF2127_REG_ALARM_SC 0x0A
54+ #define PCF2127_REG_ALARM_MN 0x0B
55+ #define PCF2127_REG_ALARM_HR 0x0C
56+ #define PCF2127_REG_ALARM_DM 0x0D
57+ #define PCF2127_REG_ALARM_DW 0x0E
4958/* Watchdog registers */
5059#define PCF2127_REG_WD_CTL 0x10
5160#define PCF2127_BIT_WD_CTL_TF0 BIT(0)
@@ -324,6 +333,114 @@ static const struct watchdog_ops pcf2127_watchdog_ops = {
324333 .set_timeout = pcf2127_wdt_set_timeout ,
325334};
326335
336+ /* Alarm */
337+ static int pcf2127_rtc_read_alarm (struct device * dev , struct rtc_wkalrm * alrm )
338+ {
339+ struct pcf2127 * pcf2127 = dev_get_drvdata (dev );
340+ unsigned int buf [5 ], ctrl2 ;
341+ int ret ;
342+
343+ ret = regmap_read (pcf2127 -> regmap , PCF2127_REG_CTRL2 , & ctrl2 );
344+ if (ret )
345+ return ret ;
346+
347+ ret = pcf2127_wdt_active_ping (& pcf2127 -> wdd );
348+ if (ret )
349+ return ret ;
350+
351+ ret = regmap_bulk_read (pcf2127 -> regmap , PCF2127_REG_ALARM_SC , buf ,
352+ sizeof (buf ));
353+ if (ret )
354+ return ret ;
355+
356+ alrm -> enabled = ctrl2 & PCF2127_BIT_CTRL2_AIE ;
357+ alrm -> pending = ctrl2 & PCF2127_BIT_CTRL2_AF ;
358+
359+ alrm -> time .tm_sec = bcd2bin (buf [0 ] & 0x7F );
360+ alrm -> time .tm_min = bcd2bin (buf [1 ] & 0x7F );
361+ alrm -> time .tm_hour = bcd2bin (buf [2 ] & 0x3F );
362+ alrm -> time .tm_mday = bcd2bin (buf [3 ] & 0x3F );
363+ alrm -> time .tm_wday = buf [4 ] & 0x07 ;
364+
365+ return 0 ;
366+ }
367+
368+ static int pcf2127_rtc_alarm_irq_enable (struct device * dev , u32 enable )
369+ {
370+ struct pcf2127 * pcf2127 = dev_get_drvdata (dev );
371+ int ret ;
372+
373+ ret = regmap_update_bits (pcf2127 -> regmap , PCF2127_REG_CTRL2 ,
374+ PCF2127_BIT_CTRL2_AIE ,
375+ enable ? PCF2127_BIT_CTRL2_AIE : 0 );
376+ if (ret )
377+ return ret ;
378+
379+ return pcf2127_wdt_active_ping (& pcf2127 -> wdd );
380+ }
381+
382+ static int pcf2127_rtc_set_alarm (struct device * dev , struct rtc_wkalrm * alrm )
383+ {
384+ struct pcf2127 * pcf2127 = dev_get_drvdata (dev );
385+ uint8_t buf [5 ];
386+ int ret ;
387+
388+ ret = regmap_update_bits (pcf2127 -> regmap , PCF2127_REG_CTRL2 ,
389+ PCF2127_BIT_CTRL2_AF , 0 );
390+ if (ret )
391+ return ret ;
392+
393+ ret = pcf2127_wdt_active_ping (& pcf2127 -> wdd );
394+ if (ret )
395+ return ret ;
396+
397+ buf [0 ] = bin2bcd (alrm -> time .tm_sec );
398+ buf [1 ] = bin2bcd (alrm -> time .tm_min );
399+ buf [2 ] = bin2bcd (alrm -> time .tm_hour );
400+ buf [3 ] = bin2bcd (alrm -> time .tm_mday );
401+ buf [4 ] = (alrm -> time .tm_wday & 0x07 );
402+
403+ ret = regmap_bulk_write (pcf2127 -> regmap , PCF2127_REG_ALARM_SC , buf ,
404+ sizeof (buf ));
405+ if (ret )
406+ return ret ;
407+
408+ return pcf2127_rtc_alarm_irq_enable (dev , alrm -> enabled );
409+ }
410+
411+ static irqreturn_t pcf2127_rtc_irq (int irq , void * dev )
412+ {
413+ struct pcf2127 * pcf2127 = dev_get_drvdata (dev );
414+ unsigned int ctrl2 = 0 ;
415+ int ret = 0 ;
416+
417+ ret = regmap_read (pcf2127 -> regmap , PCF2127_REG_CTRL2 , & ctrl2 );
418+ if (ret )
419+ return IRQ_NONE ;
420+
421+ if (ctrl2 & PCF2127_BIT_CTRL2_AF ) {
422+ regmap_write (pcf2127 -> regmap , PCF2127_REG_CTRL2 ,
423+ ctrl2 & ~PCF2127_BIT_CTRL2_AF );
424+
425+ rtc_update_irq (pcf2127 -> rtc , 1 , RTC_IRQF | RTC_AF );
426+ }
427+
428+ ret = pcf2127_wdt_active_ping (& pcf2127 -> wdd );
429+ if (ret )
430+ return IRQ_NONE ;
431+
432+ return IRQ_HANDLED ;
433+ }
434+
435+ static const struct rtc_class_ops pcf2127_rtc_alrm_ops = {
436+ .ioctl = pcf2127_rtc_ioctl ,
437+ .read_time = pcf2127_rtc_read_time ,
438+ .set_time = pcf2127_rtc_set_time ,
439+ .read_alarm = pcf2127_rtc_read_alarm ,
440+ .set_alarm = pcf2127_rtc_set_alarm ,
441+ .alarm_irq_enable = pcf2127_rtc_alarm_irq_enable ,
442+ };
443+
327444/* sysfs interface */
328445
329446static ssize_t timestamp0_store (struct device * dev ,
@@ -419,6 +536,7 @@ static int pcf2127_probe(struct device *dev, struct regmap *regmap,
419536 const char * name , bool has_nvmem )
420537{
421538 struct pcf2127 * pcf2127 ;
539+ int alarm_irq = 0 ;
422540 u32 wdd_timeout ;
423541 int ret = 0 ;
424542
@@ -441,6 +559,22 @@ static int pcf2127_probe(struct device *dev, struct regmap *regmap,
441559 pcf2127 -> rtc -> range_max = RTC_TIMESTAMP_END_2099 ;
442560 pcf2127 -> rtc -> set_start_time = true; /* Sets actual start to 1970 */
443561
562+ alarm_irq = of_irq_get_byname (dev -> of_node , "alarm" );
563+ if (alarm_irq >= 0 ) {
564+ ret = devm_request_irq (dev , alarm_irq , pcf2127_rtc_irq ,
565+ IRQF_TRIGGER_LOW | IRQF_ONESHOT ,
566+ dev_name (dev ), dev );
567+ if (ret ) {
568+ dev_err (dev , "failed to request alarm irq\n" );
569+ return ret ;
570+ }
571+ }
572+
573+ if (alarm_irq >= 0 || device_property_read_bool (dev , "wakeup-source" )) {
574+ device_init_wakeup (dev , true);
575+ pcf2127 -> rtc -> ops = & pcf2127_rtc_alrm_ops ;
576+ }
577+
444578 pcf2127 -> wdd .parent = dev ;
445579 pcf2127 -> wdd .info = & pcf2127_wdt_info ;
446580 pcf2127 -> wdd .ops = & pcf2127_watchdog_ops ;
0 commit comments