summaryrefslogtreecommitdiff
path: root/drivers
diff options
context:
space:
mode:
authorTom Rini <[email protected]>2025-10-22 09:07:56 -0600
committerTom Rini <[email protected]>2025-10-22 09:07:56 -0600
commit29a96acaa3a84c68264d8dcf2182000bce71175e (patch)
treeabd59b96eeb5783eb0ec7bb43423c3910a328502 /drivers
parentb21ba014a9e51ae33916ec17786fdb03587ed9b6 (diff)
parented6ec8d1ca0658d811df1cc78d06fec4f7f69fc9 (diff)
Merge tag 'net-20251022' of https://source.denx.de/u-boot/custodians/u-boot-net
Pull request net-20251022 net: - airoha: improvements - Tighten a few more driver dependencies - designware: fix bitbang init error - phy: Make driver overloading get_phy_id depend on !COMPILE_TEST - phy: add paged PHY register accessors - make dhcp_run() common for NET and NET_LWIP - dwc_eth_ops: Correct check for FDT_64BIT - mediatek: mt7988: various fixup + MDIO detach - phy: aquantia: switch to use phy_get_ofnode(), fix bindings typo net-legacy: - bootp: Prevent buffer overflow to avoid leaking the RAM content - tftp: make TFTP ports unconditionally configurable misc: - uthreads: Make use of CONFIG_IS_ENABLED consistently
Diffstat (limited to 'drivers')
-rw-r--r--drivers/net/Kconfig10
-rw-r--r--drivers/net/Makefile1
-rw-r--r--drivers/net/airoha_eth.c40
-rw-r--r--drivers/net/designware.c12
-rw-r--r--drivers/net/mdio-mt7531-mmio.c168
-rw-r--r--drivers/net/mdio-mt7531-mmio.h9
-rw-r--r--drivers/net/mtk_eth/Kconfig2
-rw-r--r--drivers/net/mtk_eth/mt7531.c20
-rw-r--r--drivers/net/mtk_eth/mt7988.c92
-rw-r--r--drivers/net/phy/Kconfig2
-rw-r--r--drivers/net/phy/aquantia.c2
-rw-r--r--drivers/net/phy/phy.c113
-rw-r--r--drivers/power/domain/Kconfig2
13 files changed, 421 insertions, 52 deletions
diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig
index 7ae28c4e0d5..c9b35b5a2ff 100644
--- a/drivers/net/Kconfig
+++ b/drivers/net/Kconfig
@@ -179,7 +179,7 @@ config CALXEDA_XGMAC
machines.
config DWC_ETH_XGMAC
- bool "Synopsys DWC Ethernet XGMAC device support"
+ bool
select PHYLIB
help
This driver supports the Synopsys Designware Ethernet XGMAC (10G
@@ -190,7 +190,8 @@ config DWC_ETH_XGMAC_SOCFPGA
bool "Synopsys DWC Ethernet XGMAC device support for SOCFPGA"
select REGMAP
select SYSCON
- depends on DWC_ETH_XGMAC
+ select DWC_ETH_XGMAC
+ depends on ARCH_SOCFPGA
default y if TARGET_SOCFPGA_AGILEX5
help
The Synopsys Designware Ethernet XGMAC IP block with specific
@@ -376,7 +377,7 @@ config ETH_DESIGNWARE_SOCFPGA
select SYSCON
select DW_ALTDESCRIPTOR
bool "Altera SoCFPGA extras for Synopsys Designware Ethernet MAC"
- depends on ETH_DESIGNWARE
+ depends on ARCH_SOCFPGA && ETH_DESIGNWARE
help
The Altera SoCFPGA requires additional configuration of the
Altera system manager to correctly interface with the PHY.
@@ -966,6 +967,9 @@ config TSEC_ENET
This driver implements support for the (Enhanced) Three-Speed
Ethernet Controller found on Freescale SoCs.
+config MDIO_MT7531_MMIO
+ bool
+
source "drivers/net/mtk_eth/Kconfig"
config HIFEMAC_ETH
diff --git a/drivers/net/Makefile b/drivers/net/Makefile
index f8f9a71f815..a3c3420898c 100644
--- a/drivers/net/Makefile
+++ b/drivers/net/Makefile
@@ -63,6 +63,7 @@ obj-$(CONFIG_MACB) += macb.o
obj-$(CONFIG_MCFFEC) += mcffec.o mcfmii.o
obj-$(CONFIG_MDIO_IPQ4019) += mdio-ipq4019.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
obj-$(CONFIG_MDIO_MUX_MESON_GXL) += mdio_mux_meson_gxl.o
diff --git a/drivers/net/airoha_eth.c b/drivers/net/airoha_eth.c
index 6588eb3a806..19c3d60044c 100644
--- a/drivers/net/airoha_eth.c
+++ b/drivers/net/airoha_eth.c
@@ -449,14 +449,10 @@ static int airoha_qdma_init_rx_queue(struct airoha_queue *q,
RX_RING_SIZE_MASK,
FIELD_PREP(RX_RING_SIZE_MASK, ndesc));
- /*
- * See arht_eth_free_pkt() for the reasons used to fill
- * REG_RX_CPU_IDX(qid) register.
- */
airoha_qdma_rmw(qdma, REG_RX_RING_SIZE(qid), RX_RING_THR_MASK,
FIELD_PREP(RX_RING_THR_MASK, 0));
airoha_qdma_rmw(qdma, REG_RX_CPU_IDX(qid), RX_RING_CPU_IDX_MASK,
- FIELD_PREP(RX_RING_CPU_IDX_MASK, q->ndesc - 3));
+ FIELD_PREP(RX_RING_CPU_IDX_MASK, q->ndesc - 1));
airoha_qdma_rmw(qdma, REG_RX_DMA_IDX(qid), RX_RING_DMA_IDX_MASK,
FIELD_PREP(RX_RING_DMA_IDX_MASK, q->head));
@@ -920,7 +916,6 @@ static int arht_eth_free_pkt(struct udevice *dev, uchar *packet, int length)
struct airoha_qdma *qdma = &eth->qdma[0];
struct airoha_queue *q;
int qid;
- u16 prev, pprev;
if (!packet)
return 0;
@@ -930,22 +925,29 @@ static int arht_eth_free_pkt(struct udevice *dev, uchar *packet, int length)
/*
* Due to cpu cache issue the airoha_qdma_reset_rx_desc() function
- * will always touch 2 descriptors:
- * - if current descriptor is even, then the previous and the one
- * before previous descriptors will be touched (previous cacheline)
- * - if current descriptor is odd, then only current and previous
- * descriptors will be touched (current cacheline)
+ * will always touch 2 descriptors placed on the same cacheline:
+ * - if current descriptor is even, then current and next
+ * descriptors will be touched
+ * - if current descriptor is odd, then current and previous
+ * descriptors will be touched
*
- * Thus, to prevent possible destroying of rx queue, only (q->ndesc - 2)
- * descriptors might be used for packet receiving.
+ * Thus, to prevent possible destroying of rx queue, we should:
+ * - do nothing in the even descriptor case,
+ * - utilize 2 descriptors (current and previous one) in the
+ * odd descriptor case.
+ *
+ * WARNING: Observations shows that PKTBUFSRX must be even and
+ * larger than 7 for reliable driver operations.
*/
- prev = (q->head + q->ndesc - 1) % q->ndesc;
- pprev = (q->head + q->ndesc - 2) % q->ndesc;
- q->head = (q->head + 1) % q->ndesc;
+ if (q->head & 0x01) {
+ airoha_qdma_reset_rx_desc(q, q->head - 1);
+ airoha_qdma_reset_rx_desc(q, q->head);
- airoha_qdma_reset_rx_desc(q, prev);
- airoha_qdma_rmw(qdma, REG_RX_CPU_IDX(qid), RX_RING_CPU_IDX_MASK,
- FIELD_PREP(RX_RING_CPU_IDX_MASK, pprev));
+ airoha_qdma_rmw(qdma, REG_RX_CPU_IDX(qid), RX_RING_CPU_IDX_MASK,
+ FIELD_PREP(RX_RING_CPU_IDX_MASK, q->head));
+ }
+
+ q->head = (q->head + 1) % q->ndesc;
return 0;
}
diff --git a/drivers/net/designware.c b/drivers/net/designware.c
index 2fd92cf16bb..6ed9c6d538a 100644
--- a/drivers/net/designware.c
+++ b/drivers/net/designware.c
@@ -125,6 +125,16 @@ static int dw_mdio_reset(struct mii_dev *bus)
return __dw_mdio_reset(dev);
}
+
+#if IS_ENABLED(CONFIG_BITBANGMII)
+static int dw_bb_mdio_reset(struct mii_dev *bus)
+{
+ struct dw_eth_dev *priv = bus->priv;
+
+ return __dw_mdio_reset(priv->dev);
+}
+#endif
+
#endif
#if IS_ENABLED(CONFIG_DM_MDIO)
@@ -348,7 +358,7 @@ static int dw_bb_mdio_init(const char *name, struct udevice *dev)
bus->read = dw_bb_miiphy_read;
bus->write = dw_bb_miiphy_write;
#if CONFIG_IS_ENABLED(DM_GPIO)
- bus->reset = dw_mdio_reset;
+ bus->reset = dw_bb_mdio_reset;
#endif
bus->priv = dwpriv;
diff --git a/drivers/net/mdio-mt7531-mmio.c b/drivers/net/mdio-mt7531-mmio.c
new file mode 100644
index 00000000000..3e325ca58da
--- /dev/null
+++ b/drivers/net/mdio-mt7531-mmio.c
@@ -0,0 +1,168 @@
+// SPDX-License-Identifier: GPL-2.0+
+
+#include <asm/io.h>
+#include <dm.h>
+#include <linux/bitfield.h>
+#include <linux/iopoll.h>
+#include <miiphy.h>
+
+#define MT7531_PHY_IAC 0x701c
+#define MT7531_PHY_ACS_ST BIT(31)
+#define MT7531_MDIO_REG_ADDR_CL22 GENMASK(29, 25)
+#define MT7531_MDIO_DEV_ADDR MT7531_MDIO_REG_ADDR_CL22
+#define MT7531_MDIO_PHY_ADDR GENMASK(24, 20)
+#define MT7531_MDIO_CMD GENMASK(19, 18)
+#define MT7531_MDIO_CMD_READ_CL45 FIELD_PREP_CONST(MT7531_MDIO_CMD, 0x3)
+#define MT7531_MDIO_CMD_READ_CL22 FIELD_PREP_CONST(MT7531_MDIO_CMD, 0x2)
+#define MT7531_MDIO_CMD_WRITE FIELD_PREP_CONST(MT7531_MDIO_CMD, 0x1)
+#define MT7531_MDIO_CMD_ADDR FIELD_PREP_CONST(MT7531_MDIO_CMD, 0x0)
+#define MT7531_MDIO_ST GENMASK(17, 16)
+#define MT7531_MDIO_ST_CL22 FIELD_PREP_CONST(MT7531_MDIO_ST, 0x1)
+#define MT7531_MDIO_ST_CL45 FIELD_PREP_CONST(MT7531_MDIO_ST, 0x0)
+#define MT7531_MDIO_RW_DATA GENMASK(15, 0)
+#define MT7531_MDIO_REG_ADDR_CL45 MT7531_MDIO_RW_DATA
+
+#define MT7531_MDIO_TIMEOUT 100000
+#define MT7531_MDIO_SLEEP 20
+
+struct mt7531_mdio_priv {
+ phys_addr_t switch_regs;
+};
+
+static int mt7531_mdio_wait_busy(struct mt7531_mdio_priv *priv)
+{
+ unsigned int busy;
+
+ return readl_poll_sleep_timeout(priv->switch_regs + MT7531_PHY_IAC,
+ busy, (busy & MT7531_PHY_ACS_ST) == 0,
+ MT7531_MDIO_SLEEP, MT7531_MDIO_TIMEOUT);
+}
+
+static int mt7531_mdio_read(struct mt7531_mdio_priv *priv, int addr, int devad, int reg)
+{
+ u32 val;
+
+ if (devad != MDIO_DEVAD_NONE) {
+ if (mt7531_mdio_wait_busy(priv))
+ return -ETIMEDOUT;
+
+ val = MT7531_PHY_ACS_ST |
+ MT7531_MDIO_ST_CL45 | MT7531_MDIO_CMD_ADDR |
+ FIELD_PREP(MT7531_MDIO_PHY_ADDR, addr) |
+ FIELD_PREP(MT7531_MDIO_DEV_ADDR, devad) |
+ FIELD_PREP(MT7531_MDIO_REG_ADDR_CL45, reg);
+
+ writel(val, priv->switch_regs + MT7531_PHY_IAC);
+ }
+
+ if (mt7531_mdio_wait_busy(priv))
+ return -ETIMEDOUT;
+
+ val = MT7531_PHY_ACS_ST | FIELD_PREP(MT7531_MDIO_PHY_ADDR, addr);
+ if (devad != MDIO_DEVAD_NONE)
+ val |= MT7531_MDIO_ST_CL45 | MT7531_MDIO_CMD_READ_CL45 |
+ FIELD_PREP(MT7531_MDIO_DEV_ADDR, devad);
+ else
+ val |= MT7531_MDIO_ST_CL22 | MT7531_MDIO_CMD_READ_CL22 |
+ FIELD_PREP(MT7531_MDIO_REG_ADDR_CL22, reg);
+
+ writel(val, priv->switch_regs + MT7531_PHY_IAC);
+
+ if (mt7531_mdio_wait_busy(priv))
+ return -ETIMEDOUT;
+
+ val = readl(priv->switch_regs + MT7531_PHY_IAC);
+ return val & MT7531_MDIO_RW_DATA;
+}
+
+static int mt7531_mdio_write(struct mt7531_mdio_priv *priv, int addr, int devad,
+ int reg, u16 value)
+{
+ u32 val;
+
+ if (devad != MDIO_DEVAD_NONE) {
+ if (mt7531_mdio_wait_busy(priv))
+ return -ETIMEDOUT;
+
+ val = MT7531_PHY_ACS_ST |
+ MT7531_MDIO_ST_CL45 | MT7531_MDIO_CMD_ADDR |
+ FIELD_PREP(MT7531_MDIO_PHY_ADDR, addr) |
+ FIELD_PREP(MT7531_MDIO_DEV_ADDR, devad) |
+ FIELD_PREP(MT7531_MDIO_REG_ADDR_CL45, reg);
+
+ writel(val, priv->switch_regs + MT7531_PHY_IAC);
+ }
+
+ if (mt7531_mdio_wait_busy(priv))
+ return -ETIMEDOUT;
+
+ val = MT7531_PHY_ACS_ST | FIELD_PREP(MT7531_MDIO_PHY_ADDR, addr) |
+ MT7531_MDIO_CMD_WRITE | FIELD_PREP(MT7531_MDIO_RW_DATA, value);
+ if (devad != MDIO_DEVAD_NONE)
+ val |= MT7531_MDIO_ST_CL45 |
+ FIELD_PREP(MT7531_MDIO_DEV_ADDR, devad);
+ else
+ val |= MT7531_MDIO_ST_CL22 |
+ FIELD_PREP(MT7531_MDIO_REG_ADDR_CL22, reg);
+
+ writel(val, priv->switch_regs + MT7531_PHY_IAC);
+
+ if (mt7531_mdio_wait_busy(priv))
+ return -ETIMEDOUT;
+
+ return 0;
+}
+
+int mt7531_mdio_mmio_read(struct mii_dev *bus, int addr, int devad, int reg)
+{
+ struct mt7531_mdio_priv *priv = bus->priv;
+
+ return mt7531_mdio_read(priv, addr, devad, reg);
+}
+
+int mt7531_mdio_mmio_write(struct mii_dev *bus, int addr, int devad,
+ int reg, u16 value)
+{
+ struct mt7531_mdio_priv *priv = bus->priv;
+
+ return mt7531_mdio_write(priv, addr, devad, reg, value);
+}
+
+static int dm_mt7531_mdio_read(struct udevice *dev, int addr, int devad, int reg)
+{
+ struct mt7531_mdio_priv *priv = dev_get_priv(dev);
+
+ return mt7531_mdio_read(priv, addr, devad, reg);
+}
+
+static int dm_mt7531_mdio_write(struct udevice *dev, int addr, int devad,
+ int reg, u16 value)
+{
+ struct mt7531_mdio_priv *priv = dev_get_priv(dev);
+
+ return mt7531_mdio_write(priv, addr, devad, reg, value);
+}
+
+static const struct mdio_ops mt7531_mdio_ops = {
+ .read = dm_mt7531_mdio_read,
+ .write = dm_mt7531_mdio_write,
+};
+
+static int mt7531_mdio_probe(struct udevice *dev)
+{
+ struct mt7531_mdio_priv *priv = dev_get_priv(dev);
+
+ priv->switch_regs = dev_read_addr(dev);
+ if (priv->switch_regs == FDT_ADDR_T_NONE)
+ return -EINVAL;
+
+ return 0;
+}
+
+U_BOOT_DRIVER(mt7531_mdio) = {
+ .name = "mt7531-mdio-mmio",
+ .id = UCLASS_MDIO,
+ .probe = mt7531_mdio_probe,
+ .ops = &mt7531_mdio_ops,
+ .priv_auto = sizeof(struct mt7531_mdio_priv),
+};
diff --git a/drivers/net/mdio-mt7531-mmio.h b/drivers/net/mdio-mt7531-mmio.h
new file mode 100644
index 00000000000..f98102cb939
--- /dev/null
+++ b/drivers/net/mdio-mt7531-mmio.h
@@ -0,0 +1,9 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+
+struct mt7531_mdio_mmio_priv {
+ phys_addr_t switch_regs;
+};
+
+int mt7531_mdio_mmio_read(struct mii_dev *bus, int addr, int devad, int reg);
+int mt7531_mdio_mmio_write(struct mii_dev *bus, int addr, int devad,
+ int reg, u16 value);
diff --git a/drivers/net/mtk_eth/Kconfig b/drivers/net/mtk_eth/Kconfig
index e8cdf408237..5d4e54ab90e 100644
--- a/drivers/net/mtk_eth/Kconfig
+++ b/drivers/net/mtk_eth/Kconfig
@@ -1,6 +1,7 @@
config MEDIATEK_ETH
bool "MediaTek Ethernet GMAC Driver"
+ depends on ARCH_MEDIATEK || ARCH_MTMIPS
select PHYLIB
select DM_GPIO
select DM_RESET
@@ -30,6 +31,7 @@ config MTK_ETH_SWITCH_MT7531
config MTK_ETH_SWITCH_MT7988
bool "Support for MediaTek MT7988 built-in ethernet switch"
depends on TARGET_MT7988
+ select MDIO_MT7531_MMIO
default y
config MTK_ETH_SWITCH_AN8855
diff --git a/drivers/net/mtk_eth/mt7531.c b/drivers/net/mtk_eth/mt7531.c
index 32d6bebbbdb..965bc3cb7e9 100644
--- a/drivers/net/mtk_eth/mt7531.c
+++ b/drivers/net/mtk_eth/mt7531.c
@@ -22,17 +22,13 @@
static int mt7531_core_reg_read(struct mt753x_switch_priv *priv, u32 reg)
{
- u8 phy_addr = MT753X_PHY_ADDR(priv->phy_base, 0);
-
- return mt7531_mmd_read(priv, phy_addr, 0x1f, reg);
+ return mt7531_mmd_read(priv, 0, 0x1f, reg);
}
static void mt7531_core_reg_write(struct mt753x_switch_priv *priv, u32 reg,
u32 val)
{
- u8 phy_addr = MT753X_PHY_ADDR(priv->phy_base, 0);
-
- mt7531_mmd_write(priv, phy_addr, 0x1f, reg, val);
+ mt7531_mmd_write(priv, 0, 0x1f, reg, val);
}
static void mt7531_core_pll_setup(struct mt753x_switch_priv *priv)
@@ -171,7 +167,7 @@ static int mt7531_setup(struct mtk_eth_switch_priv *swpriv)
{
struct mt753x_switch_priv *priv = (struct mt753x_switch_priv *)swpriv;
u32 i, val, pmcr, port5_sgmii;
- u16 phy_addr, phy_val;
+ u16 phy_val;
priv->smi_addr = MT753X_DFL_SMI_ADDR;
priv->phy_base = (priv->smi_addr + 1) & MT753X_SMI_ADDR_MASK;
@@ -180,10 +176,9 @@ static int mt7531_setup(struct mtk_eth_switch_priv *swpriv)
/* Turn off PHYs */
for (i = 0; i < MT753X_NUM_PHYS; i++) {
- phy_addr = MT753X_PHY_ADDR(priv->phy_base, i);
- phy_val = mt7531_mii_read(priv, phy_addr, MII_BMCR);
+ phy_val = mt7531_mii_read(priv, i, MII_BMCR);
phy_val |= BMCR_PDOWN;
- mt7531_mii_write(priv, phy_addr, MII_BMCR, phy_val);
+ mt7531_mii_write(priv, i, MII_BMCR, phy_val);
}
/* Force MAC link down before reset */
@@ -239,10 +234,9 @@ static int mt7531_setup(struct mtk_eth_switch_priv *swpriv)
/* Turn on PHYs */
for (i = 0; i < MT753X_NUM_PHYS; i++) {
- phy_addr = MT753X_PHY_ADDR(priv->phy_base, i);
- phy_val = mt7531_mii_read(priv, phy_addr, MII_BMCR);
+ phy_val = mt7531_mii_read(priv, i, MII_BMCR);
phy_val &= ~BMCR_PDOWN;
- mt7531_mii_write(priv, phy_addr, MII_BMCR, phy_val);
+ mt7531_mii_write(priv, i, MII_BMCR, phy_val);
}
mt7531_phy_setting(priv);
diff --git a/drivers/net/mtk_eth/mt7988.c b/drivers/net/mtk_eth/mt7988.c
index a416d87840c..29b6363cbd7 100644
--- a/drivers/net/mtk_eth/mt7988.c
+++ b/drivers/net/mtk_eth/mt7988.c
@@ -6,6 +6,7 @@
* Author: Mark Lee <[email protected]>
*/
+#include <malloc.h>
#include <miiphy.h>
#include <linux/delay.h>
#include <linux/mdio.h>
@@ -14,6 +15,8 @@
#include "mtk_eth.h"
#include "mt753x.h"
+#include "../mdio-mt7531-mmio.h"
+
static int mt7988_reg_read(struct mt753x_switch_priv *priv, u32 reg, u32 *data)
{
*data = readl(priv->epriv.ethsys_base + GSW_BASE + reg);
@@ -30,20 +33,34 @@ static int mt7988_reg_write(struct mt753x_switch_priv *priv, u32 reg, u32 data)
static void mt7988_phy_setting(struct mt753x_switch_priv *priv)
{
+ struct mii_dev *mdio_bus = priv->mdio_bus;
u16 val;
u32 i;
for (i = 0; i < MT753X_NUM_PHYS; i++) {
+ u16 addr = MT753X_PHY_ADDR(priv->phy_base, i);
+
+ /* Set PHY to PHY page 1 */
+ mt7531_mdio_mmio_write(mdio_bus, addr, MDIO_DEVAD_NONE,
+ 0x1f, 0x1);
+
/* Enable HW auto downshift */
- mt7531_mii_write(priv, i, 0x1f, 0x1);
- val = mt7531_mii_read(priv, i, PHY_EXT_REG_14);
+ val = mt7531_mdio_mmio_read(mdio_bus, addr, MDIO_DEVAD_NONE,
+ PHY_EXT_REG_14);
val |= PHY_EN_DOWN_SHFIT;
- mt7531_mii_write(priv, i, PHY_EXT_REG_14, val);
+ mt7531_mdio_mmio_write(mdio_bus, addr, MDIO_DEVAD_NONE,
+ PHY_EXT_REG_14, val);
/* PHY link down power saving enable */
- val = mt7531_mii_read(priv, i, PHY_EXT_REG_17);
+ val = mt7531_mdio_mmio_read(mdio_bus, addr, MDIO_DEVAD_NONE,
+ PHY_EXT_REG_17);
val |= PHY_LINKDOWN_POWER_SAVING_EN;
- mt7531_mii_write(priv, i, PHY_EXT_REG_17, val);
+ mt7531_mdio_mmio_write(mdio_bus, addr, MDIO_DEVAD_NONE,
+ PHY_EXT_REG_17, val);
+
+ /* Restore PHY to PHY page 0 */
+ mt7531_mdio_mmio_write(mdio_bus, addr, MDIO_DEVAD_NONE,
+ 0x1f, 0x0);
}
}
@@ -58,24 +75,66 @@ static void mt7988_mac_control(struct mtk_eth_switch_priv *swpriv, bool enable)
mt7988_reg_write(priv, PMCR_REG(6), pmcr);
}
+static int mt7988_mdio_register(struct mt753x_switch_priv *priv)
+{
+ struct mt7531_mdio_mmio_priv *mdio_priv;
+ struct mii_dev *mdio_bus = mdio_alloc();
+ int ret;
+
+ if (!mdio_bus)
+ return -ENOMEM;
+
+ mdio_priv = malloc(sizeof(*mdio_priv));
+ if (!mdio_priv)
+ return -ENOMEM;
+
+ mdio_priv->switch_regs = (phys_addr_t)priv->epriv.ethsys_base + GSW_BASE;
+
+ mdio_bus->read = mt7531_mdio_mmio_read;
+ mdio_bus->write = mt7531_mdio_mmio_write;
+ snprintf(mdio_bus->name, sizeof(mdio_bus->name), priv->epriv.sw->name);
+
+ mdio_bus->priv = mdio_priv;
+
+ ret = mdio_register(mdio_bus);
+ if (ret) {
+ free(mdio_bus->priv);
+ mdio_free(mdio_bus);
+ return ret;
+ }
+
+ priv->mdio_bus = mdio_bus;
+
+ return 0;
+}
+
static int mt7988_setup(struct mtk_eth_switch_priv *swpriv)
{
struct mt753x_switch_priv *priv = (struct mt753x_switch_priv *)swpriv;
+ struct mii_dev *mdio_bus;
u16 phy_addr, phy_val;
+ int ret, i;
u32 pmcr;
- int i;
priv->smi_addr = MT753X_DFL_SMI_ADDR;
priv->phy_base = (priv->smi_addr + 1) & MT753X_SMI_ADDR_MASK;
priv->reg_read = mt7988_reg_read;
priv->reg_write = mt7988_reg_write;
+ ret = mt7988_mdio_register(priv);
+ if (ret)
+ return ret;
+
+ mdio_bus = priv->mdio_bus;
+
/* Turn off PHYs */
for (i = 0; i < MT753X_NUM_PHYS; i++) {
phy_addr = MT753X_PHY_ADDR(priv->phy_base, i);
- phy_val = mt7531_mii_read(priv, phy_addr, MII_BMCR);
+ phy_val = mt7531_mdio_mmio_read(mdio_bus, phy_addr,
+ MDIO_DEVAD_NONE, MII_BMCR);
phy_val |= BMCR_PDOWN;
- mt7531_mii_write(priv, phy_addr, MII_BMCR, phy_val);
+ mt7531_mdio_mmio_write(mdio_bus, phy_addr, MDIO_DEVAD_NONE,
+ MII_BMCR, phy_val);
}
switch (priv->epriv.phy_interface) {
@@ -129,21 +188,26 @@ static int mt7988_setup(struct mtk_eth_switch_priv *swpriv)
/* Turn on PHYs */
for (i = 0; i < MT753X_NUM_PHYS; i++) {
phy_addr = MT753X_PHY_ADDR(priv->phy_base, i);
- phy_val = mt7531_mii_read(priv, phy_addr, MII_BMCR);
+ phy_val = mt7531_mdio_mmio_read(mdio_bus, phy_addr,
+ MDIO_DEVAD_NONE, MII_BMCR);
phy_val &= ~BMCR_PDOWN;
- mt7531_mii_write(priv, phy_addr, MII_BMCR, phy_val);
+ mt7531_mdio_mmio_write(mdio_bus, phy_addr, MDIO_DEVAD_NONE,
+ MII_BMCR, phy_val);
}
mt7988_phy_setting(priv);
- return mt7531_mdio_register(priv);
+ return 0;
}
-static int mt7531_cleanup(struct mtk_eth_switch_priv *swpriv)
+static int mt7988_cleanup(struct mtk_eth_switch_priv *swpriv)
{
struct mt753x_switch_priv *priv = (struct mt753x_switch_priv *)swpriv;
+ struct mii_dev *mdio_bus = priv->mdio_bus;
- mdio_unregister(priv->mdio_bus);
+ mdio_unregister(mdio_bus);
+ free(mdio_bus->priv);
+ mdio_free(mdio_bus);
return 0;
}
@@ -155,6 +219,6 @@ MTK_ETH_SWITCH(mt7988) = {
.reset_wait_time = 50,
.setup = mt7988_setup,
- .cleanup = mt7531_cleanup,
+ .cleanup = mt7988_cleanup,
.mac_control = mt7988_mac_control,
};
diff --git a/drivers/net/phy/Kconfig b/drivers/net/phy/Kconfig
index 185c6a3156e..018be98705a 100644
--- a/drivers/net/phy/Kconfig
+++ b/drivers/net/phy/Kconfig
@@ -56,6 +56,7 @@ endif # B53_SWITCH
config MV88E61XX_SWITCH
bool "Marvell MV88E61xx Ethernet switch PHY support."
+ depends on !COMPILE_TEST
if MV88E61XX_SWITCH
@@ -119,6 +120,7 @@ config PHY_BROADCOM
config PHY_CORTINA
bool "Cortina Ethernet PHYs support"
+ depends on !COMPILE_TEST
config SYS_CORTINA_NO_FW_UPLOAD
bool "Cortina firmware loading support"
diff --git a/drivers/net/phy/aquantia.c b/drivers/net/phy/aquantia.c
index f63a13824ca..903fcd667f6 100644
--- a/drivers/net/phy/aquantia.c
+++ b/drivers/net/phy/aquantia.c
@@ -338,7 +338,7 @@ static int aquantia_set_proto(struct phy_device *phydev,
static int aquantia_dts_config(struct phy_device *phydev)
{
- ofnode node = phydev->node;
+ ofnode node = phy_get_ofnode(phydev);
u32 prop;
u16 reg;
diff --git a/drivers/net/phy/phy.c b/drivers/net/phy/phy.c
index 9702d042296..b58283fe3d5 100644
--- a/drivers/net/phy/phy.c
+++ b/drivers/net/phy/phy.c
@@ -1250,3 +1250,116 @@ bool phy_interface_is_ncsi(void)
return 0;
#endif
}
+
+/**
+ * __phy_read_page() - read the current page
+ * @phydev: a pointer to a &struct phy_device
+ *
+ * Returns page index or < 0 on error
+ */
+static int __phy_read_page(struct phy_device *phydev)
+{
+ struct phy_driver *drv = phydev->drv;
+
+ if (!drv->read_page) {
+ debug("read_page callback not available, PHY driver not loaded?\n");
+ return -EOPNOTSUPP;
+ }
+
+ return drv->read_page(phydev);
+}
+
+/**
+ * __phy_write_page() - Write a new page
+ * @phydev: a pointer to a &struct phy_device
+ * @page: page index to select
+ *
+ * Returns 0 or < 0 on error.
+ */
+static int __phy_write_page(struct phy_device *phydev, int page)
+{
+ struct phy_driver *drv = phydev->drv;
+
+ if (!drv->write_page) {
+ debug("write_page callback not available, PHY driver not loaded?\n");
+ return -EOPNOTSUPP;
+ }
+
+ return drv->write_page(phydev, page);
+}
+
+/**
+ * phy_save_page() - save the current page
+ * @phydev: a pointer to a &struct phy_device
+ *
+ * Return the current page number. On error,
+ * returns a negative errno. phy_restore_page() must always be called
+ * after this, irrespective of success or failure of this call.
+ */
+int phy_save_page(struct phy_device *phydev)
+{
+ return __phy_read_page(phydev);
+}
+
+/**
+ * phy_select_page - Switch to a PHY page and return the previous page
+ * @phydev: a pointer to a &struct phy_device
+ * @page: desired page
+ *
+ * NOTE: Save the current PHY page, and set the current page.
+ * On error, returns a negative errno, otherwise returns the previous page number.
+ * phy_restore_page() must always be called after this, irrespective
+ * of success or failure of this call.
+ */
+int phy_select_page(struct phy_device *phydev, int page)
+{
+ int ret, oldpage;
+
+ oldpage = ret = phy_save_page(phydev);
+ if (ret < 0)
+ return ret;
+
+ if (oldpage != page) {
+ ret = __phy_write_page(phydev, page);
+ if (ret < 0)
+ return ret;
+ }
+
+ return oldpage;
+}
+
+/**
+ * phy_restore_page - Restore a previously saved page and propagate status
+ * @phydev: a pointer to a &struct phy_device
+ * @oldpage: the old page, return value from phy_save_page() or phy_select_page()
+ * @ret: operation's return code
+ *
+ * Restoring @oldpage if it is a valid page.
+ * This function propagates the earliest error code from the group of
+ * operations.
+ *
+ * Returns:
+ * @oldpage if it was a negative value, otherwise
+ * @ret if it was a negative errno value, otherwise
+ * phy_write_page()'s negative value if it were in error, otherwise
+ * @ret.
+ */
+int phy_restore_page(struct phy_device *phydev, int oldpage, int ret)
+{
+ int r;
+
+ if (oldpage >= 0) {
+ r = __phy_write_page(phydev, oldpage);
+
+ /* Propagate the operation return code if the page write
+ * was successful.
+ */
+ if (ret >= 0 && r < 0)
+ ret = r;
+ } else {
+ /* Propagate the phy page selection error code */
+ ret = oldpage;
+ }
+
+ return ret;
+} \ No newline at end of file
diff --git a/drivers/power/domain/Kconfig b/drivers/power/domain/Kconfig
index ebf5d828cb0..0ad885c9e8b 100644
--- a/drivers/power/domain/Kconfig
+++ b/drivers/power/domain/Kconfig
@@ -20,7 +20,7 @@ config APPLE_PMGR_POWER_DOMAIN
config AGILEX5_PMGR_POWER_DOMAIN
bool "Enable the Agilex5 PMGR power domain driver"
- depends on SPL_POWER_DOMAIN
+ depends on SPL_POWER_DOMAIN && TARGET_SOCFPGA_SOC64
help
Enable support for power gating peripherals' SRAM specified in
the handoff data values obtained from the bitstream to reduce