Skip to content

Commit 113f40a

Browse files
committed
feat(esp_hw_support): support gate PLL div clock source by reference count
1 parent 34f249a commit 113f40a

File tree

12 files changed

+153
-68
lines changed

12 files changed

+153
-68
lines changed

components/esp_hw_support/include/esp_private/esp_clk_tree_common.h

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,9 @@ uint32_t esp_clk_tree_lp_fast_get_freq_hz(esp_clk_tree_src_freq_precision_t prec
7878
/**
7979
* @brief Enable / Disable the clock gate of the clock source
8080
*
81+
* @note The clock enable status is maintained by reference counter and
82+
* its status is not reset after software restart.
83+
*
8184
* @param[in] clk_src Clock source available to modules, in soc_module_clk_t
8285
* @param[in] enable Enable / Disable the clock gate
8386
*
@@ -92,6 +95,13 @@ uint32_t esp_clk_tree_lp_fast_get_freq_hz(esp_clk_tree_src_freq_precision_t prec
9295
*/
9396
esp_err_t esp_clk_tree_enable_src(soc_module_clk_t clk_src, bool enable);
9497

98+
#if SOC_CLOCK_TREE_MANAGEMENT_SUPPORTED
99+
/**
100+
* @brief Set the clock source not in use on the clock tree to the gated state.
101+
*/
102+
void esp_clk_tree_initialize(void);
103+
#endif
104+
95105
#ifdef __cplusplus
96106
}
97107
#endif

components/esp_hw_support/include/esp_private/regi2c_ctrl.h

Lines changed: 19 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,12 +7,17 @@
77
#pragma once
88

99
#include <stdint.h>
10+
#include <stdbool.h>
1011
#include "sdkconfig.h"
1112
#include "esp_rom_regi2c.h"
1213
#include "soc/soc_caps.h"
1314
#include "esp_private/periph_ctrl.h"
1415
#include "hal/regi2c_ctrl_ll.h"
1516

17+
#ifndef BOOTLOADER_BUILD
18+
#include "esp_private/esp_clk_tree_common.h"
19+
#endif
20+
1621
#ifdef __cplusplus
1722
extern "C" {
1823
#endif
@@ -25,22 +30,32 @@ extern "C" {
2530

2631
#else // !BOOTLOADER_BUILD
2732

33+
static inline __attribute__((always_inline)) void ANA_I2C_SRC_CLOCK_ENABLE(bool enable) {
34+
#if SOC_CLK_ANA_I2C_MST_DEPENDS_ON_MODEM_APB
35+
esp_clk_tree_enable_src(SOC_MOD_CLK_MODEM_APB, enable);
36+
#endif
37+
}
38+
2839
#if ANA_I2C_MST_CLK_HAS_ROOT_GATING
2940
// This clock needs to be enabled for regi2c write/read, pll calibaration, PHY, RNG, ADC, etc.
3041
// Use reference count to manage the analog i2c master clock
31-
#define ANALOG_CLOCK_ENABLE() \
42+
#define ANALOG_CLOCK_ENABLE() { \
43+
ANA_I2C_SRC_CLOCK_ENABLE(true); \
3244
PERIPH_RCC_ACQUIRE_ATOMIC(PERIPH_ANA_I2C_MASTER_MODULE, ref_count) { \
3345
if (ref_count == 0) { \
3446
regi2c_ctrl_ll_master_enable_clock(true); \
3547
} \
36-
}
48+
} \
49+
}
3750

38-
#define ANALOG_CLOCK_DISABLE() \
51+
#define ANALOG_CLOCK_DISABLE() { \
3952
PERIPH_RCC_RELEASE_ATOMIC(PERIPH_ANA_I2C_MASTER_MODULE, ref_count) { \
4053
if (ref_count == 0) { \
4154
regi2c_ctrl_ll_master_enable_clock(false); \
4255
} \
43-
}
56+
} \
57+
ANA_I2C_SRC_CLOCK_ENABLE(false); \
58+
}
4459

4560
#else
4661
#define ANALOG_CLOCK_ENABLE()

components/esp_hw_support/linker.lf

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ entries:
1616
if PM_SLP_IRAM_OPT = y:
1717
rtc_clk (noflash)
1818
rtc_time (noflash_text)
19+
esp_clk_tree: esp_clk_tree_enable_src (noflash)
1920
if IDF_TARGET_ESP32 = y:
2021
rtc_clk:rtc_clk_cpu_freq_to_pll_mhz (noflash)
2122
rtc_clk:rtc_clk_cpu_freq_to_xtal (noflash)

components/esp_hw_support/modem_clock.c

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -141,7 +141,7 @@ static void IRAM_ATTR modem_clock_data_dump_configure(modem_clock_context_t *ctx
141141
modem_clock_context_t * __attribute__((weak)) IRAM_ATTR MODEM_CLOCK_instance(void)
142142
{
143143
/* It should be explicitly defined in the internal RAM */
144-
static DRAM_ATTR modem_clock_hal_context_t modem_clock_hal = { .syscon_dev = &MODEM_SYSCON, .lpcon_dev = &MODEM_LPCON };
144+
static DRAM_ATTR modem_clock_hal_context_t modem_clock_hal = { .syscon_dev = NULL, .lpcon_dev = NULL };
145145
static DRAM_ATTR modem_clock_context_t modem_clock_context = {
146146
.hal = &modem_clock_hal, .lock = portMUX_INITIALIZER_UNLOCKED,
147147
.dev = {
@@ -167,6 +167,13 @@ modem_clock_context_t * __attribute__((weak)) IRAM_ATTR MODEM_CLOCK_instance(voi
167167
},
168168
.lpclk_src = { [0 ... PERIPH_MODEM_MODULE_NUM - 1] = MODEM_CLOCK_LPCLK_SRC_INVALID }
169169
};
170+
if (modem_clock_hal.syscon_dev == NULL || modem_clock_hal.lpcon_dev == NULL) {
171+
modem_clock_hal.syscon_dev = &MODEM_SYSCON;
172+
modem_clock_hal.lpcon_dev = &MODEM_LPCON;
173+
#if SOC_CLOCK_TREE_MANAGEMENT_SUPPORTED
174+
esp_clk_tree_enable_src(SOC_MOD_CLK_MODEM_APB, true);
175+
#endif
176+
}
170177
return &modem_clock_context;
171178
}
172179

components/esp_hw_support/port/esp32c5/esp_clk_tree.c

Lines changed: 63 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
*/
66

77
#include <stdint.h>
8+
#include "sdkconfig.h"
89
#include "esp_clk_tree.h"
910
#include "esp_err.h"
1011
#include "esp_check.h"
@@ -68,40 +69,72 @@ uint32_t *freq_value)
6869
return ESP_OK;
6970
}
7071

72+
#define ENUM2ARRAY(clk_src) (clk_src - SOC_MOD_CLK_PLL_F12M)
73+
static __NOINIT_ATTR int16_t s_pll_src_cg_ref_cnt[9] = { 0 };
74+
static bool esp_clk_tree_initialized = false;
75+
76+
void esp_clk_tree_initialize(void)
77+
{
78+
soc_reset_reason_t rst_reason = esp_rom_get_reset_reason(0);
79+
if ((rst_reason == RESET_REASON_CPU0_MWDT0) || (rst_reason == RESET_REASON_CPU0_MWDT1) \
80+
|| (rst_reason == RESET_REASON_CPU0_SW) || (rst_reason == RESET_REASON_CPU0_RTC_WDT) \
81+
|| (rst_reason == RESET_REASON_CPU0_JTAG) || (rst_reason == RESET_REASON_CPU0_LOCKUP)) {
82+
esp_clk_tree_initialized = true;
83+
return;
84+
} else {
85+
bzero(s_pll_src_cg_ref_cnt, sizeof(s_pll_src_cg_ref_cnt));
86+
}
87+
88+
soc_cpu_clk_src_t current_cpu_clk_src = clk_ll_cpu_get_src();
89+
90+
if (current_cpu_clk_src == SOC_CPU_CLK_SRC_PLL_F160M) {
91+
s_pll_src_cg_ref_cnt[ENUM2ARRAY(SOC_MOD_CLK_PLL_F160M)] = 1;
92+
_clk_gate_ll_ref_240m_clk_en(false);
93+
} else if (current_cpu_clk_src == SOC_CPU_CLK_SRC_PLL_F240M) {
94+
s_pll_src_cg_ref_cnt[ENUM2ARRAY(SOC_MOD_CLK_PLL_F240M)] = 1;
95+
_clk_gate_ll_ref_160m_clk_en(false);
96+
}
97+
_clk_gate_ll_ref_120m_clk_en(false);
98+
_clk_gate_ll_ref_80m_clk_en(false);
99+
_clk_gate_ll_ref_60m_clk_en(false);
100+
#if !CONFIG_USJ_ENABLE_USB_SERIAL_JTAG && !CONFIG_ESP_CONSOLE_USB_SERIAL_JTAG_ENABLED
101+
_clk_gate_ll_ref_48m_clk_en(false);
102+
#endif
103+
_clk_gate_ll_ref_40m_clk_en(false);
104+
_clk_gate_ll_ref_20m_clk_en(false);
105+
_clk_gate_ll_ref_12m_clk_en(false);
106+
esp_clk_tree_initialized = true;
107+
}
108+
71109
esp_err_t esp_clk_tree_enable_src(soc_module_clk_t clk_src, bool enable)
72110
{
111+
if (!esp_clk_tree_initialized || (clk_src < SOC_MOD_CLK_PLL_F12M) || (clk_src > SOC_MOD_CLK_PLL_F240M)) {
112+
return ESP_OK;
113+
}
114+
73115
PERIPH_RCC_ATOMIC() {
74-
switch (clk_src) {
75-
case SOC_MOD_CLK_PLL_F12M:
76-
clk_gate_ll_ref_12m_clk_en(enable);
77-
break;
78-
case SOC_MOD_CLK_PLL_F20M:
79-
clk_gate_ll_ref_20m_clk_en(enable);
80-
break;
81-
case SOC_MOD_CLK_PLL_F40M:
82-
clk_gate_ll_ref_40m_clk_en(enable);
83-
break;
84-
case SOC_MOD_CLK_PLL_F48M:
85-
clk_gate_ll_ref_48m_clk_en(enable);
86-
break;
87-
case SOC_MOD_CLK_PLL_F60M:
88-
clk_gate_ll_ref_60m_clk_en(enable);
89-
break;
90-
case SOC_MOD_CLK_PLL_F80M:
91-
clk_gate_ll_ref_80m_clk_en(enable);
92-
break;
93-
case SOC_MOD_CLK_PLL_F120M:
94-
clk_gate_ll_ref_120m_clk_en(enable);
95-
break;
96-
case SOC_MOD_CLK_PLL_F160M:
97-
clk_gate_ll_ref_160m_clk_en(enable);
98-
break;
99-
case SOC_MOD_CLK_PLL_F240M:
100-
clk_gate_ll_ref_240m_clk_en(enable);
101-
break;
102-
default:
103-
break;
116+
if (enable) {
117+
s_pll_src_cg_ref_cnt[ENUM2ARRAY(clk_src)]++;
118+
}
119+
if (s_pll_src_cg_ref_cnt[ENUM2ARRAY(clk_src)] == 1) {
120+
switch (clk_src) {
121+
case SOC_MOD_CLK_PLL_F12M: clk_gate_ll_ref_12m_clk_en(enable); break;
122+
case SOC_MOD_CLK_PLL_F20M: clk_gate_ll_ref_20m_clk_en(enable); break;
123+
case SOC_MOD_CLK_PLL_F40M: clk_gate_ll_ref_40m_clk_en(enable); break;
124+
case SOC_MOD_CLK_PLL_F48M: clk_gate_ll_ref_48m_clk_en(enable); break;
125+
case SOC_MOD_CLK_PLL_F60M: clk_gate_ll_ref_60m_clk_en(enable); break;
126+
case SOC_MOD_CLK_PLL_F80M: clk_gate_ll_ref_80m_clk_en(enable); break;
127+
case SOC_MOD_CLK_PLL_F120M: clk_gate_ll_ref_120m_clk_en(enable); break;
128+
case SOC_MOD_CLK_PLL_F160M: clk_gate_ll_ref_160m_clk_en(enable); break;
129+
case SOC_MOD_CLK_PLL_F240M: clk_gate_ll_ref_240m_clk_en(enable); break;
130+
default: break;
131+
}
132+
}
133+
if (!enable) {
134+
s_pll_src_cg_ref_cnt[ENUM2ARRAY(clk_src)]--;
104135
}
136+
assert(s_pll_src_cg_ref_cnt[ENUM2ARRAY(clk_src)] >= 0);
105137
}
106138
return ESP_OK;
107139
}
140+
#undef ENUM2ARRAY

components/esp_hw_support/port/esp32c5/rtc_clk.c

Lines changed: 34 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -286,37 +286,53 @@ __attribute__((weak)) void rtc_clk_set_cpu_switch_to_pll(int event_id)
286286
{
287287
}
288288

289+
static void rtc_clk_update_pll_state_on_cpu_src_switching_start(soc_cpu_clk_src_t old_src, soc_cpu_clk_src_t new_src)
290+
{
291+
if ((new_src == SOC_CPU_CLK_SRC_PLL_F160M) || (new_src == SOC_CPU_CLK_SRC_PLL_F240M)) {
292+
if (s_cur_pll_freq != CLK_LL_PLL_480M_FREQ_MHZ) {
293+
rtc_clk_bbpll_enable();
294+
rtc_clk_bbpll_configure(rtc_clk_xtal_freq_get(), CLK_LL_PLL_480M_FREQ_MHZ);
295+
}
296+
#ifndef BOOTLOADER_BUILD
297+
esp_clk_tree_enable_src((new_src == SOC_CPU_CLK_SRC_PLL_F240M) ? SOC_MOD_CLK_PLL_F240M : SOC_MOD_CLK_PLL_F160M, true);
298+
#endif
299+
}
300+
}
301+
302+
static void rtc_clk_update_pll_state_on_cpu_switching_end(soc_cpu_clk_src_t old_src, soc_cpu_clk_src_t new_src)
303+
{
304+
if ((old_src == SOC_CPU_CLK_SRC_PLL_F160M) || (old_src == SOC_CPU_CLK_SRC_PLL_F240M)) {
305+
#ifndef BOOTLOADER_BUILD
306+
esp_clk_tree_enable_src((old_src == SOC_CPU_CLK_SRC_PLL_F240M) ? SOC_MOD_CLK_PLL_F240M : SOC_MOD_CLK_PLL_F160M, false);
307+
#endif
308+
if ((new_src != SOC_CPU_CLK_SRC_PLL_F160M) && (new_src != SOC_CPU_CLK_SRC_PLL_F240M) && !s_bbpll_digi_consumers_ref_count) {
309+
// We don't turn off the bbpll if some consumers depend on bbpll
310+
rtc_clk_bbpll_disable();
311+
}
312+
}
313+
}
314+
289315
void rtc_clk_cpu_freq_set_config(const rtc_cpu_freq_config_t *config)
290316
{
291317
soc_cpu_clk_src_t old_cpu_clk_src = clk_ll_cpu_get_src();
318+
if (old_cpu_clk_src != config->source) {
319+
rtc_clk_update_pll_state_on_cpu_src_switching_start(old_cpu_clk_src, config->source);
320+
}
292321
if (config->source == SOC_CPU_CLK_SRC_XTAL) {
293322
rtc_clk_cpu_freq_to_xtal(config->freq_mhz, config->div);
294-
if (((old_cpu_clk_src == SOC_CPU_CLK_SRC_PLL_F160M) || (old_cpu_clk_src == SOC_CPU_CLK_SRC_PLL_F240M)) && !s_bbpll_digi_consumers_ref_count) {
295-
// We don't turn off the bbpll if some consumers depend on bbpll
296-
rtc_clk_bbpll_disable();
297-
}
298323
} else if (config->source == SOC_CPU_CLK_SRC_PLL_F240M) {
299-
if (old_cpu_clk_src != SOC_CPU_CLK_SRC_PLL_F240M && old_cpu_clk_src != SOC_CPU_CLK_SRC_PLL_F160M) {
300-
rtc_clk_set_cpu_switch_to_pll(SLEEP_EVENT_HW_PLL_EN_START);
301-
rtc_clk_bbpll_enable();
302-
rtc_clk_bbpll_configure(rtc_clk_xtal_freq_get(), CLK_LL_PLL_480M_FREQ_MHZ);
303-
}
324+
rtc_clk_set_cpu_switch_to_pll(SLEEP_EVENT_HW_PLL_EN_START);
304325
rtc_clk_cpu_freq_to_pll_240_mhz(config->freq_mhz);
305326
rtc_clk_set_cpu_switch_to_pll(SLEEP_EVENT_HW_PLL_EN_STOP);
306327
} else if (config->source == SOC_CPU_CLK_SRC_PLL_F160M) {
307-
if (old_cpu_clk_src != SOC_CPU_CLK_SRC_PLL_F240M && old_cpu_clk_src != SOC_CPU_CLK_SRC_PLL_F160M) {
308-
rtc_clk_set_cpu_switch_to_pll(SLEEP_EVENT_HW_PLL_EN_START);
309-
rtc_clk_bbpll_enable();
310-
rtc_clk_bbpll_configure(rtc_clk_xtal_freq_get(), CLK_LL_PLL_480M_FREQ_MHZ);
311-
}
328+
rtc_clk_set_cpu_switch_to_pll(SLEEP_EVENT_HW_PLL_EN_START);
312329
rtc_clk_cpu_freq_to_pll_160_mhz(config->freq_mhz);
313330
rtc_clk_set_cpu_switch_to_pll(SLEEP_EVENT_HW_PLL_EN_STOP);
314331
} else if (config->source == SOC_CPU_CLK_SRC_RC_FAST) {
315332
rtc_clk_cpu_freq_to_8m();
316-
if (((old_cpu_clk_src == SOC_CPU_CLK_SRC_PLL_F160M) || (old_cpu_clk_src == SOC_CPU_CLK_SRC_PLL_F240M)) && !s_bbpll_digi_consumers_ref_count) {
317-
// We don't turn off the bbpll if some consumers depend on bbpll
318-
rtc_clk_bbpll_disable();
319-
}
333+
}
334+
if (old_cpu_clk_src != config->source) {
335+
rtc_clk_update_pll_state_on_cpu_switching_end(old_cpu_clk_src, config->source);
320336
}
321337
}
322338

components/esp_hw_support/port/esp32h21/esp_clk_tree.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,5 +54,5 @@ uint32_t *freq_value)
5454
esp_err_t esp_clk_tree_enable_src(soc_module_clk_t clk_src, bool enable)
5555
{
5656
(void)clk_src; (void)enable;
57-
return ESP_ERR_NOT_SUPPORTED;
57+
return ESP_OK;
5858
}

components/esp_system/port/cpu_start.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -707,6 +707,9 @@ void IRAM_ATTR call_start_cpu0(void)
707707
trax_start_trace(TRAX_DOWNCOUNT_WORDS);
708708
#endif // CONFIG_ESP32_TRAX || CONFIG_ESP32S2_TRAX || CONFIG_ESP32S3_TRAX
709709

710+
#if SOC_CLOCK_TREE_MANAGEMENT_SUPPORTED
711+
esp_clk_tree_initialize();
712+
#endif
710713
esp_clk_init();
711714
esp_perip_clk_init();
712715

components/esp_system/port/soc/esp32c5/clk.c

Lines changed: 2 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -239,12 +239,14 @@ __attribute__((weak)) void esp_perip_clk_init(void)
239239
* oscillator (40 MHz) to provide the clock during the sleep process in some
240240
* scenarios), the module needs to switch to the required clock source by
241241
* itself. */
242+
#if CONFIG_ESP_WIFI_ENABLED
242243
soc_rtc_slow_clk_src_t rtc_slow_clk_src = rtc_clk_slow_src_get();
243244
modem_clock_lpclk_src_t modem_lpclk_src = (modem_clock_lpclk_src_t)(
244245
(rtc_slow_clk_src == SOC_RTC_SLOW_CLK_SRC_XTAL32K) ? MODEM_CLOCK_LPCLK_SRC_XTAL32K
245246
: (rtc_slow_clk_src == SOC_RTC_SLOW_CLK_SRC_OSC_SLOW) ? MODEM_CLOCK_LPCLK_SRC_EXT32K
246247
: MODEM_CLOCK_LPCLK_SRC_RC_SLOW);
247248
modem_clock_select_lp_clock_source(PERIPH_WIFI_MODULE, modem_lpclk_src, 0);
249+
#endif
248250

249251
/* On ESP32-C5 ECO1, clearing BIT(31) of PCR_FPGA_DEBUG_REG is used to fix
250252
* the issue where the modem module fails to transmit and receive packets
@@ -329,19 +331,6 @@ __attribute__((weak)) void esp_perip_clk_init(void)
329331
usb_serial_jtag_ll_enable_mem_clock(false);
330332
usb_serial_jtag_ll_set_mem_pd(true);
331333
#endif
332-
333-
if (clk_ll_cpu_get_src() != SOC_CPU_CLK_SRC_PLL_F240M) {
334-
_clk_gate_ll_ref_240m_clk_en(false);
335-
}
336-
if (clk_ll_cpu_get_src() != SOC_CPU_CLK_SRC_PLL_F160M) {
337-
_clk_gate_ll_ref_160m_clk_en(false);
338-
}
339-
_clk_gate_ll_ref_120m_clk_en(false);
340-
_clk_gate_ll_ref_80m_clk_en(false);
341-
_clk_gate_ll_ref_60m_clk_en(false);
342-
_clk_gate_ll_ref_40m_clk_en(false);
343-
_clk_gate_ll_ref_20m_clk_en(false);
344-
_clk_gate_ll_ref_12m_clk_en(false);
345334
}
346335

347336
if ((rst_reason == RESET_REASON_CHIP_POWER_ON) || (rst_reason == RESET_REASON_CHIP_BROWN_OUT) \

components/soc/esp32c5/include/soc/Kconfig.soc_caps.in

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -255,6 +255,10 @@ config SOC_PM_SUPPORTED
255255
bool
256256
default y
257257

258+
config SOC_CLOCK_TREE_MANAGEMENT_SUPPORTED
259+
bool
260+
default y
261+
258262
config SOC_SPIRAM_SUPPORTED
259263
bool
260264
default y
@@ -1671,6 +1675,10 @@ config SOC_RCC_IS_INDEPENDENT
16711675
bool
16721676
default y
16731677

1678+
config SOC_CLK_ANA_I2C_MST_DEPENDS_ON_MODEM_APB
1679+
bool
1680+
default y
1681+
16741682
config SOC_TEMPERATURE_SENSOR_SUPPORT_FAST_RC
16751683
bool
16761684
default y

0 commit comments

Comments
 (0)