20
20
#include <linux/slab.h>
21
21
#include <linux/module.h>
22
22
#include <linux/of.h>
23
+ #include <linux/of_irq.h>
23
24
#include <linux/regmap.h>
24
25
#include <linux/watchdog.h>
25
26
28
29
#define PCF2127_BIT_CTRL1_TSF1 BIT(4)
29
30
/* Control register 2 */
30
31
#define PCF2127_REG_CTRL2 0x01
32
+ #define PCF2127_BIT_CTRL2_AIE BIT(1)
31
33
#define PCF2127_BIT_CTRL2_TSIE BIT(2)
34
+ #define PCF2127_BIT_CTRL2_AF BIT(4)
32
35
#define PCF2127_BIT_CTRL2_TSF2 BIT(5)
33
36
/* Control register 3 */
34
37
#define PCF2127_REG_CTRL3 0x02
46
49
#define PCF2127_REG_DW 0x07
47
50
#define PCF2127_REG_MO 0x08
48
51
#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
49
58
/* Watchdog registers */
50
59
#define PCF2127_REG_WD_CTL 0x10
51
60
#define PCF2127_BIT_WD_CTL_TF0 BIT(0)
@@ -324,6 +333,114 @@ static const struct watchdog_ops pcf2127_watchdog_ops = {
324
333
.set_timeout = pcf2127_wdt_set_timeout ,
325
334
};
326
335
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
+
327
444
/* sysfs interface */
328
445
329
446
static ssize_t timestamp0_store (struct device * dev ,
@@ -419,6 +536,7 @@ static int pcf2127_probe(struct device *dev, struct regmap *regmap,
419
536
const char * name , bool has_nvmem )
420
537
{
421
538
struct pcf2127 * pcf2127 ;
539
+ int alarm_irq = 0 ;
422
540
u32 wdd_timeout ;
423
541
int ret = 0 ;
424
542
@@ -441,6 +559,22 @@ static int pcf2127_probe(struct device *dev, struct regmap *regmap,
441
559
pcf2127 -> rtc -> range_max = RTC_TIMESTAMP_END_2099 ;
442
560
pcf2127 -> rtc -> set_start_time = true; /* Sets actual start to 1970 */
443
561
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
+
444
578
pcf2127 -> wdd .parent = dev ;
445
579
pcf2127 -> wdd .info = & pcf2127_wdt_info ;
446
580
pcf2127 -> wdd .ops = & pcf2127_watchdog_ops ;
0 commit comments