1 /*
2  * SPDX-FileCopyrightText: 2015-2024 Espressif Systems (Shanghai) CO LTD
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 /*******************************************************************************
8  * NOTICE
9  * The hal is not public api, don't use in application code.
10  * See readme.md in hal/include/hal/readme.md
11  ******************************************************************************/
12 
13 // The LL layer for ESP32-S3 GPIO register operations
14 
15 #pragma once
16 
17 #include <stdbool.h>
18 #include "soc/soc.h"
19 #include "soc/gpio_periph.h"
20 #include "soc/rtc_cntl_reg.h"
21 #include "soc/rtc_io_reg.h"
22 #include "soc/usb_serial_jtag_reg.h"
23 #include "hal/gpio_types.h"
24 #include "soc/gpio_struct.h"
25 #include "hal/misc.h"
26 
27 #ifdef __cplusplus
28 extern "C" {
29 #endif
30 
31 // Get GPIO hardware instance with giving gpio num
32 #define GPIO_LL_GET_HW(num) (((num) == 0) ? (&GPIO) : NULL)
33 
34 // On ESP32S3, pro cpu and app cpu shares the same interrupt enable bit
35 #define GPIO_LL_INTR_ENA      (BIT(0))
36 #define GPIO_LL_NMI_INTR_ENA  (BIT(1))
37 
38 /**
39  * @brief Get the configuration for an IO
40  *
41  * @param hw Peripheral GPIO hardware instance address.
42  * @param gpio_num GPIO number
43  * @param pu Pull-up enabled or not
44  * @param pd Pull-down enabled or not
45  * @param ie Input enabled or not
46  * @param oe Output enabled or not
47  * @param od Open-drain enabled or not
48  * @param drv Drive strength value
49  * @param fun_sel IOMUX function selection value
50  * @param sig_out Outputting peripheral signal index
51  * @param slp_sel Pin sleep mode enabled or not
52  */
gpio_ll_get_io_config(gpio_dev_t * hw,uint32_t gpio_num,bool * pu,bool * pd,bool * ie,bool * oe,bool * od,uint32_t * drv,uint32_t * fun_sel,uint32_t * sig_out,bool * slp_sel)53 static inline void gpio_ll_get_io_config(gpio_dev_t *hw, uint32_t gpio_num,
54                                          bool *pu, bool *pd, bool *ie, bool *oe, bool *od, uint32_t *drv,
55                                          uint32_t *fun_sel, uint32_t *sig_out, bool *slp_sel)
56 {
57     uint32_t bit_shift = (gpio_num < 32) ? gpio_num : (gpio_num - 32);
58     uint32_t bit_mask = 1 << bit_shift;
59     uint32_t iomux_reg_val = REG_READ(GPIO_PIN_MUX_REG[gpio_num]);
60     *pu = (iomux_reg_val & FUN_PU_M) >> FUN_PU_S;
61     *pd = (iomux_reg_val & FUN_PD_M) >> FUN_PD_S;
62     *ie = (iomux_reg_val & FUN_IE_M) >> FUN_IE_S;
63     *oe = (((gpio_num < 32) ? hw->enable : hw->enable1.val) & bit_mask) >> bit_shift;
64     *od = hw->pin[gpio_num].pad_driver;
65     *drv = (iomux_reg_val & FUN_DRV_M) >> FUN_DRV_S;
66     *fun_sel = (iomux_reg_val & MCU_SEL_M) >> MCU_SEL_S;
67     *sig_out = hw->func_out_sel_cfg[gpio_num].func_sel;
68     *slp_sel = (iomux_reg_val & SLP_SEL_M) >> SLP_SEL_S;
69 }
70 
71 /**
72   * @brief Enable pull-up on GPIO.
73   *
74   * @param hw Peripheral GPIO hardware instance address.
75   * @param gpio_num GPIO number
76   */
gpio_ll_pullup_en(gpio_dev_t * hw,uint32_t gpio_num)77 static inline void gpio_ll_pullup_en(gpio_dev_t *hw, uint32_t gpio_num)
78 {
79     REG_SET_BIT(GPIO_PIN_MUX_REG[gpio_num], FUN_PU);
80 }
81 
82 /**
83   * @brief Disable pull-up on GPIO.
84   *
85   * @param hw Peripheral GPIO hardware instance address.
86   * @param gpio_num GPIO number
87   */
88 __attribute__((always_inline))
gpio_ll_pullup_dis(gpio_dev_t * hw,uint32_t gpio_num)89 static inline void gpio_ll_pullup_dis(gpio_dev_t *hw, uint32_t gpio_num)
90 {
91     // The pull-up value of the USB pins are controlled by the pins’ pull-up value together with USB pull-up value
92     // USB DP pin is default to PU enabled
93     // Note that from esp32s3 ECO1, USB_EXCHG_PINS feature has been supported. If this efuse is burnt, the gpio pin
94     // which should be checked is USB_DM_GPIO_NUM instead.
95     if (gpio_num == USB_DP_GPIO_NUM) {
96         SET_PERI_REG_MASK(USB_SERIAL_JTAG_CONF0_REG, USB_SERIAL_JTAG_PAD_PULL_OVERRIDE);
97         CLEAR_PERI_REG_MASK(USB_SERIAL_JTAG_CONF0_REG, USB_SERIAL_JTAG_DP_PULLUP);
98     }
99     REG_CLR_BIT(IO_MUX_GPIO0_REG + (gpio_num * 4), FUN_PU);
100 }
101 
102 /**
103   * @brief Enable pull-down on GPIO.
104   *
105   * @param hw Peripheral GPIO hardware instance address.
106   * @param gpio_num GPIO number
107   */
gpio_ll_pulldown_en(gpio_dev_t * hw,uint32_t gpio_num)108 static inline void gpio_ll_pulldown_en(gpio_dev_t *hw, uint32_t gpio_num)
109 {
110     REG_SET_BIT(GPIO_PIN_MUX_REG[gpio_num], FUN_PD);
111 }
112 
113 /**
114   * @brief Disable pull-down on GPIO.
115   *
116   * @param hw Peripheral GPIO hardware instance address.
117   * @param gpio_num GPIO number
118   */
119 __attribute__((always_inline))
gpio_ll_pulldown_dis(gpio_dev_t * hw,uint32_t gpio_num)120 static inline void gpio_ll_pulldown_dis(gpio_dev_t *hw, uint32_t gpio_num)
121 {
122     REG_CLR_BIT(IO_MUX_GPIO0_REG + (gpio_num * 4), FUN_PD);
123 }
124 
125 /**
126  * @brief  GPIO set interrupt trigger type
127  *
128  * @param  hw Peripheral GPIO hardware instance address.
129  * @param  gpio_num GPIO number. If you want to set the trigger type of e.g. of GPIO16, gpio_num should be GPIO_NUM_16 (16);
130  * @param  intr_type Interrupt type, select from gpio_int_type_t
131  */
gpio_ll_set_intr_type(gpio_dev_t * hw,uint32_t gpio_num,gpio_int_type_t intr_type)132 static inline void gpio_ll_set_intr_type(gpio_dev_t *hw, uint32_t gpio_num, gpio_int_type_t intr_type)
133 {
134     hw->pin[gpio_num].int_type = intr_type;
135 }
136 
137 /**
138   * @brief Get GPIO interrupt status
139   *
140   * @param hw Peripheral GPIO hardware instance address.
141   * @param core_id interrupt core id
142   * @param status interrupt status
143   */
144 __attribute__((always_inline))
gpio_ll_get_intr_status(gpio_dev_t * hw,uint32_t core_id,uint32_t * status)145 static inline void gpio_ll_get_intr_status(gpio_dev_t *hw, uint32_t core_id, uint32_t *status)
146 {
147     // On ESP32S3, pcpu_int register represents GPIO0-31 interrupt status on both cores
148     (void)core_id;
149     *status = hw->pcpu_int;
150 }
151 
152 /**
153   * @brief Get GPIO interrupt status high
154   *
155   * @param hw Peripheral GPIO hardware instance address.
156   * @param core_id interrupt core id
157   * @param status interrupt status high
158   */
159 __attribute__((always_inline))
gpio_ll_get_intr_status_high(gpio_dev_t * hw,uint32_t core_id,uint32_t * status)160 static inline void gpio_ll_get_intr_status_high(gpio_dev_t *hw, uint32_t core_id, uint32_t *status)
161 {
162     // On ESP32S3, pcpu_int1 register represents GPIO32-48 interrupt status on both cores
163     (void)core_id;
164     *status = hw->pcpu_int1.intr;
165 }
166 
167 /**
168   * @brief Clear GPIO interrupt status
169   *
170   * @param hw Peripheral GPIO hardware instance address.
171   * @param mask interrupt status clear mask
172   */
173 __attribute__((always_inline))
gpio_ll_clear_intr_status(gpio_dev_t * hw,uint32_t mask)174 static inline void gpio_ll_clear_intr_status(gpio_dev_t *hw, uint32_t mask)
175 {
176     hw->status_w1tc = mask;
177 }
178 
179 /**
180   * @brief Clear GPIO interrupt status high
181   *
182   * @param hw Peripheral GPIO hardware instance address.
183   * @param mask interrupt status high clear mask
184   */
185 __attribute__((always_inline))
gpio_ll_clear_intr_status_high(gpio_dev_t * hw,uint32_t mask)186 static inline void gpio_ll_clear_intr_status_high(gpio_dev_t *hw, uint32_t mask)
187 {
188     hw->status1_w1tc.intr_st = mask;
189 }
190 
191 /**
192  * @brief  Enable GPIO module interrupt signal
193  *
194  * @param  hw Peripheral GPIO hardware instance address.
195  * @param  core_id Interrupt enabled CPU to corresponding ID
196  * @param  gpio_num GPIO number. If you want to enable the interrupt of e.g. GPIO16, gpio_num should be GPIO_NUM_16 (16);
197  */
198 __attribute__((always_inline))
gpio_ll_intr_enable_on_core(gpio_dev_t * hw,uint32_t core_id,uint32_t gpio_num)199 static inline void gpio_ll_intr_enable_on_core(gpio_dev_t *hw, uint32_t core_id, uint32_t gpio_num)
200 {
201     (void)core_id;
202     GPIO.pin[gpio_num].int_ena = GPIO_LL_INTR_ENA;     //enable intr
203 }
204 
205 /**
206  * @brief  Disable GPIO module interrupt signal
207  *
208  * @param  hw Peripheral GPIO hardware instance address.
209  * @param  gpio_num GPIO number. If you want to disable the interrupt of e.g. GPIO16, gpio_num should be GPIO_NUM_16 (16);
210  */
211 __attribute__((always_inline))
gpio_ll_intr_disable(gpio_dev_t * hw,uint32_t gpio_num)212 static inline void gpio_ll_intr_disable(gpio_dev_t *hw, uint32_t gpio_num)
213 {
214     hw->pin[gpio_num].int_ena = 0;                             //disable GPIO intr
215 }
216 
217 /**
218   * @brief Disable input mode on GPIO.
219   *
220   * @param hw Peripheral GPIO hardware instance address.
221   * @param gpio_num GPIO number
222   */
223 __attribute__((always_inline))
gpio_ll_input_disable(gpio_dev_t * hw,uint32_t gpio_num)224 static inline void gpio_ll_input_disable(gpio_dev_t *hw, uint32_t gpio_num)
225 {
226     PIN_INPUT_DISABLE(IO_MUX_GPIO0_REG + (gpio_num * 4));
227 }
228 
229 /**
230   * @brief Enable input mode on GPIO.
231   *
232   * @param hw Peripheral GPIO hardware instance address.
233   * @param gpio_num GPIO number
234   */
gpio_ll_input_enable(gpio_dev_t * hw,uint32_t gpio_num)235 static inline void gpio_ll_input_enable(gpio_dev_t *hw, uint32_t gpio_num)
236 {
237     PIN_INPUT_ENABLE(IO_MUX_GPIO0_REG + (gpio_num * 4));
238 }
239 
240 /**
241  * @brief Enable GPIO pin filter
242  *
243  * @param hw Peripheral GPIO hardware instance address.
244  * @param gpio_num GPIO number of the pad.
245  */
gpio_ll_pin_filter_enable(gpio_dev_t * hw,uint32_t gpio_num)246 static inline void gpio_ll_pin_filter_enable(gpio_dev_t *hw, uint32_t gpio_num)
247 {
248     PIN_FILTER_EN(IO_MUX_GPIO0_REG + (gpio_num * 4));
249 }
250 
251 /**
252  * @brief Disable GPIO pin filter
253  *
254  * @param hw Peripheral GPIO hardware instance address.
255  * @param gpio_num GPIO number of the pad.
256  */
gpio_ll_pin_filter_disable(gpio_dev_t * hw,uint32_t gpio_num)257 static inline void gpio_ll_pin_filter_disable(gpio_dev_t *hw, uint32_t gpio_num)
258 {
259     PIN_FILTER_DIS(IO_MUX_GPIO0_REG + (gpio_num * 4));
260 }
261 
262 /**
263   * @brief Disable output mode on GPIO.
264   *
265   * @param hw Peripheral GPIO hardware instance address.
266   * @param gpio_num GPIO number
267   */
268 __attribute__((always_inline))
gpio_ll_output_disable(gpio_dev_t * hw,uint32_t gpio_num)269 static inline void gpio_ll_output_disable(gpio_dev_t *hw, uint32_t gpio_num)
270 {
271     if (gpio_num < 32) {
272         hw->enable_w1tc = (0x1 << gpio_num);
273     } else {
274         hw->enable1_w1tc.data = (0x1 << (gpio_num - 32));
275     }
276 
277     // Ensure no other output signal is routed via GPIO matrix to this pin
278     REG_WRITE(GPIO_FUNC0_OUT_SEL_CFG_REG + (gpio_num * 4),
279               SIG_GPIO_OUT_IDX);
280 }
281 
282 /**
283   * @brief Enable output mode on GPIO.
284   *
285   * @param hw Peripheral GPIO hardware instance address.
286   * @param gpio_num GPIO number
287   */
gpio_ll_output_enable(gpio_dev_t * hw,uint32_t gpio_num)288 static inline __attribute__((always_inline)) void gpio_ll_output_enable(gpio_dev_t *hw, uint32_t gpio_num)
289 {
290     if (gpio_num < 32) {
291         hw->enable_w1ts = (0x1 << gpio_num);
292     } else {
293         hw->enable1_w1ts.data = (0x1 << (gpio_num - 32));
294     }
295 }
296 
297 /**
298   * @brief Disable open-drain mode on GPIO.
299   *
300   * @param hw Peripheral GPIO hardware instance address.
301   * @param gpio_num GPIO number
302   */
gpio_ll_od_disable(gpio_dev_t * hw,uint32_t gpio_num)303 static inline __attribute__((always_inline)) void gpio_ll_od_disable(gpio_dev_t *hw, uint32_t gpio_num)
304 {
305     hw->pin[gpio_num].pad_driver = 0;
306 }
307 
308 /**
309   * @brief Enable open-drain mode on GPIO.
310   *
311   * @param hw Peripheral GPIO hardware instance address.
312   * @param gpio_num GPIO number
313   */
gpio_ll_od_enable(gpio_dev_t * hw,uint32_t gpio_num)314 static inline void gpio_ll_od_enable(gpio_dev_t *hw, uint32_t gpio_num)
315 {
316     hw->pin[gpio_num].pad_driver = 1;
317 }
318 
319 /**
320  * @brief  Select a function for the pin in the IOMUX
321  *
322  * @param  hw Peripheral GPIO hardware instance address.
323  * @param  gpio_num GPIO number
324  * @param  func Function to assign to the pin
325  */
gpio_ll_func_sel(gpio_dev_t * hw,uint8_t gpio_num,uint32_t func)326 static inline __attribute__((always_inline)) void gpio_ll_func_sel(gpio_dev_t *hw, uint8_t gpio_num, uint32_t func)
327 {
328     if (gpio_num == USB_DM_GPIO_NUM || gpio_num == USB_DP_GPIO_NUM) {
329         CLEAR_PERI_REG_MASK(USB_SERIAL_JTAG_CONF0_REG, USB_SERIAL_JTAG_USB_PAD_ENABLE);
330     }
331     PIN_FUNC_SELECT(IO_MUX_GPIO0_REG + (gpio_num * 4), func);
332 }
333 
334 /**
335  * @brief  GPIO set output level
336  *
337  * @param  hw Peripheral GPIO hardware instance address.
338  * @param  gpio_num GPIO number. If you want to set the output level of e.g. GPIO16, gpio_num should be GPIO_NUM_16 (16);
339  * @param  level Output level. 0: low ; 1: high
340  */
341 __attribute__((always_inline))
gpio_ll_set_level(gpio_dev_t * hw,uint32_t gpio_num,uint32_t level)342 static inline void gpio_ll_set_level(gpio_dev_t *hw, uint32_t gpio_num, uint32_t level)
343 {
344     if (level) {
345         if (gpio_num < 32) {
346             hw->out_w1ts = (1 << gpio_num);
347         } else {
348             hw->out1_w1ts.data = (1 << (gpio_num - 32));
349         }
350     } else {
351         if (gpio_num < 32) {
352             hw->out_w1tc = (1 << gpio_num);
353         } else {
354             hw->out1_w1tc.data = (1 << (gpio_num - 32));
355         }
356     }
357 }
358 
359 /**
360  * @brief  GPIO get input level
361  *
362  * @warning If the pad is not configured for input (or input and output) the returned value is always 0.
363  *
364  * @param  hw Peripheral GPIO hardware instance address.
365  * @param  gpio_num GPIO number. If you want to get the logic level of e.g. pin GPIO16, gpio_num should be GPIO_NUM_16 (16);
366  *
367  * @return
368  *     - 0 the GPIO input level is 0
369  *     - 1 the GPIO input level is 1
370  */
gpio_ll_get_level(gpio_dev_t * hw,uint32_t gpio_num)371 static inline int gpio_ll_get_level(gpio_dev_t *hw, uint32_t gpio_num)
372 {
373     if (gpio_num < 32) {
374         return (hw->in >> gpio_num) & 0x1;
375     } else {
376         return (hw->in1.data >> (gpio_num - 32)) & 0x1;
377     }
378 }
379 
380 /**
381  * @brief Enable GPIO wake-up function.
382  *
383  * @param hw Peripheral GPIO hardware instance address.
384  * @param gpio_num GPIO number.
385  */
gpio_ll_wakeup_enable(gpio_dev_t * hw,uint32_t gpio_num)386 static inline void gpio_ll_wakeup_enable(gpio_dev_t *hw, uint32_t gpio_num)
387 {
388     hw->pin[gpio_num].wakeup_enable = 0x1;
389 }
390 
391 /**
392  * @brief Disable GPIO wake-up function.
393  *
394  * @param hw Peripheral GPIO hardware instance address.
395  * @param gpio_num GPIO number
396  */
gpio_ll_wakeup_disable(gpio_dev_t * hw,uint32_t gpio_num)397 static inline void gpio_ll_wakeup_disable(gpio_dev_t *hw, uint32_t gpio_num)
398 {
399     hw->pin[gpio_num].wakeup_enable = 0;
400 }
401 
402 /**
403   * @brief Set GPIO pad drive capability
404   *
405   * @param hw Peripheral GPIO hardware instance address.
406   * @param gpio_num GPIO number, only support output GPIOs
407   * @param strength Drive capability of the pad
408   */
gpio_ll_set_drive_capability(gpio_dev_t * hw,uint32_t gpio_num,gpio_drive_cap_t strength)409 static inline void gpio_ll_set_drive_capability(gpio_dev_t *hw, uint32_t gpio_num, gpio_drive_cap_t strength)
410 {
411     uint32_t drv_cap = (uint32_t)strength;
412     // DRV = 1 and DRV = 2 register bits are flipped for IO17, IO18 on the target
413     if (gpio_num == 17 || gpio_num == 18) {
414         drv_cap = ((drv_cap & 0x1) << 1) | ((drv_cap & 0x2) >> 1); // swap bit0 and bit1
415     }
416     SET_PERI_REG_BITS(IO_MUX_GPIO0_REG + (gpio_num * 4), FUN_DRV_V, drv_cap, FUN_DRV_S);
417 }
418 
419 /**
420   * @brief Get GPIO pad drive capability
421   *
422   * @param hw Peripheral GPIO hardware instance address.
423   * @param gpio_num GPIO number, only support output GPIOs
424   * @param strength Pointer to accept drive capability of the pad
425   */
gpio_ll_get_drive_capability(gpio_dev_t * hw,uint32_t gpio_num,gpio_drive_cap_t * strength)426 static inline void gpio_ll_get_drive_capability(gpio_dev_t *hw, uint32_t gpio_num, gpio_drive_cap_t *strength)
427 {
428     uint32_t drv_cap = GET_PERI_REG_BITS2(IO_MUX_GPIO0_REG + (gpio_num * 4), FUN_DRV_V, FUN_DRV_S);
429     // DRV = 1 and DRV = 2 register bits are flipped for IO17, IO18 on the target
430     if (gpio_num == 17 || gpio_num == 18) {
431         drv_cap = ((drv_cap & 0x1) << 1) | ((drv_cap & 0x2) >> 1); // swap bit0 and bit1
432     }
433     *strength = (gpio_drive_cap_t)drv_cap;
434 }
435 
436 /**
437   * @brief Enable all digital gpio pad hold function during Deep-sleep.
438   *
439   * @param hw Peripheral GPIO hardware instance address.
440   */
gpio_ll_deep_sleep_hold_en(gpio_dev_t * hw)441 static inline void gpio_ll_deep_sleep_hold_en(gpio_dev_t *hw)
442 {
443     CLEAR_PERI_REG_MASK(RTC_CNTL_DIG_ISO_REG, RTC_CNTL_DG_PAD_FORCE_UNHOLD);
444     SET_PERI_REG_MASK(RTC_CNTL_DIG_ISO_REG, RTC_CNTL_DG_PAD_AUTOHOLD_EN_M);
445 }
446 
447 /**
448   * @brief Disable all digital gpio pad hold function during Deep-sleep.
449   *
450   * @param hw Peripheral GPIO hardware instance address.
451   */
gpio_ll_deep_sleep_hold_dis(gpio_dev_t * hw)452 static inline void gpio_ll_deep_sleep_hold_dis(gpio_dev_t *hw)
453 {
454     CLEAR_PERI_REG_MASK(RTC_CNTL_DIG_ISO_REG, RTC_CNTL_DG_PAD_AUTOHOLD_EN_M);
455 }
456 
457 /**
458  * @brief  Get deep sleep hold status
459  *
460  * @param  hw Peripheral GPIO hardware instance address.
461  *
462  * @return
463  *     - true  deep sleep hold is enabled
464  *     - false deep sleep hold is disabled
465  */
466 __attribute__((always_inline))
gpio_ll_deep_sleep_hold_is_en(gpio_dev_t * hw)467 static inline bool gpio_ll_deep_sleep_hold_is_en(gpio_dev_t *hw)
468 {
469     return !GET_PERI_REG_MASK(RTC_CNTL_DIG_ISO_REG, RTC_CNTL_DG_PAD_FORCE_UNHOLD) && GET_PERI_REG_MASK(RTC_CNTL_DIG_ISO_REG, RTC_CNTL_DG_PAD_AUTOHOLD_EN_M);
470 }
471 
472 /**
473   * @brief Enable gpio pad hold function.
474   *
475   * @param hw Peripheral GPIO hardware instance address.
476   * @param gpio_num GPIO number, only support output GPIOs
477   */
gpio_ll_hold_en(gpio_dev_t * hw,uint32_t gpio_num)478 static inline void gpio_ll_hold_en(gpio_dev_t *hw, uint32_t gpio_num)
479 {
480     SET_PERI_REG_MASK(RTC_CNTL_DIG_PAD_HOLD_REG, GPIO_HOLD_MASK[gpio_num]);
481 }
482 
483 /**
484   * @brief Disable gpio pad hold function.
485   *
486   * @param hw Peripheral GPIO hardware instance address.
487   * @param gpio_num GPIO number, only support output GPIOs
488   */
gpio_ll_hold_dis(gpio_dev_t * hw,uint32_t gpio_num)489 static inline void gpio_ll_hold_dis(gpio_dev_t *hw, uint32_t gpio_num)
490 {
491     CLEAR_PERI_REG_MASK(RTC_CNTL_DIG_PAD_HOLD_REG, GPIO_HOLD_MASK[gpio_num]);
492 }
493 
494 /**
495   * @brief Get gpio pad hold status.
496   *
497   * @param hw Peripheral GPIO hardware instance address.
498   * @param gpio_num GPIO number, only support output GPIOs
499   *
500   * @note caller must ensure that gpio_num is a digital io pad
501   *
502   * @return
503   *     - true  digital gpio pad is held
504   *     - false digital gpio pad is unheld
505   */
506 __attribute__((always_inline))
gpio_ll_is_digital_io_hold(gpio_dev_t * hw,uint32_t gpio_num)507 static inline bool gpio_ll_is_digital_io_hold(gpio_dev_t *hw, uint32_t gpio_num)
508 {
509     return GET_PERI_REG_MASK(RTC_CNTL_DIG_PAD_HOLD_REG, BIT(gpio_num - 21));
510 }
511 
512 /**
513   * @brief Set pad input to a peripheral signal through the IOMUX.
514   *
515   * @param hw Peripheral GPIO hardware instance address.
516   * @param gpio_num GPIO number of the pad.
517   * @param signal_idx Peripheral signal id to input. One of the ``*_IN_IDX`` signals in ``soc/gpio_sig_map.h``.
518   */
519 __attribute__((always_inline))
gpio_ll_iomux_in(gpio_dev_t * hw,uint32_t gpio,uint32_t signal_idx)520 static inline void gpio_ll_iomux_in(gpio_dev_t *hw, uint32_t gpio, uint32_t signal_idx)
521 {
522     hw->func_in_sel_cfg[signal_idx].sig_in_sel = 0;
523     PIN_INPUT_ENABLE(IO_MUX_GPIO0_REG + (gpio * 4));
524 }
525 
526 /**
527  * @brief  Select a function for the pin in the IOMUX
528  *
529  * @param  pin_name Pin name to configure
530  * @param  func Function to assign to the pin
531  */
gpio_ll_iomux_func_sel(uint32_t pin_name,uint32_t func)532 static inline __attribute__((always_inline)) void gpio_ll_iomux_func_sel(uint32_t pin_name, uint32_t func)
533 {
534     if (pin_name == IO_MUX_GPIO19_REG || pin_name == IO_MUX_GPIO20_REG) {
535         CLEAR_PERI_REG_MASK(USB_SERIAL_JTAG_CONF0_REG, USB_SERIAL_JTAG_USB_PAD_ENABLE);
536     }
537     PIN_FUNC_SELECT(pin_name, func);
538 }
539 
540 /**
541   * @brief Set peripheral output to an GPIO pad through the IOMUX.
542   *
543   * @param hw Peripheral GPIO hardware instance address.
544   * @param gpio_num gpio_num GPIO number of the pad.
545   * @param func The function number of the peripheral pin to output pin.
546   *        One of the ``FUNC_X_*`` of specified pin (X) in ``soc/io_mux_reg.h``.
547   * @param oen_inv True if the output enable needs to be inverted, otherwise False.
548   */
gpio_ll_iomux_out(gpio_dev_t * hw,uint8_t gpio_num,int func,uint32_t oen_inv)549 static inline void gpio_ll_iomux_out(gpio_dev_t *hw, uint8_t gpio_num, int func, uint32_t oen_inv)
550 {
551     hw->func_out_sel_cfg[gpio_num].oen_sel = 0;
552     hw->func_out_sel_cfg[gpio_num].oen_inv_sel = oen_inv;
553     gpio_ll_iomux_func_sel(GPIO_PIN_MUX_REG[gpio_num], func);
554 }
555 
556 /**
557  * @brief Get the GPIO number that is routed to the input peripheral signal through GPIO matrix.
558  *
559  * @param hw Peripheral GPIO hardware instance address.
560  * @param in_sig_idx Peripheral signal index (tagged as input attribute).
561  *
562  * @return
563  *    - -1     Signal bypassed GPIO matrix
564  *    - Others GPIO number
565  */
gpio_ll_get_in_signal_connected_io(gpio_dev_t * hw,uint32_t in_sig_idx)566 static inline int gpio_ll_get_in_signal_connected_io(gpio_dev_t *hw, uint32_t in_sig_idx)
567 {
568     typeof(hw->func_in_sel_cfg[in_sig_idx]) reg;
569     reg.val = hw->func_in_sel_cfg[in_sig_idx].val;
570     return (reg.sig_in_sel ? reg.func_sel : -1);
571 }
572 
573 /**
574   * @brief Force hold digital gpio pad.
575   * @note GPIO force hold, whether the chip in sleep mode or wakeup mode.
576   */
gpio_ll_force_hold_all(void)577 static inline void gpio_ll_force_hold_all(void)
578 {
579     CLEAR_PERI_REG_MASK(RTC_CNTL_DIG_ISO_REG, RTC_CNTL_DG_PAD_FORCE_UNHOLD);
580     SET_PERI_REG_MASK(RTC_CNTL_DIG_ISO_REG, RTC_CNTL_DG_PAD_FORCE_HOLD);
581 }
582 
583 /**
584   * @brief Force unhold digital gpio pad.
585   * @note GPIO force unhold, whether the chip in sleep mode or wakeup mode.
586   */
gpio_ll_force_unhold_all(void)587 static inline void gpio_ll_force_unhold_all(void)
588 {
589     CLEAR_PERI_REG_MASK(RTC_CNTL_DIG_ISO_REG, RTC_CNTL_DG_PAD_FORCE_HOLD);
590     SET_PERI_REG_MASK(RTC_CNTL_DIG_ISO_REG, RTC_CNTL_DG_PAD_FORCE_UNHOLD);
591     SET_PERI_REG_MASK(RTC_CNTL_DIG_ISO_REG, RTC_CNTL_CLR_DG_PAD_AUTOHOLD);
592 }
593 
594 /**
595   * @brief Enable GPIO pin used for wakeup from sleep.
596   *
597   * @param hw Peripheral GPIO hardware instance address.
598   * @param gpio_num GPIO number
599   */
gpio_ll_sleep_sel_en(gpio_dev_t * hw,uint32_t gpio_num)600 static inline void gpio_ll_sleep_sel_en(gpio_dev_t *hw, uint32_t gpio_num)
601 {
602     PIN_SLP_SEL_ENABLE(GPIO_PIN_MUX_REG[gpio_num]);
603 }
604 
605 /**
606   * @brief Disable GPIO pin used for wakeup from sleep.
607   *
608   * @param hw Peripheral GPIO hardware instance address.
609   * @param gpio_num GPIO number
610   */
gpio_ll_sleep_sel_dis(gpio_dev_t * hw,uint32_t gpio_num)611 static inline void gpio_ll_sleep_sel_dis(gpio_dev_t *hw, uint32_t gpio_num)
612 {
613     PIN_SLP_SEL_DISABLE(GPIO_PIN_MUX_REG[gpio_num]);
614 }
615 
616 /**
617   * @brief Disable GPIO pull-up in sleep mode.
618   *
619   * @param hw Peripheral GPIO hardware instance address.
620   * @param gpio_num GPIO number
621   */
gpio_ll_sleep_pullup_dis(gpio_dev_t * hw,uint32_t gpio_num)622 static inline void gpio_ll_sleep_pullup_dis(gpio_dev_t *hw, uint32_t gpio_num)
623 {
624     PIN_SLP_PULLUP_DISABLE(GPIO_PIN_MUX_REG[gpio_num]);
625 }
626 
627 /**
628   * @brief Enable GPIO pull-up in sleep mode.
629   *
630   * @param hw Peripheral GPIO hardware instance address.
631   * @param gpio_num GPIO number
632   */
gpio_ll_sleep_pullup_en(gpio_dev_t * hw,uint32_t gpio_num)633 static inline void gpio_ll_sleep_pullup_en(gpio_dev_t *hw, uint32_t gpio_num)
634 {
635     PIN_SLP_PULLUP_ENABLE(GPIO_PIN_MUX_REG[gpio_num]);
636 }
637 
638 /**
639   * @brief Enable GPIO pull-down in sleep mode.
640   *
641   * @param hw Peripheral GPIO hardware instance address.
642   * @param gpio_num GPIO number
643   */
gpio_ll_sleep_pulldown_en(gpio_dev_t * hw,uint32_t gpio_num)644 static inline void gpio_ll_sleep_pulldown_en(gpio_dev_t *hw, uint32_t gpio_num)
645 {
646     PIN_SLP_PULLDOWN_ENABLE(GPIO_PIN_MUX_REG[gpio_num]);
647 }
648 
649 /**
650   * @brief Disable GPIO pull-down in sleep mode.
651   *
652   * @param hw Peripheral GPIO hardware instance address.
653   * @param gpio_num GPIO number
654   */
gpio_ll_sleep_pulldown_dis(gpio_dev_t * hw,uint32_t gpio_num)655 static inline void gpio_ll_sleep_pulldown_dis(gpio_dev_t *hw, uint32_t gpio_num)
656 {
657     PIN_SLP_PULLDOWN_DISABLE(GPIO_PIN_MUX_REG[gpio_num]);
658 }
659 
660 /**
661   * @brief Disable GPIO input in sleep mode.
662   *
663   * @param hw Peripheral GPIO hardware instance address.
664   * @param gpio_num GPIO number
665   */
gpio_ll_sleep_input_disable(gpio_dev_t * hw,uint32_t gpio_num)666 static inline void gpio_ll_sleep_input_disable(gpio_dev_t *hw, uint32_t gpio_num)
667 {
668     PIN_SLP_INPUT_DISABLE(GPIO_PIN_MUX_REG[gpio_num]);
669 }
670 
671 /**
672   * @brief Enable GPIO input in sleep mode.
673   *
674   * @param hw Peripheral GPIO hardware instance address.
675   * @param gpio_num GPIO number
676   */
gpio_ll_sleep_input_enable(gpio_dev_t * hw,uint32_t gpio_num)677 static inline void gpio_ll_sleep_input_enable(gpio_dev_t *hw, uint32_t gpio_num)
678 {
679     PIN_SLP_INPUT_ENABLE(GPIO_PIN_MUX_REG[gpio_num]);
680 }
681 
682 /**
683   * @brief Disable GPIO output in sleep mode.
684   *
685   * @param hw Peripheral GPIO hardware instance address.
686   * @param gpio_num GPIO number
687   */
gpio_ll_sleep_output_disable(gpio_dev_t * hw,uint32_t gpio_num)688 static inline void gpio_ll_sleep_output_disable(gpio_dev_t *hw, uint32_t gpio_num)
689 {
690     PIN_SLP_OUTPUT_DISABLE(GPIO_PIN_MUX_REG[gpio_num]);
691 }
692 
693 /**
694   * @brief Enable GPIO output in sleep mode.
695   *
696   * @param hw Peripheral GPIO hardware instance address.
697   * @param gpio_num GPIO number
698   */
gpio_ll_sleep_output_enable(gpio_dev_t * hw,uint32_t gpio_num)699 static inline void gpio_ll_sleep_output_enable(gpio_dev_t *hw, uint32_t gpio_num)
700 {
701     PIN_SLP_OUTPUT_ENABLE(GPIO_PIN_MUX_REG[gpio_num]);
702 }
703 
704 #ifdef __cplusplus
705 }
706 #endif
707