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