aboutsummaryrefslogtreecommitdiff
path: root/drivers/net/phy
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/phy')
-rw-r--r--drivers/net/phy/Kconfig20
-rw-r--r--drivers/net/phy/Makefile1
-rw-r--r--drivers/net/phy/ethernet_id.c69
-rw-r--r--drivers/net/phy/phy.c13
4 files changed, 99 insertions, 4 deletions
diff --git a/drivers/net/phy/Kconfig b/drivers/net/phy/Kconfig
index 4f8d33ce8f..014a4de223 100644
--- a/drivers/net/phy/Kconfig
+++ b/drivers/net/phy/Kconfig
@@ -2,6 +2,10 @@
config BITBANGMII
bool "Bit-banged ethernet MII management channel support"
+config BITBANGMII_MULTI
+ bool "Enable the multi bus support"
+ depends on BITBANGMII
+
config MV88E6352_SWITCH
bool "Marvell 88E6352 switch support"
@@ -307,6 +311,14 @@ config PHY_XILINX_GMII2RGMII
as bridge between MAC connected over GMII and external phy that
is connected over RGMII interface.
+config PHY_ETHERNET_ID
+ bool "Read ethernet PHY id"
+ depends on DM_GPIO
+ default y if ZYNQ_GEM
+ help
+ Enable this config to read ethernet phy id from the phy node of DT
+ and create a phy device using id.
+
config PHY_FIXED
bool "Fixed-Link PHY"
depends on DM_ETH
@@ -322,3 +334,11 @@ config PHY_NCSI
depends on DM_ETH
endif #PHYLIB
+
+config PHY_RESET_DELAY
+ int "Extra delay after reset before MII register access"
+ default 0
+ help
+ Some PHYs need extra delay after reset before any MII register access
+ is possible. For such PHY, set this option to the usec delay
+ required.
diff --git a/drivers/net/phy/Makefile b/drivers/net/phy/Makefile
index 77f7f60621..b28440bc4e 100644
--- a/drivers/net/phy/Makefile
+++ b/drivers/net/phy/Makefile
@@ -32,6 +32,7 @@ obj-$(CONFIG_PHY_TI_DP83867) += dp83867.o
obj-$(CONFIG_PHY_TI_DP83869) += dp83869.o
obj-$(CONFIG_PHY_XILINX) += xilinx_phy.o
obj-$(CONFIG_PHY_XILINX_GMII2RGMII) += xilinx_gmii2rgmii.o
+obj-$(CONFIG_PHY_ETHERNET_ID) += ethernet_id.o
obj-$(CONFIG_PHY_VITESSE) += vitesse.o
obj-$(CONFIG_PHY_MSCC) += mscc.o
obj-$(CONFIG_PHY_FIXED) += fixed.o
diff --git a/drivers/net/phy/ethernet_id.c b/drivers/net/phy/ethernet_id.c
new file mode 100644
index 0000000000..5617ac3ad6
--- /dev/null
+++ b/drivers/net/phy/ethernet_id.c
@@ -0,0 +1,69 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Xilinx ethernet phy reset driver
+ *
+ * Copyright (C) 2022 Xilinx, Inc.
+ */
+
+#include <common.h>
+#include <dm/device_compat.h>
+#include <phy.h>
+#include <linux/delay.h>
+#include <asm/gpio.h>
+
+struct phy_device *phy_connect_phy_id(struct mii_dev *bus, struct udevice *dev,
+ phy_interface_t interface)
+{
+ struct phy_device *phydev;
+ struct ofnode_phandle_args phandle_args;
+ struct gpio_desc gpio;
+ ofnode node;
+ u32 id, assert, deassert;
+ u16 vendor, device;
+ int ret;
+
+ if (dev_read_phandle_with_args(dev, "phy-handle", NULL, 0, 0,
+ &phandle_args))
+ return NULL;
+
+ if (!ofnode_valid(phandle_args.node))
+ return NULL;
+
+ node = phandle_args.node;
+
+ ret = ofnode_read_eth_phy_id(node, &vendor, &device);
+ if (ret) {
+ dev_err(dev, "Failed to read eth PHY id, err: %d\n", ret);
+ return NULL;
+ }
+
+ ret = gpio_request_by_name_nodev(node, "reset-gpios", 0, &gpio,
+ GPIOD_ACTIVE_LOW);
+ if (!ret) {
+ assert = ofnode_read_u32_default(node, "reset-assert-us", 0);
+ deassert = ofnode_read_u32_default(node,
+ "reset-deassert-us", 0);
+ ret = dm_gpio_set_value(&gpio, 1);
+ if (ret) {
+ dev_err(dev, "Failed assert gpio, err: %d\n", ret);
+ return NULL;
+ }
+
+ udelay(assert);
+
+ ret = dm_gpio_set_value(&gpio, 0);
+ if (ret) {
+ dev_err(dev, "Failed deassert gpio, err: %d\n", ret);
+ return NULL;
+ }
+
+ udelay(deassert);
+ }
+
+ id = vendor << 16 | device;
+ phydev = phy_device_create(bus, 0, id, false, interface);
+ if (phydev)
+ phydev->node = node;
+
+ return phydev;
+}
diff --git a/drivers/net/phy/phy.c b/drivers/net/phy/phy.c
index c9fc20855b..92fff5b72c 100644
--- a/drivers/net/phy/phy.c
+++ b/drivers/net/phy/phy.c
@@ -659,9 +659,9 @@ static struct phy_driver *get_phy_driver(struct phy_device *phydev,
return generic_for_interface(interface);
}
-static struct phy_device *phy_device_create(struct mii_dev *bus, int addr,
- u32 phy_id, bool is_c45,
- phy_interface_t interface)
+struct phy_device *phy_device_create(struct mii_dev *bus, int addr,
+ u32 phy_id, bool is_c45,
+ phy_interface_t interface)
{
struct phy_device *dev;
@@ -872,7 +872,7 @@ int phy_reset(struct phy_device *phydev)
return -1;
}
-#ifdef CONFIG_PHY_RESET_DELAY
+#if CONFIG_PHY_RESET_DELAY > 0
udelay(CONFIG_PHY_RESET_DELAY); /* Intel LXT971A needs this */
#endif
/*
@@ -1047,6 +1047,11 @@ struct phy_device *phy_connect(struct mii_dev *bus, int addr,
phydev = phy_device_create(bus, 0, PHY_NCSI_ID, false, interface);
#endif
+#ifdef CONFIG_PHY_ETHERNET_ID
+ if (!phydev)
+ phydev = phy_connect_phy_id(bus, dev, interface);
+#endif
+
#ifdef CONFIG_PHY_XILINX_GMII2RGMII
if (!phydev)
phydev = phy_connect_gmii2rgmii(bus, dev, interface);