From 8bd502f975ea52123bb199f7ed65ca3f1554e788 Mon Sep 17 00:00:00 2001 From: hebinglin Date: Fri, 12 Dec 2025 17:38:24 +0800 Subject: [PATCH] change(esp_hw_support): divide modem_clock config into port layer --- .../include/esp_private/esp_modem_clock.h | 133 ++++- components/esp_hw_support/modem_clock.c | 477 +----------------- .../port/esp32c5/CMakeLists.txt | 4 + .../port/esp32c5/modem_clock_impl.c | 364 +++++++++++++ .../port/esp32c6/CMakeLists.txt | 3 + .../port/esp32c6/modem_clock_impl.c | 414 +++++++++++++++ .../port/esp32c61/CMakeLists.txt | 4 + .../port/esp32c61/modem_clock_impl.c | 364 +++++++++++++ .../port/esp32h2/CMakeLists.txt | 4 + .../port/esp32h2/modem_clock_impl.c | 282 +++++++++++ .../port/esp32h21/CMakeLists.txt | 4 + .../port/esp32h21/modem_clock_impl.c | 254 ++++++++++ .../port/esp32h4/CMakeLists.txt | 4 + .../port/esp32h4/modem_clock_impl.c | 271 ++++++++++ .../hal/include/hal/modem_clock_types.h | 10 + 15 files changed, 2109 insertions(+), 483 deletions(-) create mode 100644 components/esp_hw_support/port/esp32c5/modem_clock_impl.c create mode 100644 components/esp_hw_support/port/esp32c6/modem_clock_impl.c create mode 100644 components/esp_hw_support/port/esp32c61/modem_clock_impl.c create mode 100644 components/esp_hw_support/port/esp32h2/modem_clock_impl.c create mode 100644 components/esp_hw_support/port/esp32h21/modem_clock_impl.c create mode 100644 components/esp_hw_support/port/esp32h4/modem_clock_impl.c 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 82171e593a..cd5c988597 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 @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2022-2025 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2022-2026 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -15,8 +15,9 @@ #include "soc/periph_defs.h" #include "hal/modem_clock_types.h" #include "esp_private/esp_pmu.h" +#include "esp_private/critical_section.h" -#if SOC_MODEM_CLOCK_IS_INDEPENDENT +#if SOC_MODEM_CLOCK_IS_INDEPENDENT && SOC_MODEM_CLOCK_SUPPORTED #include "hal/modem_clock_hal.h" #endif @@ -24,6 +25,98 @@ extern "C" { #endif +#if SOC_MODEM_CLOCK_IS_INDEPENDENT && SOC_MODEM_CLOCK_SUPPORTED +// Please define the frequently called modules in the low bit, +// which will improve the execution efficiency +typedef enum { + MODEM_CLOCK_MODEM_ADC_COMMON_FE, + MODEM_CLOCK_MODEM_PRIVATE_FE, + MODEM_CLOCK_COEXIST, +#if ANA_I2C_MST_CLK_HAS_ROOT_GATING + MODEM_CLOCK_I2C_MASTER, +#endif +#if SOC_PHY_CALIBRATION_CLOCK_IS_INDEPENDENT + MODEM_CLOCK_WIFI_APB, + MODEM_CLOCK_WIFI_BB_44M, +#endif +#if SOC_WIFI_SUPPORTED + MODEM_CLOCK_WIFI_MAC, + MODEM_CLOCK_WIFI_BB, +#endif + MODEM_CLOCK_ETM, +#if SOC_BT_SUPPORTED + MODEM_CLOCK_BLE_MAC, +#endif +#if SOC_BT_SUPPORTED || SOC_IEEE802154_SUPPORTED + MODEM_CLOCK_BT_I154_COMMON_BB, +#endif +#if SOC_IEEE802154_SUPPORTED + MODEM_CLOCK_802154_MAC, +#endif + MODEM_CLOCK_DATADUMP, + MODEM_CLOCK_DEVICE_MAX +} modem_clock_device_t; + +#define MODEM_STATUS_IDLE (0) +#define MODEM_STATUS_WIFI_INITED (0x1UL) + +struct modem_clock_context; + +typedef struct { + int16_t refs; /* Reference count for this device, if with_refcnt is enabled */ + uint16_t with_refcnt : 1; /* Enable reference count management (true=use refs, false=ignore refs) */ + uint16_t reserved : 15; /* reserved for 15 bits aligned */ + void (*configure)(struct modem_clock_context *, bool); +#if CONFIG_ESP_MODEM_CLOCK_ENABLE_CHECKING + esp_err_t (*check_enable)(struct modem_clock_context *); +#endif +} modem_clock_device_context_t; + +typedef struct modem_clock_context { + modem_clock_hal_context_t *hal; + spinlock_t lock; + modem_clock_device_context_t *dev; +#if SOC_PM_SUPPORT_PMU_MODEM_STATE + const uint8_t *initial_gating_mode; +#endif + /* the low-power clock source for each module */ + modem_clock_lpclk_src_t lpclk_src[PERIPH_MODEM_MODULE_NUM]; +#if SOC_WIFI_SUPPORTED + uint32_t modem_status; +#endif +} modem_clock_context_t; + +/** + * @brief Get module clock dependencies + * Each chip implements this function in its port file + * @param module The modem module + * @return Bitmask of clock dependencies + */ +uint32_t modem_clock_get_module_deps(shared_periph_module_t module); + +/** + * @brief Modem clock device context array + * Each chip defines this array in its port file + */ +extern modem_clock_device_context_t g_modem_clock_dev[MODEM_CLOCK_DEVICE_MAX]; + +#if SOC_PM_SUPPORT_PMU_MODEM_STATE +/** + * @brief Initial gating mode for each clock domain + * Each chip defines this array in its port file + */ +extern const uint8_t g_initial_gating_mode[MODEM_CLOCK_DOMAIN_MAX]; +#endif + +#if SOC_PM_SUPPORT_PMU_MODEM_STATE +/* the ICG code's bit 0, 1 and 2 indicates the ICG state + * of pmu SLEEP, MODEM and ACTIVE mode respectively */ + #define ICG_NOGATING_ACTIVE (BIT(PMU_HP_ICG_MODEM_CODE_ACTIVE)) + #define ICG_NOGATING_SLEEP (BIT(PMU_HP_ICG_MODEM_CODE_SLEEP)) + #define ICG_NOGATING_MODEM (BIT(PMU_HP_ICG_MODEM_CODE_MODEM)) +#endif // SOC_PM_SUPPORT_PMU_MODEM_STATE +#endif // SOC_MODEM_CLOCK_IS_INDEPENDENT && SOC_MODEM_CLOCK_SUPPORTED + /** * @brief Enable the clock of modem module * @@ -93,28 +186,13 @@ void modem_clock_module_mac_reset(shared_periph_module_t module); #if SOC_BLE_USE_WIFI_PWR_CLK_WORKAROUND /** - * @brief Enable modem clock domain clock gate to gate it's output + * @brief Apply or clear BT low-power clock workaround for enabling Wi-Fi power clock * - * @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 + * @param ctx modem clock context + * @param select true to apply (ungate); false to clear (gate) + * @param src lowpower clock source */ -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); +void modem_clock_bt_wifipwr_clk_workaround(modem_clock_context_t *ctx, bool select, modem_clock_lpclk_src_t src); #endif /** @@ -137,6 +215,17 @@ void modem_clock_deselect_lp_clock_source(shared_periph_module_t module); */ void modem_clock_deselect_all_module_lp_clock_source(void); +#if CONFIG_IDF_TARGET_ESP32H2 +/** + * @brief BLE RTC timer LPCLK workaround on ESP32H2 + * + * @param ctx modem clock context + * @param enable true to enable rc32k; false to disable rc32k + * @param src lowpower clock source + */ +void modem_clock_select_ble_rtc_timer_clk_workaround(modem_clock_context_t *ctx, bool enable, modem_clock_lpclk_src_t src); +#endif + /** * @brief Reset wifi mac */ diff --git a/components/esp_hw_support/modem_clock.c b/components/esp_hw_support/modem_clock.c index 8e78cd45b3..e063c35778 100644 --- a/components/esp_hw_support/modem_clock.c +++ b/components/esp_hw_support/modem_clock.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2022-2025 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2022-2026 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -11,266 +11,14 @@ #include "esp_attr.h" #include "soc/soc.h" #include "soc/soc_caps.h" -#include "freertos/FreeRTOS.h" #include "esp_private/esp_modem_clock.h" #include "esp_private/esp_sleep_internal.h" #include "esp_private/esp_pmu.h" -#include "esp_private/critical_section.h" #include "esp_sleep.h" #include "hal/efuse_hal.h" #include "hal/clk_tree_ll.h" -#include "hal/regi2c_ctrl_ll.h" -#include "esp_private/regi2c_ctrl.h" -#if CONFIG_IDF_TARGET_ESP32H2 -#include "soc/rtc.h" -#endif // CONFIG_IDF_TARGET_ESP32H2 - -// Please define the frequently called modules in the low bit, -// which will improve the execution efficiency -typedef enum { - MODEM_CLOCK_MODEM_ADC_COMMON_FE, - MODEM_CLOCK_MODEM_PRIVATE_FE, - MODEM_CLOCK_COEXIST, -#if ANA_I2C_MST_CLK_HAS_ROOT_GATING - MODEM_CLOCK_I2C_MASTER, -#endif -#if SOC_PHY_CALIBRATION_CLOCK_IS_INDEPENDENT - MODEM_CLOCK_WIFI_APB, - MODEM_CLOCK_WIFI_BB_44M, -#endif -#if SOC_WIFI_SUPPORTED - MODEM_CLOCK_WIFI_MAC, - MODEM_CLOCK_WIFI_BB, -#endif - MODEM_CLOCK_ETM, -#if SOC_BT_SUPPORTED - MODEM_CLOCK_BLE_MAC, -#endif -#if SOC_BT_SUPPORTED || SOC_IEEE802154_SUPPORTED - MODEM_CLOCK_BT_I154_COMMON_BB, -#endif -#if SOC_IEEE802154_SUPPORTED - MODEM_CLOCK_802154_MAC, -#endif - MODEM_CLOCK_DATADUMP, - MODEM_CLOCK_DEVICE_MAX -} modem_clock_device_t; - -#define MODEM_STATUS_IDLE (0) -#define MODEM_STATUS_WIFI_INITED (0x1UL) - -typedef struct modem_clock_context { - modem_clock_hal_context_t *hal; - portMUX_TYPE lock; - struct { - int16_t refs; /* Reference count for this device, if with_refcnt is enabled */ - uint16_t with_refcnt : 1; /* Enable reference count management (true=use refs, false=ignore refs) */ - uint16_t reserved : 15; /* reserved for 15 bits aligned */ - void (*configure)(struct modem_clock_context *, bool); -#if CONFIG_ESP_MODEM_CLOCK_ENABLE_CHECKING - esp_err_t (*check_enable)(struct modem_clock_context *); -#endif - } dev[MODEM_CLOCK_DEVICE_MAX]; - /* the low-power clock source for each module */ - modem_clock_lpclk_src_t lpclk_src[PERIPH_MODEM_MODULE_NUM]; -#if SOC_WIFI_SUPPORTED - uint32_t modem_status; -#endif -} modem_clock_context_t; - - -#if SOC_WIFI_SUPPORTED -static void IRAM_ATTR modem_clock_wifi_mac_configure(modem_clock_context_t *ctx, bool enable) -{ - if (enable || !(ctx->modem_status & MODEM_STATUS_WIFI_INITED)) { -#if !SOC_PHY_CALIBRATION_CLOCK_IS_INDEPENDENT - modem_syscon_ll_enable_wifi_apb_clock(ctx->hal->syscon_dev, enable); -#endif - modem_syscon_ll_enable_wifi_mac_clock(ctx->hal->syscon_dev, enable); - } -} - -static void IRAM_ATTR modem_clock_wifi_bb_configure(modem_clock_context_t *ctx, bool enable) -{ - if (enable || !(ctx->modem_status & MODEM_STATUS_WIFI_INITED)) { - modem_syscon_ll_clk_wifibb_configure(ctx->hal->syscon_dev, enable); - } -} - -#if CONFIG_ESP_MODEM_CLOCK_ENABLE_CHECKING -static esp_err_t IRAM_ATTR modem_clock_wifi_mac_check_enable(modem_clock_context_t *ctx) -{ - bool all_clock_enabled = true; -#if !SOC_PHY_CALIBRATION_CLOCK_IS_INDEPENDENT - all_clock_enabled &= modem_syscon_ll_wifi_apb_clock_is_enabled(ctx->hal->syscon_dev); -#endif - all_clock_enabled &= modem_syscon_ll_wifi_mac_clock_is_enabled(ctx->hal->syscon_dev); - return all_clock_enabled ? ESP_OK : ESP_FAIL; -} - -static esp_err_t IRAM_ATTR modem_clock_wifi_bb_check_enable(modem_clock_context_t *ctx) -{ - return modem_syscon_ll_wifibb_clock_is_enabled(ctx->hal->syscon_dev) ? ESP_OK : ESP_FAIL; -} -#endif -#endif // SOC_WIFI_SUPPORTED - -#if SOC_BT_SUPPORTED -static void IRAM_ATTR modem_clock_ble_mac_configure(modem_clock_context_t *ctx, bool enable) -{ - modem_syscon_ll_enable_bt_mac_clock(ctx->hal->syscon_dev, enable); - modem_syscon_ll_enable_modem_sec_clock(ctx->hal->syscon_dev, enable); - modem_syscon_ll_enable_ble_timer_clock(ctx->hal->syscon_dev, enable); -} - -#if CONFIG_ESP_MODEM_CLOCK_ENABLE_CHECKING -static esp_err_t IRAM_ATTR modem_clock_ble_mac_check_enable(modem_clock_context_t *ctx) -{ - bool all_clock_enabled = true; - all_clock_enabled &= modem_syscon_ll_bt_mac_clock_is_enabled(ctx->hal->syscon_dev); - all_clock_enabled &= modem_syscon_ll_modem_sec_clock_is_enabled(ctx->hal->syscon_dev); - all_clock_enabled &= modem_syscon_ll_ble_timer_clock_is_enabled(ctx->hal->syscon_dev); - return all_clock_enabled ? ESP_OK : ESP_FAIL; -} -#endif -#endif // SOC_BT_SUPPORTED - -#if SOC_PHY_CALIBRATION_CLOCK_IS_INDEPENDENT -static void IRAM_ATTR modem_clock_wifi_apb_configure(modem_clock_context_t *ctx, bool enable) -{ - if (enable || !(ctx->modem_status & MODEM_STATUS_WIFI_INITED)) { - modem_syscon_ll_enable_wifi_apb_clock(ctx->hal->syscon_dev, enable); - } -} - -static void IRAM_ATTR modem_clock_wifi_bb_44m_configure(modem_clock_context_t *ctx, bool enable) -{ - if (enable || !(ctx->modem_status & MODEM_STATUS_WIFI_INITED)) { - modem_syscon_ll_enable_wifibb_44m_clock(ctx->hal->syscon_dev, enable); - } -} - -#if CONFIG_ESP_MODEM_CLOCK_ENABLE_CHECKING -static esp_err_t IRAM_ATTR modem_clock_wifi_apb_check_enable(modem_clock_context_t *ctx) -{ - return modem_syscon_ll_wifi_apb_clock_is_enabled(ctx->hal->syscon_dev) ? ESP_OK : ESP_FAIL; -} - -static esp_err_t IRAM_ATTR modem_clock_wifi_bb_44m_check_enable(modem_clock_context_t *ctx) -{ - return modem_syscon_ll_wifibb_44m_clock_is_enabled(ctx->hal->syscon_dev) ? ESP_OK : ESP_FAIL; -} -#endif -#endif - -#if SOC_BT_SUPPORTED || SOC_IEEE802154_SUPPORTED -static void IRAM_ATTR modem_clock_ble_i154_bb_configure(modem_clock_context_t *ctx, bool enable) -{ - modem_syscon_ll_enable_bt_apb_clock(ctx->hal->syscon_dev, enable); - modem_syscon_ll_enable_bt_clock(ctx->hal->syscon_dev, enable); -} - -#if CONFIG_ESP_MODEM_CLOCK_ENABLE_CHECKING -static esp_err_t IRAM_ATTR modem_clock_ble_i154_bb_check_enable(modem_clock_context_t *ctx) -{ - bool all_clock_enabled = true; - all_clock_enabled &= modem_syscon_ll_bt_apb_clock_is_enabled(ctx->hal->syscon_dev); - all_clock_enabled &= modem_syscon_ll_bt_clock_is_enabled(ctx->hal->syscon_dev); - return all_clock_enabled ? ESP_OK : ESP_FAIL; -} -#endif -#endif // SOC_BT_SUPPORTED || SOC_IEEE802154_SUPPORTED - -#if SOC_IEEE802154_SUPPORTED -static void IRAM_ATTR modem_clock_ieee802154_mac_configure(modem_clock_context_t *ctx, bool enable) -{ - modem_syscon_ll_enable_ieee802154_apb_clock(ctx->hal->syscon_dev, enable); - modem_syscon_ll_enable_ieee802154_mac_clock(ctx->hal->syscon_dev, enable); -} - -#if CONFIG_ESP_MODEM_CLOCK_ENABLE_CHECKING -static esp_err_t IRAM_ATTR modem_clock_ieee802154_mac_check_enable(modem_clock_context_t *ctx) -{ - bool all_clock_enabled = true; - all_clock_enabled &= modem_syscon_ll_ieee802154_apb_clock_is_enabled(ctx->hal->syscon_dev); - all_clock_enabled &= modem_syscon_ll_ieee802154_mac_clock_is_enabled(ctx->hal->syscon_dev); - return all_clock_enabled ? ESP_OK : ESP_FAIL; -} -#endif -#endif // SOC_IEEE802154_SUPPORTED - -static void IRAM_ATTR modem_clock_coex_configure(modem_clock_context_t *ctx, bool enable) -{ - modem_lpcon_ll_enable_coex_clock(ctx->hal->lpcon_dev, enable); -} - -static void IRAM_ATTR modem_clock_modem_adc_common_fe_configure(modem_clock_context_t *ctx, bool enable) -{ - modem_clock_hal_enable_modem_common_fe_clock(ctx->hal, enable); -} - -static void IRAM_ATTR modem_clock_modem_private_fe_configure(modem_clock_context_t *ctx, bool enable) -{ - modem_clock_hal_enable_modem_private_fe_clock(ctx->hal, enable); -} - -#if ANA_I2C_MST_CLK_HAS_ROOT_GATING -static void IRAM_ATTR modem_clock_i2c_master_configure(modem_clock_context_t *ctx, bool enable) -{ - if (enable) { - ANALOG_CLOCK_ENABLE(); - } else { - ANALOG_CLOCK_DISABLE(); - } -} -#endif - -static void IRAM_ATTR modem_clock_etm_configure(modem_clock_context_t *ctx, bool enable) -{ - modem_syscon_ll_enable_etm_clock(ctx->hal->syscon_dev, enable); -} - -static void IRAM_ATTR modem_clock_data_dump_configure(modem_clock_context_t *ctx, bool enable) -{ - modem_syscon_ll_enable_data_dump_clock(ctx->hal->syscon_dev, enable); - modem_syscon_ll_enable_data_dump_mux_clock(ctx->hal->syscon_dev, enable); -} - -#if CONFIG_ESP_MODEM_CLOCK_ENABLE_CHECKING -static esp_err_t IRAM_ATTR modem_clock_coex_check_enable(modem_clock_context_t *ctx) -{ - return modem_lpcon_ll_coex_clock_is_enabled(ctx->hal->lpcon_dev) ? ESP_OK : ESP_FAIL; -} - -static esp_err_t IRAM_ATTR modem_clock_modem_adc_common_fe_check_enable(modem_clock_context_t *ctx) -{ - return modem_clock_hal_modem_common_fe_clock_is_enabled(ctx->hal) ? ESP_OK : ESP_FAIL; -} - -static esp_err_t IRAM_ATTR modem_clock_modem_private_fe_check_enable(modem_clock_context_t *ctx) -{ - return modem_clock_hal_modem_private_fe_clock_is_enabled(ctx->hal) ? ESP_OK : ESP_FAIL; -} - -#if ANA_I2C_MST_CLK_HAS_ROOT_GATING -static esp_err_t IRAM_ATTR modem_clock_i2c_master_check_enable(modem_clock_context_t *ctx) -{ - return ANALOG_CLOCK_IS_ENABLED() ? ESP_OK : ESP_FAIL; -} -#endif - -static esp_err_t IRAM_ATTR modem_clock_etm_check_enable(modem_clock_context_t *ctx) -{ - return modem_syscon_ll_etm_clock_is_enabled(ctx->hal->syscon_dev) ? ESP_OK : ESP_FAIL; -} - -static esp_err_t IRAM_ATTR modem_clock_data_dump_check_enable(modem_clock_context_t *ctx) -{ - bool all_clock_enabled = true; - all_clock_enabled &= modem_syscon_ll_data_dump_clock_is_enabled(ctx->hal->syscon_dev); - all_clock_enabled &= modem_syscon_ll_data_dump_mux_clock_is_enabled(ctx->hal->syscon_dev); - return all_clock_enabled ? ESP_OK : ESP_FAIL; -} +#if SOC_CLOCK_TREE_MANAGEMENT_SUPPORTED +#include "esp_private/esp_clk_tree_common.h" #endif modem_clock_context_t * __attribute__((weak)) IRAM_ATTR MODEM_CLOCK_instance(void) @@ -278,113 +26,27 @@ modem_clock_context_t * __attribute__((weak)) IRAM_ATTR MODEM_CLOCK_instance(voi /* It should be explicitly defined in the internal RAM */ static DRAM_ATTR modem_clock_hal_context_t modem_clock_hal = { .syscon_dev = NULL, .lpcon_dev = NULL }; static DRAM_ATTR modem_clock_context_t modem_clock_context = { - .hal = &modem_clock_hal, .lock = portMUX_INITIALIZER_UNLOCKED, - .dev = { - [MODEM_CLOCK_MODEM_ADC_COMMON_FE] = { .refs = 0, .with_refcnt = true, .configure = modem_clock_modem_adc_common_fe_configure }, - [MODEM_CLOCK_MODEM_PRIVATE_FE] = { .refs = 0, .with_refcnt = true, .configure = modem_clock_modem_private_fe_configure }, - [MODEM_CLOCK_COEXIST] = { .refs = 0, .with_refcnt = true, .configure = modem_clock_coex_configure }, -#if ANA_I2C_MST_CLK_HAS_ROOT_GATING - // ANALOG_CLOCK_ENABLE/DISABLE has its own ref_cnt management. - [MODEM_CLOCK_I2C_MASTER] = { .refs = 0, .with_refcnt = false, .configure = modem_clock_i2c_master_configure }, + .hal = &modem_clock_hal, .lock = SPINLOCK_INITIALIZER, + .dev = g_modem_clock_dev, +#if SOC_PM_SUPPORT_PMU_MODEM_STATE + .initial_gating_mode = g_initial_gating_mode, #endif -#if SOC_PHY_CALIBRATION_CLOCK_IS_INDEPENDENT - [MODEM_CLOCK_WIFI_APB] = { .refs = 0, .with_refcnt = true, .configure = modem_clock_wifi_apb_configure }, - [MODEM_CLOCK_WIFI_BB_44M] = { .refs = 0, .with_refcnt = true, .configure = modem_clock_wifi_bb_44m_configure }, -#endif -#if SOC_WIFI_SUPPORTED - [MODEM_CLOCK_WIFI_MAC] = { .refs = 0, .with_refcnt = true, .configure = modem_clock_wifi_mac_configure }, - [MODEM_CLOCK_WIFI_BB] = { .refs = 0, .with_refcnt = true, .configure = modem_clock_wifi_bb_configure }, -#endif - [MODEM_CLOCK_ETM] = { .refs = 0, .with_refcnt = true, .configure = modem_clock_etm_configure }, -#if SOC_BT_SUPPORTED - [MODEM_CLOCK_BLE_MAC] = { .refs = 0, .with_refcnt = true, .configure = modem_clock_ble_mac_configure }, -#endif -#if SOC_IEEE802154_SUPPORTED || SOC_BT_SUPPORTED - [MODEM_CLOCK_BT_I154_COMMON_BB] = { .refs = 0, .with_refcnt = true, .configure = modem_clock_ble_i154_bb_configure }, -#endif -#if SOC_IEEE802154_SUPPORTED - [MODEM_CLOCK_802154_MAC] = { .refs = 0, .with_refcnt = true, .configure = modem_clock_ieee802154_mac_configure }, -#endif - [MODEM_CLOCK_DATADUMP] = { .refs = 0, .with_refcnt = true, .configure = modem_clock_data_dump_configure } - }, .lpclk_src = { [0 ... PERIPH_MODEM_MODULE_NUM - 1] = MODEM_CLOCK_LPCLK_SRC_INVALID } #if SOC_WIFI_SUPPORTED , .modem_status = MODEM_STATUS_IDLE #endif }; - if (modem_clock_hal.syscon_dev == NULL || modem_clock_hal.lpcon_dev == NULL) { modem_clock_hal.syscon_dev = &MODEM_SYSCON; modem_clock_hal.lpcon_dev = &MODEM_LPCON; #if SOC_CLOCK_TREE_MANAGEMENT_SUPPORTED ESP_ERROR_CHECK(esp_clk_tree_enable_src(SOC_MOD_CLK_MODEM_APB, true)); #endif -#if CONFIG_ESP_MODEM_CLOCK_ENABLE_CHECKING - modem_clock_context.dev[MODEM_CLOCK_MODEM_ADC_COMMON_FE].check_enable = modem_clock_modem_adc_common_fe_check_enable; - modem_clock_context.dev[MODEM_CLOCK_MODEM_PRIVATE_FE].check_enable = modem_clock_modem_private_fe_check_enable; - modem_clock_context.dev[MODEM_CLOCK_COEXIST].check_enable = modem_clock_coex_check_enable; - #if ANA_I2C_MST_CLK_HAS_ROOT_GATING - modem_clock_context.dev[MODEM_CLOCK_I2C_MASTER].check_enable = modem_clock_i2c_master_check_enable; - #endif - #if SOC_PHY_CALIBRATION_CLOCK_IS_INDEPENDENT - modem_clock_context.dev[MODEM_CLOCK_WIFI_APB].check_enable = modem_clock_wifi_apb_check_enable; - modem_clock_context.dev[MODEM_CLOCK_WIFI_BB_44M].check_enable = modem_clock_wifi_bb_44m_check_enable; - #endif - #if SOC_WIFI_SUPPORTED - modem_clock_context.dev[MODEM_CLOCK_WIFI_MAC].check_enable = modem_clock_wifi_mac_check_enable; - modem_clock_context.dev[MODEM_CLOCK_WIFI_BB].check_enable = modem_clock_wifi_bb_check_enable; - #endif - modem_clock_context.dev[MODEM_CLOCK_ETM].check_enable = modem_clock_etm_check_enable; - #if SOC_BT_SUPPORTED - modem_clock_context.dev[MODEM_CLOCK_BLE_MAC].check_enable = modem_clock_ble_mac_check_enable; - #endif - #if SOC_IEEE802154_SUPPORTED || SOC_BT_SUPPORTED - modem_clock_context.dev[MODEM_CLOCK_BT_I154_COMMON_BB].check_enable = modem_clock_ble_i154_bb_check_enable; - #endif - #if SOC_IEEE802154_SUPPORTED - modem_clock_context.dev[MODEM_CLOCK_802154_MAC].check_enable = modem_clock_ieee802154_mac_check_enable; - #endif - modem_clock_context.dev[MODEM_CLOCK_DATADUMP].check_enable = modem_clock_data_dump_check_enable; -#endif // CONFIG_ESP_MODEM_CLOCK_ENABLE_CHECKING } return &modem_clock_context; } -#if SOC_BLE_USE_WIFI_PWR_CLK_WORKAROUND -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; - } - - esp_os_enter_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))); - esp_os_exit_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; - } - - esp_os_enter_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))); - esp_os_exit_critical_safe(&MODEM_CLOCK_instance()->lock); - return ESP_OK; -} -#endif // #if SOC_BLE_USE_WIFI_PWR_CLK_WORKAROUND - static void IRAM_ATTR modem_clock_device_enable(modem_clock_context_t *ctx, uint32_t dev_map) { int16_t refs = 0; @@ -453,88 +115,6 @@ void IRAM_ATTR modem_clock_module_mac_reset(shared_periph_module_t module) } esp_os_exit_critical_safe(&ctx->lock); } -#if SOC_PHY_CALIBRATION_CLOCK_IS_INDEPENDENT -#define WIFI_CLOCK_DEPS (BIT(MODEM_CLOCK_WIFI_MAC) | BIT(MODEM_CLOCK_WIFI_APB) | BIT(MODEM_CLOCK_WIFI_BB) | BIT(MODEM_CLOCK_WIFI_BB_44M) | BIT(MODEM_CLOCK_COEXIST)) -#else -#define WIFI_CLOCK_DEPS (BIT(MODEM_CLOCK_WIFI_MAC) | BIT(MODEM_CLOCK_WIFI_BB) | BIT(MODEM_CLOCK_COEXIST)) -#endif -#define BLE_CLOCK_DEPS (BIT(MODEM_CLOCK_BLE_MAC) | BIT(MODEM_CLOCK_BT_I154_COMMON_BB) | BIT(MODEM_CLOCK_ETM) | BIT(MODEM_CLOCK_COEXIST)) -#define IEEE802154_CLOCK_DEPS (BIT(MODEM_CLOCK_802154_MAC) | BIT(MODEM_CLOCK_BT_I154_COMMON_BB) | BIT(MODEM_CLOCK_ETM) | BIT(MODEM_CLOCK_COEXIST)) -#define COEXIST_CLOCK_DEPS (BIT(MODEM_CLOCK_COEXIST)) -#if ANA_I2C_MST_CLK_HAS_ROOT_GATING -#define I2C_ANA_MST_CLOCK_DEPS (BIT(MODEM_CLOCK_I2C_MASTER)) -#else -#define I2C_ANA_MST_CLOCK_DEPS (0) -#endif -#define PHY_CLOCK_DEPS (I2C_ANA_MST_CLOCK_DEPS | BIT(MODEM_CLOCK_MODEM_ADC_COMMON_FE) | BIT(MODEM_CLOCK_MODEM_PRIVATE_FE)) -#define MODEM_ETM_CLOCK_DEPS (BIT(MODEM_CLOCK_ETM)) -#define MODEM_ADC_COMMON_FE_CLOCK_DEPS (BIT(MODEM_CLOCK_MODEM_ADC_COMMON_FE)) -#if SOC_PHY_CALIBRATION_CLOCK_IS_INDEPENDENT -#define PHY_CALIBRATION_WIFI_CLOCK_DEPS (BIT(MODEM_CLOCK_WIFI_APB) | BIT(MODEM_CLOCK_WIFI_BB) | BIT(MODEM_CLOCK_WIFI_BB_44M)) -#define PHY_CALIBRATION_BT_I154_CLOCK_DEPS (BIT(MODEM_CLOCK_WIFI_APB) | BIT(MODEM_CLOCK_WIFI_BB_44M) | BIT(MODEM_CLOCK_BT_I154_COMMON_BB)) -#else -#define PHY_CALIBRATION_WIFI_CLOCK_DEPS (BIT(MODEM_CLOCK_WIFI_BB)) -#define PHY_CALIBRATION_BT_I154_CLOCK_DEPS (BIT(MODEM_CLOCK_BT_I154_COMMON_BB)) -#endif -#ifndef SOC_WIFI_SUPPORTED -#undef PHY_CALIBRATION_WIFI_CLOCK_DEPS -#define PHY_CALIBRATION_WIFI_CLOCK_DEPS 0 -#endif -#if !defined(SOC_BT_SUPPORTED) && !defined(SOC_IEEE802154_SUPPORTED) -#undef PHY_CALIBRATION_BT_I154_CLOCK_DEPS -#define PHY_CALIBRATION_BT_I154_CLOCK_DEPS 0 -#endif -#define PHY_CALIBRATION_CLOCK_DEPS (PHY_CALIBRATION_WIFI_CLOCK_DEPS | PHY_CALIBRATION_BT_I154_CLOCK_DEPS) - -static IRAM_ATTR uint32_t modem_clock_get_module_deps(shared_periph_module_t module) -{ - uint32_t deps = 0; - switch (module) { - case PERIPH_ANA_I2C_MASTER_MODULE: deps = I2C_ANA_MST_CLOCK_DEPS; break; - case PERIPH_PHY_MODULE: deps = PHY_CLOCK_DEPS; break; - case PERIPH_MODEM_ADC_COMMON_FE_MODULE: deps = MODEM_ADC_COMMON_FE_CLOCK_DEPS; break; -#if SOC_WIFI_SUPPORTED || SOC_BT_SUPPORTED || SOC_IEEE802154_SUPPORTED - case PERIPH_COEX_MODULE: deps = COEXIST_CLOCK_DEPS; break; -#endif -#if SOC_WIFI_SUPPORTED - case PERIPH_WIFI_MODULE: deps = WIFI_CLOCK_DEPS; break; -#endif -#if SOC_BT_SUPPORTED - case PERIPH_BT_MODULE: deps = BLE_CLOCK_DEPS; break; -#endif - case PERIPH_PHY_CALIBRATION_MODULE: deps = PHY_CALIBRATION_CLOCK_DEPS; break; -#if SOC_IEEE802154_SUPPORTED - case PERIPH_IEEE802154_MODULE: deps = IEEE802154_CLOCK_DEPS; break; -#endif -#if SOC_BT_SUPPORTED || SOC_IEEE802154_SUPPORTED - case PERIPH_MODEM_ETM_MODULE: deps = MODEM_ETM_CLOCK_DEPS; break; -#endif - default: - assert(0); - } - return deps; -} - -/* the ICG code's bit 0, 1 and 2 indicates the ICG state - * of pmu SLEEP, MODEM and ACTIVE mode respectively */ -#define ICG_NOGATING_ACTIVE (BIT(PMU_HP_ICG_MODEM_CODE_ACTIVE)) -#define ICG_NOGATING_SLEEP (BIT(PMU_HP_ICG_MODEM_CODE_SLEEP)) -#define ICG_NOGATING_MODEM (BIT(PMU_HP_ICG_MODEM_CODE_MODEM)) - -#if SOC_PM_SUPPORT_PMU_MODEM_STATE -static const DRAM_ATTR uint32_t initial_gating_mode[MODEM_CLOCK_DOMAIN_MAX] = { - [MODEM_CLOCK_DOMAIN_MODEM_APB] = ICG_NOGATING_ACTIVE | ICG_NOGATING_MODEM, - [MODEM_CLOCK_DOMAIN_MODEM_PERIPH] = ICG_NOGATING_ACTIVE, - [MODEM_CLOCK_DOMAIN_WIFI] = ICG_NOGATING_ACTIVE | ICG_NOGATING_MODEM, - [MODEM_CLOCK_DOMAIN_BT] = ICG_NOGATING_ACTIVE, - [MODEM_CLOCK_DOMAIN_MODEM_FE] = ICG_NOGATING_ACTIVE | ICG_NOGATING_MODEM, - [MODEM_CLOCK_DOMAIN_IEEE802154] = ICG_NOGATING_ACTIVE, - [MODEM_CLOCK_DOMAIN_LP_APB] = ICG_NOGATING_ACTIVE | ICG_NOGATING_MODEM, - [MODEM_CLOCK_DOMAIN_I2C_MASTER] = ICG_NOGATING_ACTIVE | ICG_NOGATING_MODEM, - [MODEM_CLOCK_DOMAIN_COEX] = ICG_NOGATING_ACTIVE | ICG_NOGATING_MODEM, - [MODEM_CLOCK_DOMAIN_WIFIPWR] = ICG_NOGATING_ACTIVE | ICG_NOGATING_MODEM, -}; -#endif #if SOC_PM_SUPPORT_PMU_MODEM_STATE static IRAM_ATTR void modem_clock_module_icg_map_init_all(void) @@ -542,7 +122,7 @@ static IRAM_ATTR void modem_clock_module_icg_map_init_all(void) esp_os_enter_critical_safe(&MODEM_CLOCK_instance()->lock); for (int domain = 0; domain < MODEM_CLOCK_DOMAIN_MAX; domain++) { 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, initial_gating_mode[domain] | code); + modem_clock_hal_set_clock_domain_icg_bitmap(MODEM_CLOCK_instance()->hal, domain, MODEM_CLOCK_instance()->initial_gating_mode[domain] | code); #if CONFIG_ESP_MODEM_CLOCK_ENABLE_CHECKING assert((modem_clock_hal_get_clock_domain_icg_bitmap(MODEM_CLOCK_instance()->hal, domain) & code) == code); #endif @@ -633,36 +213,17 @@ void modem_clock_select_lp_clock_source(shared_periph_module_t module, modem_clo case PERIPH_BT_MODULE: { #if CONFIG_IDF_TARGET_ESP32H2 - bool rc_clk_en = true; - bool selected = (src == MODEM_CLOCK_LPCLK_SRC_MAIN_XTAL) || - (src == MODEM_CLOCK_LPCLK_SRC_RC_SLOW); - if (selected) { - rc_clk_en = clk_ll_rc32k_is_enabled(); - if (!rc_clk_en) { - rtc_clk_rc32k_enable(true); - } - modem_clock_hal_select_ble_rtc_timer_lpclk_source(MODEM_CLOCK_instance()->hal, MODEM_CLOCK_LPCLK_SRC_RC32K); - } -#endif // CONFIG_IDF_TARGET_ESP32H2 + modem_clock_select_ble_rtc_timer_clk_workaround(MODEM_CLOCK_instance(), true, src); +#endif modem_clock_hal_deselect_all_ble_rtc_timer_lpclk_source(MODEM_CLOCK_instance()->hal); modem_clock_hal_select_ble_rtc_timer_lpclk_source(MODEM_CLOCK_instance()->hal, src); modem_clock_hal_set_ble_rtc_timer_divisor_value(MODEM_CLOCK_instance()->hal, divider); modem_clock_hal_enable_ble_rtc_timer_clock(MODEM_CLOCK_instance()->hal, true); #if CONFIG_IDF_TARGET_ESP32H2 - if (!rc_clk_en) { - extern void r_esp_ble_rtc_ticks_delay(uint32_t ticks); - r_esp_ble_rtc_ticks_delay(2); - rtc_clk_rc32k_enable(false); - } -#endif // CONFIG_IDF_TARGET_ESP32H2 + modem_clock_select_ble_rtc_timer_clk_workaround(MODEM_CLOCK_instance(), false, src); +#endif #if SOC_BLE_USE_WIFI_PWR_CLK_WORKAROUND - if (efuse_hal_chip_revision() != 0) { - if (src == MODEM_CLOCK_LPCLK_SRC_MAIN_XTAL) { - esp_sleep_clock_config(ESP_SLEEP_CLOCK_BT_USE_WIFI_PWR_CLK, ESP_SLEEP_CLOCK_OPTION_UNGATE); - modem_clock_hal_enable_wifipwr_clock(MODEM_CLOCK_instance()->hal, true); - modem_clock_domain_clk_gate_disable(MODEM_CLOCK_DOMAIN_WIFIPWR, PMU_HP_ICG_MODEM_CODE_SLEEP); - } - } + modem_clock_bt_wifipwr_clk_workaround(MODEM_CLOCK_instance(), true, src); #endif break; } @@ -714,7 +275,6 @@ void modem_clock_deselect_lp_clock_source(shared_periph_module_t module) #if SOC_LIGHT_SLEEP_SUPPORTED modem_clock_lpclk_src_t last_src = MODEM_CLOCK_instance()->lpclk_src[module - PERIPH_MODEM_MODULE_MIN]; #endif - MODEM_CLOCK_instance()->lpclk_src[module - PERIPH_MODEM_MODULE_MIN] = MODEM_CLOCK_LPCLK_SRC_INVALID; switch (module) { #if SOC_WIFI_SUPPORTED @@ -728,14 +288,8 @@ void modem_clock_deselect_lp_clock_source(shared_periph_module_t module) case PERIPH_BT_MODULE: modem_clock_hal_deselect_all_ble_rtc_timer_lpclk_source(MODEM_CLOCK_instance()->hal); modem_clock_hal_enable_ble_rtc_timer_clock(MODEM_CLOCK_instance()->hal, false); -#if SOC_BLE_USE_WIFI_PWR_CLK_WORKAROUND && SOC_LIGHT_SLEEP_SUPPORTED // TODO: [ESP32C5] IDF-8643 - if (efuse_hal_chip_revision() != 0) { - if (last_src == MODEM_CLOCK_LPCLK_SRC_MAIN_XTAL) { - esp_sleep_clock_config(ESP_SLEEP_CLOCK_BT_USE_WIFI_PWR_CLK, ESP_SLEEP_CLOCK_OPTION_GATE); - modem_clock_hal_enable_wifipwr_clock(MODEM_CLOCK_instance()->hal, false); - modem_clock_domain_clk_gate_enable(MODEM_CLOCK_DOMAIN_WIFIPWR, PMU_HP_ICG_MODEM_CODE_SLEEP); - } - } +#if SOC_BLE_USE_WIFI_PWR_CLK_WORKAROUND + modem_clock_bt_wifipwr_clk_workaround(MODEM_CLOCK_instance(), false, last_src); #endif break; #endif // SOC_BT_SUPPORTED @@ -746,6 +300,7 @@ void modem_clock_deselect_lp_clock_source(shared_periph_module_t module) default: break; } + MODEM_CLOCK_instance()->lpclk_src[module - PERIPH_MODEM_MODULE_MIN] = MODEM_CLOCK_LPCLK_SRC_INVALID; esp_os_exit_critical_safe(&MODEM_CLOCK_instance()->lock); #if SOC_LIGHT_SLEEP_SUPPORTED diff --git a/components/esp_hw_support/port/esp32c5/CMakeLists.txt b/components/esp_hw_support/port/esp32c5/CMakeLists.txt index b27e92b99c..b8dba1dc73 100644 --- a/components/esp_hw_support/port/esp32c5/CMakeLists.txt +++ b/components/esp_hw_support/port/esp32c5/CMakeLists.txt @@ -12,6 +12,10 @@ set(srcs "rtc_clk_init.c" if(NOT non_os_build) list(APPEND srcs "sar_periph_ctrl.c") + + if(CONFIG_SOC_MODEM_CLOCK_IS_INDEPENDENT AND CONFIG_SOC_MODEM_CLOCK_SUPPORTED) + list(APPEND srcs "modem_clock_impl.c") + endif() endif() if(NOT BOOTLOADER_BUILD AND CONFIG_ESP_ENABLE_PVT) diff --git a/components/esp_hw_support/port/esp32c5/modem_clock_impl.c b/components/esp_hw_support/port/esp32c5/modem_clock_impl.c new file mode 100644 index 0000000000..ef303da61a --- /dev/null +++ b/components/esp_hw_support/port/esp32c5/modem_clock_impl.c @@ -0,0 +1,364 @@ +/* + * SPDX-FileCopyrightText: 2025-2026 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include "sdkconfig.h" +#include "esp_attr.h" +#include "soc/soc_caps.h" +#include "esp_private/esp_modem_clock.h" +#include "esp_private/regi2c_ctrl.h" + +/* Clock dependency definitions */ +#if SOC_PHY_CALIBRATION_CLOCK_IS_INDEPENDENT +#define WIFI_CLOCK_DEPS (BIT(MODEM_CLOCK_WIFI_MAC) | BIT(MODEM_CLOCK_WIFI_APB) | BIT(MODEM_CLOCK_WIFI_BB) | BIT(MODEM_CLOCK_WIFI_BB_44M) | BIT(MODEM_CLOCK_COEXIST)) +#else +#define WIFI_CLOCK_DEPS (BIT(MODEM_CLOCK_WIFI_MAC) | BIT(MODEM_CLOCK_WIFI_BB) | BIT(MODEM_CLOCK_COEXIST)) +#endif +#define BLE_CLOCK_DEPS (BIT(MODEM_CLOCK_BLE_MAC) | BIT(MODEM_CLOCK_BT_I154_COMMON_BB) | BIT(MODEM_CLOCK_ETM) | BIT(MODEM_CLOCK_COEXIST)) +#define IEEE802154_CLOCK_DEPS (BIT(MODEM_CLOCK_802154_MAC) | BIT(MODEM_CLOCK_BT_I154_COMMON_BB) | BIT(MODEM_CLOCK_ETM) | BIT(MODEM_CLOCK_COEXIST)) +#define COEXIST_CLOCK_DEPS (BIT(MODEM_CLOCK_COEXIST)) +#if ANA_I2C_MST_CLK_HAS_ROOT_GATING +#define I2C_ANA_MST_CLOCK_DEPS (BIT(MODEM_CLOCK_I2C_MASTER)) +#else +#define I2C_ANA_MST_CLOCK_DEPS (0) +#endif +#define PHY_CLOCK_DEPS (I2C_ANA_MST_CLOCK_DEPS | BIT(MODEM_CLOCK_MODEM_ADC_COMMON_FE) | BIT(MODEM_CLOCK_MODEM_PRIVATE_FE)) +#define MODEM_ETM_CLOCK_DEPS (BIT(MODEM_CLOCK_ETM)) +#define MODEM_ADC_COMMON_FE_CLOCK_DEPS (BIT(MODEM_CLOCK_MODEM_ADC_COMMON_FE)) +#if SOC_PHY_CALIBRATION_CLOCK_IS_INDEPENDENT +#define PHY_CALIBRATION_WIFI_CLOCK_DEPS (BIT(MODEM_CLOCK_WIFI_APB) | BIT(MODEM_CLOCK_WIFI_BB) | BIT(MODEM_CLOCK_WIFI_BB_44M)) +#define PHY_CALIBRATION_BT_I154_CLOCK_DEPS (BIT(MODEM_CLOCK_WIFI_APB) | BIT(MODEM_CLOCK_WIFI_BB_44M) | BIT(MODEM_CLOCK_BT_I154_COMMON_BB)) +#else +#define PHY_CALIBRATION_WIFI_CLOCK_DEPS (BIT(MODEM_CLOCK_WIFI_BB)) +#define PHY_CALIBRATION_BT_I154_CLOCK_DEPS (BIT(MODEM_CLOCK_BT_I154_COMMON_BB)) +#endif +#ifndef SOC_WIFI_SUPPORTED +#undef PHY_CALIBRATION_WIFI_CLOCK_DEPS +#define PHY_CALIBRATION_WIFI_CLOCK_DEPS 0 +#endif +#if !defined(SOC_BT_SUPPORTED) && !defined(SOC_IEEE802154_SUPPORTED) +#undef PHY_CALIBRATION_BT_I154_CLOCK_DEPS +#define PHY_CALIBRATION_BT_I154_CLOCK_DEPS 0 +#endif +#define PHY_CALIBRATION_CLOCK_DEPS (PHY_CALIBRATION_WIFI_CLOCK_DEPS | PHY_CALIBRATION_BT_I154_CLOCK_DEPS) + +uint32_t modem_clock_get_module_deps(shared_periph_module_t module) +{ + uint32_t deps = 0; + switch (module) { + case PERIPH_ANA_I2C_MASTER_MODULE: deps = I2C_ANA_MST_CLOCK_DEPS; break; + case PERIPH_PHY_MODULE: deps = PHY_CLOCK_DEPS; break; + case PERIPH_MODEM_ADC_COMMON_FE_MODULE: deps = MODEM_ADC_COMMON_FE_CLOCK_DEPS; break; +#if SOC_WIFI_SUPPORTED || SOC_BT_SUPPORTED || SOC_IEEE802154_SUPPORTED + case PERIPH_COEX_MODULE: deps = COEXIST_CLOCK_DEPS; break; +#endif +#if SOC_WIFI_SUPPORTED + case PERIPH_WIFI_MODULE: deps = WIFI_CLOCK_DEPS; break; +#endif +#if SOC_BT_SUPPORTED + case PERIPH_BT_MODULE: deps = BLE_CLOCK_DEPS; break; +#endif + case PERIPH_PHY_CALIBRATION_MODULE: deps = PHY_CALIBRATION_CLOCK_DEPS; break; +#if SOC_IEEE802154_SUPPORTED + case PERIPH_IEEE802154_MODULE: deps = IEEE802154_CLOCK_DEPS; break; +#endif +#if SOC_BT_SUPPORTED || SOC_IEEE802154_SUPPORTED + case PERIPH_MODEM_ETM_MODULE: deps = MODEM_ETM_CLOCK_DEPS; break; +#endif + default: + assert(0); + } + return deps; +} + +#if SOC_WIFI_SUPPORTED +static void IRAM_ATTR modem_clock_wifi_mac_configure(modem_clock_context_t *ctx, bool enable) +{ + if (enable || !(ctx->modem_status & MODEM_STATUS_WIFI_INITED)) { +#if !SOC_PHY_CALIBRATION_CLOCK_IS_INDEPENDENT + modem_syscon_ll_enable_wifi_apb_clock(ctx->hal->syscon_dev, enable); +#endif + modem_syscon_ll_enable_wifi_mac_clock(ctx->hal->syscon_dev, enable); + } +} + +static void IRAM_ATTR modem_clock_wifi_bb_configure(modem_clock_context_t *ctx, bool enable) +{ + if (enable || !(ctx->modem_status & MODEM_STATUS_WIFI_INITED)) { + modem_syscon_ll_clk_wifibb_configure(ctx->hal->syscon_dev, enable); + } +} + +#if CONFIG_ESP_MODEM_CLOCK_ENABLE_CHECKING +static esp_err_t IRAM_ATTR modem_clock_wifi_mac_check_enable(modem_clock_context_t *ctx) +{ + bool all_clock_enabled = true; +#if !SOC_PHY_CALIBRATION_CLOCK_IS_INDEPENDENT + all_clock_enabled &= modem_syscon_ll_wifi_apb_clock_is_enabled(ctx->hal->syscon_dev); +#endif + all_clock_enabled &= modem_syscon_ll_wifi_mac_clock_is_enabled(ctx->hal->syscon_dev); + return all_clock_enabled ? ESP_OK : ESP_FAIL; +} + +static esp_err_t IRAM_ATTR modem_clock_wifi_bb_check_enable(modem_clock_context_t *ctx) +{ + return modem_syscon_ll_wifibb_clock_is_enabled(ctx->hal->syscon_dev) ? ESP_OK : ESP_FAIL; +} +#endif +#endif // SOC_WIFI_SUPPORTED + +#if SOC_BT_SUPPORTED +static void IRAM_ATTR modem_clock_ble_mac_configure(modem_clock_context_t *ctx, bool enable) +{ + modem_syscon_ll_enable_bt_mac_clock(ctx->hal->syscon_dev, enable); + modem_syscon_ll_enable_modem_sec_clock(ctx->hal->syscon_dev, enable); + modem_syscon_ll_enable_ble_timer_clock(ctx->hal->syscon_dev, enable); +} + +#if CONFIG_ESP_MODEM_CLOCK_ENABLE_CHECKING +static esp_err_t IRAM_ATTR modem_clock_ble_mac_check_enable(modem_clock_context_t *ctx) +{ + bool all_clock_enabled = true; + all_clock_enabled &= modem_syscon_ll_bt_mac_clock_is_enabled(ctx->hal->syscon_dev); + all_clock_enabled &= modem_syscon_ll_modem_sec_clock_is_enabled(ctx->hal->syscon_dev); + all_clock_enabled &= modem_syscon_ll_ble_timer_clock_is_enabled(ctx->hal->syscon_dev); + return all_clock_enabled ? ESP_OK : ESP_FAIL; +} +#endif +#endif // SOC_BT_SUPPORTED + +#if SOC_PHY_CALIBRATION_CLOCK_IS_INDEPENDENT +static void IRAM_ATTR modem_clock_wifi_apb_configure(modem_clock_context_t *ctx, bool enable) +{ + if (enable || !(ctx->modem_status & MODEM_STATUS_WIFI_INITED)) { + modem_syscon_ll_enable_wifi_apb_clock(ctx->hal->syscon_dev, enable); + } +} + +static void IRAM_ATTR modem_clock_wifi_bb_44m_configure(modem_clock_context_t *ctx, bool enable) +{ + if (enable || !(ctx->modem_status & MODEM_STATUS_WIFI_INITED)) { + modem_syscon_ll_enable_wifibb_44m_clock(ctx->hal->syscon_dev, enable); + } +} + +#if CONFIG_ESP_MODEM_CLOCK_ENABLE_CHECKING +static esp_err_t IRAM_ATTR modem_clock_wifi_apb_check_enable(modem_clock_context_t *ctx) +{ + return modem_syscon_ll_wifi_apb_clock_is_enabled(ctx->hal->syscon_dev) ? ESP_OK : ESP_FAIL; +} + +static esp_err_t IRAM_ATTR modem_clock_wifi_bb_44m_check_enable(modem_clock_context_t *ctx) +{ + return modem_syscon_ll_wifibb_44m_clock_is_enabled(ctx->hal->syscon_dev) ? ESP_OK : ESP_FAIL; +} +#endif +#endif + +#if SOC_BT_SUPPORTED || SOC_IEEE802154_SUPPORTED +static void IRAM_ATTR modem_clock_ble_i154_bb_configure(modem_clock_context_t *ctx, bool enable) +{ + modem_syscon_ll_enable_bt_apb_clock(ctx->hal->syscon_dev, enable); + modem_syscon_ll_enable_bt_clock(ctx->hal->syscon_dev, enable); +} + +#if CONFIG_ESP_MODEM_CLOCK_ENABLE_CHECKING +static esp_err_t IRAM_ATTR modem_clock_ble_i154_bb_check_enable(modem_clock_context_t *ctx) +{ + bool all_clock_enabled = true; + all_clock_enabled &= modem_syscon_ll_bt_apb_clock_is_enabled(ctx->hal->syscon_dev); + all_clock_enabled &= modem_syscon_ll_bt_clock_is_enabled(ctx->hal->syscon_dev); + return all_clock_enabled ? ESP_OK : ESP_FAIL; +} +#endif +#endif // SOC_BT_SUPPORTED || SOC_IEEE802154_SUPPORTED + +#if SOC_IEEE802154_SUPPORTED +static void IRAM_ATTR modem_clock_ieee802154_mac_configure(modem_clock_context_t *ctx, bool enable) +{ + modem_syscon_ll_enable_ieee802154_apb_clock(ctx->hal->syscon_dev, enable); + modem_syscon_ll_enable_ieee802154_mac_clock(ctx->hal->syscon_dev, enable); +} + +#if CONFIG_ESP_MODEM_CLOCK_ENABLE_CHECKING +static esp_err_t IRAM_ATTR modem_clock_ieee802154_mac_check_enable(modem_clock_context_t *ctx) +{ + bool all_clock_enabled = true; + all_clock_enabled &= modem_syscon_ll_ieee802154_apb_clock_is_enabled(ctx->hal->syscon_dev); + all_clock_enabled &= modem_syscon_ll_ieee802154_mac_clock_is_enabled(ctx->hal->syscon_dev); + return all_clock_enabled ? ESP_OK : ESP_FAIL; +} +#endif +#endif // SOC_IEEE802154_SUPPORTED + +static void IRAM_ATTR modem_clock_coex_configure(modem_clock_context_t *ctx, bool enable) +{ + modem_lpcon_ll_enable_coex_clock(ctx->hal->lpcon_dev, enable); +} + +static void IRAM_ATTR modem_clock_modem_adc_common_fe_configure(modem_clock_context_t *ctx, bool enable) +{ + modem_clock_hal_enable_modem_common_fe_clock(ctx->hal, enable); +} + +static void IRAM_ATTR modem_clock_modem_private_fe_configure(modem_clock_context_t *ctx, bool enable) +{ + modem_clock_hal_enable_modem_private_fe_clock(ctx->hal, enable); +} + +#if ANA_I2C_MST_CLK_HAS_ROOT_GATING +static void IRAM_ATTR modem_clock_i2c_master_configure(modem_clock_context_t *ctx, bool enable) +{ + if (enable) { + ANALOG_CLOCK_ENABLE(); + } else { + ANALOG_CLOCK_DISABLE(); + } +} +#endif + +static void IRAM_ATTR modem_clock_etm_configure(modem_clock_context_t *ctx, bool enable) +{ + modem_syscon_ll_enable_etm_clock(ctx->hal->syscon_dev, enable); +} + +static void IRAM_ATTR modem_clock_data_dump_configure(modem_clock_context_t *ctx, bool enable) +{ + modem_syscon_ll_enable_data_dump_clock(ctx->hal->syscon_dev, enable); + modem_syscon_ll_enable_data_dump_mux_clock(ctx->hal->syscon_dev, enable); +} + +#if CONFIG_ESP_MODEM_CLOCK_ENABLE_CHECKING +static esp_err_t IRAM_ATTR modem_clock_coex_check_enable(modem_clock_context_t *ctx) +{ + return modem_lpcon_ll_coex_clock_is_enabled(ctx->hal->lpcon_dev) ? ESP_OK : ESP_FAIL; +} + +static esp_err_t IRAM_ATTR modem_clock_modem_adc_common_fe_check_enable(modem_clock_context_t *ctx) +{ + return modem_clock_hal_modem_common_fe_clock_is_enabled(ctx->hal) ? ESP_OK : ESP_FAIL; +} + +static esp_err_t IRAM_ATTR modem_clock_modem_private_fe_check_enable(modem_clock_context_t *ctx) +{ + return modem_clock_hal_modem_private_fe_clock_is_enabled(ctx->hal) ? ESP_OK : ESP_FAIL; +} + +#if ANA_I2C_MST_CLK_HAS_ROOT_GATING +static esp_err_t IRAM_ATTR modem_clock_i2c_master_check_enable(modem_clock_context_t *ctx) +{ + return ANALOG_CLOCK_IS_ENABLED() ? ESP_OK : ESP_FAIL; +} +#endif + +static esp_err_t IRAM_ATTR modem_clock_etm_check_enable(modem_clock_context_t *ctx) +{ + return modem_syscon_ll_etm_clock_is_enabled(ctx->hal->syscon_dev) ? ESP_OK : ESP_FAIL; +} + +static esp_err_t IRAM_ATTR modem_clock_data_dump_check_enable(modem_clock_context_t *ctx) +{ + bool all_clock_enabled = true; + all_clock_enabled &= modem_syscon_ll_data_dump_clock_is_enabled(ctx->hal->syscon_dev); + all_clock_enabled &= modem_syscon_ll_data_dump_mux_clock_is_enabled(ctx->hal->syscon_dev); + return all_clock_enabled ? ESP_OK : ESP_FAIL; +} +#endif + +DRAM_ATTR modem_clock_device_context_t g_modem_clock_dev[MODEM_CLOCK_DEVICE_MAX] = { + [MODEM_CLOCK_MODEM_ADC_COMMON_FE] = { .refs = 0, .with_refcnt = true, .configure = modem_clock_modem_adc_common_fe_configure +#if CONFIG_ESP_MODEM_CLOCK_ENABLE_CHECKING + , .check_enable = modem_clock_modem_adc_common_fe_check_enable +#endif + }, + [MODEM_CLOCK_MODEM_PRIVATE_FE] = { .refs = 0, .with_refcnt = true, .configure = modem_clock_modem_private_fe_configure +#if CONFIG_ESP_MODEM_CLOCK_ENABLE_CHECKING + , .check_enable = modem_clock_modem_private_fe_check_enable +#endif + }, + [MODEM_CLOCK_COEXIST] = { .refs = 0, .with_refcnt = true, .configure = modem_clock_coex_configure +#if CONFIG_ESP_MODEM_CLOCK_ENABLE_CHECKING + , .check_enable = modem_clock_coex_check_enable +#endif + }, +#if ANA_I2C_MST_CLK_HAS_ROOT_GATING +// ANALOG_CLOCK_ENABLE/DISABLE has its own ref_cnt management. + [MODEM_CLOCK_I2C_MASTER] = { .refs = 0, .with_refcnt = false, .configure = modem_clock_i2c_master_configure +#if CONFIG_ESP_MODEM_CLOCK_ENABLE_CHECKING + , .check_enable = modem_clock_i2c_master_check_enable +#endif + }, +#endif +#if SOC_PHY_CALIBRATION_CLOCK_IS_INDEPENDENT + [MODEM_CLOCK_WIFI_APB] = { .refs = 0, .with_refcnt = true, .configure = modem_clock_wifi_apb_configure +#if CONFIG_ESP_MODEM_CLOCK_ENABLE_CHECKING + , .check_enable = modem_clock_wifi_apb_check_enable +#endif + }, + [MODEM_CLOCK_WIFI_BB_44M] = { .refs = 0, .with_refcnt = true, .configure = modem_clock_wifi_bb_44m_configure +#if CONFIG_ESP_MODEM_CLOCK_ENABLE_CHECKING + , .check_enable = modem_clock_wifi_bb_44m_check_enable +#endif + }, +#endif +#if SOC_WIFI_SUPPORTED + [MODEM_CLOCK_WIFI_MAC] = { .refs = 0, .with_refcnt = true, .configure = modem_clock_wifi_mac_configure +#if CONFIG_ESP_MODEM_CLOCK_ENABLE_CHECKING + , .check_enable = modem_clock_wifi_mac_check_enable +#endif + }, + [MODEM_CLOCK_WIFI_BB] = { .refs = 0, .with_refcnt = true, .configure = modem_clock_wifi_bb_configure +#if CONFIG_ESP_MODEM_CLOCK_ENABLE_CHECKING + , .check_enable = modem_clock_wifi_bb_check_enable +#endif + }, +#endif + [MODEM_CLOCK_ETM] = { .refs = 0, .with_refcnt = true, .configure = modem_clock_etm_configure +#if CONFIG_ESP_MODEM_CLOCK_ENABLE_CHECKING + , .check_enable = modem_clock_etm_check_enable +#endif + }, +#if SOC_BT_SUPPORTED + [MODEM_CLOCK_BLE_MAC] = { .refs = 0, .with_refcnt = true, .configure = modem_clock_ble_mac_configure +#if CONFIG_ESP_MODEM_CLOCK_ENABLE_CHECKING + , .check_enable = modem_clock_ble_mac_check_enable +#endif + }, +#endif +#if SOC_IEEE802154_SUPPORTED || SOC_BT_SUPPORTED + [MODEM_CLOCK_BT_I154_COMMON_BB] = { .refs = 0, .with_refcnt = true, .configure = modem_clock_ble_i154_bb_configure +#if CONFIG_ESP_MODEM_CLOCK_ENABLE_CHECKING + , .check_enable = modem_clock_ble_i154_bb_check_enable +#endif + }, +#endif +#if SOC_IEEE802154_SUPPORTED + [MODEM_CLOCK_802154_MAC] = { .refs = 0, .with_refcnt = true, .configure = modem_clock_ieee802154_mac_configure +#if CONFIG_ESP_MODEM_CLOCK_ENABLE_CHECKING + , .check_enable = modem_clock_ieee802154_mac_check_enable +#endif + }, +#endif + [MODEM_CLOCK_DATADUMP] = { .refs = 0, .with_refcnt = true, .configure = modem_clock_data_dump_configure +#if CONFIG_ESP_MODEM_CLOCK_ENABLE_CHECKING + , .check_enable = modem_clock_data_dump_check_enable +#endif + } +}; + +#if SOC_PM_SUPPORT_PMU_MODEM_STATE +const DRAM_ATTR uint8_t g_initial_gating_mode[MODEM_CLOCK_DOMAIN_MAX] = { + [MODEM_CLOCK_DOMAIN_MODEM_APB] = ICG_NOGATING_ACTIVE | ICG_NOGATING_MODEM, + [MODEM_CLOCK_DOMAIN_MODEM_PERIPH] = ICG_NOGATING_ACTIVE, + [MODEM_CLOCK_DOMAIN_WIFI] = ICG_NOGATING_ACTIVE | ICG_NOGATING_MODEM, + [MODEM_CLOCK_DOMAIN_BT] = ICG_NOGATING_ACTIVE, + [MODEM_CLOCK_DOMAIN_MODEM_FE] = ICG_NOGATING_ACTIVE | ICG_NOGATING_MODEM, + [MODEM_CLOCK_DOMAIN_IEEE802154] = ICG_NOGATING_ACTIVE, + [MODEM_CLOCK_DOMAIN_LP_APB] = ICG_NOGATING_ACTIVE | ICG_NOGATING_MODEM, + [MODEM_CLOCK_DOMAIN_I2C_MASTER] = ICG_NOGATING_ACTIVE | ICG_NOGATING_MODEM, + [MODEM_CLOCK_DOMAIN_COEX] = ICG_NOGATING_ACTIVE | ICG_NOGATING_MODEM, + [MODEM_CLOCK_DOMAIN_WIFIPWR] = ICG_NOGATING_ACTIVE | ICG_NOGATING_MODEM, +}; +#endif diff --git a/components/esp_hw_support/port/esp32c6/CMakeLists.txt b/components/esp_hw_support/port/esp32c6/CMakeLists.txt index bf7b225913..73a9c16820 100644 --- a/components/esp_hw_support/port/esp32c6/CMakeLists.txt +++ b/components/esp_hw_support/port/esp32c6/CMakeLists.txt @@ -13,6 +13,9 @@ set(srcs "rtc_clk_init.c" if(NOT non_os_build) list(APPEND srcs "sar_periph_ctrl.c") + if(CONFIG_SOC_MODEM_CLOCK_IS_INDEPENDENT AND CONFIG_SOC_MODEM_CLOCK_SUPPORTED) + list(APPEND srcs "modem_clock_impl.c") + endif() endif() if(NOT BOOTLOADER_BUILD AND CONFIG_ESP_ENABLE_PVT) diff --git a/components/esp_hw_support/port/esp32c6/modem_clock_impl.c b/components/esp_hw_support/port/esp32c6/modem_clock_impl.c new file mode 100644 index 0000000000..bce1cce4fb --- /dev/null +++ b/components/esp_hw_support/port/esp32c6/modem_clock_impl.c @@ -0,0 +1,414 @@ +/* + * SPDX-FileCopyrightText: 2025-2026 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include "sdkconfig.h" +#include "esp_attr.h" +#include "soc/soc_caps.h" +#include "esp_private/esp_modem_clock.h" +#include "esp_private/regi2c_ctrl.h" + +/* Clock dependency definitions */ +#if SOC_PHY_CALIBRATION_CLOCK_IS_INDEPENDENT +#define WIFI_CLOCK_DEPS (BIT(MODEM_CLOCK_WIFI_MAC) | BIT(MODEM_CLOCK_WIFI_APB) | BIT(MODEM_CLOCK_WIFI_BB) | BIT(MODEM_CLOCK_WIFI_BB_44M) | BIT(MODEM_CLOCK_COEXIST)) +#else +#define WIFI_CLOCK_DEPS (BIT(MODEM_CLOCK_WIFI_MAC) | BIT(MODEM_CLOCK_WIFI_BB) | BIT(MODEM_CLOCK_COEXIST)) +#endif +#define BLE_CLOCK_DEPS (BIT(MODEM_CLOCK_BLE_MAC) | BIT(MODEM_CLOCK_BT_I154_COMMON_BB) | BIT(MODEM_CLOCK_ETM) | BIT(MODEM_CLOCK_COEXIST)) +#define IEEE802154_CLOCK_DEPS (BIT(MODEM_CLOCK_802154_MAC) | BIT(MODEM_CLOCK_BT_I154_COMMON_BB) | BIT(MODEM_CLOCK_ETM) | BIT(MODEM_CLOCK_COEXIST)) +#define COEXIST_CLOCK_DEPS (BIT(MODEM_CLOCK_COEXIST)) +#if ANA_I2C_MST_CLK_HAS_ROOT_GATING +#define I2C_ANA_MST_CLOCK_DEPS (BIT(MODEM_CLOCK_I2C_MASTER)) +#else +#define I2C_ANA_MST_CLOCK_DEPS (0) +#endif +#define PHY_CLOCK_DEPS (I2C_ANA_MST_CLOCK_DEPS | BIT(MODEM_CLOCK_MODEM_ADC_COMMON_FE) | BIT(MODEM_CLOCK_MODEM_PRIVATE_FE)) +#define MODEM_ETM_CLOCK_DEPS (BIT(MODEM_CLOCK_ETM)) +#define MODEM_ADC_COMMON_FE_CLOCK_DEPS (BIT(MODEM_CLOCK_MODEM_ADC_COMMON_FE)) +#if SOC_PHY_CALIBRATION_CLOCK_IS_INDEPENDENT +#define PHY_CALIBRATION_WIFI_CLOCK_DEPS (BIT(MODEM_CLOCK_WIFI_APB) | BIT(MODEM_CLOCK_WIFI_BB) | BIT(MODEM_CLOCK_WIFI_BB_44M)) +#define PHY_CALIBRATION_BT_I154_CLOCK_DEPS (BIT(MODEM_CLOCK_WIFI_APB) | BIT(MODEM_CLOCK_WIFI_BB_44M) | BIT(MODEM_CLOCK_BT_I154_COMMON_BB)) +#else +#define PHY_CALIBRATION_WIFI_CLOCK_DEPS (BIT(MODEM_CLOCK_WIFI_BB)) +#define PHY_CALIBRATION_BT_I154_CLOCK_DEPS (BIT(MODEM_CLOCK_BT_I154_COMMON_BB)) +#endif +#ifndef SOC_WIFI_SUPPORTED +#undef PHY_CALIBRATION_WIFI_CLOCK_DEPS +#define PHY_CALIBRATION_WIFI_CLOCK_DEPS 0 +#endif +#if !defined(SOC_BT_SUPPORTED) && !defined(SOC_IEEE802154_SUPPORTED) +#undef PHY_CALIBRATION_BT_I154_CLOCK_DEPS +#define PHY_CALIBRATION_BT_I154_CLOCK_DEPS 0 +#endif +#define PHY_CALIBRATION_CLOCK_DEPS (PHY_CALIBRATION_WIFI_CLOCK_DEPS | PHY_CALIBRATION_BT_I154_CLOCK_DEPS) + +uint32_t modem_clock_get_module_deps(shared_periph_module_t module) +{ + uint32_t deps = 0; + switch (module) { + case PERIPH_ANA_I2C_MASTER_MODULE: deps = I2C_ANA_MST_CLOCK_DEPS; break; + case PERIPH_PHY_MODULE: deps = PHY_CLOCK_DEPS; break; + case PERIPH_MODEM_ADC_COMMON_FE_MODULE: deps = MODEM_ADC_COMMON_FE_CLOCK_DEPS; break; +#if SOC_WIFI_SUPPORTED || SOC_BT_SUPPORTED || SOC_IEEE802154_SUPPORTED + case PERIPH_COEX_MODULE: deps = COEXIST_CLOCK_DEPS; break; +#endif +#if SOC_WIFI_SUPPORTED + case PERIPH_WIFI_MODULE: deps = WIFI_CLOCK_DEPS; break; +#endif +#if SOC_BT_SUPPORTED + case PERIPH_BT_MODULE: deps = BLE_CLOCK_DEPS; break; +#endif + case PERIPH_PHY_CALIBRATION_MODULE: deps = PHY_CALIBRATION_CLOCK_DEPS; break; +#if SOC_IEEE802154_SUPPORTED + case PERIPH_IEEE802154_MODULE: deps = IEEE802154_CLOCK_DEPS; break; +#endif +#if SOC_BT_SUPPORTED || SOC_IEEE802154_SUPPORTED + case PERIPH_MODEM_ETM_MODULE: deps = MODEM_ETM_CLOCK_DEPS; break; +#endif + default: + assert(0); + } + return deps; +} + +#if SOC_WIFI_SUPPORTED +static void IRAM_ATTR modem_clock_wifi_mac_configure(modem_clock_context_t *ctx, bool enable) +{ + if (enable || !(ctx->modem_status & MODEM_STATUS_WIFI_INITED)) { +#if !SOC_PHY_CALIBRATION_CLOCK_IS_INDEPENDENT + modem_syscon_ll_enable_wifi_apb_clock(ctx->hal->syscon_dev, enable); +#endif + modem_syscon_ll_enable_wifi_mac_clock(ctx->hal->syscon_dev, enable); + } +} + +static void IRAM_ATTR modem_clock_wifi_bb_configure(modem_clock_context_t *ctx, bool enable) +{ + if (enable || !(ctx->modem_status & MODEM_STATUS_WIFI_INITED)) { + modem_syscon_ll_clk_wifibb_configure(ctx->hal->syscon_dev, enable); + } +} + +#if CONFIG_ESP_MODEM_CLOCK_ENABLE_CHECKING +static esp_err_t IRAM_ATTR modem_clock_wifi_mac_check_enable(modem_clock_context_t *ctx) +{ + bool all_clock_enabled = true; +#if !SOC_PHY_CALIBRATION_CLOCK_IS_INDEPENDENT + all_clock_enabled &= modem_syscon_ll_wifi_apb_clock_is_enabled(ctx->hal->syscon_dev); +#endif + all_clock_enabled &= modem_syscon_ll_wifi_mac_clock_is_enabled(ctx->hal->syscon_dev); + return all_clock_enabled ? ESP_OK : ESP_FAIL; +} + +static esp_err_t IRAM_ATTR modem_clock_wifi_bb_check_enable(modem_clock_context_t *ctx) +{ + return modem_syscon_ll_wifibb_clock_is_enabled(ctx->hal->syscon_dev) ? ESP_OK : ESP_FAIL; +} +#endif +#endif // SOC_WIFI_SUPPORTED + +#if SOC_BT_SUPPORTED +static void IRAM_ATTR modem_clock_ble_mac_configure(modem_clock_context_t *ctx, bool enable) +{ + modem_syscon_ll_enable_bt_mac_clock(ctx->hal->syscon_dev, enable); + modem_syscon_ll_enable_modem_sec_clock(ctx->hal->syscon_dev, enable); + modem_syscon_ll_enable_ble_timer_clock(ctx->hal->syscon_dev, enable); +} + +#if CONFIG_ESP_MODEM_CLOCK_ENABLE_CHECKING +static esp_err_t IRAM_ATTR modem_clock_ble_mac_check_enable(modem_clock_context_t *ctx) +{ + bool all_clock_enabled = true; + all_clock_enabled &= modem_syscon_ll_bt_mac_clock_is_enabled(ctx->hal->syscon_dev); + all_clock_enabled &= modem_syscon_ll_modem_sec_clock_is_enabled(ctx->hal->syscon_dev); + all_clock_enabled &= modem_syscon_ll_ble_timer_clock_is_enabled(ctx->hal->syscon_dev); + return all_clock_enabled ? ESP_OK : ESP_FAIL; +} +#endif +#endif // SOC_BT_SUPPORTED + +#if SOC_PHY_CALIBRATION_CLOCK_IS_INDEPENDENT +static void IRAM_ATTR modem_clock_wifi_apb_configure(modem_clock_context_t *ctx, bool enable) +{ + if (enable || !(ctx->modem_status & MODEM_STATUS_WIFI_INITED)) { + modem_syscon_ll_enable_wifi_apb_clock(ctx->hal->syscon_dev, enable); + } +} + +static void IRAM_ATTR modem_clock_wifi_bb_44m_configure(modem_clock_context_t *ctx, bool enable) +{ + if (enable || !(ctx->modem_status & MODEM_STATUS_WIFI_INITED)) { + modem_syscon_ll_enable_wifibb_44m_clock(ctx->hal->syscon_dev, enable); + } +} + +#if CONFIG_ESP_MODEM_CLOCK_ENABLE_CHECKING +static esp_err_t IRAM_ATTR modem_clock_wifi_apb_check_enable(modem_clock_context_t *ctx) +{ + return modem_syscon_ll_wifi_apb_clock_is_enabled(ctx->hal->syscon_dev) ? ESP_OK : ESP_FAIL; +} + +static esp_err_t IRAM_ATTR modem_clock_wifi_bb_44m_check_enable(modem_clock_context_t *ctx) +{ + return modem_syscon_ll_wifibb_44m_clock_is_enabled(ctx->hal->syscon_dev) ? ESP_OK : ESP_FAIL; +} +#endif +#endif + +#if SOC_BT_SUPPORTED || SOC_IEEE802154_SUPPORTED +static void IRAM_ATTR modem_clock_ble_i154_bb_configure(modem_clock_context_t *ctx, bool enable) +{ + modem_syscon_ll_enable_bt_apb_clock(ctx->hal->syscon_dev, enable); + modem_syscon_ll_enable_bt_clock(ctx->hal->syscon_dev, enable); +} + +#if CONFIG_ESP_MODEM_CLOCK_ENABLE_CHECKING +static esp_err_t IRAM_ATTR modem_clock_ble_i154_bb_check_enable(modem_clock_context_t *ctx) +{ + bool all_clock_enabled = true; + all_clock_enabled &= modem_syscon_ll_bt_apb_clock_is_enabled(ctx->hal->syscon_dev); + all_clock_enabled &= modem_syscon_ll_bt_clock_is_enabled(ctx->hal->syscon_dev); + return all_clock_enabled ? ESP_OK : ESP_FAIL; +} +#endif +#endif // SOC_BT_SUPPORTED || SOC_IEEE802154_SUPPORTED + +#if SOC_IEEE802154_SUPPORTED +static void IRAM_ATTR modem_clock_ieee802154_mac_configure(modem_clock_context_t *ctx, bool enable) +{ + modem_syscon_ll_enable_ieee802154_apb_clock(ctx->hal->syscon_dev, enable); + modem_syscon_ll_enable_ieee802154_mac_clock(ctx->hal->syscon_dev, enable); +} + +#if CONFIG_ESP_MODEM_CLOCK_ENABLE_CHECKING +static esp_err_t IRAM_ATTR modem_clock_ieee802154_mac_check_enable(modem_clock_context_t *ctx) +{ + bool all_clock_enabled = true; + all_clock_enabled &= modem_syscon_ll_ieee802154_apb_clock_is_enabled(ctx->hal->syscon_dev); + all_clock_enabled &= modem_syscon_ll_ieee802154_mac_clock_is_enabled(ctx->hal->syscon_dev); + return all_clock_enabled ? ESP_OK : ESP_FAIL; +} +#endif +#endif // SOC_IEEE802154_SUPPORTED + +static void IRAM_ATTR modem_clock_coex_configure(modem_clock_context_t *ctx, bool enable) +{ + modem_lpcon_ll_enable_coex_clock(ctx->hal->lpcon_dev, enable); +} + +static void IRAM_ATTR modem_clock_modem_adc_common_fe_configure(modem_clock_context_t *ctx, bool enable) +{ + modem_clock_hal_enable_modem_common_fe_clock(ctx->hal, enable); +} + +static void IRAM_ATTR modem_clock_modem_private_fe_configure(modem_clock_context_t *ctx, bool enable) +{ + modem_clock_hal_enable_modem_private_fe_clock(ctx->hal, enable); +} + +#if ANA_I2C_MST_CLK_HAS_ROOT_GATING +static void IRAM_ATTR modem_clock_i2c_master_configure(modem_clock_context_t *ctx, bool enable) +{ + if (enable) { + ANALOG_CLOCK_ENABLE(); + } else { + ANALOG_CLOCK_DISABLE(); + } +} +#endif + +static void IRAM_ATTR modem_clock_etm_configure(modem_clock_context_t *ctx, bool enable) +{ + modem_syscon_ll_enable_etm_clock(ctx->hal->syscon_dev, enable); +} + +static void IRAM_ATTR modem_clock_data_dump_configure(modem_clock_context_t *ctx, bool enable) +{ + modem_syscon_ll_enable_data_dump_clock(ctx->hal->syscon_dev, enable); + modem_syscon_ll_enable_data_dump_mux_clock(ctx->hal->syscon_dev, enable); +} + +#if CONFIG_ESP_MODEM_CLOCK_ENABLE_CHECKING +static esp_err_t IRAM_ATTR modem_clock_coex_check_enable(modem_clock_context_t *ctx) +{ + return modem_lpcon_ll_coex_clock_is_enabled(ctx->hal->lpcon_dev) ? ESP_OK : ESP_FAIL; +} + +static esp_err_t IRAM_ATTR modem_clock_modem_adc_common_fe_check_enable(modem_clock_context_t *ctx) +{ + return modem_clock_hal_modem_common_fe_clock_is_enabled(ctx->hal) ? ESP_OK : ESP_FAIL; +} + +static esp_err_t IRAM_ATTR modem_clock_modem_private_fe_check_enable(modem_clock_context_t *ctx) +{ + return modem_clock_hal_modem_private_fe_clock_is_enabled(ctx->hal) ? ESP_OK : ESP_FAIL; +} + +#if ANA_I2C_MST_CLK_HAS_ROOT_GATING +static esp_err_t IRAM_ATTR modem_clock_i2c_master_check_enable(modem_clock_context_t *ctx) +{ + return ANALOG_CLOCK_IS_ENABLED() ? ESP_OK : ESP_FAIL; +} +#endif + +static esp_err_t IRAM_ATTR modem_clock_etm_check_enable(modem_clock_context_t *ctx) +{ + return modem_syscon_ll_etm_clock_is_enabled(ctx->hal->syscon_dev) ? ESP_OK : ESP_FAIL; +} + +static esp_err_t IRAM_ATTR modem_clock_data_dump_check_enable(modem_clock_context_t *ctx) +{ + bool all_clock_enabled = true; + all_clock_enabled &= modem_syscon_ll_data_dump_clock_is_enabled(ctx->hal->syscon_dev); + all_clock_enabled &= modem_syscon_ll_data_dump_mux_clock_is_enabled(ctx->hal->syscon_dev); + return all_clock_enabled ? ESP_OK : ESP_FAIL; +} +#endif + +DRAM_ATTR modem_clock_device_context_t g_modem_clock_dev[MODEM_CLOCK_DEVICE_MAX] = { + [MODEM_CLOCK_MODEM_ADC_COMMON_FE] = { .refs = 0, .with_refcnt = true, .configure = modem_clock_modem_adc_common_fe_configure +#if CONFIG_ESP_MODEM_CLOCK_ENABLE_CHECKING + , .check_enable = modem_clock_modem_adc_common_fe_check_enable +#endif + }, + [MODEM_CLOCK_MODEM_PRIVATE_FE] = { .refs = 0, .with_refcnt = true, .configure = modem_clock_modem_private_fe_configure +#if CONFIG_ESP_MODEM_CLOCK_ENABLE_CHECKING + , .check_enable = modem_clock_modem_private_fe_check_enable +#endif + }, + [MODEM_CLOCK_COEXIST] = { .refs = 0, .with_refcnt = true, .configure = modem_clock_coex_configure +#if CONFIG_ESP_MODEM_CLOCK_ENABLE_CHECKING + , .check_enable = modem_clock_coex_check_enable +#endif + }, +#if ANA_I2C_MST_CLK_HAS_ROOT_GATING +// ANALOG_CLOCK_ENABLE/DISABLE has its own ref_cnt management. + [MODEM_CLOCK_I2C_MASTER] = { .refs = 0, .with_refcnt = false, .configure = modem_clock_i2c_master_configure +#if CONFIG_ESP_MODEM_CLOCK_ENABLE_CHECKING + , .check_enable = modem_clock_i2c_master_check_enable +#endif + }, +#endif +#if SOC_PHY_CALIBRATION_CLOCK_IS_INDEPENDENT + [MODEM_CLOCK_WIFI_APB] = { .refs = 0, .with_refcnt = true, .configure = modem_clock_wifi_apb_configure +#if CONFIG_ESP_MODEM_CLOCK_ENABLE_CHECKING + , .check_enable = modem_clock_wifi_apb_check_enable +#endif + }, + [MODEM_CLOCK_WIFI_BB_44M] = { .refs = 0, .with_refcnt = true, .configure = modem_clock_wifi_bb_44m_configure +#if CONFIG_ESP_MODEM_CLOCK_ENABLE_CHECKING + , .check_enable = modem_clock_wifi_bb_44m_check_enable +#endif + }, +#endif +#if SOC_WIFI_SUPPORTED + [MODEM_CLOCK_WIFI_MAC] = { .refs = 0, .with_refcnt = true, .configure = modem_clock_wifi_mac_configure +#if CONFIG_ESP_MODEM_CLOCK_ENABLE_CHECKING + , .check_enable = modem_clock_wifi_mac_check_enable +#endif + }, + [MODEM_CLOCK_WIFI_BB] = { .refs = 0, .with_refcnt = true, .configure = modem_clock_wifi_bb_configure +#if CONFIG_ESP_MODEM_CLOCK_ENABLE_CHECKING + , .check_enable = modem_clock_wifi_bb_check_enable +#endif + }, +#endif + [MODEM_CLOCK_ETM] = { .refs = 0, .with_refcnt = true, .configure = modem_clock_etm_configure +#if CONFIG_ESP_MODEM_CLOCK_ENABLE_CHECKING + , .check_enable = modem_clock_etm_check_enable +#endif + }, +#if SOC_BT_SUPPORTED + [MODEM_CLOCK_BLE_MAC] = { .refs = 0, .with_refcnt = true, .configure = modem_clock_ble_mac_configure +#if CONFIG_ESP_MODEM_CLOCK_ENABLE_CHECKING + , .check_enable = modem_clock_ble_mac_check_enable +#endif + }, +#endif +#if SOC_IEEE802154_SUPPORTED || SOC_BT_SUPPORTED + [MODEM_CLOCK_BT_I154_COMMON_BB] = { .refs = 0, .with_refcnt = true, .configure = modem_clock_ble_i154_bb_configure +#if CONFIG_ESP_MODEM_CLOCK_ENABLE_CHECKING + , .check_enable = modem_clock_ble_i154_bb_check_enable +#endif + }, +#endif +#if SOC_IEEE802154_SUPPORTED + [MODEM_CLOCK_802154_MAC] = { .refs = 0, .with_refcnt = true, .configure = modem_clock_ieee802154_mac_configure +#if CONFIG_ESP_MODEM_CLOCK_ENABLE_CHECKING + , .check_enable = modem_clock_ieee802154_mac_check_enable +#endif + }, +#endif + [MODEM_CLOCK_DATADUMP] = { .refs = 0, .with_refcnt = true, .configure = modem_clock_data_dump_configure +#if CONFIG_ESP_MODEM_CLOCK_ENABLE_CHECKING + , .check_enable = modem_clock_data_dump_check_enable +#endif + } +}; + +#if SOC_PM_SUPPORT_PMU_MODEM_STATE +const DRAM_ATTR uint8_t g_initial_gating_mode[MODEM_CLOCK_DOMAIN_MAX] = { + [MODEM_CLOCK_DOMAIN_MODEM_APB] = ICG_NOGATING_ACTIVE | ICG_NOGATING_MODEM, + [MODEM_CLOCK_DOMAIN_MODEM_PERIPH] = ICG_NOGATING_ACTIVE, + [MODEM_CLOCK_DOMAIN_WIFI] = ICG_NOGATING_ACTIVE | ICG_NOGATING_MODEM, + [MODEM_CLOCK_DOMAIN_BT] = ICG_NOGATING_ACTIVE, + [MODEM_CLOCK_DOMAIN_MODEM_FE] = ICG_NOGATING_ACTIVE | ICG_NOGATING_MODEM, + [MODEM_CLOCK_DOMAIN_IEEE802154] = ICG_NOGATING_ACTIVE, + [MODEM_CLOCK_DOMAIN_LP_APB] = ICG_NOGATING_ACTIVE | ICG_NOGATING_MODEM, + [MODEM_CLOCK_DOMAIN_I2C_MASTER] = ICG_NOGATING_ACTIVE | ICG_NOGATING_MODEM, + [MODEM_CLOCK_DOMAIN_COEX] = ICG_NOGATING_ACTIVE | ICG_NOGATING_MODEM, + [MODEM_CLOCK_DOMAIN_WIFIPWR] = ICG_NOGATING_ACTIVE | ICG_NOGATING_MODEM, +}; +#endif + +#if SOC_BLE_USE_WIFI_PWR_CLK_WORKAROUND +static esp_err_t modem_clock_domain_clk_gate_enable(modem_clock_context_t *ctx, 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; + } + + esp_os_enter_critical_safe(&ctx->lock); + uint32_t code = modem_clock_hal_get_clock_domain_icg_bitmap(ctx->hal, domain); + modem_clock_hal_set_clock_domain_icg_bitmap(ctx->hal, domain, (code & ~BIT(mode))); + esp_os_exit_critical_safe(&ctx->lock); + return ESP_OK; +} + +static esp_err_t modem_clock_domain_clk_gate_disable(modem_clock_context_t *ctx, 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; + } + + esp_os_enter_critical_safe(&ctx->lock); + uint32_t code = modem_clock_hal_get_clock_domain_icg_bitmap(ctx->hal, domain); + modem_clock_hal_set_clock_domain_icg_bitmap(ctx->hal, domain, (code | BIT(mode))); + esp_os_exit_critical_safe(&ctx->lock); + return ESP_OK; +} + +void modem_clock_bt_wifipwr_clk_workaround(modem_clock_context_t *ctx, bool select, modem_clock_lpclk_src_t src) +{ + if (efuse_hal_chip_revision() != 0 && src == MODEM_CLOCK_LPCLK_SRC_MAIN_XTAL) { + if (select) + { + esp_sleep_clock_config(ESP_SLEEP_CLOCK_BT_USE_WIFI_PWR_CLK, ESP_SLEEP_CLOCK_OPTION_UNGATE); + modem_clock_hal_enable_wifipwr_clock(ctx->hal, true); + modem_clock_domain_clk_gate_disable(ctx, MODEM_CLOCK_DOMAIN_WIFIPWR, PMU_HP_ICG_MODEM_CODE_SLEEP); + } else { + esp_sleep_clock_config(ESP_SLEEP_CLOCK_BT_USE_WIFI_PWR_CLK, ESP_SLEEP_CLOCK_OPTION_GATE); + modem_clock_hal_enable_wifipwr_clock(ctx->hal, false); + modem_clock_domain_clk_gate_enable(ctx, MODEM_CLOCK_DOMAIN_WIFIPWR, PMU_HP_ICG_MODEM_CODE_SLEEP); + } + } +} +#endif // #if SOC_BLE_USE_WIFI_PWR_CLK_WORKAROUND diff --git a/components/esp_hw_support/port/esp32c61/CMakeLists.txt b/components/esp_hw_support/port/esp32c61/CMakeLists.txt index 33715e7cb5..73a9c16820 100644 --- a/components/esp_hw_support/port/esp32c61/CMakeLists.txt +++ b/components/esp_hw_support/port/esp32c61/CMakeLists.txt @@ -12,6 +12,10 @@ set(srcs "rtc_clk_init.c" if(NOT non_os_build) list(APPEND srcs "sar_periph_ctrl.c") + + if(CONFIG_SOC_MODEM_CLOCK_IS_INDEPENDENT AND CONFIG_SOC_MODEM_CLOCK_SUPPORTED) + list(APPEND srcs "modem_clock_impl.c") + endif() endif() if(NOT BOOTLOADER_BUILD AND CONFIG_ESP_ENABLE_PVT) diff --git a/components/esp_hw_support/port/esp32c61/modem_clock_impl.c b/components/esp_hw_support/port/esp32c61/modem_clock_impl.c new file mode 100644 index 0000000000..ef303da61a --- /dev/null +++ b/components/esp_hw_support/port/esp32c61/modem_clock_impl.c @@ -0,0 +1,364 @@ +/* + * SPDX-FileCopyrightText: 2025-2026 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include "sdkconfig.h" +#include "esp_attr.h" +#include "soc/soc_caps.h" +#include "esp_private/esp_modem_clock.h" +#include "esp_private/regi2c_ctrl.h" + +/* Clock dependency definitions */ +#if SOC_PHY_CALIBRATION_CLOCK_IS_INDEPENDENT +#define WIFI_CLOCK_DEPS (BIT(MODEM_CLOCK_WIFI_MAC) | BIT(MODEM_CLOCK_WIFI_APB) | BIT(MODEM_CLOCK_WIFI_BB) | BIT(MODEM_CLOCK_WIFI_BB_44M) | BIT(MODEM_CLOCK_COEXIST)) +#else +#define WIFI_CLOCK_DEPS (BIT(MODEM_CLOCK_WIFI_MAC) | BIT(MODEM_CLOCK_WIFI_BB) | BIT(MODEM_CLOCK_COEXIST)) +#endif +#define BLE_CLOCK_DEPS (BIT(MODEM_CLOCK_BLE_MAC) | BIT(MODEM_CLOCK_BT_I154_COMMON_BB) | BIT(MODEM_CLOCK_ETM) | BIT(MODEM_CLOCK_COEXIST)) +#define IEEE802154_CLOCK_DEPS (BIT(MODEM_CLOCK_802154_MAC) | BIT(MODEM_CLOCK_BT_I154_COMMON_BB) | BIT(MODEM_CLOCK_ETM) | BIT(MODEM_CLOCK_COEXIST)) +#define COEXIST_CLOCK_DEPS (BIT(MODEM_CLOCK_COEXIST)) +#if ANA_I2C_MST_CLK_HAS_ROOT_GATING +#define I2C_ANA_MST_CLOCK_DEPS (BIT(MODEM_CLOCK_I2C_MASTER)) +#else +#define I2C_ANA_MST_CLOCK_DEPS (0) +#endif +#define PHY_CLOCK_DEPS (I2C_ANA_MST_CLOCK_DEPS | BIT(MODEM_CLOCK_MODEM_ADC_COMMON_FE) | BIT(MODEM_CLOCK_MODEM_PRIVATE_FE)) +#define MODEM_ETM_CLOCK_DEPS (BIT(MODEM_CLOCK_ETM)) +#define MODEM_ADC_COMMON_FE_CLOCK_DEPS (BIT(MODEM_CLOCK_MODEM_ADC_COMMON_FE)) +#if SOC_PHY_CALIBRATION_CLOCK_IS_INDEPENDENT +#define PHY_CALIBRATION_WIFI_CLOCK_DEPS (BIT(MODEM_CLOCK_WIFI_APB) | BIT(MODEM_CLOCK_WIFI_BB) | BIT(MODEM_CLOCK_WIFI_BB_44M)) +#define PHY_CALIBRATION_BT_I154_CLOCK_DEPS (BIT(MODEM_CLOCK_WIFI_APB) | BIT(MODEM_CLOCK_WIFI_BB_44M) | BIT(MODEM_CLOCK_BT_I154_COMMON_BB)) +#else +#define PHY_CALIBRATION_WIFI_CLOCK_DEPS (BIT(MODEM_CLOCK_WIFI_BB)) +#define PHY_CALIBRATION_BT_I154_CLOCK_DEPS (BIT(MODEM_CLOCK_BT_I154_COMMON_BB)) +#endif +#ifndef SOC_WIFI_SUPPORTED +#undef PHY_CALIBRATION_WIFI_CLOCK_DEPS +#define PHY_CALIBRATION_WIFI_CLOCK_DEPS 0 +#endif +#if !defined(SOC_BT_SUPPORTED) && !defined(SOC_IEEE802154_SUPPORTED) +#undef PHY_CALIBRATION_BT_I154_CLOCK_DEPS +#define PHY_CALIBRATION_BT_I154_CLOCK_DEPS 0 +#endif +#define PHY_CALIBRATION_CLOCK_DEPS (PHY_CALIBRATION_WIFI_CLOCK_DEPS | PHY_CALIBRATION_BT_I154_CLOCK_DEPS) + +uint32_t modem_clock_get_module_deps(shared_periph_module_t module) +{ + uint32_t deps = 0; + switch (module) { + case PERIPH_ANA_I2C_MASTER_MODULE: deps = I2C_ANA_MST_CLOCK_DEPS; break; + case PERIPH_PHY_MODULE: deps = PHY_CLOCK_DEPS; break; + case PERIPH_MODEM_ADC_COMMON_FE_MODULE: deps = MODEM_ADC_COMMON_FE_CLOCK_DEPS; break; +#if SOC_WIFI_SUPPORTED || SOC_BT_SUPPORTED || SOC_IEEE802154_SUPPORTED + case PERIPH_COEX_MODULE: deps = COEXIST_CLOCK_DEPS; break; +#endif +#if SOC_WIFI_SUPPORTED + case PERIPH_WIFI_MODULE: deps = WIFI_CLOCK_DEPS; break; +#endif +#if SOC_BT_SUPPORTED + case PERIPH_BT_MODULE: deps = BLE_CLOCK_DEPS; break; +#endif + case PERIPH_PHY_CALIBRATION_MODULE: deps = PHY_CALIBRATION_CLOCK_DEPS; break; +#if SOC_IEEE802154_SUPPORTED + case PERIPH_IEEE802154_MODULE: deps = IEEE802154_CLOCK_DEPS; break; +#endif +#if SOC_BT_SUPPORTED || SOC_IEEE802154_SUPPORTED + case PERIPH_MODEM_ETM_MODULE: deps = MODEM_ETM_CLOCK_DEPS; break; +#endif + default: + assert(0); + } + return deps; +} + +#if SOC_WIFI_SUPPORTED +static void IRAM_ATTR modem_clock_wifi_mac_configure(modem_clock_context_t *ctx, bool enable) +{ + if (enable || !(ctx->modem_status & MODEM_STATUS_WIFI_INITED)) { +#if !SOC_PHY_CALIBRATION_CLOCK_IS_INDEPENDENT + modem_syscon_ll_enable_wifi_apb_clock(ctx->hal->syscon_dev, enable); +#endif + modem_syscon_ll_enable_wifi_mac_clock(ctx->hal->syscon_dev, enable); + } +} + +static void IRAM_ATTR modem_clock_wifi_bb_configure(modem_clock_context_t *ctx, bool enable) +{ + if (enable || !(ctx->modem_status & MODEM_STATUS_WIFI_INITED)) { + modem_syscon_ll_clk_wifibb_configure(ctx->hal->syscon_dev, enable); + } +} + +#if CONFIG_ESP_MODEM_CLOCK_ENABLE_CHECKING +static esp_err_t IRAM_ATTR modem_clock_wifi_mac_check_enable(modem_clock_context_t *ctx) +{ + bool all_clock_enabled = true; +#if !SOC_PHY_CALIBRATION_CLOCK_IS_INDEPENDENT + all_clock_enabled &= modem_syscon_ll_wifi_apb_clock_is_enabled(ctx->hal->syscon_dev); +#endif + all_clock_enabled &= modem_syscon_ll_wifi_mac_clock_is_enabled(ctx->hal->syscon_dev); + return all_clock_enabled ? ESP_OK : ESP_FAIL; +} + +static esp_err_t IRAM_ATTR modem_clock_wifi_bb_check_enable(modem_clock_context_t *ctx) +{ + return modem_syscon_ll_wifibb_clock_is_enabled(ctx->hal->syscon_dev) ? ESP_OK : ESP_FAIL; +} +#endif +#endif // SOC_WIFI_SUPPORTED + +#if SOC_BT_SUPPORTED +static void IRAM_ATTR modem_clock_ble_mac_configure(modem_clock_context_t *ctx, bool enable) +{ + modem_syscon_ll_enable_bt_mac_clock(ctx->hal->syscon_dev, enable); + modem_syscon_ll_enable_modem_sec_clock(ctx->hal->syscon_dev, enable); + modem_syscon_ll_enable_ble_timer_clock(ctx->hal->syscon_dev, enable); +} + +#if CONFIG_ESP_MODEM_CLOCK_ENABLE_CHECKING +static esp_err_t IRAM_ATTR modem_clock_ble_mac_check_enable(modem_clock_context_t *ctx) +{ + bool all_clock_enabled = true; + all_clock_enabled &= modem_syscon_ll_bt_mac_clock_is_enabled(ctx->hal->syscon_dev); + all_clock_enabled &= modem_syscon_ll_modem_sec_clock_is_enabled(ctx->hal->syscon_dev); + all_clock_enabled &= modem_syscon_ll_ble_timer_clock_is_enabled(ctx->hal->syscon_dev); + return all_clock_enabled ? ESP_OK : ESP_FAIL; +} +#endif +#endif // SOC_BT_SUPPORTED + +#if SOC_PHY_CALIBRATION_CLOCK_IS_INDEPENDENT +static void IRAM_ATTR modem_clock_wifi_apb_configure(modem_clock_context_t *ctx, bool enable) +{ + if (enable || !(ctx->modem_status & MODEM_STATUS_WIFI_INITED)) { + modem_syscon_ll_enable_wifi_apb_clock(ctx->hal->syscon_dev, enable); + } +} + +static void IRAM_ATTR modem_clock_wifi_bb_44m_configure(modem_clock_context_t *ctx, bool enable) +{ + if (enable || !(ctx->modem_status & MODEM_STATUS_WIFI_INITED)) { + modem_syscon_ll_enable_wifibb_44m_clock(ctx->hal->syscon_dev, enable); + } +} + +#if CONFIG_ESP_MODEM_CLOCK_ENABLE_CHECKING +static esp_err_t IRAM_ATTR modem_clock_wifi_apb_check_enable(modem_clock_context_t *ctx) +{ + return modem_syscon_ll_wifi_apb_clock_is_enabled(ctx->hal->syscon_dev) ? ESP_OK : ESP_FAIL; +} + +static esp_err_t IRAM_ATTR modem_clock_wifi_bb_44m_check_enable(modem_clock_context_t *ctx) +{ + return modem_syscon_ll_wifibb_44m_clock_is_enabled(ctx->hal->syscon_dev) ? ESP_OK : ESP_FAIL; +} +#endif +#endif + +#if SOC_BT_SUPPORTED || SOC_IEEE802154_SUPPORTED +static void IRAM_ATTR modem_clock_ble_i154_bb_configure(modem_clock_context_t *ctx, bool enable) +{ + modem_syscon_ll_enable_bt_apb_clock(ctx->hal->syscon_dev, enable); + modem_syscon_ll_enable_bt_clock(ctx->hal->syscon_dev, enable); +} + +#if CONFIG_ESP_MODEM_CLOCK_ENABLE_CHECKING +static esp_err_t IRAM_ATTR modem_clock_ble_i154_bb_check_enable(modem_clock_context_t *ctx) +{ + bool all_clock_enabled = true; + all_clock_enabled &= modem_syscon_ll_bt_apb_clock_is_enabled(ctx->hal->syscon_dev); + all_clock_enabled &= modem_syscon_ll_bt_clock_is_enabled(ctx->hal->syscon_dev); + return all_clock_enabled ? ESP_OK : ESP_FAIL; +} +#endif +#endif // SOC_BT_SUPPORTED || SOC_IEEE802154_SUPPORTED + +#if SOC_IEEE802154_SUPPORTED +static void IRAM_ATTR modem_clock_ieee802154_mac_configure(modem_clock_context_t *ctx, bool enable) +{ + modem_syscon_ll_enable_ieee802154_apb_clock(ctx->hal->syscon_dev, enable); + modem_syscon_ll_enable_ieee802154_mac_clock(ctx->hal->syscon_dev, enable); +} + +#if CONFIG_ESP_MODEM_CLOCK_ENABLE_CHECKING +static esp_err_t IRAM_ATTR modem_clock_ieee802154_mac_check_enable(modem_clock_context_t *ctx) +{ + bool all_clock_enabled = true; + all_clock_enabled &= modem_syscon_ll_ieee802154_apb_clock_is_enabled(ctx->hal->syscon_dev); + all_clock_enabled &= modem_syscon_ll_ieee802154_mac_clock_is_enabled(ctx->hal->syscon_dev); + return all_clock_enabled ? ESP_OK : ESP_FAIL; +} +#endif +#endif // SOC_IEEE802154_SUPPORTED + +static void IRAM_ATTR modem_clock_coex_configure(modem_clock_context_t *ctx, bool enable) +{ + modem_lpcon_ll_enable_coex_clock(ctx->hal->lpcon_dev, enable); +} + +static void IRAM_ATTR modem_clock_modem_adc_common_fe_configure(modem_clock_context_t *ctx, bool enable) +{ + modem_clock_hal_enable_modem_common_fe_clock(ctx->hal, enable); +} + +static void IRAM_ATTR modem_clock_modem_private_fe_configure(modem_clock_context_t *ctx, bool enable) +{ + modem_clock_hal_enable_modem_private_fe_clock(ctx->hal, enable); +} + +#if ANA_I2C_MST_CLK_HAS_ROOT_GATING +static void IRAM_ATTR modem_clock_i2c_master_configure(modem_clock_context_t *ctx, bool enable) +{ + if (enable) { + ANALOG_CLOCK_ENABLE(); + } else { + ANALOG_CLOCK_DISABLE(); + } +} +#endif + +static void IRAM_ATTR modem_clock_etm_configure(modem_clock_context_t *ctx, bool enable) +{ + modem_syscon_ll_enable_etm_clock(ctx->hal->syscon_dev, enable); +} + +static void IRAM_ATTR modem_clock_data_dump_configure(modem_clock_context_t *ctx, bool enable) +{ + modem_syscon_ll_enable_data_dump_clock(ctx->hal->syscon_dev, enable); + modem_syscon_ll_enable_data_dump_mux_clock(ctx->hal->syscon_dev, enable); +} + +#if CONFIG_ESP_MODEM_CLOCK_ENABLE_CHECKING +static esp_err_t IRAM_ATTR modem_clock_coex_check_enable(modem_clock_context_t *ctx) +{ + return modem_lpcon_ll_coex_clock_is_enabled(ctx->hal->lpcon_dev) ? ESP_OK : ESP_FAIL; +} + +static esp_err_t IRAM_ATTR modem_clock_modem_adc_common_fe_check_enable(modem_clock_context_t *ctx) +{ + return modem_clock_hal_modem_common_fe_clock_is_enabled(ctx->hal) ? ESP_OK : ESP_FAIL; +} + +static esp_err_t IRAM_ATTR modem_clock_modem_private_fe_check_enable(modem_clock_context_t *ctx) +{ + return modem_clock_hal_modem_private_fe_clock_is_enabled(ctx->hal) ? ESP_OK : ESP_FAIL; +} + +#if ANA_I2C_MST_CLK_HAS_ROOT_GATING +static esp_err_t IRAM_ATTR modem_clock_i2c_master_check_enable(modem_clock_context_t *ctx) +{ + return ANALOG_CLOCK_IS_ENABLED() ? ESP_OK : ESP_FAIL; +} +#endif + +static esp_err_t IRAM_ATTR modem_clock_etm_check_enable(modem_clock_context_t *ctx) +{ + return modem_syscon_ll_etm_clock_is_enabled(ctx->hal->syscon_dev) ? ESP_OK : ESP_FAIL; +} + +static esp_err_t IRAM_ATTR modem_clock_data_dump_check_enable(modem_clock_context_t *ctx) +{ + bool all_clock_enabled = true; + all_clock_enabled &= modem_syscon_ll_data_dump_clock_is_enabled(ctx->hal->syscon_dev); + all_clock_enabled &= modem_syscon_ll_data_dump_mux_clock_is_enabled(ctx->hal->syscon_dev); + return all_clock_enabled ? ESP_OK : ESP_FAIL; +} +#endif + +DRAM_ATTR modem_clock_device_context_t g_modem_clock_dev[MODEM_CLOCK_DEVICE_MAX] = { + [MODEM_CLOCK_MODEM_ADC_COMMON_FE] = { .refs = 0, .with_refcnt = true, .configure = modem_clock_modem_adc_common_fe_configure +#if CONFIG_ESP_MODEM_CLOCK_ENABLE_CHECKING + , .check_enable = modem_clock_modem_adc_common_fe_check_enable +#endif + }, + [MODEM_CLOCK_MODEM_PRIVATE_FE] = { .refs = 0, .with_refcnt = true, .configure = modem_clock_modem_private_fe_configure +#if CONFIG_ESP_MODEM_CLOCK_ENABLE_CHECKING + , .check_enable = modem_clock_modem_private_fe_check_enable +#endif + }, + [MODEM_CLOCK_COEXIST] = { .refs = 0, .with_refcnt = true, .configure = modem_clock_coex_configure +#if CONFIG_ESP_MODEM_CLOCK_ENABLE_CHECKING + , .check_enable = modem_clock_coex_check_enable +#endif + }, +#if ANA_I2C_MST_CLK_HAS_ROOT_GATING +// ANALOG_CLOCK_ENABLE/DISABLE has its own ref_cnt management. + [MODEM_CLOCK_I2C_MASTER] = { .refs = 0, .with_refcnt = false, .configure = modem_clock_i2c_master_configure +#if CONFIG_ESP_MODEM_CLOCK_ENABLE_CHECKING + , .check_enable = modem_clock_i2c_master_check_enable +#endif + }, +#endif +#if SOC_PHY_CALIBRATION_CLOCK_IS_INDEPENDENT + [MODEM_CLOCK_WIFI_APB] = { .refs = 0, .with_refcnt = true, .configure = modem_clock_wifi_apb_configure +#if CONFIG_ESP_MODEM_CLOCK_ENABLE_CHECKING + , .check_enable = modem_clock_wifi_apb_check_enable +#endif + }, + [MODEM_CLOCK_WIFI_BB_44M] = { .refs = 0, .with_refcnt = true, .configure = modem_clock_wifi_bb_44m_configure +#if CONFIG_ESP_MODEM_CLOCK_ENABLE_CHECKING + , .check_enable = modem_clock_wifi_bb_44m_check_enable +#endif + }, +#endif +#if SOC_WIFI_SUPPORTED + [MODEM_CLOCK_WIFI_MAC] = { .refs = 0, .with_refcnt = true, .configure = modem_clock_wifi_mac_configure +#if CONFIG_ESP_MODEM_CLOCK_ENABLE_CHECKING + , .check_enable = modem_clock_wifi_mac_check_enable +#endif + }, + [MODEM_CLOCK_WIFI_BB] = { .refs = 0, .with_refcnt = true, .configure = modem_clock_wifi_bb_configure +#if CONFIG_ESP_MODEM_CLOCK_ENABLE_CHECKING + , .check_enable = modem_clock_wifi_bb_check_enable +#endif + }, +#endif + [MODEM_CLOCK_ETM] = { .refs = 0, .with_refcnt = true, .configure = modem_clock_etm_configure +#if CONFIG_ESP_MODEM_CLOCK_ENABLE_CHECKING + , .check_enable = modem_clock_etm_check_enable +#endif + }, +#if SOC_BT_SUPPORTED + [MODEM_CLOCK_BLE_MAC] = { .refs = 0, .with_refcnt = true, .configure = modem_clock_ble_mac_configure +#if CONFIG_ESP_MODEM_CLOCK_ENABLE_CHECKING + , .check_enable = modem_clock_ble_mac_check_enable +#endif + }, +#endif +#if SOC_IEEE802154_SUPPORTED || SOC_BT_SUPPORTED + [MODEM_CLOCK_BT_I154_COMMON_BB] = { .refs = 0, .with_refcnt = true, .configure = modem_clock_ble_i154_bb_configure +#if CONFIG_ESP_MODEM_CLOCK_ENABLE_CHECKING + , .check_enable = modem_clock_ble_i154_bb_check_enable +#endif + }, +#endif +#if SOC_IEEE802154_SUPPORTED + [MODEM_CLOCK_802154_MAC] = { .refs = 0, .with_refcnt = true, .configure = modem_clock_ieee802154_mac_configure +#if CONFIG_ESP_MODEM_CLOCK_ENABLE_CHECKING + , .check_enable = modem_clock_ieee802154_mac_check_enable +#endif + }, +#endif + [MODEM_CLOCK_DATADUMP] = { .refs = 0, .with_refcnt = true, .configure = modem_clock_data_dump_configure +#if CONFIG_ESP_MODEM_CLOCK_ENABLE_CHECKING + , .check_enable = modem_clock_data_dump_check_enable +#endif + } +}; + +#if SOC_PM_SUPPORT_PMU_MODEM_STATE +const DRAM_ATTR uint8_t g_initial_gating_mode[MODEM_CLOCK_DOMAIN_MAX] = { + [MODEM_CLOCK_DOMAIN_MODEM_APB] = ICG_NOGATING_ACTIVE | ICG_NOGATING_MODEM, + [MODEM_CLOCK_DOMAIN_MODEM_PERIPH] = ICG_NOGATING_ACTIVE, + [MODEM_CLOCK_DOMAIN_WIFI] = ICG_NOGATING_ACTIVE | ICG_NOGATING_MODEM, + [MODEM_CLOCK_DOMAIN_BT] = ICG_NOGATING_ACTIVE, + [MODEM_CLOCK_DOMAIN_MODEM_FE] = ICG_NOGATING_ACTIVE | ICG_NOGATING_MODEM, + [MODEM_CLOCK_DOMAIN_IEEE802154] = ICG_NOGATING_ACTIVE, + [MODEM_CLOCK_DOMAIN_LP_APB] = ICG_NOGATING_ACTIVE | ICG_NOGATING_MODEM, + [MODEM_CLOCK_DOMAIN_I2C_MASTER] = ICG_NOGATING_ACTIVE | ICG_NOGATING_MODEM, + [MODEM_CLOCK_DOMAIN_COEX] = ICG_NOGATING_ACTIVE | ICG_NOGATING_MODEM, + [MODEM_CLOCK_DOMAIN_WIFIPWR] = ICG_NOGATING_ACTIVE | ICG_NOGATING_MODEM, +}; +#endif diff --git a/components/esp_hw_support/port/esp32h2/CMakeLists.txt b/components/esp_hw_support/port/esp32h2/CMakeLists.txt index 0be7eb5dd9..600aed3ccc 100644 --- a/components/esp_hw_support/port/esp32h2/CMakeLists.txt +++ b/components/esp_hw_support/port/esp32h2/CMakeLists.txt @@ -13,6 +13,10 @@ if(NOT non_os_build) list(APPEND srcs "sar_periph_ctrl.c") endif() +if(CONFIG_SOC_MODEM_CLOCK_IS_INDEPENDENT AND CONFIG_SOC_MODEM_CLOCK_SUPPORTED) + list(APPEND srcs "modem_clock_impl.c") +endif() + add_prefix(srcs "${CMAKE_CURRENT_LIST_DIR}/" "${srcs}") target_sources(${COMPONENT_LIB} PRIVATE "${srcs}") diff --git a/components/esp_hw_support/port/esp32h2/modem_clock_impl.c b/components/esp_hw_support/port/esp32h2/modem_clock_impl.c new file mode 100644 index 0000000000..85a930f434 --- /dev/null +++ b/components/esp_hw_support/port/esp32h2/modem_clock_impl.c @@ -0,0 +1,282 @@ +/* + * SPDX-FileCopyrightText: 2025-2026 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include "sdkconfig.h" +#include "esp_attr.h" +#include "soc/soc_caps.h" +#include "esp_private/esp_modem_clock.h" +#include "esp_private/regi2c_ctrl.h" +#if CONFIG_IDF_TARGET_ESP32H2 +#include "soc/rtc.h" +#endif // CONFIG_IDF_TARGET_ESP32H2 + +/* Clock dependency definitions */ +#define BLE_CLOCK_DEPS (BIT(MODEM_CLOCK_BLE_MAC) | BIT(MODEM_CLOCK_BT_I154_COMMON_BB) | BIT(MODEM_CLOCK_ETM) | BIT(MODEM_CLOCK_COEXIST)) +#define IEEE802154_CLOCK_DEPS (BIT(MODEM_CLOCK_802154_MAC) | BIT(MODEM_CLOCK_BT_I154_COMMON_BB) | BIT(MODEM_CLOCK_ETM) | BIT(MODEM_CLOCK_COEXIST)) +#define COEXIST_CLOCK_DEPS (BIT(MODEM_CLOCK_COEXIST)) +#if ANA_I2C_MST_CLK_HAS_ROOT_GATING +#define I2C_ANA_MST_CLOCK_DEPS (BIT(MODEM_CLOCK_I2C_MASTER)) +#else +#define I2C_ANA_MST_CLOCK_DEPS (0) +#endif +#define PHY_CLOCK_DEPS (I2C_ANA_MST_CLOCK_DEPS | BIT(MODEM_CLOCK_MODEM_ADC_COMMON_FE) | BIT(MODEM_CLOCK_MODEM_PRIVATE_FE)) +#define MODEM_ETM_CLOCK_DEPS (BIT(MODEM_CLOCK_ETM)) +#define MODEM_ADC_COMMON_FE_CLOCK_DEPS (BIT(MODEM_CLOCK_MODEM_ADC_COMMON_FE)) +#if SOC_PHY_CALIBRATION_CLOCK_IS_INDEPENDENT +#define PHY_CALIBRATION_CLOCK_DEPS (BIT(MODEM_CLOCK_WIFI_APB) | BIT(MODEM_CLOCK_WIFI_BB_44M)) +#define PHY_CALIBRATION_WIFI_CLOCK_DEPS (BIT(MODEM_CLOCK_WIFI_APB) | BIT(MODEM_CLOCK_WIFI_BB) | BIT(MODEM_CLOCK_WIFI_BB_44M)) +#define PHY_CALIBRATION_BT_I154_CLOCK_DEPS (BIT(MODEM_CLOCK_WIFI_APB) | BIT(MODEM_CLOCK_WIFI_BB_44M) | BIT(MODEM_CLOCK_BT_I154_COMMON_BB)) +#else +#define PHY_CALIBRATION_WIFI_CLOCK_DEPS (BIT(MODEM_CLOCK_WIFI_BB)) +#define PHY_CALIBRATION_BT_I154_CLOCK_DEPS (BIT(MODEM_CLOCK_BT_I154_COMMON_BB)) +#endif +#ifndef SOC_WIFI_SUPPORTED +#undef PHY_CALIBRATION_WIFI_CLOCK_DEPS +#define PHY_CALIBRATION_WIFI_CLOCK_DEPS 0 +#endif +#if !defined(SOC_BT_SUPPORTED) && !defined(SOC_IEEE802154_SUPPORTED) +#undef PHY_CALIBRATION_BT_I154_CLOCK_DEPS +#define PHY_CALIBRATION_BT_I154_CLOCK_DEPS 0 +#endif +#define PHY_CALIBRATION_CLOCK_DEPS (PHY_CALIBRATION_WIFI_CLOCK_DEPS | PHY_CALIBRATION_BT_I154_CLOCK_DEPS) + +uint32_t modem_clock_get_module_deps(shared_periph_module_t module) +{ + uint32_t deps = 0; + switch (module) { + case PERIPH_ANA_I2C_MASTER_MODULE: deps = I2C_ANA_MST_CLOCK_DEPS; break; + case PERIPH_PHY_MODULE: deps = PHY_CLOCK_DEPS; break; + case PERIPH_MODEM_ADC_COMMON_FE_MODULE: deps = MODEM_ADC_COMMON_FE_CLOCK_DEPS; break; +#if SOC_BT_SUPPORTED || SOC_IEEE802154_SUPPORTED + case PERIPH_COEX_MODULE: deps = COEXIST_CLOCK_DEPS; break; +#endif +#if SOC_BT_SUPPORTED + case PERIPH_BT_MODULE: deps = BLE_CLOCK_DEPS; break; +#endif + case PERIPH_PHY_CALIBRATION_MODULE: deps = PHY_CALIBRATION_CLOCK_DEPS; break; +#if SOC_IEEE802154_SUPPORTED + case PERIPH_IEEE802154_MODULE: deps = IEEE802154_CLOCK_DEPS; break; +#endif +#if SOC_BT_SUPPORTED || SOC_IEEE802154_SUPPORTED + case PERIPH_MODEM_ETM_MODULE: deps = MODEM_ETM_CLOCK_DEPS; break; +#endif + default: + assert(0); + } + return deps; +} + +#if SOC_BT_SUPPORTED +static void IRAM_ATTR modem_clock_ble_mac_configure(modem_clock_context_t *ctx, bool enable) +{ + modem_syscon_ll_enable_bt_mac_clock(ctx->hal->syscon_dev, enable); + modem_syscon_ll_enable_modem_sec_clock(ctx->hal->syscon_dev, enable); + modem_syscon_ll_enable_ble_timer_clock(ctx->hal->syscon_dev, enable); +} + +#if CONFIG_ESP_MODEM_CLOCK_ENABLE_CHECKING +static esp_err_t IRAM_ATTR modem_clock_ble_mac_check_enable(modem_clock_context_t *ctx) +{ + bool all_clock_enabled = true; + all_clock_enabled &= modem_syscon_ll_bt_mac_clock_is_enabled(ctx->hal->syscon_dev); + all_clock_enabled &= modem_syscon_ll_modem_sec_clock_is_enabled(ctx->hal->syscon_dev); + all_clock_enabled &= modem_syscon_ll_ble_timer_clock_is_enabled(ctx->hal->syscon_dev); + return all_clock_enabled ? ESP_OK : ESP_FAIL; +} +#endif +#endif // SOC_BT_SUPPORTED + +#if SOC_BT_SUPPORTED || SOC_IEEE802154_SUPPORTED +static void IRAM_ATTR modem_clock_ble_i154_bb_configure(modem_clock_context_t *ctx, bool enable) +{ + modem_syscon_ll_enable_bt_apb_clock(ctx->hal->syscon_dev, enable); + modem_syscon_ll_enable_bt_clock(ctx->hal->syscon_dev, enable); +} + +#if CONFIG_ESP_MODEM_CLOCK_ENABLE_CHECKING +static esp_err_t IRAM_ATTR modem_clock_ble_i154_bb_check_enable(modem_clock_context_t *ctx) +{ + bool all_clock_enabled = true; + all_clock_enabled &= modem_syscon_ll_bt_apb_clock_is_enabled(ctx->hal->syscon_dev); + all_clock_enabled &= modem_syscon_ll_bt_clock_is_enabled(ctx->hal->syscon_dev); + return all_clock_enabled ? ESP_OK : ESP_FAIL; +} +#endif +#endif // SOC_BT_SUPPORTED || SOC_IEEE802154_SUPPORTED + +#if SOC_IEEE802154_SUPPORTED +static void IRAM_ATTR modem_clock_ieee802154_mac_configure(modem_clock_context_t *ctx, bool enable) +{ + modem_syscon_ll_enable_ieee802154_apb_clock(ctx->hal->syscon_dev, enable); + modem_syscon_ll_enable_ieee802154_mac_clock(ctx->hal->syscon_dev, enable); +} + +#if CONFIG_ESP_MODEM_CLOCK_ENABLE_CHECKING +static esp_err_t IRAM_ATTR modem_clock_ieee802154_mac_check_enable(modem_clock_context_t *ctx) +{ + bool all_clock_enabled = true; + all_clock_enabled &= modem_syscon_ll_ieee802154_apb_clock_is_enabled(ctx->hal->syscon_dev); + all_clock_enabled &= modem_syscon_ll_ieee802154_mac_clock_is_enabled(ctx->hal->syscon_dev); + return all_clock_enabled ? ESP_OK : ESP_FAIL; +} +#endif +#endif // SOC_IEEE802154_SUPPORTED + +static void IRAM_ATTR modem_clock_coex_configure(modem_clock_context_t *ctx, bool enable) +{ + modem_lpcon_ll_enable_coex_clock(ctx->hal->lpcon_dev, enable); +} + +static void IRAM_ATTR modem_clock_modem_adc_common_fe_configure(modem_clock_context_t *ctx, bool enable) +{ + modem_clock_hal_enable_modem_common_fe_clock(ctx->hal, enable); +} + +static void IRAM_ATTR modem_clock_modem_private_fe_configure(modem_clock_context_t *ctx, bool enable) +{ + modem_clock_hal_enable_modem_private_fe_clock(ctx->hal, enable); +} + +#if ANA_I2C_MST_CLK_HAS_ROOT_GATING +static void IRAM_ATTR modem_clock_i2c_master_configure(modem_clock_context_t *ctx, bool enable) +{ + if (enable) { + ANALOG_CLOCK_ENABLE(); + } else { + ANALOG_CLOCK_DISABLE(); + } +} +#endif + +static void IRAM_ATTR modem_clock_etm_configure(modem_clock_context_t *ctx, bool enable) +{ + modem_syscon_ll_enable_etm_clock(ctx->hal->syscon_dev, enable); +} + +static void IRAM_ATTR modem_clock_data_dump_configure(modem_clock_context_t *ctx, bool enable) +{ + modem_syscon_ll_enable_data_dump_clock(ctx->hal->syscon_dev, enable); + modem_syscon_ll_enable_data_dump_mux_clock(ctx->hal->syscon_dev, enable); +} + +#if CONFIG_ESP_MODEM_CLOCK_ENABLE_CHECKING +static esp_err_t IRAM_ATTR modem_clock_coex_check_enable(modem_clock_context_t *ctx) +{ + return modem_lpcon_ll_coex_clock_is_enabled(ctx->hal->lpcon_dev) ? ESP_OK : ESP_FAIL; +} + +static esp_err_t IRAM_ATTR modem_clock_modem_adc_common_fe_check_enable(modem_clock_context_t *ctx) +{ + return modem_clock_hal_modem_common_fe_clock_is_enabled(ctx->hal) ? ESP_OK : ESP_FAIL; +} + +static esp_err_t IRAM_ATTR modem_clock_modem_private_fe_check_enable(modem_clock_context_t *ctx) +{ + return modem_clock_hal_modem_private_fe_clock_is_enabled(ctx->hal) ? ESP_OK : ESP_FAIL; +} + +#if ANA_I2C_MST_CLK_HAS_ROOT_GATING +static esp_err_t IRAM_ATTR modem_clock_i2c_master_check_enable(modem_clock_context_t *ctx) +{ + return ANALOG_CLOCK_IS_ENABLED() ? ESP_OK : ESP_FAIL; +} +#endif + +static esp_err_t IRAM_ATTR modem_clock_etm_check_enable(modem_clock_context_t *ctx) +{ + return modem_syscon_ll_etm_clock_is_enabled(ctx->hal->syscon_dev) ? ESP_OK : ESP_FAIL; +} + +static esp_err_t IRAM_ATTR modem_clock_data_dump_check_enable(modem_clock_context_t *ctx) +{ + bool all_clock_enabled = true; + all_clock_enabled &= modem_syscon_ll_data_dump_clock_is_enabled(ctx->hal->syscon_dev); + all_clock_enabled &= modem_syscon_ll_data_dump_mux_clock_is_enabled(ctx->hal->syscon_dev); + return all_clock_enabled ? ESP_OK : ESP_FAIL; +} +#endif + +DRAM_ATTR modem_clock_device_context_t g_modem_clock_dev[MODEM_CLOCK_DEVICE_MAX] = { + [MODEM_CLOCK_MODEM_ADC_COMMON_FE] = { .refs = 0, .with_refcnt = true, .configure = modem_clock_modem_adc_common_fe_configure +#if CONFIG_ESP_MODEM_CLOCK_ENABLE_CHECKING + , .check_enable = modem_clock_modem_adc_common_fe_check_enable +#endif + }, + [MODEM_CLOCK_MODEM_PRIVATE_FE] = { .refs = 0, .with_refcnt = true, .configure = modem_clock_modem_private_fe_configure +#if CONFIG_ESP_MODEM_CLOCK_ENABLE_CHECKING + , .check_enable = modem_clock_modem_private_fe_check_enable +#endif + }, + [MODEM_CLOCK_COEXIST] = { .refs = 0, .with_refcnt = true, .configure = modem_clock_coex_configure +#if CONFIG_ESP_MODEM_CLOCK_ENABLE_CHECKING + , .check_enable = modem_clock_coex_check_enable +#endif + }, +#if ANA_I2C_MST_CLK_HAS_ROOT_GATING +// ANALOG_CLOCK_ENABLE/DISABLE has its own ref_cnt management. + [MODEM_CLOCK_I2C_MASTER] = { .refs = 0, .with_refcnt = false, .configure = modem_clock_i2c_master_configure +#if CONFIG_ESP_MODEM_CLOCK_ENABLE_CHECKING + , .check_enable = modem_clock_i2c_master_check_enable +#endif + }, +#endif + [MODEM_CLOCK_ETM] = { .refs = 0, .with_refcnt = true, .configure = modem_clock_etm_configure +#if CONFIG_ESP_MODEM_CLOCK_ENABLE_CHECKING + , .check_enable = modem_clock_etm_check_enable +#endif + }, +#if SOC_BT_SUPPORTED + [MODEM_CLOCK_BLE_MAC] = { .refs = 0, .with_refcnt = true, .configure = modem_clock_ble_mac_configure +#if CONFIG_ESP_MODEM_CLOCK_ENABLE_CHECKING + , .check_enable = modem_clock_ble_mac_check_enable +#endif + }, +#endif +#if SOC_IEEE802154_SUPPORTED || SOC_BT_SUPPORTED + [MODEM_CLOCK_BT_I154_COMMON_BB] = { .refs = 0, .with_refcnt = true, .configure = modem_clock_ble_i154_bb_configure +#if CONFIG_ESP_MODEM_CLOCK_ENABLE_CHECKING + , .check_enable = modem_clock_ble_i154_bb_check_enable +#endif + }, +#endif +#if SOC_IEEE802154_SUPPORTED + [MODEM_CLOCK_802154_MAC] = { .refs = 0, .with_refcnt = true, .configure = modem_clock_ieee802154_mac_configure +#if CONFIG_ESP_MODEM_CLOCK_ENABLE_CHECKING + , .check_enable = modem_clock_ieee802154_mac_check_enable +#endif + }, +#endif + [MODEM_CLOCK_DATADUMP] = { .refs = 0, .with_refcnt = true, .configure = modem_clock_data_dump_configure +#if CONFIG_ESP_MODEM_CLOCK_ENABLE_CHECKING + , .check_enable = modem_clock_data_dump_check_enable +#endif + } +}; + +#if CONFIG_IDF_TARGET_ESP32H2 +/* rc32k clock enable status before selecting BLE RTC timer clock source */ +static bool rc_clk_en = true; +void modem_clock_select_ble_rtc_timer_clk_workaround(modem_clock_context_t *ctx, bool enable, modem_clock_lpclk_src_t src) +{ + if (enable) { + bool selected = (src == MODEM_CLOCK_LPCLK_SRC_MAIN_XTAL) || + (src == MODEM_CLOCK_LPCLK_SRC_RC_SLOW); + if (selected) { + rc_clk_en = clk_ll_rc32k_is_enabled(); + if (!rc_clk_en) { + rtc_clk_rc32k_enable(true); + } + modem_clock_hal_select_ble_rtc_timer_lpclk_source(ctx->hal, MODEM_CLOCK_LPCLK_SRC_RC32K); + } + } else { + if (!rc_clk_en) { + extern void r_esp_ble_rtc_ticks_delay(uint32_t ticks); + r_esp_ble_rtc_ticks_delay(2); + rtc_clk_rc32k_enable(false); + } + } +} +#endif // CONFIG_IDF_TARGET_ESP32H2 diff --git a/components/esp_hw_support/port/esp32h21/CMakeLists.txt b/components/esp_hw_support/port/esp32h21/CMakeLists.txt index 9f9db291e3..6b623f2d04 100644 --- a/components/esp_hw_support/port/esp32h21/CMakeLists.txt +++ b/components/esp_hw_support/port/esp32h21/CMakeLists.txt @@ -11,6 +11,10 @@ if(CONFIG_SOC_PMU_SUPPORTED) ) endif() +if(CONFIG_SOC_MODEM_CLOCK_IS_INDEPENDENT AND CONFIG_SOC_MODEM_CLOCK_SUPPORTED) + list(APPEND srcs "modem_clock_impl.c") +endif() + add_prefix(srcs "${CMAKE_CURRENT_LIST_DIR}/" "${srcs}") target_sources(${COMPONENT_LIB} PRIVATE "${srcs}") diff --git a/components/esp_hw_support/port/esp32h21/modem_clock_impl.c b/components/esp_hw_support/port/esp32h21/modem_clock_impl.c new file mode 100644 index 0000000000..232e5a16b6 --- /dev/null +++ b/components/esp_hw_support/port/esp32h21/modem_clock_impl.c @@ -0,0 +1,254 @@ +/* + * SPDX-FileCopyrightText: 2025-2026 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include "sdkconfig.h" +#include "esp_attr.h" +#include "soc/soc_caps.h" +#include "esp_private/esp_modem_clock.h" +#include "esp_private/regi2c_ctrl.h" + +/* Clock dependency definitions */ +#define BLE_CLOCK_DEPS (BIT(MODEM_CLOCK_BLE_MAC) | BIT(MODEM_CLOCK_BT_I154_COMMON_BB) | BIT(MODEM_CLOCK_ETM) | BIT(MODEM_CLOCK_COEXIST)) +#define IEEE802154_CLOCK_DEPS (BIT(MODEM_CLOCK_802154_MAC) | BIT(MODEM_CLOCK_BT_I154_COMMON_BB) | BIT(MODEM_CLOCK_ETM) | BIT(MODEM_CLOCK_COEXIST)) +#define COEXIST_CLOCK_DEPS (BIT(MODEM_CLOCK_COEXIST)) +#if ANA_I2C_MST_CLK_HAS_ROOT_GATING +#define I2C_ANA_MST_CLOCK_DEPS (BIT(MODEM_CLOCK_I2C_MASTER)) +#else +#define I2C_ANA_MST_CLOCK_DEPS (0) +#endif +#define PHY_CLOCK_DEPS (I2C_ANA_MST_CLOCK_DEPS | BIT(MODEM_CLOCK_MODEM_ADC_COMMON_FE) | BIT(MODEM_CLOCK_MODEM_PRIVATE_FE)) +#define MODEM_ETM_CLOCK_DEPS (BIT(MODEM_CLOCK_ETM)) +#define MODEM_ADC_COMMON_FE_CLOCK_DEPS (BIT(MODEM_CLOCK_MODEM_ADC_COMMON_FE)) +#if SOC_PHY_CALIBRATION_CLOCK_IS_INDEPENDENT +#define PHY_CALIBRATION_CLOCK_DEPS (BIT(MODEM_CLOCK_WIFI_APB) | BIT(MODEM_CLOCK_WIFI_BB_44M)) +#define PHY_CALIBRATION_WIFI_CLOCK_DEPS (BIT(MODEM_CLOCK_WIFI_APB) | BIT(MODEM_CLOCK_WIFI_BB) | BIT(MODEM_CLOCK_WIFI_BB_44M)) +#define PHY_CALIBRATION_BT_I154_CLOCK_DEPS (BIT(MODEM_CLOCK_WIFI_APB) | BIT(MODEM_CLOCK_WIFI_BB_44M) | BIT(MODEM_CLOCK_BT_I154_COMMON_BB)) +#else +#define PHY_CALIBRATION_WIFI_CLOCK_DEPS (BIT(MODEM_CLOCK_WIFI_BB)) +#define PHY_CALIBRATION_BT_I154_CLOCK_DEPS (BIT(MODEM_CLOCK_BT_I154_COMMON_BB)) +#endif +#ifndef SOC_WIFI_SUPPORTED +#undef PHY_CALIBRATION_WIFI_CLOCK_DEPS +#define PHY_CALIBRATION_WIFI_CLOCK_DEPS 0 +#endif +#if !defined(SOC_BT_SUPPORTED) && !defined(SOC_IEEE802154_SUPPORTED) +#undef PHY_CALIBRATION_BT_I154_CLOCK_DEPS +#define PHY_CALIBRATION_BT_I154_CLOCK_DEPS 0 +#endif +#define PHY_CALIBRATION_CLOCK_DEPS (PHY_CALIBRATION_WIFI_CLOCK_DEPS | PHY_CALIBRATION_BT_I154_CLOCK_DEPS) + +uint32_t modem_clock_get_module_deps(shared_periph_module_t module) +{ + uint32_t deps = 0; + switch (module) { + case PERIPH_ANA_I2C_MASTER_MODULE: deps = I2C_ANA_MST_CLOCK_DEPS; break; + case PERIPH_PHY_MODULE: deps = PHY_CLOCK_DEPS; break; + case PERIPH_MODEM_ADC_COMMON_FE_MODULE: deps = MODEM_ADC_COMMON_FE_CLOCK_DEPS; break; +#if SOC_BT_SUPPORTED || SOC_IEEE802154_SUPPORTED + case PERIPH_COEX_MODULE: deps = COEXIST_CLOCK_DEPS; break; +#endif +#if SOC_BT_SUPPORTED + case PERIPH_BT_MODULE: deps = BLE_CLOCK_DEPS; break; +#endif + case PERIPH_PHY_CALIBRATION_MODULE: deps = PHY_CALIBRATION_CLOCK_DEPS; break; +#if SOC_IEEE802154_SUPPORTED + case PERIPH_IEEE802154_MODULE: deps = IEEE802154_CLOCK_DEPS; break; +#endif +#if SOC_BT_SUPPORTED || SOC_IEEE802154_SUPPORTED + case PERIPH_MODEM_ETM_MODULE: deps = MODEM_ETM_CLOCK_DEPS; break; +#endif + default: + assert(0); + } + return deps; +} + +#if SOC_BT_SUPPORTED +static void IRAM_ATTR modem_clock_ble_mac_configure(modem_clock_context_t *ctx, bool enable) +{ + modem_syscon_ll_enable_bt_mac_clock(ctx->hal->syscon_dev, enable); + modem_syscon_ll_enable_modem_sec_clock(ctx->hal->syscon_dev, enable); + modem_syscon_ll_enable_ble_timer_clock(ctx->hal->syscon_dev, enable); +} + +#if CONFIG_ESP_MODEM_CLOCK_ENABLE_CHECKING +static esp_err_t IRAM_ATTR modem_clock_ble_mac_check_enable(modem_clock_context_t *ctx) +{ + bool all_clock_enabled = true; + all_clock_enabled &= modem_syscon_ll_bt_mac_clock_is_enabled(ctx->hal->syscon_dev); + all_clock_enabled &= modem_syscon_ll_modem_sec_clock_is_enabled(ctx->hal->syscon_dev); + all_clock_enabled &= modem_syscon_ll_ble_timer_clock_is_enabled(ctx->hal->syscon_dev); + return all_clock_enabled ? ESP_OK : ESP_FAIL; +} +#endif +#endif // SOC_BT_SUPPORTED + +#if SOC_BT_SUPPORTED || SOC_IEEE802154_SUPPORTED +static void IRAM_ATTR modem_clock_ble_i154_bb_configure(modem_clock_context_t *ctx, bool enable) +{ + modem_syscon_ll_enable_bt_apb_clock(ctx->hal->syscon_dev, enable); + modem_syscon_ll_enable_bt_clock(ctx->hal->syscon_dev, enable); +} + +#if CONFIG_ESP_MODEM_CLOCK_ENABLE_CHECKING +static esp_err_t IRAM_ATTR modem_clock_ble_i154_bb_check_enable(modem_clock_context_t *ctx) +{ + bool all_clock_enabled = true; + all_clock_enabled &= modem_syscon_ll_bt_apb_clock_is_enabled(ctx->hal->syscon_dev); + all_clock_enabled &= modem_syscon_ll_bt_clock_is_enabled(ctx->hal->syscon_dev); + return all_clock_enabled ? ESP_OK : ESP_FAIL; +} +#endif +#endif // SOC_BT_SUPPORTED || SOC_IEEE802154_SUPPORTED + +#if SOC_IEEE802154_SUPPORTED +static void IRAM_ATTR modem_clock_ieee802154_mac_configure(modem_clock_context_t *ctx, bool enable) +{ + modem_syscon_ll_enable_ieee802154_apb_clock(ctx->hal->syscon_dev, enable); + modem_syscon_ll_enable_ieee802154_mac_clock(ctx->hal->syscon_dev, enable); +} + +#if CONFIG_ESP_MODEM_CLOCK_ENABLE_CHECKING +static esp_err_t IRAM_ATTR modem_clock_ieee802154_mac_check_enable(modem_clock_context_t *ctx) +{ + bool all_clock_enabled = true; + all_clock_enabled &= modem_syscon_ll_ieee802154_apb_clock_is_enabled(ctx->hal->syscon_dev); + all_clock_enabled &= modem_syscon_ll_ieee802154_mac_clock_is_enabled(ctx->hal->syscon_dev); + return all_clock_enabled ? ESP_OK : ESP_FAIL; +} +#endif +#endif // SOC_IEEE802154_SUPPORTED + +static void IRAM_ATTR modem_clock_coex_configure(modem_clock_context_t *ctx, bool enable) +{ + modem_lpcon_ll_enable_coex_clock(ctx->hal->lpcon_dev, enable); +} + +static void IRAM_ATTR modem_clock_modem_adc_common_fe_configure(modem_clock_context_t *ctx, bool enable) +{ + modem_clock_hal_enable_modem_common_fe_clock(ctx->hal, enable); +} + +static void IRAM_ATTR modem_clock_modem_private_fe_configure(modem_clock_context_t *ctx, bool enable) +{ + modem_clock_hal_enable_modem_private_fe_clock(ctx->hal, enable); +} + +#if ANA_I2C_MST_CLK_HAS_ROOT_GATING +static void IRAM_ATTR modem_clock_i2c_master_configure(modem_clock_context_t *ctx, bool enable) +{ + if (enable) { + ANALOG_CLOCK_ENABLE(); + } else { + ANALOG_CLOCK_DISABLE(); + } +} +#endif + +static void IRAM_ATTR modem_clock_etm_configure(modem_clock_context_t *ctx, bool enable) +{ + modem_syscon_ll_enable_etm_clock(ctx->hal->syscon_dev, enable); +} + +static void IRAM_ATTR modem_clock_data_dump_configure(modem_clock_context_t *ctx, bool enable) +{ + modem_syscon_ll_enable_data_dump_clock(ctx->hal->syscon_dev, enable); + modem_syscon_ll_enable_data_dump_mux_clock(ctx->hal->syscon_dev, enable); +} + +#if CONFIG_ESP_MODEM_CLOCK_ENABLE_CHECKING +static esp_err_t IRAM_ATTR modem_clock_coex_check_enable(modem_clock_context_t *ctx) +{ + return modem_lpcon_ll_coex_clock_is_enabled(ctx->hal->lpcon_dev) ? ESP_OK : ESP_FAIL; +} + +static esp_err_t IRAM_ATTR modem_clock_modem_adc_common_fe_check_enable(modem_clock_context_t *ctx) +{ + return modem_clock_hal_modem_common_fe_clock_is_enabled(ctx->hal) ? ESP_OK : ESP_FAIL; +} + +static esp_err_t IRAM_ATTR modem_clock_modem_private_fe_check_enable(modem_clock_context_t *ctx) +{ + return modem_clock_hal_modem_private_fe_clock_is_enabled(ctx->hal) ? ESP_OK : ESP_FAIL; +} + +#if ANA_I2C_MST_CLK_HAS_ROOT_GATING +static esp_err_t IRAM_ATTR modem_clock_i2c_master_check_enable(modem_clock_context_t *ctx) +{ + return ANALOG_CLOCK_IS_ENABLED() ? ESP_OK : ESP_FAIL; +} +#endif + +static esp_err_t IRAM_ATTR modem_clock_etm_check_enable(modem_clock_context_t *ctx) +{ + return modem_syscon_ll_etm_clock_is_enabled(ctx->hal->syscon_dev) ? ESP_OK : ESP_FAIL; +} + +static esp_err_t IRAM_ATTR modem_clock_data_dump_check_enable(modem_clock_context_t *ctx) +{ + bool all_clock_enabled = true; + all_clock_enabled &= modem_syscon_ll_data_dump_clock_is_enabled(ctx->hal->syscon_dev); + all_clock_enabled &= modem_syscon_ll_data_dump_mux_clock_is_enabled(ctx->hal->syscon_dev); + return all_clock_enabled ? ESP_OK : ESP_FAIL; +} +#endif + +DRAM_ATTR modem_clock_device_context_t g_modem_clock_dev[MODEM_CLOCK_DEVICE_MAX] = { + [MODEM_CLOCK_MODEM_ADC_COMMON_FE] = { .refs = 0, .with_refcnt = true, .configure = modem_clock_modem_adc_common_fe_configure +#if CONFIG_ESP_MODEM_CLOCK_ENABLE_CHECKING + , .check_enable = modem_clock_modem_adc_common_fe_check_enable +#endif + }, + [MODEM_CLOCK_MODEM_PRIVATE_FE] = { .refs = 0, .with_refcnt = true, .configure = modem_clock_modem_private_fe_configure +#if CONFIG_ESP_MODEM_CLOCK_ENABLE_CHECKING + , .check_enable = modem_clock_modem_private_fe_check_enable +#endif + }, + [MODEM_CLOCK_COEXIST] = { .refs = 0, .with_refcnt = true, .configure = modem_clock_coex_configure +#if CONFIG_ESP_MODEM_CLOCK_ENABLE_CHECKING + , .check_enable = modem_clock_coex_check_enable +#endif + }, +#if ANA_I2C_MST_CLK_HAS_ROOT_GATING +// ANALOG_CLOCK_ENABLE/DISABLE has its own ref_cnt management. + [MODEM_CLOCK_I2C_MASTER] = { .refs = 0, .with_refcnt = false, .configure = modem_clock_i2c_master_configure +#if CONFIG_ESP_MODEM_CLOCK_ENABLE_CHECKING + , .check_enable = modem_clock_i2c_master_check_enable +#endif + }, +#endif + [MODEM_CLOCK_ETM] = { .refs = 0, .with_refcnt = true, .configure = modem_clock_etm_configure +#if CONFIG_ESP_MODEM_CLOCK_ENABLE_CHECKING + , .check_enable = modem_clock_etm_check_enable +#endif + }, +#if SOC_BT_SUPPORTED + [MODEM_CLOCK_BLE_MAC] = { .refs = 0, .with_refcnt = true, .configure = modem_clock_ble_mac_configure +#if CONFIG_ESP_MODEM_CLOCK_ENABLE_CHECKING + , .check_enable = modem_clock_ble_mac_check_enable +#endif + }, +#endif +#if SOC_IEEE802154_SUPPORTED || SOC_BT_SUPPORTED + [MODEM_CLOCK_BT_I154_COMMON_BB] = { .refs = 0, .with_refcnt = true, .configure = modem_clock_ble_i154_bb_configure +#if CONFIG_ESP_MODEM_CLOCK_ENABLE_CHECKING + , .check_enable = modem_clock_ble_i154_bb_check_enable +#endif + }, +#endif +#if SOC_IEEE802154_SUPPORTED + [MODEM_CLOCK_802154_MAC] = { .refs = 0, .with_refcnt = true, .configure = modem_clock_ieee802154_mac_configure +#if CONFIG_ESP_MODEM_CLOCK_ENABLE_CHECKING + , .check_enable = modem_clock_ieee802154_mac_check_enable +#endif + }, +#endif + [MODEM_CLOCK_DATADUMP] = { .refs = 0, .with_refcnt = true, .configure = modem_clock_data_dump_configure +#if CONFIG_ESP_MODEM_CLOCK_ENABLE_CHECKING + , .check_enable = modem_clock_data_dump_check_enable +#endif + } +}; diff --git a/components/esp_hw_support/port/esp32h4/CMakeLists.txt b/components/esp_hw_support/port/esp32h4/CMakeLists.txt index 8c824225ec..b9340190d3 100644 --- a/components/esp_hw_support/port/esp32h4/CMakeLists.txt +++ b/components/esp_hw_support/port/esp32h4/CMakeLists.txt @@ -14,6 +14,10 @@ endif() if(NOT BOOTLOADER_BUILD) # list(APPEND srcs "sar_periph_ctrl.c") // TODO: [ESP32H4] IDF-12368 + + if(CONFIG_SOC_MODEM_CLOCK_IS_INDEPENDENT AND CONFIG_SOC_MODEM_CLOCK_SUPPORTED) + list(APPEND srcs "modem_clock_impl.c") + endif() endif() add_prefix(srcs "${CMAKE_CURRENT_LIST_DIR}/" "${srcs}") diff --git a/components/esp_hw_support/port/esp32h4/modem_clock_impl.c b/components/esp_hw_support/port/esp32h4/modem_clock_impl.c new file mode 100644 index 0000000000..40c019c74f --- /dev/null +++ b/components/esp_hw_support/port/esp32h4/modem_clock_impl.c @@ -0,0 +1,271 @@ +/* + * SPDX-FileCopyrightText: 2025-2026 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include "sdkconfig.h" +#include "esp_attr.h" +#include "soc/soc_caps.h" +#include "esp_private/esp_modem_clock.h" +#include "esp_private/regi2c_ctrl.h" + +/* Clock dependency definitions */ +#define BLE_CLOCK_DEPS (BIT(MODEM_CLOCK_BLE_MAC) | BIT(MODEM_CLOCK_BT_I154_COMMON_BB) | BIT(MODEM_CLOCK_ETM) | BIT(MODEM_CLOCK_COEXIST)) +#define IEEE802154_CLOCK_DEPS (BIT(MODEM_CLOCK_802154_MAC) | BIT(MODEM_CLOCK_BT_I154_COMMON_BB) | BIT(MODEM_CLOCK_ETM) | BIT(MODEM_CLOCK_COEXIST)) +#define COEXIST_CLOCK_DEPS (BIT(MODEM_CLOCK_COEXIST)) +#if ANA_I2C_MST_CLK_HAS_ROOT_GATING +#define I2C_ANA_MST_CLOCK_DEPS (BIT(MODEM_CLOCK_I2C_MASTER)) +#else +#define I2C_ANA_MST_CLOCK_DEPS (0) +#endif +#define PHY_CLOCK_DEPS (I2C_ANA_MST_CLOCK_DEPS | BIT(MODEM_CLOCK_MODEM_ADC_COMMON_FE) | BIT(MODEM_CLOCK_MODEM_PRIVATE_FE)) +#define MODEM_ETM_CLOCK_DEPS (BIT(MODEM_CLOCK_ETM)) +#define MODEM_ADC_COMMON_FE_CLOCK_DEPS (BIT(MODEM_CLOCK_MODEM_ADC_COMMON_FE)) +#if SOC_PHY_CALIBRATION_CLOCK_IS_INDEPENDENT +#define PHY_CALIBRATION_CLOCK_DEPS (BIT(MODEM_CLOCK_WIFI_APB) | BIT(MODEM_CLOCK_WIFI_BB_44M)) +#define PHY_CALIBRATION_WIFI_CLOCK_DEPS (BIT(MODEM_CLOCK_WIFI_APB) | BIT(MODEM_CLOCK_WIFI_BB) | BIT(MODEM_CLOCK_WIFI_BB_44M)) +#define PHY_CALIBRATION_BT_I154_CLOCK_DEPS (BIT(MODEM_CLOCK_WIFI_APB) | BIT(MODEM_CLOCK_WIFI_BB_44M) | BIT(MODEM_CLOCK_BT_I154_COMMON_BB)) +#else +#define PHY_CALIBRATION_WIFI_CLOCK_DEPS (BIT(MODEM_CLOCK_WIFI_BB)) +#define PHY_CALIBRATION_BT_I154_CLOCK_DEPS (BIT(MODEM_CLOCK_BT_I154_COMMON_BB)) +#endif +#ifndef SOC_WIFI_SUPPORTED +#undef PHY_CALIBRATION_WIFI_CLOCK_DEPS +#define PHY_CALIBRATION_WIFI_CLOCK_DEPS 0 +#endif +#if !defined(SOC_BT_SUPPORTED) && !defined(SOC_IEEE802154_SUPPORTED) +#undef PHY_CALIBRATION_BT_I154_CLOCK_DEPS +#define PHY_CALIBRATION_BT_I154_CLOCK_DEPS 0 +#endif +#define PHY_CALIBRATION_CLOCK_DEPS (PHY_CALIBRATION_WIFI_CLOCK_DEPS | PHY_CALIBRATION_BT_I154_CLOCK_DEPS) + +uint32_t modem_clock_get_module_deps(shared_periph_module_t module) +{ + uint32_t deps = 0; + switch (module) { + case PERIPH_ANA_I2C_MASTER_MODULE: deps = I2C_ANA_MST_CLOCK_DEPS; break; + case PERIPH_PHY_MODULE: deps = PHY_CLOCK_DEPS; break; + case PERIPH_MODEM_ADC_COMMON_FE_MODULE: deps = MODEM_ADC_COMMON_FE_CLOCK_DEPS; break; +#if SOC_BT_SUPPORTED || SOC_IEEE802154_SUPPORTED + case PERIPH_COEX_MODULE: deps = COEXIST_CLOCK_DEPS; break; +#endif +#if SOC_BT_SUPPORTED + case PERIPH_BT_MODULE: deps = BLE_CLOCK_DEPS; break; +#endif + case PERIPH_PHY_CALIBRATION_MODULE: deps = PHY_CALIBRATION_CLOCK_DEPS; break; +#if SOC_IEEE802154_SUPPORTED + case PERIPH_IEEE802154_MODULE: deps = IEEE802154_CLOCK_DEPS; break; +#endif +#if SOC_BT_SUPPORTED || SOC_IEEE802154_SUPPORTED + case PERIPH_MODEM_ETM_MODULE: deps = MODEM_ETM_CLOCK_DEPS; break; +#endif + default: + assert(0); + } + return deps; +} + +#if SOC_BT_SUPPORTED +static void IRAM_ATTR modem_clock_ble_mac_configure(modem_clock_context_t *ctx, bool enable) +{ + modem_syscon_ll_enable_bt_mac_clock(ctx->hal->syscon_dev, enable); + modem_syscon_ll_enable_modem_sec_clock(ctx->hal->syscon_dev, enable); + modem_syscon_ll_enable_ble_timer_clock(ctx->hal->syscon_dev, enable); +} + +#if CONFIG_ESP_MODEM_CLOCK_ENABLE_CHECKING +static esp_err_t IRAM_ATTR modem_clock_ble_mac_check_enable(modem_clock_context_t *ctx) +{ + bool all_clock_enabled = true; + all_clock_enabled &= modem_syscon_ll_bt_mac_clock_is_enabled(ctx->hal->syscon_dev); + all_clock_enabled &= modem_syscon_ll_modem_sec_clock_is_enabled(ctx->hal->syscon_dev); + all_clock_enabled &= modem_syscon_ll_ble_timer_clock_is_enabled(ctx->hal->syscon_dev); + return all_clock_enabled ? ESP_OK : ESP_FAIL; +} +#endif +#endif // SOC_BT_SUPPORTED + +#if SOC_BT_SUPPORTED || SOC_IEEE802154_SUPPORTED +static void IRAM_ATTR modem_clock_ble_i154_bb_configure(modem_clock_context_t *ctx, bool enable) +{ + modem_syscon_ll_enable_bt_apb_clock(ctx->hal->syscon_dev, enable); + modem_syscon_ll_enable_bt_clock(ctx->hal->syscon_dev, enable); +} + +#if CONFIG_ESP_MODEM_CLOCK_ENABLE_CHECKING +static esp_err_t IRAM_ATTR modem_clock_ble_i154_bb_check_enable(modem_clock_context_t *ctx) +{ + bool all_clock_enabled = true; + all_clock_enabled &= modem_syscon_ll_bt_apb_clock_is_enabled(ctx->hal->syscon_dev); + all_clock_enabled &= modem_syscon_ll_bt_clock_is_enabled(ctx->hal->syscon_dev); + return all_clock_enabled ? ESP_OK : ESP_FAIL; +} +#endif +#endif // SOC_BT_SUPPORTED || SOC_IEEE802154_SUPPORTED + +#if SOC_IEEE802154_SUPPORTED +static void IRAM_ATTR modem_clock_ieee802154_mac_configure(modem_clock_context_t *ctx, bool enable) +{ + modem_syscon_ll_enable_ieee802154_apb_clock(ctx->hal->syscon_dev, enable); + modem_syscon_ll_enable_ieee802154_mac_clock(ctx->hal->syscon_dev, enable); +} + +#if CONFIG_ESP_MODEM_CLOCK_ENABLE_CHECKING +static esp_err_t IRAM_ATTR modem_clock_ieee802154_mac_check_enable(modem_clock_context_t *ctx) +{ + bool all_clock_enabled = true; + all_clock_enabled &= modem_syscon_ll_ieee802154_apb_clock_is_enabled(ctx->hal->syscon_dev); + all_clock_enabled &= modem_syscon_ll_ieee802154_mac_clock_is_enabled(ctx->hal->syscon_dev); + return all_clock_enabled ? ESP_OK : ESP_FAIL; +} +#endif +#endif // SOC_IEEE802154_SUPPORTED + +static void IRAM_ATTR modem_clock_coex_configure(modem_clock_context_t *ctx, bool enable) +{ + modem_lpcon_ll_enable_coex_clock(ctx->hal->lpcon_dev, enable); +} + +static void IRAM_ATTR modem_clock_modem_adc_common_fe_configure(modem_clock_context_t *ctx, bool enable) +{ + modem_clock_hal_enable_modem_common_fe_clock(ctx->hal, enable); +} + +static void IRAM_ATTR modem_clock_modem_private_fe_configure(modem_clock_context_t *ctx, bool enable) +{ + modem_clock_hal_enable_modem_private_fe_clock(ctx->hal, enable); +} + +#if ANA_I2C_MST_CLK_HAS_ROOT_GATING +static void IRAM_ATTR modem_clock_i2c_master_configure(modem_clock_context_t *ctx, bool enable) +{ + if (enable) { + ANALOG_CLOCK_ENABLE(); + } else { + ANALOG_CLOCK_DISABLE(); + } +} +#endif + +static void IRAM_ATTR modem_clock_etm_configure(modem_clock_context_t *ctx, bool enable) +{ + modem_syscon_ll_enable_etm_clock(ctx->hal->syscon_dev, enable); +} + +static void IRAM_ATTR modem_clock_data_dump_configure(modem_clock_context_t *ctx, bool enable) +{ + modem_syscon_ll_enable_data_dump_clock(ctx->hal->syscon_dev, enable); + modem_syscon_ll_enable_data_dump_mux_clock(ctx->hal->syscon_dev, enable); +} + +#if CONFIG_ESP_MODEM_CLOCK_ENABLE_CHECKING +static esp_err_t IRAM_ATTR modem_clock_coex_check_enable(modem_clock_context_t *ctx) +{ + return modem_lpcon_ll_coex_clock_is_enabled(ctx->hal->lpcon_dev) ? ESP_OK : ESP_FAIL; +} + +static esp_err_t IRAM_ATTR modem_clock_modem_adc_common_fe_check_enable(modem_clock_context_t *ctx) +{ + return modem_clock_hal_modem_common_fe_clock_is_enabled(ctx->hal) ? ESP_OK : ESP_FAIL; +} + +static esp_err_t IRAM_ATTR modem_clock_modem_private_fe_check_enable(modem_clock_context_t *ctx) +{ + return modem_clock_hal_modem_private_fe_clock_is_enabled(ctx->hal) ? ESP_OK : ESP_FAIL; +} + +#if ANA_I2C_MST_CLK_HAS_ROOT_GATING +static esp_err_t IRAM_ATTR modem_clock_i2c_master_check_enable(modem_clock_context_t *ctx) +{ + return ANALOG_CLOCK_IS_ENABLED() ? ESP_OK : ESP_FAIL; +} +#endif + +static esp_err_t IRAM_ATTR modem_clock_etm_check_enable(modem_clock_context_t *ctx) +{ + return modem_syscon_ll_etm_clock_is_enabled(ctx->hal->syscon_dev) ? ESP_OK : ESP_FAIL; +} + +static esp_err_t IRAM_ATTR modem_clock_data_dump_check_enable(modem_clock_context_t *ctx) +{ + bool all_clock_enabled = true; + all_clock_enabled &= modem_syscon_ll_data_dump_clock_is_enabled(ctx->hal->syscon_dev); + all_clock_enabled &= modem_syscon_ll_data_dump_mux_clock_is_enabled(ctx->hal->syscon_dev); + return all_clock_enabled ? ESP_OK : ESP_FAIL; +} +#endif + +DRAM_ATTR modem_clock_device_context_t g_modem_clock_dev[MODEM_CLOCK_DEVICE_MAX] = { + [MODEM_CLOCK_MODEM_ADC_COMMON_FE] = { .refs = 0, .with_refcnt = true, .configure = modem_clock_modem_adc_common_fe_configure +#if CONFIG_ESP_MODEM_CLOCK_ENABLE_CHECKING + , .check_enable = modem_clock_modem_adc_common_fe_check_enable +#endif + }, + [MODEM_CLOCK_MODEM_PRIVATE_FE] = { .refs = 0, .with_refcnt = true, .configure = modem_clock_modem_private_fe_configure +#if CONFIG_ESP_MODEM_CLOCK_ENABLE_CHECKING + , .check_enable = modem_clock_modem_private_fe_check_enable +#endif + }, + [MODEM_CLOCK_COEXIST] = { .refs = 0, .with_refcnt = true, .configure = modem_clock_coex_configure +#if CONFIG_ESP_MODEM_CLOCK_ENABLE_CHECKING + , .check_enable = modem_clock_coex_check_enable +#endif + }, +#if ANA_I2C_MST_CLK_HAS_ROOT_GATING +// ANALOG_CLOCK_ENABLE/DISABLE has its own ref_cnt management. + [MODEM_CLOCK_I2C_MASTER] = { .refs = 0, .with_refcnt = false, .configure = modem_clock_i2c_master_configure +#if CONFIG_ESP_MODEM_CLOCK_ENABLE_CHECKING + , .check_enable = modem_clock_i2c_master_check_enable +#endif + }, +#endif + [MODEM_CLOCK_ETM] = { .refs = 0, .with_refcnt = true, .configure = modem_clock_etm_configure +#if CONFIG_ESP_MODEM_CLOCK_ENABLE_CHECKING + , .check_enable = modem_clock_etm_check_enable +#endif + }, +#if SOC_BT_SUPPORTED + [MODEM_CLOCK_BLE_MAC] = { .refs = 0, .with_refcnt = true, .configure = modem_clock_ble_mac_configure +#if CONFIG_ESP_MODEM_CLOCK_ENABLE_CHECKING + , .check_enable = modem_clock_ble_mac_check_enable +#endif + }, +#endif +#if SOC_IEEE802154_SUPPORTED || SOC_BT_SUPPORTED + [MODEM_CLOCK_BT_I154_COMMON_BB] = { .refs = 0, .with_refcnt = true, .configure = modem_clock_ble_i154_bb_configure +#if CONFIG_ESP_MODEM_CLOCK_ENABLE_CHECKING + , .check_enable = modem_clock_ble_i154_bb_check_enable +#endif + }, +#endif +#if SOC_IEEE802154_SUPPORTED + [MODEM_CLOCK_802154_MAC] = { .refs = 0, .with_refcnt = true, .configure = modem_clock_ieee802154_mac_configure +#if CONFIG_ESP_MODEM_CLOCK_ENABLE_CHECKING + , .check_enable = modem_clock_ieee802154_mac_check_enable +#endif + }, +#endif + [MODEM_CLOCK_DATADUMP] = { .refs = 0, .with_refcnt = true, .configure = modem_clock_data_dump_configure +#if CONFIG_ESP_MODEM_CLOCK_ENABLE_CHECKING + , .check_enable = modem_clock_data_dump_check_enable +#endif + } +}; + +#if SOC_PM_SUPPORT_PMU_MODEM_STATE +const DRAM_ATTR uint8_t g_initial_gating_mode[MODEM_CLOCK_DOMAIN_MAX] = { + [MODEM_CLOCK_DOMAIN_MODEM_APB] = ICG_NOGATING_ACTIVE | ICG_NOGATING_MODEM, + [MODEM_CLOCK_DOMAIN_MODEM_PERIPH] = ICG_NOGATING_ACTIVE, +#if SOC_BT_SUPPORTED + [MODEM_CLOCK_DOMAIN_BT] = ICG_NOGATING_ACTIVE, +#endif + [MODEM_CLOCK_DOMAIN_MODEM_FE] = ICG_NOGATING_ACTIVE | ICG_NOGATING_MODEM, +#if SOC_IEEE802154_SUPPORTED + [MODEM_CLOCK_DOMAIN_IEEE802154] = ICG_NOGATING_ACTIVE, +#endif + [MODEM_CLOCK_DOMAIN_LP_APB] = ICG_NOGATING_ACTIVE | ICG_NOGATING_MODEM, + [MODEM_CLOCK_DOMAIN_I2C_MASTER] = ICG_NOGATING_ACTIVE | ICG_NOGATING_MODEM, + [MODEM_CLOCK_DOMAIN_COEX] = ICG_NOGATING_ACTIVE | ICG_NOGATING_MODEM, +}; +#endif diff --git a/components/hal/include/hal/modem_clock_types.h b/components/hal/include/hal/modem_clock_types.h index 71794e4d75..fc4d0bb3ba 100644 --- a/components/hal/include/hal/modem_clock_types.h +++ b/components/hal/include/hal/modem_clock_types.h @@ -6,6 +6,8 @@ #pragma once +#include "soc/soc_caps.h" + #ifdef __cplusplus extern "C" { #endif @@ -13,14 +15,22 @@ extern "C" { typedef enum { MODEM_CLOCK_DOMAIN_MODEM_APB = 0, MODEM_CLOCK_DOMAIN_MODEM_PERIPH, +#if SOC_WIFI_SUPPORTED MODEM_CLOCK_DOMAIN_WIFI, +#endif +#if SOC_BT_SUPPORTED MODEM_CLOCK_DOMAIN_BT, +#endif MODEM_CLOCK_DOMAIN_MODEM_FE, +#if SOC_IEEE802154_SUPPORTED MODEM_CLOCK_DOMAIN_IEEE802154, +#endif MODEM_CLOCK_DOMAIN_LP_APB, MODEM_CLOCK_DOMAIN_I2C_MASTER, MODEM_CLOCK_DOMAIN_COEX, +#if SOC_WIFI_SUPPORTED || SOC_BLE_USE_WIFI_PWR_CLK_WORKAROUND MODEM_CLOCK_DOMAIN_WIFIPWR, +#endif MODEM_CLOCK_DOMAIN_MAX } modem_clock_domain_t;