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