1 From e2e7f6e29c99a1c6afc0e0aa4b9ea80302d28720 Mon Sep 17 00:00:00 2001
2 From: Daniel Golle <daniel@makrotopia.org>
3 Date: Tue, 4 Jan 2022 12:07:46 +0000
4 Subject: [PATCH 3/3] net: ethernet: mtk_eth_soc: implement Clause 45 MDIO
7 Implement read and write access to IEEE 802.3 Clause 45 Ethernet
8 phy registers while making use of new mdiobus_c45_regad and
9 mdiobus_c45_devad helpers.
11 Tested on the Ubiquiti UniFi 6 LR access point featuring
12 MediaTek MT7622BV WiSoC with Aquantia AQR112C.
14 Signed-off-by: Daniel Golle <daniel@makrotopia.org>
15 Signed-off-by: David S. Miller <davem@davemloft.net>
17 drivers/net/ethernet/mediatek/mtk_eth_soc.c | 70 +++++++++++++++++----
18 drivers/net/ethernet/mediatek/mtk_eth_soc.h | 3 +
19 2 files changed, 60 insertions(+), 13 deletions(-)
21 --- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c
22 +++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
23 @@ -196,13 +196,35 @@ static int _mtk_mdio_write(struct mtk_et
27 - mtk_w32(eth, PHY_IAC_ACCESS |
30 - PHY_IAC_REG(phy_reg) |
31 - PHY_IAC_ADDR(phy_addr) |
32 - PHY_IAC_DATA(write_data),
34 + if (phy_reg & MII_ADDR_C45) {
35 + mtk_w32(eth, PHY_IAC_ACCESS |
37 + PHY_IAC_CMD_C45_ADDR |
38 + PHY_IAC_REG(mdiobus_c45_devad(phy_reg)) |
39 + PHY_IAC_ADDR(phy_addr) |
40 + PHY_IAC_DATA(mdiobus_c45_regad(phy_reg)),
43 + ret = mtk_mdio_busy_wait(eth);
47 + mtk_w32(eth, PHY_IAC_ACCESS |
50 + PHY_IAC_REG(mdiobus_c45_devad(phy_reg)) |
51 + PHY_IAC_ADDR(phy_addr) |
52 + PHY_IAC_DATA(write_data),
55 + mtk_w32(eth, PHY_IAC_ACCESS |
58 + PHY_IAC_REG(phy_reg) |
59 + PHY_IAC_ADDR(phy_addr) |
60 + PHY_IAC_DATA(write_data),
64 ret = mtk_mdio_busy_wait(eth);
66 @@ -219,12 +241,33 @@ static int _mtk_mdio_read(struct mtk_eth
70 - mtk_w32(eth, PHY_IAC_ACCESS |
72 - PHY_IAC_CMD_C22_READ |
73 - PHY_IAC_REG(phy_reg) |
74 - PHY_IAC_ADDR(phy_addr),
76 + if (phy_reg & MII_ADDR_C45) {
77 + mtk_w32(eth, PHY_IAC_ACCESS |
79 + PHY_IAC_CMD_C45_ADDR |
80 + PHY_IAC_REG(mdiobus_c45_devad(phy_reg)) |
81 + PHY_IAC_ADDR(phy_addr) |
82 + PHY_IAC_DATA(mdiobus_c45_regad(phy_reg)),
85 + ret = mtk_mdio_busy_wait(eth);
89 + mtk_w32(eth, PHY_IAC_ACCESS |
91 + PHY_IAC_CMD_C45_READ |
92 + PHY_IAC_REG(mdiobus_c45_devad(phy_reg)) |
93 + PHY_IAC_ADDR(phy_addr),
96 + mtk_w32(eth, PHY_IAC_ACCESS |
98 + PHY_IAC_CMD_C22_READ |
99 + PHY_IAC_REG(phy_reg) |
100 + PHY_IAC_ADDR(phy_addr),
104 ret = mtk_mdio_busy_wait(eth);
106 @@ -683,6 +726,7 @@ static int mtk_mdio_init(struct mtk_eth
107 eth->mii_bus->name = "mdio";
108 eth->mii_bus->read = mtk_mdio_read;
109 eth->mii_bus->write = mtk_mdio_write;
110 + eth->mii_bus->probe_capabilities = MDIOBUS_C22_C45;
111 eth->mii_bus->priv = eth;
112 eth->mii_bus->parent = eth->dev;
114 --- a/drivers/net/ethernet/mediatek/mtk_eth_soc.h
115 +++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.h
117 #define PHY_IAC_ADDR_MASK GENMASK(24, 20)
118 #define PHY_IAC_ADDR(x) FIELD_PREP(PHY_IAC_ADDR_MASK, (x))
119 #define PHY_IAC_CMD_MASK GENMASK(19, 18)
120 +#define PHY_IAC_CMD_C45_ADDR FIELD_PREP(PHY_IAC_CMD_MASK, 0)
121 #define PHY_IAC_CMD_WRITE FIELD_PREP(PHY_IAC_CMD_MASK, 1)
122 #define PHY_IAC_CMD_C22_READ FIELD_PREP(PHY_IAC_CMD_MASK, 2)
123 +#define PHY_IAC_CMD_C45_READ FIELD_PREP(PHY_IAC_CMD_MASK, 3)
124 #define PHY_IAC_START_MASK GENMASK(17, 16)
125 +#define PHY_IAC_START_C45 FIELD_PREP(PHY_IAC_START_MASK, 0)
126 #define PHY_IAC_START_C22 FIELD_PREP(PHY_IAC_START_MASK, 1)
127 #define PHY_IAC_DATA_MASK GENMASK(15, 0)
128 #define PHY_IAC_DATA(x) FIELD_PREP(PHY_IAC_DATA_MASK, (x))