diff --git a/components/esp_hw_support/include/esp_private/esp_modem_clock.h b/components/esp_hw_support/include/esp_private/esp_modem_clock.h index e01f912d83..bd822ebfbd 100644 --- a/components/esp_hw_support/include/esp_private/esp_modem_clock.h +++ b/components/esp_hw_support/include/esp_private/esp_modem_clock.h @@ -10,9 +10,11 @@ #include #include +#include "esp_err.h" #include "soc/soc_caps.h" #include "soc/periph_defs.h" #include "hal/modem_clock_types.h" +#include "esp_private/esp_pmu.h" #if SOC_MODEM_CLOCK_IS_INDEPENDENT #include "hal/modem_clock_hal.h" @@ -77,6 +79,32 @@ void modem_clock_module_mac_reset(periph_module_t module); */ void modem_clock_domain_pmu_state_icg_map_init(void); +#if SOC_PMU_SUPPORTED +/** + * @brief Enable modem clock domain clock gate to gate it's output + * + * @param domain modem module clock domain + * @param mode PMU HP system ACTIVE, MODEM and SLEEP state + * + * @return + * - ESP_OK on success + * - ESP_ERR_INVALID_ARG if the argument value are not correct + */ +esp_err_t modem_clock_domain_clk_gate_enable(modem_clock_domain_t domain, pmu_hp_icg_modem_mode_t mode); + +/** + * @brief Disable modem clock domain clock gate to ungate it's output + * + * @param domain modem module clock domain + * @param mode PMU HP system ACTIVE, MODEM and SLEEP state + * + * @return + * - ESP_OK on success + * - ESP_ERR_INVALID_ARG if the argument value are not correct + */ +esp_err_t modem_clock_domain_clk_gate_disable(modem_clock_domain_t domain, pmu_hp_icg_modem_mode_t mode); +#endif + /** * @brief Select the modem module lowpower clock source and configure the clock divider * diff --git a/components/esp_hw_support/modem_clock.c b/components/esp_hw_support/modem_clock.c index dec1c3c332..0e14ee4fc5 100644 --- a/components/esp_hw_support/modem_clock.c +++ b/components/esp_hw_support/modem_clock.c @@ -180,6 +180,38 @@ void modem_clock_domain_pmu_state_icg_map_init(void) { modem_clock_domain_power_state_icg_map_init(MODEM_CLOCK_instance()); } + +esp_err_t modem_clock_domain_clk_gate_enable(modem_clock_domain_t domain, pmu_hp_icg_modem_mode_t mode) +{ + if (domain >= MODEM_CLOCK_DOMAIN_MAX || domain < MODEM_CLOCK_DOMAIN_MODEM_APB) { + return ESP_ERR_INVALID_ARG; + } + if (mode > PMU_HP_ICG_MODEM_CODE_ACTIVE || mode < PMU_HP_ICG_MODEM_CODE_SLEEP) { + return ESP_ERR_INVALID_ARG; + } + + portENTER_CRITICAL_SAFE(&MODEM_CLOCK_instance()->lock); + uint32_t code = modem_clock_hal_get_clock_domain_icg_bitmap(MODEM_CLOCK_instance()->hal, domain); + modem_clock_hal_set_clock_domain_icg_bitmap(MODEM_CLOCK_instance()->hal, domain, (code & ~BIT(mode))); + portEXIT_CRITICAL_SAFE(&MODEM_CLOCK_instance()->lock); + return ESP_OK; +} + +esp_err_t modem_clock_domain_clk_gate_disable(modem_clock_domain_t domain, pmu_hp_icg_modem_mode_t mode) +{ + if (domain >= MODEM_CLOCK_DOMAIN_MAX || domain < MODEM_CLOCK_DOMAIN_MODEM_APB) { + return ESP_ERR_INVALID_ARG; + } + if (mode > PMU_HP_ICG_MODEM_CODE_ACTIVE || mode < PMU_HP_ICG_MODEM_CODE_SLEEP) { + return ESP_ERR_INVALID_ARG; + } + + portENTER_CRITICAL_SAFE(&MODEM_CLOCK_instance()->lock); + uint32_t code = modem_clock_hal_get_clock_domain_icg_bitmap(MODEM_CLOCK_instance()->hal, domain); + modem_clock_hal_set_clock_domain_icg_bitmap(MODEM_CLOCK_instance()->hal, domain, (code | BIT(mode))); + portEXIT_CRITICAL_SAFE(&MODEM_CLOCK_instance()->lock); + return ESP_OK; +} #endif // #if SOC_PM_SUPPORT_PMU_MODEM_STATE static void IRAM_ATTR modem_clock_device_enable(modem_clock_context_t *ctx, uint32_t dev_map) diff --git a/components/hal/esp32c6/include/hal/modem_lpcon_ll.h b/components/hal/esp32c6/include/hal/modem_lpcon_ll.h index 3374defb42..aa4288f519 100644 --- a/components/hal/esp32c6/include/hal/modem_lpcon_ll.h +++ b/components/hal/esp32c6/include/hal/modem_lpcon_ll.h @@ -192,24 +192,48 @@ static inline void modem_lpcon_ll_enable_ble_rtc_timer_force_clock(modem_lpcon_d hw->clk_conf_force_on.clk_lp_timer_fo = en; } +__attribute__((always_inline)) +static inline uint32_t modem_lpcon_ll_get_wifipwr_icg_bitmap(modem_lpcon_dev_t *hw) +{ + return hw->clk_conf_power_st.clk_wifipwr_st_map; +} + __attribute__((always_inline)) static inline void modem_lpcon_ll_set_wifipwr_icg_bitmap(modem_lpcon_dev_t *hw, uint32_t bitmap) { hw->clk_conf_power_st.clk_wifipwr_st_map = bitmap; } +__attribute__((always_inline)) +static inline uint32_t modem_lpcon_ll_get_coex_icg_bitmap(modem_lpcon_dev_t *hw) +{ + return hw->clk_conf_power_st.clk_coex_st_map; +} + __attribute__((always_inline)) static inline void modem_lpcon_ll_set_coex_icg_bitmap(modem_lpcon_dev_t *hw, uint32_t bitmap) { hw->clk_conf_power_st.clk_coex_st_map = bitmap; } +__attribute__((always_inline)) +static inline uint32_t modem_lpcon_ll_get_i2c_master_icg_bitmap(modem_lpcon_dev_t *hw) +{ + return hw->clk_conf_power_st.clk_i2c_mst_st_map; +} + __attribute__((always_inline)) static inline void modem_lpcon_ll_set_i2c_master_icg_bitmap(modem_lpcon_dev_t *hw, uint32_t bitmap) { hw->clk_conf_power_st.clk_i2c_mst_st_map = bitmap; } +__attribute__((always_inline)) +static inline uint32_t modem_lpcon_ll_get_lp_apb_icg_bitmap(modem_lpcon_dev_t *hw) +{ + return hw->clk_conf_power_st.clk_lp_apb_st_map; +} + __attribute__((always_inline)) static inline void modem_lpcon_ll_set_lp_apb_icg_bitmap(modem_lpcon_dev_t *hw, uint32_t bitmap) { diff --git a/components/hal/esp32c6/include/hal/modem_syscon_ll.h b/components/hal/esp32c6/include/hal/modem_syscon_ll.h index 9fc2b50a3e..1b9a6a9056 100644 --- a/components/hal/esp32c6/include/hal/modem_syscon_ll.h +++ b/components/hal/esp32c6/include/hal/modem_syscon_ll.h @@ -105,36 +105,73 @@ static inline void modem_syscon_ll_enable_data_dump_force_clock(modem_syscon_dev { hw->clk_conf_force_on.clk_data_dump_fo = 1; } + +__attribute__((always_inline)) +static inline uint32_t modem_syscon_ll_get_ieee802154_icg_bitmap(modem_syscon_dev_t *hw) +{ + return hw->clk_conf_power_st.clk_zb_st_map; +} + __attribute__((always_inline)) static inline void modem_syscon_ll_set_ieee802154_icg_bitmap(modem_syscon_dev_t *hw, uint32_t bitmap) { hw->clk_conf_power_st.clk_zb_st_map = bitmap; } +__attribute__((always_inline)) +static inline uint32_t modem_syscon_ll_get_fe_icg_bitmap(modem_syscon_dev_t *hw) +{ + return hw->clk_conf_power_st.clk_fe_st_map; +} + __attribute__((always_inline)) static inline void modem_syscon_ll_set_fe_icg_bitmap(modem_syscon_dev_t *hw, uint32_t bitmap) { hw->clk_conf_power_st.clk_fe_st_map = bitmap; } +__attribute__((always_inline)) +static inline uint32_t modem_syscon_ll_get_bt_icg_bitmap(modem_syscon_dev_t *hw) +{ + return hw->clk_conf_power_st.clk_bt_st_map; +} + __attribute__((always_inline)) static inline void modem_syscon_ll_set_bt_icg_bitmap(modem_syscon_dev_t *hw, uint32_t bitmap) { hw->clk_conf_power_st.clk_bt_st_map = bitmap; } +__attribute__((always_inline)) +static inline uint32_t modem_syscon_ll_get_wifi_icg_bitmap(modem_syscon_dev_t *hw) +{ + return hw->clk_conf_power_st.clk_wifi_st_map; +} + __attribute__((always_inline)) static inline void modem_syscon_ll_set_wifi_icg_bitmap(modem_syscon_dev_t *hw, uint32_t bitmap) { hw->clk_conf_power_st.clk_wifi_st_map = bitmap; } +__attribute__((always_inline)) +static inline uint32_t modem_syscon_ll_get_modem_periph_icg_bitmap(modem_syscon_dev_t *hw) +{ + return hw->clk_conf_power_st.clk_modem_peri_st_map; +} + __attribute__((always_inline)) static inline void modem_syscon_ll_set_modem_periph_icg_bitmap(modem_syscon_dev_t *hw, uint32_t bitmap) { hw->clk_conf_power_st.clk_modem_peri_st_map = bitmap; } +__attribute__((always_inline)) +static inline uint32_t modem_syscon_ll_get_modem_apb_icg_bitmap(modem_syscon_dev_t *hw) +{ + return hw->clk_conf_power_st.clk_modem_apb_st_map; +} + __attribute__((always_inline)) static inline void modem_syscon_ll_set_modem_apb_icg_bitmap(modem_syscon_dev_t *hw, uint32_t bitmap) { diff --git a/components/hal/esp32c6/modem_clock_hal.c b/components/hal/esp32c6/modem_clock_hal.c index 449006b701..a59aa84e2c 100644 --- a/components/hal/esp32c6/modem_clock_hal.c +++ b/components/hal/esp32c6/modem_clock_hal.c @@ -58,6 +58,48 @@ void modem_clock_hal_set_clock_domain_icg_bitmap(modem_clock_hal_context_t *hal, } } +uint32_t modem_clock_hal_get_clock_domain_icg_bitmap(modem_clock_hal_context_t *hal, modem_clock_domain_t domain) +{ + HAL_ASSERT(domain < MODEM_CLOCK_DOMAIN_MAX); + uint32_t bitmap = 0; + switch (domain) + { + case MODEM_CLOCK_DOMAIN_MODEM_APB: + bitmap = modem_syscon_ll_get_modem_apb_icg_bitmap(hal->syscon_dev); + break; + case MODEM_CLOCK_DOMAIN_MODEM_PERIPH: + bitmap = modem_syscon_ll_get_modem_periph_icg_bitmap(hal->syscon_dev); + break; + case MODEM_CLOCK_DOMAIN_WIFI: + bitmap = modem_syscon_ll_get_wifi_icg_bitmap(hal->syscon_dev); + break; + case MODEM_CLOCK_DOMAIN_BT: + bitmap = modem_syscon_ll_get_bt_icg_bitmap(hal->syscon_dev); + break; + case MODEM_CLOCK_DOMAIN_FE: + bitmap = modem_syscon_ll_get_fe_icg_bitmap(hal->syscon_dev); + break; + case MODEM_CLOCK_DOMAIN_IEEE802154: + bitmap = modem_syscon_ll_get_ieee802154_icg_bitmap(hal->syscon_dev); + break; + case MODEM_CLOCK_DOMAIN_LP_APB: + bitmap = modem_lpcon_ll_get_lp_apb_icg_bitmap(hal->lpcon_dev); + break; + case MODEM_CLOCK_DOMAIN_I2C_MASTER: + bitmap = modem_lpcon_ll_get_i2c_master_icg_bitmap(hal->lpcon_dev); + break; + case MODEM_CLOCK_DOMAIN_COEX: + bitmap = modem_lpcon_ll_get_coex_icg_bitmap(hal->lpcon_dev); + break; + case MODEM_CLOCK_DOMAIN_WIFIPWR: + bitmap = modem_lpcon_ll_get_wifipwr_icg_bitmap(hal->lpcon_dev); + break; + default: + break; + } + return bitmap; +} + void modem_clock_hal_enable_fe_clock(modem_clock_hal_context_t *hal, bool enable) { if (enable) { diff --git a/components/hal/include/hal/modem_clock_hal.h b/components/hal/include/hal/modem_clock_hal.h index 9912308f5e..0ce13035aa 100644 --- a/components/hal/include/hal/modem_clock_hal.h +++ b/components/hal/include/hal/modem_clock_hal.h @@ -24,6 +24,7 @@ typedef struct { #if MAC_SUPPORT_PMU_MODEM_STATE void modem_clock_hal_set_clock_domain_icg_bitmap(modem_clock_hal_context_t *hal, modem_clock_domain_t domain, uint32_t bitmap); +uint32_t modem_clock_hal_get_clock_domain_icg_bitmap(modem_clock_hal_context_t *hal, modem_clock_domain_t domain); #endif void modem_clock_hal_enable_fe_clock(modem_clock_hal_context_t *hal, bool enable);