1 /*
2  * SPDX-FileCopyrightText: 2022-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 soc/include/hal/readme.md
11  ******************************************************************************/
12 
13 // The LL layer for ESP32-H2 GPIO register operations
14 
15 #pragma once
16 
17 #include <stdlib.h>
18 #include <stdbool.h>
19 #include "soc/soc.h"
20 #include "soc/gpio_periph.h"
21 #include "soc/gpio_struct.h"
22 #include "soc/lp_aon_struct.h"
23 #include "soc/pmu_struct.h"
24 #include "soc/usb_serial_jtag_reg.h"
25 #include "soc/pcr_struct.h"
26 #include "soc/clk_tree_defs.h"
27 #include "hal/gpio_types.h"
28 #include "hal/misc.h"
29 #include "hal/assert.h"
30 
31 #ifdef __cplusplus
32 extern "C" {
33 #endif
34 
35 // Get GPIO hardware instance with giving gpio num
36 #define GPIO_LL_GET_HW(num) (((num) == 0) ? (&GPIO) : NULL)
37 
38 #define GPIO_LL_PRO_CPU_INTR_ENA      (BIT(0))
39 #define GPIO_LL_PRO_CPU_NMI_INTR_ENA  (BIT(1))
40 
41 /**
42  * @brief Get the configuration for an IO
43  *
44  * @param hw Peripheral GPIO hardware instance address.
45  * @param gpio_num GPIO number
46  * @param pu Pull-up enabled or not
47  * @param pd Pull-down enabled or not
48  * @param ie Input enabled or not
49  * @param oe Output enabled or not
50  * @param od Open-drain enabled or not
51  * @param drv Drive strength value
52  * @param fun_sel IOMUX function selection value
53  * @param sig_out Outputting peripheral signal index
54  * @param slp_sel Pin sleep mode enabled or not
55  */
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)56 static inline void gpio_ll_get_io_config(gpio_dev_t *hw, uint32_t gpio_num,
57                                          bool *pu, bool *pd, bool *ie, bool *oe, bool *od, uint32_t *drv,
58                                          uint32_t *fun_sel, uint32_t *sig_out, bool *slp_sel)
59 {
60     uint32_t bit_mask = 1 << gpio_num;
61     uint32_t iomux_reg_val = REG_READ(GPIO_PIN_MUX_REG[gpio_num]);
62     *pu = (iomux_reg_val & FUN_PU_M) >> FUN_PU_S;
63     *pd = (iomux_reg_val & FUN_PD_M) >> FUN_PD_S;
64     *ie = (iomux_reg_val & FUN_IE_M) >> FUN_IE_S;
65     *oe = (hw->enable.val & bit_mask) >> gpio_num;
66     *od = hw->pin[gpio_num].pad_driver;
67     *drv = (iomux_reg_val & FUN_DRV_M) >> FUN_DRV_S;
68     *fun_sel = (iomux_reg_val & MCU_SEL_M) >> MCU_SEL_S;
69     *sig_out = hw->func_out_sel_cfg[gpio_num].out_sel;
70     *slp_sel = (iomux_reg_val & SLP_SEL_M) >> SLP_SEL_S;
71 }
72 
73 /**
74   * @brief Enable pull-up on GPIO.
75   *
76   * @param hw Peripheral GPIO hardware instance address.
77   * @param gpio_num GPIO number
78   */
gpio_ll_pullup_en(gpio_dev_t * hw,gpio_num_t gpio_num)79 static inline void gpio_ll_pullup_en(gpio_dev_t *hw, gpio_num_t gpio_num)
80 {
81     REG_SET_BIT(IO_MUX_GPIO0_REG + (gpio_num * 4), FUN_PU);
82 }
83 
84 /**
85   * @brief Disable pull-up on GPIO.
86   *
87   * @param hw Peripheral GPIO hardware instance address.
88   * @param gpio_num GPIO number
89   */
90 __attribute__((always_inline))
gpio_ll_pullup_dis(gpio_dev_t * hw,gpio_num_t gpio_num)91 static inline void gpio_ll_pullup_dis(gpio_dev_t *hw, gpio_num_t gpio_num)
92 {
93     // The pull-up value of the USB pins are controlled by the pins’ pull-up value together with USB pull-up value
94     // USB DP pin is default to PU enabled
95     // Note that esp32h2 has supported USB_EXCHG_PINS feature. If this efuse is burnt, the gpio pin
96     // which should be checked is USB_INT_PHY0_DM_GPIO_NUM instead.
97     // TODO: read the specific efuse with efuse_ll.h
98     if (gpio_num == USB_DP_GPIO_NUM) {
99         SET_PERI_REG_MASK(USB_SERIAL_JTAG_CONF0_REG, USB_SERIAL_JTAG_PAD_PULL_OVERRIDE);
100         CLEAR_PERI_REG_MASK(USB_SERIAL_JTAG_CONF0_REG, USB_SERIAL_JTAG_DP_PULLUP);
101     }
102     REG_CLR_BIT(IO_MUX_GPIO0_REG + (gpio_num * 4), FUN_PU);
103 }
104 
105 /**
106   * @brief Enable pull-down on GPIO.
107   *
108   * @param hw Peripheral GPIO hardware instance address.
109   * @param gpio_num GPIO number
110   */
gpio_ll_pulldown_en(gpio_dev_t * hw,gpio_num_t gpio_num)111 static inline void gpio_ll_pulldown_en(gpio_dev_t *hw, gpio_num_t gpio_num)
112 {
113     REG_SET_BIT(IO_MUX_GPIO0_REG + (gpio_num * 4), FUN_PD);
114 }
115 
116 /**
117   * @brief Disable pull-down on GPIO.
118   *
119   * @param hw Peripheral GPIO hardware instance address.
120   * @param gpio_num GPIO number
121   */
122 __attribute__((always_inline))
gpio_ll_pulldown_dis(gpio_dev_t * hw,gpio_num_t gpio_num)123 static inline void gpio_ll_pulldown_dis(gpio_dev_t *hw, gpio_num_t gpio_num)
124 {
125     REG_CLR_BIT(IO_MUX_GPIO0_REG + (gpio_num * 4), FUN_PD);
126 }
127 
128 /**
129  * @brief  GPIO set interrupt trigger type
130  *
131  * @param  hw Peripheral GPIO hardware instance address.
132  * @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);
133  * @param  intr_type Interrupt type, select from gpio_int_type_t
134  */
gpio_ll_set_intr_type(gpio_dev_t * hw,gpio_num_t gpio_num,gpio_int_type_t intr_type)135 static inline void gpio_ll_set_intr_type(gpio_dev_t *hw, gpio_num_t gpio_num, gpio_int_type_t intr_type)
136 {
137     hw->pin[gpio_num].int_type = intr_type;
138 }
139 
140 /**
141   * @brief Get GPIO interrupt status
142   *
143   * @param hw Peripheral GPIO hardware instance address.
144   * @param core_id interrupt core id
145   * @param status interrupt status
146   */
147 __attribute__((always_inline))
gpio_ll_get_intr_status(gpio_dev_t * hw,uint32_t core_id,uint32_t * status)148 static inline void gpio_ll_get_intr_status(gpio_dev_t *hw, uint32_t core_id, uint32_t *status)
149 {
150     (void)core_id;
151     *status = hw->pcpu_int.procpu_int;
152 }
153 
154 /**
155   * @brief Get GPIO interrupt status high
156   *
157   * @param hw Peripheral GPIO hardware instance address.
158   * @param core_id interrupt core id
159   * @param status interrupt status high
160   */
161 __attribute__((always_inline))
gpio_ll_get_intr_status_high(gpio_dev_t * hw,uint32_t core_id,uint32_t * status)162 static inline void gpio_ll_get_intr_status_high(gpio_dev_t *hw, uint32_t core_id, uint32_t *status)
163 {
164     *status = 0; // Less than 32 GPIOs in ESP32-H2
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.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     // Less than 32 GPIOs on ESP32-H2 Do nothing.
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,gpio_num_t gpio_num)199 static inline void gpio_ll_intr_enable_on_core(gpio_dev_t *hw, uint32_t core_id, gpio_num_t gpio_num)
200 {
201     HAL_ASSERT(core_id == 0 && "target SoC only has a single core");
202     GPIO.pin[gpio_num].int_ena = GPIO_LL_PRO_CPU_INTR_ENA;     //enable pro cpu 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,gpio_num_t gpio_num)212 static inline void gpio_ll_intr_disable(gpio_dev_t *hw, gpio_num_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,gpio_num_t gpio_num)224 static inline void gpio_ll_input_disable(gpio_dev_t *hw, gpio_num_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,gpio_num_t gpio_num)235 static inline void gpio_ll_input_enable(gpio_dev_t *hw, gpio_num_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 Select gpio hysteresis control by efuse.
264   *
265   * @param hw Peripheral GPIO hardware instance address.
266   * @param gpio_num GPIO number
267   */
gpio_ll_pin_input_hysteresis_ctrl_sel_efuse(gpio_dev_t * hw,uint32_t gpio_num)268 static inline void gpio_ll_pin_input_hysteresis_ctrl_sel_efuse(gpio_dev_t *hw, uint32_t gpio_num)
269 {
270     PIN_HYS_EN_SEL_EFUSE(IO_MUX_GPIO0_REG + (gpio_num * 4));
271 }
272 
273 /**
274   * @brief Select gpio hysteresis control by software.
275   *
276   * @param hw Peripheral GPIO hardware instance address.
277   * @param gpio_num GPIO number
278   */
gpio_ll_pin_input_hysteresis_ctrl_sel_soft(gpio_dev_t * hw,uint32_t gpio_num)279 static inline void gpio_ll_pin_input_hysteresis_ctrl_sel_soft(gpio_dev_t *hw, uint32_t gpio_num)
280 {
281     PIN_HYS_EN_SEL_SOFT(IO_MUX_GPIO0_REG + (gpio_num * 4));
282 }
283 
284 /**
285   * @brief Enable gpio hysteresis if controlled by software.
286   *
287   * @param hw Peripheral GPIO hardware instance address.
288   * @param gpio_num GPIO number
289   */
gpio_ll_pin_input_hysteresis_enable(gpio_dev_t * hw,uint32_t gpio_num)290 static inline void gpio_ll_pin_input_hysteresis_enable(gpio_dev_t *hw, uint32_t gpio_num)
291 {
292     PIN_HYS_SOFT_ENABLE(IO_MUX_GPIO0_REG + (gpio_num * 4));
293 }
294 
295 /**
296   * @brief Disable gpio hysteresis if controlled by software.
297   *
298   * @param hw Peripheral GPIO hardware instance address.
299   * @param gpio_num GPIO number
300   */
gpio_ll_pin_input_hysteresis_disable(gpio_dev_t * hw,uint32_t gpio_num)301 static inline void gpio_ll_pin_input_hysteresis_disable(gpio_dev_t *hw, uint32_t gpio_num)
302 {
303     PIN_HYS_SOFT_DISABLE(IO_MUX_GPIO0_REG + (gpio_num * 4));
304 }
305 
306 /**
307   * @brief Disable output mode on GPIO.
308   *
309   * @param hw Peripheral GPIO hardware instance address.
310   * @param gpio_num GPIO number
311   */
312 __attribute__((always_inline))
gpio_ll_output_disable(gpio_dev_t * hw,gpio_num_t gpio_num)313 static inline void gpio_ll_output_disable(gpio_dev_t *hw, gpio_num_t gpio_num)
314 {
315     hw->enable_w1tc.enable_w1tc = (0x1 << gpio_num);
316     // Ensure no other output signal is routed via GPIO matrix to this pin
317     REG_WRITE(GPIO_FUNC0_OUT_SEL_CFG_REG + (gpio_num * 4), SIG_GPIO_OUT_IDX);
318 }
319 
320 /**
321   * @brief Enable output mode on GPIO.
322   *
323   * @param hw Peripheral GPIO hardware instance address.
324   * @param gpio_num GPIO number
325   */
gpio_ll_output_enable(gpio_dev_t * hw,gpio_num_t gpio_num)326 static inline void gpio_ll_output_enable(gpio_dev_t *hw, gpio_num_t gpio_num)
327 {
328     hw->enable_w1ts.enable_w1ts = (0x1 << gpio_num);
329 }
330 
331 /**
332   * @brief Disable open-drain mode on GPIO.
333   *
334   * @param hw Peripheral GPIO hardware instance address.
335   * @param gpio_num GPIO number
336   */
gpio_ll_od_disable(gpio_dev_t * hw,gpio_num_t gpio_num)337 static inline void gpio_ll_od_disable(gpio_dev_t *hw, gpio_num_t gpio_num)
338 {
339     hw->pin[gpio_num].pad_driver = 0;
340 }
341 
342 /**
343   * @brief Enable open-drain mode on GPIO.
344   *
345   * @param hw Peripheral GPIO hardware instance address.
346   * @param gpio_num GPIO number
347   */
gpio_ll_od_enable(gpio_dev_t * hw,gpio_num_t gpio_num)348 static inline void gpio_ll_od_enable(gpio_dev_t *hw, gpio_num_t gpio_num)
349 {
350     hw->pin[gpio_num].pad_driver = 1;
351 }
352 
353 /**
354  * @brief  GPIO set output level
355  *
356  * @param  hw Peripheral GPIO hardware instance address.
357  * @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);
358  * @param  level Output level. 0: low ; 1: high
359  */
360 __attribute__((always_inline))
gpio_ll_set_level(gpio_dev_t * hw,gpio_num_t gpio_num,uint32_t level)361 static inline void gpio_ll_set_level(gpio_dev_t *hw, gpio_num_t gpio_num, uint32_t level)
362 {
363     if (level) {
364         hw->out_w1ts.out_w1ts = (1 << gpio_num);
365     } else {
366         hw->out_w1tc.out_w1tc = (1 << gpio_num);
367     }
368 }
369 
370 /**
371  * @brief  GPIO get input level
372  *
373  * @warning If the pad is not configured for input (or input and output) the returned value is always 0.
374  *
375  * @param  hw Peripheral GPIO hardware instance address.
376  * @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);
377  *
378  * @return
379  *     - 0 the GPIO input level is 0
380  *     - 1 the GPIO input level is 1
381  */
gpio_ll_get_level(gpio_dev_t * hw,gpio_num_t gpio_num)382 static inline int gpio_ll_get_level(gpio_dev_t *hw, gpio_num_t gpio_num)
383 {
384     return (hw->in.in_data_next >> gpio_num) & 0x1;
385 }
386 
387 /**
388  * @brief Enable GPIO wake-up function.
389  *
390  * @param hw Peripheral GPIO hardware instance address.
391  * @param gpio_num GPIO number.
392  * @param intr_type GPIO wake-up type. Only GPIO_INTR_LOW_LEVEL or GPIO_INTR_HIGH_LEVEL can be used.
393  */
gpio_ll_wakeup_enable(gpio_dev_t * hw,gpio_num_t gpio_num)394 static inline void gpio_ll_wakeup_enable(gpio_dev_t *hw, gpio_num_t gpio_num)
395 {
396     hw->pin[gpio_num].wakeup_enable = 0x1;
397 }
398 
399 /**
400  * @brief Disable GPIO wake-up function.
401  *
402  * @param hw Peripheral GPIO hardware instance address.
403  * @param gpio_num GPIO number
404  */
gpio_ll_wakeup_disable(gpio_dev_t * hw,gpio_num_t gpio_num)405 static inline void gpio_ll_wakeup_disable(gpio_dev_t *hw, gpio_num_t gpio_num)
406 {
407     hw->pin[gpio_num].wakeup_enable = 0;
408 }
409 
410 /**
411   * @brief Set GPIO pad drive capability
412   *
413   * @param hw Peripheral GPIO hardware instance address.
414   * @param gpio_num GPIO number, only support output GPIOs
415   * @param strength Drive capability of the pad
416   */
gpio_ll_set_drive_capability(gpio_dev_t * hw,gpio_num_t gpio_num,gpio_drive_cap_t strength)417 static inline void gpio_ll_set_drive_capability(gpio_dev_t *hw, gpio_num_t gpio_num, gpio_drive_cap_t strength)
418 {
419     SET_PERI_REG_BITS(IO_MUX_GPIO0_REG + (gpio_num * 4), FUN_DRV_V, strength, FUN_DRV_S);
420 }
421 
422 /**
423   * @brief Get GPIO pad drive capability
424   *
425   * @param hw Peripheral GPIO hardware instance address.
426   * @param gpio_num GPIO number, only support output GPIOs
427   * @param strength Pointer to accept drive capability of the pad
428   */
gpio_ll_get_drive_capability(gpio_dev_t * hw,gpio_num_t gpio_num,gpio_drive_cap_t * strength)429 static inline void gpio_ll_get_drive_capability(gpio_dev_t *hw, gpio_num_t gpio_num, gpio_drive_cap_t *strength)
430 {
431     *strength = (gpio_drive_cap_t)GET_PERI_REG_BITS2(IO_MUX_GPIO0_REG + (gpio_num * 4), FUN_DRV_V, FUN_DRV_S);
432 }
433 
434 /**
435   * @brief Enable gpio pad hold function.
436   *
437   * @param hw Peripheral GPIO hardware instance address.
438   * @param gpio_num GPIO number, only support output GPIOs
439   */
gpio_ll_hold_en(gpio_dev_t * hw,gpio_num_t gpio_num)440 static inline void gpio_ll_hold_en(gpio_dev_t *hw, gpio_num_t gpio_num)
441 {
442     LP_AON.gpio_hold0.gpio_hold0 |= GPIO_HOLD_MASK[gpio_num];
443 }
444 
445 /**
446   * @brief Disable gpio pad hold function.
447   *
448   * @param hw Peripheral GPIO hardware instance address.
449   * @param gpio_num GPIO number, only support output GPIOs
450   */
gpio_ll_hold_dis(gpio_dev_t * hw,gpio_num_t gpio_num)451 static inline void gpio_ll_hold_dis(gpio_dev_t *hw, gpio_num_t gpio_num)
452 {
453     LP_AON.gpio_hold0.gpio_hold0 &= ~GPIO_HOLD_MASK[gpio_num];
454 }
455 
456 /**
457   * @brief Set pad input to a peripheral signal through the IOMUX.
458   *
459   * @param hw Peripheral GPIO hardware instance address.
460   * @param gpio_num GPIO number of the pad.
461   * @param signal_idx Peripheral signal id to input. One of the ``*_IN_IDX`` signals in ``soc/gpio_sig_map.h``.
462   */
463 __attribute__((always_inline))
gpio_ll_iomux_in(gpio_dev_t * hw,uint32_t gpio,uint32_t signal_idx)464 static inline void gpio_ll_iomux_in(gpio_dev_t *hw, uint32_t gpio, uint32_t signal_idx)
465 {
466     hw->func_in_sel_cfg[signal_idx].sig_in_sel = 0;
467     PIN_INPUT_ENABLE(IO_MUX_GPIO0_REG + (gpio * 4));
468 }
469 
470 /**
471  * @brief  Select a function for the pin in the IOMUX
472  *
473  * @param  pin_name Pin name to configure
474  * @param  func Function to assign to the pin
475  */
gpio_ll_iomux_func_sel(uint32_t pin_name,uint32_t func)476 static inline void gpio_ll_iomux_func_sel(uint32_t pin_name, uint32_t func)
477 {
478     // Disable USB Serial JTAG if pins 26 or pins 27 needs to select an IOMUX function
479     if (pin_name == IO_MUX_GPIO26_REG || pin_name == IO_MUX_GPIO27_REG) {
480         CLEAR_PERI_REG_MASK(USB_SERIAL_JTAG_CONF0_REG, USB_SERIAL_JTAG_USB_PAD_ENABLE);
481     }
482     PIN_FUNC_SELECT(pin_name, func);
483 }
484 
485 /**
486  * @brief  Select a function for the pin in the IOMUX
487  *
488  * @param  hw Peripheral GPIO hardware instance address.
489  * @param  gpio_num GPIO number
490  * @param  func Function to assign to the pin
491  */
492 __attribute__((always_inline))
gpio_ll_func_sel(gpio_dev_t * hw,uint8_t gpio_num,uint32_t func)493 static inline void gpio_ll_func_sel(gpio_dev_t *hw, uint8_t gpio_num, uint32_t func)
494 {
495     // Disable USB Serial JTAG if pins 26 or pins 27 needs to select an IOMUX function
496     if (gpio_num == USB_DM_GPIO_NUM || gpio_num == USB_DP_GPIO_NUM) {
497         CLEAR_PERI_REG_MASK(USB_SERIAL_JTAG_CONF0_REG, USB_SERIAL_JTAG_USB_PAD_ENABLE);
498     }
499     PIN_FUNC_SELECT(IO_MUX_GPIO0_REG + (gpio_num * 4), func);
500 }
501 
502 /**
503   * @brief Set peripheral output to an GPIO pad through the IOMUX.
504   *
505   * @param hw Peripheral GPIO hardware instance address.
506   * @param gpio_num gpio_num GPIO number of the pad.
507   * @param func The function number of the peripheral pin to output pin.
508   *        One of the ``FUNC_X_*`` of specified pin (X) in ``soc/io_mux_reg.h``.
509   * @param oen_inv True if the output enable needs to be inverted, otherwise False.
510   */
gpio_ll_iomux_out(gpio_dev_t * hw,uint8_t gpio_num,int func,uint32_t oen_inv)511 static inline void gpio_ll_iomux_out(gpio_dev_t *hw, uint8_t gpio_num, int func, uint32_t oen_inv)
512 {
513     hw->func_out_sel_cfg[gpio_num].oen_sel = 0;
514     hw->func_out_sel_cfg[gpio_num].oen_inv_sel = oen_inv;
515     gpio_ll_iomux_func_sel(IO_MUX_GPIO0_REG + (gpio_num * 4), func);
516 }
517 
518 /**
519  * @brief Set clock source of IO MUX module
520  *
521  * @param src IO MUX clock source (only a subset of soc_module_clk_t values are valid)
522  */
gpio_ll_iomux_set_clk_src(soc_module_clk_t src)523 static inline void gpio_ll_iomux_set_clk_src(soc_module_clk_t src)
524 {
525     switch (src) {
526     case SOC_MOD_CLK_XTAL:
527         PCR.iomux_clk_conf.iomux_func_clk_sel = 0;
528         break;
529     case SOC_MOD_CLK_PLL_F48M:
530         PCR.iomux_clk_conf.iomux_func_clk_sel = 2;
531         break;
532     default:
533         // Unsupported IO_MUX clock source
534         HAL_ASSERT(false);
535     }
536 }
537 
538 /**
539  * @brief Get the GPIO number that is routed to the input peripheral signal through GPIO matrix.
540  *
541  * @param hw Peripheral GPIO hardware instance address.
542  * @param in_sig_idx Peripheral signal index (tagged as input attribute).
543  *
544  * @return
545  *    - -1     Signal bypassed GPIO matrix
546  *    - Others GPIO number
547  */
gpio_ll_get_in_signal_connected_io(gpio_dev_t * hw,uint32_t in_sig_idx)548 static inline int gpio_ll_get_in_signal_connected_io(gpio_dev_t *hw, uint32_t in_sig_idx)
549 {
550     gpio_func_in_sel_cfg_reg_t reg;
551     reg.val = hw->func_in_sel_cfg[in_sig_idx].val;
552     return (reg.sig_in_sel ? reg.in_sel : -1);
553 }
554 
555 /**
556   * @brief Force hold all digital(VDDPST2) and lp(VDDPST1) io pads.
557   * @note GPIO force hold, whether the chip in sleep mode or wakeup mode.
558   */
gpio_ll_force_hold_all(void)559 static inline void gpio_ll_force_hold_all(void)
560 {
561     // WT flags, they get self-cleared after the configuration is done
562     PMU.imm.pad_hold_all.tie_high_hp_pad_hold_all = 1;
563     PMU.imm.pad_hold_all.tie_high_lp_pad_hold_all = 1;
564 }
565 
566 /**
567   * @brief Force unhold all digital(VDDPST2) and lp(VDDPST1) io pads.
568   * @note GPIO force unhold, whether the chip in sleep mode or wakeup mode.
569   */
gpio_ll_force_unhold_all(void)570 static inline void gpio_ll_force_unhold_all(void)
571 {
572     // WT flags, they get self-cleared after the configuration is done
573     PMU.imm.pad_hold_all.tie_low_hp_pad_hold_all = 1;
574     PMU.imm.pad_hold_all.tie_low_lp_pad_hold_all = 1;
575 }
576 
577 /**
578   * @brief Enable GPIO pin to use sleep mode pin functions during light sleep.
579   *
580   * @param hw Peripheral GPIO hardware instance address.
581   * @param gpio_num GPIO number
582   */
gpio_ll_sleep_sel_en(gpio_dev_t * hw,gpio_num_t gpio_num)583 static inline void gpio_ll_sleep_sel_en(gpio_dev_t *hw, gpio_num_t gpio_num)
584 {
585     PIN_SLP_SEL_ENABLE(IO_MUX_GPIO0_REG + (gpio_num * 4));
586 }
587 
588 /**
589   * @brief Disable GPIO pin to use sleep mode pin functions during light sleep.
590   * Pin functions remains the same in both normal execution and in light-sleep mode.
591   *
592   * @param hw Peripheral GPIO hardware instance address.
593   * @param gpio_num GPIO number
594   */
gpio_ll_sleep_sel_dis(gpio_dev_t * hw,gpio_num_t gpio_num)595 static inline void gpio_ll_sleep_sel_dis(gpio_dev_t *hw, gpio_num_t gpio_num)
596 {
597     PIN_SLP_SEL_DISABLE(IO_MUX_GPIO0_REG + (gpio_num * 4));
598 }
599 
600 /**
601   * @brief Disable GPIO pull-up in sleep mode.
602   *
603   * @param hw Peripheral GPIO hardware instance address.
604   * @param gpio_num GPIO number
605   */
gpio_ll_sleep_pullup_dis(gpio_dev_t * hw,gpio_num_t gpio_num)606 static inline void gpio_ll_sleep_pullup_dis(gpio_dev_t *hw, gpio_num_t gpio_num)
607 {
608     PIN_SLP_PULLUP_DISABLE(IO_MUX_GPIO0_REG + (gpio_num * 4));
609 }
610 
611 /**
612   * @brief Enable GPIO pull-up in sleep mode.
613   *
614   * @param hw Peripheral GPIO hardware instance address.
615   * @param gpio_num GPIO number
616   */
gpio_ll_sleep_pullup_en(gpio_dev_t * hw,gpio_num_t gpio_num)617 static inline void gpio_ll_sleep_pullup_en(gpio_dev_t *hw, gpio_num_t gpio_num)
618 {
619     PIN_SLP_PULLUP_ENABLE(IO_MUX_GPIO0_REG + (gpio_num * 4));
620 }
621 
622 /**
623   * @brief Enable GPIO pull-down in sleep mode.
624   *
625   * @param hw Peripheral GPIO hardware instance address.
626   * @param gpio_num GPIO number
627   */
gpio_ll_sleep_pulldown_en(gpio_dev_t * hw,gpio_num_t gpio_num)628 static inline void gpio_ll_sleep_pulldown_en(gpio_dev_t *hw, gpio_num_t gpio_num)
629 {
630     PIN_SLP_PULLDOWN_ENABLE(IO_MUX_GPIO0_REG + (gpio_num * 4));
631 }
632 
633 /**
634   * @brief Disable GPIO pull-down in sleep mode.
635   *
636   * @param hw Peripheral GPIO hardware instance address.
637   * @param gpio_num GPIO number
638   */
gpio_ll_sleep_pulldown_dis(gpio_dev_t * hw,gpio_num_t gpio_num)639 static inline void gpio_ll_sleep_pulldown_dis(gpio_dev_t *hw, gpio_num_t gpio_num)
640 {
641     PIN_SLP_PULLDOWN_DISABLE(IO_MUX_GPIO0_REG + (gpio_num * 4));
642 }
643 
644 /**
645   * @brief Disable GPIO input in sleep mode.
646   *
647   * @param hw Peripheral GPIO hardware instance address.
648   * @param gpio_num GPIO number
649   */
gpio_ll_sleep_input_disable(gpio_dev_t * hw,gpio_num_t gpio_num)650 static inline void gpio_ll_sleep_input_disable(gpio_dev_t *hw, gpio_num_t gpio_num)
651 {
652     PIN_SLP_INPUT_DISABLE(IO_MUX_GPIO0_REG + (gpio_num * 4));
653 }
654 
655 /**
656   * @brief Enable GPIO input in sleep mode.
657   *
658   * @param hw Peripheral GPIO hardware instance address.
659   * @param gpio_num GPIO number
660   */
gpio_ll_sleep_input_enable(gpio_dev_t * hw,gpio_num_t gpio_num)661 static inline void gpio_ll_sleep_input_enable(gpio_dev_t *hw, gpio_num_t gpio_num)
662 {
663     PIN_SLP_INPUT_ENABLE(IO_MUX_GPIO0_REG + (gpio_num * 4));
664 }
665 
666 /**
667   * @brief Disable GPIO output in sleep mode.
668   *
669   * @param hw Peripheral GPIO hardware instance address.
670   * @param gpio_num GPIO number
671   */
gpio_ll_sleep_output_disable(gpio_dev_t * hw,gpio_num_t gpio_num)672 static inline void gpio_ll_sleep_output_disable(gpio_dev_t *hw, gpio_num_t gpio_num)
673 {
674     PIN_SLP_OUTPUT_DISABLE(IO_MUX_GPIO0_REG + (gpio_num * 4));
675 }
676 
677 /**
678   * @brief Enable GPIO output in sleep mode.
679   *
680   * @param hw Peripheral GPIO hardware instance address.
681   * @param gpio_num GPIO number
682   */
gpio_ll_sleep_output_enable(gpio_dev_t * hw,gpio_num_t gpio_num)683 static inline void gpio_ll_sleep_output_enable(gpio_dev_t *hw, gpio_num_t gpio_num)
684 {
685     PIN_SLP_OUTPUT_ENABLE(IO_MUX_GPIO0_REG + (gpio_num * 4));
686 }
687 
688 /**
689  * @brief Enable GPIO deep-sleep wake-up function.
690  *
691  * @param hw Peripheral GPIO hardware instance address.
692  * @param gpio_num GPIO number.
693  * @param intr_type GPIO wake-up type. Only GPIO_INTR_LOW_LEVEL or GPIO_INTR_HIGH_LEVEL can be used.
694  */
gpio_ll_deepsleep_wakeup_enable(gpio_dev_t * hw,gpio_num_t gpio_num,gpio_int_type_t intr_type)695 static inline void gpio_ll_deepsleep_wakeup_enable(gpio_dev_t *hw, gpio_num_t gpio_num, gpio_int_type_t intr_type)
696 {
697     HAL_ASSERT((gpio_num >= GPIO_NUM_7 && gpio_num <= GPIO_NUM_14) &&
698                "only gpio7~14 support deep sleep wake-up function");
699 
700     LP_AON.ext_wakeup_cntl.ext_wakeup_filter = 1;
701 
702     uint32_t wakeup_sel_mask = HAL_FORCE_READ_U32_REG_FIELD(LP_AON.ext_wakeup_cntl, ext_wakeup_sel);
703     wakeup_sel_mask |= BIT(gpio_num - 7);
704     HAL_FORCE_MODIFY_U32_REG_FIELD(LP_AON.ext_wakeup_cntl, ext_wakeup_sel, wakeup_sel_mask);
705 
706     bool trigger_level = (intr_type == GPIO_INTR_LOW_LEVEL) ? 0 : 1;
707     uint32_t wakeup_level_mask = HAL_FORCE_READ_U32_REG_FIELD(LP_AON.ext_wakeup_cntl, ext_wakeup_lv);
708     if (trigger_level) {
709         wakeup_level_mask |= BIT(gpio_num - 7);
710     } else {
711         wakeup_level_mask &= ~BIT(gpio_num - 7);
712     }
713     HAL_FORCE_MODIFY_U32_REG_FIELD(LP_AON.ext_wakeup_cntl, ext_wakeup_lv, wakeup_level_mask);
714 }
715 
716 /**
717  * @brief Disable GPIO deep-sleep wake-up function.
718  *
719  * @param hw Peripheral GPIO hardware instance address.
720  * @param gpio_num GPIO number
721  */
gpio_ll_deepsleep_wakeup_disable(gpio_dev_t * hw,gpio_num_t gpio_num)722 static inline void gpio_ll_deepsleep_wakeup_disable(gpio_dev_t *hw, gpio_num_t gpio_num)
723 {
724     HAL_ASSERT((gpio_num >= GPIO_NUM_7 && gpio_num <= GPIO_NUM_14) &&
725                "only gpio7~14 support deep sleep wake-up function");
726 
727     uint32_t wakeup_sel_mask = HAL_FORCE_READ_U32_REG_FIELD(LP_AON.ext_wakeup_cntl, ext_wakeup_sel);
728     wakeup_sel_mask &= ~BIT(gpio_num - 7);
729     HAL_FORCE_MODIFY_U32_REG_FIELD(LP_AON.ext_wakeup_cntl, ext_wakeup_sel, wakeup_sel_mask);
730 }
731 
732 /**
733  * @brief Get the status of whether an IO is used for deep-sleep wake-up.
734  *
735  * @param hw Peripheral GPIO hardware instance address.
736  * @param gpio_num GPIO number
737  * @return True if the pin is enabled to wake up from deep-sleep
738  */
gpio_ll_deepsleep_wakeup_is_enabled(gpio_dev_t * hw,uint32_t gpio_num)739 static inline bool gpio_ll_deepsleep_wakeup_is_enabled(gpio_dev_t *hw, uint32_t gpio_num)
740 {
741     HAL_ASSERT((gpio_num >= GPIO_NUM_7 && gpio_num <= GPIO_NUM_14) &&
742                "only gpio7~14 support deep sleep wake-up function");
743 
744     uint32_t wakeup_sel_mask = HAL_FORCE_READ_U32_REG_FIELD(LP_AON.ext_wakeup_cntl, ext_wakeup_sel);
745     return wakeup_sel_mask & BIT(gpio_num - 7);
746 }
747 
748 #ifdef __cplusplus
749 }
750 #endif
751