1010#include <stdbool.h>
1111#include <zephyr/kernel.h>
1212#include <zephyr/device.h>
13+ #include <zephyr/drivers/gpio.h>
1314#include <zephyr/drivers/mdio.h>
1415#include <zephyr/logging/log.h>
1516#include <zephyr/net/mdio.h>
2021
2122LOG_MODULE_REGISTER (phy_adin , CONFIG_PHY_LOG_LEVEL );
2223
24+ /*
25+ * Only compile in support for the optional GPIOs if at least one enabled device tree node
26+ * has them.
27+ */
28+ #define ADIN2111_RST_GPIO_SUPPORT \
29+ (DT_ANY_COMPAT_HAS_PROP_STATUS_OKAY(adi_adin1100_phy, reset_gpios) || \
30+ DT_ANY_COMPAT_HAS_PROP_STATUS_OKAY(adi_adin2111_phy, reset_gpios))
31+
2332/* PHYs out of reset check retry delay */
2433#define ADIN2111_PHY_AWAIT_DELAY_POLL_US 15U
2534/*
@@ -36,6 +45,7 @@ LOG_MODULE_REGISTER(phy_adin, CONFIG_PHY_LOG_LEVEL);
3645
3746/* Software reset, CLK_25 disabled time*/
3847#define ADIN1100_PHY_SFT_RESET_MS 25U
48+ #define ADIN1100_PHY_HRD_RESET_MS 70U
3949
4050/* PHYs autonegotiation complete timeout */
4151#define ADIN2111_AN_COMPLETE_AWAIT_TIMEOUT_MS 3000U
@@ -94,6 +104,9 @@ struct phy_adin2111_config {
94104 bool led0_en ;
95105 bool led1_en ;
96106 bool tx_24v ;
107+ #if ADIN2111_RST_GPIO_SUPPORT
108+ const struct gpio_dt_spec reset_gpio ;
109+ #endif /* ADIN2111_RST_GPIO_SUPPORT */
97110 bool mii ;
98111};
99112
@@ -352,6 +365,31 @@ static int phy_adin2111_reset(const struct device *dev)
352365{
353366 int ret ;
354367
368+ #if ADIN2111_RST_GPIO_SUPPORT
369+ const struct phy_adin2111_config * config = dev -> config ;
370+
371+ if (!config -> reset_gpio .port ) {
372+ goto skip_reset_gpio ;
373+ }
374+
375+ /* Assert reset (min. reset pulse width 10us) */
376+ ret = gpio_pin_set_dt (& config -> reset_gpio , 1 );
377+ if (ret < 0 ) {
378+ return ret ;
379+ }
380+ k_busy_wait (50 );
381+
382+ /* Deassert reset */
383+ ret = gpio_pin_set_dt (& config -> reset_gpio , 0 );
384+ if (ret < 0 ) {
385+ return ret ;
386+ }
387+
388+ k_msleep (ADIN1100_PHY_HRD_RESET_MS );
389+
390+ return 0 ;
391+ skip_reset_gpio :
392+ #endif /* ADIN2111_RST_GPIO_SUPPORT */
355393 ret = phy_adin2111_c22_write (dev , MII_BMCR , MII_BMCR_RESET );
356394 if (ret < 0 ) {
357395 return ret ;
@@ -439,6 +477,15 @@ static int phy_adin2111_init(const struct device *dev)
439477 data -> state .is_up = false;
440478 data -> state .speed = LINK_FULL_10BASE ;
441479
480+ #if ADIN2111_RST_GPIO_SUPPORT
481+ if (cfg -> reset_gpio .port ) {
482+ ret = gpio_pin_configure_dt (& cfg -> reset_gpio , GPIO_OUTPUT_INACTIVE );
483+ if (ret < 0 ) {
484+ return ret ;
485+ }
486+ }
487+ #endif /* ADIN2111_RST_GPIO_SUPPORT */
488+
442489 /*
443490 * For adin1100 and further mii stuff,
444491 * reset may not be performed from the mac layer, doing a clean reset here.
@@ -617,13 +664,21 @@ static DEVICE_API(ethphy, phy_adin2111_api) = {
617664 .write = phy_adin2111_reg_write ,
618665};
619666
667+ #if ADIN2111_RST_GPIO_SUPPORT
668+ #define RESET_GPIO (n ) \
669+ .reset_gpio = GPIO_DT_SPEC_INST_GET_OR(n, reset_gpios, {0}),
670+ #else
671+ #define RESET_GPIO (n )
672+ #endif /* reset gpio */
673+
620674#define ADIN2111_PHY_INITIALIZE (n , model ) \
621675 static const struct phy_adin2111_config phy_adin##model##_config_##n = { \
622676 .mdio = DEVICE_DT_GET(DT_INST_BUS(n)), \
623677 .phy_addr = DT_INST_REG_ADDR(n), \
624678 .led0_en = DT_INST_PROP(n, led0_en), \
625679 .led1_en = DT_INST_PROP(n, led1_en), \
626680 .tx_24v = !(DT_INST_PROP(n, disable_tx_mode_24v)), \
681+ RESET_GPIO(n) \
627682 IF_ENABLED(DT_HAS_COMPAT_STATUS_OKAY(adi_adin1100_phy), \
628683 (.mii = 1)) \
629684 }; \
0 commit comments