1 /*
2 * SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6
7 /*******************************************************************************
8 * NOTICE
9 * The ll is not public api, don't use in application code.
10 * See readme.md in hal/include/hal/readme.md
11 ******************************************************************************/
12
13 #pragma once
14
15 #include <stdlib.h>
16 #include <stdbool.h>
17 #include "soc/rtc_periph.h"
18 #include "soc/pcr_struct.h"
19 #include "soc/rtc_io_struct.h"
20 #include "soc/lp_aon_struct.h"
21 #include "soc/pmu_struct.h"
22 #include "hal/misc.h"
23 #include "hal/assert.h"
24 #include "hal/gpio_types.h"
25 #include "soc/io_mux_reg.h"
26
27 #ifdef __cplusplus
28 extern "C" {
29 #endif
30
31 #define RTCIO_LL_PIN_FUNC 0
32
33 typedef enum {
34 RTCIO_FUNC_RTC = 0x0, /*!< The pin controlled by RTC module. */
35 RTCIO_FUNC_DIGITAL = 0x1, /*!< The pin controlled by DIGITAL module. */
36 } rtcio_ll_func_t;
37
38 typedef enum {
39 RTCIO_WAKEUP_DISABLE = 0, /*!< Disable GPIO interrupt */
40 RTCIO_WAKEUP_LOW_LEVEL = 0x4, /*!< GPIO interrupt type : input low level trigger */
41 RTCIO_WAKEUP_HIGH_LEVEL = 0x5, /*!< GPIO interrupt type : input high level trigger */
42 } rtcio_ll_wake_type_t;
43
44 typedef enum {
45 RTCIO_OUTPUT_NORMAL = 0, /*!< RTCIO output mode is normal. */
46 RTCIO_OUTPUT_OD = 0x1, /*!< RTCIO output mode is open-drain. */
47 } rtcio_ll_out_mode_t;
48
49 /**
50 * @brief Select the rtcio function.
51 *
52 * @note The RTC function must be selected before the pad analog function is enabled.
53 * @note The clock gating 'PCR.iomux_conf.iomux_clk_en' is the gate of both 'lp_io' and 'etm_gpio'
54 * And it's default to be turned on, so we don't need to operate this clock gate here additionally
55 *
56 * @param rtcio_num The index of rtcio. 0 ~ MAX(rtcio).
57 * @param func Select pin function.
58 */
rtcio_ll_function_select(int rtcio_num,rtcio_ll_func_t func)59 static inline void rtcio_ll_function_select(int rtcio_num, rtcio_ll_func_t func)
60 {
61 if (func == RTCIO_FUNC_RTC) {
62 // 0: GPIO connected to digital GPIO module. 1: GPIO connected to analog RTC module.
63 uint32_t sel_mask = HAL_FORCE_READ_U32_REG_FIELD(LP_AON.gpio_mux, gpio_mux_sel);
64 sel_mask |= BIT(rtcio_num);
65 HAL_FORCE_MODIFY_U32_REG_FIELD(LP_AON.gpio_mux, gpio_mux_sel, sel_mask);
66 //0:RTC FUNCTION 1,2,3:Reserved
67 LP_IO.gpio[rtcio_num].mcu_sel = RTCIO_LL_PIN_FUNC;
68 } else if (func == RTCIO_FUNC_DIGITAL) {
69 // Clear the bit to use digital GPIO module
70 uint32_t sel_mask = HAL_FORCE_READ_U32_REG_FIELD(LP_AON.gpio_mux, gpio_mux_sel);
71 sel_mask &= ~BIT(rtcio_num);
72 HAL_FORCE_MODIFY_U32_REG_FIELD(LP_AON.gpio_mux, gpio_mux_sel, sel_mask);
73 }
74 }
75
76 /**
77 * Enable rtcio output.
78 *
79 * @param rtcio_num The index of rtcio. 0 ~ MAX(rtcio).
80 */
rtcio_ll_output_enable(int rtcio_num)81 static inline void rtcio_ll_output_enable(int rtcio_num)
82 {
83 HAL_FORCE_MODIFY_U32_REG_FIELD(LP_IO.out_enable_w1ts, enable_w1ts, BIT(rtcio_num));
84 }
85
86 /**
87 * Disable rtcio output.
88 *
89 * @param rtcio_num The index of rtcio. 0 ~ MAX(rtcio).
90 */
rtcio_ll_output_disable(int rtcio_num)91 static inline void rtcio_ll_output_disable(int rtcio_num)
92 {
93 HAL_FORCE_MODIFY_U32_REG_FIELD(LP_IO.out_enable_w1tc, enable_w1tc, BIT(rtcio_num));
94 }
95
96 /**
97 * Set RTCIO output level.
98 *
99 * @param rtcio_num The index of rtcio. 0 ~ MAX(rtcio).
100 * @param level 0: output low; ~0: output high.
101 */
rtcio_ll_set_level(int rtcio_num,uint32_t level)102 static inline void rtcio_ll_set_level(int rtcio_num, uint32_t level)
103 {
104 if (level) {
105 HAL_FORCE_MODIFY_U32_REG_FIELD(LP_IO.out_data_w1ts, out_data_w1ts, BIT(rtcio_num));
106 } else {
107 HAL_FORCE_MODIFY_U32_REG_FIELD(LP_IO.out_data_w1tc, out_data_w1tc, BIT(rtcio_num));
108 }
109 }
110
111 /**
112 * Enable rtcio input.
113 *
114 * @param rtcio_num The index of rtcio. 0 ~ MAX(rtcio).
115 */
rtcio_ll_input_enable(int rtcio_num)116 static inline void rtcio_ll_input_enable(int rtcio_num)
117 {
118 LP_IO.gpio[rtcio_num].fun_ie = 1;
119 }
120
121 /**
122 * Disable rtcio input.
123 *
124 * @param rtcio_num The index of rtcio. 0 ~ MAX(rtcio).
125 */
rtcio_ll_input_disable(int rtcio_num)126 static inline void rtcio_ll_input_disable(int rtcio_num)
127 {
128 LP_IO.gpio[rtcio_num].fun_ie = 0;
129 }
130
131 /**
132 * Get RTCIO input level.
133 *
134 * @param rtcio_num The index of rtcio. 0 ~ MAX(rtcio).
135 * @return 0: input low; ~0: input high.
136 */
rtcio_ll_get_level(int rtcio_num)137 static inline uint32_t rtcio_ll_get_level(int rtcio_num)
138 {
139 return (uint32_t)(LP_IO.in.in_data_next >> rtcio_num) & 0x1;
140 }
141
142 /**
143 * @brief Set RTC GPIO pad drive capability
144 *
145 * @param rtcio_num The index of rtcio. 0 ~ MAX(rtcio).
146 * @param strength Drive capability of the pad. Range: 0 ~ 3.
147 */
rtcio_ll_set_drive_capability(int rtcio_num,uint32_t strength)148 static inline void rtcio_ll_set_drive_capability(int rtcio_num, uint32_t strength)
149 {
150 LP_IO.gpio[rtcio_num].fun_drv = strength;
151 }
152
153 /**
154 * @brief Get RTC GPIO pad drive capability.
155 *
156 * @param rtcio_num The index of rtcio. 0 ~ MAX(rtcio).
157 * @return Drive capability of the pad. Range: 0 ~ 3.
158 */
rtcio_ll_get_drive_capability(int rtcio_num)159 static inline uint32_t rtcio_ll_get_drive_capability(int rtcio_num)
160 {
161 return LP_IO.gpio[rtcio_num].fun_drv;
162 }
163
164 /**
165 * @brief Set RTC GPIO pad output mode.
166 *
167 * @param rtcio_num The index of rtcio. 0 ~ MAX(rtcio).
168 * @return mode Output mode.
169 */
rtcio_ll_output_mode_set(int rtcio_num,rtcio_ll_out_mode_t mode)170 static inline void rtcio_ll_output_mode_set(int rtcio_num, rtcio_ll_out_mode_t mode)
171 {
172 LP_IO.pin[rtcio_num].pad_driver = mode;
173 }
174
175 /**
176 * RTC GPIO pullup enable.
177 *
178 * @param rtcio_num The index of rtcio. 0 ~ MAX(rtcio).
179 */
rtcio_ll_pullup_enable(int rtcio_num)180 static inline void rtcio_ll_pullup_enable(int rtcio_num)
181 {
182 /* Enable internal weak pull-up */
183 LP_IO.gpio[rtcio_num].fun_wpu = 1;
184 }
185
186 /**
187 * RTC GPIO pullup disable.
188 *
189 * @param rtcio_num The index of rtcio. 0 ~ MAX(rtcio).
190 */
rtcio_ll_pullup_disable(int rtcio_num)191 static inline void rtcio_ll_pullup_disable(int rtcio_num)
192 {
193 /* Disable internal weak pull-up */
194 LP_IO.gpio[rtcio_num].fun_wpu = 0;
195 }
196
197 /**
198 * RTC GPIO pulldown enable.
199 *
200 * @param rtcio_num The index of rtcio. 0 ~ MAX(rtcio).
201 */
rtcio_ll_pulldown_enable(int rtcio_num)202 static inline void rtcio_ll_pulldown_enable(int rtcio_num)
203 {
204 /* Enable internal weak pull-down */
205 LP_IO.gpio[rtcio_num].fun_wpd = 1;
206 }
207
208 /**
209 * RTC GPIO pulldown disable.
210 *
211 * @param rtcio_num The index of rtcio. 0 ~ MAX(rtcio).
212 */
rtcio_ll_pulldown_disable(int rtcio_num)213 static inline void rtcio_ll_pulldown_disable(int rtcio_num)
214 {
215 /* Enable internal weak pull-down */
216 LP_IO.gpio[rtcio_num].fun_wpd = 0;
217 }
218
219 /**
220 * Enable force hold function for an RTC IO pad.
221 *
222 * Enabling HOLD function will cause the pad to lock current status, such as,
223 * input/output enable, input/output value, function, drive strength values.
224 * This function is useful when going into light or deep sleep mode to prevent
225 * the pin configuration from changing.
226 *
227 * @param rtcio_num The index of rtcio. 0 ~ MAX(rtcio).
228 */
rtcio_ll_force_hold_enable(int rtcio_num)229 static inline void rtcio_ll_force_hold_enable(int rtcio_num)
230 {
231 LP_AON.gpio_hold0.gpio_hold0 |= BIT(rtcio_num);
232 }
233
234 /**
235 * Disable hold function on an RTC IO pad
236 *
237 * @note If disable the pad hold, the status of pad maybe changed in sleep mode.
238 * @param rtcio_num The index of rtcio. 0 ~ MAX(rtcio).
239 */
rtcio_ll_force_hold_disable(int rtcio_num)240 static inline void rtcio_ll_force_hold_disable(int rtcio_num)
241 {
242 LP_AON.gpio_hold0.gpio_hold0 &= ~BIT(rtcio_num);
243 }
244
245 /**
246 * Enable force hold function for all RTC IO pads
247 *
248 * Enabling HOLD function will cause the pad to lock current status, such as,
249 * input/output enable, input/output value, function, drive strength values.
250 * This function is useful when going into light or deep sleep mode to prevent
251 * the pin configuration from changing.
252 */
rtcio_ll_force_hold_all(void)253 static inline void rtcio_ll_force_hold_all(void)
254 {
255 PMU.imm.pad_hold_all.tie_high_lp_pad_hold_all = 1;
256 }
257
258 /**
259 * Disable hold function fon all RTC IO pads
260 *
261 * @note If disable the pad hold, the status of pad maybe changed in sleep mode.
262 */
rtcio_ll_force_unhold_all(void)263 static inline void rtcio_ll_force_unhold_all(void)
264 {
265 PMU.imm.pad_hold_all.tie_low_lp_pad_hold_all = 1;
266 }
267
268 /**
269 * Enable wakeup function and set wakeup type from light sleep or deep sleep for rtcio.
270 *
271 * @param rtcio_num The index of rtcio. 0 ~ MAX(rtcio).
272 * @param type Wakeup on high level or low level.
273 */
rtcio_ll_wakeup_enable(int rtcio_num,rtcio_ll_wake_type_t type)274 static inline void rtcio_ll_wakeup_enable(int rtcio_num, rtcio_ll_wake_type_t type)
275 {
276 LP_IO.pin[rtcio_num].wakeup_enable = 0x1;
277 LP_IO.pin[rtcio_num].int_type = type;
278 }
279
280 /**
281 * Disable wakeup function from light sleep or deep sleep for rtcio.
282 *
283 * @param rtcio_num The index of rtcio. 0 ~ MAX(rtcio).
284 */
rtcio_ll_wakeup_disable(int rtcio_num)285 static inline void rtcio_ll_wakeup_disable(int rtcio_num)
286 {
287 LP_IO.pin[rtcio_num].wakeup_enable = 0;
288 LP_IO.pin[rtcio_num].int_type = RTCIO_WAKEUP_DISABLE;
289 }
290
291 /**
292 * Enable rtc io output in deep sleep.
293 *
294 * @param rtcio_num The index of rtcio. 0 ~ MAX(rtcio).
295 */
rtcio_ll_enable_output_in_sleep(gpio_num_t gpio_num)296 static inline void rtcio_ll_enable_output_in_sleep(gpio_num_t gpio_num)
297 {
298 LP_IO.gpio[gpio_num].mcu_oe = 1;
299 }
300
301 /**
302 * Disable rtc io output in deep sleep.
303 *
304 * @param rtcio_num The index of rtcio. 0 ~ MAX(rtcio).
305 */
rtcio_ll_disable_output_in_sleep(gpio_num_t gpio_num)306 static inline void rtcio_ll_disable_output_in_sleep(gpio_num_t gpio_num)
307 {
308 LP_IO.gpio[gpio_num].mcu_oe = 0;
309 }
310
311 /**
312 * Enable rtc io input in deep sleep.
313 *
314 * @param rtcio_num The index of rtcio. 0 ~ MAX(rtcio).
315 */
rtcio_ll_enable_input_in_sleep(gpio_num_t gpio_num)316 static inline void rtcio_ll_enable_input_in_sleep(gpio_num_t gpio_num)
317 {
318 LP_IO.gpio[gpio_num].mcu_ie = 1;
319 }
320
321 /**
322 * Disable rtc io input in deep sleep.
323 *
324 * @param rtcio_num The index of rtcio. 0 ~ MAX(rtcio).
325 */
rtcio_ll_disable_input_in_sleep(gpio_num_t gpio_num)326 static inline void rtcio_ll_disable_input_in_sleep(gpio_num_t gpio_num)
327 {
328 LP_IO.gpio[gpio_num].mcu_ie = 0;
329 }
330
331 /**
332 * Enable rtc io keep another setting in deep sleep.
333 *
334 * @param rtcio_num The index of rtcio. 0 ~ MAX(rtcio).
335 */
rtcio_ll_enable_sleep_setting(gpio_num_t gpio_num)336 static inline void rtcio_ll_enable_sleep_setting(gpio_num_t gpio_num)
337 {
338 LP_IO.gpio[gpio_num].slp_sel = 1;
339 }
340
341 /**
342 * Disable rtc io keep another setting in deep sleep. (Default)
343 *
344 * @param rtcio_num The index of rtcio. 0 ~ MAX(rtcio).
345 */
rtcio_ll_disable_sleep_setting(gpio_num_t gpio_num)346 static inline void rtcio_ll_disable_sleep_setting(gpio_num_t gpio_num)
347 {
348 LP_IO.gpio[gpio_num].slp_sel = 0;
349 }
350
351 /**
352 * @brief Get the status of whether an IO is used for sleep wake-up.
353 *
354 * @param hw Peripheral GPIO hardware instance address.
355 * @param gpio_num GPIO number
356 * @return True if the pin is enabled to wake up from deep-sleep
357 */
rtcio_ll_wakeup_is_enabled(gpio_num_t gpio_num)358 static inline bool rtcio_ll_wakeup_is_enabled(gpio_num_t gpio_num)
359 {
360 HAL_ASSERT(gpio_num <= GPIO_NUM_7 && "gpio larger than 7 does not support deep sleep wake-up function");
361 // On ESP32-C6, (lp_io pin number) == (gpio pin number)
362 return LP_IO.pin[gpio_num].wakeup_enable;
363 }
364
365 /**
366 * @brief Get the rtc io interrupt status
367 *
368 * @return bit 0~7 corresponding to 0 ~ SOC_RTCIO_PIN_COUNT.
369 */
rtcio_ll_get_interrupt_status(void)370 static inline uint32_t rtcio_ll_get_interrupt_status(void)
371 {
372 return (uint32_t)(LP_IO.status.status_interrupt);
373 }
374
375 /**
376 * @brief Clear all LP IO pads status
377 */
rtcio_ll_clear_interrupt_status(void)378 static inline void rtcio_ll_clear_interrupt_status(void)
379 {
380 HAL_FORCE_MODIFY_U32_REG_FIELD(LP_IO.status_w1tc, status_w1tc, 0xff);
381 }
382
383 #ifdef __cplusplus
384 }
385 #endif
386