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