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