1 /*
2  * SPDX-FileCopyrightText: 2018-2022 Espressif Systems (Shanghai) CO LTD
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 #include "rtc_wdt.h"
8 #include "soc/rtc.h"
9 #include "hal/efuse_ll.h"
10 
11 #if CONFIG_IDF_TARGET_ESP32 || CONFIG_IDF_TARGET_ESP32S2
12 
rtc_wdt_get_protect_status(void)13 bool rtc_wdt_get_protect_status(void)
14 {
15     return READ_PERI_REG(RTC_CNTL_WDTWPROTECT_REG) != RTC_CNTL_WDT_WKEY_VALUE;
16 }
17 
rtc_wdt_protect_off(void)18 void rtc_wdt_protect_off(void)
19 {
20     WRITE_PERI_REG(RTC_CNTL_WDTWPROTECT_REG, RTC_CNTL_WDT_WKEY_VALUE);
21 }
22 
rtc_wdt_protect_on(void)23 void rtc_wdt_protect_on(void)
24 {
25     WRITE_PERI_REG(RTC_CNTL_WDTWPROTECT_REG, 0);
26 }
27 
28 
rtc_wdt_enable(void)29 void rtc_wdt_enable(void)
30 {
31     REG_SET_BIT(RTC_CNTL_WDTFEED_REG, RTC_CNTL_WDT_FEED);
32     SET_PERI_REG_MASK(RTC_CNTL_WDTCONFIG0_REG, RTC_CNTL_WDT_EN | RTC_CNTL_WDT_PAUSE_IN_SLP);
33 }
34 
rtc_wdt_flashboot_mode_enable(void)35 void rtc_wdt_flashboot_mode_enable(void)
36 {
37     REG_SET_BIT(RTC_CNTL_WDTCONFIG0_REG, RTC_CNTL_WDT_FLASHBOOT_MOD_EN);
38 }
39 
rtc_wdt_disable(void)40 void rtc_wdt_disable(void)
41 {
42     bool protect = rtc_wdt_get_protect_status();
43     if (protect) {
44         rtc_wdt_protect_off();
45     }
46     REG_SET_BIT(RTC_CNTL_WDTFEED_REG, RTC_CNTL_WDT_FEED);
47     rtc_wdt_set_stage(RTC_WDT_STAGE0, RTC_WDT_STAGE_ACTION_OFF);
48     rtc_wdt_set_stage(RTC_WDT_STAGE1, RTC_WDT_STAGE_ACTION_OFF);
49     rtc_wdt_set_stage(RTC_WDT_STAGE2, RTC_WDT_STAGE_ACTION_OFF);
50     rtc_wdt_set_stage(RTC_WDT_STAGE3, RTC_WDT_STAGE_ACTION_OFF);
51     REG_CLR_BIT(RTC_CNTL_WDTCONFIG0_REG, RTC_CNTL_WDT_FLASHBOOT_MOD_EN);
52     REG_CLR_BIT(RTC_CNTL_WDTCONFIG0_REG, RTC_CNTL_WDT_EN);
53     if (protect) {
54         rtc_wdt_protect_on();
55     }
56 }
57 
rtc_wdt_feed(void)58 void rtc_wdt_feed(void)
59 {
60     bool protect = rtc_wdt_get_protect_status();
61     if (protect) {
62         rtc_wdt_protect_off();
63     }
64     REG_SET_BIT(RTC_CNTL_WDTFEED_REG, RTC_CNTL_WDT_FEED);
65     if (protect) {
66         rtc_wdt_protect_on();
67     }
68 }
69 
get_addr_reg(rtc_wdt_stage_t stage)70 static uint32_t get_addr_reg(rtc_wdt_stage_t stage)
71 {
72     uint32_t reg;
73     if (stage == RTC_WDT_STAGE0) {
74         reg = RTC_CNTL_WDTCONFIG1_REG;
75     } else if (stage == RTC_WDT_STAGE1) {
76         reg = RTC_CNTL_WDTCONFIG2_REG;
77     } else if (stage == RTC_WDT_STAGE2) {
78         reg = RTC_CNTL_WDTCONFIG3_REG;
79     } else {
80         reg = RTC_CNTL_WDTCONFIG4_REG;
81     }
82     return reg;
83 }
84 
rtc_wdt_set_time(rtc_wdt_stage_t stage,unsigned int timeout_ms)85 esp_err_t rtc_wdt_set_time(rtc_wdt_stage_t stage, unsigned int timeout_ms)
86 {
87     if (stage > 3) {
88         return ESP_ERR_INVALID_ARG;
89     }
90     uint32_t timeout = (uint32_t) ((uint64_t) rtc_clk_slow_freq_get_hz() * timeout_ms / 1000);
91 #if !CONFIG_IDF_TARGET_ESP32
92     if (stage == RTC_WDT_STAGE0) {
93         timeout = timeout >> (1 + efuse_ll_get_wdt_delay_sel());
94     }
95 #endif
96     WRITE_PERI_REG(get_addr_reg(stage), timeout);
97     return ESP_OK;
98 }
99 
rtc_wdt_get_timeout(rtc_wdt_stage_t stage,unsigned int * timeout_ms)100 esp_err_t rtc_wdt_get_timeout(rtc_wdt_stage_t stage, unsigned int *timeout_ms)
101 {
102     if (stage > 3) {
103         return ESP_ERR_INVALID_ARG;
104     }
105     uint32_t time_tick;
106     uint32_t rtc_slow_freq = rtc_clk_slow_freq_get_hz();
107     if (rtc_slow_freq == 0) {
108         return ESP_ERR_INVALID_STATE;
109     }
110     time_tick = READ_PERI_REG(get_addr_reg(stage));
111     *timeout_ms = time_tick * 1000 / rtc_slow_freq;
112 
113     return ESP_OK;
114 }
115 
rtc_wdt_set_stage(rtc_wdt_stage_t stage,rtc_wdt_stage_action_t stage_sel)116 esp_err_t rtc_wdt_set_stage(rtc_wdt_stage_t stage, rtc_wdt_stage_action_t stage_sel)
117 {
118     if (stage > 3 || stage_sel > 4) {
119         return ESP_ERR_INVALID_ARG;
120     }
121     if (stage == RTC_WDT_STAGE0) {
122         REG_SET_FIELD(RTC_CNTL_WDTCONFIG0_REG, RTC_CNTL_WDT_STG0, stage_sel);
123     } else if (stage == RTC_WDT_STAGE1) {
124         REG_SET_FIELD(RTC_CNTL_WDTCONFIG0_REG, RTC_CNTL_WDT_STG1, stage_sel);
125     } else if (stage == RTC_WDT_STAGE2) {
126         REG_SET_FIELD(RTC_CNTL_WDTCONFIG0_REG, RTC_CNTL_WDT_STG2, stage_sel);
127     } else {
128         REG_SET_FIELD(RTC_CNTL_WDTCONFIG0_REG, RTC_CNTL_WDT_STG3, stage_sel);
129     }
130 
131     return ESP_OK;
132 }
133 
rtc_wdt_set_length_of_reset_signal(rtc_wdt_reset_sig_t reset_src,rtc_wdt_length_sig_t reset_signal_length)134 esp_err_t rtc_wdt_set_length_of_reset_signal(rtc_wdt_reset_sig_t reset_src, rtc_wdt_length_sig_t reset_signal_length)
135 {
136     if (reset_src > 1 || reset_signal_length > 7) {
137         return ESP_ERR_INVALID_ARG;
138     }
139     if (reset_src == 0) {
140         REG_SET_FIELD(RTC_CNTL_WDTCONFIG0_REG, RTC_CNTL_WDT_SYS_RESET_LENGTH, reset_signal_length);
141     } else {
142         REG_SET_FIELD(RTC_CNTL_WDTCONFIG0_REG, RTC_CNTL_WDT_CPU_RESET_LENGTH, reset_signal_length);
143     }
144 
145     return ESP_OK;
146 }
147 
rtc_wdt_is_on(void)148 bool rtc_wdt_is_on(void)
149 {
150     return (REG_GET_BIT(RTC_CNTL_WDTCONFIG0_REG, RTC_CNTL_WDT_EN) != 0) || (REG_GET_BIT(RTC_CNTL_WDTCONFIG0_REG, RTC_CNTL_WDT_FLASHBOOT_MOD_EN) != 0);
151 }
152 
153 #endif // CONFIG_IDF_TARGET_ESP32 || CONFIG_IDF_TARGET_ESP32S2
154