diff --git a/components/esp_hw_support/modem_clock.c b/components/esp_hw_support/modem_clock.c index e69f3ca16ef..566b3b89bf0 100644 --- a/components/esp_hw_support/modem_clock.c +++ b/components/esp_hw_support/modem_clock.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2022-2024 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2022-2026 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -50,8 +50,9 @@ typedef struct modem_clock_context { modem_clock_hal_context_t *hal; portMUX_TYPE lock; struct { - int16_t refs; - uint16_t reserved; /* reserved for 4 bytes aligned */ + 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); } dev[MODEM_CLOCK_DEVICE_MAX]; /* the low-power clock source for each module */ @@ -137,23 +138,23 @@ modem_clock_context_t * __attribute__((weak)) IRAM_ATTR MODEM_CLOCK_instance(voi 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, .configure = modem_clock_modem_adc_common_fe_configure }, - [MODEM_CLOCK_MODEM_PRIVATE_FE] = { .refs = 0, .configure = modem_clock_modem_private_fe_configure }, - [MODEM_CLOCK_COEXIST] = { .refs = 0, .configure = modem_clock_coex_configure }, - [MODEM_CLOCK_I2C_MASTER] = { .refs = 0, .configure = modem_clock_i2c_master_configure }, + [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 }, + [MODEM_CLOCK_I2C_MASTER] = { .refs = 0, .with_refcnt = true, .configure = modem_clock_i2c_master_configure }, #if SOC_WIFI_SUPPORTED - [MODEM_CLOCK_WIFI_MAC] = { .refs = 0, .configure = modem_clock_wifi_mac_configure }, - [MODEM_CLOCK_WIFI_BB] = { .refs = 0, .configure = modem_clock_wifi_bb_configure }, + [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, .configure = modem_clock_etm_configure }, + [MODEM_CLOCK_ETM] = { .refs = 0, .with_refcnt = true, .configure = modem_clock_etm_configure }, #if SOC_BT_SUPPORTED - [MODEM_CLOCK_BLE_MAC] = { .refs = 0, .configure = modem_clock_ble_mac_configure }, - [MODEM_CLOCK_BLE_BB] = { .refs = 0, .configure = modem_clock_ble_bb_configure }, + [MODEM_CLOCK_BLE_MAC] = { .refs = 0, .with_refcnt = true, .configure = modem_clock_ble_mac_configure }, + [MODEM_CLOCK_BLE_BB] = { .refs = 0, .with_refcnt = true, .configure = modem_clock_ble_bb_configure }, #endif #if SOC_IEEE802154_SUPPORTED - [MODEM_CLOCK_802154_MAC] = { .refs = 0, .configure = modem_clock_ieee802154_mac_configure }, + [MODEM_CLOCK_802154_MAC] = { .refs = 0, .with_refcnt = true, .configure = modem_clock_ieee802154_mac_configure }, #endif - [MODEM_CLOCK_DATADUMP] = { .refs = 0, .configure = modem_clock_data_dump_configure } + [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 } }; @@ -196,11 +197,14 @@ esp_err_t modem_clock_domain_clk_gate_disable(modem_clock_domain_t domain, pmu_h static void IRAM_ATTR modem_clock_device_enable(modem_clock_context_t *ctx, uint32_t dev_map) { + int16_t refs = 0; portENTER_CRITICAL_SAFE(&ctx->lock); for (int i = 0; dev_map; dev_map >>= 1, i++) { if (dev_map & BIT(0)) { - ctx->dev[i].refs++; - (*ctx->dev[i].configure)(ctx, true); + refs = ctx->dev[i].with_refcnt ? ctx->dev[i].refs++ : refs; + if (refs == 0 || !ctx->dev[i].with_refcnt) { + (*ctx->dev[i].configure)(ctx, true); + } } } portEXIT_CRITICAL_SAFE(&ctx->lock); @@ -212,10 +216,13 @@ static void IRAM_ATTR modem_clock_device_disable(modem_clock_context_t *ctx, uin portENTER_CRITICAL_SAFE(&ctx->lock); for (int i = 0; dev_map; dev_map >>= 1, i++) { if (dev_map & BIT(0)) { - refs = --ctx->dev[i].refs; - if (refs == 0) { + refs = ctx->dev[i].with_refcnt ? --ctx->dev[i].refs : refs; + if (refs == 0 || !ctx->dev[i].with_refcnt) { (*ctx->dev[i].configure)(ctx, false); } + if (ctx->dev[i].with_refcnt) { + assert(refs >= 0); + } } } portEXIT_CRITICAL_SAFE(&ctx->lock);