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