5151/* Register 0x0405: Unknown Register */
5252#define DP83TG720S_UNKNOWN_0405 0x405
5353
54+ #define DP83TG720S_LINK_QUAL_3 0x547
55+ #define DP83TG720S_LINK_LOSS_CNT_MASK GENMASK(15, 10)
56+
5457/* Register 0x0576: TDR Master Link Down Control */
5558#define DP83TG720S_TDR_MASTER_LINK_DOWN 0x576
5659
6063/* In RGMII mode, Enable or disable the internal delay for TXD */
6164#define DP83TG720S_RGMII_TX_CLK_SEL BIT(0)
6265
66+ /*
67+ * DP83TG720S_PKT_STAT_x registers correspond to similarly named registers
68+ * in the datasheet (PKT_STAT_1 through PKT_STAT_6). These registers store
69+ * 32-bit or 16-bit counters for TX and RX statistics and must be read in
70+ * sequence to ensure the counters are cleared correctly.
71+ *
72+ * - DP83TG720S_PKT_STAT_1: Contains TX packet count bits [15:0].
73+ * - DP83TG720S_PKT_STAT_2: Contains TX packet count bits [31:16].
74+ * - DP83TG720S_PKT_STAT_3: Contains TX error packet count.
75+ * - DP83TG720S_PKT_STAT_4: Contains RX packet count bits [15:0].
76+ * - DP83TG720S_PKT_STAT_5: Contains RX packet count bits [31:16].
77+ * - DP83TG720S_PKT_STAT_6: Contains RX error packet count.
78+ *
79+ * Keeping the register names as defined in the datasheet helps maintain
80+ * clarity and alignment with the documentation.
81+ */
82+ #define DP83TG720S_PKT_STAT_1 0x639
83+ #define DP83TG720S_PKT_STAT_2 0x63a
84+ #define DP83TG720S_PKT_STAT_3 0x63b
85+ #define DP83TG720S_PKT_STAT_4 0x63c
86+ #define DP83TG720S_PKT_STAT_5 0x63d
87+ #define DP83TG720S_PKT_STAT_6 0x63e
88+
6389/* Register 0x083F: Unknown Register */
6490#define DP83TG720S_UNKNOWN_083F 0x83f
6591
6995
7096#define DP83TG720_SQI_MAX 7
7197
98+ struct dp83tg720_stats {
99+ u64 link_loss_cnt ;
100+ u64 tx_pkt_cnt ;
101+ u64 tx_err_pkt_cnt ;
102+ u64 rx_pkt_cnt ;
103+ u64 rx_err_pkt_cnt ;
104+ };
105+
106+ struct dp83tg720_priv {
107+ struct dp83tg720_stats stats ;
108+ };
109+
110+ /**
111+ * dp83tg720_update_stats - Update the PHY statistics for the DP83TD510 PHY.
112+ * @phydev: Pointer to the phy_device structure.
113+ *
114+ * The function reads the PHY statistics registers and updates the statistics
115+ * structure.
116+ *
117+ * Returns: 0 on success or a negative error code on failure.
118+ */
119+ static int dp83tg720_update_stats (struct phy_device * phydev )
120+ {
121+ struct dp83tg720_priv * priv = phydev -> priv ;
122+ u32 count ;
123+ int ret ;
124+
125+ /* Read the link loss count */
126+ ret = phy_read_mmd (phydev , MDIO_MMD_VEND2 , DP83TG720S_LINK_QUAL_3 );
127+ if (ret < 0 )
128+ return ret ;
129+ /* link_loss_cnt */
130+ count = FIELD_GET (DP83TG720S_LINK_LOSS_CNT_MASK , ret );
131+ priv -> stats .link_loss_cnt += count ;
132+
133+ /* The DP83TG720S_PKT_STAT registers are divided into two groups:
134+ * - Group 1 (TX stats): DP83TG720S_PKT_STAT_1 to DP83TG720S_PKT_STAT_3
135+ * - Group 2 (RX stats): DP83TG720S_PKT_STAT_4 to DP83TG720S_PKT_STAT_6
136+ *
137+ * Registers in each group are cleared only after reading them in a
138+ * plain sequence (e.g., 1, 2, 3 for Group 1 or 4, 5, 6 for Group 2).
139+ * Any deviation from the sequence, such as reading 1, 2, 1, 2, 3, will
140+ * prevent the group from being cleared. Additionally, the counters
141+ * for a group are frozen as soon as the first register in that group
142+ * is accessed.
143+ */
144+ ret = phy_read_mmd (phydev , MDIO_MMD_VEND2 , DP83TG720S_PKT_STAT_1 );
145+ if (ret < 0 )
146+ return ret ;
147+ /* tx_pkt_cnt_15_0 */
148+ count = ret ;
149+
150+ ret = phy_read_mmd (phydev , MDIO_MMD_VEND2 , DP83TG720S_PKT_STAT_2 );
151+ if (ret < 0 )
152+ return ret ;
153+ /* tx_pkt_cnt_31_16 */
154+ count |= ret << 16 ;
155+ priv -> stats .tx_pkt_cnt += count ;
156+
157+ ret = phy_read_mmd (phydev , MDIO_MMD_VEND2 , DP83TG720S_PKT_STAT_3 );
158+ if (ret < 0 )
159+ return ret ;
160+ /* tx_err_pkt_cnt */
161+ priv -> stats .tx_err_pkt_cnt += ret ;
162+
163+ ret = phy_read_mmd (phydev , MDIO_MMD_VEND2 , DP83TG720S_PKT_STAT_4 );
164+ if (ret < 0 )
165+ return ret ;
166+ /* rx_pkt_cnt_15_0 */
167+ count = ret ;
168+
169+ ret = phy_read_mmd (phydev , MDIO_MMD_VEND2 , DP83TG720S_PKT_STAT_5 );
170+ if (ret < 0 )
171+ return ret ;
172+ /* rx_pkt_cnt_31_16 */
173+ count |= ret << 16 ;
174+ priv -> stats .rx_pkt_cnt += count ;
175+
176+ ret = phy_read_mmd (phydev , MDIO_MMD_VEND2 , DP83TG720S_PKT_STAT_6 );
177+ if (ret < 0 )
178+ return ret ;
179+ /* rx_err_pkt_cnt */
180+ priv -> stats .rx_err_pkt_cnt += ret ;
181+
182+ return 0 ;
183+ }
184+
185+ static void dp83tg720_get_link_stats (struct phy_device * phydev ,
186+ struct ethtool_link_ext_stats * link_stats )
187+ {
188+ struct dp83tg720_priv * priv = phydev -> priv ;
189+
190+ link_stats -> link_down_events = priv -> stats .link_loss_cnt ;
191+ }
192+
193+ static void dp83tg720_get_phy_stats (struct phy_device * phydev ,
194+ struct ethtool_eth_phy_stats * eth_stats ,
195+ struct ethtool_phy_stats * stats )
196+ {
197+ struct dp83tg720_priv * priv = phydev -> priv ;
198+
199+ stats -> tx_packets = priv -> stats .tx_pkt_cnt ;
200+ stats -> tx_errors = priv -> stats .tx_err_pkt_cnt ;
201+ stats -> rx_packets = priv -> stats .rx_pkt_cnt ;
202+ stats -> rx_errors = priv -> stats .rx_err_pkt_cnt ;
203+ }
204+
72205/**
73206 * dp83tg720_cable_test_start - Start the cable test for the DP83TG720 PHY.
74207 * @phydev: Pointer to the phy_device structure.
@@ -182,6 +315,11 @@ static int dp83tg720_cable_test_get_status(struct phy_device *phydev,
182315
183316 ethnl_cable_test_result (phydev , ETHTOOL_A_CABLE_PAIR_A , stat );
184317
318+ /* save the current stats before resetting the PHY */
319+ ret = dp83tg720_update_stats (phydev );
320+ if (ret )
321+ return ret ;
322+
185323 return phy_init_hw (phydev );
186324}
187325
@@ -217,6 +355,11 @@ static int dp83tg720_read_status(struct phy_device *phydev)
217355 phy_sts = phy_read (phydev , DP83TG720S_MII_REG_10 );
218356 phydev -> link = !!(phy_sts & DP83TG720S_LINK_STATUS );
219357 if (!phydev -> link ) {
358+ /* save the current stats before resetting the PHY */
359+ ret = dp83tg720_update_stats (phydev );
360+ if (ret )
361+ return ret ;
362+
220363 /* According to the "DP83TC81x, DP83TG72x Software
221364 * Implementation Guide", the PHY needs to be reset after a
222365 * link loss or if no link is created after at least 100ms.
@@ -341,12 +484,27 @@ static int dp83tg720_config_init(struct phy_device *phydev)
341484 return genphy_c45_pma_baset1_read_master_slave (phydev );
342485}
343486
487+ static int dp83tg720_probe (struct phy_device * phydev )
488+ {
489+ struct device * dev = & phydev -> mdio .dev ;
490+ struct dp83tg720_priv * priv ;
491+
492+ priv = devm_kzalloc (dev , sizeof (* priv ), GFP_KERNEL );
493+ if (!priv )
494+ return - ENOMEM ;
495+
496+ phydev -> priv = priv ;
497+
498+ return 0 ;
499+ }
500+
344501static struct phy_driver dp83tg720_driver [] = {
345502{
346503 PHY_ID_MATCH_MODEL (DP83TG720S_PHY_ID ),
347504 .name = "TI DP83TG720S" ,
348505
349506 .flags = PHY_POLL_CABLE_TEST ,
507+ .probe = dp83tg720_probe ,
350508 .config_aneg = dp83tg720_config_aneg ,
351509 .read_status = dp83tg720_read_status ,
352510 .get_features = genphy_c45_pma_read_ext_abilities ,
@@ -355,6 +513,9 @@ static struct phy_driver dp83tg720_driver[] = {
355513 .get_sqi_max = dp83tg720_get_sqi_max ,
356514 .cable_test_start = dp83tg720_cable_test_start ,
357515 .cable_test_get_status = dp83tg720_cable_test_get_status ,
516+ .get_link_stats = dp83tg720_get_link_stats ,
517+ .get_phy_stats = dp83tg720_get_phy_stats ,
518+ .update_stats = dp83tg720_update_stats ,
358519
359520 .suspend = genphy_suspend ,
360521 .resume = genphy_resume ,
0 commit comments