drivers: mdio_esp32: let the REF_CLK be initialized before the PHY.

When GPIO17 or 16 is used as an external REF_CLK signal, the output is
enabled in eth_esp32.c This was added in PR number #65759 and then refined
in PR #74442. However this does not work for PHYs which need the REF_CLK
for MDIO communication, such as LAN8720A. In such cases phy_mii driver
tries to get the ID of such a PHY before REF_CLK is present. Therefore
in this PR I propose to move REF_CLK initialization from eth_esp32.c to
mdio_esp32.c which gets initialized before PHY and ETH.

Signed-off-by: Łukasz Iwaszkiewicz <lukasz.iwaszkiewicz@gmail.com>
This commit is contained in:
Łukasz Iwaszkiewicz 2024-06-26 12:19:57 +02:00 committed by Benjamin Cabé
commit 2fa0afbc37
2 changed files with 55 additions and 0 deletions

View file

@ -16,6 +16,8 @@
#include <esp_mac.h> #include <esp_mac.h>
#include <hal/emac_hal.h> #include <hal/emac_hal.h>
#include <hal/emac_ll.h> #include <hal/emac_ll.h>
#include <soc/rtc.h>
#include <clk_ctrl_os.h>
LOG_MODULE_REGISTER(mdio_esp32, CONFIG_MDIO_LOG_LEVEL); LOG_MODULE_REGISTER(mdio_esp32, CONFIG_MDIO_LOG_LEVEL);
@ -86,6 +88,35 @@ static int mdio_esp32_write(const struct device *dev, uint8_t prtad,
return mdio_transfer(dev, prtad, regad, true, data, NULL); return mdio_transfer(dev, prtad, regad, true, data, NULL);
} }
#if DT_INST_NODE_HAS_PROP(0, ref_clk_output_gpios)
static int emac_config_apll_clock(void)
{
uint32_t expt_freq = MHZ(50);
uint32_t real_freq = 0;
esp_err_t ret = periph_rtc_apll_freq_set(expt_freq, &real_freq);
if (ret == ESP_ERR_INVALID_ARG) {
LOG_ERR("Set APLL clock coefficients failed");
return -EIO;
}
if (ret == ESP_ERR_INVALID_STATE) {
LOG_INF("APLL is occupied already, it is working at %d Hz", real_freq);
}
/* If the difference of real APLL frequency
* is not within 50 ppm, i.e. 2500 Hz,
* the APLL is unavailable
*/
if (abs((int)real_freq - (int)expt_freq) > 2500) {
LOG_ERR("The APLL is working at an unusable frequency");
return -EIO;
}
return 0;
}
#endif
static int mdio_esp32_initialize(const struct device *dev) static int mdio_esp32_initialize(const struct device *dev)
{ {
const struct mdio_esp32_dev_config *const cfg = dev->config; const struct mdio_esp32_dev_config *const cfg = dev->config;
@ -113,6 +144,24 @@ static int mdio_esp32_initialize(const struct device *dev)
/* Only the mac registers are required for MDIO */ /* Only the mac registers are required for MDIO */
dev_data->hal.mac_regs = &EMAC_MAC; dev_data->hal.mac_regs = &EMAC_MAC;
#if DT_INST_NODE_HAS_PROP(0, ref_clk_output_gpios)
emac_hal_init(&dev_data->hal, NULL, NULL, NULL);
emac_hal_iomux_init_rmii();
BUILD_ASSERT(DT_INST_GPIO_PIN(0, ref_clk_output_gpios) == 16 ||
DT_INST_GPIO_PIN(0, ref_clk_output_gpios) == 17,
"Only GPIO16/17 are allowed as a GPIO REF_CLK source!");
int ref_clk_gpio = DT_INST_GPIO_PIN(0, ref_clk_output_gpios);
emac_hal_iomux_rmii_clk_output(ref_clk_gpio);
emac_ll_clock_enable_rmii_output(dev_data->hal.ext_regs);
periph_rtc_apll_acquire();
res = emac_config_apll_clock();
if (res != 0) {
goto err;
}
rtc_clk_apll_enable(true);
#endif
/* Init MDIO clock */ /* Init MDIO clock */
emac_hal_set_csr_clock_range(&dev_data->hal, esp_clk_apb_freq()); emac_hal_set_csr_clock_range(&dev_data->hal, esp_clk_apb_freq());

View file

@ -8,3 +8,9 @@ compatible: "espressif,esp32-mdio"
include: include:
- name: mdio-controller.yaml - name: mdio-controller.yaml
- name: pinctrl-device.yaml - name: pinctrl-device.yaml
properties:
ref-clk-output-gpios:
type: phandle-array
description: |
GPIO to output RMII Clock.