diff --git a/components/esp_system/port/soc/esp32p4/system_internal.c b/components/esp_system/port/soc/esp32p4/system_internal.c index e1ba50c1ef..cd9c84908e 100644 --- a/components/esp_system/port/soc/esp32p4/system_internal.c +++ b/components/esp_system/port/soc/esp32p4/system_internal.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2022-2024 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2022-2025 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -27,6 +27,10 @@ #include "soc/hp_sys_clkrst_reg.h" #include "soc/lp_clkrst_reg.h" #include "soc/hp_system_reg.h" +#include "hal/gdma_ll.h" +#include "hal/axi_dma_ll.h" +#include "hal/dw_gdma_ll.h" +#include "hal/dma2d_ll.h" void IRAM_ATTR esp_system_reset_modules_on_exit(void) { @@ -37,6 +41,32 @@ void IRAM_ATTR esp_system_reset_modules_on_exit(void) } } + // Note: AXI bus doesn't allow an undergoing transaction to be interrupted in the middle + // If you want to reset a AXI master, you should make sure that the master is in IDLE first + if (gdma_ll_is_bus_clock_enabled(1)) { + for (int i = 0; i < GDMA_LL_AXI_PAIRS_PER_GROUP; i++) { + axi_dma_ll_tx_abort(AXI_DMA_LL_GET_HW(0), i, true); + axi_dma_ll_rx_abort(AXI_DMA_LL_GET_HW(0), i, true); + while (!axi_dma_ll_tx_is_reset_avail(AXI_DMA_LL_GET_HW(0), i)); + while (!axi_dma_ll_rx_is_reset_avail(AXI_DMA_LL_GET_HW(0), i)); + } + } + if (dma2d_ll_is_bus_clock_enabled(0)) { + for (int i = 0; i < SOC_DMA2D_RX_CHANNELS_PER_GROUP; i++) { + dma2d_ll_rx_abort(DMA2D_LL_GET_HW(0), i, true); + while (!dma2d_ll_rx_is_reset_avail(DMA2D_LL_GET_HW(0), i)); + } + for (int i = 0; i < SOC_DMA2D_TX_CHANNELS_PER_GROUP; i++) { + dma2d_ll_tx_abort(DMA2D_LL_GET_HW(0), i, true); + while (!dma2d_ll_tx_is_reset_avail(DMA2D_LL_GET_HW(0), i)); + } + } + if (dw_gdma_ll_is_bus_clock_enabled(0)) { + for (int i = 0; i < DW_GDMA_LL_CHANNELS_PER_GROUP; i++) { + dw_gdma_ll_channel_abort(DW_GDMA_LL_GET_HW(0), i); + } + } + // Set Peripheral clk rst SET_PERI_REG_MASK(HP_SYS_CLKRST_HP_RST_EN1_REG, HP_SYS_CLKRST_REG_RST_EN_TIMERGRP1); SET_PERI_REG_MASK(HP_SYS_CLKRST_HP_RST_EN1_REG, HP_SYS_CLKRST_REG_RST_EN_STIMER); @@ -47,7 +77,6 @@ void IRAM_ATTR esp_system_reset_modules_on_exit(void) SET_PERI_REG_MASK(HP_SYS_CLKRST_HP_RST_EN1_REG, HP_SYS_CLKRST_REG_RST_EN_UART2_CORE); SET_PERI_REG_MASK(HP_SYS_CLKRST_HP_RST_EN1_REG, HP_SYS_CLKRST_REG_RST_EN_UART3_CORE); SET_PERI_REG_MASK(HP_SYS_CLKRST_HP_RST_EN1_REG, HP_SYS_CLKRST_REG_RST_EN_UART4_CORE); - SET_PERI_REG_MASK(HP_SYS_CLKRST_HP_RST_EN0_REG, HP_SYS_CLKRST_REG_RST_EN_GDMA); SET_PERI_REG_MASK(HP_SYS_CLKRST_HP_RST_EN2_REG, HP_SYS_CLKRST_REG_RST_EN_ADC); // Clear Peripheral clk rst @@ -60,7 +89,6 @@ void IRAM_ATTR esp_system_reset_modules_on_exit(void) CLEAR_PERI_REG_MASK(HP_SYS_CLKRST_HP_RST_EN1_REG, HP_SYS_CLKRST_REG_RST_EN_UART2_CORE); CLEAR_PERI_REG_MASK(HP_SYS_CLKRST_HP_RST_EN1_REG, HP_SYS_CLKRST_REG_RST_EN_UART3_CORE); CLEAR_PERI_REG_MASK(HP_SYS_CLKRST_HP_RST_EN1_REG, HP_SYS_CLKRST_REG_RST_EN_UART4_CORE); - CLEAR_PERI_REG_MASK(HP_SYS_CLKRST_HP_RST_EN0_REG, HP_SYS_CLKRST_REG_RST_EN_GDMA); CLEAR_PERI_REG_MASK(HP_SYS_CLKRST_HP_RST_EN2_REG, HP_SYS_CLKRST_REG_RST_EN_ADC); #if CONFIG_ESP32P4_REV_MIN_FULL <= 100 diff --git a/components/hal/dma2d_hal.c b/components/hal/dma2d_hal.c index ff533ff209..f632881e62 100644 --- a/components/hal/dma2d_hal.c +++ b/components/hal/dma2d_hal.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2023-2025 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -14,16 +14,16 @@ void dma2d_hal_init(dma2d_hal_context_t *hal, int group_id) void dma2d_hal_tx_reset_channel(dma2d_hal_context_t *hal, uint32_t channel) { - dma2d_ll_tx_disable_cmd(hal->dev, channel, true); + dma2d_ll_tx_abort(hal->dev, channel, true); while (!dma2d_ll_tx_is_reset_avail(hal->dev, channel)); dma2d_ll_tx_reset_channel(hal->dev, channel); - dma2d_ll_tx_disable_cmd(hal->dev, channel, false); + dma2d_ll_tx_abort(hal->dev, channel, false); } void dma2d_hal_rx_reset_channel(dma2d_hal_context_t *hal, uint32_t channel) { - dma2d_ll_rx_disable_cmd(hal->dev, channel, true); + dma2d_ll_rx_abort(hal->dev, channel, true); while (!dma2d_ll_rx_is_reset_avail(hal->dev, channel)); dma2d_ll_rx_reset_channel(hal->dev, channel); - dma2d_ll_rx_disable_cmd(hal->dev, channel, false); + dma2d_ll_rx_abort(hal->dev, channel, false); } diff --git a/components/hal/dw_gdma_hal.c b/components/hal/dw_gdma_hal.c index 1549b0dde3..df49f51f4c 100644 --- a/components/hal/dw_gdma_hal.c +++ b/components/hal/dw_gdma_hal.c @@ -11,7 +11,7 @@ void dw_gdma_hal_init(dw_gdma_hal_context_t *hal, const dw_gdma_hal_config_t *config) { - hal->dev = DW_GDMA_LL_GET_HW(); + hal->dev = DW_GDMA_LL_GET_HW(0); dw_gdma_ll_reset(hal->dev); dw_gdma_ll_enable_controller(hal->dev, true); dw_gdma_ll_enable_intr_global(hal->dev, true); diff --git a/components/hal/esp32p4/include/hal/axi_dma_ll.h b/components/hal/esp32p4/include/hal/axi_dma_ll.h index 923dcc66ac..a6c5a2dae1 100644 --- a/components/hal/esp32p4/include/hal/axi_dma_ll.h +++ b/components/hal/esp32p4/include/hal/axi_dma_ll.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2022-2024 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2022-2025 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -195,6 +195,15 @@ static inline void axi_dma_ll_rx_stop(axi_dma_dev_t *dev, uint32_t channel) dev->in[channel].conf.in_link1.inlink_stop_chn = 1; } +/** + * @brief Abort the RX channel, stop the undergoing transfer immediately + */ +__attribute__((always_inline)) +static inline void axi_dma_ll_rx_abort(axi_dma_dev_t *dev, uint32_t channel, bool abort) +{ + dev->in[channel].conf.in_conf0.in_cmd_disable_chn = abort; +} + /** * @brief Restart a new inlink right after the last descriptor */ @@ -291,6 +300,15 @@ static inline void axi_dma_ll_rx_enable_ext_mem_ecc_aes_access(axi_dma_dev_t *de dev->in[channel].conf.in_conf0.in_ecc_aes_en_chn = enable; } +/** + * @brief Return if the channel is ready to be reset + */ +__attribute__((always_inline)) +static inline bool axi_dma_ll_rx_is_reset_avail(axi_dma_dev_t *dev, uint32_t channel) +{ + return dev->in_reset_avail_chn[channel].in_reset_avail_chn; +} + ///////////////////////////////////// TX ///////////////////////////////////////// /** * @brief Get DMA TX channel interrupt status word @@ -429,6 +447,15 @@ static inline void axi_dma_ll_tx_stop(axi_dma_dev_t *dev, uint32_t channel) dev->out[channel].conf.out_link1.outlink_stop_chn = 1; } +/** + * @brief Abort the TX channel, stop the undergoing transfer immediately + */ +__attribute__((always_inline)) +static inline void axi_dma_ll_tx_abort(axi_dma_dev_t *dev, uint32_t channel, bool abort) +{ + dev->out[channel].conf.out_conf0.out_cmd_disable_chn = abort; +} + /** * @brief Restart a new outlink right after the last descriptor */ @@ -507,6 +534,15 @@ static inline void axi_dma_ll_tx_enable_ext_mem_ecc_aes_access(axi_dma_dev_t *de dev->out[channel].conf.out_conf0.out_ecc_aes_en_chn = enable; } +/** + * @brief Return if the channel is ready to be reset + */ +__attribute__((always_inline)) +static inline bool axi_dma_ll_tx_is_reset_avail(axi_dma_dev_t *dev, uint32_t channel) +{ + return dev->out_reset_avail_chn[channel].out_reset_avail_chn; +} + ///////////////////////////////////// CRC-TX ///////////////////////////////////////// /** diff --git a/components/hal/esp32p4/include/hal/dma2d_ll.h b/components/hal/esp32p4/include/hal/dma2d_ll.h index 8ec6f91ea4..f36fcdd433 100644 --- a/components/hal/esp32p4/include/hal/dma2d_ll.h +++ b/components/hal/esp32p4/include/hal/dma2d_ll.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2023-2025 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -105,6 +105,16 @@ static inline void dma2d_ll_reset_register(int group_id) /// the critical section needs to declare the __DECLARE_RCC_ATOMIC_ENV variable in advance #define dma2d_ll_reset_register(...) (void)__DECLARE_RCC_ATOMIC_ENV; dma2d_ll_reset_register(__VA_ARGS__) +/** + * @brief Check if the bus clock is enabled for the DMA module + */ +__attribute__((always_inline)) +static inline bool dma2d_ll_is_bus_clock_enabled(int group_id) +{ + (void) group_id; + return HP_SYS_CLKRST.soc_clk_ctrl1.reg_dma2d_sys_clk_en; +} + /** * @brief Enable 2D-DMA module */ @@ -278,7 +288,7 @@ static inline bool dma2d_ll_rx_is_reset_avail(dma2d_dev_t *dev, uint32_t channel * @brief Disable 2D-DMA RX channel via a command */ __attribute__((always_inline)) -static inline void dma2d_ll_rx_disable_cmd(dma2d_dev_t *dev, uint32_t channel, bool disable) +static inline void dma2d_ll_rx_abort(dma2d_dev_t *dev, uint32_t channel, bool disable) { volatile dma2d_in_conf0_chn_reg_t *reg = (volatile dma2d_in_conf0_chn_reg_t *)DMA2D_LL_IN_CHANNEL_GET_REG_ADDR(dev, channel, in_conf0); reg->in_cmd_disable_chn = disable; @@ -811,7 +821,7 @@ static inline bool dma2d_ll_tx_is_reset_avail(dma2d_dev_t *dev, uint32_t channel * @brief Disable 2D-DMA TX channel via a command */ __attribute__((always_inline)) -static inline void dma2d_ll_tx_disable_cmd(dma2d_dev_t *dev, uint32_t channel, bool disable) +static inline void dma2d_ll_tx_abort(dma2d_dev_t *dev, uint32_t channel, bool disable) { dev->out_channel[channel].out_conf0.out_cmd_disable_chn = disable; } diff --git a/components/hal/esp32p4/include/hal/dw_gdma_ll.h b/components/hal/esp32p4/include/hal/dw_gdma_ll.h index efe817b8e3..e206928844 100644 --- a/components/hal/esp32p4/include/hal/dw_gdma_ll.h +++ b/components/hal/esp32p4/include/hal/dw_gdma_ll.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2023-2025 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -15,7 +15,7 @@ #include "soc/hp_sys_clkrst_struct.h" #include "soc/reg_base.h" -#define DW_GDMA_LL_GET_HW() (&DW_GDMA) +#define DW_GDMA_LL_GET_HW(id) (((id) == 0) ? (&DW_GDMA) : NULL) #define DW_GDMA_LL_GROUPS 1 // there's one DW-GDMA instance connected to the AXI bus #define DW_GDMA_LL_CHANNELS_PER_GROUP 4 // there are 4 independent channels in the DW-GDMA @@ -101,7 +101,7 @@ static inline void dw_gdma_ll_enable_bus_clock(int group_id, bool enable) /** * @brief Reset the DMA module */ -static inline void dw_gdma_ll_reset_register(int group_id) +static inline void _dw_gdma_ll_reset_register(int group_id) { (void)group_id; HP_SYS_CLKRST.hp_rst_en0.reg_rst_en_gdma = 1; @@ -110,7 +110,17 @@ static inline void dw_gdma_ll_reset_register(int group_id) /// use a macro to wrap the function, force the caller to use it in a critical section /// the critical section needs to declare the __DECLARE_RCC_ATOMIC_ENV variable in advance -#define dw_gdma_ll_reset_register(...) (void)__DECLARE_RCC_ATOMIC_ENV; dw_gdma_ll_reset_register(__VA_ARGS__) +#define dw_gdma_ll_reset_register(...) (void)__DECLARE_RCC_ATOMIC_ENV; _dw_gdma_ll_reset_register(__VA_ARGS__) + +/** + * @brief Check if the bus clock is enabled for the DMA module + */ +__attribute__((always_inline)) +static inline bool dw_gdma_ll_is_bus_clock_enabled(int group_id) +{ + (void) group_id; + return HP_SYS_CLKRST.soc_clk_ctrl1.reg_gdma_sys_clk_en && HP_SYS_CLKRST.soc_clk_ctrl0.reg_gdma_cpu_clk_en; +} /** * @brief Reset the DMA controller by software @@ -320,10 +330,12 @@ static inline void dw_gdma_ll_channel_suspend(dw_gdma_dev_t *dev, uint8_t channe * @param dev Pointer to the DW_GDMA registers * @param channel Channel number */ +__attribute__((always_inline)) static inline void dw_gdma_ll_channel_abort(dw_gdma_dev_t *dev, uint8_t channel) { // the abort bit clears itself after the abort is done dev->chen1.val = 0x101 << channel; + while (dev->chen1.val & (0x101 << channel)); } /** diff --git a/components/hal/esp32p4/include/hal/gdma_ll.h b/components/hal/esp32p4/include/hal/gdma_ll.h index f058a9af7c..fc1c983704 100644 --- a/components/hal/esp32p4/include/hal/gdma_ll.h +++ b/components/hal/esp32p4/include/hal/gdma_ll.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2022-2025 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -108,6 +108,19 @@ static inline void gdma_ll_enable_bus_clock(int group_id, bool enable) /// the critical section needs to declare the __DECLARE_RCC_ATOMIC_ENV variable in advance #define gdma_ll_enable_bus_clock(...) (void)__DECLARE_RCC_ATOMIC_ENV; gdma_ll_enable_bus_clock(__VA_ARGS__) +/** + * @brief Check if the bus clock is enabled for the DMA module + */ +__attribute__((always_inline)) +static inline bool gdma_ll_is_bus_clock_enabled(int group_id) +{ + if (group_id == 0) { + return HP_SYS_CLKRST.soc_clk_ctrl1.reg_ahb_pdma_sys_clk_en; + } else { + return HP_SYS_CLKRST.soc_clk_ctrl1.reg_axi_pdma_sys_clk_en; + } +} + /** * @brief Reset the DMA module */ diff --git a/components/hal/esp32p4/include/hal/lcd_ll.h b/components/hal/esp32p4/include/hal/lcd_ll.h index 3bad577486..7c67bbadef 100644 --- a/components/hal/esp32p4/include/hal/lcd_ll.h +++ b/components/hal/esp32p4/include/hal/lcd_ll.h @@ -63,7 +63,7 @@ static inline void lcd_ll_enable_bus_clock(int group_id, bool enable) * * @param group_id Group ID */ -static inline void lcd_ll_reset_register(int group_id) +static inline void _lcd_ll_reset_register(int group_id) { (void)group_id; HP_SYS_CLKRST.hp_rst_en2.reg_rst_en_lcdcam = 1; @@ -72,7 +72,7 @@ static inline void lcd_ll_reset_register(int group_id) /// use a macro to wrap the function, force the caller to use it in a critical section /// the critical section needs to declare the __DECLARE_RCC_RC_ATOMIC_ENV variable in advance -#define lcd_ll_reset_register(...) (void)__DECLARE_RCC_RC_ATOMIC_ENV; lcd_ll_reset_register(__VA_ARGS__) +#define lcd_ll_reset_register(...) (void)__DECLARE_RCC_RC_ATOMIC_ENV; _lcd_ll_reset_register(__VA_ARGS__) /** * @brief Enable clock gating