34
34
#define DP83TD510E_CTRL_HW_RESET BIT(15)
35
35
#define DP83TD510E_CTRL_SW_RESET BIT(14)
36
36
37
+ /*
38
+ * DP83TD510E_PKT_STAT_x registers correspond to similarly named registers
39
+ * in the datasheet (PKT_STAT_1 through PKT_STAT_6). These registers store
40
+ * 32-bit or 16-bit counters for TX and RX statistics and must be read in
41
+ * sequence to ensure the counters are cleared correctly.
42
+ *
43
+ * - DP83TD510E_PKT_STAT_1: Contains TX packet count bits [15:0].
44
+ * - DP83TD510E_PKT_STAT_2: Contains TX packet count bits [31:16].
45
+ * - DP83TD510E_PKT_STAT_3: Contains TX error packet count.
46
+ * - DP83TD510E_PKT_STAT_4: Contains RX packet count bits [15:0].
47
+ * - DP83TD510E_PKT_STAT_5: Contains RX packet count bits [31:16].
48
+ * - DP83TD510E_PKT_STAT_6: Contains RX error packet count.
49
+ *
50
+ * Keeping the register names as defined in the datasheet helps maintain
51
+ * clarity and alignment with the documentation.
52
+ */
53
+ #define DP83TD510E_PKT_STAT_1 0x12b
54
+ #define DP83TD510E_PKT_STAT_2 0x12c
55
+ #define DP83TD510E_PKT_STAT_3 0x12d
56
+ #define DP83TD510E_PKT_STAT_4 0x12e
57
+ #define DP83TD510E_PKT_STAT_5 0x12f
58
+ #define DP83TD510E_PKT_STAT_6 0x130
59
+
37
60
#define DP83TD510E_AN_STAT_1 0x60c
38
61
#define DP83TD510E_MASTER_SLAVE_RESOL_FAIL BIT(15)
39
62
@@ -58,8 +81,16 @@ static const u16 dp83td510_mse_sqi_map[] = {
58
81
0x0000 /* 24dB =< SNR */
59
82
};
60
83
84
+ struct dp83td510_stats {
85
+ u64 tx_pkt_cnt ;
86
+ u64 tx_err_pkt_cnt ;
87
+ u64 rx_pkt_cnt ;
88
+ u64 rx_err_pkt_cnt ;
89
+ };
90
+
61
91
struct dp83td510_priv {
62
92
bool alcd_test_active ;
93
+ struct dp83td510_stats stats ;
63
94
};
64
95
65
96
/* Time Domain Reflectometry (TDR) Functionality of DP83TD510 PHY
@@ -177,6 +208,85 @@ struct dp83td510_priv {
177
208
#define DP83TD510E_ALCD_COMPLETE BIT(15)
178
209
#define DP83TD510E_ALCD_CABLE_LENGTH GENMASK(10, 0)
179
210
211
+ /**
212
+ * dp83td510_update_stats - Update the PHY statistics for the DP83TD510 PHY.
213
+ * @phydev: Pointer to the phy_device structure.
214
+ *
215
+ * The function reads the PHY statistics registers and updates the statistics
216
+ * structure.
217
+ *
218
+ * Returns: 0 on success or a negative error code on failure.
219
+ */
220
+ static int dp83td510_update_stats (struct phy_device * phydev )
221
+ {
222
+ struct dp83td510_priv * priv = phydev -> priv ;
223
+ u32 count ;
224
+ int ret ;
225
+
226
+ /* The DP83TD510E_PKT_STAT registers are divided into two groups:
227
+ * - Group 1 (TX stats): DP83TD510E_PKT_STAT_1 to DP83TD510E_PKT_STAT_3
228
+ * - Group 2 (RX stats): DP83TD510E_PKT_STAT_4 to DP83TD510E_PKT_STAT_6
229
+ *
230
+ * Registers in each group are cleared only after reading them in a
231
+ * plain sequence (e.g., 1, 2, 3 for Group 1 or 4, 5, 6 for Group 2).
232
+ * Any deviation from the sequence, such as reading 1, 2, 1, 2, 3, will
233
+ * prevent the group from being cleared. Additionally, the counters
234
+ * for a group are frozen as soon as the first register in that group
235
+ * is accessed.
236
+ */
237
+ ret = phy_read_mmd (phydev , MDIO_MMD_VEND2 , DP83TD510E_PKT_STAT_1 );
238
+ if (ret < 0 )
239
+ return ret ;
240
+ /* tx_pkt_cnt_15_0 */
241
+ count = ret ;
242
+
243
+ ret = phy_read_mmd (phydev , MDIO_MMD_VEND2 , DP83TD510E_PKT_STAT_2 );
244
+ if (ret < 0 )
245
+ return ret ;
246
+ /* tx_pkt_cnt_31_16 */
247
+ count |= ret << 16 ;
248
+ priv -> stats .tx_pkt_cnt += count ;
249
+
250
+ ret = phy_read_mmd (phydev , MDIO_MMD_VEND2 , DP83TD510E_PKT_STAT_3 );
251
+ if (ret < 0 )
252
+ return ret ;
253
+ /* tx_err_pkt_cnt */
254
+ priv -> stats .tx_err_pkt_cnt += ret ;
255
+
256
+ ret = phy_read_mmd (phydev , MDIO_MMD_VEND2 , DP83TD510E_PKT_STAT_4 );
257
+ if (ret < 0 )
258
+ return ret ;
259
+ /* rx_pkt_cnt_15_0 */
260
+ count = ret ;
261
+
262
+ ret = phy_read_mmd (phydev , MDIO_MMD_VEND2 , DP83TD510E_PKT_STAT_5 );
263
+ if (ret < 0 )
264
+ return ret ;
265
+ /* rx_pkt_cnt_31_16 */
266
+ count |= ret << 16 ;
267
+ priv -> stats .rx_pkt_cnt += count ;
268
+
269
+ ret = phy_read_mmd (phydev , MDIO_MMD_VEND2 , DP83TD510E_PKT_STAT_6 );
270
+ if (ret < 0 )
271
+ return ret ;
272
+ /* rx_err_pkt_cnt */
273
+ priv -> stats .rx_err_pkt_cnt += ret ;
274
+
275
+ return 0 ;
276
+ }
277
+
278
+ static void dp83td510_get_phy_stats (struct phy_device * phydev ,
279
+ struct ethtool_eth_phy_stats * eth_stats ,
280
+ struct ethtool_phy_stats * stats )
281
+ {
282
+ struct dp83td510_priv * priv = phydev -> priv ;
283
+
284
+ stats -> tx_packets = priv -> stats .tx_pkt_cnt ;
285
+ stats -> tx_errors = priv -> stats .tx_err_pkt_cnt ;
286
+ stats -> rx_packets = priv -> stats .rx_pkt_cnt ;
287
+ stats -> rx_errors = priv -> stats .rx_err_pkt_cnt ;
288
+ }
289
+
180
290
static int dp83td510_config_intr (struct phy_device * phydev )
181
291
{
182
292
int ret ;
@@ -599,6 +709,8 @@ static struct phy_driver dp83td510_driver[] = {
599
709
.get_sqi_max = dp83td510_get_sqi_max ,
600
710
.cable_test_start = dp83td510_cable_test_start ,
601
711
.cable_test_get_status = dp83td510_cable_test_get_status ,
712
+ .get_phy_stats = dp83td510_get_phy_stats ,
713
+ .update_stats = dp83td510_update_stats ,
602
714
603
715
.suspend = genphy_suspend ,
604
716
.resume = genphy_resume ,
0 commit comments