1 /*
2 * Copyright (c) 2006-2020, RT-Thread Development Team
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 *
6 * Change Logs:
7 * Date Author Notes
8 * 2017-08-24 chinesebear first version
9 */
10 #include "mii.h"
11
mii_nway_result(unsigned int negotiated)12 static inline unsigned int mii_nway_result(unsigned int negotiated)
13 {
14 unsigned int ret;
15
16 if (negotiated & LPA_100FULL)
17 ret = LPA_100FULL;
18 else if (negotiated & LPA_100BASE4)
19 ret = LPA_100BASE4;
20 else if (negotiated & LPA_100HALF)
21 ret = LPA_100HALF;
22 else if (negotiated & LPA_10FULL)
23 ret = LPA_10FULL;
24 else
25 ret = LPA_10HALF;
26
27 return ret;
28 }
29
mii_check_gmii_support(struct mii_if_info * mii)30 static int mii_check_gmii_support(struct mii_if_info *mii)
31 {
32 int reg;
33
34 reg = mii->mdio_read(mii->dev, mii->phy_id, MII_BMSR);
35 if (reg & BMSR_ESTATEN)
36 {
37 reg = mii->mdio_read(mii->dev, mii->phy_id, MII_ESTATUS);
38 if (reg & (ESTATUS_1000_TFULL | ESTATUS_1000_THALF))
39 return 1;
40 }
41
42 return 0;
43 }
44
mii_ethtool_gset(struct mii_if_info * mii,struct ethtool_cmd * ecmd)45 static int mii_ethtool_gset(struct mii_if_info *mii, struct ethtool_cmd *ecmd)
46 {
47 struct synopGMACNetworkAdapter *dev = mii->dev;
48 u32 advert, bmcr, lpa, nego;
49 u32 advert2 = 0, bmcr2 = 0, lpa2 = 0;
50
51 ecmd->supported =
52 (SUPPORTED_10baseT_Half | SUPPORTED_10baseT_Full |
53 SUPPORTED_100baseT_Half | SUPPORTED_100baseT_Full |
54 SUPPORTED_Autoneg | SUPPORTED_TP | SUPPORTED_MII);
55 if (mii->supports_gmii)
56 ecmd->supported |= SUPPORTED_1000baseT_Half |
57 SUPPORTED_1000baseT_Full;
58
59 /* only supports twisted-pair */
60 ecmd->port = PORT_MII;
61
62 /* only supports internal transceiver */
63 ecmd->transceiver = XCVR_INTERNAL;
64
65 /* this isn't fully supported at higher layers */
66 ecmd->phy_address = mii->phy_id;
67
68 ecmd->advertising = ADVERTISED_TP | ADVERTISED_MII;
69 advert = mii->mdio_read(dev, mii->phy_id, MII_ADVERTISE);
70 if (mii->supports_gmii)
71 advert2 = mii->mdio_read(dev, mii->phy_id, MII_CTRL1000);
72
73 if (advert & ADVERTISE_10HALF)
74 ecmd->advertising |= ADVERTISED_10baseT_Half;
75 if (advert & ADVERTISE_10FULL)
76 ecmd->advertising |= ADVERTISED_10baseT_Full;
77 if (advert & ADVERTISE_100HALF)
78 ecmd->advertising |= ADVERTISED_100baseT_Half;
79 if (advert & ADVERTISE_100FULL)
80 ecmd->advertising |= ADVERTISED_100baseT_Full;
81 if (advert2 & ADVERTISE_1000HALF)
82 ecmd->advertising |= ADVERTISED_1000baseT_Half;
83 if (advert2 & ADVERTISE_1000FULL)
84 ecmd->advertising |= ADVERTISED_1000baseT_Full;
85
86 bmcr = mii->mdio_read(dev, mii->phy_id, MII_BMCR);
87 lpa = mii->mdio_read(dev, mii->phy_id, MII_LPA);
88 if (mii->supports_gmii)
89 {
90 bmcr2 = mii->mdio_read(dev, mii->phy_id, MII_CTRL1000);
91 lpa2 = mii->mdio_read(dev, mii->phy_id, MII_STAT1000);
92 }
93 if (bmcr & BMCR_ANENABLE)
94 {
95 ecmd->advertising |= ADVERTISED_Autoneg;
96 ecmd->autoneg = AUTONEG_ENABLE;
97
98 nego = mii_nway_result(advert & lpa);
99 if ((bmcr2 & (ADVERTISE_1000HALF | ADVERTISE_1000FULL)) &
100 (lpa2 >> 2))
101 ecmd->speed = SPEED_1000;
102 else if (nego == LPA_100FULL || nego == LPA_100HALF)
103 ecmd->speed = SPEED_100;
104 else
105 ecmd->speed = SPEED_10;
106 if ((lpa2 & LPA_1000FULL) || nego == LPA_100FULL ||
107 nego == LPA_10FULL)
108 {
109 ecmd->duplex = DUPLEX_FULL;
110 mii->full_duplex = 1;
111 }
112 else
113 {
114 ecmd->duplex = DUPLEX_HALF;
115 mii->full_duplex = 0;
116 }
117 }
118 else
119 {
120 ecmd->autoneg = AUTONEG_DISABLE;
121
122 ecmd->speed = ((bmcr & BMCR_SPEED1000 &&
123 (bmcr & BMCR_SPEED100) == 0) ? SPEED_1000 :
124 (bmcr & BMCR_SPEED100) ? SPEED_100 : SPEED_10);
125 ecmd->duplex = (bmcr & BMCR_FULLDPLX) ? DUPLEX_FULL : DUPLEX_HALF;
126 }
127
128 /* ignore maxtxpkt, maxrxpkt for now */
129
130 return 0;
131 }
132
mii_link_ok(struct mii_if_info * mii)133 static int mii_link_ok(struct mii_if_info *mii)
134 {
135 /* first, a dummy read, needed to latch some MII phys */
136 mii->mdio_read(mii->dev, mii->phy_id, MII_BMSR);
137 if (mii->mdio_read(mii->dev, mii->phy_id, MII_BMSR) & BMSR_LSTATUS)
138 return 1;
139 return 0;
140 }
141