gpio_hal_workaround.c 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111
  1. /*
  2. * SPDX-FileCopyrightText: 2015-2022 Espressif Systems (Shanghai) CO LTD
  3. *
  4. * SPDX-License-Identifier: Apache-2.0
  5. */
  6. // The HAL layer for GPIO (common part)
  7. //
  8. #include "esp_attr.h"
  9. #include "soc/soc.h"
  10. #include "hal/gpio_hal.h"
  11. #include "soc/soc_caps.h"
  12. #if CONFIG_GPIO_ESP32_SUPPORT_SWITCH_SLP_PULL
  13. typedef struct gpio_slp_mode_cfg {
  14. volatile uint16_t fun_pu[((SOC_GPIO_PIN_COUNT-1) >> 4) + 1];
  15. volatile uint16_t fun_pd[((SOC_GPIO_PIN_COUNT-1) >> 4) + 1];
  16. } gpio_slp_mode_cfg_t;
  17. static void gpio_hal_sleep_mode_setup_wrapper(
  18. gpio_hal_context_t *hal,
  19. uint32_t gpio_num,
  20. void (*opt)(gpio_hal_context_t *, uint32_t, void *)
  21. )
  22. {
  23. static DRAM_ATTR gpio_slp_mode_cfg_t gpio_cfg;
  24. if (opt) {
  25. (*opt)(hal, gpio_num, (void *)&gpio_cfg);
  26. }
  27. }
  28. /**
  29. * @brief GPIO pu/pd information backup function
  30. * @param hal gpio hal
  31. * @param gpio_num gpio num
  32. * @param args pointer for bitmap to backup GPIO pu/pd information
  33. */
  34. static void gpio_hal_fun_pupd_backup(gpio_hal_context_t *hal, uint32_t gpio_num, void *args)
  35. {
  36. /* On ESP32, setting SLP_PU, SLP_PD couldn`t change GPIO status
  37. * from FUN_PU, FUN_PD to SLP_PU, SLP_PD at sleep.
  38. * On the ESP32S2, it does.
  39. * The following code emulates ESP32S2`s behavior:
  40. */
  41. gpio_slp_mode_cfg_t *pcfg = (gpio_slp_mode_cfg_t *)args;
  42. if (gpio_ll_sleep_sel_is_enabled(hal->dev, gpio_num)) {
  43. /* Record fun_pu and fun_pd state in bitmap */
  44. if (gpio_ll_pullup_is_enabled(hal->dev, gpio_num)) {
  45. pcfg->fun_pu[gpio_num >> 4] |= BIT(gpio_num & 0xf);
  46. } else {
  47. pcfg->fun_pu[gpio_num >> 4] &= ~BIT(gpio_num & 0xf);
  48. }
  49. if (gpio_ll_pulldown_is_enabled(hal->dev, gpio_num)) {
  50. pcfg->fun_pd[gpio_num >> 4] |= BIT(gpio_num & 0xf);
  51. } else {
  52. pcfg->fun_pd[gpio_num >> 4] &= ~BIT(gpio_num & 0xf);
  53. }
  54. if (gpio_ll_sleep_pullup_is_enabled(hal->dev, gpio_num)) {
  55. gpio_ll_pullup_en(hal->dev, gpio_num);
  56. } else {
  57. gpio_ll_pullup_dis(hal->dev, gpio_num);
  58. }
  59. if (gpio_ll_sleep_pulldown_is_enabled(hal->dev, gpio_num)) {
  60. gpio_ll_pulldown_en(hal->dev, gpio_num);
  61. } else {
  62. gpio_ll_pulldown_dis(hal->dev, gpio_num);
  63. }
  64. }
  65. }
  66. /**
  67. * @brief GPIO pu/pd information backup function
  68. * @param hal gpio hal
  69. * @param gpio_num gpio num
  70. * @param args pointer for bitmap to restore GPIO pu/pd information
  71. */
  72. static void gpio_hal_fun_pupd_restore(gpio_hal_context_t *hal, uint32_t gpio_num, void *args)
  73. {
  74. /* On ESP32, setting SLP_PU, SLP_PD couldn`t change GPIO status
  75. * from SLP_PU, SLP_PD to FUN_PU, FUN_PD when it wakes up.
  76. * On the ESP32S2, it does.
  77. * The following code emulates ESP32S2`s behavior:
  78. */
  79. gpio_slp_mode_cfg_t *pcfg = (gpio_slp_mode_cfg_t *)args;
  80. if (gpio_ll_sleep_sel_is_enabled(hal->dev, gpio_num)) {
  81. if (pcfg->fun_pu[gpio_num >> 4] & BIT(gpio_num & 0xf)) {
  82. gpio_ll_pullup_en(hal->dev, gpio_num);
  83. } else {
  84. gpio_ll_pullup_dis(hal->dev, gpio_num);
  85. }
  86. if (pcfg->fun_pd[gpio_num >> 4] & BIT(gpio_num & 0xf)) {
  87. gpio_ll_pulldown_en(hal->dev, gpio_num);
  88. } else {
  89. gpio_ll_pulldown_dis(hal->dev, gpio_num);
  90. }
  91. }
  92. }
  93. void gpio_hal_sleep_pupd_config_apply(gpio_hal_context_t *hal, uint32_t gpio_num)
  94. {
  95. gpio_hal_sleep_mode_setup_wrapper(hal, gpio_num, gpio_hal_fun_pupd_backup);
  96. }
  97. void gpio_hal_sleep_pupd_config_unapply(gpio_hal_context_t *hal, uint32_t gpio_num)
  98. {
  99. gpio_hal_sleep_mode_setup_wrapper(hal, gpio_num, gpio_hal_fun_pupd_restore);
  100. }
  101. #endif