forked from Minki/linux
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: Daniel Golle <daniel@makrotopia.org> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
parent
c6af53f038
commit
e2e7f6e29c
@ -103,13 +103,35 @@ static int _mtk_mdio_write(struct mtk_eth *eth, u32 phy_addr, u32 phy_reg,
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
mtk_w32(eth, PHY_IAC_ACCESS |
|
||||
PHY_IAC_START_C22 |
|
||||
PHY_IAC_CMD_WRITE |
|
||||
PHY_IAC_REG(phy_reg) |
|
||||
PHY_IAC_ADDR(phy_addr) |
|
||||
PHY_IAC_DATA(write_data),
|
||||
MTK_PHY_IAC);
|
||||
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 |
|
||||
PHY_IAC_REG(phy_reg) |
|
||||
PHY_IAC_ADDR(phy_addr) |
|
||||
PHY_IAC_DATA(write_data),
|
||||
MTK_PHY_IAC);
|
||||
}
|
||||
|
||||
ret = mtk_mdio_busy_wait(eth);
|
||||
if (ret < 0)
|
||||
@ -126,12 +148,33 @@ static int _mtk_mdio_read(struct mtk_eth *eth, u32 phy_addr, u32 phy_reg)
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
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);
|
||||
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;
|
||||
|
||||
|
@ -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))
|
||||
|
Loading…
Reference in New Issue
Block a user