1 /*
2  * SPDX-FileCopyrightText: 2019-2022 Espressif Systems (Shanghai) CO LTD
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 #include <zephyr/kernel.h>
8 
9 #include <string.h>
10 #include "esp_log.h"
11 #include "esp_err.h"
12 #include "esp_check.h"
13 #include "driver/rtc_io.h"
14 #include "hal/rtc_io_hal.h"
15 #include "soc/soc_caps.h"
16 
17 static const char __attribute__((__unused__)) *RTCIO_TAG = "RTCIO";
18 
19 extern int rtc_spinlock;
20 
21 #define RTCIO_ENTER_CRITICAL()    do { rtc_spinlock = irq_lock(); } while(0)
22 #define RTCIO_EXIT_CRITICAL()    irq_unlock(rtc_spinlock);
23 
24 #if SOC_RTCIO_INPUT_OUTPUT_SUPPORTED
25 
26 /*---------------------------------------------------------------
27                         RTC IO
28 ---------------------------------------------------------------*/
rtc_gpio_init(gpio_num_t gpio_num)29 esp_err_t rtc_gpio_init(gpio_num_t gpio_num)
30 {
31     ESP_RETURN_ON_FALSE(rtc_gpio_is_valid_gpio(gpio_num), ESP_ERR_INVALID_ARG, RTCIO_TAG, "RTCIO number error");
32     RTCIO_ENTER_CRITICAL();
33     rtcio_hal_function_select(rtc_io_number_get(gpio_num), RTCIO_FUNC_RTC);
34     RTCIO_EXIT_CRITICAL();
35 
36     return ESP_OK;
37 }
38 
rtc_gpio_deinit(gpio_num_t gpio_num)39 esp_err_t rtc_gpio_deinit(gpio_num_t gpio_num)
40 {
41     ESP_RETURN_ON_FALSE(rtc_gpio_is_valid_gpio(gpio_num), ESP_ERR_INVALID_ARG, RTCIO_TAG, "RTCIO number error");
42     RTCIO_ENTER_CRITICAL();
43     // Select Gpio as Digital Gpio
44     rtcio_hal_function_select(rtc_io_number_get(gpio_num), RTCIO_FUNC_DIGITAL);
45     RTCIO_EXIT_CRITICAL();
46 
47     return ESP_OK;
48 }
49 
rtc_gpio_set_level(gpio_num_t gpio_num,uint32_t level)50 esp_err_t rtc_gpio_set_level(gpio_num_t gpio_num, uint32_t level)
51 {
52     ESP_RETURN_ON_FALSE(rtc_gpio_is_valid_gpio(gpio_num), ESP_ERR_INVALID_ARG, RTCIO_TAG, "RTCIO number error");
53     RTCIO_ENTER_CRITICAL();
54     rtcio_hal_set_level(rtc_io_number_get(gpio_num), level);
55     RTCIO_EXIT_CRITICAL();
56 
57     return ESP_OK;
58 }
59 
rtc_gpio_get_level(gpio_num_t gpio_num)60 uint32_t rtc_gpio_get_level(gpio_num_t gpio_num)
61 {
62     ESP_RETURN_ON_FALSE(rtc_gpio_is_valid_gpio(gpio_num), ESP_ERR_INVALID_ARG, RTCIO_TAG, "RTCIO number error");
63     return rtcio_hal_get_level(rtc_io_number_get(gpio_num));
64 }
65 
rtc_gpio_set_drive_capability(gpio_num_t gpio_num,gpio_drive_cap_t strength)66 esp_err_t rtc_gpio_set_drive_capability(gpio_num_t gpio_num, gpio_drive_cap_t strength)
67 {
68     ESP_RETURN_ON_FALSE(rtc_gpio_is_valid_gpio(gpio_num), ESP_ERR_INVALID_ARG, RTCIO_TAG, "RTCIO number error");
69     ESP_RETURN_ON_FALSE(GPIO_IS_VALID_OUTPUT_GPIO(gpio_num), ESP_ERR_INVALID_ARG, RTCIO_TAG, "Output pad only");
70     ESP_RETURN_ON_FALSE(strength < GPIO_DRIVE_CAP_MAX, ESP_ERR_INVALID_ARG, RTCIO_TAG, "RTCIO drive capability error");
71     RTCIO_ENTER_CRITICAL();
72     rtcio_hal_set_drive_capability(rtc_io_number_get(gpio_num), strength);
73     RTCIO_EXIT_CRITICAL();
74 
75     return ESP_OK;
76 }
77 
rtc_gpio_get_drive_capability(gpio_num_t gpio_num,gpio_drive_cap_t * strength)78 esp_err_t rtc_gpio_get_drive_capability(gpio_num_t gpio_num, gpio_drive_cap_t *strength)
79 {
80     ESP_RETURN_ON_FALSE(rtc_gpio_is_valid_gpio(gpio_num), ESP_ERR_INVALID_ARG, RTCIO_TAG, "RTCIO number error");
81     ESP_RETURN_ON_FALSE(GPIO_IS_VALID_OUTPUT_GPIO(gpio_num), ESP_ERR_INVALID_ARG, RTCIO_TAG, "Output pad only");
82     ESP_RETURN_ON_FALSE(strength != NULL, ESP_ERR_INVALID_ARG, RTCIO_TAG, "GPIO drive pointer error");
83     *strength = (gpio_drive_cap_t)rtcio_hal_get_drive_capability(rtc_io_number_get(gpio_num));
84 
85     return ESP_OK;
86 }
87 
rtc_gpio_set_direction(gpio_num_t gpio_num,rtc_gpio_mode_t mode)88 esp_err_t rtc_gpio_set_direction(gpio_num_t gpio_num, rtc_gpio_mode_t mode)
89 {
90     ESP_RETURN_ON_FALSE(rtc_gpio_is_valid_gpio(gpio_num), ESP_ERR_INVALID_ARG, RTCIO_TAG, "RTCIO number error");
91     RTCIO_ENTER_CRITICAL();
92     rtcio_hal_set_direction(rtc_io_number_get(gpio_num), mode);
93     RTCIO_EXIT_CRITICAL();
94 
95     return ESP_OK;
96 }
97 
rtc_gpio_set_direction_in_sleep(gpio_num_t gpio_num,rtc_gpio_mode_t mode)98 esp_err_t rtc_gpio_set_direction_in_sleep(gpio_num_t gpio_num, rtc_gpio_mode_t mode)
99 {
100     ESP_RETURN_ON_FALSE(rtc_gpio_is_valid_gpio(gpio_num), ESP_ERR_INVALID_ARG, RTCIO_TAG, "RTCIO number error");
101     RTCIO_ENTER_CRITICAL();
102     rtcio_hal_set_direction_in_sleep(rtc_io_number_get(gpio_num), mode);
103     RTCIO_EXIT_CRITICAL();
104 
105     return ESP_OK;
106 }
107 
rtc_gpio_pullup_en(gpio_num_t gpio_num)108 esp_err_t rtc_gpio_pullup_en(gpio_num_t gpio_num)
109 {
110     ESP_RETURN_ON_FALSE(rtc_gpio_is_valid_gpio(gpio_num), ESP_ERR_INVALID_ARG, RTCIO_TAG, "RTCIO number error");
111     RTCIO_ENTER_CRITICAL();
112     rtcio_hal_pullup_enable(rtc_io_number_get(gpio_num));
113     RTCIO_EXIT_CRITICAL();
114 
115     return ESP_OK;
116 }
117 
rtc_gpio_pullup_dis(gpio_num_t gpio_num)118 esp_err_t rtc_gpio_pullup_dis(gpio_num_t gpio_num)
119 {
120     ESP_RETURN_ON_FALSE(rtc_gpio_is_valid_gpio(gpio_num), ESP_ERR_INVALID_ARG, RTCIO_TAG, "RTCIO number error");
121     RTCIO_ENTER_CRITICAL();
122     rtcio_hal_pullup_disable(rtc_io_number_get(gpio_num));
123     RTCIO_EXIT_CRITICAL();
124 
125     return ESP_OK;
126 }
127 
rtc_gpio_pulldown_en(gpio_num_t gpio_num)128 esp_err_t rtc_gpio_pulldown_en(gpio_num_t gpio_num)
129 {
130     ESP_RETURN_ON_FALSE(rtc_gpio_is_valid_gpio(gpio_num), ESP_ERR_INVALID_ARG, RTCIO_TAG, "RTCIO number error");
131     RTCIO_ENTER_CRITICAL();
132     rtcio_hal_pulldown_enable(rtc_io_number_get(gpio_num));
133     RTCIO_EXIT_CRITICAL();
134 
135     return ESP_OK;
136 }
137 
rtc_gpio_pulldown_dis(gpio_num_t gpio_num)138 esp_err_t rtc_gpio_pulldown_dis(gpio_num_t gpio_num)
139 {
140     ESP_RETURN_ON_FALSE(rtc_gpio_is_valid_gpio(gpio_num), ESP_ERR_INVALID_ARG, RTCIO_TAG, "RTCIO number error");
141     RTCIO_ENTER_CRITICAL();
142     rtcio_hal_pulldown_disable(rtc_io_number_get(gpio_num));
143     RTCIO_EXIT_CRITICAL();
144 
145     return ESP_OK;
146 }
147 
148 #endif // SOC_RTCIO_INPUT_OUTPUT_SUPPORTED
149 
150 #if SOC_RTCIO_HOLD_SUPPORTED
151 
rtc_gpio_hold_en(gpio_num_t gpio_num)152 esp_err_t rtc_gpio_hold_en(gpio_num_t gpio_num)
153 {
154     ESP_RETURN_ON_FALSE(rtc_gpio_is_valid_gpio(gpio_num), ESP_ERR_INVALID_ARG, RTCIO_TAG, "RTCIO number error");
155     RTCIO_ENTER_CRITICAL();
156     rtcio_hal_hold_enable(rtc_io_number_get(gpio_num));
157     RTCIO_EXIT_CRITICAL();
158     return ESP_OK;
159 }
160 
rtc_gpio_hold_dis(gpio_num_t gpio_num)161 esp_err_t rtc_gpio_hold_dis(gpio_num_t gpio_num)
162 {
163     ESP_RETURN_ON_FALSE(rtc_gpio_is_valid_gpio(gpio_num), ESP_ERR_INVALID_ARG, RTCIO_TAG, "RTCIO number error");
164     RTCIO_ENTER_CRITICAL();
165     rtcio_hal_hold_disable(rtc_io_number_get(gpio_num));
166     RTCIO_EXIT_CRITICAL();
167     return ESP_OK;
168 }
169 
rtc_gpio_isolate(gpio_num_t gpio_num)170 esp_err_t rtc_gpio_isolate(gpio_num_t gpio_num)
171 {
172     ESP_RETURN_ON_FALSE(rtc_gpio_is_valid_gpio(gpio_num), ESP_ERR_INVALID_ARG, RTCIO_TAG, "RTCIO number error");
173     RTCIO_ENTER_CRITICAL();
174     rtcio_hal_isolate(rtc_io_number_get(gpio_num));
175     RTCIO_EXIT_CRITICAL();
176 
177     return ESP_OK;
178 }
179 
rtc_gpio_force_hold_en_all(void)180 esp_err_t rtc_gpio_force_hold_en_all(void)
181 {
182     RTCIO_ENTER_CRITICAL();
183     rtcio_hal_hold_all();
184     RTCIO_EXIT_CRITICAL();
185 
186     return ESP_OK;
187 }
188 
rtc_gpio_force_hold_dis_all(void)189 esp_err_t rtc_gpio_force_hold_dis_all(void)
190 {
191     RTCIO_ENTER_CRITICAL();
192     rtcio_hal_unhold_all();
193     RTCIO_EXIT_CRITICAL();
194 
195     return ESP_OK;
196 }
197 #endif // SOC_RTCIO_HOLD_SUPPORTED
198 
199 #if SOC_RTCIO_WAKE_SUPPORTED
200 
rtc_gpio_wakeup_enable(gpio_num_t gpio_num,gpio_int_type_t intr_type)201 esp_err_t rtc_gpio_wakeup_enable(gpio_num_t gpio_num, gpio_int_type_t intr_type)
202 {
203     ESP_RETURN_ON_FALSE(rtc_gpio_is_valid_gpio(gpio_num), ESP_ERR_INVALID_ARG, RTCIO_TAG, "RTCIO number error");
204     if (intr_type == GPIO_INTR_POSEDGE || intr_type == GPIO_INTR_NEGEDGE || intr_type == GPIO_INTR_ANYEDGE) {
205         return ESP_ERR_INVALID_ARG; // Dont support this mode.
206     }
207     RTCIO_ENTER_CRITICAL();
208     rtcio_hal_wakeup_enable(rtc_io_number_get(gpio_num), intr_type);
209     RTCIO_EXIT_CRITICAL();
210     return ESP_OK;
211 }
212 
rtc_gpio_wakeup_disable(gpio_num_t gpio_num)213 esp_err_t rtc_gpio_wakeup_disable(gpio_num_t gpio_num)
214 {
215     ESP_RETURN_ON_FALSE(rtc_gpio_is_valid_gpio(gpio_num), ESP_ERR_INVALID_ARG, RTCIO_TAG, "RTCIO number error");
216     RTCIO_ENTER_CRITICAL();
217     rtcio_hal_wakeup_disable(rtc_io_number_get(gpio_num));
218     RTCIO_EXIT_CRITICAL();
219     return ESP_OK;
220 }
221 
222 #endif // SOC_RTCIO_WAKE_SUPPORTED
223 
rtc_gpio_is_valid_gpio(gpio_num_t gpio_num)224 bool rtc_gpio_is_valid_gpio(gpio_num_t gpio_num)
225 {
226 #if SOC_RTCIO_INPUT_OUTPUT_SUPPORTED
227     return (gpio_num < GPIO_PIN_COUNT && rtc_io_num_map[gpio_num] >= 0);
228 #else
229     return false;
230 #endif
231 }
232 
233 #if SOC_RTCIO_INPUT_OUTPUT_SUPPORTED
rtc_io_number_get(gpio_num_t gpio_num)234 int rtc_io_number_get(gpio_num_t gpio_num)
235 {
236     return rtc_io_num_map[gpio_num];
237 }
238 
239 #endif // SOC_RTCIO_INPUT_OUTPUT_SUPPORTED
240