summaryrefslogtreecommitdiff
path: root/drivers/net
diff options
context:
space:
mode:
authorTom Rini <[email protected]>2026-07-06 18:26:12 -0600
committerTom Rini <[email protected]>2026-07-06 18:26:12 -0600
commitee5d46b45ec0c63f8f9dd1e816e0dac3452ccc3d (patch)
tree800cd9e204ca027144070101884c0d5d3c00130f /drivers/net
parentece349ade2973e220f524ce59e59711cc919263f (diff)
parenta18265f1ccb7a272721ed4286ed3b5a6182ff424 (diff)
Merge branch 'next'
Diffstat (limited to 'drivers/net')
-rw-r--r--drivers/net/Kconfig87
-rw-r--r--drivers/net/Makefile11
-rw-r--r--drivers/net/calxedaxgmac.c2
-rw-r--r--drivers/net/dc2114x.c2
-rw-r--r--drivers/net/dwc_eth_qos.c6
-rw-r--r--drivers/net/dwc_eth_qos.h2
-rw-r--r--drivers/net/dwc_eth_qos_mtk.c442
-rw-r--r--drivers/net/ethoc.c2
-rw-r--r--drivers/net/fsl_enetc.c46
-rw-r--r--drivers/net/fsl_enetc_netc_blk_ctrl.c72
-rw-r--r--drivers/net/mcfmii.c2
-rw-r--r--drivers/net/mvgbe.c4
-rw-r--r--drivers/net/mvpp2.c60
-rw-r--r--drivers/net/phy/Kconfig18
-rw-r--r--drivers/net/phy/airoha/Kconfig13
-rw-r--r--drivers/net/phy/airoha/Makefile2
-rw-r--r--drivers/net/phy/airoha/air_an8801.c594
-rw-r--r--drivers/net/phy/airoha/air_en8811.c303
-rw-r--r--drivers/net/phy/airoha/air_phy_lib.c216
-rw-r--r--drivers/net/phy/airoha/air_phy_lib.h39
-rw-r--r--drivers/net/phy/nxp-c45-tja11xx.c2
-rw-r--r--drivers/net/qe/dm_qe_uec.c2
-rw-r--r--drivers/net/rtl8169.c18
-rw-r--r--drivers/net/ti/Kconfig4
-rw-r--r--drivers/net/tsec.c17
25 files changed, 1613 insertions, 353 deletions
diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig
index 666618681df..4399c6c7a99 100644
--- a/drivers/net/Kconfig
+++ b/drivers/net/Kconfig
@@ -184,10 +184,10 @@ config CALXEDA_XGMAC
config DWC_ETH_XGMAC
bool
select PHYLIB
- help
- This driver supports the Synopsys Designware Ethernet XGMAC (10G
- Ethernet MAC) IP block. The IP supports many options for bus type,
- clocking/reset structure, and feature list.
+ help
+ This driver supports the Synopsys Designware Ethernet XGMAC (10G
+ Ethernet MAC) IP block. The IP supports many options for bus type,
+ clocking/reset structure, and feature list.
config DWC_ETH_XGMAC_SOCFPGA
bool "Synopsys DWC Ethernet XGMAC device support for SOCFPGA"
@@ -229,8 +229,8 @@ config DWC_ETH_QOS_ADI
bool "Synopsys DWC Ethernet QOS device support for ADI SC59x-64 parts"
depends on DWC_ETH_QOS && ARCH_SC5XX
help
- The Synopsis Designware Ethernet QoS IP block with the specific
- configuration used in the ADI ADSP-SC59X 64 bit SoCs
+ The Synopsis Designware Ethernet QoS IP block with the specific
+ configuration used in the ADI ADSP-SC59X 64 bit SoCs
config DWC_ETH_QOS_IMX
bool "Synopsys DWC Ethernet QOS device support for IMX"
@@ -246,6 +246,20 @@ config DWC_ETH_QOS_INTEL
The Synopsys Designware Ethernet QOS IP block with the specific
configuration used in the Intel Elkhart-Lake soc.
+config DWC_ETH_QOS_MTK
+ bool "Synopsys DWC Ethernet QOS device support for MediaTek SoCs"
+ depends on DWC_ETH_QOS && ARCH_MEDIATEK
+ help
+ The Synopsys Designware Ethernet QOS IP block with the specific
+ configuration used in MediaTek SoCs.
+
+config DWC_ETH_QOS_QCOM
+ bool "Synopsys DWC Ethernet QOS device support for Qcom SoCs"
+ depends on DWC_ETH_QOS
+ help
+ The Synopsys Designware Ethernet QOS IP block with specific
+ configuration used in Qcom QCS404 SoC.
+
config DWC_ETH_QOS_ROCKCHIP
bool "Synopsys DWC Ethernet QOS device support for Rockchip SoCs"
depends on DWC_ETH_QOS && ARCH_ROCKCHIP
@@ -254,6 +268,13 @@ config DWC_ETH_QOS_ROCKCHIP
The Synopsys Designware Ethernet QOS IP block with specific
configuration used in Rockchip SoCs.
+config DWC_ETH_QOS_STARFIVE
+ bool "Synopsys DWC Ethernet QOS device support for STARFIVE"
+ depends on DWC_ETH_QOS
+ help
+ The Synopsys Designware Ethernet QOS IP block with specific
+ configuration used in STARFIVE JH7110 soc.
+
config DWC_ETH_QOS_STM32
bool "Synopsys DWC Ethernet QOS device support for STM32"
depends on DWC_ETH_QOS && ARCH_STM32MP
@@ -271,20 +292,6 @@ config DWC_ETH_QOS_TEGRA186
The Synopsys Designware Ethernet QOS IP block with specific
configuration used in NVIDIA's Tegra186 chip.
-config DWC_ETH_QOS_QCOM
- bool "Synopsys DWC Ethernet QOS device support for Qcom SoCs"
- depends on DWC_ETH_QOS
- help
- The Synopsys Designware Ethernet QOS IP block with specific
- configuration used in Qcom QCS404 SoC.
-
-config DWC_ETH_QOS_STARFIVE
- bool "Synopsys DWC Ethernet QOS device support for STARFIVE"
- depends on DWC_ETH_QOS
- help
- The Synopsys Designware Ethernet QOS IP block with specific
- configuration used in STARFIVE JH7110 soc.
-
config E1000
bool "Intel PRO/1000 Gigabit Ethernet support"
depends on PCI
@@ -460,9 +467,9 @@ config FSL_FM_10GEC_REGULAR_NOTATION
help
On SoCs T4240, T2080, LS1043A, etc, the notation between 10GEC and
MAC as below:
- 10GEC1->MAC9, 10GEC2->MAC10, 10GEC3->MAC1, 10GEC4->MAC2
+ 10GEC1->MAC9, 10GEC2->MAC10, 10GEC3->MAC1, 10GEC4->MAC2
While on SoCs T1024, etc, the notation between 10GEC and MAC as below:
- 10GEC1->MAC1, 10GEC2->MAC2
+ 10GEC1->MAC1, 10GEC2->MAC2
so we introduce CONFIG_FSL_FM_10GEC_REGULAR_NOTATION to identify the
new SoCs on which 10GEC enumeration is consistent with MAC
enumeration.
@@ -529,7 +536,7 @@ config KSZ9477
config LITEETH
bool "LiteX LiteEth Ethernet MAC"
help
- Driver for the LiteEth Ethernet MAC from LiteX.
+ Driver for the LiteEth Ethernet MAC from LiteX.
config MV88E6XXX
bool "Marvell MV88E6xxx Ethernet switch DSA driver"
@@ -701,12 +708,12 @@ config SJA1105
family. These are 5-port devices and are managed over an SPI
interface. Probing is handled based on OF bindings. The driver
supports the following revisions:
- - SJA1105E (Gen. 1, No TT-Ethernet)
- - SJA1105T (Gen. 1, TT-Ethernet)
- - SJA1105P (Gen. 2, No SGMII, No TT-Ethernet)
- - SJA1105Q (Gen. 2, No SGMII, TT-Ethernet)
- - SJA1105R (Gen. 2, SGMII, No TT-Ethernet)
- - SJA1105S (Gen. 2, SGMII, TT-Ethernet)
+ - SJA1105E (Gen. 1, No TT-Ethernet)
+ - SJA1105T (Gen. 1, TT-Ethernet)
+ - SJA1105P (Gen. 2, No SGMII, No TT-Ethernet)
+ - SJA1105Q (Gen. 2, No SGMII, TT-Ethernet)
+ - SJA1105R (Gen. 2, SGMII, No TT-Ethernet)
+ - SJA1105S (Gen. 2, SGMII, TT-Ethernet)
config SMC911X
bool "SMSC LAN911x and LAN921x controller driver"
@@ -740,11 +747,11 @@ config SUN4I_EMAC
This driver supports the Allwinner based SUN4I Ethernet MAC.
config SUN8I_EMAC
- bool "Allwinner Sun8i Ethernet MAC support"
- select PHYLIB
+ bool "Allwinner Sun8i Ethernet MAC support"
+ select PHYLIB
select PHY_GIGE
- help
- This driver supports the Allwinner based SUN8I/SUN50I Ethernet MAC.
+ help
+ This driver supports the Allwinner based SUN8I/SUN50I Ethernet MAC.
It can be found in H3/A64/A83T based SoCs and compatible with both
External and Internal PHYs.
@@ -905,7 +912,7 @@ config FEC1_PHY
help
Define to the hardcoded PHY address which corresponds
to the given FEC; i. e.
- #define CONFIG_FEC1_PHY 4
+ #define CONFIG_FEC1_PHY 4
means that the PHY with address 4 is connected to FEC1
When set to -1, means to probe for first available.
@@ -929,7 +936,7 @@ config FEC2_PHY
help
Define to the hardcoded PHY address which corresponds
to the given FEC; i. e.
- #define CONFIG_FEC1_PHY 4
+ #define CONFIG_FEC1_PHY 4
means that the PHY with address 4 is connected to FEC1
When set to -1, means to probe for first available.
@@ -1018,8 +1025,8 @@ config FSL_ENETC
config FSL_ENETC_NETC_BLK_CTRL
bool "NXP ENETC NETC blocks control driver"
depends on FSL_ENETC
- depends on IMX95 || IMX94
- default y if IMX95 || IMX94
+ depends on IMX95 || IMX94 || IMX952
+ default y if IMX95 || IMX94 || IMX952
help
This driver configures Integrated Endpoint Register Block (IERB) and
Privileged Register Block (PRB) of NETC. For i.MX platforms, it also
@@ -1034,7 +1041,7 @@ config MDIO_GPIO_BITBANG
bool "GPIO bitbanging MDIO driver"
depends on DM_MDIO && DM_GPIO
help
- Driver for bitbanging MDIO
+ Driver for bitbanging MDIO
config MDIO_MUX_I2CREG
bool "MDIO MUX accessed as a register over I2C"
@@ -1080,8 +1087,8 @@ config MDIO_MSCC_MIIM
depends on DM_MDIO
select REGMAP
help
- This driver supports MDIO interface found in Microsemi and Microchip
- network switches.
+ This driver supports MDIO interface found in Microsemi and Microchip
+ network switches.
config MDIO_MUX_MMIOREG
bool "MDIO MUX accessed as a MMIO register access"
diff --git a/drivers/net/Makefile b/drivers/net/Makefile
index 5e90183d090..761f7f0f451 100644
--- a/drivers/net/Makefile
+++ b/drivers/net/Makefile
@@ -5,7 +5,6 @@
obj-$(CONFIG_AG7XXX) += ag7xxx.o
-obj-y += airoha/
obj-$(CONFIG_AIROHA_ETH) += airoha_eth.o
obj-$(CONFIG_ALTERA_TSE) += altera_tse.o
obj-$(CONFIG_ASPEED_MDIO) += aspeed_mdio.o
@@ -22,12 +21,13 @@ obj-$(CONFIG_DWC_ETH_QOS) += dwc_eth_qos.o
obj-$(CONFIG_DWC_ETH_QOS_ADI) += dwc_eth_qos_adi.o
obj-$(CONFIG_DWC_ETH_QOS_IMX) += dwc_eth_qos_imx.o
obj-$(CONFIG_DWC_ETH_QOS_INTEL) += dwc_eth_qos_intel.o
-obj-$(CONFIG_DWC_ETH_QOS_ROCKCHIP) += dwc_eth_qos_rockchip.o
+obj-$(CONFIG_DWC_ETH_QOS_MTK) += dwc_eth_qos_mtk.o
obj-$(CONFIG_DWC_ETH_QOS_QCOM) += dwc_eth_qos_qcom.o
-obj-$(CONFIG_DWC_ETH_XGMAC) += dwc_eth_xgmac.o
-obj-$(CONFIG_DWC_ETH_XGMAC_SOCFPGA) += dwc_eth_xgmac_socfpga.o
+obj-$(CONFIG_DWC_ETH_QOS_ROCKCHIP) += dwc_eth_qos_rockchip.o
obj-$(CONFIG_DWC_ETH_QOS_STARFIVE) += dwc_eth_qos_starfive.o
obj-$(CONFIG_DWC_ETH_QOS_STM32) += dwc_eth_qos_stm32.o
+obj-$(CONFIG_DWC_ETH_XGMAC) += dwc_eth_xgmac.o
+obj-$(CONFIG_DWC_ETH_XGMAC_SOCFPGA) += dwc_eth_xgmac_socfpga.o
obj-$(CONFIG_E1000) += e1000.o
obj-$(CONFIG_E1000_SPI) += e1000_spi.o
obj-$(CONFIG_EEPRO100) += eepro100.o
@@ -62,9 +62,9 @@ obj-$(CONFIG_KSZ9477) += ksz9477.o
obj-$(CONFIG_LITEETH) += liteeth.o
obj-$(CONFIG_MACB) += macb.o
obj-$(CONFIG_MCFFEC) += mcffec.o mcfmii.o
+obj-$(CONFIG_MDIO_GPIO_BITBANG) += mdio_gpio.o
obj-$(CONFIG_MDIO_IPQ4019) += mdio-ipq4019.o
obj-$(CONFIG_MDIO_MSCC_MIIM) += mdio-mscc-miim.o
-obj-$(CONFIG_MDIO_GPIO_BITBANG) += mdio_gpio.o
obj-$(CONFIG_MDIO_MT7531_MMIO) += mdio-mt7531-mmio.o
obj-$(CONFIG_MDIO_MUX_I2CREG) += mdio_mux_i2creg.o
obj-$(CONFIG_MDIO_MUX_MESON_G12A) += mdio_mux_meson_g12a.o
@@ -109,6 +109,7 @@ obj-$(CONFIG_XILINX_AXIEMAC) += xilinx_axi_emac.o
obj-$(CONFIG_XILINX_AXIMRMAC) += xilinx_axi_mrmac.o
obj-$(CONFIG_XILINX_EMACLITE) += xilinx_emaclite.o
obj-$(CONFIG_ZYNQ_GEM) += zynq_gem.o
+obj-y += airoha/
obj-y += mscc_eswitch/
obj-y += phy/
obj-y += qe/
diff --git a/drivers/net/calxedaxgmac.c b/drivers/net/calxedaxgmac.c
index 92990fa6d47..df0ed820e06 100644
--- a/drivers/net/calxedaxgmac.c
+++ b/drivers/net/calxedaxgmac.c
@@ -555,7 +555,7 @@ static int xgmac_ofdata_to_platdata(struct udevice *dev)
return -ENOMEM;
dev_set_priv(dev, priv);
- pdata->iobase = devfdt_get_addr(dev);
+ pdata->iobase = dev_read_addr(dev);
if (pdata->iobase == FDT_ADDR_T_NONE) {
printf("%s: Cannot find XGMAC base address\n", __func__);
return -EINVAL;
diff --git a/drivers/net/dc2114x.c b/drivers/net/dc2114x.c
index 8fa549280aa..2a21eceac57 100644
--- a/drivers/net/dc2114x.c
+++ b/drivers/net/dc2114x.c
@@ -653,7 +653,7 @@ static int dc2114x_of_to_plat(struct udevice *dev)
struct eth_pdata *plat = dev_get_plat(dev);
struct dc2114x_priv *priv = dev_get_priv(dev);
- plat->iobase = (phys_addr_t)map_physmem((phys_addr_t)devfdt_get_addr(dev), 0, MAP_NOCACHE);
+ plat->iobase = (phys_addr_t)dev_remap_addr(dev);
priv->iobase = (void *)plat->iobase;
return 0;
diff --git a/drivers/net/dwc_eth_qos.c b/drivers/net/dwc_eth_qos.c
index 0f31d646845..b7e6299c307 100644
--- a/drivers/net/dwc_eth_qos.c
+++ b/drivers/net/dwc_eth_qos.c
@@ -1659,6 +1659,12 @@ static const struct udevice_id eqos_ids[] = {
.data = (ulong)&eqos_adi_config
},
#endif
+#if IS_ENABLED(CONFIG_DWC_ETH_QOS_MTK)
+ {
+ .compatible = "mediatek,mt8189-gmac",
+ .data = (ulong)&eqos_mtk_config
+ },
+#endif
{ }
};
diff --git a/drivers/net/dwc_eth_qos.h b/drivers/net/dwc_eth_qos.h
index ba16f1a37cb..978b848b46e 100644
--- a/drivers/net/dwc_eth_qos.h
+++ b/drivers/net/dwc_eth_qos.h
@@ -97,6 +97,7 @@ struct eqos_mac_regs {
#define EQOS_MAC_MDIO_ADDRESS_PA_MASK GENMASK(25, 21)
#define EQOS_MAC_MDIO_ADDRESS_RDA_MASK GENMASK(20, 16)
#define EQOS_MAC_MDIO_ADDRESS_CR_MASK GENMASK(11, 8)
+#define EQOS_MAC_MDIO_ADDRESS_CR_60_100 0
#define EQOS_MAC_MDIO_ADDRESS_CR_100_150 1
#define EQOS_MAC_MDIO_ADDRESS_CR_20_35 2
#define EQOS_MAC_MDIO_ADDRESS_CR_150_250 4
@@ -316,3 +317,4 @@ extern struct eqos_config eqos_stm32mp15_config;
extern struct eqos_config eqos_stm32mp25_config;
extern struct eqos_config eqos_jh7110_config;
extern struct eqos_config eqos_adi_config;
+extern struct eqos_config eqos_mtk_config;
diff --git a/drivers/net/dwc_eth_qos_mtk.c b/drivers/net/dwc_eth_qos_mtk.c
new file mode 100644
index 00000000000..43e1085dfe5
--- /dev/null
+++ b/drivers/net/dwc_eth_qos_mtk.c
@@ -0,0 +1,442 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright (c) 2026 BayLibre, SAS.
+ * Author: Julien Stephan <[email protected]>
+ */
+
+#include <dm.h>
+#include <dm/device_compat.h>
+#include <linux/bitfield.h>
+#include <net.h>
+#include <phy.h>
+#include <regmap.h>
+#include <syscon.h>
+
+#include "dwc_eth_qos.h"
+
+/*
+ * Peri Configuration register is SoC specific,
+ * so add a SoC specific prefix.
+ */
+#define MT8189_PERI_ETH_CTRL0 0x270
+#define MT8189_PERI_ETH_CTRL1 0x274
+#define MT8189_PERI_ETH_CTRL2 0x278
+
+#define EQOS_MTK_RMII_CLK_SRC_INTERNAL BIT(28)
+#define EQOS_MTK_RMII_CLK_SRC_RXC BIT(27)
+#define EQOS_MTK_ETH_INTF_SEL GENMASK(26, 24)
+#define EQOS_MTK_PHY_INTF_MII 0
+#define EQOS_MTK_PHY_INTF_RGMII 1
+#define EQOS_MTK_PHY_INTF_RMII 4
+#define EQOS_MTK_RGMII_TXC_PHASE_CTRL BIT(22)
+#define EQOS_MTK_EXT_PHY_MODE BIT(21)
+#define EQOS_MTK_TXC_OUT_OP BIT(20)
+#define EQOS_MTK_DLY_GTXC_INV BIT(12)
+#define EQOS_MTK_DLY_GTXC_STAGE_FINE GENMASK(11, 6)
+#define EQOS_MTK_DLY_GTXC_ENABLE BIT(5)
+#define EQOS_MTK_DLY_GTXC_STAGES GENMASK(4, 0)
+
+#define EQOS_MTK_DLY_RXC_INV BIT(25)
+#define EQOS_MTK_DLY_RXC_ENABLE BIT(18)
+#define EQOS_MTK_DLY_RXC_STAGES GENMASK(17, 13)
+#define EQOS_MTK_DLY_TXC_INV BIT(12)
+#define EQOS_MTK_DLY_TXC_ENABLE BIT(5)
+#define EQOS_MTK_DLY_TXC_STAGES GENMASK(4, 0)
+
+#define EQOS_MTK_DLY_RMII_RXC_INV BIT(25)
+#define EQOS_MTK_DLY_RMII_RXC_ENABLE BIT(18)
+#define EQOS_MTK_DLY_RMII_RXC_STAGES GENMASK(17, 13)
+#define EQOS_MTK_DLY_RMII_TXC_INV BIT(12)
+#define EQOS_MTK_DLY_RMII_TXC_ENABLE BIT(5)
+#define EQOS_MTK_DLY_RMII_TXC_STAGES GENMASK(4, 0)
+
+#define DELAY_MAX_PS 9800
+#define DELAY_PS_PER_STAGE 290
+
+struct eqos_mtk_priv {
+ struct regmap *peri_regmap;
+ bool rmii_clk_from_mac;
+ bool rmii_rxc;
+ u32 tx_delay_stage;
+ u32 rx_delay_stage;
+ bool tx_inv;
+ bool rx_inv;
+};
+
+static int mtk_clk_init(struct udevice *dev)
+{
+ struct eqos_priv *eqos = dev_get_priv(dev);
+ int ret;
+
+ ret = clk_get_by_name(dev, "mac_main", &eqos->clk_tx);
+ if (ret) {
+ dev_err(dev, "clk_get_by_name(mac_main) failed: %d", ret);
+ return ret;
+ }
+
+ ret = clk_get_by_name(dev, "ptp_ref", &eqos->clk_ptp_ref);
+ if (ret) {
+ dev_err(dev, "clk_get_by_name(ptp_ref) failed: %d", ret);
+ return ret;
+ }
+
+ return 0;
+}
+
+static int mtk_set_delay(struct udevice *dev)
+{
+ struct eth_pdata *pdata = dev_get_plat(dev);
+ struct eqos_mtk_priv *mtk_pdata = pdata->priv_pdata;
+ u32 gtxc_delay_val = 0, delay_val = 0, rmii_delay_val = 0;
+
+ switch (pdata->phy_interface) {
+ case PHY_INTERFACE_MODE_MII:
+ delay_val |= FIELD_PREP(EQOS_MTK_DLY_TXC_ENABLE,
+ !!mtk_pdata->tx_delay_stage);
+ delay_val |= FIELD_PREP(EQOS_MTK_DLY_TXC_STAGES, mtk_pdata->tx_delay_stage);
+ delay_val |= FIELD_PREP(EQOS_MTK_DLY_TXC_INV, mtk_pdata->tx_inv);
+
+ delay_val |= FIELD_PREP(EQOS_MTK_DLY_RXC_ENABLE,
+ !!mtk_pdata->rx_delay_stage);
+ delay_val |= FIELD_PREP(EQOS_MTK_DLY_RXC_STAGES, mtk_pdata->rx_delay_stage);
+ delay_val |= FIELD_PREP(EQOS_MTK_DLY_RXC_INV, mtk_pdata->rx_inv);
+ break;
+ case PHY_INTERFACE_MODE_RMII:
+ if (mtk_pdata->rmii_clk_from_mac) {
+ /* case 1: mac provides the rmii reference clock,
+ * and the clock output to TXC pin.
+ * The egress timing can be adjusted by RMII_TXC delay macro circuit.
+ * The ingress timing can be adjusted by RMII_RXC delay macro circuit.
+ */
+ rmii_delay_val |= FIELD_PREP(EQOS_MTK_DLY_RMII_TXC_ENABLE,
+ !!mtk_pdata->tx_delay_stage);
+ rmii_delay_val |= FIELD_PREP(EQOS_MTK_DLY_RMII_TXC_STAGES,
+ mtk_pdata->tx_delay_stage);
+ rmii_delay_val |= FIELD_PREP(EQOS_MTK_DLY_RMII_TXC_INV,
+ mtk_pdata->tx_inv);
+
+ rmii_delay_val |= FIELD_PREP(EQOS_MTK_DLY_RMII_RXC_ENABLE,
+ !!mtk_pdata->rx_delay_stage);
+ rmii_delay_val |= FIELD_PREP(EQOS_MTK_DLY_RMII_RXC_STAGES,
+ mtk_pdata->rx_delay_stage);
+ rmii_delay_val |= FIELD_PREP(EQOS_MTK_DLY_RMII_RXC_INV,
+ mtk_pdata->rx_inv);
+ } else {
+ /* case 2: the rmii reference clock is from external phy,
+ * and the property "rmii_rxc" indicates which pin(TXC/RXC)
+ * the reference clk is connected to. The reference clock is a
+ * received signal, so rx_delay_stage/rx_inv are used to indicate
+ * the reference clock timing adjustment
+ */
+ if (mtk_pdata->rmii_rxc) {
+ /* the rmii reference clock from outside is connected
+ * to RXC pin, the reference clock will be adjusted
+ * by RXC delay macro circuit.
+ */
+ delay_val |= FIELD_PREP(EQOS_MTK_DLY_RXC_ENABLE,
+ !!mtk_pdata->rx_delay_stage);
+ delay_val |= FIELD_PREP(EQOS_MTK_DLY_RXC_STAGES,
+ mtk_pdata->rx_delay_stage);
+ delay_val |= FIELD_PREP(EQOS_MTK_DLY_RXC_INV,
+ mtk_pdata->rx_inv);
+ } else {
+ /* the rmii reference clock from outside is connected
+ * to TXC pin, the reference clock will be adjusted
+ * by TXC delay macro circuit.
+ */
+ delay_val |= FIELD_PREP(EQOS_MTK_DLY_TXC_ENABLE,
+ !!mtk_pdata->rx_delay_stage);
+ delay_val |= FIELD_PREP(EQOS_MTK_DLY_TXC_STAGES,
+ mtk_pdata->rx_delay_stage);
+ delay_val |= FIELD_PREP(EQOS_MTK_DLY_TXC_INV,
+ mtk_pdata->rx_inv);
+ }
+ }
+ break;
+ case PHY_INTERFACE_MODE_RGMII:
+ case PHY_INTERFACE_MODE_RGMII_TXID:
+ case PHY_INTERFACE_MODE_RGMII_RXID:
+ case PHY_INTERFACE_MODE_RGMII_ID:
+ gtxc_delay_val |= FIELD_PREP(EQOS_MTK_DLY_GTXC_ENABLE,
+ !!mtk_pdata->tx_delay_stage);
+ gtxc_delay_val |= FIELD_PREP(EQOS_MTK_DLY_GTXC_STAGES,
+ mtk_pdata->tx_delay_stage);
+ gtxc_delay_val |= FIELD_PREP(EQOS_MTK_DLY_GTXC_INV, mtk_pdata->tx_inv);
+ gtxc_delay_val |= EQOS_MTK_DLY_GTXC_STAGE_FINE;
+
+ delay_val |= FIELD_PREP(EQOS_MTK_DLY_RXC_ENABLE,
+ !!mtk_pdata->rx_delay_stage);
+ delay_val |= FIELD_PREP(EQOS_MTK_DLY_RXC_STAGES, mtk_pdata->rx_delay_stage);
+ delay_val |= FIELD_PREP(EQOS_MTK_DLY_RXC_INV, mtk_pdata->rx_inv);
+
+ break;
+ default:
+ dev_err(dev, "phy interface not supported\n");
+ return -EINVAL;
+ }
+
+ regmap_update_bits(mtk_pdata->peri_regmap,
+ MT8189_PERI_ETH_CTRL0,
+ EQOS_MTK_RGMII_TXC_PHASE_CTRL |
+ EQOS_MTK_DLY_GTXC_ENABLE |
+ EQOS_MTK_DLY_GTXC_INV |
+ EQOS_MTK_DLY_GTXC_STAGE_FINE |
+ EQOS_MTK_DLY_GTXC_STAGES,
+ gtxc_delay_val);
+ regmap_write(mtk_pdata->peri_regmap, MT8189_PERI_ETH_CTRL1, delay_val);
+ regmap_write(mtk_pdata->peri_regmap, MT8189_PERI_ETH_CTRL2, rmii_delay_val);
+
+ return 0;
+}
+
+static int mtk_set_interface(struct udevice *dev)
+{
+ struct eth_pdata *pdata = dev_get_plat(dev);
+ struct eqos_mtk_priv *mtk_pdata = pdata->priv_pdata;
+ int rmii_clk_from_mac = mtk_pdata->rmii_clk_from_mac ? EQOS_MTK_RMII_CLK_SRC_INTERNAL : 0;
+ int rmii_rxc = mtk_pdata->rmii_rxc ? EQOS_MTK_RMII_CLK_SRC_RXC : 0;
+ u32 intf_val = 0;
+
+ /* select phy interface in top control domain */
+ switch (pdata->phy_interface) {
+ case PHY_INTERFACE_MODE_MII:
+ intf_val |= FIELD_PREP(EQOS_MTK_ETH_INTF_SEL, EQOS_MTK_PHY_INTF_MII);
+ break;
+ case PHY_INTERFACE_MODE_RMII:
+ intf_val |= (rmii_rxc | rmii_clk_from_mac);
+ intf_val |= FIELD_PREP(EQOS_MTK_ETH_INTF_SEL, EQOS_MTK_PHY_INTF_RMII);
+ break;
+ case PHY_INTERFACE_MODE_RGMII:
+ case PHY_INTERFACE_MODE_RGMII_TXID:
+ case PHY_INTERFACE_MODE_RGMII_RXID:
+ case PHY_INTERFACE_MODE_RGMII_ID:
+ intf_val |= FIELD_PREP(EQOS_MTK_ETH_INTF_SEL, EQOS_MTK_PHY_INTF_RGMII);
+ break;
+ default:
+ dev_err(dev, "phy interface not supported\n");
+ return -EINVAL;
+ }
+
+ /* only support external PHY */
+ intf_val |= EQOS_MTK_EXT_PHY_MODE;
+
+ intf_val |= EQOS_MTK_TXC_OUT_OP;
+
+ regmap_write(mtk_pdata->peri_regmap, MT8189_PERI_ETH_CTRL0, intf_val);
+
+ return 0;
+}
+
+static int mtk_config_dt(struct udevice *dev)
+{ struct eth_pdata *pdata = dev_get_plat(dev);
+ struct eqos_mtk_priv *mtk_pdata = pdata->priv_pdata;
+ struct ofnode_phandle_args args;
+ u32 tx_delay_ps = 0, rx_delay_ps = 0;
+ int ret;
+
+ if (!dev_read_u32(dev, "mediatek,tx-delay-ps", &tx_delay_ps)) {
+ if (tx_delay_ps > DELAY_MAX_PS) {
+ dev_err(dev, "Invalid TX clock delay: %dps\n", tx_delay_ps);
+ return -EINVAL;
+ }
+ }
+
+ if (!dev_read_u32(dev, "mediatek,rx-delay-ps", &rx_delay_ps)) {
+ if (rx_delay_ps > DELAY_MAX_PS) {
+ dev_err(dev, "Invalid RX clock delay: %dps\n", rx_delay_ps);
+ return -EINVAL;
+ }
+ }
+
+ mtk_pdata->tx_delay_stage = tx_delay_ps / DELAY_PS_PER_STAGE;
+ mtk_pdata->rx_delay_stage = rx_delay_ps / DELAY_PS_PER_STAGE;
+
+ mtk_pdata->tx_inv = dev_read_bool(dev, "mediatek,txc-inverse");
+ mtk_pdata->rx_inv = dev_read_bool(dev, "mediatek,rxc-inverse");
+ mtk_pdata->rmii_clk_from_mac = dev_read_bool(dev, "mediatek,rmii-clk-from-mac");
+ mtk_pdata->rmii_rxc = dev_read_bool(dev, "mediatek,rmii-rxc");
+
+ ret = dev_read_phandle_with_args(dev, "mediatek,pericfg", NULL, 0, 0, &args);
+ if (ret) {
+ dev_err(dev, "Failed to get mediatek,pericfg property: %d\n", ret);
+ return ret;
+ }
+
+ mtk_pdata->peri_regmap = syscon_node_to_regmap(args.node);
+ if (IS_ERR(mtk_pdata->peri_regmap)) {
+ dev_err(dev, "fail to get regmap: %d\n", (int)PTR_ERR(mtk_pdata->peri_regmap));
+ return PTR_ERR(mtk_pdata->peri_regmap);
+ }
+
+ return 0;
+}
+
+static int eqos_probe_resources_mtk(struct udevice *dev)
+{
+ struct eqos_priv *eqos = dev_get_priv(dev);
+ struct eth_pdata *pdata = dev_get_plat(dev);
+ struct eqos_mtk_priv *mtk_pdata;
+ int ret;
+
+ debug("%s(dev=%p):\n", __func__, dev);
+
+ ret = eqos_get_base_addr_dt(dev);
+ if (ret) {
+ dev_err(dev, "eqos_get_base_addr_dt failed: %d\n", ret);
+ return ret;
+ }
+
+ mtk_pdata = calloc(1, sizeof(struct eqos_mtk_priv));
+ if (!mtk_pdata)
+ return -ENOMEM;
+
+ pdata->priv_pdata = mtk_pdata;
+
+ ret = mtk_config_dt(dev);
+ if (ret) {
+ dev_err(dev, "mtk config dt failed: %d\n", ret);
+ goto err;
+ }
+
+ ret = mtk_clk_init(dev);
+ if (ret)
+ goto err;
+
+ pdata->phy_interface = eqos->config->interface(dev);
+ if (pdata->phy_interface == PHY_INTERFACE_MODE_NA) {
+ dev_err(dev, "Invalid PHY interface\n");
+ ret = -EINVAL;
+ goto err;
+ }
+
+ ret = mtk_set_interface(dev);
+ if (ret)
+ goto err;
+
+ ret = mtk_set_delay(dev);
+ if (ret)
+ goto err;
+
+ debug("%s: OK\n", __func__);
+ return 0;
+err:
+ free(mtk_pdata);
+ return ret;
+}
+
+static int eqos_remove_resources_mtk(struct udevice *dev)
+{
+ struct eth_pdata *pdata = dev_get_plat(dev);
+ struct eqos_mtk_priv *mtk_pdata = pdata->priv_pdata;
+
+ debug("%s(dev=%p):\n", __func__, dev);
+
+ free(mtk_pdata);
+
+ debug("%s: OK\n", __func__);
+ return 0;
+}
+
+static int eqos_stop_clks_mtk(struct udevice *dev)
+{
+ struct eqos_priv *eqos = dev_get_priv(dev);
+
+ debug("%s(dev=%p):\n", __func__, dev);
+
+ clk_disable(&eqos->clk_ptp_ref);
+ clk_disable(&eqos->clk_tx);
+
+ debug("%s: OK\n", __func__);
+ return 0;
+}
+
+static int eqos_start_clks_mtk(struct udevice *dev)
+{
+ struct eqos_priv *eqos = dev_get_priv(dev);
+ int ret;
+
+ debug("%s(dev=%p):\n", __func__, dev);
+
+ ret = clk_enable(&eqos->clk_tx);
+ if (ret < 0) {
+ dev_err(dev, "clk_enable(mac_main) failed: %d", ret);
+ goto err;
+ }
+
+ ret = clk_enable(&eqos->clk_ptp_ref);
+ if (ret < 0) {
+ dev_err(dev, "clk_enable(ptp_ref) failed: %d", ret);
+ goto err_disable_clk_mac_main;
+ }
+
+ debug("%s: OK\n", __func__);
+ return 0;
+
+err_disable_clk_mac_main:
+ clk_disable(&eqos->clk_tx);
+err:
+ debug("%s: FAILED: %d\n", __func__, ret);
+ return ret;
+}
+
+static int eqos_fix_mac_speed_mtk(struct udevice *dev)
+{
+ struct eqos_priv *eqos = dev_get_priv(dev);
+ struct eth_pdata *pdata = dev_get_plat(dev);
+ struct eqos_mtk_priv *mtk_pdata = pdata->priv_pdata;
+
+ debug("%s(dev=%p):\n", __func__, dev);
+
+ switch (pdata->phy_interface) {
+ case PHY_INTERFACE_MODE_RGMII:
+ case PHY_INTERFACE_MODE_RGMII_TXID:
+ case PHY_INTERFACE_MODE_RGMII_RXID:
+ case PHY_INTERFACE_MODE_RGMII_ID:
+ if (eqos->phy->speed == SPEED_1000)
+ regmap_update_bits(mtk_pdata->peri_regmap,
+ MT8189_PERI_ETH_CTRL0,
+ EQOS_MTK_RGMII_TXC_PHASE_CTRL |
+ EQOS_MTK_DLY_GTXC_ENABLE |
+ EQOS_MTK_DLY_GTXC_INV |
+ EQOS_MTK_DLY_GTXC_STAGE_FINE |
+ EQOS_MTK_DLY_GTXC_STAGES,
+ EQOS_MTK_RGMII_TXC_PHASE_CTRL);
+ else
+ mtk_set_delay(dev);
+ break;
+ default:
+ debug("%s: dev=%p no need to adjust mac delay\n", __func__, dev);
+ break;
+ }
+
+ debug("%s: OK\n", __func__);
+ return 0;
+}
+
+static struct eqos_ops eqos_mtk_ops = {
+ .eqos_inval_desc = eqos_inval_desc_generic,
+ .eqos_flush_desc = eqos_flush_desc_generic,
+ .eqos_inval_buffer = eqos_inval_buffer_generic,
+ .eqos_flush_buffer = eqos_flush_buffer_generic,
+ .eqos_probe_resources = eqos_probe_resources_mtk,
+ .eqos_remove_resources = eqos_remove_resources_mtk,
+ .eqos_stop_resets = eqos_null_ops,
+ .eqos_start_resets = eqos_null_ops,
+ .eqos_stop_clks = eqos_stop_clks_mtk,
+ .eqos_start_clks = eqos_start_clks_mtk,
+ .eqos_calibrate_pads = eqos_null_ops,
+ .eqos_disable_calibration = eqos_null_ops,
+ .eqos_set_tx_clk_speed = eqos_fix_mac_speed_mtk,
+ .eqos_get_enetaddr = eqos_null_ops,
+};
+
+struct eqos_config eqos_mtk_config = {
+ .reg_access_always_ok = false,
+ .mdio_wait = 10000,
+ .swr_wait = 10,
+ .config_mac = EQOS_MAC_RXQ_CTRL0_RXQ0EN_ENABLED_DCB,
+ .config_mac_mdio = EQOS_MAC_MDIO_ADDRESS_CR_60_100,
+ .axi_bus_width = EQOS_AXI_WIDTH_64,
+ .interface = dev_read_phy_mode,
+ .ops = &eqos_mtk_ops
+};
diff --git a/drivers/net/ethoc.c b/drivers/net/ethoc.c
index dc7e6f1929f..87b2b3426c8 100644
--- a/drivers/net/ethoc.c
+++ b/drivers/net/ethoc.c
@@ -686,7 +686,7 @@ static int ethoc_of_to_plat(struct udevice *dev)
fdt_addr_t addr;
pdata->eth_pdata.iobase = dev_read_addr(dev);
- addr = devfdt_get_addr_index(dev, 1);
+ addr = dev_read_addr_index(dev, 1);
if (addr != FDT_ADDR_T_NONE)
pdata->packet_base = addr;
return 0;
diff --git a/drivers/net/fsl_enetc.c b/drivers/net/fsl_enetc.c
index 206f1a381bb..f393af40e27 100644
--- a/drivers/net/fsl_enetc.c
+++ b/drivers/net/fsl_enetc.c
@@ -18,6 +18,7 @@
#include <asm/io.h>
#include <pci.h>
#include <miiphy.h>
+#include <linux/bitfield.h>
#include <linux/bug.h>
#include <linux/delay.h>
#include <linux/build_bug.h>
@@ -74,10 +75,36 @@ static int enetc_is_ls1028a(struct udevice *dev)
pplat->vendor == PCI_VENDOR_ID_FREESCALE;
}
+static int enetc_dev_id_imx(struct udevice *dev)
+{
+ if (IS_ENABLED(CONFIG_IMX952)) {
+ int bus_devfn;
+ u32 reg[5];
+ int error;
+
+ error = dev_read_u32_array(dev, "reg", reg, ARRAY_SIZE(reg));
+ if (error)
+ return error;
+
+ bus_devfn = (reg[0] >> 8) & 0xffff;
+
+ switch (bus_devfn) {
+ case 0:
+ return 0;
+ case 0x100:
+ return 1;
+ default:
+ return -EINVAL;
+ }
+ }
+
+ return PCI_DEV(pci_get_devfn(dev)) >> 3;
+}
+
static int enetc_dev_id(struct udevice *dev)
{
if (enetc_is_imx95(dev))
- return PCI_DEV(pci_get_devfn(dev)) >> 3;
+ return enetc_dev_id_imx(dev);
if (enetc_is_ls1028a(dev))
return PCI_FUNC(pci_get_devfn(dev));
@@ -396,7 +423,7 @@ static int enetc_init_sgmii(struct udevice *dev)
/* set up MAC for RGMII */
static void enetc_init_rgmii(struct udevice *dev, struct phy_device *phydev)
{
- u32 old_val, val, dpx = 0;
+ u32 old_val, val = 0;
old_val = val = enetc_read_mac_port(dev, ENETC_PM_IF_MODE);
@@ -416,15 +443,14 @@ static void enetc_init_rgmii(struct udevice *dev, struct phy_device *phydev)
val |= ENETC_PM_IFM_SSP_10;
}
- if (enetc_is_imx95(dev))
- dpx = ENETC_PM_IFM_FULL_DPX_IMX;
+ if (enetc_is_imx95(dev))
+ val = u32_replace_bits(val,
+ phydev->duplex == DUPLEX_FULL ? 0 : 1,
+ ENETC_PM_IFM_FULL_DPX_IMX);
else if (enetc_is_ls1028a(dev))
- dpx = ENETC_PM_IFM_FULL_DPX_LS;
-
- if (phydev->duplex == DUPLEX_FULL)
- val |= dpx;
- else
- val &= ~dpx;
+ val = u32_replace_bits(val,
+ phydev->duplex == DUPLEX_FULL ? 1 : 0,
+ ENETC_PM_IFM_FULL_DPX_LS);
if (val == old_val)
return;
diff --git a/drivers/net/fsl_enetc_netc_blk_ctrl.c b/drivers/net/fsl_enetc_netc_blk_ctrl.c
index 8577bb75632..0c87d80ea5c 100644
--- a/drivers/net/fsl_enetc_netc_blk_ctrl.c
+++ b/drivers/net/fsl_enetc_netc_blk_ctrl.c
@@ -35,6 +35,7 @@
#define MII_PROT_RGMII 0x2
#define MII_PROT_SERIAL 0x3
#define MII_PROT(port, prot) (((prot) & 0xf) << ((port) << 2))
+#define MII_PROT_GET(reg, port) (((reg) >> ((port) << 2)) & 0xf)
#define IMX95_CFG_LINK_PCS_PROT(a) (0x8 + (a) * 4)
#define PCS_PROT_1G_SGMII BIT(0)
@@ -97,6 +98,9 @@
#define IMX94_TIMER1_ID 1
#define IMX94_TIMER2_ID 2
+#define IMX952_ENETC0_BUS_DEVFN 0x0
+#define IMX952_ENETC1_BUS_DEVFN 0x100
+
/* Flags for different platforms */
#define NETC_HAS_NETCMIX BIT(0)
@@ -567,6 +571,69 @@ static int netc_prb_check_error(struct netc_blk_ctrl *priv)
return 0;
}
+static int imx952_netcmix_init(struct udevice *dev)
+{
+ struct netc_blk_ctrl *priv = dev_get_priv(dev);
+ ofnode child, gchild;
+ phy_interface_t interface;
+ int bus_devfn, mii_proto;
+ u32 val;
+
+ /* Default setting */
+ val = MII_PROT(0, MII_PROT_RGMII) | MII_PROT(1, MII_PROT_RGMII);
+
+ /* Update the link MII protocol through parsing phy-mode */
+ dev_for_each_subnode(child, dev) {
+ if (!ofnode_is_enabled(child))
+ continue;
+
+ ofnode_for_each_subnode(gchild, child) {
+ if (!ofnode_is_enabled(gchild))
+ continue;
+
+ if (!ofnode_device_is_compatible(gchild, "pci1131,e101"))
+ continue;
+
+ bus_devfn = netc_of_pci_get_bus_devfn(gchild);
+ if (bus_devfn < 0)
+ return -EINVAL;
+
+ interface = ofnode_read_phy_mode(gchild);
+ if (interface == -1)
+ continue;
+
+ mii_proto = netc_get_link_mii_protocol(interface);
+ if (mii_proto < 0)
+ return -EINVAL;
+
+ switch (bus_devfn) {
+ case IMX952_ENETC0_BUS_DEVFN:
+ val &= ~CFG_LINK_MII_PORT_0;
+ val |= FIELD_PREP(CFG_LINK_MII_PORT_0, mii_proto);
+ break;
+ case IMX952_ENETC1_BUS_DEVFN:
+ val &= ~CFG_LINK_MII_PORT_1;
+ val |= FIELD_PREP(CFG_LINK_MII_PORT_1, mii_proto);
+ break;
+ default:
+ return -EINVAL;
+ }
+ }
+ }
+
+ if (MII_PROT_GET(val, 1) == MII_PROT_SERIAL) {
+ /* Configure Link I/O variant */
+ netc_reg_write(priv->netcmix, IMX95_CFG_LINK_IO_VAR,
+ IO_VAR(1, IO_VAR_16FF_16G_SERDES));
+ /* Configure Link 2 PCS protocol */
+ netc_reg_write(priv->netcmix, IMX95_CFG_LINK_PCS_PROT(1),
+ PCS_PROT_2500M_SGMII);
+ }
+ netc_reg_write(priv->netcmix, IMX95_CFG_LINK_MII_PROT, val);
+
+ return 0;
+}
+
static const struct netc_devinfo imx95_devinfo = {
.netcmix_init = imx95_netcmix_init,
.ierb_init = imx95_ierb_init,
@@ -578,9 +645,14 @@ static const struct netc_devinfo imx94_devinfo = {
.xpcs_port_init = imx94_netc_xpcs_port_init,
};
+static const struct netc_devinfo imx952_devinfo = {
+ .netcmix_init = imx952_netcmix_init,
+};
+
static const struct udevice_id netc_blk_ctrl_match[] = {
{ .compatible = "nxp,imx95-netc-blk-ctrl", .data = (ulong)&imx95_devinfo },
{ .compatible = "nxp,imx94-netc-blk-ctrl", .data = (ulong)&imx94_devinfo },
+ { .compatible = "nxp,imx952-netc-blk-ctrl", .data = (ulong)&imx952_devinfo },
{},
};
diff --git a/drivers/net/mcfmii.c b/drivers/net/mcfmii.c
index 9bf887035d7..79ad6348de8 100644
--- a/drivers/net/mcfmii.c
+++ b/drivers/net/mcfmii.c
@@ -112,7 +112,7 @@ uint mii_send(uint mii_cmd)
ep->eir = FEC_EIR_MII; /* clear MII complete */
#ifdef ET_DEBUG
printf("%s[%d] %s: sent=0x%8.8x, reply=0x%8.8x\n",
- __FILE__, __LINE__, __FUNCTION__, mii_cmd, mii_reply);
+ __FILE__, __LINE__, __func__, mii_cmd, mii_reply);
#endif
return (mii_reply & 0xffff); /* data read from phy */
diff --git a/drivers/net/mvgbe.c b/drivers/net/mvgbe.c
index 107a33aa9f5..4dc738980cb 100644
--- a/drivers/net/mvgbe.c
+++ b/drivers/net/mvgbe.c
@@ -256,8 +256,8 @@ static void set_dram_access(struct mvgbe_registers *regs)
win_param.access_ctrl = EWIN_ACCESS_FULL;
win_param.high_addr = 0;
/* Get bank base and size */
- win_param.base_addr = gd->bd->bi_dram[i].start;
- win_param.size = gd->bd->bi_dram[i].size;
+ win_param.base_addr = gd->dram[i].start;
+ win_param.size = gd->dram[i].size;
if (win_param.size == 0)
win_param.enable = 0;
else
diff --git a/drivers/net/mvpp2.c b/drivers/net/mvpp2.c
index f9e979c4d58..ae5920a0201 100644
--- a/drivers/net/mvpp2.c
+++ b/drivers/net/mvpp2.c
@@ -4528,7 +4528,7 @@ static void mvpp2_phy_connect(struct udevice *dev, struct mvpp2_port *port)
*/
if (phy_dev &&
phy_dev->drv->uid == 0xffffffff) {/* Generic phy */
- dev_warn(port->phy_dev->dev,
+ dev_warn(dev,
"Marking phy as invalid, link will not be checked\n");
/* set phy_addr to invalid value */
port->phyaddr = PHY_MAX_ADDR;
@@ -4540,7 +4540,7 @@ static void mvpp2_phy_connect(struct udevice *dev, struct mvpp2_port *port)
port->phy_dev = phy_dev;
if (!phy_dev) {
- dev_err(port->phy_dev->dev, "cannot connect to phy\n");
+ dev_err(dev, "cannot connect to phy\n");
return;
}
phy_dev->supported &= PHY_GBIT_FEATURES;
@@ -4731,33 +4731,32 @@ static int mvpp2_port_init(struct udevice *dev, struct mvpp2_port *port)
static int phy_info_parse(struct udevice *dev, struct mvpp2_port *port)
{
- int port_node = dev_of_offset(dev);
- int phy_node;
+ ofnode port_node = dev_ofnode(dev);
+ ofnode phy_node;
u32 id;
int phyaddr = 0;
- int fixed_link = 0;
+ ofnode fixed_link;
int ret;
- phy_node = fdtdec_lookup_phandle(gd->fdt_blob, port_node, "phy");
- fixed_link = fdt_subnode_offset(gd->fdt_blob, port_node, "fixed-link");
+ phy_node = ofnode_parse_phandle(port_node, "phy", 0);
+ fixed_link = ofnode_find_subnode(port_node, "fixed-link");
- if (phy_node > 0) {
- int parent;
+ if (ofnode_valid(phy_node)) {
+ ofnode parent;
- if (fixed_link != -FDT_ERR_NOTFOUND) {
+ if (ofnode_valid(fixed_link)) {
/* phy_addr is set to invalid value for fixed links */
phyaddr = PHY_MAX_ADDR;
} else {
- phyaddr = fdtdec_get_int(gd->fdt_blob, phy_node,
- "reg", 0);
+ phyaddr = ofnode_read_s32_default(phy_node, "reg", 0);
if (phyaddr < 0) {
dev_err(dev, "could not find phy address\n");
return -1;
}
}
- parent = fdt_parent_offset(gd->fdt_blob, phy_node);
- ret = uclass_get_device_by_of_offset(UCLASS_MDIO, parent,
- &port->mdio_dev);
+ parent = ofnode_get_parent(phy_node);
+ ret = uclass_get_device_by_ofnode(UCLASS_MDIO, parent,
+ &port->mdio_dev);
if (ret)
return ret;
} else {
@@ -4771,7 +4770,7 @@ static int phy_info_parse(struct udevice *dev, struct mvpp2_port *port)
return -EINVAL;
}
- id = fdtdec_get_int(gd->fdt_blob, port_node, "port-id", -1);
+ id = dev_read_s32_default(dev, "port-id", -1);
if (id == -1) {
dev_err(dev, "missing port-id value\n");
return -EINVAL;
@@ -4812,7 +4811,7 @@ static void mvpp2_gpio_init(struct mvpp2_port *port)
/* Ports initialization */
static int mvpp2_port_probe(struct udevice *dev,
struct mvpp2_port *port,
- int port_node,
+ ofnode port_node,
struct mvpp2 *priv)
{
int err;
@@ -5296,16 +5295,16 @@ static int mvpp2_base_probe(struct udevice *dev)
}
/* Save base addresses for later use */
- priv->base = devfdt_get_addr_index_ptr(dev, 0);
+ priv->base = dev_read_addr_index_ptr(dev, 0);
if (!priv->base)
return -EINVAL;
if (priv->hw_version == MVPP21) {
- priv->lms_base = devfdt_get_addr_index_ptr(dev, 1);
+ priv->lms_base = dev_read_addr_index_ptr(dev, 1);
if (!priv->lms_base)
return -EINVAL;
} else {
- priv->iface_base = devfdt_get_addr_index_ptr(dev, 1);
+ priv->iface_base = dev_read_addr_index_ptr(dev, 1);
if (!priv->iface_base)
return -EINVAL;
@@ -5346,13 +5345,11 @@ static int mvpp2_probe(struct udevice *dev)
if (priv->hw_version == MVPP21) {
int priv_common_regs_num = 2;
- port->base = devfdt_get_addr_index_ptr(
- dev->parent, priv_common_regs_num + port->id);
+ port->base = dev_read_addr_index_ptr(dev->parent, priv_common_regs_num + port->id);
if (!port->base)
return -EINVAL;
} else {
- port->gop_id = fdtdec_get_int(gd->fdt_blob, dev_of_offset(dev),
- "gop-port-id", -1);
+ port->gop_id = ofnode_read_s32_default(dev_ofnode(dev), "gop-port-id", -1);
if (port->gop_id == -1) {
dev_err(dev, "missing gop-port-id value\n");
return -EINVAL;
@@ -5376,7 +5373,7 @@ static int mvpp2_probe(struct udevice *dev)
priv->probe_done = 1;
}
- err = mvpp2_port_probe(dev, port, dev_of_offset(dev), priv);
+ err = mvpp2_port_probe(dev, port, dev_ofnode(dev), priv);
if (err)
return err;
@@ -5437,13 +5434,11 @@ static struct driver mvpp2_driver = {
*/
static int mvpp2_base_bind(struct udevice *parent)
{
- const void *blob = gd->fdt_blob;
- int node = dev_of_offset(parent);
struct uclass_driver *drv;
struct udevice *dev;
struct eth_pdata *plat;
char *name;
- int subnode;
+ ofnode subnode;
u32 id;
int base_id_add;
@@ -5456,19 +5451,19 @@ static int mvpp2_base_bind(struct udevice *parent)
base_id_add = base_id;
- fdt_for_each_subnode(subnode, blob, node) {
+ dev_for_each_subnode(subnode, parent) {
/* Increment base_id for all subnodes, also the disabled ones */
base_id++;
/* Skip disabled ports */
- if (!fdtdec_get_is_enabled(blob, subnode))
+ if (!ofnode_is_enabled(subnode))
continue;
plat = calloc(1, sizeof(*plat));
if (!plat)
return -ENOMEM;
- id = fdtdec_get_int(blob, subnode, "port-id", -1);
+ id = ofnode_read_s32_default(subnode, "port-id", -1);
id += base_id_add;
name = calloc(1, 16);
@@ -5479,8 +5474,7 @@ static int mvpp2_base_bind(struct udevice *parent)
sprintf(name, "mvpp2-%d", id);
/* Create child device UCLASS_ETH and bind it */
- device_bind(parent, &mvpp2_driver, name, plat,
- offset_to_ofnode(subnode), &dev);
+ device_bind(parent, &mvpp2_driver, name, plat, subnode, &dev);
}
return 0;
diff --git a/drivers/net/phy/Kconfig b/drivers/net/phy/Kconfig
index 0025c895f12..3f7953d693c 100644
--- a/drivers/net/phy/Kconfig
+++ b/drivers/net/phy/Kconfig
@@ -81,7 +81,7 @@ config PHYLIB_10G
config PHY_ADIN
bool "Analog Devices Industrial Ethernet PHYs"
help
- Add support for configuring RGMII on Analog Devices ADIN PHYs.
+ Add support for configuring RGMII on Analog Devices ADIN PHYs.
menuconfig PHY_AQUANTIA
bool "Aquantia Ethernet PHYs support"
@@ -126,9 +126,9 @@ config SYS_CORTINA_NO_FW_UPLOAD
bool "Cortina firmware loading support"
depends on PHY_CORTINA
help
- Cortina phy has provision to store phy firmware in attached dedicated
- EEPROM. And boards designed with such EEPROM does not require firmware
- upload.
+ Cortina phy has provision to store phy firmware in attached dedicated
+ EEPROM. And boards designed with such EEPROM does not require firmware
+ upload.
choice
prompt "Location of the Cortina firmware"
@@ -167,7 +167,7 @@ config PHY_CORTINA_ACCESS
default y
depends on CORTINA_NI_ENET
help
- Cortina Access Ethernet PHYs init process
+ Cortina Access Ethernet PHYs init process
config PHY_DAVICOM
bool "Davicom Ethernet PHYs support"
@@ -317,13 +317,13 @@ config PHY_TERANETICS
config PHY_TI
bool "Texas Instruments Ethernet PHYs support"
- ---help---
+ help
Adds PHY registration support for TI PHYs.
config PHY_TI_DP83867
select PHY_TI
bool "Texas Instruments Ethernet DP83867 PHY support"
- ---help---
+ help
Adds support for the TI DP83867 1Gbit PHY.
config SPL_PHY_TI_DP83867
@@ -333,13 +333,13 @@ config SPL_PHY_TI_DP83867
config PHY_TI_DP83869
select PHY_TI
bool "Texas Instruments Ethernet DP83869 PHY support"
- ---help---
+ help
Adds support for the TI DP83869 1Gbit PHY.
config PHY_TI_GENERIC
select PHY_TI
bool "Texas Instruments Generic Ethernet PHYs support"
- ---help---
+ help
Adds support for Generic TI PHYs that don't need special handling but
the PHY name is associated with a PHY ID.
diff --git a/drivers/net/phy/airoha/Kconfig b/drivers/net/phy/airoha/Kconfig
index 4139df343ad..2d58d674200 100644
--- a/drivers/net/phy/airoha/Kconfig
+++ b/drivers/net/phy/airoha/Kconfig
@@ -2,12 +2,25 @@
menuconfig PHY_AIROHA
bool "Airoha Ethernet PHYs support"
+config PHY_AIROHA_AN8801
+ bool "Airoha Ethernet AN8801 support"
+ depends on PHY_AIROHA
+ select PHY_AIROHA_PHYLIB
+ help
+ Currently support AIROHA AN8801 1G PHY.
+
config PHY_AIROHA_EN8811
bool "Airoha Ethernet EN8811H support"
depends on PHY_AIROHA
depends on SUPPORTS_FW_LOADER
select FW_LOADER
+ select PHY_AIROHA_PHYLIB
select PHY_COMMON_PROPS
help
AIROHA EN8811H supported.
AIROHA AN8811HB supported.
+
+config PHY_AIROHA_PHYLIB
+ bool
+ help
+ Airoha Ethernet PHY common library
diff --git a/drivers/net/phy/airoha/Makefile b/drivers/net/phy/airoha/Makefile
index 84d23b19ab0..25e44004cfd 100644
--- a/drivers/net/phy/airoha/Makefile
+++ b/drivers/net/phy/airoha/Makefile
@@ -1,3 +1,5 @@
# SPDX-License-Identifier: GPL-2.0
+obj-$(CONFIG_PHY_AIROHA_AN8801) += air_an8801.o
obj-$(CONFIG_PHY_AIROHA_EN8811) += air_en8811.o
+obj-$(CONFIG_PHY_AIROHA_PHYLIB) += air_phy_lib.o
diff --git a/drivers/net/phy/airoha/air_an8801.c b/drivers/net/phy/airoha/air_an8801.c
new file mode 100644
index 00000000000..9d9958fc665
--- /dev/null
+++ b/drivers/net/phy/airoha/air_an8801.c
@@ -0,0 +1,594 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * air_an8801.c - PHY driver for Airoha AN8801.
+ * Copyright (c) 2026 Airoha Technology Corp.
+ * Copyright (C) 2026 BayLibre, SAS.
+ * Author: Kevin-KW Huang <[email protected]>
+ * Sita Huang <[email protected]>
+ * Julien Stephan <[email protected]>
+ */
+
+#include <malloc.h>
+#include <phy.h>
+#include <dm/device_compat.h>
+
+#include "air_phy_lib.h"
+
+#define AN8801R_PHY_ID1 0xc0ff
+#define AN8801R_PHY_ID2 0x0421
+#define AN8801R_PHY_ID ((u32)((AN8801R_PHY_ID1 << 16) | AN8801R_PHY_ID2))
+
+#define AN8801R_MAX_LED_SIZE 3
+
+/* MII Registers - Airoha Page 4 */
+#define AN8801_PBUS_ACCESS BIT(28)
+
+/* BPBUS Registers */
+#define AN8801_BPBUS_REG_LED_GPIO 0x54
+#define AN8801_BPBUS_REG_LED_ID_SEL 0x58
+#define LED_ID_GPIO_SEL(led, gpio) ((led) << ((gpio) * 3))
+
+#define AN8801_BPBUS_REG_GPIO_MODE 0x70
+
+#define AN8801_BPBUS_REG_LINK_MODE 0x5054
+#define AN8801_BPBUS_LINK_MODE_1000 BIT(0)
+
+#define AN8801_BPBUS_REG_BYPASS_PTP 0x21c004
+#define AN8801_BYP_PTP_RGMII_TO_GPHY BIT(0)
+
+#define AN8801_BPBUS_REG_TXDLY_STEP 0x21c024
+#define RGMII_DELAY_STEP_MASK GENMASK(2, 0)
+#define AIR_RGMII_DELAY_NOSTEP 0
+#define AIR_RGMII_DELAY_STEP_1 1
+#define AIR_RGMII_DELAY_STEP_2 2
+#define AIR_RGMII_DELAY_STEP_3 3
+#define AIR_RGMII_DELAY_STEP_4 4
+#define AIR_RGMII_DELAY_STEP_5 5
+#define AIR_RGMII_DELAY_STEP_6 6
+#define AIR_RGMII_DELAY_STEP_7 7
+#define RGMII_TXDELAY_FORCE_MODE BIT(24)
+
+#define AN8801_BPBUS_REG_RXDLY_STEP 0x21c02c
+#define RGMII_RXDELAY_ALIGN BIT(4)
+#define RGMII_RXDELAY_FORCE_MODE BIT(24)
+
+#define AN8801_BPBUS_REG_EFIFO_CTL(x) (0x270004 + (0x100 * (x))) /* 0..2 */
+#define AN8801_EFIFO_ALL_EN GENMASK(7, 0)
+#define AN8801_EFIFO_RX_EN BIT(0)
+#define AN8801_EFIFO_TX_EN BIT(1)
+#define AN8801_EFIFO_RX_CLK_EN BIT(2)
+#define AN8801_EFIFO_TX_CLK_EN BIT(3)
+#define AN8801_EFIFO_RX_EEE_EN BIT(4)
+#define AN8801_EFIFO_TX_EEE_EN BIT(5)
+#define AN8801_EFIFO_RX_ODD_NIBBLE_EN BIT(6)
+#define AN8801_EFIFO_TX_ODD_NIBBLE_EN BIT(7)
+
+#define AN8801_BPBUS_REG_HWRST_DE_GLITCH 0xc8
+#define AN8801_DE_GLITCH_EN BIT(2)
+#define AN8801_11_CYCLE_XTAL_PERIOD_DE_GLITCH GENMASK(1, 0)
+
+#define LED_BCR 0x21
+#define LED_BCR_MODE_MASK GENMASK(1, 0)
+#define LED_BCR_TIME_TEST BIT(2)
+#define LED_BCR_CLK_EN BIT(3)
+#define LED_BCR_EVT_ALL BIT(4)
+#define LED_BCR_EXT_CTRL BIT(15)
+#define LED_BCR_MODE_DISABLE 0
+#define LED_BCR_MODE_2LED 1
+#define LED_BCR_MODE_3LED_1 2
+#define LED_BCR_MODE_3LED_2 3
+
+#define LED_ON_DUR 0x22
+#define LED_ON_DUR_MASK GENMASK(15, 0)
+
+#define LED_BLINK_DUR 0x23
+#define LED_BLINK_DUR_MASK GENMASK(15, 0)
+
+#define LED_ON_CTRL(i) (0x024 + ((i) * 2))
+#define LED_ON_EVT_MASK GENMASK(6, 0)
+#define LED_ON_EVT_LINK_1000M BIT(0)
+#define LED_ON_EVT_LINK_100M BIT(1)
+#define LED_ON_EVT_LINK_10M BIT(2)
+#define LED_ON_EVT_LINK_DN BIT(3)
+#define LED_ON_EVT_FDX BIT(4)
+#define LED_ON_EVT_HDX BIT(5)
+#define LED_ON_EVT_FORCE BIT(6)
+#define LED_ON_POL BIT(14)
+#define LED_ON_EN BIT(15)
+
+#define LED_BLINK_CTRL(i) (0x025 + ((i) * 2))
+#define LED_BLINK_EVT_MASK GENMASK(9, 0)
+#define LED_BLINK_EVT_1000M_TX BIT(0)
+#define LED_BLINK_EVT_1000M_RX BIT(1)
+#define LED_BLINK_EVT_100M_TX BIT(2)
+#define LED_BLINK_EVT_100M_RX BIT(3)
+#define LED_BLINK_EVT_10M_TX BIT(4)
+#define LED_BLINK_EVT_10M_RX BIT(5)
+#define LED_BLINK_EVT_FORCE BIT(9)
+
+#define UNIT_LED_BLINK_DURATION 780
+#define LED_BLINK_DURATION(f) (UNIT_LED_BLINK_DURATION << (f))
+
+/* Link on(1G/100M/10M), no activity */
+#define AIR_LED0_ON \
+ (LED_ON_EVT_LINK_1000M | LED_ON_EVT_LINK_100M | LED_ON_EVT_LINK_10M)
+#define AIR_LED0_BLINK 0x0
+/* No link on, activity(1G/100M/10M TX/RX) */
+#define AIR_LED1_ON 0x0
+#define AIR_LED1_BLINK \
+ (LED_BLINK_EVT_1000M_TX | LED_BLINK_EVT_1000M_RX | \
+ LED_BLINK_EVT_100M_TX | LED_BLINK_EVT_100M_RX | \
+ LED_BLINK_EVT_10M_TX | LED_BLINK_EVT_10M_RX)
+/* Link on(100M/10M), activity(100M/10M TX/RX) */
+#define AIR_LED2_ON \
+ (LED_ON_EVT_LINK_100M | LED_ON_EVT_LINK_10M)
+#define AIR_LED2_BLINK \
+ (LED_BLINK_EVT_100M_TX | LED_BLINK_EVT_100M_RX | \
+ LED_BLINK_EVT_10M_TX | LED_BLINK_EVT_10M_RX)
+
+#define INVALID_DATA GENMASK(31, 0)
+
+#define AN8801_REG_PHY_INTERNAL0 0x600
+#define AN8801_REG_PHY_INTERNAL1 0x601
+
+#define AN8801_LED_ENABLE 1
+
+enum air_led_gpio_pin {
+ AIR_LED_GPIO1 = 1,
+ AIR_LED_GPIO2,
+ AIR_LED_GPIO3
+};
+
+enum air_led {
+ AIR_LED0 = 0,
+ AIR_LED1,
+ AIR_LED2,
+ AIR_LED3
+};
+
+enum air_led_blink_dut {
+ AIR_LED_BLINK_DUR_32M = 0,
+ AIR_LED_BLINK_DUR_64M,
+ AIR_LED_BLINK_DUR_128M,
+ AIR_LED_BLINK_DUR_256M,
+ AIR_LED_BLINK_DUR_512M,
+ AIR_LED_BLINK_DUR_1024M,
+ AIR_LED_BLINK_DUR_LAST
+};
+
+enum air_led_polarity {
+ AIR_ACTIVE_LOW = 0,
+ AIR_ACTIVE_HIGH,
+};
+
+enum air_led_mode {
+ AIR_LED_MODE_DISABLE = 0,
+ AIR_LED_MODE_USER_DEFINE,
+ AIR_LED_MODE_LAST
+};
+
+struct air_led_cfg {
+ u16 led_en;
+ u16 gpio;
+ u16 led_polarity;
+ u16 led_on_cfg;
+ u16 led_blk_cfg;
+};
+
+struct an8801r_priv {
+ struct air_led_cfg led_cfg[AN8801R_MAX_LED_SIZE];
+ u32 led_blink_cfg;
+ u8 rxdelay_force;
+ u8 txdelay_force;
+ u16 rxdelay_step;
+ u8 rxdelay_align;
+ u16 txdelay_step;
+};
+
+#define phydev_cfg(phy) ((struct an8801r_priv *)(phy)->priv)
+
+/*
+ * GPIO1 <-> LED0,
+ * GPIO2 <-> LED1,
+ * GPIO3 <-> LED2,
+ */
+static const struct an8801r_priv an8801r_priv_defaults = {
+ .led_cfg = {
+ /* LED Enable, GPIO, LED Polarity, LED ON, LED Blink */
+ {AN8801_LED_ENABLE, AIR_LED_GPIO1, AIR_ACTIVE_LOW, AIR_LED0_ON, AIR_LED0_BLINK},
+ {AN8801_LED_ENABLE, AIR_LED_GPIO2, AIR_ACTIVE_HIGH, AIR_LED1_ON, AIR_LED1_BLINK},
+ {AN8801_LED_ENABLE, AIR_LED_GPIO3, AIR_ACTIVE_HIGH, AIR_LED2_ON, AIR_LED2_BLINK},
+ },
+ .led_blink_cfg = AIR_LED_BLINK_DUR_64M,
+ .rxdelay_force = false,
+ .txdelay_force = false,
+ .rxdelay_step = AIR_RGMII_DELAY_NOSTEP,
+ .rxdelay_align = false,
+ .txdelay_step = AIR_RGMII_DELAY_NOSTEP,
+};
+
+static int an8801_buckpbus_reg_rmw(struct phy_device *phydev,
+ u32 addr, u32 mask, u32 set)
+{
+ return air_phy_buckpbus_reg_modify(phydev,
+ addr | AN8801_PBUS_ACCESS,
+ mask, set);
+}
+
+static int an8801_buckpbus_reg_set_bits(struct phy_device *phydev,
+ u32 addr, u32 mask)
+{
+ return air_phy_buckpbus_reg_modify(phydev,
+ addr | AN8801_PBUS_ACCESS,
+ mask, mask);
+}
+
+static int an8801_buckpbus_reg_clear_bits(struct phy_device *phydev,
+ u32 addr, u32 mask)
+{
+ return air_phy_buckpbus_reg_modify(phydev,
+ addr | AN8801_PBUS_ACCESS,
+ mask, 0);
+}
+
+static int an8801_buckpbus_reg_write(struct phy_device *phydev, u32 addr, u32 data)
+{
+ return air_phy_buckpbus_reg_write(phydev, addr | AN8801_PBUS_ACCESS, data);
+}
+
+static int an8801r_led_set_usr_def(struct phy_device *phydev, u8 entity,
+ u16 polar, u16 on_evt, u16 blk_evt)
+{
+ int ret;
+
+ if (polar == AIR_ACTIVE_HIGH)
+ on_evt |= LED_ON_POL;
+ else
+ on_evt &= ~LED_ON_POL;
+
+ on_evt |= LED_ON_EN;
+
+ ret = phy_write_mmd(phydev, MDIO_MMD_VEND2, LED_ON_CTRL(entity), on_evt);
+ if (ret)
+ return ret;
+
+ return phy_write_mmd(phydev, MDIO_MMD_VEND2, LED_BLINK_CTRL(entity), blk_evt);
+}
+
+static int an8801r_led_set_blink(struct phy_device *phydev, u16 blink)
+{
+ int ret;
+
+ ret = phy_write_mmd(phydev, MDIO_MMD_VEND2, LED_BLINK_DUR,
+ LED_BLINK_DURATION(blink));
+ if (ret)
+ return ret;
+
+ return phy_write_mmd(phydev, MDIO_MMD_VEND2, LED_ON_DUR,
+ LED_BLINK_DURATION(blink) / 2);
+}
+
+static int an8801r_led_set_mode(struct phy_device *phydev, u8 mode)
+{
+ int ret;
+
+ ret = phy_read_mmd(phydev, MDIO_MMD_VEND2, LED_BCR);
+ if (ret < 0)
+ return ret;
+
+ switch (mode) {
+ case AIR_LED_MODE_DISABLE:
+ ret &= ~LED_BCR_EXT_CTRL;
+ ret &= ~LED_BCR_MODE_MASK;
+ ret |= LED_BCR_MODE_DISABLE;
+ break;
+ case AIR_LED_MODE_USER_DEFINE:
+ ret |= LED_BCR_EXT_CTRL | LED_BCR_CLK_EN;
+ break;
+ }
+ return phy_write_mmd(phydev, MDIO_MMD_VEND2, LED_BCR, ret);
+}
+
+static int an8801r_led_set_state(struct phy_device *phydev, u8 entity, u8 state)
+{
+ int ret;
+
+ ret = phy_read_mmd(phydev, MDIO_MMD_VEND2, LED_ON_CTRL(entity));
+ if (ret < 0)
+ return ret;
+
+ if (state)
+ ret |= LED_ON_EN;
+ else
+ ret &= ~LED_ON_EN;
+
+ return phy_write_mmd(phydev, MDIO_MMD_VEND2, LED_ON_CTRL(entity), ret);
+}
+
+static int an8801r_led_init(struct phy_device *phydev)
+{
+ struct an8801r_priv *priv = phydev_cfg(phydev);
+ struct air_led_cfg *led_cfg = priv->led_cfg;
+ u16 led_blink_cfg = priv->led_blink_cfg;
+ int ret, led_id;
+
+ ret = an8801r_led_set_blink(phydev, led_blink_cfg);
+ if (ret)
+ return ret;
+
+ ret = an8801r_led_set_mode(phydev, AIR_LED_MODE_USER_DEFINE);
+ if (ret) {
+ dev_err(phydev->dev, "AN8801R: Fail to set LED mode, ret %d!\n", ret);
+ return ret;
+ }
+
+ for (led_id = AIR_LED0; led_id < AN8801R_MAX_LED_SIZE; led_id++) {
+ ret = an8801r_led_set_state(phydev, led_id, led_cfg[led_id].led_en);
+ if (ret) {
+ dev_err(phydev->dev, "AN8801R: Fail to set LED%d state, ret %d!\n",
+ led_id, ret);
+ return ret;
+ }
+
+ if (!led_cfg[led_id].led_en)
+ continue;
+
+ ret = an8801_buckpbus_reg_set_bits(phydev, AN8801_BPBUS_REG_LED_GPIO,
+ BIT(led_cfg[led_id].gpio));
+ if (ret)
+ return ret;
+
+ ret = an8801_buckpbus_reg_set_bits(phydev, AN8801_BPBUS_REG_LED_ID_SEL,
+ LED_ID_GPIO_SEL(led_id,
+ led_cfg[led_id].gpio));
+ if (ret)
+ return ret;
+
+ ret = an8801_buckpbus_reg_clear_bits(phydev, AN8801_BPBUS_REG_GPIO_MODE,
+ BIT(led_cfg[led_id].gpio));
+ if (ret)
+ return ret;
+
+ ret = an8801r_led_set_usr_def(phydev, led_id,
+ led_cfg[led_id].led_polarity,
+ led_cfg[led_id].led_on_cfg,
+ led_cfg[led_id].led_blk_cfg);
+ if (ret) {
+ dev_err(phydev->dev, "AN8801R: Fail to set LED%d, ret %d!\n",
+ led_id, ret);
+ return ret;
+ }
+ }
+ return 0;
+}
+
+static int an8801r_of_init(struct phy_device *phydev)
+{
+ struct an8801r_priv *priv = phydev_cfg(phydev);
+ ofnode node = phy_get_ofnode(phydev);
+ u32 val = 0;
+ int ret;
+
+ if (!ofnode_valid(node))
+ return -EINVAL;
+
+ if (ofnode_has_property(node, "airoha,rxclk-delay")) {
+ ret = ofnode_read_u32(node, "airoha,rxclk-delay", &val);
+ if (ret) {
+ dev_err(phydev->dev, "airoha,rxclk-delay value is invalid.\n");
+ return ret;
+ }
+ if (val > AIR_RGMII_DELAY_STEP_7) {
+ dev_err(phydev->dev, "airoha,rxclk-delay value %u out of range.\n", val);
+ return -EINVAL;
+ }
+ priv->rxdelay_force = true;
+ priv->rxdelay_step = val;
+ priv->rxdelay_align = ofnode_read_bool(node,
+ "airoha,rxclk-delay-align");
+ }
+
+ if (ofnode_has_property(node, "airoha,txclk-delay")) {
+ ret = ofnode_read_u32(node, "airoha,txclk-delay", &val);
+ if (ret) {
+ dev_err(phydev->dev, "airoha,txclk-delay value is invalid.\n");
+ return ret;
+ }
+ if (val > AIR_RGMII_DELAY_STEP_7) {
+ dev_err(phydev->dev, "airoha,txclk-delay value %u out of range.\n", val);
+ return -EINVAL;
+ }
+ priv->txdelay_force = true;
+ priv->txdelay_step = val;
+ }
+ return 0;
+}
+
+static int an8801r_rgmii_rxdelay(struct phy_device *phydev, u16 delay, u8 align)
+{
+ u32 reg_val = delay & RGMII_DELAY_STEP_MASK;
+ int ret;
+
+ if (align) {
+ reg_val |= RGMII_RXDELAY_ALIGN;
+ debug("AN8801R: Rxdelay align\n");
+ }
+ reg_val |= RGMII_RXDELAY_FORCE_MODE;
+ ret = an8801_buckpbus_reg_write(phydev, AN8801_BPBUS_REG_RXDLY_STEP, reg_val);
+ if (ret)
+ return ret;
+
+ debug("AN8801R: Force rxdelay = %d(0x%x)\n", delay, reg_val);
+ return 0;
+}
+
+static int an8801r_rgmii_txdelay(struct phy_device *phydev, u16 delay)
+{
+ u32 reg_val = delay & RGMII_DELAY_STEP_MASK;
+ int ret;
+
+ reg_val |= RGMII_TXDELAY_FORCE_MODE;
+ ret = an8801_buckpbus_reg_write(phydev, AN8801_BPBUS_REG_TXDLY_STEP, reg_val);
+ if (ret)
+ return ret;
+
+ debug("AN8801R: Force txdelay = %d(0x%x)\n", delay, reg_val);
+ return 0;
+}
+
+static int an8801r_rgmii_delay_config(struct phy_device *phydev)
+{
+ struct an8801r_priv *priv = phydev_cfg(phydev);
+ int ret;
+
+ switch (phydev->interface) {
+ case PHY_INTERFACE_MODE_RGMII_TXID:
+ return an8801r_rgmii_txdelay(phydev, AIR_RGMII_DELAY_STEP_4);
+ case PHY_INTERFACE_MODE_RGMII_RXID:
+ return an8801r_rgmii_rxdelay(phydev, AIR_RGMII_DELAY_NOSTEP, true);
+ case PHY_INTERFACE_MODE_RGMII_ID:
+ ret = an8801r_rgmii_txdelay(phydev, AIR_RGMII_DELAY_STEP_4);
+ if (ret)
+ return ret;
+ return an8801r_rgmii_rxdelay(phydev, AIR_RGMII_DELAY_NOSTEP, true);
+ case PHY_INTERFACE_MODE_RGMII:
+ default:
+ if (priv->rxdelay_force) {
+ ret = an8801r_rgmii_rxdelay(phydev, priv->rxdelay_step,
+ priv->rxdelay_align);
+ if (ret)
+ return ret;
+ }
+ if (priv->txdelay_force)
+ return an8801r_rgmii_txdelay(phydev, priv->txdelay_step);
+ return 0;
+ }
+}
+
+static int an8801r_config_init(struct phy_device *phydev)
+{
+ int ret;
+
+ ret = an8801r_of_init(phydev);
+ if (ret < 0)
+ return ret;
+
+ ret = an8801_buckpbus_reg_write(phydev, AN8801_BPBUS_REG_HWRST_DE_GLITCH,
+ AN8801_DE_GLITCH_EN |
+ AN8801_11_CYCLE_XTAL_PERIOD_DE_GLITCH);
+ if (ret)
+ return ret;
+
+ ret = phy_write_mmd(phydev, MDIO_MMD_VEND2, AN8801_REG_PHY_INTERNAL0, 0x1e);
+ if (ret)
+ return ret;
+
+ ret = phy_write_mmd(phydev, MDIO_MMD_VEND2, AN8801_REG_PHY_INTERNAL1, 0x02);
+ if (ret)
+ return ret;
+
+ ret = phy_write_mmd(phydev, MDIO_MMD_AN, MDIO_AN_EEE_ADV, 0x0);
+ if (ret)
+ return ret;
+
+ ret = an8801_buckpbus_reg_write(phydev, AN8801_BPBUS_REG_BYPASS_PTP,
+ AN8801_BYP_PTP_RGMII_TO_GPHY);
+ if (ret)
+ return ret;
+
+ ret = an8801_buckpbus_reg_write(phydev, AN8801_BPBUS_REG_EFIFO_CTL(0),
+ AN8801_EFIFO_RX_EN |
+ AN8801_EFIFO_TX_EN |
+ AN8801_EFIFO_RX_CLK_EN |
+ AN8801_EFIFO_TX_CLK_EN |
+ AN8801_EFIFO_RX_EEE_EN |
+ AN8801_EFIFO_TX_EEE_EN);
+ if (ret)
+ return ret;
+
+ ret = an8801_buckpbus_reg_write(phydev, AN8801_BPBUS_REG_EFIFO_CTL(1),
+ AN8801_EFIFO_ALL_EN);
+ if (ret)
+ return ret;
+
+ ret = an8801_buckpbus_reg_write(phydev, AN8801_BPBUS_REG_EFIFO_CTL(2),
+ AN8801_EFIFO_ALL_EN);
+ if (ret)
+ return ret;
+
+ ret = an8801r_rgmii_delay_config(phydev);
+ if (ret)
+ return ret;
+
+ ret = an8801r_led_init(phydev);
+ if (ret) {
+ dev_err(phydev->dev, "AN8801R: LED initialize fail, ret %d!\n", ret);
+ return ret;
+ }
+ return 0;
+}
+
+static int an8801r_phy_probe(struct phy_device *phydev)
+{
+ struct an8801r_priv *priv;
+ u32 phy_id;
+ int ret;
+
+ ret = get_phy_id(phydev->bus, phydev->addr, MDIO_DEVAD_NONE, &phy_id);
+ if (ret)
+ return ret;
+
+ if (phy_id != AN8801R_PHY_ID) {
+ dev_err(phydev->dev,
+ "AN8801R can't be detected (id=0x%08x).\n", phy_id);
+ return -ENODEV;
+ }
+
+ priv = malloc(sizeof(*priv));
+ if (!priv)
+ return -ENOMEM;
+
+ *priv = an8801r_priv_defaults;
+
+ phydev->priv = priv;
+
+ return 0;
+}
+
+static int an8801r_read_status(struct phy_device *phydev)
+{
+ u32 data;
+
+ if (!phydev->link)
+ return 0;
+
+ debug("AN8801R: SPEED %d\n", phydev->speed);
+ data = phydev->speed == SPEED_1000 ? AN8801_BPBUS_LINK_MODE_1000 : 0;
+
+ return an8801_buckpbus_reg_rmw(phydev, AN8801_BPBUS_REG_LINK_MODE,
+ AN8801_BPBUS_LINK_MODE_1000, data);
+}
+
+static int an8801r_startup(struct phy_device *phydev)
+{
+ int ret;
+
+ ret = genphy_startup(phydev);
+ if (ret)
+ return ret;
+
+ return an8801r_read_status(phydev);
+}
+
+U_BOOT_PHY_DRIVER(an8801r) = {
+ .name = "Airoha AN8801R",
+ .uid = AN8801R_PHY_ID,
+ .mask = 0x0ffffff0,
+ .features = PHY_GBIT_FEATURES,
+ .probe = &an8801r_phy_probe,
+ .config = &an8801r_config_init,
+ .read_page = &air_phy_read_page,
+ .write_page = &air_phy_write_page,
+ .startup = &an8801r_startup,
+ .shutdown = &genphy_shutdown,
+};
diff --git a/drivers/net/phy/airoha/air_en8811.c b/drivers/net/phy/airoha/air_en8811.c
index 32f06dd6dfa..7a07be2e956 100644
--- a/drivers/net/phy/airoha/air_en8811.c
+++ b/drivers/net/phy/airoha/air_en8811.c
@@ -25,6 +25,8 @@
#include <u-boot/crc.h>
#include <linux/phy/phy-common-props.h>
+#include "air_phy_lib.h"
+
/* MII Registers */
#define AIR_AUX_CTRL_STATUS 0x1d
#define AIR_AUX_CTRL_STATUS_SPEED_MASK GENMASK(4, 2)
@@ -33,10 +35,6 @@
#define AIR_AUX_CTRL_STATUS_SPEED_1000 0x8
#define AIR_AUX_CTRL_STATUS_SPEED_2500 0xc
-#define AIR_EXT_PAGE_ACCESS 0x1f
-#define AIR_PHY_PAGE_STANDARD 0x0000
-#define AIR_PHY_PAGE_EXTENDED_4 0x0004
-
#define AIR_PBUS_MODE_ADDR_HIGH 0x1c
/* MII Registers Page 4 */
#define AIR_BPBUS_MODE 0x10
@@ -310,166 +308,6 @@ static int air_pbus_reg_write(struct phy_device *phydev,
return ret;
}
-static int air_buckpbus_reg_write(struct phy_device *phydev,
- u32 pbus_address, u32 pbus_data)
-{
- int ret, saved_page;
-
- saved_page = phy_select_page(phydev, AIR_PHY_PAGE_EXTENDED_4);
- if (saved_page < 0)
- return saved_page;
-
- ret = phy_write(phydev, MDIO_DEVAD_NONE, AIR_BPBUS_MODE,
- AIR_BPBUS_MODE_ADDR_FIXED);
- if (ret < 0)
- goto restore_page;
-
- ret = phy_write(phydev, MDIO_DEVAD_NONE, AIR_BPBUS_WR_ADDR_HIGH,
- upper_16_bits(pbus_address));
- if (ret < 0)
- goto restore_page;
-
- ret = phy_write(phydev, MDIO_DEVAD_NONE, AIR_BPBUS_WR_ADDR_LOW,
- lower_16_bits(pbus_address));
- if (ret < 0)
- goto restore_page;
-
- ret = phy_write(phydev, MDIO_DEVAD_NONE, AIR_BPBUS_WR_DATA_HIGH,
- upper_16_bits(pbus_data));
- if (ret < 0)
- goto restore_page;
-
- ret = phy_write(phydev, MDIO_DEVAD_NONE, AIR_BPBUS_WR_DATA_LOW,
- lower_16_bits(pbus_data));
- if (ret < 0)
- goto restore_page;
-
-restore_page:
- if (ret < 0)
- dev_err(phydev->dev, "%s 0x%08x failed: %d\n", __func__,
- pbus_address, ret);
-
- return phy_restore_page(phydev, saved_page, ret);
-}
-
-static int air_buckpbus_reg_read(struct phy_device *phydev,
- u32 pbus_address, u32 *pbus_data)
-{
- int pbus_data_low, pbus_data_high;
- int ret = 0, saved_page;
-
- saved_page = phy_select_page(phydev, AIR_PHY_PAGE_EXTENDED_4);
- if (saved_page < 0)
- return saved_page;
-
- ret = phy_write(phydev, MDIO_DEVAD_NONE, AIR_BPBUS_MODE,
- AIR_BPBUS_MODE_ADDR_FIXED);
- if (ret < 0)
- goto restore_page;
-
- ret = phy_write(phydev, MDIO_DEVAD_NONE, AIR_BPBUS_RD_ADDR_HIGH,
- upper_16_bits(pbus_address));
- if (ret < 0)
- goto restore_page;
-
- ret = phy_write(phydev, MDIO_DEVAD_NONE, AIR_BPBUS_RD_ADDR_LOW,
- lower_16_bits(pbus_address));
- if (ret < 0)
- goto restore_page;
-
- pbus_data_high = phy_read(phydev, MDIO_DEVAD_NONE, AIR_BPBUS_RD_DATA_HIGH);
- if (pbus_data_high < 0) {
- ret = pbus_data_high;
- goto restore_page;
- }
-
- pbus_data_low = phy_read(phydev, MDIO_DEVAD_NONE, AIR_BPBUS_RD_DATA_LOW);
- if (pbus_data_low < 0) {
- ret = pbus_data_low;
- goto restore_page;
- }
-
- *pbus_data = pbus_data_low | (pbus_data_high << 16);
-
-restore_page:
- if (ret < 0)
- dev_err(phydev->dev, "%s 0x%08x failed: %d\n", __func__,
- pbus_address, ret);
-
- return phy_restore_page(phydev, saved_page, ret);
-}
-
-static int air_buckpbus_reg_modify(struct phy_device *phydev,
- u32 pbus_address, u32 mask, u32 set)
-{
- int pbus_data_low, pbus_data_high;
- u32 pbus_data_old, pbus_data_new;
- int ret = 0, saved_page;
-
- saved_page = phy_select_page(phydev, AIR_PHY_PAGE_EXTENDED_4);
- if (saved_page < 0)
- return saved_page;
-
- ret = phy_write(phydev, MDIO_DEVAD_NONE, AIR_BPBUS_MODE,
- AIR_BPBUS_MODE_ADDR_FIXED);
- if (ret < 0)
- goto restore_page;
-
- ret = phy_write(phydev, MDIO_DEVAD_NONE, AIR_BPBUS_RD_ADDR_HIGH,
- upper_16_bits(pbus_address));
- if (ret < 0)
- goto restore_page;
-
- ret = phy_write(phydev, MDIO_DEVAD_NONE, AIR_BPBUS_RD_ADDR_LOW,
- lower_16_bits(pbus_address));
- if (ret < 0)
- goto restore_page;
-
- pbus_data_high = phy_read(phydev, MDIO_DEVAD_NONE, AIR_BPBUS_RD_DATA_HIGH);
- if (pbus_data_high < 0) {
- ret = pbus_data_high;
- goto restore_page;
- }
-
- pbus_data_low = phy_read(phydev, MDIO_DEVAD_NONE, AIR_BPBUS_RD_DATA_LOW);
- if (pbus_data_low < 0) {
- ret = pbus_data_low;
- goto restore_page;
- }
-
- pbus_data_old = pbus_data_low | (pbus_data_high << 16);
- pbus_data_new = (pbus_data_old & ~mask) | set;
- if (pbus_data_new == pbus_data_old)
- goto restore_page;
-
- ret = phy_write(phydev, MDIO_DEVAD_NONE, AIR_BPBUS_WR_ADDR_HIGH,
- upper_16_bits(pbus_address));
- if (ret < 0)
- goto restore_page;
-
- ret = phy_write(phydev, MDIO_DEVAD_NONE, AIR_BPBUS_WR_ADDR_LOW,
- lower_16_bits(pbus_address));
- if (ret < 0)
- goto restore_page;
-
- ret = phy_write(phydev, MDIO_DEVAD_NONE, AIR_BPBUS_WR_DATA_HIGH,
- upper_16_bits(pbus_data_new));
- if (ret < 0)
- goto restore_page;
-
- ret = phy_write(phydev, MDIO_DEVAD_NONE, AIR_BPBUS_WR_DATA_LOW,
- lower_16_bits(pbus_data_new));
- if (ret < 0)
- goto restore_page;
-
-restore_page:
- if (ret < 0)
- dev_err(phydev->dev, "%s 0x%08x failed: %d\n", __func__,
- pbus_address, ret);
-
- return phy_restore_page(phydev, saved_page, ret);
-}
-
static int air_write_buf(struct phy_device *phydev, unsigned long address,
unsigned long array_size, const unsigned char *buffer)
{
@@ -540,12 +378,12 @@ static int an8811hb_check_crc(struct phy_device *phydev,
u32 pbus_value;
/* Configure CRC */
- ret = air_buckpbus_reg_modify(phydev, set1, AN8811HB_CRC_RD_EN,
- AN8811HB_CRC_RD_EN);
+ ret = air_phy_buckpbus_reg_modify(phydev, set1, AN8811HB_CRC_RD_EN,
+ AN8811HB_CRC_RD_EN);
if (ret < 0)
return ret;
- ret = air_buckpbus_reg_read(phydev, set1, &pbus_value);
+ ret = air_phy_buckpbus_reg_read(phydev, set1, &pbus_value);
if (ret < 0)
return ret;
@@ -554,14 +392,14 @@ static int an8811hb_check_crc(struct phy_device *phydev,
do {
mdelay(300);
- ret = air_buckpbus_reg_read(phydev, mon2, &pbus_value);
+ ret = air_phy_buckpbus_reg_read(phydev, mon2, &pbus_value);
if (ret < 0)
return ret;
debug("%d: reg 0x%x val 0x%x!\n", __LINE__, mon2, pbus_value);
if (pbus_value & AN8811HB_CRC_ST) {
- ret = air_buckpbus_reg_read(phydev, mon3, &pbus_value);
+ ret = air_phy_buckpbus_reg_read(phydev, mon3, &pbus_value);
if (ret < 0)
return ret;
@@ -585,11 +423,11 @@ static int an8811hb_check_crc(struct phy_device *phydev,
}
} while (--retry);
- ret = air_buckpbus_reg_modify(phydev, set1, AN8811HB_CRC_RD_EN, 0);
+ ret = air_phy_buckpbus_reg_modify(phydev, set1, AN8811HB_CRC_RD_EN, 0);
if (ret < 0)
return ret;
- ret = air_buckpbus_reg_read(phydev, set1, &pbus_value);
+ ret = air_phy_buckpbus_reg_read(phydev, set1, &pbus_value);
if (ret < 0)
return ret;
@@ -647,9 +485,9 @@ static int an8811hb_surge_protect_cfg(struct phy_device *phydev)
return ret;
}
- ret = air_buckpbus_reg_modify(phydev, AIR_PHY_CONTROL,
- AIR_PHY_CONTROL_SURGE_5R,
- AIR_PHY_CONTROL_SURGE_5R);
+ ret = air_phy_buckpbus_reg_modify(phydev, AIR_PHY_CONTROL,
+ AIR_PHY_CONTROL_SURGE_5R,
+ AIR_PHY_CONTROL_SURGE_5R);
if (ret < 0)
return ret;
@@ -707,14 +545,14 @@ static int en8811h_load_firmware(struct phy_device *phydev)
goto en8811h_load_firmware_out;
}
- ret = air_buckpbus_reg_write(phydev, EN8811H_FW_CTRL_1,
- EN8811H_FW_CTRL_1_START);
+ ret = air_phy_buckpbus_reg_write(phydev, EN8811H_FW_CTRL_1,
+ EN8811H_FW_CTRL_1_START);
if (ret < 0)
goto en8811h_load_firmware_out;
- ret = air_buckpbus_reg_modify(phydev, EN8811H_FW_CTRL_2,
- EN8811H_FW_CTRL_2_LOADING,
- EN8811H_FW_CTRL_2_LOADING);
+ ret = air_phy_buckpbus_reg_modify(phydev, EN8811H_FW_CTRL_2,
+ EN8811H_FW_CTRL_2_LOADING,
+ EN8811H_FW_CTRL_2_LOADING);
if (ret < 0)
goto en8811h_load_firmware_out;
@@ -728,13 +566,13 @@ static int en8811h_load_firmware(struct phy_device *phydev)
if (ret < 0)
goto en8811h_load_firmware_out;
- ret = air_buckpbus_reg_modify(phydev, EN8811H_FW_CTRL_2,
- EN8811H_FW_CTRL_2_LOADING, 0);
+ ret = air_phy_buckpbus_reg_modify(phydev, EN8811H_FW_CTRL_2,
+ EN8811H_FW_CTRL_2_LOADING, 0);
if (ret < 0)
goto en8811h_load_firmware_out;
- ret = air_buckpbus_reg_write(phydev, EN8811H_FW_CTRL_1,
- EN8811H_FW_CTRL_1_FINISH);
+ ret = air_phy_buckpbus_reg_write(phydev, EN8811H_FW_CTRL_1,
+ EN8811H_FW_CTRL_1_FINISH);
if (ret < 0)
goto en8811h_load_firmware_out;
@@ -742,8 +580,8 @@ static int en8811h_load_firmware(struct phy_device *phydev)
if (ret < 0)
goto en8811h_load_firmware_out;
- air_buckpbus_reg_read(phydev, EN8811H_FW_VERSION,
- &priv->firmware_version);
+ air_phy_buckpbus_reg_read(phydev, EN8811H_FW_VERSION,
+ &priv->firmware_version);
dev_info(phydev->dev, "MD32 firmware version: %08x\n",
priv->firmware_version);
@@ -779,8 +617,8 @@ static int an8811hb_load_firmware(struct phy_device *phydev)
if (ret < 0)
goto an8811hb_load_firmware_out;
- ret = air_buckpbus_reg_write(phydev, AIR_PHY_FW_CTRL_1,
- AIR_PHY_FW_CTRL_1_START);
+ ret = air_phy_buckpbus_reg_write(phydev, AIR_PHY_FW_CTRL_1,
+ AIR_PHY_FW_CTRL_1_START);
if (ret < 0)
goto an8811hb_load_firmware_out;
@@ -804,8 +642,8 @@ static int an8811hb_load_firmware(struct phy_device *phydev)
if (ret < 0)
goto an8811hb_load_firmware_out;
- ret = air_buckpbus_reg_write(phydev, AIR_PHY_FW_CTRL_1,
- AIR_PHY_FW_CTRL_1_FINISH);
+ ret = air_phy_buckpbus_reg_write(phydev, AIR_PHY_FW_CTRL_1,
+ AIR_PHY_FW_CTRL_1_FINISH);
if (ret < 0)
goto an8811hb_load_firmware_out;
@@ -818,7 +656,7 @@ static int an8811hb_load_firmware(struct phy_device *phydev)
do {
mdelay(300);
- ret = air_buckpbus_reg_read(phydev, AIR_PHY_FW_CTRL_1, &reg_val);
+ ret = air_phy_buckpbus_reg_read(phydev, AIR_PHY_FW_CTRL_1, &reg_val);
if (ret < 0)
goto an8811hb_load_firmware_out;
@@ -828,8 +666,8 @@ static int an8811hb_load_firmware(struct phy_device *phydev)
debug("%d: reg 0x%x val 0x%x!\n", __LINE__, AIR_PHY_FW_CTRL_1,
reg_val);
- ret = air_buckpbus_reg_write(phydev, AIR_PHY_FW_CTRL_1,
- AIR_PHY_FW_CTRL_1_FINISH);
+ ret = air_phy_buckpbus_reg_write(phydev, AIR_PHY_FW_CTRL_1,
+ AIR_PHY_FW_CTRL_1_FINISH);
if (ret < 0)
goto an8811hb_load_firmware_out;
@@ -839,8 +677,8 @@ static int an8811hb_load_firmware(struct phy_device *phydev)
if (ret < 0)
goto an8811hb_load_firmware_out;
- air_buckpbus_reg_read(phydev, AIR_PHY_MD32FW_VERSION,
- &priv->firmware_version);
+ air_phy_buckpbus_reg_read(phydev, AIR_PHY_MD32FW_VERSION,
+ &priv->firmware_version);
debug("MD32 firmware version: %08x\n", priv->firmware_version);
@@ -859,17 +697,17 @@ int an8811hb_cko_cfg(struct phy_device *phydev)
int ret = 0;
if (!ofnode_read_bool(node, "airoha,phy-output-clock")) {
- ret = air_buckpbus_reg_modify(phydev, AN8811HB_CLK_DRV,
- AN8811HB_CLK_DRV_CKO_MASK,
- AN8811HB_CLK_DRV_CKOPWD |
- AN8811HB_CLK_DRV_CKO_LDPWD |
- AN8811HB_CLK_DRV_CKO_LPPWD);
+ ret = air_phy_buckpbus_reg_modify(phydev, AN8811HB_CLK_DRV,
+ AN8811HB_CLK_DRV_CKO_MASK,
+ AN8811HB_CLK_DRV_CKOPWD |
+ AN8811HB_CLK_DRV_CKO_LDPWD |
+ AN8811HB_CLK_DRV_CKO_LPPWD);
if (ret < 0)
return ret;
debug("CKO Output mode - Disabled\n");
} else {
- ret = air_buckpbus_reg_read(phydev, AN8811HB_HWTRAP2, &pbus_value);
+ ret = air_phy_buckpbus_reg_read(phydev, AN8811HB_HWTRAP2, &pbus_value);
if (ret < 0)
return ret;
@@ -888,13 +726,13 @@ static int en8811h_restart_mcu(struct phy_device *phydev)
if (ret < 0)
return ret;
- ret = air_buckpbus_reg_write(phydev, EN8811H_FW_CTRL_1,
- EN8811H_FW_CTRL_1_START);
+ ret = air_phy_buckpbus_reg_write(phydev, EN8811H_FW_CTRL_1,
+ EN8811H_FW_CTRL_1_START);
if (ret < 0)
return ret;
- return air_buckpbus_reg_write(phydev, EN8811H_FW_CTRL_1,
- EN8811H_FW_CTRL_1_FINISH);
+ return air_phy_buckpbus_reg_write(phydev, EN8811H_FW_CTRL_1,
+ EN8811H_FW_CTRL_1_FINISH);
}
static int air_led_hw_control_set(struct phy_device *phydev, u8 index,
@@ -1083,9 +921,10 @@ static int en8811h_config_serdes_polarity(struct phy_device *phydev)
if (pol == PHY_POL_NORMAL)
pbus_value |= EN8811H_POLARITY_TX_NORMAL;
- return air_buckpbus_reg_modify(phydev, EN8811H_POLARITY,
- EN8811H_POLARITY_RX_REVERSE |
- EN8811H_POLARITY_TX_NORMAL, pbus_value);
+ return air_phy_buckpbus_reg_modify(phydev, EN8811H_POLARITY,
+ EN8811H_POLARITY_RX_REVERSE |
+ EN8811H_POLARITY_TX_NORMAL,
+ pbus_value);
}
static int en8811h_config(struct phy_device *phydev)
@@ -1170,12 +1009,12 @@ static int an8811hb_config(struct phy_device *phydev)
priv->mcu_needs_restart = true;
}
- ret = air_buckpbus_reg_read(phydev, AN8811HB_PRO_ID, &pbus_value);
+ ret = air_phy_buckpbus_reg_read(phydev, AN8811HB_PRO_ID, &pbus_value);
if (ret < 0)
return ret;
priv->pro_id = (pbus_value & AN8811HB_PRO_ID_VERSION) + 1;
- ret = air_buckpbus_reg_read(phydev, AN8811HB_HWTRAP2, &pbus_value);
+ ret = air_phy_buckpbus_reg_read(phydev, AN8811HB_HWTRAP2, &pbus_value);
if (ret < 0)
return ret;
priv->pkg_sel = (pbus_value & AN8811HB_HWTRAP2_PKG) >> 12;
@@ -1191,8 +1030,8 @@ static int an8811hb_config(struct phy_device *phydev)
pbus_value |= AN8811HB_RX_POLARITY_NORMAL;
debug("1 pbus_value 0x%x\n", pbus_value);
- ret = air_buckpbus_reg_modify(phydev, AN8811HB_RX_POLARITY,
- AN8811HB_RX_POLARITY_NORMAL, pbus_value);
+ ret = air_phy_buckpbus_reg_modify(phydev, AN8811HB_RX_POLARITY,
+ AN8811HB_RX_POLARITY_NORMAL, pbus_value);
if (ret < 0)
return ret;
@@ -1203,35 +1042,35 @@ static int an8811hb_config(struct phy_device *phydev)
pbus_value |= AN8811HB_TX_POLARITY_NORMAL;
debug("2 pbus_value 0x%x\n", pbus_value);
- ret = air_buckpbus_reg_modify(phydev, AN8811HB_TX_POLARITY,
- AN8811HB_TX_POLARITY_NORMAL, pbus_value);
+ ret = air_phy_buckpbus_reg_modify(phydev, AN8811HB_TX_POLARITY,
+ AN8811HB_TX_POLARITY_NORMAL, pbus_value);
if (ret < 0)
return ret;
/* Configure led gpio pins as output */
if (priv->pkg_sel) {
- ret = air_buckpbus_reg_modify(phydev, AN8811HB_GPIO_OUTPUT,
- AN8811HB_GPIO_OUTPUT_MASK,
- AN8811HB_GPIO_OUTPUT_0115);
+ ret = air_phy_buckpbus_reg_modify(phydev, AN8811HB_GPIO_OUTPUT,
+ AN8811HB_GPIO_OUTPUT_MASK,
+ AN8811HB_GPIO_OUTPUT_0115);
if (ret < 0)
return ret;
- ret = air_buckpbus_reg_modify(phydev, AN8811HB_GPIO_SEL_1,
- AN8811HB_GPIO_SEL_1_0_MASK |
- AN8811HB_GPIO_SEL_1_1_MASK,
- AN8811HB_GPIO_SEL_1_0 |
- AN8811HB_GPIO_SEL_1_1);
+ ret = air_phy_buckpbus_reg_modify(phydev, AN8811HB_GPIO_SEL_1,
+ AN8811HB_GPIO_SEL_1_0_MASK |
+ AN8811HB_GPIO_SEL_1_1_MASK,
+ AN8811HB_GPIO_SEL_1_0 |
+ AN8811HB_GPIO_SEL_1_1);
if (ret < 0)
return ret;
- ret = air_buckpbus_reg_modify(phydev, AN8811HB_GPIO_SEL_2,
- AN8811HB_GPIO_SEL_2_15_MASK,
- AN8811HB_GPIO_SEL_2_15);
+ ret = air_phy_buckpbus_reg_modify(phydev, AN8811HB_GPIO_SEL_2,
+ AN8811HB_GPIO_SEL_2_15_MASK,
+ AN8811HB_GPIO_SEL_2_15);
if (ret < 0)
return ret;
} else {
- ret = air_buckpbus_reg_modify(phydev, AN8811HB_GPIO_OUTPUT,
- AN8811HB_GPIO_OUTPUT_345,
- AN8811HB_GPIO_OUTPUT_345);
+ ret = air_phy_buckpbus_reg_modify(phydev, AN8811HB_GPIO_OUTPUT,
+ AN8811HB_GPIO_OUTPUT_345,
+ AN8811HB_GPIO_OUTPUT_345);
if (ret < 0)
return ret;
}
@@ -1401,16 +1240,6 @@ static int en8811h_probe(struct phy_device *phydev)
return 0;
}
-static int air_phy_read_page(struct phy_device *phydev)
-{
- return phy_read(phydev, MDIO_DEVAD_NONE, AIR_EXT_PAGE_ACCESS);
-}
-
-static int air_phy_write_page(struct phy_device *phydev, int page)
-{
- return phy_write(phydev, MDIO_DEVAD_NONE, AIR_EXT_PAGE_ACCESS, page);
-}
-
U_BOOT_PHY_DRIVER(en8811h) = {
.name = "Airoha EN8811H",
.uid = EN8811H_PHY_ID,
diff --git a/drivers/net/phy/airoha/air_phy_lib.c b/drivers/net/phy/airoha/air_phy_lib.c
new file mode 100644
index 00000000000..61c3bf82822
--- /dev/null
+++ b/drivers/net/phy/airoha/air_phy_lib.c
@@ -0,0 +1,216 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Airoha Ethernet PHY common library
+ *
+ * Copyright (C) 2026 Airoha Technology Corp.
+ * Copyright (C) 2026 Collabora Ltd.
+ * Louis-Alexis Eyraud <[email protected]>
+ *
+ * Adapated from https://lore.kernel.org/all/20260326-add-airoha-an8801-support-v2-2-1a42d6b6050f@collabora.com/
+ */
+
+#include <dm/device_compat.h>
+#include <linux/compat.h>
+#include <phy.h>
+
+#include "air_phy_lib.h"
+
+#define AIR_EXT_PAGE_ACCESS 0x1f
+
+static int __air_buckpbus_reg_read(struct phy_device *phydev,
+ u32 pbus_address, u32 *pbus_data)
+{
+ int pbus_data_low, pbus_data_high;
+ int ret;
+
+ ret = phy_write(phydev, MDIO_DEVAD_NONE, AIR_BPBUS_MODE,
+ AIR_BPBUS_MODE_ADDR_FIXED);
+ if (ret < 0)
+ return ret;
+
+ ret = phy_write(phydev, MDIO_DEVAD_NONE, AIR_BPBUS_RD_ADDR_HIGH,
+ upper_16_bits(pbus_address));
+ if (ret < 0)
+ return ret;
+
+ ret = phy_write(phydev, MDIO_DEVAD_NONE, AIR_BPBUS_RD_ADDR_LOW,
+ lower_16_bits(pbus_address));
+ if (ret < 0)
+ return ret;
+
+ pbus_data_high = phy_read(phydev, MDIO_DEVAD_NONE,
+ AIR_BPBUS_RD_DATA_HIGH);
+ if (pbus_data_high < 0)
+ return pbus_data_high;
+
+ pbus_data_low = phy_read(phydev, MDIO_DEVAD_NONE,
+ AIR_BPBUS_RD_DATA_LOW);
+ if (pbus_data_low < 0)
+ return pbus_data_low;
+
+ *pbus_data = pbus_data_low | (pbus_data_high << 16);
+ return 0;
+}
+
+static int __air_buckpbus_reg_write(struct phy_device *phydev,
+ u32 pbus_address, u32 pbus_data)
+{
+ int ret;
+
+ ret = phy_write(phydev, MDIO_DEVAD_NONE, AIR_BPBUS_MODE,
+ AIR_BPBUS_MODE_ADDR_FIXED);
+ if (ret < 0)
+ return ret;
+
+ ret = phy_write(phydev, MDIO_DEVAD_NONE, AIR_BPBUS_WR_ADDR_HIGH,
+ upper_16_bits(pbus_address));
+ if (ret < 0)
+ return ret;
+
+ ret = phy_write(phydev, MDIO_DEVAD_NONE, AIR_BPBUS_WR_ADDR_LOW,
+ lower_16_bits(pbus_address));
+ if (ret < 0)
+ return ret;
+
+ ret = phy_write(phydev, MDIO_DEVAD_NONE, AIR_BPBUS_WR_DATA_HIGH,
+ upper_16_bits(pbus_data));
+ if (ret < 0)
+ return ret;
+
+ ret = phy_write(phydev, MDIO_DEVAD_NONE, AIR_BPBUS_WR_DATA_LOW,
+ lower_16_bits(pbus_data));
+ if (ret < 0)
+ return ret;
+
+ return 0;
+}
+
+static int __air_buckpbus_reg_modify(struct phy_device *phydev,
+ u32 pbus_address, u32 mask, u32 set)
+{
+ int pbus_data_low, pbus_data_high;
+ u32 pbus_data_old, pbus_data_new;
+ int ret;
+
+ ret = phy_write(phydev, MDIO_DEVAD_NONE, AIR_BPBUS_MODE,
+ AIR_BPBUS_MODE_ADDR_FIXED);
+ if (ret < 0)
+ return ret;
+
+ ret = phy_write(phydev, MDIO_DEVAD_NONE, AIR_BPBUS_RD_ADDR_HIGH,
+ upper_16_bits(pbus_address));
+ if (ret < 0)
+ return ret;
+
+ ret = phy_write(phydev, MDIO_DEVAD_NONE, AIR_BPBUS_RD_ADDR_LOW,
+ lower_16_bits(pbus_address));
+ if (ret < 0)
+ return ret;
+
+ pbus_data_high = phy_read(phydev, MDIO_DEVAD_NONE,
+ AIR_BPBUS_RD_DATA_HIGH);
+ if (pbus_data_high < 0)
+ return pbus_data_high;
+
+ pbus_data_low = phy_read(phydev, MDIO_DEVAD_NONE,
+ AIR_BPBUS_RD_DATA_LOW);
+ if (pbus_data_low < 0)
+ return pbus_data_low;
+
+ pbus_data_old = pbus_data_low | (pbus_data_high << 16);
+ pbus_data_new = (pbus_data_old & ~mask) | set;
+ if (pbus_data_new == pbus_data_old)
+ return 0;
+
+ ret = phy_write(phydev, MDIO_DEVAD_NONE, AIR_BPBUS_WR_ADDR_HIGH,
+ upper_16_bits(pbus_address));
+ if (ret < 0)
+ return ret;
+
+ ret = phy_write(phydev, MDIO_DEVAD_NONE, AIR_BPBUS_WR_ADDR_LOW,
+ lower_16_bits(pbus_address));
+ if (ret < 0)
+ return ret;
+
+ ret = phy_write(phydev, MDIO_DEVAD_NONE, AIR_BPBUS_WR_DATA_HIGH,
+ upper_16_bits(pbus_data_new));
+ if (ret < 0)
+ return ret;
+
+ ret = phy_write(phydev, MDIO_DEVAD_NONE, AIR_BPBUS_WR_DATA_LOW,
+ lower_16_bits(pbus_data_new));
+ if (ret < 0)
+ return ret;
+
+ return 0;
+}
+
+int air_phy_buckpbus_reg_read(struct phy_device *phydev, u32 pbus_address,
+ u32 *pbus_data)
+{
+ int saved_page;
+ int ret = 0;
+
+ saved_page = phy_select_page(phydev, AIR_PHY_PAGE_EXTENDED_4);
+
+ if (saved_page >= 0) {
+ ret = __air_buckpbus_reg_read(phydev, pbus_address, pbus_data);
+ if (ret < 0)
+ dev_err(phydev->dev, "%s 0x%08x failed: %d\n", __func__,
+ pbus_address, ret);
+ }
+
+ return phy_restore_page(phydev, saved_page, ret);
+}
+
+int air_phy_buckpbus_reg_write(struct phy_device *phydev, u32 pbus_address,
+ u32 pbus_data)
+{
+ int saved_page;
+ int ret = 0;
+
+ saved_page = phy_select_page(phydev, AIR_PHY_PAGE_EXTENDED_4);
+
+ if (saved_page >= 0) {
+ ret = __air_buckpbus_reg_write(phydev, pbus_address,
+ pbus_data);
+ if (ret < 0)
+ dev_err(phydev->dev, "%s 0x%08x failed: %d\n", __func__,
+ pbus_address, ret);
+ }
+
+ return phy_restore_page(phydev, saved_page, ret);
+}
+
+int air_phy_buckpbus_reg_modify(struct phy_device *phydev, u32 pbus_address,
+ u32 mask, u32 set)
+{
+ int saved_page;
+ int ret = 0;
+
+ saved_page = phy_select_page(phydev, AIR_PHY_PAGE_EXTENDED_4);
+
+ if (saved_page >= 0) {
+ ret = __air_buckpbus_reg_modify(phydev, pbus_address, mask,
+ set);
+ if (ret < 0)
+ dev_err(phydev->dev, "%s 0x%08x failed: %d\n", __func__,
+ pbus_address, ret);
+ }
+
+ return phy_restore_page(phydev, saved_page, ret);
+}
+
+int air_phy_read_page(struct phy_device *phydev)
+{
+ return phy_read(phydev, MDIO_DEVAD_NONE, AIR_EXT_PAGE_ACCESS);
+}
+
+int air_phy_write_page(struct phy_device *phydev, int page)
+{
+ return phy_write(phydev, MDIO_DEVAD_NONE, AIR_EXT_PAGE_ACCESS, page);
+}
+
+MODULE_DESCRIPTION("Airoha PHY Library");
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Louis-Alexis Eyraud");
diff --git a/drivers/net/phy/airoha/air_phy_lib.h b/drivers/net/phy/airoha/air_phy_lib.h
new file mode 100644
index 00000000000..845d2f7cfb4
--- /dev/null
+++ b/drivers/net/phy/airoha/air_phy_lib.h
@@ -0,0 +1,39 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * Copyright (C) 2026 Airoha Technology Corp.
+ * Copyright (C) 2026 Collabora Ltd.
+ * Louis-Alexis Eyraud <[email protected]>
+ */
+
+#ifndef __AIR_PHY_LIB_H
+#define __AIR_PHY_LIB_H
+
+#define AIR_EXT_PAGE_ACCESS 0x1f
+
+#define AIR_PHY_PAGE_STANDARD 0x0000
+#define AIR_PHY_PAGE_EXTENDED_1 0x0001
+#define AIR_PHY_PAGE_EXTENDED_4 0x0004
+
+/* MII Registers Page 4*/
+#define AIR_BPBUS_MODE 0x10
+#define AIR_BPBUS_MODE_ADDR_FIXED 0x0000
+#define AIR_BPBUS_MODE_ADDR_INCR BIT(15)
+#define AIR_BPBUS_WR_ADDR_HIGH 0x11
+#define AIR_BPBUS_WR_ADDR_LOW 0x12
+#define AIR_BPBUS_WR_DATA_HIGH 0x13
+#define AIR_BPBUS_WR_DATA_LOW 0x14
+#define AIR_BPBUS_RD_ADDR_HIGH 0x15
+#define AIR_BPBUS_RD_ADDR_LOW 0x16
+#define AIR_BPBUS_RD_DATA_HIGH 0x17
+#define AIR_BPBUS_RD_DATA_LOW 0x18
+
+int air_phy_buckpbus_reg_modify(struct phy_device *phydev, u32 pbus_address,
+ u32 mask, u32 set);
+int air_phy_buckpbus_reg_read(struct phy_device *phydev, u32 pbus_address,
+ u32 *pbus_data);
+int air_phy_buckpbus_reg_write(struct phy_device *phydev, u32 pbus_address,
+ u32 pbus_data);
+int air_phy_read_page(struct phy_device *phydev);
+int air_phy_write_page(struct phy_device *phydev, int page);
+
+#endif /* __AIR_PHY_LIB_H */
diff --git a/drivers/net/phy/nxp-c45-tja11xx.c b/drivers/net/phy/nxp-c45-tja11xx.c
index a1e4c3d053b..9814ac498ed 100644
--- a/drivers/net/phy/nxp-c45-tja11xx.c
+++ b/drivers/net/phy/nxp-c45-tja11xx.c
@@ -343,7 +343,7 @@ static int nxp_c45_probe(struct phy_device *phydev)
{
struct nxp_c45_phy *priv;
- priv = devm_kzalloc(phydev->priv, sizeof(*priv), GFP_KERNEL);
+ priv = kzalloc(sizeof(*priv), GFP_KERNEL);
if (!priv)
return -ENOMEM;
diff --git a/drivers/net/qe/dm_qe_uec.c b/drivers/net/qe/dm_qe_uec.c
index ac3aedd8b49..f9bc5d49c8f 100644
--- a/drivers/net/qe/dm_qe_uec.c
+++ b/drivers/net/qe/dm_qe_uec.c
@@ -1133,7 +1133,7 @@ static int qe_uec_of_to_plat(struct udevice *dev)
{
struct eth_pdata *pdata = dev_get_plat(dev);
- pdata->iobase = (phys_addr_t)devfdt_get_addr(dev);
+ pdata->iobase = (phys_addr_t)dev_read_addr(dev);
pdata->phy_interface = dev_read_phy_mode(dev);
if (pdata->phy_interface == PHY_INTERFACE_MODE_NA)
diff --git a/drivers/net/rtl8169.c b/drivers/net/rtl8169.c
index 5b093623619..e203faed26b 100644
--- a/drivers/net/rtl8169.c
+++ b/drivers/net/rtl8169.c
@@ -404,7 +404,7 @@ static int rtl8169_init_board(unsigned long dev_iobase, const char *name)
u32 tmp;
#ifdef DEBUG_RTL8169
- printf ("%s\n", __FUNCTION__);
+ printf("%s\n", __func__);
#endif
ioaddr = dev_iobase;
@@ -534,7 +534,7 @@ static int rtl_recv_common(struct udevice *dev, unsigned long dev_iobase,
int length = 0;
#ifdef DEBUG_RTL8169_RX
- printf ("%s\n", __FUNCTION__);
+ printf("%s\n", __func__);
#endif
ioaddr = dev_iobase;
@@ -608,7 +608,7 @@ static int rtl_send_common(struct udevice *dev, unsigned long dev_iobase,
#ifdef DEBUG_RTL8169_TX
int stime = currticks();
- printf ("%s\n", __FUNCTION__);
+ printf("%s\n", __func__);
printf("sending %d bytes\n", len);
#endif
@@ -679,7 +679,7 @@ static void rtl8169_set_rx_mode(void)
u32 tmp = 0;
#ifdef DEBUG_RTL8169
- printf ("%s\n", __FUNCTION__);
+ printf("%s\n", __func__);
#endif
/* IFF_ALLMULTI */
@@ -701,7 +701,7 @@ static void rtl8169_hw_start(struct udevice *dev)
#ifdef DEBUG_RTL8169
int stime = currticks();
- printf ("%s\n", __FUNCTION__);
+ printf("%s\n", __func__);
#endif
#if 0
@@ -771,7 +771,7 @@ static void rtl8169_init_ring(struct udevice *dev)
#ifdef DEBUG_RTL8169
int stime = currticks();
- printf ("%s\n", __FUNCTION__);
+ printf("%s\n", __func__);
#endif
tpc->cur_rx = 0;
@@ -810,7 +810,7 @@ static void rtl8169_common_start(struct udevice *dev, unsigned char *enetaddr,
#ifdef DEBUG_RTL8169
int stime = currticks();
- printf ("%s\n", __FUNCTION__);
+ printf("%s\n", __func__);
#endif
ioaddr = dev_iobase;
@@ -851,7 +851,7 @@ static void rtl_halt_common(struct udevice *dev)
int i;
#ifdef DEBUG_RTL8169
- printf ("%s\n", __FUNCTION__);
+ printf("%s\n", __func__);
#endif
ioaddr = priv->iobase;
@@ -906,7 +906,7 @@ static int rtl_init(unsigned long dev_ioaddr, const char *name,
int option = -1, Cap10_100 = 0, Cap1000 = 0;
#ifdef DEBUG_RTL8169
- printf ("%s\n", __FUNCTION__);
+ printf("%s\n", __func__);
#endif
ioaddr = dev_ioaddr;
diff --git a/drivers/net/ti/Kconfig b/drivers/net/ti/Kconfig
index 93c3a0c35f2..2d72af8aade 100644
--- a/drivers/net/ti/Kconfig
+++ b/drivers/net/ti/Kconfig
@@ -14,7 +14,7 @@ config DRIVER_TI_EMAC
bool "TI Davinci EMAC"
depends on ARCH_DAVINCI || ARCH_OMAP2PLUS
help
- Support for davinci emac
+ Support for davinci emac
config DRIVER_TI_EMAC_USE_RMII
depends on DRIVER_TI_EMAC
@@ -26,7 +26,7 @@ config DRIVER_TI_KEYSTONE_NET
bool "TI Keystone 2 Ethernet"
depends on ARCH_KEYSTONE
help
- This driver supports the TI Keystone 2 Ethernet subsystem
+ This driver supports the TI Keystone 2 Ethernet subsystem
choice
prompt "TI Keystone 2 Ethernet NETCP IP revision"
diff --git a/drivers/net/tsec.c b/drivers/net/tsec.c
index bd4ebdd745a..d03368b9408 100644
--- a/drivers/net/tsec.c
+++ b/drivers/net/tsec.c
@@ -37,6 +37,23 @@
)
#endif /* CFG_TSEC_TBICR_SETTINGS */
+struct tsec_private {
+ struct txbd8 __iomem txbd[TX_BUF_CNT];
+ struct rxbd8 __iomem rxbd[PKTBUFSRX];
+ struct tsec __iomem *regs;
+ struct tsec_mii_mng __iomem *phyregs_sgmii;
+ struct phy_device *phydev;
+ phy_interface_t interface;
+ struct mii_dev *bus;
+ uint phyaddr;
+ uint tbiaddr;
+ char mii_devname[16];
+ u32 flags;
+ uint rx_idx; /* index of the current RX buffer */
+ uint tx_idx; /* index of the current TX buffer */
+ struct udevice *dev;
+};
+
/* Configure the TBI for SGMII operation */
static void tsec_configure_serdes(struct tsec_private *priv)
{