Skip to content

Commit 6d9fdcf

Browse files
committed
Merge branch 'fix/rmii_ref_ckl' into 'master'
fix(esp_eth): fixed ESP32P4 EMAC REF RMII CLK output mode See merge request espressif/esp-idf!37138
2 parents 23398bd + 83f1ccb commit 6d9fdcf

File tree

12 files changed

+124
-34
lines changed

12 files changed

+124
-34
lines changed

components/esp_eth/src/mac/esp_eth_mac_esp.c

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* SPDX-FileCopyrightText: 2019-2024 Espressif Systems (Shanghai) CO LTD
2+
* SPDX-FileCopyrightText: 2019-2025 Espressif Systems (Shanghai) CO LTD
33
*
44
* SPDX-License-Identifier: Apache-2.0
55
*/
@@ -22,6 +22,7 @@
2222
#endif // CONFIG_IDF_TARGET_ESP32
2323
#include "hal/clk_tree_ll.h"
2424
#include "esp_private/esp_clk.h"
25+
#include "esp_private/esp_clk_tree_common.h"
2526
#include "freertos/FreeRTOS.h"
2627
#include "freertos/task.h"
2728
#include "freertos/semphr.h"
@@ -472,11 +473,13 @@ static esp_err_t emac_config_pll_clock(emac_esp32_t *emac)
472473
}
473474
// Set divider of MPLL clock
474475
if (real_freq > RMII_CLK_HZ) {
475-
int32_t div = real_freq / RMII_CLK_HZ - 1;
476+
uint32_t div = real_freq / RMII_CLK_HZ;
476477
clk_ll_pll_f50m_set_divider(div);
477478
// compute real RMII CLK frequency
478-
real_freq /= div + 1;
479+
real_freq /= div;
479480
}
481+
// Enable 50MHz MPLL derived clock
482+
esp_clk_tree_enable_src(SOC_MOD_CLK_PLL_F50M, true);
480483
#endif
481484
// If the difference of real RMII CLK frequency is not within 50 ppm, i.e. 2500 Hz, the (A/M)PLL is unusable
482485
ESP_RETURN_ON_FALSE(abs((int)real_freq - (int)expt_freq) <= 2500,

components/esp_eth/test_apps/main/Kconfig.projbuild

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,20 @@ menu "esp_eth TEST_APPS Configuration"
5353
default 18
5454
endif
5555

56+
config TARGET_RMII_CLK_OUT
57+
bool "REF RMII CLK output"
58+
default n
59+
60+
if TARGET_RMII_CLK_OUT
61+
config TARGET_RMII_CLK_OUT_GPIO
62+
int "REF RMII CLK Output GPIO"
63+
default 23
64+
65+
config TARGET_RMII_CLK_IN_GPIO
66+
int "REF RMII CLK Input GPIO"
67+
default 32
68+
endif # TARGET_RMII_CLK_OUT
69+
5670
endif # TARGET_USE_INTERNAL_ETHERNET
5771

5872
if TARGET_USE_SPI_ETHERNET

components/esp_eth/test_apps/main/esp_eth_test_common.c

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* SPDX-FileCopyrightText: 2022-2024 Espressif Systems (Shanghai) CO LTD
2+
* SPDX-FileCopyrightText: 2022-2025 Espressif Systems (Shanghai) CO LTD
33
*
44
* SPDX-License-Identifier: Unlicense OR CC0-1.0
55
*/
@@ -39,6 +39,12 @@ esp_eth_mac_t *mac_init(void *vendor_emac_config, eth_mac_config_t *mac_config)
3939
esp32_emac_config.smi_gpio.mdc_num = CONFIG_TARGET_IO_MDC;
4040
esp32_emac_config.smi_gpio.mdio_num = CONFIG_TARGET_IO_MDIO;
4141
#endif // CONFIG_TARGET_USE_DEFAULT_EMAC_CONFIG
42+
#if CONFIG_TARGET_RMII_CLK_OUT
43+
esp32_emac_config.clock_config.rmii.clock_mode = EMAC_CLK_OUT;
44+
esp32_emac_config.clock_config.rmii.clock_gpio = CONFIG_TARGET_RMII_CLK_OUT_GPIO;
45+
esp32_emac_config.clock_config_out_in.rmii.clock_mode = EMAC_CLK_EXT_IN;
46+
esp32_emac_config.clock_config_out_in.rmii.clock_gpio = CONFIG_TARGET_RMII_CLK_IN_GPIO;
47+
#endif // CONFIG_TARGET_TEST_RMII_CLK_OUT
4248
if (vendor_emac_config == NULL) {
4349
vendor_emac_config = &esp32_emac_config;
4450
}

components/esp_eth/test_apps/main/esp_eth_test_esp_emac.c

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* SPDX-FileCopyrightText: 2022-2024 Espressif Systems (Shanghai) CO LTD
2+
* SPDX-FileCopyrightText: 2022-2025 Espressif Systems (Shanghai) CO LTD
33
*
44
* SPDX-License-Identifier: Unlicense OR CC0-1.0
55
*/
@@ -564,3 +564,23 @@ TEST_CASE("internal emac erroneous frames", "[esp_emac]")
564564
vEventGroupDelete(eth_event_group);
565565
vSemaphoreDelete(mutex);
566566
}
567+
568+
TEST_CASE("internal emac ref rmii clk out", "[esp_emac_clk_out]")
569+
{
570+
esp_eth_mac_t *mac = mac_init(NULL, NULL);
571+
TEST_ASSERT_NOT_NULL(mac);
572+
esp_eth_phy_t *phy = phy_init(NULL);
573+
TEST_ASSERT_NOT_NULL(phy);
574+
esp_eth_config_t eth_config = ETH_DEFAULT_CONFIG(mac, phy);
575+
esp_eth_handle_t eth_handle = NULL;
576+
// install Ethernet driver
577+
// This is a simple test and it only verifies the REF RMII output CLK is configured and started, and the internal
578+
// EMAC is clocked by it. It does not verify the whole system functionality. As such, it can be executed on the same
579+
// test boards which are configured to input REF RMII CLK by default with only minor HW modification.
580+
TEST_ESP_OK(esp_eth_driver_install(&eth_config, &eth_handle));
581+
extra_eth_config(eth_handle);
582+
TEST_ESP_OK(esp_eth_driver_uninstall(eth_handle));
583+
TEST_ESP_OK(phy->del(phy));
584+
TEST_ESP_OK(mac->del(mac));
585+
extra_cleanup();
586+
}

components/esp_eth/test_apps/pytest_esp_eth.py

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -315,6 +315,19 @@ def test_esp32p4_emac(dut: IdfDut) -> None:
315315
ethernet_heap_alloc_test(dut)
316316

317317

318+
@pytest.mark.eth_ip101
319+
@pytest.mark.parametrize(
320+
'config',
321+
[
322+
'rmii_clko_esp32p4',
323+
],
324+
indirect=True,
325+
)
326+
@idf_parametrize('target', ['esp32p4'], indirect=['target'])
327+
def test_esp32p4_emac_clko(dut: IdfDut) -> None:
328+
dut.run_all_single_board_cases(group='esp_emac_clk_out')
329+
330+
318331
# ----------- LAN8720 -----------
319332
@pytest.mark.eth_lan8720
320333
@pytest.mark.parametrize(
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
CONFIG_IDF_TARGET="esp32p4"
2+
3+
CONFIG_UNITY_ENABLE_FIXTURE=y
4+
CONFIG_UNITY_ENABLE_IDF_TEST_RUNNER=y
5+
CONFIG_ETH_USE_ESP32_EMAC=y
6+
CONFIG_ESP_TASK_WDT_EN=n
7+
8+
CONFIG_TARGET_USE_INTERNAL_ETHERNET=y
9+
CONFIG_TARGET_ETH_PHY_DEVICE_IP101=y
10+
11+
CONFIG_TARGET_USE_DEFAULT_EMAC_CONFIG=y
12+
13+
CONFIG_TARGET_RMII_CLK_OUT=y
14+
# Test board needs to be modified!
15+
# Connect GPIO23 to GPIO32 via wire.
16+
CONFIG_TARGET_RMII_CLK_OUT_GPIO=23
17+
CONFIG_TARGET_RMII_CLK_IN_GPIO=32

components/esp_hw_support/clk_ctrl_os.c

Lines changed: 23 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* SPDX-FileCopyrightText: 2020-2024 Espressif Systems (Shanghai) CO LTD
2+
* SPDX-FileCopyrightText: 2020-2025 Espressif Systems (Shanghai) CO LTD
33
*
44
* SPDX-License-Identifier: Apache-2.0
55
*/
@@ -23,14 +23,14 @@ static const char *TAG = "clk_ctrl_os";
2323
static portMUX_TYPE periph_spinlock = portMUX_INITIALIZER_UNLOCKED;
2424

2525
static uint8_t s_periph_ref_counts = 0;
26-
static uint32_t s_rc_fast_freq = 0; // Frequency of the RC_FAST clock in Hz
26+
static uint32_t s_rc_fast_freq_hz = 0; // Frequency of the RC_FAST clock in Hz
2727
#if SOC_CLK_APLL_SUPPORTED
2828
// Current APLL frequency, in HZ. Zero if APLL is not enabled.
29-
static uint32_t s_cur_apll_freq = 0;
29+
static uint32_t s_cur_apll_freq_hz = 0;
3030
static int s_apll_ref_cnt = 0;
3131
#endif
3232
#if SOC_CLK_MPLL_SUPPORTED
33-
static uint32_t s_cur_mpll_freq = 0;
33+
static uint32_t s_cur_mpll_freq_hz = 0;
3434
static int s_mpll_ref_cnt = 0;
3535
static esp_ldo_channel_handle_t s_ldo_chan = NULL;
3636
#endif
@@ -41,8 +41,8 @@ bool periph_rtc_dig_clk8m_enable(void)
4141
if (s_periph_ref_counts == 0) {
4242
rtc_dig_clk8m_enable();
4343
#if SOC_CLK_RC_FAST_SUPPORT_CALIBRATION
44-
s_rc_fast_freq = esp_clk_tree_rc_fast_get_freq_hz(ESP_CLK_TREE_SRC_FREQ_PRECISION_EXACT);
45-
if (s_rc_fast_freq == 0) {
44+
s_rc_fast_freq_hz = esp_clk_tree_rc_fast_get_freq_hz(ESP_CLK_TREE_SRC_FREQ_PRECISION_EXACT);
45+
if (s_rc_fast_freq_hz == 0) {
4646
rtc_dig_clk8m_disable();
4747
portEXIT_CRITICAL(&periph_spinlock);
4848
return false;
@@ -60,7 +60,7 @@ uint32_t periph_rtc_dig_clk8m_get_freq(void)
6060
/* Workaround: CLK8M calibration cannot be performed, we can only return its theoretic value */
6161
return SOC_CLK_RC_FAST_FREQ_APPROX;
6262
#else
63-
return s_rc_fast_freq;
63+
return s_rc_fast_freq_hz;
6464
#endif
6565
}
6666

@@ -70,7 +70,7 @@ void periph_rtc_dig_clk8m_disable(void)
7070
assert(s_periph_ref_counts > 0);
7171
s_periph_ref_counts--;
7272
if (s_periph_ref_counts == 0) {
73-
s_rc_fast_freq = 0;
73+
s_rc_fast_freq_hz = 0;
7474
rtc_dig_clk8m_disable();
7575
}
7676
portEXIT_CRITICAL(&periph_spinlock);
@@ -95,35 +95,35 @@ void periph_rtc_apll_release(void)
9595
s_apll_ref_cnt--;
9696
if (s_apll_ref_cnt == 0) {
9797
// If there is no peripheral using APLL, shut down the power
98-
s_cur_apll_freq = 0;
98+
s_cur_apll_freq_hz = 0;
9999
rtc_clk_apll_enable(false);
100100
}
101101
portEXIT_CRITICAL(&periph_spinlock);
102102
}
103103

104-
esp_err_t periph_rtc_apll_freq_set(uint32_t expt_freq, uint32_t *real_freq)
104+
esp_err_t periph_rtc_apll_freq_set(uint32_t expt_freq_hz, uint32_t *real_freq_hz)
105105
{
106106
uint32_t o_div = 0;
107107
uint32_t sdm0 = 0;
108108
uint32_t sdm1 = 0;
109109
uint32_t sdm2 = 0;
110110
// Guarantee 'periph_rtc_apll_acquire' has been called before set apll freq
111111
assert(s_apll_ref_cnt > 0);
112-
uint32_t apll_freq = rtc_clk_apll_coeff_calc(expt_freq, &o_div, &sdm0, &sdm1, &sdm2);
112+
uint32_t apll_freq = rtc_clk_apll_coeff_calc(expt_freq_hz, &o_div, &sdm0, &sdm1, &sdm2);
113113

114114
ESP_RETURN_ON_FALSE(apll_freq, ESP_ERR_INVALID_ARG, TAG, "APLL coefficients calculate failed");
115115
bool need_config = true;
116116
portENTER_CRITICAL(&periph_spinlock);
117117
/* If APLL is not in use or only one peripheral in use, its frequency can be changed as will
118118
* But when more than one peripheral refers APLL, its frequency is not allowed to change once it is set */
119-
if (s_cur_apll_freq == 0 || s_apll_ref_cnt < 2) {
120-
s_cur_apll_freq = apll_freq;
119+
if (s_cur_apll_freq_hz == 0 || s_apll_ref_cnt < 2) {
120+
s_cur_apll_freq_hz = apll_freq;
121121
} else {
122-
apll_freq = s_cur_apll_freq;
122+
apll_freq = s_cur_apll_freq_hz;
123123
need_config = false;
124124
}
125125
portEXIT_CRITICAL(&periph_spinlock);
126-
*real_freq = apll_freq;
126+
*real_freq_hz = apll_freq;
127127

128128
if (need_config) {
129129
ESP_LOGD(TAG, "APLL will working at %"PRIu32" Hz with coefficients [sdm0] %"PRIu32" [sdm1] %"PRIu32" [sdm2] %"PRIu32" [o_div] %"PRIu32"",
@@ -172,35 +172,35 @@ void periph_rtc_mpll_release(void)
172172
s_mpll_ref_cnt--;
173173
if (s_mpll_ref_cnt == 0) {
174174
// If there is no peripheral using MPLL, shut down the power
175-
s_cur_mpll_freq = 0;
175+
s_cur_mpll_freq_hz = 0;
176176
rtc_clk_mpll_disable();
177177
}
178178
portEXIT_CRITICAL(&periph_spinlock);
179179
}
180180

181-
esp_err_t IRAM_ATTR periph_rtc_mpll_freq_set(uint32_t expt_freq, uint32_t *real_freq)
181+
esp_err_t IRAM_ATTR periph_rtc_mpll_freq_set(uint32_t expt_freq_hz, uint32_t *real_freq_hz)
182182
{
183183
esp_err_t ret = ESP_OK;
184184

185185
// Guarantee 'periph_rtc_apll_acquire' has been called before set apll freq
186186
assert(s_mpll_ref_cnt > 0);
187187

188188
portENTER_CRITICAL(&periph_spinlock);
189-
if (s_cur_mpll_freq == expt_freq) {
189+
if (s_cur_mpll_freq_hz == expt_freq_hz) {
190190
goto end;
191191
}
192192
/* If MPLL is not in use or only one peripheral in use, its frequency can be changed as will
193193
* But when more than one peripheral refers MPLL, its frequency is not allowed to change once it is set */
194-
if (s_cur_mpll_freq == 0 || s_mpll_ref_cnt < 2) {
194+
if (s_cur_mpll_freq_hz == 0 || s_mpll_ref_cnt < 2) {
195195
uint32_t xtal_freq_mhz = clk_ll_xtal_load_freq_mhz();
196-
rtc_clk_mpll_configure(xtal_freq_mhz, expt_freq / MHZ);
197-
s_cur_mpll_freq = clk_ll_mpll_get_freq_mhz(xtal_freq_mhz);
196+
rtc_clk_mpll_configure(xtal_freq_mhz, expt_freq_hz / MHZ);
197+
s_cur_mpll_freq_hz = clk_ll_mpll_get_freq_mhz(xtal_freq_mhz) * MHZ;
198198
} else {
199199
ret = ESP_ERR_INVALID_STATE;
200200
}
201201
end:
202-
if (real_freq != NULL) {
203-
*real_freq = s_cur_mpll_freq;
202+
if (real_freq_hz != NULL) {
203+
*real_freq_hz = s_cur_mpll_freq_hz;
204204
}
205205
portEXIT_CRITICAL(&periph_spinlock);
206206
return ret;

components/esp_hw_support/include/clk_ctrl_os.h

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* SPDX-FileCopyrightText: 2020-2024 Espressif Systems (Shanghai) CO LTD
2+
* SPDX-FileCopyrightText: 2020-2025 Espressif Systems (Shanghai) CO LTD
33
*
44
* SPDX-License-Identifier: Apache-2.0
55
*/
@@ -67,9 +67,9 @@ void periph_rtc_apll_release(void);
6767
* @return
6868
* - ESP_OK: APLL frequency set success
6969
* - ESP_ERR_INVALID_ARG: The input expt_freq is out of APLL support range
70-
* - ESP_ERR_INVALID_STATE: APLL is refered by more than one peripherals, not allowed to change its frequency now
70+
* - ESP_ERR_INVALID_STATE: APLL is referred by more than one peripherals, not allowed to change its frequency now
7171
*/
72-
esp_err_t periph_rtc_apll_freq_set(uint32_t expt_freq, uint32_t *real_freq);
72+
esp_err_t periph_rtc_apll_freq_set(uint32_t expt_freq_hz, uint32_t *real_freq_hz);
7373
#endif // SOC_CLK_APLL_SUPPORTED
7474

7575
#if SOC_CLK_MPLL_SUPPORTED
@@ -96,7 +96,7 @@ void periph_rtc_mpll_release(void);
9696
* - ESP_OK: MPLL frequency set success
9797
* - ESP_ERR_INVALID_STATE: MPLL is referred by more than one peripherals, not allowed to change its frequency now
9898
*/
99-
esp_err_t periph_rtc_mpll_freq_set(uint32_t expt_freq, uint32_t *real_freq);
99+
esp_err_t periph_rtc_mpll_freq_set(uint32_t expt_freq_hz, uint32_t *real_freq_hz);
100100
#endif // SOC_CLK_MPLL_SUPPORTED
101101

102102
#ifdef __cplusplus

components/esp_hw_support/port/esp32p4/esp_clk_tree.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,9 @@ esp_err_t esp_clk_tree_enable_src(soc_module_clk_t clk_src, bool enable)
9999
case SOC_MOD_CLK_PLL_F25M:
100100
clk_gate_ll_ref_25m_clk_en(enable);
101101
break;
102+
case SOC_MOD_CLK_PLL_F50M:
103+
clk_gate_ll_ref_50m_clk_en(enable);
104+
break;
102105
case SOC_MOD_CLK_PLL_F80M:
103106
clk_gate_ll_ref_80m_clk_en(enable);
104107
break;

components/hal/esp32p4/include/hal/clk_gate_ll.h

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* SPDX-FileCopyrightText: 2015-2024 Espressif Systems (Shanghai) CO LTD
2+
* SPDX-FileCopyrightText: 2015-2025 Espressif Systems (Shanghai) CO LTD
33
*
44
* SPDX-License-Identifier: Apache-2.0
55
*/
@@ -88,6 +88,19 @@ FORCE_INLINE_ATTR void _clk_gate_ll_xtal_to_lp_periph_en(bool enable)
8888
/// the critical section needs to declare the __DECLARE_RCC_ATOMIC_ENV variable in advance
8989
#define clk_gate_ll_xtal_to_lp_periph_en(...) (void)__DECLARE_RCC_ATOMIC_ENV; _clk_gate_ll_xtal_to_lp_periph_en(__VA_ARGS__)
9090

91+
/**
92+
* Enable or disable the clock gate for ref_50m.
93+
* @param enable Enable / disable
94+
*/
95+
FORCE_INLINE_ATTR void _clk_gate_ll_ref_50m_clk_en(bool enable)
96+
{
97+
HP_SYS_CLKRST.ref_clk_ctrl1.reg_ref_50m_clk_en = enable;
98+
}
99+
/// use a macro to wrap the function, force the caller to use it in a critical section
100+
/// the critical section needs to declare the __DECLARE_RCC_ATOMIC_ENV variable in advance
101+
#define clk_gate_ll_ref_50m_clk_en(...) (void)__DECLARE_RCC_ATOMIC_ENV; _clk_gate_ll_ref_50m_clk_en(__VA_ARGS__)
102+
103+
91104
#ifdef __cplusplus
92105
}
93106
#endif

0 commit comments

Comments
 (0)