1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3 * Driver for Analog Devices, Inc. ADIN1140 10BASE-T1S MAC-PHY
4 *
5 * Copyright 2026 Analog Devices Inc.
6 */
7
8 #include <linux/cleanup.h>
9 #include <linux/etherdevice.h>
10 #include <linux/kernel.h>
11 #include <linux/mdio.h>
12 #include <linux/module.h>
13 #include <linux/oa_tc6.h>
14 #include <linux/phy.h>
15
16 #define ADIN1140_MAC_CONFIG2_STAT_CLR_RD BIT(6)
17 #define ADIN1140_MAC_CONFIG2_FWD_UNK2HOST BIT(2)
18
19 #define ADIN1140_MAC_P1_LOOP_ADDR_REG 0xC4
20
21 #define ADIN1140_MAC_ADDR_FILT_UPR_REG 0x50
22 #define ADIN1140_MAC_ADDR_FILT_APPLY2PORT1 BIT(30)
23 #define ADIN1140_MAC_ADDR_FILT_TO_HOST BIT(16)
24
25 #define ADIN1140_MAC_ADDR_FILT_LWR_REG 0x51
26
27 #define ADIN1140_MAC_ADDR_MASK_UPR_REG 0x70
28 #define ADIN1140_MAC_ADDR_MASK_LWR_REG 0x71
29
30 #define ADIN1140_MAC_FILT_MC_SLOT 0U
31 #define ADIN1140_MAC_FILT_BC_SLOT 1U
32 #define ADIN1140_MAC_FILT_UC_SLOT 2U
33 #define ADIN1140_MAC_FILT_MAX_SLOT 16U
34 #define ADIN1140_MAC_FILT_MASK_LIMIT 2U
35
36 #define ADIN1140_MAC_RX_FRAME_CNT 0xA1
37 #define ADIN1140_MAC_RX_BC_FRAME_CNT 0xA2
38 #define ADIN1140_MAC_RX_MC_FRAME_CNT 0xA3
39 #define ADIN1140_MAC_RX_CRC_ERR_CNT 0xA5
40 #define ADIN1140_MAC_RX_ALIGN_ERR_CNT 0xA6
41 #define ADIN1140_MAC_RX_PREAMBLE_ERR_CNT 0xA7
42 #define ADIN1140_MAC_RX_SHORT_ERR_CNT 0xA8
43 #define ADIN1140_MAC_RX_LONG_ERR_CNT 0xA9
44 #define ADIN1140_MAC_RX_PHY_ERR_CNT 0xAA
45 #define ADIN1140_MAC_RX_DRP_FULL_CNT 0xAB
46 #define ADIN1140_MAC_RX_DRP_FILTER_CNT 0xAD
47 #define ADIN1140_MAC_RX_IFG_ERR_CNT 0xAE
48 #define ADIN1140_MAC_TX_FRAME_CNT 0xB1
49 #define ADIN1140_MAC_TX_BC_FRAME_CNT 0xB2
50 #define ADIN1140_MAC_TX_MC_FRAME_CNT 0xB3
51 #define ADIN1140_MAC_TX_SINGLE_COL_CNT 0xB5
52 #define ADIN1140_MAC_TX_MULTI_COL_CNT 0xB6
53 #define ADIN1140_MAC_TX_DEFERRED_CNT 0xB7
54 #define ADIN1140_MAC_TX_LATE_COL_CNT 0xB8
55 #define ADIN1140_MAC_TX_EXCESS_COL_CNT 0xB9
56 #define ADIN1140_MAC_TX_UNDERRUN_CNT 0xBA
57
58 /* ADIN1140_MAC_FILT_MAX_SLOT - 3 (multicast, broadcast and unicast
59 * reserved slots)
60 */
61 #define ADIN1140_MAC_FILT_AVAIL 13U
62
63 #define ADIN1140_PHY_CTRL_DEFAULT 0x1000
64 #define ADIN1140_PHY_STATUS_DEFAULT 0x082D
65 #define ADIN1140_PHY_ID1 0x0283
66 #define ADIN1140_PHY_ID2 0xBE00
67
68 #define ADIN1140_STATS_CHECK_DELAY (3 * HZ)
69
70 enum adin1140_statistics_entry {
71 rx_frames,
72 rx_bc_frames,
73 rx_mc_frames,
74 rx_crc_errors,
75 rx_align_errors,
76 rx_preamble_errors,
77 rx_short_frame_errors,
78 rx_long_frame_errors,
79 rx_phy_errors,
80 rx_fifo_full_dropped,
81 rx_addr_filter_dropped,
82 rx_ifg_errors,
83 tx_frames,
84 tx_bc_frames,
85 tx_mc_frames,
86 tx_single_collision,
87 tx_multi_collision,
88 tx_deferred,
89 tx_late_collision,
90 tx_excess_collision,
91 tx_underrun,
92 ADIN1140_STATS_CNT,
93 };
94
95 struct adin1140_statistics_reg {
96 const char *name;
97 enum adin1140_statistics_entry idx;
98 };
99
100 struct adin1140_priv {
101 struct net_device *netdev;
102 struct oa_tc6 *tc6;
103 struct mii_bus *mdiobus;
104 struct phy_device *phydev;
105 struct delayed_work stats_work;
106
107 /* Protects stats[] from concurrent updates in adin1140_stats_work
108 * and reads in the get_stats functions
109 */
110 spinlock_t stat_lock;
111 u64 stats[ADIN1140_STATS_CNT];
112 };
113
114 static const u32 adin1140_stat_regs[] = {
115 [rx_frames] = ADIN1140_MAC_RX_FRAME_CNT,
116 [rx_bc_frames] = ADIN1140_MAC_RX_BC_FRAME_CNT,
117 [rx_mc_frames] = ADIN1140_MAC_RX_MC_FRAME_CNT,
118 [rx_crc_errors] = ADIN1140_MAC_RX_CRC_ERR_CNT,
119 [rx_align_errors] = ADIN1140_MAC_RX_ALIGN_ERR_CNT,
120 [rx_preamble_errors] = ADIN1140_MAC_RX_PREAMBLE_ERR_CNT,
121 [rx_short_frame_errors] = ADIN1140_MAC_RX_SHORT_ERR_CNT,
122 [rx_long_frame_errors] = ADIN1140_MAC_RX_LONG_ERR_CNT,
123 [rx_phy_errors] = ADIN1140_MAC_RX_PHY_ERR_CNT,
124 [rx_fifo_full_dropped] = ADIN1140_MAC_RX_DRP_FULL_CNT,
125 [rx_addr_filter_dropped] = ADIN1140_MAC_RX_DRP_FILTER_CNT,
126 [rx_ifg_errors] = ADIN1140_MAC_RX_IFG_ERR_CNT,
127 [tx_frames] = ADIN1140_MAC_TX_FRAME_CNT,
128 [tx_bc_frames] = ADIN1140_MAC_TX_BC_FRAME_CNT,
129 [tx_mc_frames] = ADIN1140_MAC_TX_MC_FRAME_CNT,
130 [tx_single_collision] = ADIN1140_MAC_TX_SINGLE_COL_CNT,
131 [tx_multi_collision] = ADIN1140_MAC_TX_MULTI_COL_CNT,
132 [tx_deferred] = ADIN1140_MAC_TX_DEFERRED_CNT,
133 [tx_late_collision] = ADIN1140_MAC_TX_LATE_COL_CNT,
134 [tx_excess_collision] = ADIN1140_MAC_TX_EXCESS_COL_CNT,
135 [tx_underrun] = ADIN1140_MAC_TX_UNDERRUN_CNT,
136 };
137
138 static const struct adin1140_statistics_reg adin1140_stats[] = {
139 {.name = "rx_preamble_errors", .idx = rx_preamble_errors},
140 {.name = "rx_ifg_errors", .idx = rx_ifg_errors},
141 };
142
adin1140_mac_filter_set(struct adin1140_priv * priv,const u8 * addr,const u8 * mask,u8 slot)143 static int adin1140_mac_filter_set(struct adin1140_priv *priv,
144 const u8 *addr, const u8 *mask,
145 u8 slot)
146 {
147 u32 reg_address;
148 u32 val;
149 int ret;
150
151 if (slot >= ADIN1140_MAC_FILT_MAX_SLOT)
152 return -ENOSPC;
153
154 reg_address = ADIN1140_MAC_ADDR_FILT_UPR_REG + 2 * slot;
155
156 ret = oa_tc6_write_register_mms(priv->tc6, OA_TC6_MAC_MMS1,
157 reg_address,
158 get_unaligned_be16(&addr[0]) |
159 ADIN1140_MAC_ADDR_FILT_APPLY2PORT1 |
160 ADIN1140_MAC_ADDR_FILT_TO_HOST);
161 if (ret)
162 return ret;
163
164 reg_address = ADIN1140_MAC_ADDR_FILT_LWR_REG + 2 * slot;
165 ret = oa_tc6_write_register_mms(priv->tc6, OA_TC6_MAC_MMS1,
166 reg_address,
167 get_unaligned_be32(&addr[2]));
168 if (ret)
169 return ret;
170
171 /* Only the first 2 destination MAC filter slots support masking.
172 * For the other entries, the destination address in the received
173 * frame must match exactly.
174 */
175 if (slot >= ADIN1140_MAC_FILT_MASK_LIMIT)
176 return 0;
177
178 val = get_unaligned_be16(&mask[0]);
179 reg_address = ADIN1140_MAC_ADDR_MASK_UPR_REG + (2 * slot);
180
181 ret = oa_tc6_write_register_mms(priv->tc6, OA_TC6_MAC_MMS1,
182 reg_address, val);
183 if (ret)
184 return ret;
185
186 val = get_unaligned_be32(&mask[2]);
187 reg_address = ADIN1140_MAC_ADDR_MASK_LWR_REG + (2 * slot);
188
189 return oa_tc6_write_register_mms(priv->tc6, OA_TC6_MAC_MMS1,
190 reg_address, val);
191 }
192
adin1140_mac_filter_clear(struct adin1140_priv * priv,u8 slot)193 static int adin1140_mac_filter_clear(struct adin1140_priv *priv, u8 slot)
194 {
195 u8 mask[ETH_ALEN];
196 u8 addr[ETH_ALEN];
197
198 memset(mask, 0xFF, ETH_ALEN);
199 memset(addr, 0x0, ETH_ALEN);
200
201 return adin1140_mac_filter_set(priv, addr, mask, slot);
202 }
203
adin1140_filter_unicast(struct adin1140_priv * priv)204 static int adin1140_filter_unicast(struct adin1140_priv *priv)
205 {
206 /* Only the first 2 filter slots support masking, so no unicast
207 * address will ever need a mask. The first slots are used for the
208 * all multicast and broadcast filter.
209 */
210 return adin1140_mac_filter_set(priv, priv->netdev->dev_addr, NULL,
211 ADIN1140_MAC_FILT_UC_SLOT);
212 }
213
adin1140_filter_all_multicast(struct adin1140_priv * priv,bool en)214 static int adin1140_filter_all_multicast(struct adin1140_priv *priv, bool en)
215 {
216 u8 multicast_addr[ETH_ALEN] = {1, 0, 0, 0, 0, 0};
217
218 if (en)
219 return adin1140_mac_filter_set(priv, multicast_addr,
220 multicast_addr,
221 ADIN1140_MAC_FILT_MC_SLOT);
222
223 return adin1140_mac_filter_clear(priv, ADIN1140_MAC_FILT_MC_SLOT);
224 }
225
adin1140_filter_broadcast(struct adin1140_priv * priv,bool enabled)226 static int adin1140_filter_broadcast(struct adin1140_priv *priv, bool enabled)
227 {
228 u8 mask[ETH_ALEN];
229
230 if (enabled) {
231 memset(mask, 0xFF, ETH_ALEN);
232 return adin1140_mac_filter_set(priv, mask, mask,
233 ADIN1140_MAC_FILT_BC_SLOT);
234 }
235
236 return adin1140_mac_filter_clear(priv, ADIN1140_MAC_FILT_BC_SLOT);
237 }
238
adin1140_default_filter_config(struct adin1140_priv * priv)239 static int adin1140_default_filter_config(struct adin1140_priv *priv)
240 {
241 int ret;
242
243 ret = adin1140_filter_broadcast(priv, true);
244 if (ret)
245 return ret;
246
247 return adin1140_filter_unicast(priv);
248 }
249
adin1140_promiscuous_mode(struct adin1140_priv * priv,bool enabled)250 static int adin1140_promiscuous_mode(struct adin1140_priv *priv, bool enabled)
251 {
252 int ret;
253 u32 val;
254
255 ret = oa_tc6_read_register(priv->tc6, OA_TC6_REG_CONFIG2, &val);
256 if (ret)
257 return ret;
258
259 if (enabled)
260 val |= ADIN1140_MAC_CONFIG2_FWD_UNK2HOST;
261 else
262 val &= ~ADIN1140_MAC_CONFIG2_FWD_UNK2HOST;
263
264 return oa_tc6_write_register(priv->tc6, OA_TC6_REG_CONFIG2, val);
265 }
266
adin1140_rx_mode(struct net_device * dev,struct netdev_hw_addr_list * uc,struct netdev_hw_addr_list * mc)267 static int adin1140_rx_mode(struct net_device *dev,
268 struct netdev_hw_addr_list *uc,
269 struct netdev_hw_addr_list *mc)
270 {
271 struct adin1140_priv *priv = netdev_priv(dev);
272 struct netdev_hw_addr *ha;
273 bool all_multi, promisc;
274 u32 mac_addrs;
275 u8 slot, i;
276 int ret;
277
278 /* The ADIN1140 has 16 dest MAC address filter slots:
279 * 0 - reserved for all multicast filter.
280 * 1 - reserved for broadcast filter.
281 * 2 - reserved for the device's own unicast MAC.
282 * 3 -> 15 - available for other unicast/multicast filters.
283 */
284
285 mac_addrs = netdev_hw_addr_list_count(uc);
286 all_multi = false;
287 promisc = false;
288
289 if (priv->netdev->flags & IFF_PROMISC)
290 promisc = true;
291 else if (priv->netdev->flags & IFF_ALLMULTI)
292 all_multi = true;
293 else
294 mac_addrs += netdev_hw_addr_list_count(mc);
295
296 if (mac_addrs > ADIN1140_MAC_FILT_AVAIL) {
297 /* The filter table is full. Enable promisc mode. */
298 promisc = true;
299 }
300
301 ret = adin1140_promiscuous_mode(priv, promisc);
302 if (ret)
303 return ret;
304
305 ret = adin1140_filter_all_multicast(priv, all_multi);
306 if (ret)
307 return ret;
308
309 slot = ADIN1140_MAC_FILT_UC_SLOT + 1;
310 if (!promisc) {
311 netdev_hw_addr_list_for_each(ha, uc) {
312 ret = adin1140_mac_filter_set(priv, ha->addr, NULL,
313 slot);
314 if (ret)
315 return ret;
316
317 slot++;
318 }
319
320 if (!all_multi) {
321 netdev_hw_addr_list_for_each(ha, mc) {
322 ret = adin1140_mac_filter_set(priv, ha->addr,
323 NULL, slot);
324 if (ret)
325 return ret;
326
327 slot++;
328 }
329 }
330 }
331
332 for (i = slot; i < ADIN1140_MAC_FILT_MAX_SLOT; i++) {
333 ret = adin1140_mac_filter_clear(priv, i);
334 if (ret)
335 return ret;
336 }
337
338 return 0;
339 }
340
adin1140_stats_work(struct work_struct * work)341 static void adin1140_stats_work(struct work_struct *work)
342 {
343 struct delayed_work *dwork = to_delayed_work(work);
344 struct adin1140_priv *priv;
345 u32 reg_val;
346 int ret;
347 u32 i;
348
349 priv = container_of(dwork, struct adin1140_priv, stats_work);
350
351 for (i = 0; i < ARRAY_SIZE(adin1140_stat_regs); i++) {
352 ret = oa_tc6_read_register_mms(priv->tc6, OA_TC6_MAC_MMS1,
353 adin1140_stat_regs[i],
354 ®_val);
355 if (ret)
356 goto out;
357
358 scoped_guard(spinlock, &priv->stat_lock)
359 priv->stats[i] += reg_val;
360 }
361
362 out:
363 schedule_delayed_work(dwork, ADIN1140_STATS_CHECK_DELAY);
364 }
365
adin1140_configure(struct adin1140_priv * priv)366 static int adin1140_configure(struct adin1140_priv *priv)
367 {
368 u32 reg_val;
369 int ret;
370
371 ret = oa_tc6_zero_align_receive_frame_enable(priv->tc6);
372 if (ret)
373 return ret;
374
375 /* Disable MAC loopback */
376 ret = oa_tc6_write_register_mms(priv->tc6, OA_TC6_MAC_MMS1,
377 ADIN1140_MAC_P1_LOOP_ADDR_REG, 0x0);
378 if (ret)
379 return ret;
380
381 ret = oa_tc6_read_register(priv->tc6, OA_TC6_REG_CONFIG2, ®_val);
382 if (ret)
383 return ret;
384
385 reg_val |= ADIN1140_MAC_CONFIG2_STAT_CLR_RD;
386
387 ret = oa_tc6_write_register(priv->tc6, OA_TC6_REG_CONFIG2, reg_val);
388 if (ret)
389 return ret;
390
391 return adin1140_default_filter_config(priv);
392 }
393
adin1140_open(struct net_device * netdev)394 static int adin1140_open(struct net_device *netdev)
395 {
396 struct adin1140_priv *priv = netdev_priv(netdev);
397
398 schedule_delayed_work(&priv->stats_work, ADIN1140_STATS_CHECK_DELAY);
399
400 phy_start(netdev->phydev);
401 netif_start_queue(netdev);
402
403 return 0;
404 }
405
adin1140_close(struct net_device * netdev)406 static int adin1140_close(struct net_device *netdev)
407 {
408 struct adin1140_priv *priv = netdev_priv(netdev);
409
410 cancel_delayed_work_sync(&priv->stats_work);
411
412 netif_stop_queue(netdev);
413 phy_stop(netdev->phydev);
414
415 return 0;
416 }
417
adin1140_start_xmit(struct sk_buff * skb,struct net_device * netdev)418 static netdev_tx_t adin1140_start_xmit(struct sk_buff *skb,
419 struct net_device *netdev)
420 {
421 struct adin1140_priv *priv = netdev_priv(netdev);
422
423 /* The MAC doesn't automatically pad the frame to a 60 byte minimum
424 * size in case the host sends a shorter skb, so we have to do it in
425 * the driver. The FCS will be added by the MAC.
426 */
427 if (skb_put_padto(skb, ETH_ZLEN))
428 return NETDEV_TX_OK;
429
430 return oa_tc6_start_xmit(priv->tc6, skb);
431 }
432
adin1140_set_mac_address(struct net_device * netdev,void * addr)433 static int adin1140_set_mac_address(struct net_device *netdev, void *addr)
434 {
435 struct adin1140_priv *priv = netdev_priv(netdev);
436 struct sockaddr *address = addr;
437 u8 mask[ETH_ALEN];
438 int ret;
439
440 ret = eth_prepare_mac_addr_change(netdev, addr);
441 if (ret < 0)
442 return ret;
443
444 if (ether_addr_equal(address->sa_data, netdev->dev_addr))
445 return 0;
446
447 memset(mask, 0xFF, ETH_ALEN);
448 ret = adin1140_mac_filter_set(priv, address->sa_data, mask,
449 ADIN1140_MAC_FILT_UC_SLOT);
450 if (ret)
451 return ret;
452
453 eth_commit_mac_addr_change(netdev, addr);
454
455 return 0;
456 }
457
__adin1140_ndo_get_stats64(struct adin1140_priv * priv,struct rtnl_link_stats64 * storage)458 static void __adin1140_ndo_get_stats64(struct adin1140_priv *priv,
459 struct rtnl_link_stats64 *storage)
460 {
461 storage->rx_errors = priv->stats[rx_crc_errors] +
462 priv->stats[rx_align_errors] +
463 priv->stats[rx_preamble_errors] +
464 priv->stats[rx_short_frame_errors] +
465 priv->stats[rx_long_frame_errors] +
466 priv->stats[rx_phy_errors] +
467 priv->stats[rx_ifg_errors];
468
469 storage->tx_errors = priv->stats[tx_excess_collision] +
470 priv->stats[tx_underrun];
471
472 storage->rx_dropped = priv->stats[rx_fifo_full_dropped] +
473 priv->stats[rx_addr_filter_dropped];
474
475 storage->multicast = priv->stats[rx_mc_frames];
476
477 storage->collisions = priv->stats[tx_single_collision] +
478 priv->stats[tx_multi_collision];
479
480 storage->rx_length_errors = priv->stats[rx_short_frame_errors] +
481 priv->stats[rx_long_frame_errors];
482 storage->rx_over_errors = priv->stats[rx_fifo_full_dropped];
483 storage->rx_crc_errors = priv->stats[rx_crc_errors];
484 storage->rx_frame_errors = priv->stats[rx_align_errors];
485 storage->rx_missed_errors = priv->stats[rx_fifo_full_dropped];
486
487 storage->tx_aborted_errors = priv->stats[tx_excess_collision];
488 storage->tx_fifo_errors = priv->stats[tx_underrun];
489 storage->tx_window_errors = priv->stats[tx_late_collision];
490 }
491
adin1140_ndo_get_stats64(struct net_device * dev,struct rtnl_link_stats64 * storage)492 static void adin1140_ndo_get_stats64(struct net_device *dev,
493 struct rtnl_link_stats64 *storage)
494 {
495 struct adin1140_priv *priv = netdev_priv(dev);
496
497 storage->rx_packets = priv->netdev->stats.rx_packets;
498 storage->tx_packets = priv->netdev->stats.tx_packets;
499
500 storage->rx_bytes = priv->netdev->stats.rx_bytes;
501 storage->tx_bytes = priv->netdev->stats.tx_bytes;
502
503 scoped_guard(spinlock, &priv->stat_lock)
504 __adin1140_ndo_get_stats64(priv, storage);
505 }
506
adin1140_get_drvinfo(struct net_device * netdev,struct ethtool_drvinfo * info)507 static void adin1140_get_drvinfo(struct net_device *netdev,
508 struct ethtool_drvinfo *info)
509 {
510 strscpy(info->driver, "ADIN1140", sizeof(info->driver));
511 strscpy(info->bus_info, dev_name(netdev->dev.parent),
512 sizeof(info->bus_info));
513 }
514
adin1140_get_ethtool_stats(struct net_device * netdev,struct ethtool_stats * stats,u64 * data)515 static void adin1140_get_ethtool_stats(struct net_device *netdev,
516 struct ethtool_stats *stats, u64 *data)
517 {
518 struct adin1140_priv *priv = netdev_priv(netdev);
519 u32 i;
520
521 scoped_guard(spinlock, &priv->stat_lock) {
522 for (i = 0; i < ARRAY_SIZE(adin1140_stats); i++)
523 data[i] = priv->stats[adin1140_stats[i].idx];
524 }
525 }
526
adin1140_get_ethtool_strings(struct net_device * netdev,u32 sset,u8 * p)527 static void adin1140_get_ethtool_strings(struct net_device *netdev, u32 sset,
528 u8 *p)
529 {
530 u32 i;
531
532 switch (sset) {
533 case ETH_SS_STATS:
534 for (i = 0; i < ARRAY_SIZE(adin1140_stats); i++)
535 ethtool_puts(&p, adin1140_stats[i].name);
536
537 break;
538 }
539 }
540
adin1140_get_sset_count(struct net_device * netdev,int sset)541 static int adin1140_get_sset_count(struct net_device *netdev, int sset)
542 {
543 switch (sset) {
544 case ETH_SS_STATS:
545 return ARRAY_SIZE(adin1140_stats);
546 default:
547 return -EOPNOTSUPP;
548 }
549 }
550
__adin1140_eth_mac_stats(struct adin1140_priv * priv,struct ethtool_eth_mac_stats * mac_stats)551 static void __adin1140_eth_mac_stats(struct adin1140_priv *priv,
552 struct ethtool_eth_mac_stats *mac_stats)
553 {
554 mac_stats->FramesReceivedOK = priv->stats[rx_frames];
555 mac_stats->BroadcastFramesReceivedOK = priv->stats[rx_bc_frames];
556 mac_stats->MulticastFramesReceivedOK = priv->stats[rx_mc_frames];
557 mac_stats->FrameCheckSequenceErrors = priv->stats[rx_crc_errors];
558 mac_stats->AlignmentErrors = priv->stats[rx_align_errors];
559 mac_stats->FrameTooLongErrors = priv->stats[rx_long_frame_errors];
560 mac_stats->FramesLostDueToIntMACRcvError =
561 priv->stats[rx_fifo_full_dropped];
562 mac_stats->FramesTransmittedOK = priv->stats[tx_frames];
563 mac_stats->BroadcastFramesXmittedOK = priv->stats[tx_bc_frames];
564 mac_stats->MulticastFramesXmittedOK = priv->stats[tx_mc_frames];
565 mac_stats->SingleCollisionFrames = priv->stats[tx_single_collision];
566 mac_stats->MultipleCollisionFrames = priv->stats[tx_multi_collision];
567 mac_stats->FramesWithDeferredXmissions = priv->stats[tx_deferred];
568 mac_stats->LateCollisions = priv->stats[tx_late_collision];
569 mac_stats->FramesAbortedDueToXSColls =
570 priv->stats[tx_excess_collision];
571 mac_stats->FramesLostDueToIntMACXmitError = priv->stats[tx_underrun];
572 }
573
adin1140_get_eth_mac_stats(struct net_device * netdev,struct ethtool_eth_mac_stats * mac_stats)574 static void adin1140_get_eth_mac_stats(struct net_device *netdev,
575 struct ethtool_eth_mac_stats *mac_stats)
576 {
577 struct adin1140_priv *priv = netdev_priv(netdev);
578
579 scoped_guard(spinlock, &priv->stat_lock)
580 __adin1140_eth_mac_stats(priv, mac_stats);
581 }
582
adin1140_mdiobus_read(struct mii_bus * bus,int addr,int regnum)583 static int adin1140_mdiobus_read(struct mii_bus *bus, int addr, int regnum)
584 {
585 /* The ADIN1140's standard PHY C22 register map (OA TC6 0xFF00 -
586 * 0xFF1F), of which only 0xFF00 - 0xFF03 are implemented) cannot be
587 * accessed while frames are being received by the PHY. In case this
588 * happens the CONFIG0 and CONFIG2 register values will get corrupted,
589 * getting a random value. Both reads and writes cause the same
590 * behavior. This is a workaround that avoids MDIO accesses all
591 * together. Since this is a 10BASE-T1S PHY, only the loopback and
592 * reset (AN) bits in the control register (0x0) can be written.
593 * These functionalities have custom implementations in the PHY
594 * driver. C45 accesses do not cause this issue.
595 */
596
597 switch (regnum) {
598 case MII_BMCR:
599 return ADIN1140_PHY_CTRL_DEFAULT;
600 case MII_BMSR:
601 return ADIN1140_PHY_STATUS_DEFAULT;
602 case MII_PHYSID1:
603 return ADIN1140_PHY_ID1;
604 case MII_PHYSID2:
605 return ADIN1140_PHY_ID2;
606 default:
607 return 0xFFFF;
608 }
609 }
610
adin1140_mdiobus_write(struct mii_bus * bus,int addr,int regnum,u16 val)611 static int adin1140_mdiobus_write(struct mii_bus *bus, int addr, int regnum,
612 u16 val)
613 {
614 return -EIO;
615 }
616
adin1140_mdio_register(struct adin1140_priv * priv,struct spi_device * spidev)617 static int adin1140_mdio_register(struct adin1140_priv *priv,
618 struct spi_device *spidev)
619 {
620 priv->mdiobus = devm_mdiobus_alloc(&spidev->dev);
621 if (!priv->mdiobus)
622 return dev_err_probe(&spidev->dev, -ENOMEM,
623 "MDIO bus alloc failed\n");
624
625 priv->mdiobus->name = "adin1140-mdiobus";
626 priv->mdiobus->priv = priv->tc6;
627 priv->mdiobus->parent = &spidev->dev;
628 priv->mdiobus->phy_mask = GENMASK(31, 1);
629 priv->mdiobus->read = adin1140_mdiobus_read;
630 priv->mdiobus->write = adin1140_mdiobus_write;
631 priv->mdiobus->read_c45 = oa_tc6_mdiobus_read_c45;
632 priv->mdiobus->write_c45 = oa_tc6_mdiobus_write_c45;
633
634 snprintf(priv->mdiobus->id, MII_BUS_ID_SIZE, "adin1140-%s.%u",
635 dev_name(&spidev->dev), spi_get_chipselect(spidev, 0));
636
637 return devm_mdiobus_register(&spidev->dev, priv->mdiobus);
638 }
639
adin1140_handle_link_change(struct net_device * netdev)640 static void adin1140_handle_link_change(struct net_device *netdev)
641 {
642 phy_print_status(netdev->phydev);
643 }
644
adin1140_phy_remove(void * data)645 static void adin1140_phy_remove(void *data)
646 {
647 phy_disconnect(data);
648 }
649
adin1140_phy_init(struct adin1140_priv * priv,struct spi_device * spidev)650 static int adin1140_phy_init(struct adin1140_priv *priv,
651 struct spi_device *spidev)
652 {
653 int ret;
654
655 ret = adin1140_mdio_register(priv, spidev);
656 if (ret)
657 return ret;
658
659 priv->phydev = phy_find_first(priv->mdiobus);
660 if (!priv->phydev)
661 return dev_err_probe(&spidev->dev, -ENODEV, "No PHY found\n");
662
663 priv->phydev->is_internal = true;
664 ret = phy_connect_direct(priv->netdev, priv->phydev,
665 &adin1140_handle_link_change,
666 PHY_INTERFACE_MODE_INTERNAL);
667 if (ret)
668 return dev_err_probe(&spidev->dev, ret,
669 "Can't attach PHY to %s\n",
670 priv->mdiobus->id);
671
672 ret = devm_add_action_or_reset(&spidev->dev, adin1140_phy_remove,
673 priv->phydev);
674 if (ret)
675 return ret;
676
677 phy_attached_info(priv->phydev);
678
679 return 0;
680 }
681
682 static const struct ethtool_ops adin1140_ethtool_ops = {
683 .get_drvinfo = adin1140_get_drvinfo,
684 .get_link = ethtool_op_get_link,
685 .get_ethtool_stats = adin1140_get_ethtool_stats,
686 .get_sset_count = adin1140_get_sset_count,
687 .get_strings = adin1140_get_ethtool_strings,
688 .get_link_ksettings = phy_ethtool_get_link_ksettings,
689 .set_link_ksettings = phy_ethtool_set_link_ksettings,
690 .get_eth_mac_stats = adin1140_get_eth_mac_stats,
691 };
692
693 static const struct net_device_ops adin1140_netdev_ops = {
694 .ndo_open = adin1140_open,
695 .ndo_stop = adin1140_close,
696 .ndo_start_xmit = adin1140_start_xmit,
697 .ndo_set_mac_address = adin1140_set_mac_address,
698 .ndo_validate_addr = eth_validate_addr,
699 .ndo_set_rx_mode_async = adin1140_rx_mode,
700 .ndo_eth_ioctl = phy_do_ioctl_running,
701 .ndo_get_stats64 = adin1140_ndo_get_stats64,
702 };
703
adin1140_oa_tc6_remove(void * data)704 static void adin1140_oa_tc6_remove(void *data)
705 {
706 oa_tc6_exit(data);
707 }
708
adin1140_probe(struct spi_device * spi)709 static int adin1140_probe(struct spi_device *spi)
710 {
711 struct oa_tc6_quirks tc6_quirks = {};
712 struct net_device *netdev;
713 struct adin1140_priv *priv;
714 int ret;
715
716 netdev = devm_alloc_etherdev(&spi->dev, sizeof(struct adin1140_priv));
717 if (!netdev)
718 return -ENOMEM;
719
720 priv = netdev_priv(netdev);
721 priv->netdev = netdev;
722 spi_set_drvdata(spi, priv);
723 spin_lock_init(&priv->stat_lock);
724
725 tc6_quirks.quirk_flags = OA_TC6_BROKEN_PHY;
726
727 priv->tc6 = oa_tc6_init(spi, netdev, &tc6_quirks);
728 if (!priv->tc6)
729 return -ENODEV;
730
731 ret = devm_add_action_or_reset(&spi->dev, adin1140_oa_tc6_remove,
732 priv->tc6);
733 if (ret)
734 return ret;
735
736 ret = adin1140_phy_init(priv, spi);
737 if (ret)
738 return ret;
739
740 if (device_get_ethdev_address(&spi->dev, netdev))
741 eth_hw_addr_random(netdev);
742
743 ret = adin1140_configure(priv);
744 if (ret)
745 return ret;
746
747 INIT_DELAYED_WORK(&priv->stats_work, adin1140_stats_work);
748
749 netdev->if_port = IF_PORT_10BASET;
750 netdev->irq = spi->irq;
751 netdev->netdev_ops = &adin1140_netdev_ops;
752 netdev->ethtool_ops = &adin1140_ethtool_ops;
753 netdev->netns_immutable = true;
754 netdev->priv_flags |= IFF_LIVE_ADDR_CHANGE |
755 IFF_UNICAST_FLT;
756
757 ret = devm_register_netdev(&spi->dev, netdev);
758 if (ret)
759 return dev_err_probe(&spi->dev, ret,
760 "Failed to register netdev");
761
762 return 0;
763 }
764
765 static const struct spi_device_id adin1140_spi_id[] = {
766 { .name = "ad3306" },
767 { .name = "adin1140" },
768 {},
769 };
770 MODULE_DEVICE_TABLE(spi, adin1140_spi_id);
771
772 static const struct of_device_id adin1140_match_table[] = {
773 { .compatible = "adi,ad3306" },
774 { .compatible = "adi,adin1140" },
775 { }
776 };
777 MODULE_DEVICE_TABLE(of, adin1140_match_table);
778
779 static struct spi_driver adin1140_driver = {
780 .driver = {
781 .name = "adin1140",
782 .of_match_table = adin1140_match_table,
783 },
784 .probe = adin1140_probe,
785 .id_table = adin1140_spi_id,
786 };
787 module_spi_driver(adin1140_driver);
788
789 MODULE_DESCRIPTION("Analog Devices, Inc. ADIN1140 10BASE-T1S MAC-PHY");
790 MODULE_AUTHOR("Ciprian Regus <ciprian.regus@analog.com>");
791 MODULE_LICENSE("GPL");
792