rtc-pcf2127.c (3d715ebaf006bd5a495e9a717cf0fc5c260ee738) rtc-pcf2127.c (adb9675d74e403537150f025ed2b7a2e1ed0a7b4)
1// SPDX-License-Identifier: GPL-2.0-only
2/*
3 * An I2C and SPI driver for the NXP PCF2127/29/31 RTC
4 * Copyright 2013 Til-Technologies
5 *
6 * Author: Renaud Cerrato <r.cerrato@til-technologies.fr>
7 *
8 * Watchdog and tamper functions

--- 66 unchanged lines hidden (view full) ---

75 * PCF2129/31 doesn't have this feature.
76 */
77#define PCF2127_REG_RAM_ADDR_MSB 0x1A
78#define PCF2127_REG_RAM_WRT_CMD 0x1C
79#define PCF2127_REG_RAM_RD_CMD 0x1D
80
81/* Watchdog timer value constants */
82#define PCF2127_WD_VAL_STOP 0
1// SPDX-License-Identifier: GPL-2.0-only
2/*
3 * An I2C and SPI driver for the NXP PCF2127/29/31 RTC
4 * Copyright 2013 Til-Technologies
5 *
6 * Author: Renaud Cerrato <r.cerrato@til-technologies.fr>
7 *
8 * Watchdog and tamper functions

--- 66 unchanged lines hidden (view full) ---

75 * PCF2129/31 doesn't have this feature.
76 */
77#define PCF2127_REG_RAM_ADDR_MSB 0x1A
78#define PCF2127_REG_RAM_WRT_CMD 0x1C
79#define PCF2127_REG_RAM_RD_CMD 0x1D
80
81/* Watchdog timer value constants */
82#define PCF2127_WD_VAL_STOP 0
83#define PCF2127_WD_VAL_MIN 2
84#define PCF2127_WD_VAL_MAX 255
85#define PCF2127_WD_VAL_DEFAULT 60
83/* PCF2127/29 watchdog timer value constants */
84#define PCF2127_WD_CLOCK_HZ_X1000 1000 /* 1Hz */
85#define PCF2127_WD_MIN_HW_HEARTBEAT_MS 500
86/* PCF2131 watchdog timer value constants */
87#define PCF2131_WD_CLOCK_HZ_X1000 250 /* 1/4Hz */
88#define PCF2131_WD_MIN_HW_HEARTBEAT_MS 4000
86
89
90#define PCF2127_WD_DEFAULT_TIMEOUT_S 60
91
87/* Mask for currently enabled interrupts */
88#define PCF2127_CTRL1_IRQ_MASK (PCF2127_BIT_CTRL1_TSF1)
89#define PCF2127_CTRL2_IRQ_MASK ( \
90 PCF2127_BIT_CTRL2_AF | \
91 PCF2127_BIT_CTRL2_WDTF | \
92 PCF2127_BIT_CTRL2_TSF2)
93
94#define PCF2127_MAX_TS_SUPPORTED 4

--- 86 unchanged lines hidden (view full) ---

181 unsigned int has_nvmem:1;
182 unsigned int has_bit_wd_ctl_cd0:1;
183 unsigned int has_int_a_b:1; /* PCF2131 supports two interrupt outputs. */
184 u8 reg_time_base; /* Time/date base register. */
185 u8 regs_alarm_base; /* Alarm function base registers. */
186 u8 reg_wd_ctl; /* Watchdog control register. */
187 u8 reg_wd_val; /* Watchdog value register. */
188 u8 reg_clkout; /* Clkout register. */
92/* Mask for currently enabled interrupts */
93#define PCF2127_CTRL1_IRQ_MASK (PCF2127_BIT_CTRL1_TSF1)
94#define PCF2127_CTRL2_IRQ_MASK ( \
95 PCF2127_BIT_CTRL2_AF | \
96 PCF2127_BIT_CTRL2_WDTF | \
97 PCF2127_BIT_CTRL2_TSF2)
98
99#define PCF2127_MAX_TS_SUPPORTED 4

--- 86 unchanged lines hidden (view full) ---

186 unsigned int has_nvmem:1;
187 unsigned int has_bit_wd_ctl_cd0:1;
188 unsigned int has_int_a_b:1; /* PCF2131 supports two interrupt outputs. */
189 u8 reg_time_base; /* Time/date base register. */
190 u8 regs_alarm_base; /* Alarm function base registers. */
191 u8 reg_wd_ctl; /* Watchdog control register. */
192 u8 reg_wd_val; /* Watchdog value register. */
193 u8 reg_clkout; /* Clkout register. */
194 int wdd_clock_hz_x1000; /* Watchdog clock in Hz multiplicated by 1000 */
195 int wdd_min_hw_heartbeat_ms;
189 unsigned int ts_count;
190 struct pcf21xx_ts_config ts[PCF2127_MAX_TS_SUPPORTED];
191 struct attribute_group attribute_group;
192};
193
194struct pcf2127 {
195 struct rtc_device *rtc;
196 struct watchdog_device wdd;

--- 187 unchanged lines hidden (view full) ---

384 return regmap_bulk_write(pcf2127->regmap, PCF2127_REG_RAM_WRT_CMD,
385 val, bytes);
386}
387
388/* watchdog driver */
389
390static int pcf2127_wdt_ping(struct watchdog_device *wdd)
391{
196 unsigned int ts_count;
197 struct pcf21xx_ts_config ts[PCF2127_MAX_TS_SUPPORTED];
198 struct attribute_group attribute_group;
199};
200
201struct pcf2127 {
202 struct rtc_device *rtc;
203 struct watchdog_device wdd;

--- 187 unchanged lines hidden (view full) ---

391 return regmap_bulk_write(pcf2127->regmap, PCF2127_REG_RAM_WRT_CMD,
392 val, bytes);
393}
394
395/* watchdog driver */
396
397static int pcf2127_wdt_ping(struct watchdog_device *wdd)
398{
399 int wd_val;
392 struct pcf2127 *pcf2127 = watchdog_get_drvdata(wdd);
393
400 struct pcf2127 *pcf2127 = watchdog_get_drvdata(wdd);
401
394 return regmap_write(pcf2127->regmap, pcf2127->cfg->reg_wd_val, wdd->timeout);
402 /*
403 * Compute counter value of WATCHDG_TIM_VAL to obtain desired period
404 * in seconds, depending on the source clock frequency.
405 */
406 wd_val = ((wdd->timeout * pcf2127->cfg->wdd_clock_hz_x1000) / 1000) + 1;
407
408 return regmap_write(pcf2127->regmap, pcf2127->cfg->reg_wd_val, wd_val);
395}
396
397/*
398 * Restart watchdog timer if feature is active.
399 *
400 * Note: Reading CTRL2 register causes watchdog to stop which is unfortunate,
401 * since register also contain control/status flags for other features.
402 * Always call this function after reading CTRL2 register.

--- 45 unchanged lines hidden (view full) ---

448static const struct watchdog_ops pcf2127_watchdog_ops = {
449 .owner = THIS_MODULE,
450 .start = pcf2127_wdt_start,
451 .stop = pcf2127_wdt_stop,
452 .ping = pcf2127_wdt_ping,
453 .set_timeout = pcf2127_wdt_set_timeout,
454};
455
409}
410
411/*
412 * Restart watchdog timer if feature is active.
413 *
414 * Note: Reading CTRL2 register causes watchdog to stop which is unfortunate,
415 * since register also contain control/status flags for other features.
416 * Always call this function after reading CTRL2 register.

--- 45 unchanged lines hidden (view full) ---

462static const struct watchdog_ops pcf2127_watchdog_ops = {
463 .owner = THIS_MODULE,
464 .start = pcf2127_wdt_start,
465 .stop = pcf2127_wdt_stop,
466 .ping = pcf2127_wdt_ping,
467 .set_timeout = pcf2127_wdt_set_timeout,
468};
469
470/*
471 * Compute watchdog period, t, in seconds, from the WATCHDG_TIM_VAL register
472 * value, n, and the clock frequency, f1000, in Hz x 1000.
473 *
474 * The PCF2127/29 datasheet gives t as:
475 * t = n / f
476 * The PCF2131 datasheet gives t as:
477 * t = (n - 1) / f
478 * For both variants, the watchdog is triggered when the WATCHDG_TIM_VAL reaches
479 * the value 1, and not zero. Consequently, the equation from the PCF2131
480 * datasheet seems to be the correct one for both variants.
481 */
482static int pcf2127_watchdog_get_period(int n, int f1000)
483{
484 return (1000 * (n - 1)) / f1000;
485}
486
456static int pcf2127_watchdog_init(struct device *dev, struct pcf2127 *pcf2127)
457{
458 u32 wdd_timeout;
459 int ret;
460
461 if (!IS_ENABLED(CONFIG_WATCHDOG) ||
462 !device_property_read_bool(dev, "reset-source"))
463 return 0;
464
465 pcf2127->wdd.parent = dev;
466 pcf2127->wdd.info = &pcf2127_wdt_info;
467 pcf2127->wdd.ops = &pcf2127_watchdog_ops;
487static int pcf2127_watchdog_init(struct device *dev, struct pcf2127 *pcf2127)
488{
489 u32 wdd_timeout;
490 int ret;
491
492 if (!IS_ENABLED(CONFIG_WATCHDOG) ||
493 !device_property_read_bool(dev, "reset-source"))
494 return 0;
495
496 pcf2127->wdd.parent = dev;
497 pcf2127->wdd.info = &pcf2127_wdt_info;
498 pcf2127->wdd.ops = &pcf2127_watchdog_ops;
468 pcf2127->wdd.min_timeout = PCF2127_WD_VAL_MIN;
469 pcf2127->wdd.max_timeout = PCF2127_WD_VAL_MAX;
470 pcf2127->wdd.timeout = PCF2127_WD_VAL_DEFAULT;
471 pcf2127->wdd.min_hw_heartbeat_ms = 500;
499
500 pcf2127->wdd.min_timeout =
501 pcf2127_watchdog_get_period(
502 2, pcf2127->cfg->wdd_clock_hz_x1000);
503 pcf2127->wdd.max_timeout =
504 pcf2127_watchdog_get_period(
505 255, pcf2127->cfg->wdd_clock_hz_x1000);
506 pcf2127->wdd.timeout = PCF2127_WD_DEFAULT_TIMEOUT_S;
507
508 dev_dbg(dev, "%s clock = %d Hz / 1000\n", __func__,
509 pcf2127->cfg->wdd_clock_hz_x1000);
510
511 pcf2127->wdd.min_hw_heartbeat_ms = pcf2127->cfg->wdd_min_hw_heartbeat_ms;
472 pcf2127->wdd.status = WATCHDOG_NOWAYOUT_INIT_STATUS;
473
474 watchdog_set_drvdata(&pcf2127->wdd, pcf2127);
475
476 /* Test if watchdog timer is started by bootloader */
477 ret = regmap_read(pcf2127->regmap, pcf2127->cfg->reg_wd_val, &wdd_timeout);
478 if (ret)
479 return ret;

--- 400 unchanged lines hidden (view full) ---

880 .has_nvmem = 1,
881 .has_bit_wd_ctl_cd0 = 1,
882 .has_int_a_b = 0,
883 .reg_time_base = PCF2127_REG_TIME_BASE,
884 .regs_alarm_base = PCF2127_REG_ALARM_BASE,
885 .reg_wd_ctl = PCF2127_REG_WD_CTL,
886 .reg_wd_val = PCF2127_REG_WD_VAL,
887 .reg_clkout = PCF2127_REG_CLKOUT,
512 pcf2127->wdd.status = WATCHDOG_NOWAYOUT_INIT_STATUS;
513
514 watchdog_set_drvdata(&pcf2127->wdd, pcf2127);
515
516 /* Test if watchdog timer is started by bootloader */
517 ret = regmap_read(pcf2127->regmap, pcf2127->cfg->reg_wd_val, &wdd_timeout);
518 if (ret)
519 return ret;

--- 400 unchanged lines hidden (view full) ---

920 .has_nvmem = 1,
921 .has_bit_wd_ctl_cd0 = 1,
922 .has_int_a_b = 0,
923 .reg_time_base = PCF2127_REG_TIME_BASE,
924 .regs_alarm_base = PCF2127_REG_ALARM_BASE,
925 .reg_wd_ctl = PCF2127_REG_WD_CTL,
926 .reg_wd_val = PCF2127_REG_WD_VAL,
927 .reg_clkout = PCF2127_REG_CLKOUT,
928 .wdd_clock_hz_x1000 = PCF2127_WD_CLOCK_HZ_X1000,
929 .wdd_min_hw_heartbeat_ms = PCF2127_WD_MIN_HW_HEARTBEAT_MS,
888 .ts_count = 1,
889 .ts[0] = {
890 .reg_base = PCF2127_REG_TS1_BASE,
891 .gnd_detect_reg = PCF2127_REG_CTRL1,
892 .gnd_detect_bit = PCF2127_BIT_CTRL1_TSF1,
893 .inter_detect_reg = PCF2127_REG_CTRL2,
894 .inter_detect_bit = PCF2127_BIT_CTRL2_TSF2,
895 .ie_reg = PCF2127_REG_CTRL2,

--- 9 unchanged lines hidden (view full) ---

905 .has_nvmem = 0,
906 .has_bit_wd_ctl_cd0 = 0,
907 .has_int_a_b = 0,
908 .reg_time_base = PCF2127_REG_TIME_BASE,
909 .regs_alarm_base = PCF2127_REG_ALARM_BASE,
910 .reg_wd_ctl = PCF2127_REG_WD_CTL,
911 .reg_wd_val = PCF2127_REG_WD_VAL,
912 .reg_clkout = PCF2127_REG_CLKOUT,
930 .ts_count = 1,
931 .ts[0] = {
932 .reg_base = PCF2127_REG_TS1_BASE,
933 .gnd_detect_reg = PCF2127_REG_CTRL1,
934 .gnd_detect_bit = PCF2127_BIT_CTRL1_TSF1,
935 .inter_detect_reg = PCF2127_REG_CTRL2,
936 .inter_detect_bit = PCF2127_BIT_CTRL2_TSF2,
937 .ie_reg = PCF2127_REG_CTRL2,

--- 9 unchanged lines hidden (view full) ---

947 .has_nvmem = 0,
948 .has_bit_wd_ctl_cd0 = 0,
949 .has_int_a_b = 0,
950 .reg_time_base = PCF2127_REG_TIME_BASE,
951 .regs_alarm_base = PCF2127_REG_ALARM_BASE,
952 .reg_wd_ctl = PCF2127_REG_WD_CTL,
953 .reg_wd_val = PCF2127_REG_WD_VAL,
954 .reg_clkout = PCF2127_REG_CLKOUT,
955 .wdd_clock_hz_x1000 = PCF2127_WD_CLOCK_HZ_X1000,
956 .wdd_min_hw_heartbeat_ms = PCF2127_WD_MIN_HW_HEARTBEAT_MS,
913 .ts_count = 1,
914 .ts[0] = {
915 .reg_base = PCF2127_REG_TS1_BASE,
916 .gnd_detect_reg = PCF2127_REG_CTRL1,
917 .gnd_detect_bit = PCF2127_BIT_CTRL1_TSF1,
918 .inter_detect_reg = PCF2127_REG_CTRL2,
919 .inter_detect_bit = PCF2127_BIT_CTRL2_TSF2,
920 .ie_reg = PCF2127_REG_CTRL2,

--- 9 unchanged lines hidden (view full) ---

930 .has_nvmem = 0,
931 .has_bit_wd_ctl_cd0 = 0,
932 .has_int_a_b = 1,
933 .reg_time_base = PCF2131_REG_TIME_BASE,
934 .regs_alarm_base = PCF2131_REG_ALARM_BASE,
935 .reg_wd_ctl = PCF2131_REG_WD_CTL,
936 .reg_wd_val = PCF2131_REG_WD_VAL,
937 .reg_clkout = PCF2131_REG_CLKOUT,
957 .ts_count = 1,
958 .ts[0] = {
959 .reg_base = PCF2127_REG_TS1_BASE,
960 .gnd_detect_reg = PCF2127_REG_CTRL1,
961 .gnd_detect_bit = PCF2127_BIT_CTRL1_TSF1,
962 .inter_detect_reg = PCF2127_REG_CTRL2,
963 .inter_detect_bit = PCF2127_BIT_CTRL2_TSF2,
964 .ie_reg = PCF2127_REG_CTRL2,

--- 9 unchanged lines hidden (view full) ---

974 .has_nvmem = 0,
975 .has_bit_wd_ctl_cd0 = 0,
976 .has_int_a_b = 1,
977 .reg_time_base = PCF2131_REG_TIME_BASE,
978 .regs_alarm_base = PCF2131_REG_ALARM_BASE,
979 .reg_wd_ctl = PCF2131_REG_WD_CTL,
980 .reg_wd_val = PCF2131_REG_WD_VAL,
981 .reg_clkout = PCF2131_REG_CLKOUT,
982 .wdd_clock_hz_x1000 = PCF2131_WD_CLOCK_HZ_X1000,
983 .wdd_min_hw_heartbeat_ms = PCF2131_WD_MIN_HW_HEARTBEAT_MS,
938 .ts_count = 4,
939 .ts[0] = {
940 .reg_base = PCF2131_REG_TS1_BASE,
941 .gnd_detect_reg = PCF2131_REG_CTRL4,
942 .gnd_detect_bit = PCF2131_BIT_CTRL4_TSF1,
943 .inter_detect_bit = 0,
944 .ie_reg = PCF2131_REG_CTRL5,
945 .ie_bit = PCF2131_BIT_CTRL5_TSIE1,

--- 197 unchanged lines hidden (view full) ---

1143 if (ret < 0)
1144 return ret;
1145
1146 msleep(100);
1147 }
1148
1149 /*
1150 * Watchdog timer enabled and reset pin /RST activated when timed out.
984 .ts_count = 4,
985 .ts[0] = {
986 .reg_base = PCF2131_REG_TS1_BASE,
987 .gnd_detect_reg = PCF2131_REG_CTRL4,
988 .gnd_detect_bit = PCF2131_BIT_CTRL4_TSF1,
989 .inter_detect_bit = 0,
990 .ie_reg = PCF2131_REG_CTRL5,
991 .ie_bit = PCF2131_BIT_CTRL5_TSIE1,

--- 197 unchanged lines hidden (view full) ---

1189 if (ret < 0)
1190 return ret;
1191
1192 msleep(100);
1193 }
1194
1195 /*
1196 * Watchdog timer enabled and reset pin /RST activated when timed out.
1151 * Select 1Hz clock source for watchdog timer.
1197 * Select 1Hz clock source for watchdog timer (1/4Hz for PCF2131).
1152 * Note: Countdown timer disabled and not available.
1153 * For pca2129, pcf2129 and pcf2131, only bit[7] is for Symbol WD_CD
1154 * of register watchdg_tim_ctl. The bit[6] is labeled
1155 * as T. Bits labeled as T must always be written with
1156 * logic 0.
1157 */
1158 ret = regmap_update_bits(pcf2127->regmap, pcf2127->cfg->reg_wd_ctl,
1159 PCF2127_BIT_WD_CTL_CD1 |

--- 330 unchanged lines hidden ---
1198 * Note: Countdown timer disabled and not available.
1199 * For pca2129, pcf2129 and pcf2131, only bit[7] is for Symbol WD_CD
1200 * of register watchdg_tim_ctl. The bit[6] is labeled
1201 * as T. Bits labeled as T must always be written with
1202 * logic 0.
1203 */
1204 ret = regmap_update_bits(pcf2127->regmap, pcf2127->cfg->reg_wd_ctl,
1205 PCF2127_BIT_WD_CTL_CD1 |

--- 330 unchanged lines hidden ---