1 /*
2 * SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6
7 #include <stdint.h>
8 #include <stdlib.h>
9 #include <esp_types.h>
10 #include "sdkconfig.h"
11 #include "esp_attr.h"
12 #include "esp_log.h"
13 #include "soc/soc.h"
14 #include "soc/pcr_reg.h"
15 #include "esp_private/esp_pau.h"
16 #include "esp_private/periph_ctrl.h"
17
18 static __attribute__((unused)) const char *TAG = "pau_regdma";
19
20 typedef struct {
21 pau_hal_context_t *hal;
22 } pau_context_t;
23
PAU_instance(void)24 pau_context_t * __attribute__((weak)) IRAM_ATTR PAU_instance(void)
25 {
26 static pau_hal_context_t pau_hal = { .dev = NULL };
27 static pau_context_t pau_context = { .hal = &pau_hal };
28
29 /* periph_module_enable don not need to be put in iram because it is
30 * called before the flash is powered off and will not be called again. */
31
32 if (pau_hal.dev == NULL) {
33 pau_hal.dev = &PAU;
34 periph_module_enable(PERIPH_REGDMA_MODULE);
35 }
36
37 return &pau_context;
38 }
39
pau_regdma_set_entry_link_addr(pau_regdma_link_addr_t * link_entries)40 void pau_regdma_set_entry_link_addr(pau_regdma_link_addr_t *link_entries)
41 {
42 ESP_LOGD(TAG, "All link addresses %p,%p,%p,%p", (*link_entries)[0], (*link_entries)[1], (*link_entries)[2], (*link_entries)[3]);
43 pau_hal_set_regdma_entry_link_addr(PAU_instance()->hal, link_entries);
44 }
45
46 #if SOC_PM_SUPPORT_PMU_MODEM_STATE
pau_regdma_set_modem_link_addr(void * link_addr)47 void pau_regdma_set_modem_link_addr(void *link_addr)
48 {
49 pau_hal_set_regdma_modem_link_addr(PAU_instance()->hal, link_addr);
50 }
51
pau_regdma_trigger_modem_link_backup(void)52 void pau_regdma_trigger_modem_link_backup(void)
53 {
54 pau_hal_start_regdma_modem_link(PAU_instance()->hal, true);
55 pau_hal_stop_regdma_modem_link(PAU_instance()->hal);
56 }
57
pau_regdma_trigger_modem_link_restore(void)58 void pau_regdma_trigger_modem_link_restore(void)
59 {
60 pau_hal_start_regdma_modem_link(PAU_instance()->hal, false);
61 pau_hal_stop_regdma_modem_link(PAU_instance()->hal);
62 }
63 #endif
64
65 #if SOC_PM_RETENTION_SW_TRIGGER_REGDMA
pau_regdma_set_system_link_addr(void * link_addr)66 void IRAM_ATTR pau_regdma_set_system_link_addr(void *link_addr)
67 {
68 /* ESP32H2 use software to trigger REGDMA to restore instead of PMU,
69 * because regdma has power bug, so we need to manually set the clock
70 * for regdma before using it after the chip wakes up. We use
71 * pau_hal_clock_configure because periph_module_enable will consume
72 * a relatively large amount of memory space. */
73
74 pau_hal_regdma_clock_configure(PAU_instance()->hal, true);
75 pau_hal_set_regdma_system_link_addr(PAU_instance()->hal, link_addr);
76 }
77
pau_regdma_trigger_system_link_backup(void)78 void IRAM_ATTR pau_regdma_trigger_system_link_backup(void)
79 {
80 pau_hal_start_regdma_system_link(PAU_instance()->hal, true);
81 pau_hal_stop_regdma_system_link(PAU_instance()->hal);
82 }
83
pau_regdma_trigger_system_link_restore(void)84 void IRAM_ATTR pau_regdma_trigger_system_link_restore(void)
85 {
86 pau_hal_start_regdma_system_link(PAU_instance()->hal, false);
87 pau_hal_stop_regdma_system_link(PAU_instance()->hal);
88 }
89 #endif
90
pau_regdma_set_extra_link_addr(void * link_addr)91 void IRAM_ATTR pau_regdma_set_extra_link_addr(void *link_addr)
92 {
93 pau_hal_set_regdma_extra_link_addr(PAU_instance()->hal, link_addr);
94 }
95
pau_regdma_trigger_extra_link_backup(void)96 void IRAM_ATTR pau_regdma_trigger_extra_link_backup(void)
97 {
98 pau_hal_start_regdma_extra_link(PAU_instance()->hal, true);
99 pau_hal_stop_regdma_extra_link(PAU_instance()->hal);
100 }
101
pau_regdma_trigger_extra_link_restore(void)102 void IRAM_ATTR pau_regdma_trigger_extra_link_restore(void)
103 {
104 pau_hal_start_regdma_extra_link(PAU_instance()->hal, false);
105 pau_hal_stop_regdma_extra_link(PAU_instance()->hal);
106 }
107