xref: /linux/drivers/net/ethernet/adi/adin1140.c (revision 91ec2035134982b98fab0609a9fd8480e8217dc1)
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 					       &reg_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, &reg_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