diff --git a/components/esp_hal_usb/esp32h4/include/hal/usb_dwc_ll.h b/components/esp_hal_usb/esp32h4/include/hal/usb_dwc_ll.h index ef85560faf1..5b4dc746218 100644 --- a/components/esp_hal_usb/esp32h4/include/hal/usb_dwc_ll.h +++ b/components/esp_hal_usb/esp32h4/include/hal/usb_dwc_ll.h @@ -8,6 +8,7 @@ #include #include +#include "esp_attr.h" #include "soc/usb_dwc_struct.h" #include "soc/usb_dwc_cfg.h" #include "hal/usb_dwc_types.h" @@ -977,6 +978,32 @@ static inline void usb_dwc_ll_qtd_get_status(usb_dwc_ll_dma_qtd_t *qtd, int *rem qtd->buffer_status_val = 0; } +// ---------------------------- Power and Clock Gating Register -------------------------------- +FORCE_INLINE_ATTR void usb_dwc_ll_set_stoppclk(usb_dwc_dev_t *hw, bool stop) +{ + hw->pcgcctl_reg.stoppclk = stop; +} + +FORCE_INLINE_ATTR bool usb_dwc_ll_get_stoppclk_st(usb_dwc_dev_t *hw) +{ + return hw->pcgcctl_reg.stoppclk; +} + +FORCE_INLINE_ATTR void usb_dwc_ll_set_gatehclk(usb_dwc_dev_t *hw, bool gate) +{ + hw->pcgcctl_reg.gatehclk = gate; +} + +FORCE_INLINE_ATTR bool usb_dwc_ll_get_gatehclk_st(usb_dwc_dev_t *hw) +{ + return hw->pcgcctl_reg.gatehclk; +} + +FORCE_INLINE_ATTR bool usb_dwc_ll_get_physleep_st(usb_dwc_dev_t *hw) +{ + return hw->pcgcctl_reg.physleep; +} + #ifdef __cplusplus } #endif diff --git a/components/esp_hal_usb/esp32p4/include/hal/usb_dwc_ll.h b/components/esp_hal_usb/esp32p4/include/hal/usb_dwc_ll.h index 7fb3bcbfb29..0f0feb90228 100644 --- a/components/esp_hal_usb/esp32p4/include/hal/usb_dwc_ll.h +++ b/components/esp_hal_usb/esp32p4/include/hal/usb_dwc_ll.h @@ -1060,6 +1060,21 @@ FORCE_INLINE_ATTR bool usb_dwc_ll_get_stoppclk_st(usb_dwc_dev_t *hw) return hw->pcgcctl_reg.stoppclk; } +FORCE_INLINE_ATTR void usb_dwc_ll_set_gatehclk(usb_dwc_dev_t *hw, bool gate) +{ + hw->pcgcctl_reg.gatehclk = gate; +} + +FORCE_INLINE_ATTR bool usb_dwc_ll_get_gatehclk_st(usb_dwc_dev_t *hw) +{ + return hw->pcgcctl_reg.gatehclk; +} + +FORCE_INLINE_ATTR bool usb_dwc_ll_get_physleep_st(usb_dwc_dev_t *hw) +{ + return hw->pcgcctl_reg.physleep; +} + #ifdef __cplusplus } #endif diff --git a/components/esp_hal_usb/esp32s2/include/hal/usb_dwc_ll.h b/components/esp_hal_usb/esp32s2/include/hal/usb_dwc_ll.h index aaa8cc64681..bcc0a9d2782 100644 --- a/components/esp_hal_usb/esp32s2/include/hal/usb_dwc_ll.h +++ b/components/esp_hal_usb/esp32s2/include/hal/usb_dwc_ll.h @@ -8,6 +8,7 @@ #include #include +#include "esp_attr.h" #include "soc/usb_dwc_struct.h" #include "soc/usb_dwc_cfg.h" #include "hal/usb_dwc_types.h" @@ -975,6 +976,32 @@ static inline void usb_dwc_ll_qtd_get_status(usb_dwc_ll_dma_qtd_t *qtd, int *rem qtd->buffer_status_val = 0; } +// ---------------------------- Power and Clock Gating Register -------------------------------- +FORCE_INLINE_ATTR void usb_dwc_ll_set_stoppclk(usb_dwc_dev_t *hw, bool stop) +{ + hw->pcgcctl_reg.stoppclk = stop; +} + +FORCE_INLINE_ATTR bool usb_dwc_ll_get_stoppclk_st(usb_dwc_dev_t *hw) +{ + return hw->pcgcctl_reg.stoppclk; +} + +FORCE_INLINE_ATTR void usb_dwc_ll_set_gatehclk(usb_dwc_dev_t *hw, bool gate) +{ + hw->pcgcctl_reg.gatehclk = gate; +} + +FORCE_INLINE_ATTR bool usb_dwc_ll_get_gatehclk_st(usb_dwc_dev_t *hw) +{ + return hw->pcgcctl_reg.gatehclk; +} + +FORCE_INLINE_ATTR bool usb_dwc_ll_get_physleep_st(usb_dwc_dev_t *hw) +{ + return hw->pcgcctl_reg.physleep; +} + #ifdef __cplusplus } #endif diff --git a/components/esp_hal_usb/esp32s3/include/hal/usb_dwc_ll.h b/components/esp_hal_usb/esp32s3/include/hal/usb_dwc_ll.h index da560893636..97c1290ad9f 100644 --- a/components/esp_hal_usb/esp32s3/include/hal/usb_dwc_ll.h +++ b/components/esp_hal_usb/esp32s3/include/hal/usb_dwc_ll.h @@ -8,6 +8,7 @@ #include #include +#include "esp_attr.h" #include "soc/usb_dwc_struct.h" #include "soc/usb_dwc_cfg.h" #include "hal/usb_dwc_types.h" @@ -975,6 +976,32 @@ static inline void usb_dwc_ll_qtd_get_status(usb_dwc_ll_dma_qtd_t *qtd, int *rem qtd->buffer_status_val = 0; } +// ---------------------------- Power and Clock Gating Register -------------------------------- +FORCE_INLINE_ATTR void usb_dwc_ll_set_stoppclk(usb_dwc_dev_t *hw, bool stop) +{ + hw->pcgcctl_reg.stoppclk = stop; +} + +FORCE_INLINE_ATTR bool usb_dwc_ll_get_stoppclk_st(usb_dwc_dev_t *hw) +{ + return hw->pcgcctl_reg.stoppclk; +} + +FORCE_INLINE_ATTR void usb_dwc_ll_set_gatehclk(usb_dwc_dev_t *hw, bool gate) +{ + hw->pcgcctl_reg.gatehclk = gate; +} + +FORCE_INLINE_ATTR bool usb_dwc_ll_get_gatehclk_st(usb_dwc_dev_t *hw) +{ + return hw->pcgcctl_reg.gatehclk; +} + +FORCE_INLINE_ATTR bool usb_dwc_ll_get_physleep_st(usb_dwc_dev_t *hw) +{ + return hw->pcgcctl_reg.physleep; +} + #ifdef __cplusplus } #endif diff --git a/components/esp_hal_usb/include/hal/usb_dwc_hal.h b/components/esp_hal_usb/include/hal/usb_dwc_hal.h index e703f20cfc9..879ba44d898 100644 --- a/components/esp_hal_usb/include/hal/usb_dwc_hal.h +++ b/components/esp_hal_usb/include/hal/usb_dwc_hal.h @@ -552,6 +552,66 @@ static inline bool usb_dwc_hal_port_check_if_suspended(usb_dwc_hal_context_t *ha return usb_dwc_ll_hprt_get_port_suspend(hal->dev); } +// ----------------------------------------------------- Power and Clock gating ---------------------------------------- + +/** + * @brief Gate internal clock of the DWC_OTG core + * + * This function gates the internal clock of the DWC_OTG core to reduce power consumption + * + * Internal clock gating: + * - stop PHY clock (PCLK) + * - gate HCLK to modules other than the AHB slave, AHB master and wakeup logic + * Internal clock un-gating: + * - un-stop PHY clock (PCLK) + * - un-gate HCLK + * + * @note This is a part of a sequence from the DWC Programming guide, chapter 14.2.2.1 + * @param hal Context of the HAL layer + * @param enable Enable or disable internal clock gating + */ +static inline void usb_dwc_hal_pwr_clk_internal_clock_gate(usb_dwc_hal_context_t *hal, bool enable) +{ + usb_dwc_ll_set_stoppclk(hal->dev, enable); // Enable/disable PHY clock stop + usb_dwc_ll_set_gatehclk(hal->dev, enable); // Gate/ungate HCLK +} + +/** + * @brief Check if the PHY clock (PCLK) stop is enabled or disabled + * + * @param hal Context of the HAL layer + * @return true The PCLK stop is enabled + * @return false The PCLK stop is not enabled + */ +static inline bool usb_dwc_hal_pwr_clk_check_phy_clk_stopped(usb_dwc_hal_context_t *hal) +{ + return usb_dwc_ll_get_stoppclk_st(hal->dev); +} + +/** + * @brief Check if the HCLK is gated or ungated + * + * @param hal Context of the HAL layer + * @return true The HCLK is gated + * @return false The HCLK is not gated + */ +static inline bool usb_dwc_hal_pwr_clk_check_hclk_gated(usb_dwc_hal_context_t *hal) +{ + return usb_dwc_ll_get_gatehclk_st(hal->dev); +} + +/** + * @brief Check if PHY is in sleep state + * + * @param hal Context of the HAL layer + * @return true The USB PHY is in sleep state + * @return false The USB PHY is not in sleep state + */ +static inline bool usb_dwc_hal_pwr_clk_check_phy_sleep(usb_dwc_hal_context_t *hal) +{ + return usb_dwc_ll_get_physleep_st(hal->dev); +} + // ----------------------------------------------------- Channel ------------------------------------------------------- // ----------------- Channel Allocation --------------------