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