84718d300b5df7df04e55914a52204ea069b90e6
[openwrt/staging/neocturne.git] /
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
5 access
6
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.
10
11 Tested on the Ubiquiti UniFi 6 LR access point featuring
12 MediaTek MT7622BV WiSoC with Aquantia AQR112C.
13
14 Signed-off-by: Daniel Golle <daniel@makrotopia.org>
15 Signed-off-by: David S. Miller <davem@davemloft.net>
16 ---
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(-)
20
21 --- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c
22 +++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
23 @@ -323,13 +323,35 @@ static int _mtk_mdio_write(struct mtk_et
24 if (ret < 0)
25 return ret;
26
27 - mtk_w32(eth, PHY_IAC_ACCESS |
28 - PHY_IAC_START_C22 |
29 - PHY_IAC_CMD_WRITE |
30 - PHY_IAC_REG(phy_reg) |
31 - PHY_IAC_ADDR(phy_addr) |
32 - PHY_IAC_DATA(write_data),
33 - MTK_PHY_IAC);
34 + if (phy_reg & MII_ADDR_C45) {
35 + mtk_w32(eth, PHY_IAC_ACCESS |
36 + PHY_IAC_START_C45 |
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)),
41 + MTK_PHY_IAC);
42 +
43 + ret = mtk_mdio_busy_wait(eth);
44 + if (ret < 0)
45 + return ret;
46 +
47 + mtk_w32(eth, PHY_IAC_ACCESS |
48 + PHY_IAC_START_C45 |
49 + PHY_IAC_CMD_WRITE |
50 + PHY_IAC_REG(mdiobus_c45_devad(phy_reg)) |
51 + PHY_IAC_ADDR(phy_addr) |
52 + PHY_IAC_DATA(write_data),
53 + MTK_PHY_IAC);
54 + } else {
55 + mtk_w32(eth, PHY_IAC_ACCESS |
56 + PHY_IAC_START_C22 |
57 + PHY_IAC_CMD_WRITE |
58 + PHY_IAC_REG(phy_reg) |
59 + PHY_IAC_ADDR(phy_addr) |
60 + PHY_IAC_DATA(write_data),
61 + MTK_PHY_IAC);
62 + }
63
64 ret = mtk_mdio_busy_wait(eth);
65 if (ret < 0)
66 @@ -346,12 +368,33 @@ static int _mtk_mdio_read(struct mtk_eth
67 if (ret < 0)
68 return ret;
69
70 - mtk_w32(eth, PHY_IAC_ACCESS |
71 - PHY_IAC_START_C22 |
72 - PHY_IAC_CMD_C22_READ |
73 - PHY_IAC_REG(phy_reg) |
74 - PHY_IAC_ADDR(phy_addr),
75 - MTK_PHY_IAC);
76 + if (phy_reg & MII_ADDR_C45) {
77 + mtk_w32(eth, PHY_IAC_ACCESS |
78 + PHY_IAC_START_C45 |
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)),
83 + MTK_PHY_IAC);
84 +
85 + ret = mtk_mdio_busy_wait(eth);
86 + if (ret < 0)
87 + return ret;
88 +
89 + mtk_w32(eth, PHY_IAC_ACCESS |
90 + PHY_IAC_START_C45 |
91 + PHY_IAC_CMD_C45_READ |
92 + PHY_IAC_REG(mdiobus_c45_devad(phy_reg)) |
93 + PHY_IAC_ADDR(phy_addr),
94 + MTK_PHY_IAC);
95 + } else {
96 + mtk_w32(eth, PHY_IAC_ACCESS |
97 + PHY_IAC_START_C22 |
98 + PHY_IAC_CMD_C22_READ |
99 + PHY_IAC_REG(phy_reg) |
100 + PHY_IAC_ADDR(phy_addr),
101 + MTK_PHY_IAC);
102 + }
103
104 ret = mtk_mdio_busy_wait(eth);
105 if (ret < 0)
106 @@ -1013,6 +1056,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;
113
114 --- a/drivers/net/ethernet/mediatek/mtk_eth_soc.h
115 +++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.h
116 @@ -382,9 +382,12 @@
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))