forked from openwrt/openwrt
/
701-net-ethernet-mtk_eth_soc-add-support-for-clause-45-mdio.patch
94 lines (88 loc) · 2.87 KB
/
701-net-ethernet-mtk_eth_soc-add-support-for-clause-45-mdio.patch
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c
+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
@@ -103,10 +103,30 @@ static u32 _mtk_mdio_write(struct mtk_et
write_data &= 0xffff;
- mtk_w32(eth, PHY_IAC_ACCESS | PHY_IAC_START | PHY_IAC_WRITE |
- (phy_register << PHY_IAC_REG_SHIFT) |
- (phy_addr << PHY_IAC_ADDR_SHIFT) | write_data,
- MTK_PHY_IAC);
+ if (phy_register & MII_ADDR_C45) {
+ u8 dev_num = (phy_register >> 16) & 0x1f;
+ u16 reg = (u16)(phy_register & 0xffff);
+
+ mtk_w32(eth, PHY_IAC_ACCESS | PHY_IAC_START_C45 | PHY_IAC_SET_ADDR |
+ (phy_addr << PHY_IAC_ADDR_SHIFT) |
+ (dev_num << PHY_IAC_REG_SHIFT) |
+ reg,
+ MTK_PHY_IAC);
+
+ if (mtk_mdio_busy_wait(eth))
+ return 0xffff;
+
+ mtk_w32(eth, PHY_IAC_ACCESS | PHY_IAC_START_C45 | PHY_IAC_WRITE |
+ (phy_addr << PHY_IAC_ADDR_SHIFT) |
+ (dev_num << PHY_IAC_REG_SHIFT) |
+ write_data,
+ MTK_PHY_IAC);
+ } else {
+ mtk_w32(eth, PHY_IAC_ACCESS | PHY_IAC_START | PHY_IAC_WRITE |
+ (phy_register << PHY_IAC_REG_SHIFT) |
+ (phy_addr << PHY_IAC_ADDR_SHIFT) | write_data,
+ MTK_PHY_IAC);
+ }
if (mtk_mdio_busy_wait(eth))
return -1;
@@ -121,10 +141,29 @@ static u32 _mtk_mdio_read(struct mtk_eth
if (mtk_mdio_busy_wait(eth))
return 0xffff;
- mtk_w32(eth, PHY_IAC_ACCESS | PHY_IAC_START | PHY_IAC_READ |
- (phy_reg << PHY_IAC_REG_SHIFT) |
- (phy_addr << PHY_IAC_ADDR_SHIFT),
- MTK_PHY_IAC);
+ if (phy_reg & MII_ADDR_C45) {
+ u8 dev_num = (phy_reg >> 16) & 0x1f;
+ u16 reg = (u16)(phy_reg & 0xffff);
+
+ mtk_w32(eth, PHY_IAC_ACCESS | PHY_IAC_START_C45 | PHY_IAC_SET_ADDR |
+ (phy_addr << PHY_IAC_ADDR_SHIFT) |
+ (dev_num << PHY_IAC_REG_SHIFT) |
+ reg,
+ MTK_PHY_IAC);
+
+ if (mtk_mdio_busy_wait(eth))
+ return 0xffff;
+
+ mtk_w32(eth, PHY_IAC_ACCESS | PHY_IAC_START_C45 | PHY_IAC_READ_C45 |
+ (phy_addr << PHY_IAC_ADDR_SHIFT) |
+ (dev_num << PHY_IAC_REG_SHIFT),
+ MTK_PHY_IAC);
+ } else {
+ mtk_w32(eth, PHY_IAC_ACCESS | PHY_IAC_START | PHY_IAC_READ |
+ (phy_reg << PHY_IAC_REG_SHIFT) |
+ (phy_addr << PHY_IAC_ADDR_SHIFT),
+ MTK_PHY_IAC);
+ }
if (mtk_mdio_busy_wait(eth))
return 0xffff;
@@ -584,6 +623,7 @@ static int mtk_mdio_init(struct mtk_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;
--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.h
+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.h
@@ -340,9 +340,12 @@
/* PHY Indirect Access Control registers */
#define MTK_PHY_IAC 0x10004
#define PHY_IAC_ACCESS BIT(31)
+#define PHY_IAC_SET_ADDR 0
#define PHY_IAC_READ BIT(19)
+#define PHY_IAC_READ_C45 (BIT(18) | BIT(19))
#define PHY_IAC_WRITE BIT(18)
#define PHY_IAC_START BIT(16)
+#define PHY_IAC_START_C45 0
#define PHY_IAC_ADDR_SHIFT 20
#define PHY_IAC_REG_SHIFT 25
#define PHY_IAC_TIMEOUT HZ