From cdfc6c159f6b51f67fd314a1dd4a61d5c18d5d93 Mon Sep 17 00:00:00 2001 From: robert-hh Date: Sun, 3 Mar 2024 12:54:33 +0100 Subject: [PATCH] esp32/network_lan: Add a separate argument to set PHY power pin. Prior to this commit, the pin defined for power would be used by the esp_idf driver to reset the PHY. That worked, but sometimes the MDIO configuration started before the power was fully settled, leading to an error. With the change in this commit, the power for the PHY is independently enabled in network_lan.c with a 100ms delay to allow the power to settle. A separate define for a reset pin is provided, even if the PHY reset pin is rarely connected. Fixes issue #14013. Signed-off-by: robert-hh --- docs/esp32/quickref.rst | 1 + ports/esp32/network_lan.c | 14 ++++++++++++-- 2 files changed, 13 insertions(+), 2 deletions(-) diff --git a/docs/esp32/quickref.rst b/docs/esp32/quickref.rst index 9c77dc402e..6c07c584d3 100644 --- a/docs/esp32/quickref.rst +++ b/docs/esp32/quickref.rst @@ -128,6 +128,7 @@ The keyword arguments for the constructor defining the PHY type and interface ar - mdc=pin-object # set the mdc and mdio pins. - mdio=pin-object +- reset=pin-object # set the reset pin of the PHY device. - power=pin-object # set the pin which switches the power of the PHY device. - phy_type= # Select the PHY device type. Supported devices are PHY_LAN8710, PHY_LAN8720, PH_IP101, PHY_RTL8201, PHY_DP83848 and PHY_KSZ8041 diff --git a/ports/esp32/network_lan.c b/ports/esp32/network_lan.c index d7d9a9f7ac..570c9a4afd 100644 --- a/ports/esp32/network_lan.c +++ b/ports/esp32/network_lan.c @@ -51,6 +51,7 @@ typedef struct _lan_if_obj_t { bool initialized; int8_t mdc_pin; int8_t mdio_pin; + int8_t phy_reset_pin; int8_t phy_power_pin; int8_t phy_cs_pin; int8_t phy_int_pin; @@ -99,12 +100,13 @@ static mp_obj_t get_lan(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_ar return MP_OBJ_FROM_PTR(&lan_obj); } - enum { ARG_id, ARG_mdc, ARG_mdio, ARG_power, ARG_phy_addr, ARG_phy_type, + enum { ARG_id, ARG_mdc, ARG_mdio, ARG_reset, ARG_power, ARG_phy_addr, ARG_phy_type, ARG_spi, ARG_cs, ARG_int, ARG_ref_clk_mode, ARG_ref_clk }; static const mp_arg_t allowed_args[] = { { MP_QSTR_id, MP_ARG_OBJ, {.u_obj = mp_const_none} }, { MP_QSTR_mdc, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = mp_const_none} }, { MP_QSTR_mdio, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = mp_const_none} }, + { MP_QSTR_reset, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = mp_const_none} }, { MP_QSTR_power, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = mp_const_none} }, { MP_QSTR_phy_addr, MP_ARG_KW_ONLY | MP_ARG_REQUIRED | MP_ARG_INT }, { MP_QSTR_phy_type, MP_ARG_KW_ONLY | MP_ARG_REQUIRED | MP_ARG_INT }, @@ -128,6 +130,7 @@ static mp_obj_t get_lan(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_ar self->mdc_pin = GET_PIN(ARG_mdc); self->mdio_pin = GET_PIN(ARG_mdio); + self->phy_reset_pin = GET_PIN(ARG_reset); self->phy_power_pin = GET_PIN(ARG_power); self->phy_cs_pin = GET_PIN(ARG_cs); self->phy_int_pin = GET_PIN(ARG_int); @@ -179,8 +182,15 @@ static mp_obj_t get_lan(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_ar eth_phy_config_t phy_config = ETH_PHY_DEFAULT_CONFIG(); phy_config.phy_addr = self->phy_addr; - phy_config.reset_gpio_num = self->phy_power_pin; + phy_config.reset_gpio_num = self->phy_reset_pin; self->phy = NULL; + // Switch on the power before PHY is reset + if (self->phy_power_pin >= 0) { + mp_hal_pin_output(self->phy_power_pin); + mp_hal_pin_write(self->phy_power_pin, 1); + // let the power settle + mp_hal_delay_ms(100); + } #if CONFIG_ETH_USE_SPI_ETHERNET spi_device_interface_config_t devcfg = { .mode = 0,