1 /*
2  * Copyright (c) 2023 PHOENIX CONTACT Electronics GmbH
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 #include <zephyr/logging/log.h>
8 LOG_MODULE_REGISTER(eth_adin2111, CONFIG_ETHERNET_LOG_LEVEL);
9 
10 #include <zephyr/net/net_pkt.h>
11 #include <zephyr/net/ethernet.h>
12 #include <zephyr/net/phy.h>
13 
14 #if CONFIG_ETH_ADIN2111_SPI_CFG0
15 #include <zephyr/sys/crc.h>
16 #endif /* CONFIG_ETH_ADIN2111_SPI_CFG0 */
17 #include <string.h>
18 #include <errno.h>
19 
20 #include <zephyr/net/net_if.h>
21 #include <zephyr/net/ethernet.h>
22 #include <zephyr/net/phy.h>
23 #include <zephyr/drivers/ethernet/eth_adin2111.h>
24 
25 #include "phy/phy_adin2111_priv.h"
26 #include "eth_adin2111_priv.h"
27 
28 /* SPI Communication check retry delay */
29 #define ADIN2111_DEV_AWAIT_DELAY_POLL_US	100U
30 /* Number of retries SPI Communication check */
31 #define ADIN2111_DEV_AWAIT_RETRY_COUNT		200U
32 
33 /* ADIN RESETC check retry delay */
34 #define ADIN2111_RESETC_AWAIT_DELAY_POLL_US	100U
35 /* Number of retries for ADIN RESETC check */
36 #define ADIN2111_RESETC_AWAIT_RETRY_COUNT	200U
37 
38 /* Boot delay for clocks stabilisation (maximum 90ms) */
39 #define ADIN2111_HW_BOOT_DELAY_MS		100
40 
41 /* MAC Address Rule and DA Filter multicast slot/idx */
42 #define ADIN2111_MULTICAST_ADDR_SLOT		0U
43 /* MAC Address Rule and DA Filter broadcast slot/idx */
44 #define ADIN2111_BROADCAST_ADDR_SLOT		1U
45 /* MAC Address Rule and DA Filter Port 1 slot/idx */
46 #define ADIN2111_UNICAST_P1_ADDR_SLOT		2U
47 /* MAC Address Rule and DA Filter Port 2 slot/idx */
48 #define ADIN2111_UNICAST_P2_ADDR_SLOT		3U
49 
eth_adin2111_lock(const struct device * dev,k_timeout_t timeout)50 int eth_adin2111_lock(const struct device *dev, k_timeout_t timeout)
51 {
52 	struct adin2111_data *ctx = dev->data;
53 
54 	return k_mutex_lock(&ctx->lock, timeout);
55 }
56 
eth_adin2111_unlock(const struct device * dev)57 int eth_adin2111_unlock(const struct device *dev)
58 {
59 	struct adin2111_data *ctx = dev->data;
60 
61 	return k_mutex_unlock(&ctx->lock);
62 }
63 
eth_adin2111_reg_write(const struct device * dev,const uint16_t reg,const uint32_t val)64 int eth_adin2111_reg_write(const struct device *dev, const uint16_t reg,
65 			   const uint32_t val)
66 {
67 	const struct adin2111_config *cfg = dev->config;
68 	size_t header_size = ADIN2111_WRITE_HEADER_SIZE;
69 	size_t data_size = sizeof(uint32_t);
70 #if CONFIG_ETH_ADIN2111_SPI_CFG0
71 	uint8_t buf[ADIN2111_REG_WRITE_BUF_SIZE_CRC] = { 0 };
72 #else
73 	uint8_t buf[ADIN2111_REG_WRITE_BUF_SIZE] = { 0 };
74 #endif /* CONFIG_ETH_ADIN2111_SPI_CFG0 */
75 
76 	/* spi header */
77 	*(uint16_t *)buf = htons((ADIN2111_WRITE_TXN_CTRL | reg));
78 #if CONFIG_ETH_ADIN2111_SPI_CFG0
79 	buf[2] = crc8_ccitt(0, buf, header_size);
80 	++header_size;
81 #endif /* CONFIG_ETH_ADIN2111_SPI_CFG0 */
82 
83 	/* reg */
84 	*(uint32_t *)(buf + header_size) = htonl(val);
85 #if CONFIG_ETH_ADIN2111_SPI_CFG0
86 	buf[header_size + data_size] = crc8_ccitt(0, &buf[header_size], data_size);
87 	++data_size;
88 #endif /* CONFIG_ETH_ADIN2111_SPI_CFG0 */
89 
90 	const struct spi_buf spi_tx_buf = {
91 		.buf = buf,
92 		.len = header_size + data_size
93 	};
94 	const struct spi_buf_set tx = { .buffers = &spi_tx_buf, .count = 1U };
95 
96 	return spi_write_dt(&cfg->spi, &tx);
97 }
98 
eth_adin2111_reg_read(const struct device * dev,const uint16_t reg,uint32_t * val)99 int eth_adin2111_reg_read(const struct device *dev, const uint16_t reg,
100 			  uint32_t *val)
101 {
102 	const struct adin2111_config *cfg = dev->config;
103 	size_t header_len = ADIN2111_READ_HEADER_SIZE;
104 	size_t read_len = sizeof(uint32_t);
105 	int ret;
106 #if CONFIG_ETH_ADIN2111_SPI_CFG0
107 	uint8_t rcv_crc;
108 	uint8_t comp_crc;
109 	uint8_t buf[ADIN2111_REG_READ_BUF_SIZE_CRC] = { 0 };
110 #else
111 	uint8_t buf[ADIN2111_REG_READ_BUF_SIZE] = { 0 };
112 #endif /* CONFIG_ETH_ADIN2111_SPI_CFG0 */
113 
114 	/* spi header */
115 	*(uint16_t *)buf = htons((ADIN2111_READ_TXN_CTRL | reg));
116 #if CONFIG_ETH_ADIN2111_SPI_CFG0
117 	buf[2] = crc8_ccitt(0, buf, ADIN2111_SPI_HEADER_SIZE);
118 	/* TA */
119 	buf[3] = 0U;
120 	++header_len;
121 	++read_len;
122 #else
123 	/* TA */
124 	buf[2] = 0U;
125 #endif /* CONFIG_ETH_ADIN2111_SPI_CFG0 */
126 
127 	const struct spi_buf tx_buf = { .buf = buf, .len = header_len + read_len };
128 	const struct spi_buf rx_buf = { .buf = buf, .len = header_len + read_len };
129 	const struct spi_buf_set tx = { .buffers = &tx_buf, .count = 1U };
130 	const struct spi_buf_set rx = { .buffers = &rx_buf, .count = 1U };
131 
132 	ret = spi_transceive_dt(&cfg->spi, &tx, &rx);
133 	if (ret < 0) {
134 		return ret;
135 	}
136 
137 #if CONFIG_ETH_ADIN2111_SPI_CFG0
138 	comp_crc = crc8_ccitt(0, &buf[header_len], sizeof(uint32_t));
139 	rcv_crc = buf[header_len + sizeof(uint32_t)];
140 
141 	if (rcv_crc != comp_crc) {
142 		/* invalid crc */
143 		return -EIO;
144 	}
145 #endif /* CONFIG_ETH_ADIN2111_SPI_CFG0 */
146 
147 	*val = ntohl((*(uint32_t *)(&buf[header_len])));
148 
149 	return ret;
150 }
151 
adin2111_read_fifo(const struct device * dev,const uint8_t port)152 static int adin2111_read_fifo(const struct device *dev, const uint8_t port)
153 {
154 	const struct adin2111_config *cfg = dev->config;
155 	struct adin2111_data *ctx = dev->data;
156 	struct net_if *iface;
157 	struct net_pkt *pkt;
158 	size_t header_len = ADIN2111_READ_HEADER_SIZE;
159 	uint16_t fsize_reg = ((port == 0U) ? ADIN2111_P1_RX_FSIZE : ADIN2111_P2_RX_FSIZE);
160 	uint16_t rx_reg = ((port == 0U) ? ADIN2111_P1_RX : ADIN2111_P2_RX);
161 	uint32_t fsize;
162 	uint32_t fsize_real;
163 	uint32_t padding_len;
164 #if CONFIG_ETH_ADIN2111_SPI_CFG0
165 	uint8_t cmd_buf[ADIN2111_FIFO_READ_CMD_BUF_SIZE_CRC] = { 0 };
166 #else
167 	uint8_t cmd_buf[ADIN2111_FIFO_READ_CMD_BUF_SIZE] = { 0 };
168 #endif /* CONFIG_ETH_ADIN2111_SPI_CFG0 */
169 	int ret;
170 
171 	iface = ((struct adin2111_port_data *)ctx->port[port]->data)->iface;
172 
173 	/* get received frame size in bytes */
174 	ret = eth_adin2111_reg_read(dev, fsize_reg, &fsize);
175 	if (ret < 0) {
176 		eth_stats_update_errors_rx(iface);
177 		LOG_ERR("Port %u failed to read RX FSIZE, %d", port, ret);
178 		return ret;
179 	}
180 
181 	/* burst read must be in multiples of 4 */
182 	padding_len = ((fsize % 4) == 0) ? 0U : (ROUND_UP(fsize, 4U) - fsize);
183 	/* actual frame length is FSIZE - FRAME HEADER */
184 	fsize_real = fsize - ADIN2111_FRAME_HEADER_SIZE;
185 
186 	/* spi header */
187 	*(uint16_t *)cmd_buf = htons((ADIN2111_READ_TXN_CTRL | rx_reg));
188 #if CONFIG_ETH_ADIN2111_SPI_CFG0
189 	cmd_buf[2] = crc8_ccitt(0, cmd_buf, ADIN2111_SPI_HEADER_SIZE);
190 	/* TA */
191 	cmd_buf[3] = 0U;
192 	++header_len;
193 #else
194 	/* TA */
195 	cmd_buf[2] = 0U;
196 #endif /* CONFIG_ETH_ADIN2111_SPI_CFG0 */
197 
198 	const struct spi_buf tx_buf = { .buf = cmd_buf, .len = sizeof(cmd_buf) };
199 	const struct spi_buf rx_buf[3] = {
200 		{.buf = NULL, .len = sizeof(cmd_buf) + ADIN2111_FRAME_HEADER_SIZE},
201 		{.buf = ctx->buf, .len = fsize_real},
202 		{.buf = NULL, .len = padding_len }
203 	};
204 	const struct spi_buf_set tx = { .buffers = &tx_buf, .count = 1U };
205 	const struct spi_buf_set rx = {
206 		.buffers = rx_buf,
207 		.count = ((padding_len == 0U) ? 2U : 3U)
208 	};
209 
210 	ret = spi_transceive_dt(&cfg->spi, &tx, &rx);
211 	if (ret < 0) {
212 		eth_stats_update_errors_rx(iface);
213 		LOG_ERR("Port %u failed to read RX FIFO, %d", port, ret);
214 		return ret;
215 	}
216 
217 	pkt = net_pkt_rx_alloc_with_buffer(iface, fsize_real, AF_UNSPEC, 0,
218 					   K_MSEC(CONFIG_ETH_ADIN2111_TIMEOUT));
219 	if (!pkt) {
220 		eth_stats_update_errors_rx(iface);
221 		LOG_ERR("Port %u failed to alloc frame RX buffer, %u bytes",
222 			port, fsize_real);
223 		return -ENOMEM;
224 	}
225 
226 	ret = net_pkt_write(pkt, ctx->buf, fsize_real);
227 	if (ret < 0) {
228 		eth_stats_update_errors_rx(iface);
229 		net_pkt_unref(pkt);
230 		LOG_ERR("Port %u failed to fill RX frame, %d", port, ret);
231 		return ret;
232 	}
233 
234 	ret = net_recv_data(iface, pkt);
235 	if (ret < 0) {
236 		eth_stats_update_errors_rx(iface);
237 		net_pkt_unref(pkt);
238 		LOG_ERR("Port %u failed to enqueue frame to RX queue, %d",
239 			port, ret);
240 		return ret;
241 	}
242 
243 	eth_stats_update_bytes_rx(iface, fsize_real);
244 	eth_stats_update_pkts_rx(iface);
245 
246 	return ret;
247 }
248 
adin2111_port_on_phyint(const struct device * dev)249 static inline void adin2111_port_on_phyint(const struct device *dev)
250 {
251 	const struct adin2111_port_config *cfg = dev->config;
252 	struct adin2111_port_data *data = dev->data;
253 	struct phy_link_state state;
254 
255 	if (phy_adin2111_handle_phy_irq(cfg->phy, &state) < 0) {
256 		/* no change or error */
257 		return;
258 	}
259 
260 	if (state.is_up) {
261 		net_eth_carrier_on(data->iface);
262 	} else {
263 		net_eth_carrier_off(data->iface);
264 	}
265 }
266 
adin2111_offload_thread(void * p1,void * p2,void * p3)267 static void adin2111_offload_thread(void *p1, void *p2, void *p3)
268 {
269 	ARG_UNUSED(p2);
270 	ARG_UNUSED(p3);
271 
272 	const struct device *dev = p1;
273 	struct adin2111_data *ctx = dev->data;
274 	const struct adin2111_config *adin_cfg = dev->config;
275 	bool is_adin2111 = (adin_cfg->id == ADIN2111_MAC);
276 	uint32_t status0;
277 	uint32_t status1;
278 	int ret;
279 
280 	for (;;) {
281 		/* await INT */
282 		k_sem_take(&ctx->offload_sem, K_FOREVER);
283 
284 		/* lock device */
285 		eth_adin2111_lock(dev, K_FOREVER);
286 
287 		/* disable interrupts */
288 		ret = eth_adin2111_reg_write(dev, ADIN2111_IMASK0, UINT32_MAX);
289 		if (ret < 0) {
290 			goto continue_unlock;
291 		}
292 		ret = eth_adin2111_reg_write(dev, ADIN2111_IMASK1, UINT32_MAX);
293 		if (ret < 0) {
294 			goto continue_unlock;
295 		}
296 
297 		/* read interrupts */
298 		ret = eth_adin2111_reg_read(dev, ADIN2111_STATUS0, &status0);
299 		if (ret < 0) {
300 			goto continue_unlock;
301 		}
302 		ret = eth_adin2111_reg_read(dev, ADIN2111_STATUS1, &status1);
303 		if (ret < 0) {
304 			goto continue_unlock;
305 		}
306 
307 #if CONFIG_ETH_ADIN2111_SPI_CFG0
308 		if (status0 & ADIN2111_STATUS1_SPI_ERR) {
309 			LOG_WRN("Detected TX SPI CRC error");
310 		}
311 #endif /* CONFIG_ETH_ADIN2111_SPI_CFG0 */
312 
313 		/* handle port 1 phy interrupts */
314 		if (status0 & ADIN2111_STATUS0_PHYINT) {
315 			adin2111_port_on_phyint(ctx->port[0]);
316 		}
317 
318 		/* handle port 2 phy interrupts */
319 		if ((status1 & ADIN2111_STATUS1_PHYINT) && is_adin2111) {
320 			adin2111_port_on_phyint(ctx->port[1]);
321 		}
322 
323 		/* handle port 1 rx */
324 		if (status1 & ADIN2111_STATUS1_P1_RX_RDY) {
325 			do {
326 				ret = adin2111_read_fifo(dev, 0U);
327 				if (ret < 0) {
328 					break;
329 				}
330 
331 				ret = eth_adin2111_reg_read(dev, ADIN2111_STATUS1, &status1);
332 				if (ret < 0) {
333 					goto continue_unlock;
334 				}
335 			} while (!!(status1 & ADIN2111_STATUS1_P1_RX_RDY));
336 		}
337 
338 		/* handle port 2 rx */
339 		if ((status1 & ADIN2111_STATUS1_P2_RX_RDY) && is_adin2111) {
340 			do {
341 				ret = adin2111_read_fifo(dev, 1U);
342 				if (ret < 0) {
343 					break;
344 				}
345 
346 				ret = eth_adin2111_reg_read(dev, ADIN2111_STATUS1, &status1);
347 				if (ret < 0) {
348 					goto continue_unlock;
349 				}
350 			} while (!!(status1 & ADIN2111_STATUS1_P2_RX_RDY));
351 		}
352 
353 continue_unlock:
354 		/* clear interrupts */
355 		ret = eth_adin2111_reg_write(dev, ADIN2111_STATUS0, ADIN2111_STATUS0_CLEAR);
356 		if (ret < 0) {
357 			LOG_ERR("Failed to clear STATUS0, %d", ret);
358 		}
359 		ret = eth_adin2111_reg_write(dev, ADIN2111_STATUS1, ADIN2111_STATUS1_CLEAR);
360 		if (ret < 0) {
361 			LOG_ERR("Failed to clear STATUS1, %d", ret);
362 		}
363 		/* enable interrupts */
364 		ret = eth_adin2111_reg_write(dev, ADIN2111_IMASK0, ctx->imask0);
365 		if (ret < 0) {
366 			LOG_ERR("Failed to write IMASK0, %d", ret);
367 		}
368 		ret = eth_adin2111_reg_write(dev, ADIN2111_IMASK1, ctx->imask1);
369 		if (ret < 0) {
370 			LOG_ERR("Failed to write IMASK1, %d", ret);
371 		}
372 		eth_adin2111_unlock(dev);
373 	};
374 }
375 
adin2111_int_callback(const struct device * dev,struct gpio_callback * cb,uint32_t pins)376 static void adin2111_int_callback(const struct device *dev,
377 				  struct gpio_callback *cb,
378 				  uint32_t pins)
379 {
380 	ARG_UNUSED(dev);
381 	ARG_UNUSED(pins);
382 
383 	struct adin2111_data *ctx = CONTAINER_OF(cb, struct adin2111_data, gpio_int_callback);
384 
385 	k_sem_give(&ctx->offload_sem);
386 }
387 
adin2111_read_tx_space(const struct device * dev,uint32_t * space)388 static int adin2111_read_tx_space(const struct device *dev, uint32_t *space)
389 {
390 	uint32_t val;
391 	int ret;
392 
393 	ret = eth_adin2111_reg_read(dev, ADIN2111_TX_SPACE, &val);
394 	if (ret < 0) {
395 		return ret;
396 	}
397 
398 	/* tx space is a number of halfwords (16-bits), multiply by 2 for bytes */
399 	*space = val * 2;
400 
401 	return ret;
402 }
403 
adin2111_port_send(const struct device * dev,struct net_pkt * pkt)404 static int adin2111_port_send(const struct device *dev, struct net_pkt *pkt)
405 {
406 	const struct adin2111_port_config *cfg = dev->config;
407 #if defined(CONFIG_NET_STATISTICS_ETHERNET)
408 	struct adin2111_port_data *data = dev->data;
409 #endif /* CONFIG_NET_STATISTICS_ETHERNET */
410 	const struct device *adin = cfg->adin;
411 	struct adin2111_data *ctx = cfg->adin->data;
412 	size_t pkt_len = net_pkt_get_len(pkt);
413 	size_t header_size = ADIN2111_WRITE_HEADER_SIZE;
414 	size_t padded_size;
415 	size_t burst_size;
416 	uint32_t tx_space;
417 	int ret;
418 
419 	eth_adin2111_lock(adin, K_FOREVER);
420 
421 	/* query remaining tx fifo space */
422 	ret = adin2111_read_tx_space(adin, &tx_space);
423 	if (ret < 0) {
424 		eth_stats_update_errors_tx(data->iface);
425 		LOG_ERR("Failed to read TX FIFO space, %d", ret);
426 		goto end_unlock;
427 	}
428 
429 	/**
430 	 * verify that there is space for the frame
431 	 * (frame + 2b header + 2b size field)
432 	 */
433 	if (tx_space <
434 	   (pkt_len + ADIN2111_FRAME_HEADER_SIZE + ADIN2111_INTERNAL_HEADER_SIZE)) {
435 		/* tx buffer is full */
436 		eth_stats_update_errors_tx(data->iface);
437 		ret = -EBUSY;
438 		goto end_unlock;
439 	}
440 
441 	/**
442 	 * pad to 64 bytes, otherwise MAC/PHY has to do it
443 	 * internally MAC adds 4 bytes for forward error correction
444 	 */
445 	if ((pkt_len + ADIN2111_TX_FIFO_BUFFER_MARGIN) < 64) {
446 		padded_size = pkt_len
447 			+ (64 - (pkt_len + ADIN2111_TX_FIFO_BUFFER_MARGIN))
448 			+ ADIN2111_FRAME_HEADER_SIZE;
449 	} else {
450 		padded_size = pkt_len + ADIN2111_FRAME_HEADER_SIZE;
451 	}
452 
453 	/* prepare burst write (write data must be in multiples of 4) */
454 	burst_size = ROUND_UP(padded_size, 4);
455 	if ((burst_size + ADIN2111_WRITE_HEADER_SIZE) > CONFIG_ETH_ADIN2111_BUFFER_SIZE) {
456 		ret = -ENOMEM;
457 		eth_stats_update_errors_tx(data->iface);
458 		goto end_unlock;
459 	}
460 
461 	/* prepare tx buffer */
462 	memset(ctx->buf, 0, burst_size + ADIN2111_WRITE_HEADER_SIZE);
463 
464 	/* spi header */
465 	*(uint16_t *)ctx->buf = htons(ADIN2111_TXN_CTRL_TX_REG);
466 #if CONFIG_ETH_ADIN2111_SPI_CFG0
467 	ctx->buf[2] = crc8_ccitt(0, ctx->buf, header_size);
468 	++header_size;
469 #endif /* CONFIG_ETH_ADIN2111_SPI_CFG0 */
470 
471 	/* frame header */
472 	*(uint16_t *)(ctx->buf + header_size) = htons(cfg->port_idx);
473 
474 	/* read pkt into tx buffer */
475 	ret = net_pkt_read(pkt,
476 			   (ctx->buf + header_size + ADIN2111_FRAME_HEADER_SIZE),
477 			   pkt_len);
478 	if (ret < 0) {
479 		eth_stats_update_errors_tx(data->iface);
480 		LOG_ERR("Port %u failed to read PKT into TX buffer, %d",
481 			cfg->port_idx, ret);
482 		goto end_unlock;
483 	}
484 
485 	/* write transmit size */
486 	ret = eth_adin2111_reg_write(adin, ADIN2111_TX_FSIZE, padded_size);
487 	if (ret < 0) {
488 		eth_stats_update_errors_tx(data->iface);
489 		LOG_ERR("Port %u write FSIZE failed, %d", cfg->port_idx, ret);
490 		goto end_unlock;
491 	}
492 
493 	/* write transaction */
494 	const struct spi_buf buf = {
495 		.buf = ctx->buf,
496 		.len = header_size + burst_size
497 	};
498 	const struct spi_buf_set tx = { .buffers = &buf, .count = 1U };
499 
500 	ret = spi_write_dt(&((const struct adin2111_config *) adin->config)->spi,
501 			   &tx);
502 	if (ret < 0) {
503 		eth_stats_update_errors_tx(data->iface);
504 		LOG_ERR("Port %u frame SPI write failed, %d", cfg->port_idx, ret);
505 		goto end_unlock;
506 	}
507 
508 	eth_stats_update_bytes_tx(data->iface, pkt_len);
509 	eth_stats_update_pkts_tx(data->iface);
510 
511 end_unlock:
512 	eth_adin2111_unlock(adin);
513 	return ret;
514 }
515 
adin2111_config_sync(const struct device * dev)516 static int adin2111_config_sync(const struct device *dev)
517 {
518 	int ret;
519 	uint32_t val;
520 
521 	ret = eth_adin2111_reg_read(dev, ADIN2111_CONFIG0, &val);
522 	if (ret < 0) {
523 		return ret;
524 	}
525 
526 	val |= ADIN2111_CONFIG0_SYNC;
527 
528 	ret = eth_adin2111_reg_write(dev, ADIN2111_CONFIG0, val);
529 	if (ret < 0) {
530 		return ret;
531 	}
532 
533 	return 0;
534 }
535 
adin2111_write_filter_address(const struct device * dev,uint8_t * addr,uint8_t * mask,uint32_t rules,uint16_t slot)536 static int adin2111_write_filter_address(const struct device *dev,
537 					 uint8_t *addr, uint8_t *mask,
538 					 uint32_t rules, uint16_t slot)
539 {
540 	uint16_t offset = slot * 2U;
541 	int ret;
542 
543 	ret = eth_adin2111_reg_write(dev, ADIN2111_ADDR_FILT_UPR + offset,
544 				     rules | sys_get_be16(&addr[0]));
545 	if (ret < 0) {
546 		return ret;
547 	}
548 
549 	ret = eth_adin2111_reg_write(dev, ADIN2111_ADDR_FILT_LWR  + offset,
550 				     sys_get_be32(&addr[2]));
551 	if (ret < 0) {
552 		return ret;
553 	}
554 
555 	if (offset > 2U) {
556 		/* mask filter addresses are limited to 2 */
557 		return 0;
558 	}
559 
560 	ret = eth_adin2111_reg_write(dev, ADIN2111_ADDR_MSK_UPR + offset,
561 				     sys_get_be16(&mask[0]));
562 	if (ret < 0) {
563 		return ret;
564 	}
565 
566 	ret = eth_adin2111_reg_write(dev, ADIN2111_ADDR_MSK_LWR + offset,
567 				     sys_get_be32(&mask[2]));
568 	if (ret < 0) {
569 		return ret;
570 	}
571 
572 	return ret;
573 }
574 
adin2111_filter_multicast(const struct device * dev)575 static int adin2111_filter_multicast(const struct device *dev)
576 {
577 	const struct adin2111_config *cfg = dev->config;
578 	bool is_adin2111 = (cfg->id == ADIN2111_MAC);
579 	uint8_t mm[6] = {BIT(0), 0U,  0U, 0U, 0U, 0U};
580 	uint32_t rules = ADIN2111_ADDR_APPLY2PORT1 |
581 			 (is_adin2111 ? ADIN2111_ADDR_APPLY2PORT2 : 0) |
582 			 ADIN2111_ADDR_TO_HOST |
583 			 ADIN2111_ADDR_TO_OTHER_PORT;
584 
585 	return adin2111_write_filter_address(dev, mm, mm, rules,
586 					     ADIN2111_MULTICAST_ADDR_SLOT);
587 }
588 
adin2111_filter_broadcast(const struct device * dev)589 static int adin2111_filter_broadcast(const struct device *dev)
590 {
591 	const struct adin2111_config *cfg = dev->config;
592 	bool is_adin2111 = (cfg->id == ADIN2111_MAC);
593 	uint8_t mac[] = {0xFFU, 0xFFU, 0xFFU, 0xFFU, 0xFFU, 0xFFU};
594 	uint32_t rules = ADIN2111_ADDR_APPLY2PORT1 |
595 			 (is_adin2111 ? ADIN2111_ADDR_APPLY2PORT2 : 0) |
596 			 ADIN2111_ADDR_TO_HOST |
597 			 ADIN2111_ADDR_TO_OTHER_PORT;
598 
599 	return adin2111_write_filter_address(dev, mac, mac, rules,
600 					     ADIN2111_BROADCAST_ADDR_SLOT);
601 }
602 
adin2111_filter_unicast(const struct device * dev,uint8_t * addr,uint8_t port_idx)603 static int adin2111_filter_unicast(const struct device *dev, uint8_t *addr,
604 				   uint8_t port_idx)
605 {
606 	uint32_t rules = (port_idx == 0 ? ADIN2111_ADDR_APPLY2PORT1
607 					: ADIN2111_ADDR_APPLY2PORT2)
608 			 | ADIN2111_ADDR_TO_HOST;
609 	uint16_t slot = (port_idx == 0 ? ADIN2111_UNICAST_P1_ADDR_SLOT
610 				       : ADIN2111_UNICAST_P2_ADDR_SLOT);
611 
612 	return adin2111_write_filter_address(dev, addr, NULL, rules, slot);
613 }
614 
adin2111_port_iface_init(struct net_if * iface)615 static void adin2111_port_iface_init(struct net_if *iface)
616 {
617 	const struct device *dev = net_if_get_device(iface);
618 	const struct adin2111_port_config *cfg = dev->config;
619 	struct adin2111_port_data *data = dev->data;
620 	const struct device *adin = cfg->adin;
621 	struct adin2111_data *ctx = adin->data;
622 	int ret;
623 
624 	if (!device_is_ready(adin)) {
625 		LOG_ERR("ADIN %s is not ready, can't init port %u iface",
626 			cfg->adin->name, cfg->port_idx);
627 		return;
628 	}
629 
630 	if (!device_is_ready(cfg->phy)) {
631 		LOG_ERR("PHY %u is not ready, can't init port %u iface",
632 			cfg->phy_addr, cfg->port_idx);
633 		return;
634 	}
635 
636 	ctx->port[cfg->port_idx] = dev;
637 	data->iface = iface;
638 
639 	ret = adin2111_filter_unicast(adin, data->mac_addr, cfg->port_idx);
640 	if (ret < 0) {
641 		LOG_ERR("Port %u, failed to set unicast filter, %d",
642 			cfg->port_idx, ret);
643 		return;
644 	}
645 	net_if_set_link_addr(iface, data->mac_addr, sizeof(data->mac_addr),
646 			     NET_LINK_ETHERNET);
647 	ethernet_init(iface);
648 	net_if_carrier_off(iface);
649 
650 	--ctx->ifaces_left_to_init;
651 
652 	/* if all ports are initialized */
653 	if (ctx->ifaces_left_to_init == 0U) {
654 		/* setup rx filters */
655 		ret = adin2111_filter_multicast(adin);
656 		if (ret < 0) {
657 			LOG_ERR("Couldn't set multicast filter, %d", ret);
658 			return;
659 		}
660 		ret = adin2111_filter_broadcast(adin);
661 		if (ret < 0) {
662 			LOG_ERR("Couldn't set broadcast filter, %d", ret);
663 			return;
664 		}
665 
666 		/* sync */
667 		ret = adin2111_config_sync(adin);
668 		if (ret < 0) {
669 			LOG_ERR("Failed to write CONFIG0 SYNC, %d", ret);
670 			return;
671 		}
672 
673 		/* all ifaces are done, start INT processing */
674 		k_thread_create(&ctx->rx_thread, ctx->rx_thread_stack,
675 				CONFIG_ETH_ADIN2111_IRQ_THREAD_STACK_SIZE,
676 				adin2111_offload_thread,
677 				(void *)adin, NULL, NULL,
678 				CONFIG_ETH_ADIN2111_IRQ_THREAD_PRIO,
679 				K_ESSENTIAL, K_NO_WAIT);
680 		k_thread_name_set(&ctx->rx_thread, "eth_adin2111_offload");
681 	}
682 }
683 
adin2111_port_get_capabilities(const struct device * dev)684 static enum ethernet_hw_caps adin2111_port_get_capabilities(const struct device *dev)
685 {
686 	ARG_UNUSED(dev);
687 	return ETHERNET_LINK_10BASE_T
688 #if defined(CONFIG_NET_LLDP)
689 		| ETHERNET_LLDP
690 #endif
691 		;
692 }
693 
adin2111_port_set_config(const struct device * dev,enum ethernet_config_type type,const struct ethernet_config * config)694 static int adin2111_port_set_config(const struct device *dev,
695 				    enum ethernet_config_type type,
696 				    const struct ethernet_config *config)
697 {
698 	const struct adin2111_port_config *cfg = dev->config;
699 	struct adin2111_port_data *data = dev->data;
700 	const struct device *adin = cfg->adin;
701 	int ret = -ENOTSUP;
702 
703 	(void)eth_adin2111_lock(adin, K_FOREVER);
704 
705 	if (type == ETHERNET_CONFIG_TYPE_MAC_ADDRESS) {
706 		ret = adin2111_filter_unicast(adin, (uint8_t *)&config->mac_address.addr[0],
707 					      cfg->port_idx);
708 		if (ret < 0) {
709 			goto end_unlock;
710 		}
711 
712 		(void)memcpy(data->mac_addr, config->mac_address.addr, sizeof(data->mac_addr));
713 
714 		(void)net_if_set_link_addr(data->iface, data->mac_addr, sizeof(data->mac_addr),
715 					   NET_LINK_ETHERNET);
716 	}
717 
718 end_unlock:
719 	(void)eth_adin2111_unlock(adin);
720 	return ret;
721 }
722 
723 #if defined(CONFIG_NET_STATISTICS_ETHERNET)
adin2111_port_get_stats(const struct device * dev)724 static struct net_stats_eth *adin2111_port_get_stats(const struct device *dev)
725 {
726 	struct adin2111_port_data *data = dev->data;
727 
728 	return &data->stats;
729 }
730 #endif /* CONFIG_NET_STATISTICS_ETHERNET */
731 
adin2111_check_spi(const struct device * dev)732 static int adin2111_check_spi(const struct device *dev)
733 {
734 	uint32_t count;
735 	uint32_t val;
736 	int ret;
737 
738 	/* check SPI communication by reading PHYID */
739 	for (count = 0U; count < ADIN2111_DEV_AWAIT_RETRY_COUNT; ++count) {
740 		ret = eth_adin2111_reg_read(dev, ADIN2111_PHYID, &val);
741 		if (ret >= 0) {
742 			if (val == ADIN2111_PHYID_RST_VAL || val == ADIN1110_PHYID_RST_VAL) {
743 				break;
744 			}
745 			ret = -ETIMEDOUT;
746 		}
747 		k_sleep(K_USEC(ADIN2111_DEV_AWAIT_DELAY_POLL_US));
748 	}
749 
750 	return ret;
751 }
752 
adin2111_await_device(const struct device * dev)753 static int adin2111_await_device(const struct device *dev)
754 {
755 	uint32_t count;
756 	uint32_t val;
757 	int ret;
758 
759 	/* await reset complete (RESETC) and clear it */
760 	for (count = 0U; count < ADIN2111_RESETC_AWAIT_RETRY_COUNT; ++count) {
761 		ret = eth_adin2111_reg_read(dev, ADIN2111_STATUS0, &val);
762 		if (ret >= 0) {
763 			/* if out of reset */
764 			if (val & ADIN2111_STATUS0_RESETC) {
765 				/* clear RESETC */
766 				ret = eth_adin2111_reg_write(dev, ADIN2111_STATUS0,
767 							 ADIN2111_STATUS0_RESETC);
768 				if (ret >= 0) {
769 					break;
770 				}
771 			}
772 			ret = -ETIMEDOUT;
773 		}
774 		k_sleep(K_USEC(ADIN2111_RESETC_AWAIT_DELAY_POLL_US));
775 	}
776 
777 	return ret;
778 }
779 
adin2111_init(const struct device * dev)780 static int adin2111_init(const struct device *dev)
781 {
782 	const struct adin2111_config *cfg = dev->config;
783 	bool is_adin2111 = (cfg->id == ADIN2111_MAC);
784 	struct adin2111_data *ctx = dev->data;
785 	int ret;
786 	uint32_t val;
787 
788 	__ASSERT(cfg->spi.config.frequency <= ADIN2111_SPI_MAX_FREQUENCY,
789 		 "SPI frequency exceeds supported maximum\n");
790 
791 	if (!spi_is_ready_dt(&cfg->spi)) {
792 		LOG_ERR("SPI bus %s not ready", cfg->spi.bus->name);
793 		return -ENODEV;
794 	}
795 
796 	if (!gpio_is_ready_dt(&cfg->interrupt)) {
797 		LOG_ERR("Interrupt GPIO device %s is not ready",
798 			cfg->interrupt.port->name);
799 		return -ENODEV;
800 	}
801 
802 	ret = gpio_pin_configure_dt(&cfg->interrupt, GPIO_INPUT);
803 	if (ret < 0) {
804 		LOG_ERR("Failed to configure interrupt GPIO, %d", ret);
805 		return ret;
806 	}
807 
808 	if (cfg->reset.port != NULL) {
809 		if (!gpio_is_ready_dt(&cfg->reset)) {
810 			LOG_ERR("Reset GPIO device %s is not ready",
811 			cfg->reset.port->name);
812 			return -ENODEV;
813 		}
814 
815 		ret = gpio_pin_configure_dt(&cfg->reset, GPIO_OUTPUT_INACTIVE);
816 		if (ret < 0) {
817 			LOG_ERR("Failed to configure reset GPIO, %d", ret);
818 			return ret;
819 		}
820 
821 		/* perform hard reset */
822 		/* assert pin low for 16 µs (10 µs min) */
823 		gpio_pin_set_dt(&cfg->reset, 1);
824 		k_busy_wait(16U);
825 		/* deassert and wait for 90 ms (max) for clocks stabilisation */
826 		gpio_pin_set_dt(&cfg->reset, 0);
827 		k_msleep(ADIN2111_HW_BOOT_DELAY_MS);
828 	}
829 
830 	gpio_init_callback(&(ctx->gpio_int_callback),
831 			   adin2111_int_callback,
832 			   BIT(cfg->interrupt.pin));
833 
834 	ret = gpio_add_callback(cfg->interrupt.port, &ctx->gpio_int_callback);
835 	if (ret < 0) {
836 		LOG_ERR("Failed to add INT callback, %d", ret);
837 		return ret;
838 	}
839 
840 	ret = adin2111_check_spi(dev);
841 	if (ret < 0) {
842 		LOG_ERR("Failed to communicate over SPI, %d", ret);
843 		return ret;
844 	}
845 
846 	/* perform MACPHY soft reset */
847 	ret = eth_adin2111_reg_write(dev, ADIN2111_RESET, ADIN2111_RESET_SWRESET);
848 	if (ret < 0) {
849 		LOG_ERR("MACPHY software reset failed, %d", ret);
850 		return ret;
851 	}
852 
853 	ret = adin2111_await_device(dev);
854 	if (ret < 0) {
855 		LOG_ERR("ADIN did't come out of the reset, %d", ret);
856 		return ret;
857 	}
858 
859 	/* CONFIG 0 */
860 	/* disable Frame Check Sequence validation on the host */
861 	/* if that is enabled, then CONFIG_ETH_ADIN2111_SPI_CFG0 must be off */
862 	ret = eth_adin2111_reg_read(dev, ADIN2111_CONFIG0, &val);
863 	if (ret < 0) {
864 		LOG_ERR("Failed to read CONFIG0, %d", ret);
865 		return ret;
866 	}
867 
868 	/* RXCTE must be disabled for Generic SPI */
869 	val &= ~ADIN2111_CONFIG0_RXCTE;
870 	val &= ~(ADIN2111_CONFIG0_TXCTE | ADIN2111_CONFIG0_TXFCSVE);
871 
872 	ret = eth_adin2111_reg_write(dev, ADIN2111_CONFIG0, val);
873 	if (ret < 0) {
874 		LOG_ERR("Failed to write CONFIG0, %d", ret);
875 		return ret;
876 	}
877 
878 	/* CONFIG 2 */
879 	ret = eth_adin2111_reg_read(dev, ADIN2111_CONFIG2, &val);
880 	if (ret < 0) {
881 		LOG_ERR("Failed to read CONFIG2, %d", ret);
882 		return ret;
883 	}
884 
885 #if CONFIG_ETH_ADIN2111_SPI_CFG0
886 	val |= ADIN2111_CONFIG2_CRC_APPEND;
887 #else
888 	val &= ~ADIN2111_CONFIG2_CRC_APPEND;
889 #endif /* CONFIG_ETH_ADIN2111_SPI_CFG0 */
890 
891 	/* configure forwarding of frames with unknown destination address */
892 	/* to the other port. This forwarding is done in hardware.         */
893 	/* The setting will take effect after the ports                    */
894 	/* are out of software powerdown.                                  */
895 	val |= (ADIN2111_CONFIG2_PORT_CUT_THRU_EN |
896 		(is_adin2111 ? ADIN2111_CONFIG2_P1_FWD_UNK2P2 : 0) |
897 		(is_adin2111 ? ADIN2111_CONFIG2_P2_FWD_UNK2P1 : 0));
898 
899 	ret = eth_adin2111_reg_write(dev, ADIN2111_CONFIG2, val);
900 	if (ret < 0) {
901 		LOG_ERR("Failed to write CONFIG2, %d", ret);
902 		return ret;
903 	}
904 
905 	/* configure interrupt masks */
906 	ctx->imask0 = ~ADIN2111_IMASK0_PHYINTM;
907 	ctx->imask1 = ~(ADIN2111_IMASK1_TX_RDY_MASK |
908 			ADIN2111_IMASK1_P1_RX_RDY_MASK |
909 			ADIN2111_IMASK1_SPI_ERR_MASK |
910 			(is_adin2111 ? ADIN2111_IMASK1_P2_RX_RDY_MASK : 0) |
911 			(is_adin2111 ? ADIN2111_IMASK1_P2_PHYINT_MASK : 0));
912 
913 	/* enable interrupts */
914 	ret = eth_adin2111_reg_write(dev, ADIN2111_IMASK0, ctx->imask0);
915 	if (ret < 0) {
916 		LOG_ERR("Failed to write IMASK0, %d", ret);
917 		return ret;
918 	}
919 	ret = eth_adin2111_reg_write(dev, ADIN2111_IMASK1, ctx->imask1);
920 	if (ret < 0) {
921 		LOG_ERR("Failed to write IMASK1, %d", ret);
922 		return ret;
923 	}
924 
925 	ret = gpio_pin_interrupt_configure_dt(&cfg->interrupt,
926 						GPIO_INT_EDGE_TO_ACTIVE);
927 	if (ret < 0) {
928 		LOG_ERR("Failed to enable INT, %d", ret);
929 		return ret;
930 	}
931 
932 	return ret;
933 }
934 
935 static const struct ethernet_api adin2111_port_api = {
936 	.iface_api.init = adin2111_port_iface_init,
937 	.get_capabilities = adin2111_port_get_capabilities,
938 	.set_config = adin2111_port_set_config,
939 	.send = adin2111_port_send,
940 #if defined(CONFIG_NET_STATISTICS_ETHERNET)
941 	.get_stats = adin2111_port_get_stats,
942 #endif /* CONFIG_NET_STATISTICS_ETHERNET */
943 };
944 
945 #define ADIN2111_STR(x)		#x
946 #define ADIN2111_XSTR(x)	ADIN2111_STR(x)
947 
948 #define ADIN2111_MDIO_PHY_BY_ADDR(adin_n, phy_addr)						\
949 	DEVICE_DT_GET(DT_CHILD(DT_INST_CHILD(adin_n, mdio), ethernet_phy_##phy_addr))
950 
951 #define ADIN2111_PORT_MAC(adin_n, port_n)							\
952 	DT_PROP(DT_CHILD(DT_DRV_INST(adin_n), port##port_n), local_mac_address)
953 
954 #define ADIN2111_PORT_DEVICE_INIT_INSTANCE(parent_n, port_n, phy_n, name)			\
955 	static struct adin2111_port_data name##_port_data_##port_n = {				\
956 		.mac_addr = ADIN2111_PORT_MAC(parent_n, phy_n),					\
957 	};											\
958 	static const struct adin2111_port_config name##_port_config_##port_n = {		\
959 		.adin = DEVICE_DT_INST_GET(parent_n),						\
960 		.phy = ADIN2111_MDIO_PHY_BY_ADDR(parent_n, phy_n),				\
961 		.port_idx = port_n,								\
962 		.phy_addr = phy_n,								\
963 	};											\
964 	NET_DEVICE_INIT_INSTANCE(name##_port_##port_n, "port_" ADIN2111_XSTR(port_n), port_n,	\
965 				 NULL, NULL, &name##_port_data_##port_n,			\
966 				 &name##_port_config_##port_n, CONFIG_ETH_INIT_PRIORITY,	\
967 				 &adin2111_port_api, ETHERNET_L2,				\
968 				 NET_L2_GET_CTX_TYPE(ETHERNET_L2), NET_ETH_MTU);
969 
970 #define ADIN2111_SPI_OPERATION ((uint16_t)(SPI_OP_MODE_MASTER | SPI_TRANSFER_MSB | SPI_WORD_SET(8)))
971 
972 #define ADIN2111_MAC_INITIALIZE(inst, dev_id, ifaces, name)					\
973 	static uint8_t __aligned(4) name##_buffer_##inst[CONFIG_ETH_ADIN2111_BUFFER_SIZE];	\
974 	static const struct adin2111_config name##_config_##inst = {				\
975 		.id = dev_id,								\
976 		.spi = SPI_DT_SPEC_INST_GET(inst, ADIN2111_SPI_OPERATION, 1),			\
977 		.interrupt = GPIO_DT_SPEC_INST_GET(inst, int_gpios),				\
978 		.reset = GPIO_DT_SPEC_INST_GET_OR(inst, reset_gpios, { 0 }),			\
979 	};											\
980 	static struct adin2111_data name##_data_##inst = {					\
981 		.ifaces_left_to_init = ifaces,							\
982 		.port = {},									\
983 		.offload_sem = Z_SEM_INITIALIZER(name##_data_##inst.offload_sem, 0, 1),         \
984 		.lock = Z_MUTEX_INITIALIZER(name##_data_##inst.lock),				\
985 		.buf = name##_buffer_##inst,							\
986 	};											\
987 	/* adin */										\
988 	DEVICE_DT_DEFINE(DT_DRV_INST(inst), adin2111_init, NULL,				\
989 			 &name##_data_##inst, &name##_config_##inst,				\
990 			 POST_KERNEL, CONFIG_ETH_INIT_PRIORITY,					\
991 			 NULL);
992 
993 #define ADIN2111_MAC_INIT(inst)	ADIN2111_MAC_INITIALIZE(inst, ADIN2111_MAC, 2, adin2111)	\
994 	/* ports */										\
995 	ADIN2111_PORT_DEVICE_INIT_INSTANCE(inst, 0, 1, adin2111)				\
996 	ADIN2111_PORT_DEVICE_INIT_INSTANCE(inst, 1, 2, adin2111)
997 
998 #undef DT_DRV_COMPAT
999 #define DT_DRV_COMPAT adi_adin2111
1000 DT_INST_FOREACH_STATUS_OKAY(ADIN2111_MAC_INIT)
1001 
1002 #define ADIN1110_MAC_INIT(inst)	ADIN2111_MAC_INITIALIZE(inst, ADIN1110_MAC, 1, adin1110)	\
1003 	/* ports */										\
1004 	ADIN2111_PORT_DEVICE_INIT_INSTANCE(inst, 0, 1, adin1110)
1005 
1006 #undef DT_DRV_COMPAT
1007 #define DT_DRV_COMPAT adi_adin1110
1008 DT_INST_FOREACH_STATUS_OKAY(ADIN1110_MAC_INIT)
1009