Commit e2e7f6e2 authored by Daniel Golle's avatar Daniel Golle Committed by David S. Miller
Browse files

net: ethernet: mtk_eth_soc: implement Clause 45 MDIO access



Implement read and write access to IEEE 802.3 Clause 45 Ethernet
phy registers while making use of new mdiobus_c45_regad and
mdiobus_c45_devad helpers.

Tested on the Ubiquiti UniFi 6 LR access point featuring
MediaTek MT7622BV WiSoC with Aquantia AQR112C.

Signed-off-by: default avatarDaniel Golle <daniel@makrotopia.org>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent c6af53f0
Loading
Loading
Loading
Loading
+57 −13
Original line number Diff line number Diff line
@@ -103,6 +103,27 @@ static int _mtk_mdio_write(struct mtk_eth *eth, u32 phy_addr, u32 phy_reg,
	if (ret < 0)
		return ret;

	if (phy_reg & MII_ADDR_C45) {
		mtk_w32(eth, PHY_IAC_ACCESS |
			     PHY_IAC_START_C45 |
			     PHY_IAC_CMD_C45_ADDR |
			     PHY_IAC_REG(mdiobus_c45_devad(phy_reg)) |
			     PHY_IAC_ADDR(phy_addr) |
			     PHY_IAC_DATA(mdiobus_c45_regad(phy_reg)),
			MTK_PHY_IAC);

		ret = mtk_mdio_busy_wait(eth);
		if (ret < 0)
			return ret;

		mtk_w32(eth, PHY_IAC_ACCESS |
			     PHY_IAC_START_C45 |
			     PHY_IAC_CMD_WRITE |
			     PHY_IAC_REG(mdiobus_c45_devad(phy_reg)) |
			     PHY_IAC_ADDR(phy_addr) |
			     PHY_IAC_DATA(write_data),
			MTK_PHY_IAC);
	} else {
		mtk_w32(eth, PHY_IAC_ACCESS |
			     PHY_IAC_START_C22 |
			     PHY_IAC_CMD_WRITE |
@@ -110,6 +131,7 @@ static int _mtk_mdio_write(struct mtk_eth *eth, u32 phy_addr, u32 phy_reg,
			     PHY_IAC_ADDR(phy_addr) |
			     PHY_IAC_DATA(write_data),
			MTK_PHY_IAC);
	}

	ret = mtk_mdio_busy_wait(eth);
	if (ret < 0)
@@ -122,16 +144,37 @@ static int _mtk_mdio_read(struct mtk_eth *eth, u32 phy_addr, u32 phy_reg)
{
	int ret;

	ret = mtk_mdio_busy_wait(eth);
	if (ret < 0)
		return ret;

	if (phy_reg & MII_ADDR_C45) {
		mtk_w32(eth, PHY_IAC_ACCESS |
			     PHY_IAC_START_C45 |
			     PHY_IAC_CMD_C45_ADDR |
			     PHY_IAC_REG(mdiobus_c45_devad(phy_reg)) |
			     PHY_IAC_ADDR(phy_addr) |
			     PHY_IAC_DATA(mdiobus_c45_regad(phy_reg)),
			MTK_PHY_IAC);

		ret = mtk_mdio_busy_wait(eth);
		if (ret < 0)
			return ret;

		mtk_w32(eth, PHY_IAC_ACCESS |
			     PHY_IAC_START_C45 |
			     PHY_IAC_CMD_C45_READ |
			     PHY_IAC_REG(mdiobus_c45_devad(phy_reg)) |
			     PHY_IAC_ADDR(phy_addr),
			MTK_PHY_IAC);
	} else {
		mtk_w32(eth, PHY_IAC_ACCESS |
			     PHY_IAC_START_C22 |
			     PHY_IAC_CMD_C22_READ |
			     PHY_IAC_REG(phy_reg) |
			     PHY_IAC_ADDR(phy_addr),
			MTK_PHY_IAC);
	}

	ret = mtk_mdio_busy_wait(eth);
	if (ret < 0)
@@ -504,6 +547,7 @@ static int mtk_mdio_init(struct mtk_eth *eth)
	eth->mii_bus->name = "mdio";
	eth->mii_bus->read = mtk_mdio_read;
	eth->mii_bus->write = mtk_mdio_write;
	eth->mii_bus->probe_capabilities = MDIOBUS_C22_C45;
	eth->mii_bus->priv = eth;
	eth->mii_bus->parent = eth->dev;

+3 −0
Original line number Diff line number Diff line
@@ -346,9 +346,12 @@
#define PHY_IAC_ADDR_MASK	GENMASK(24, 20)
#define PHY_IAC_ADDR(x)		FIELD_PREP(PHY_IAC_ADDR_MASK, (x))
#define PHY_IAC_CMD_MASK	GENMASK(19, 18)
#define PHY_IAC_CMD_C45_ADDR	FIELD_PREP(PHY_IAC_CMD_MASK, 0)
#define PHY_IAC_CMD_WRITE	FIELD_PREP(PHY_IAC_CMD_MASK, 1)
#define PHY_IAC_CMD_C22_READ	FIELD_PREP(PHY_IAC_CMD_MASK, 2)
#define PHY_IAC_CMD_C45_READ	FIELD_PREP(PHY_IAC_CMD_MASK, 3)
#define PHY_IAC_START_MASK	GENMASK(17, 16)
#define PHY_IAC_START_C45	FIELD_PREP(PHY_IAC_START_MASK, 0)
#define PHY_IAC_START_C22	FIELD_PREP(PHY_IAC_START_MASK, 1)
#define PHY_IAC_DATA_MASK	GENMASK(15, 0)
#define PHY_IAC_DATA(x)		FIELD_PREP(PHY_IAC_DATA_MASK, (x))