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 #define DT_DRV_COMPAT adi_adin2111
29
30 /* SPI Communication check retry delay */
31 #define ADIN2111_DEV_AWAIT_DELAY_POLL_US 100U
32 /* Number of retries SPI Communication check */
33 #define ADIN2111_DEV_AWAIT_RETRY_COUNT 200U
34
35 /* ADIN RESETC check retry delay */
36 #define ADIN2111_RESETC_AWAIT_DELAY_POLL_US 100U
37 /* Number of retries for ADIN RESETC check */
38 #define ADIN2111_RESETC_AWAIT_RETRY_COUNT 200U
39
40 /* Boot delay for clocks stabilisation (maximum 90ms) */
41 #define ADIN2111_HW_BOOT_DELAY_MS 100
42
43 /* MAC Address Rule and DA Filter multicast slot/idx */
44 #define ADIN2111_MULTICAST_ADDR_SLOT 0U
45 /* MAC Address Rule and DA Filter broadcast slot/idx */
46 #define ADIN2111_BROADCAST_ADDR_SLOT 1U
47 /* MAC Address Rule and DA Filter Port 1 slot/idx */
48 #define ADIN2111_UNICAST_P1_ADDR_SLOT 2U
49 /* MAC Address Rule and DA Filter Port 2 slot/idx */
50 #define ADIN2111_UNICAST_P2_ADDR_SLOT 3U
51 /* Free slots for further filtering */
52 #define ADIN2111_FILTER_FIRST_SLOT 4U
53 #define ADIN2111_FILTER_SLOTS 16U
54
55 /* As per RM rev. A table 3, t3 >= 50ms, delay for SPI interface to be ready */
56 #define ADIN2111_SPI_ACTIVE_DELAY_MS 50U
57 /* As per RM rev. A page 20: approximately 10 ms (maximum) for internal logic to be ready. */
58 #define ADIN2111_SW_RESET_DELAY_MS 10U
59
eth_adin2111_mac_reset(const struct device * dev)60 int eth_adin2111_mac_reset(const struct device *dev)
61 {
62 uint32_t val;
63 int ret;
64
65 ret = eth_adin2111_reg_write(dev, ADIN2111_SOFT_RST_REG, ADIN2111_SWRESET_KEY1);
66 if (ret < 0) {
67 return ret;
68 }
69 ret = eth_adin2111_reg_write(dev, ADIN2111_SOFT_RST_REG, ADIN2111_SWRESET_KEY2);
70 if (ret < 0) {
71 return ret;
72 }
73 ret = eth_adin2111_reg_write(dev, ADIN2111_SOFT_RST_REG, ADIN2111_SWRELEASE_KEY1);
74 if (ret < 0) {
75 return ret;
76 }
77 ret = eth_adin2111_reg_write(dev, ADIN2111_SOFT_RST_REG, ADIN2111_SWRELEASE_KEY2);
78 if (ret < 0) {
79 return ret;
80 }
81 ret = eth_adin2111_reg_read(dev, ADIN1110_MAC_RST_STATUS_REG, &val);
82 if (ret < 0) {
83 return ret;
84 }
85 if (val == 0) {
86 return -EBUSY;
87 }
88
89 return 0;
90 }
91
eth_adin2111_reg_update(const struct device * dev,const uint16_t reg,uint32_t mask,uint32_t data)92 int eth_adin2111_reg_update(const struct device *dev, const uint16_t reg,
93 uint32_t mask, uint32_t data)
94 {
95 uint32_t val;
96 int ret;
97
98 ret = eth_adin2111_reg_read(dev, reg, &val);
99 if (ret < 0) {
100 return ret;
101 }
102
103 val &= ~mask;
104 val |= mask & data;
105
106 return eth_adin2111_reg_write(dev, reg, val);
107 }
108
eth_adin2111_get_iface(const struct device * dev,const uint16_t port_idx)109 struct net_if *eth_adin2111_get_iface(const struct device *dev, const uint16_t port_idx)
110 {
111 struct adin2111_data *ctx = dev->data;
112
113 return ((struct adin2111_port_data *)ctx->port[port_idx]->data)->iface;
114 }
115
eth_adin2111_lock(const struct device * dev,k_timeout_t timeout)116 int eth_adin2111_lock(const struct device *dev, k_timeout_t timeout)
117 {
118 struct adin2111_data *ctx = dev->data;
119
120 return k_mutex_lock(&ctx->lock, timeout);
121 }
122
eth_adin2111_unlock(const struct device * dev)123 int eth_adin2111_unlock(const struct device *dev)
124 {
125 struct adin2111_data *ctx = dev->data;
126
127 return k_mutex_unlock(&ctx->lock);
128 }
129
eth_adin2111_oa_get_parity(const uint32_t x)130 static inline bool eth_adin2111_oa_get_parity(const uint32_t x)
131 {
132 uint32_t y;
133
134 y = x ^ (x >> 1);
135 y = y ^ (y >> 2);
136 y = y ^ (y >> 4);
137 y = y ^ (y >> 8);
138 y = y ^ (y >> 16);
139
140 return !(y & 1);
141 }
142
eth_adin2111_oa_spi_xfer(const struct device * dev,uint8_t * buf_rx,uint8_t * buf_tx,int len)143 int eth_adin2111_oa_spi_xfer(const struct device *dev, uint8_t *buf_rx, uint8_t *buf_tx, int len)
144 {
145 const struct adin2111_config *cfg = dev->config;
146
147 struct spi_buf tx_buf[1];
148 struct spi_buf rx_buf[1];
149 struct spi_buf_set tx;
150 struct spi_buf_set rx;
151 int ret;
152
153 tx_buf[0].buf = buf_tx;
154 tx_buf[0].len = len;
155 rx_buf[0].buf = buf_rx;
156 rx_buf[0].len = len;
157
158 rx.buffers = rx_buf;
159 rx.count = 1;
160 tx.buffers = tx_buf;
161 tx.count = 1;
162
163 ret = spi_transceive_dt(&cfg->spi, &tx, &rx);
164 if (ret < 0) {
165 LOG_ERR("ERRR dma!\n");
166 return ret;
167 }
168
169 return 0;
170 }
171
eth_adin2111_reg_read_oa(const struct device * dev,const uint16_t reg,uint32_t * val)172 static int eth_adin2111_reg_read_oa(const struct device *dev, const uint16_t reg,
173 uint32_t *val)
174 {
175 struct adin2111_data *ctx = dev->data;
176 uint32_t pval;
177 uint32_t *hdr = (uint32_t *)ctx->oa_tx_buf;
178 int len;
179 int ret;
180
181 *hdr = reg << 8;
182 if (reg >= 0x30) {
183 *hdr |= ADIN2111_OA_CTL_MMS;
184 }
185
186 *hdr |= eth_adin2111_oa_get_parity(*hdr);
187 *hdr = sys_cpu_to_be32(*hdr);
188
189 len = (ctx->oa_prot) ? ADIN2111_OA_CTL_LEN_PROT : ADIN2111_OA_CTL_LEN;
190
191 ret = eth_adin2111_oa_spi_xfer(dev, ctx->oa_rx_buf, ctx->oa_tx_buf, len);
192 if (ret < 0) {
193 return ret;
194 }
195
196 *val = sys_be32_to_cpu(*(uint32_t *)&ctx->oa_rx_buf[8]);
197
198 /* In protected mode read data is followed by its compliment value */
199 if (ctx->oa_prot) {
200 pval = sys_be32_to_cpu(*(uint32_t *)&ctx->oa_rx_buf[12]);
201 if (*val != ~pval) {
202 LOG_ERR("OA protected mode rx error !");
203 return -1;
204 }
205 }
206
207 return 0;
208 }
209
eth_adin2111_reg_write_oa(const struct device * dev,const uint16_t reg,uint32_t val)210 static int eth_adin2111_reg_write_oa(const struct device *dev, const uint16_t reg,
211 uint32_t val)
212 {
213 struct adin2111_data *ctx = dev->data;
214 uint32_t pval;
215 uint32_t *hdr = (uint32_t *)ctx->oa_tx_buf;
216 int len;
217 int ret;
218
219 *hdr = reg << 8 | ADIN2111_OA_CTL_WNR;
220 if (reg >= 0x30) {
221 *hdr |= ADIN2111_OA_CTL_MMS;
222 }
223
224 *hdr |= eth_adin2111_oa_get_parity(*hdr);
225 *hdr = sys_cpu_to_be32(*hdr);
226
227 len = (ctx->oa_prot) ? ADIN2111_OA_CTL_LEN_PROT : ADIN2111_OA_CTL_LEN;
228
229 *(uint32_t *)&ctx->oa_tx_buf[4] = sys_cpu_to_be32(val);
230 if (ctx->oa_prot) {
231 *(uint32_t *)&ctx->oa_tx_buf[8] = sys_cpu_to_be32(~val);
232 }
233
234 ret = eth_adin2111_oa_spi_xfer(dev, ctx->oa_rx_buf, ctx->oa_tx_buf, len);
235 if (ret < 0) {
236 return ret;
237 }
238
239 if (ctx->oa_prot) {
240 pval = sys_be32_to_cpu(*(uint32_t *)&ctx->oa_rx_buf[12]);
241 if (val != ~pval) {
242 LOG_ERR("OA protected mode tx error !");
243 return -1;
244 }
245 }
246
247 return 0;
248 }
249
eth_adin2111_oa_data_read(const struct device * dev,const uint16_t port_idx)250 int eth_adin2111_oa_data_read(const struct device *dev, const uint16_t port_idx)
251 {
252 struct adin2111_data *ctx = dev->data;
253 struct net_if *iface = ((struct adin2111_port_data *)ctx->port[port_idx]->data)->iface;
254 struct net_pkt *pkt;
255 uint32_t hdr, ftr;
256 int i, len, rx_pos, ret, rca, swo;
257
258 ret = eth_adin2111_reg_read(dev, ADIN2111_BUFSTS, &rca);
259 if (ret < 0) {
260 LOG_ERR("can't read BUFSTS");
261 return -EIO;
262 }
263
264 rca &= ADIN2111_BUFSTS_RCA_MASK;
265
266 /* Preare all tx headers */
267 for (i = 0, len = 0; i < rca; ++i) {
268 hdr = ADIN2111_OA_DATA_HDR_DNC;
269 hdr |= eth_adin2111_oa_get_parity(hdr);
270
271 *(uint32_t *)&ctx->oa_tx_buf[len] = sys_cpu_to_be32(hdr);
272
273 len += sizeof(uint32_t) + ctx->oa_cps;
274 }
275
276 ret = eth_adin2111_oa_spi_xfer(dev, ctx->oa_rx_buf, ctx->oa_tx_buf, len);
277 if (ret < 0) {
278 LOG_ERR("SPI xfer failed");
279 return ret;
280 }
281
282 for (i = 0, rx_pos = 0; i < rca; ++i) {
283
284 ftr = sys_be32_to_cpu(*(uint32_t *)&ctx->oa_rx_buf[rx_pos + ctx->oa_cps]);
285
286 if (eth_adin2111_oa_get_parity(ftr)) {
287 LOG_ERR("OA RX: Footer parity error !");
288 return -EIO;
289 }
290 if (!(ftr & ADIN2111_OA_DATA_FTR_SYNC)) {
291 LOG_ERR("OA RX: Configuration not in sync !");
292 return -EIO;
293 }
294 if (!(ftr & ADIN2111_OA_DATA_FTR_DV)) {
295 LOG_DBG("OA RX: Data chunk not valid, skip !");
296 goto update_pos;
297 }
298 if (ftr & ADIN2111_OA_DATA_FTR_SV) {
299 swo = (ftr & ADIN2111_OA_DATA_FTR_SWO_MSK) >> ADIN2111_OA_DATA_FTR_SWO;
300 if (swo != 0) {
301 LOG_ERR("OA RX: Misalignbed start of frame !");
302 return -EIO;
303 }
304 /* Reset store cursor */
305 ctx->scur = 0;
306 }
307
308 len = (ftr & ADIN2111_OA_DATA_FTR_EV) ?
309 ((ftr & ADIN2111_OA_DATA_FTR_EBO_MSK) >> ADIN2111_OA_DATA_FTR_EBO) + 1 :
310 ctx->oa_cps;
311 memcpy(&ctx->buf[ctx->scur], &ctx->oa_rx_buf[rx_pos], len);
312 ctx->scur += len;
313
314 if (ftr & ADIN2111_OA_DATA_FTR_EV) {
315 pkt = net_pkt_rx_alloc_with_buffer(iface, CONFIG_ETH_ADIN2111_BUFFER_SIZE,
316 AF_UNSPEC, 0,
317 K_MSEC(CONFIG_ETH_ADIN2111_TIMEOUT));
318 if (!pkt) {
319 LOG_ERR("OA RX: cannot allcate packet space, skipping.");
320 return -EIO;
321 }
322 /* Skipping CRC32 */
323 ret = net_pkt_write(pkt, ctx->buf, ctx->scur - sizeof(uint32_t));
324 if (ret < 0) {
325 net_pkt_unref(pkt);
326 LOG_ERR("Failed to write pkt, scur %d, err %d", ctx->scur, ret);
327 return ret;
328 }
329 ret = net_recv_data(iface, pkt);
330 if (ret < 0) {
331 net_pkt_unref(pkt);
332 LOG_ERR("Port %u failed to enqueue frame to RX queue, %d",
333 port_idx, ret);
334 return ret;
335 }
336 }
337 update_pos:
338 rx_pos += ctx->oa_cps + sizeof(uint32_t);
339 }
340
341 return ret;
342 }
343
344 /*
345 * Setting up for a single dma transfer.
346 */
eth_adin2111_send_oa_frame(const struct device * dev,struct net_pkt * pkt,const uint16_t port_idx)347 static int eth_adin2111_send_oa_frame(const struct device *dev, struct net_pkt *pkt,
348 const uint16_t port_idx)
349 {
350 struct adin2111_data *ctx = dev->data;
351 uint16_t clen, len = net_pkt_get_len(pkt);
352 uint32_t hdr;
353 uint8_t chunks, i;
354 int ret, txc, cur;
355
356 chunks = len / ctx->oa_cps;
357
358 if (len % ctx->oa_cps) {
359 chunks++;
360 }
361
362 ret = eth_adin2111_reg_read(dev, ADIN2111_BUFSTS, &txc);
363 if (ret < 0) {
364 LOG_ERR("Cannot read txc");
365 return -EIO;
366 }
367
368 txc = (txc & ADIN2111_BUFSTS_TXC_MASK) >> ADIN2111_BUFSTS_TXC;
369 if (txc < chunks) {
370 return -EIO;
371 }
372
373 /* Prepare for single dma transfer */
374 for (i = 1, cur = 0; i <= chunks; i++) {
375 hdr = ADIN2111_OA_DATA_HDR_DNC | ADIN2111_OA_DATA_HDR_DV |
376 ADIN2111_OA_DATA_HDR_NORX;
377 hdr |= (!!port_idx << ADIN2111_OA_DATA_HDR_VS);
378 if (i == 1) {
379 hdr |= ADIN2111_OA_DATA_HDR_SV;
380 }
381 if (i == chunks) {
382 hdr |= ADIN2111_OA_DATA_HDR_EV;
383 hdr |= (ctx->oa_cps - 1) << ADIN2111_OA_DATA_HDR_EBO;
384 }
385
386 hdr |= eth_adin2111_oa_get_parity(hdr);
387
388 *(uint32_t *)&ctx->oa_tx_buf[cur] = sys_cpu_to_be32(hdr);
389 cur += sizeof(uint32_t);
390
391 clen = len > ctx->oa_cps ? ctx->oa_cps : len;
392 ret = net_pkt_read(pkt, &ctx->oa_tx_buf[cur], clen);
393 if (ret < 0) {
394 LOG_ERR("Cannot read from tx packet");
395 return ret;
396 }
397 cur += ctx->oa_cps;
398 len -= clen;
399 }
400
401 ret = eth_adin2111_oa_spi_xfer(dev, ctx->oa_rx_buf, ctx->oa_tx_buf, cur);
402 if (ret < 0) {
403 LOG_ERR("Error on SPI xfer");
404 return ret;
405 }
406
407 return 0;
408 }
409
eth_adin2111_reg_read_generic(const struct device * dev,const uint16_t reg,uint32_t * val)410 static int eth_adin2111_reg_read_generic(const struct device *dev,
411 const uint16_t reg,
412 uint32_t *val)
413 {
414 const struct adin2111_config *cfg = dev->config;
415 size_t header_len = ADIN2111_READ_HEADER_SIZE;
416 size_t read_len = sizeof(uint32_t);
417 int ret;
418 #if CONFIG_ETH_ADIN2111_SPI_CFG0
419 uint8_t rcv_crc;
420 uint8_t comp_crc;
421 uint8_t buf[ADIN2111_REG_READ_BUF_SIZE_CRC] = { 0 };
422 #else
423 uint8_t buf[ADIN2111_REG_READ_BUF_SIZE] = { 0 };
424 #endif /* CONFIG_ETH_ADIN2111_SPI_CFG0 */
425
426 /* spi header */
427 *(uint16_t *)buf = htons((ADIN2111_READ_TXN_CTRL | reg));
428 #if CONFIG_ETH_ADIN2111_SPI_CFG0
429 buf[2] = crc8_ccitt(0, buf, ADIN2111_SPI_HEADER_SIZE);
430 /* TA */
431 buf[3] = 0U;
432 ++header_len;
433 ++read_len;
434 #else
435 /* TA */
436 buf[2] = 0U;
437 #endif /* CONFIG_ETH_ADIN2111_SPI_CFG0 */
438
439 const struct spi_buf tx_buf = { .buf = buf, .len = header_len + read_len };
440 const struct spi_buf rx_buf = { .buf = buf, .len = header_len + read_len };
441 const struct spi_buf_set tx = { .buffers = &tx_buf, .count = 1U };
442 const struct spi_buf_set rx = { .buffers = &rx_buf, .count = 1U };
443
444 ret = spi_transceive_dt(&cfg->spi, &tx, &rx);
445 if (ret < 0) {
446 return ret;
447 }
448
449 #if CONFIG_ETH_ADIN2111_SPI_CFG0
450 comp_crc = crc8_ccitt(0, &buf[header_len], sizeof(uint32_t));
451 rcv_crc = buf[header_len + sizeof(uint32_t)];
452
453 if (rcv_crc != comp_crc) {
454 /* invalid crc */
455 return -EIO;
456 }
457 #endif /* CONFIG_ETH_ADIN2111_SPI_CFG0 */
458
459 *val = ntohl((*(uint32_t *)(&buf[header_len])));
460
461 return ret;
462 }
463
eth_adin2111_reg_write_generic(const struct device * dev,const uint16_t reg,const uint32_t val)464 static int eth_adin2111_reg_write_generic(const struct device *dev,
465 const uint16_t reg,
466 const uint32_t val)
467 {
468 const struct adin2111_config *cfg = dev->config;
469 size_t header_size = ADIN2111_WRITE_HEADER_SIZE;
470 size_t data_size = sizeof(uint32_t);
471 #if CONFIG_ETH_ADIN2111_SPI_CFG0
472 uint8_t buf[ADIN2111_REG_WRITE_BUF_SIZE_CRC] = { 0 };
473 #else
474 uint8_t buf[ADIN2111_REG_WRITE_BUF_SIZE] = { 0 };
475 #endif /* CONFIG_ETH_ADIN2111_SPI_CFG0 */
476
477 /* spi header */
478 *(uint16_t *)buf = htons((ADIN2111_WRITE_TXN_CTRL | reg));
479 #if CONFIG_ETH_ADIN2111_SPI_CFG0
480 buf[2] = crc8_ccitt(0, buf, header_size);
481 ++header_size;
482 #endif /* CONFIG_ETH_ADIN2111_SPI_CFG0 */
483
484 /* reg */
485 *(uint32_t *)(buf + header_size) = htonl(val);
486 #if CONFIG_ETH_ADIN2111_SPI_CFG0
487 buf[header_size + data_size] = crc8_ccitt(0, &buf[header_size], data_size);
488 ++data_size;
489 #endif /* CONFIG_ETH_ADIN2111_SPI_CFG0 */
490
491 const struct spi_buf spi_tx_buf = {
492 .buf = buf,
493 .len = header_size + data_size
494 };
495 const struct spi_buf_set tx = { .buffers = &spi_tx_buf, .count = 1U };
496
497 return spi_write_dt(&cfg->spi, &tx);
498 }
499
eth_adin2111_reg_read(const struct device * dev,const uint16_t reg,uint32_t * val)500 int eth_adin2111_reg_read(const struct device *dev, const uint16_t reg,
501 uint32_t *val)
502 {
503 struct adin2111_data *ctx = dev->data;
504 int rval;
505
506 if (ctx->oa) {
507 rval = eth_adin2111_reg_read_oa(dev, reg, val);
508 } else {
509 rval = eth_adin2111_reg_read_generic(dev, reg, val);
510 }
511
512 return rval;
513 }
514
eth_adin2111_reg_write(const struct device * dev,const uint16_t reg,const uint32_t val)515 int eth_adin2111_reg_write(const struct device *dev, const uint16_t reg,
516 const uint32_t val)
517 {
518 struct adin2111_data *ctx = dev->data;
519 int rval;
520
521 if (ctx->oa) {
522 rval = eth_adin2111_reg_write_oa(dev, reg, val);
523 } else {
524 rval = eth_adin2111_reg_write_generic(dev, reg, val);
525 }
526
527 return rval;
528 }
529
adin2111_read_fifo(const struct device * dev,const uint16_t port_idx)530 static int adin2111_read_fifo(const struct device *dev, const uint16_t port_idx)
531 {
532 const struct adin2111_config *cfg = dev->config;
533 struct adin2111_data *ctx = dev->data;
534 struct net_if *iface;
535 struct net_pkt *pkt;
536 uint16_t fsize_reg = ((port_idx == 0U) ? ADIN2111_P1_RX_FSIZE : ADIN2111_P2_RX_FSIZE);
537 uint16_t rx_reg = ((port_idx == 0U) ? ADIN2111_P1_RX : ADIN2111_P2_RX);
538 uint32_t fsize;
539 uint32_t fsize_real;
540 uint32_t padding_len;
541 #if CONFIG_ETH_ADIN2111_SPI_CFG0
542 uint8_t cmd_buf[ADIN2111_FIFO_READ_CMD_BUF_SIZE_CRC] = { 0 };
543 #else
544 uint8_t cmd_buf[ADIN2111_FIFO_READ_CMD_BUF_SIZE] = { 0 };
545 #endif /* CONFIG_ETH_ADIN2111_SPI_CFG0 */
546 int ret;
547
548 iface = ((struct adin2111_port_data *)ctx->port[port_idx]->data)->iface;
549
550 /* get received frame size in bytes */
551 ret = eth_adin2111_reg_read(dev, fsize_reg, &fsize);
552 if (ret < 0) {
553 eth_stats_update_errors_rx(iface);
554 LOG_ERR("Port %u failed to read RX FSIZE, %d", port_idx, ret);
555 return ret;
556 }
557
558 /* burst read must be in multiples of 4 */
559 padding_len = ((fsize % 4) == 0) ? 0U : (ROUND_UP(fsize, 4U) - fsize);
560 /* actual available frame length is FSIZE - FRAME HEADER */
561 fsize -= ADIN2111_FRAME_HEADER_SIZE;
562
563 /* spi header */
564 *(uint16_t *)cmd_buf = htons((ADIN2111_READ_TXN_CTRL | rx_reg));
565 #if CONFIG_ETH_ADIN2111_SPI_CFG0
566 cmd_buf[2] = crc8_ccitt(0, cmd_buf, ADIN2111_SPI_HEADER_SIZE);
567 /* TA */
568 cmd_buf[3] = 0U;
569 #else
570 /* TA */
571 cmd_buf[2] = 0U;
572 #endif /* CONFIG_ETH_ADIN2111_SPI_CFG0 */
573
574 const struct spi_buf tx_buf = { .buf = cmd_buf, .len = sizeof(cmd_buf) };
575 const struct spi_buf rx_buf[3] = {
576 {.buf = NULL, .len = sizeof(cmd_buf) + ADIN2111_FRAME_HEADER_SIZE},
577 {.buf = ctx->buf, .len = fsize},
578 {.buf = NULL, .len = padding_len }
579 };
580 const struct spi_buf_set tx = { .buffers = &tx_buf, .count = 1U };
581 const struct spi_buf_set rx = {
582 .buffers = rx_buf,
583 .count = ((padding_len == 0U) ? 2U : 3U)
584 };
585
586 ret = spi_transceive_dt(&cfg->spi, &tx, &rx);
587 if (ret < 0) {
588 eth_stats_update_errors_rx(iface);
589 LOG_ERR("Port %u failed to read RX FIFO, %d", port_idx, ret);
590 return ret;
591 }
592
593 /* remove CRC32 and pass to the stack */
594 fsize_real = fsize - sizeof(uint32_t);
595
596 pkt = net_pkt_rx_alloc_with_buffer(iface, fsize_real, AF_UNSPEC, 0,
597 K_MSEC(CONFIG_ETH_ADIN2111_TIMEOUT));
598 if (!pkt) {
599 eth_stats_update_errors_rx(iface);
600 LOG_ERR("Port %u failed to alloc frame RX buffer, %u bytes",
601 port_idx, fsize_real);
602 return -ENOMEM;
603 }
604
605 ret = net_pkt_write(pkt, ctx->buf, fsize_real);
606 if (ret < 0) {
607 eth_stats_update_errors_rx(iface);
608 net_pkt_unref(pkt);
609 LOG_ERR("Port %u failed to fill RX frame, %d", port_idx, ret);
610 return ret;
611 }
612
613 ret = net_recv_data(iface, pkt);
614 if (ret < 0) {
615 eth_stats_update_errors_rx(iface);
616 net_pkt_unref(pkt);
617 LOG_ERR("Port %u failed to enqueue frame to RX queue, %d",
618 port_idx, ret);
619 return ret;
620 }
621
622 eth_stats_update_bytes_rx(iface, fsize_real);
623 eth_stats_update_pkts_rx(iface);
624
625 return ret;
626 }
627
adin2111_port_on_phyint(const struct device * dev)628 static inline void adin2111_port_on_phyint(const struct device *dev)
629 {
630 const struct adin2111_port_config *cfg = dev->config;
631 struct adin2111_port_data *data = dev->data;
632 struct phy_link_state state;
633
634 if (phy_adin2111_handle_phy_irq(cfg->phy, &state) < 0) {
635 /* no change or error */
636 return;
637 }
638
639 if (state.is_up) {
640 net_eth_carrier_on(data->iface);
641 } else {
642 net_eth_carrier_off(data->iface);
643 }
644 }
645
adin2111_offload_thread(void * p1,void * p2,void * p3)646 static void adin2111_offload_thread(void *p1, void *p2, void *p3)
647 {
648 ARG_UNUSED(p2);
649 ARG_UNUSED(p3);
650
651 const struct device *dev = p1;
652 struct adin2111_data *ctx = dev->data;
653 const struct adin2111_config *adin_cfg = dev->config;
654 const bool is_adin2111 = (adin_cfg->id == ADIN2111_MAC);
655 uint32_t status0;
656 uint32_t status1;
657 int ret;
658
659 for (;;) {
660 /* await INT */
661 k_sem_take(&ctx->offload_sem, K_FOREVER);
662
663 /* lock device */
664 eth_adin2111_lock(dev, K_FOREVER);
665
666 /* disable interrupts */
667 ret = eth_adin2111_reg_write(dev, ADIN2111_IMASK0, UINT32_MAX);
668 if (ret < 0) {
669 goto continue_unlock;
670 }
671 ret = eth_adin2111_reg_write(dev, ADIN2111_IMASK1, UINT32_MAX);
672 if (ret < 0) {
673 goto continue_unlock;
674 }
675
676 /* read interrupts */
677 ret = eth_adin2111_reg_read(dev, ADIN2111_STATUS0, &status0);
678 if (ret < 0) {
679 goto continue_unlock;
680 }
681 ret = eth_adin2111_reg_read(dev, ADIN2111_STATUS1, &status1);
682 if (ret < 0) {
683 goto continue_unlock;
684 }
685
686 /* handle port 1 phy interrupts */
687 if (status0 & ADIN2111_STATUS0_PHYINT) {
688 adin2111_port_on_phyint(ctx->port[0]);
689 }
690
691 /* handle port 2 phy interrupts */
692 if (is_adin2111 && (status1 & ADIN2111_STATUS1_PHYINT)) {
693 adin2111_port_on_phyint(ctx->port[1]);
694 }
695
696 if (ctx->oa) {
697 if (status1 & ADIN2111_STATUS1_P1_RX_RDY) {
698 ret = eth_adin2111_oa_data_read(dev, 0);
699 if (ret < 0) {
700 goto continue_unlock;
701 }
702 }
703 if (is_adin2111 && (status1 & ADIN2111_STATUS1_P2_RX_RDY)) {
704 ret = eth_adin2111_oa_data_read(dev, 1);
705 if (ret < 0) {
706 goto continue_unlock;
707 }
708 }
709 } else {
710 #if CONFIG_ETH_ADIN2111_SPI_CFG0
711 if (status0 & ADIN2111_STATUS1_SPI_ERR) {
712 LOG_WRN("Detected TX SPI CRC error");
713 }
714 #endif /* CONFIG_ETH_ADIN2111_SPI_CFG0 */
715
716 /* handle port 1 rx */
717 if (status1 & ADIN2111_STATUS1_P1_RX_RDY) {
718 do {
719 ret = adin2111_read_fifo(dev, 0U);
720 if (ret < 0) {
721 break;
722 }
723
724 ret = eth_adin2111_reg_read(dev, ADIN2111_STATUS1,
725 &status1);
726 if (ret < 0) {
727 goto continue_unlock;
728 }
729 } while (!!(status1 & ADIN2111_STATUS1_P1_RX_RDY));
730 }
731
732 /* handle port 2 rx */
733 if (is_adin2111 && (status1 & ADIN2111_STATUS1_P2_RX_RDY)) {
734 do {
735 ret = adin2111_read_fifo(dev, 1U);
736 if (ret < 0) {
737 break;
738 }
739
740 ret = eth_adin2111_reg_read(dev, ADIN2111_STATUS1,
741 &status1);
742 if (ret < 0) {
743 goto continue_unlock;
744 }
745 } while (!!(status1 & ADIN2111_STATUS1_P2_RX_RDY));
746 }
747 }
748
749 continue_unlock:
750 /* clear interrupts */
751 ret = eth_adin2111_reg_write(dev, ADIN2111_STATUS0, ADIN2111_STATUS0_CLEAR);
752 if (ret < 0) {
753 LOG_ERR("Failed to clear STATUS0, %d", ret);
754 }
755 ret = eth_adin2111_reg_write(dev, ADIN2111_STATUS1, ADIN2111_STATUS1_CLEAR);
756 if (ret < 0) {
757 LOG_ERR("Failed to clear STATUS1, %d", ret);
758 }
759 /* enable interrupts */
760 ret = eth_adin2111_reg_write(dev, ADIN2111_IMASK0, ctx->imask0);
761 if (ret < 0) {
762 LOG_ERR("Failed to write IMASK0, %d", ret);
763 }
764 ret = eth_adin2111_reg_write(dev, ADIN2111_IMASK1, ctx->imask1);
765 if (ret < 0) {
766 LOG_ERR("Failed to write IMASK1, %d", ret);
767 }
768 eth_adin2111_unlock(dev);
769 }
770 }
771
adin2111_int_callback(const struct device * dev,struct gpio_callback * cb,uint32_t pins)772 static void adin2111_int_callback(const struct device *dev,
773 struct gpio_callback *cb,
774 uint32_t pins)
775 {
776 ARG_UNUSED(dev);
777 ARG_UNUSED(pins);
778
779 struct adin2111_data *ctx = CONTAINER_OF(cb, struct adin2111_data, gpio_int_callback);
780
781 k_sem_give(&ctx->offload_sem);
782 }
783
adin2111_read_tx_space(const struct device * dev,uint32_t * space)784 static int adin2111_read_tx_space(const struct device *dev, uint32_t *space)
785 {
786 uint32_t val;
787 int ret;
788
789 ret = eth_adin2111_reg_read(dev, ADIN2111_TX_SPACE, &val);
790 if (ret < 0) {
791 return ret;
792 }
793
794 /* tx space is a number of halfwords (16-bits), multiply by 2 for bytes */
795 *space = val * 2;
796
797 return ret;
798 }
799
adin2111_port_send(const struct device * dev,struct net_pkt * pkt)800 static int adin2111_port_send(const struct device *dev, struct net_pkt *pkt)
801 {
802 const struct adin2111_port_config *cfg = dev->config;
803 #if defined(CONFIG_NET_STATISTICS_ETHERNET)
804 struct adin2111_port_data *data = dev->data;
805 #endif /* CONFIG_NET_STATISTICS_ETHERNET */
806 const struct device *adin = cfg->adin;
807 struct adin2111_data *ctx = cfg->adin->data;
808 size_t pkt_len = net_pkt_get_len(pkt);
809 size_t header_size = ADIN2111_WRITE_HEADER_SIZE;
810 size_t padded_size;
811 size_t burst_size;
812 uint32_t tx_space;
813 int ret;
814
815 eth_adin2111_lock(adin, K_FOREVER);
816
817 if (ctx->oa) {
818 uint32_t val, rca = 0;
819 /*
820 * By high-traffic zperf test, noted that ADIN2111 does not like we send
821 * if there is something to be received. It stops to issue rx interrupts
822 * and zperf transfer hangs. Forcing a receive for this case.
823 */
824 ret = eth_adin2111_reg_read(adin, ADIN2111_BUFSTS, &val);
825 if (ret < 0) {
826 return ret;
827 }
828 rca = val & ADIN2111_BUFSTS_RCA_MASK;
829
830 if (rca > 0) {
831 eth_adin2111_unlock(adin);
832 k_sem_give(&ctx->offload_sem);
833 k_yield();
834 eth_adin2111_lock(adin, K_FOREVER);
835 }
836
837 ret = eth_adin2111_send_oa_frame(cfg->adin, pkt, htons(cfg->port_idx));
838
839 goto end_check;
840 }
841
842 /* query remaining tx fifo space */
843 ret = adin2111_read_tx_space(adin, &tx_space);
844 if (ret < 0) {
845 eth_stats_update_errors_tx(data->iface);
846 LOG_ERR("Failed to read TX FIFO space, %d", ret);
847 goto end_unlock;
848 }
849
850 /**
851 * verify that there is space for the frame
852 * (frame + 2b header + 2b size field)
853 */
854 if (tx_space <
855 (pkt_len + ADIN2111_FRAME_HEADER_SIZE + ADIN2111_INTERNAL_HEADER_SIZE)) {
856 /* tx buffer is full */
857 eth_stats_update_errors_tx(data->iface);
858 ret = -EBUSY;
859 goto end_unlock;
860 }
861
862 /**
863 * pad to 64 bytes, otherwise MAC/PHY has to do it
864 * internally MAC adds 4 bytes for forward error correction
865 */
866 if ((pkt_len + ADIN2111_TX_FIFO_BUFFER_MARGIN) < 64) {
867 padded_size = pkt_len
868 + (64 - (pkt_len + ADIN2111_TX_FIFO_BUFFER_MARGIN))
869 + ADIN2111_FRAME_HEADER_SIZE;
870 } else {
871 padded_size = pkt_len + ADIN2111_FRAME_HEADER_SIZE;
872 }
873
874 /* prepare burst write (write data must be in multiples of 4) */
875 burst_size = ROUND_UP(padded_size, 4);
876 if ((burst_size + ADIN2111_WRITE_HEADER_SIZE) > CONFIG_ETH_ADIN2111_BUFFER_SIZE) {
877 ret = -ENOMEM;
878 eth_stats_update_errors_tx(data->iface);
879 goto end_unlock;
880 }
881
882 /* prepare tx buffer */
883 memset(ctx->buf, 0, burst_size + ADIN2111_WRITE_HEADER_SIZE);
884
885 /* spi header */
886 *(uint16_t *)ctx->buf = htons(ADIN2111_TXN_CTRL_TX_REG);
887 #if CONFIG_ETH_ADIN2111_SPI_CFG0
888 ctx->buf[2] = crc8_ccitt(0, ctx->buf, header_size);
889 ++header_size;
890 #endif /* CONFIG_ETH_ADIN2111_SPI_CFG0 */
891
892 /* frame header */
893 *(uint16_t *)(ctx->buf + header_size) = htons(cfg->port_idx);
894
895 /* read pkt into tx buffer */
896 ret = net_pkt_read(pkt,
897 (ctx->buf + header_size + ADIN2111_FRAME_HEADER_SIZE),
898 pkt_len);
899 if (ret < 0) {
900 eth_stats_update_errors_tx(data->iface);
901 LOG_ERR("Port %u failed to read PKT into TX buffer, %d",
902 cfg->port_idx, ret);
903 goto end_unlock;
904 }
905
906 /* write transmit size */
907 ret = eth_adin2111_reg_write(adin, ADIN2111_TX_FSIZE, padded_size);
908 if (ret < 0) {
909 eth_stats_update_errors_tx(data->iface);
910 LOG_ERR("Port %u write FSIZE failed, %d", cfg->port_idx, ret);
911 goto end_unlock;
912 }
913
914 /* write transaction */
915 const struct spi_buf buf = {
916 .buf = ctx->buf,
917 .len = header_size + burst_size
918 };
919 const struct spi_buf_set tx = { .buffers = &buf, .count = 1U };
920
921 ret = spi_write_dt(&((const struct adin2111_config *) adin->config)->spi,
922 &tx);
923 end_check:
924 if (ret < 0) {
925 eth_stats_update_errors_tx(data->iface);
926 LOG_ERR("Port %u frame SPI write failed, %d", cfg->port_idx, ret);
927 goto end_unlock;
928 }
929
930 eth_stats_update_bytes_tx(data->iface, pkt_len);
931 eth_stats_update_pkts_tx(data->iface);
932
933 end_unlock:
934 eth_adin2111_unlock(adin);
935 return ret;
936 }
937
adin2111_config_sync(const struct device * dev)938 static int adin2111_config_sync(const struct device *dev)
939 {
940 int ret;
941 uint32_t val;
942
943 ret = eth_adin2111_reg_read(dev, ADIN2111_CONFIG0, &val);
944 if (ret < 0) {
945 return ret;
946 }
947
948 val |= ADIN2111_CONFIG0_SYNC;
949
950 ret = eth_adin2111_reg_write(dev, ADIN2111_CONFIG0, val);
951 if (ret < 0) {
952 return ret;
953 }
954
955 return 0;
956 }
957
adin2111_write_filter_address(const struct device * dev,uint8_t * addr,uint8_t * mask,uint32_t rules,uint16_t slot)958 static int adin2111_write_filter_address(const struct device *dev,
959 uint8_t *addr, uint8_t *mask,
960 uint32_t rules, uint16_t slot)
961 {
962 uint16_t offset = slot * 2U;
963 int ret;
964
965 ret = eth_adin2111_reg_write(dev, ADIN2111_ADDR_FILT_UPR + offset,
966 rules | sys_get_be16(&addr[0]));
967 if (ret < 0) {
968 return ret;
969 }
970
971 ret = eth_adin2111_reg_write(dev, ADIN2111_ADDR_FILT_LWR + offset,
972 sys_get_be32(&addr[2]));
973 if (ret < 0) {
974 return ret;
975 }
976
977 if (offset > 2U) {
978 /* mask filter addresses are limited to 2 */
979 return 0;
980 }
981
982 ret = eth_adin2111_reg_write(dev, ADIN2111_ADDR_MSK_UPR + offset,
983 sys_get_be16(&mask[0]));
984 if (ret < 0) {
985 return ret;
986 }
987
988 ret = eth_adin2111_reg_write(dev, ADIN2111_ADDR_MSK_LWR + offset,
989 sys_get_be32(&mask[2]));
990 if (ret < 0) {
991 return ret;
992 }
993
994 return ret;
995 }
996
adin2111_filter_multicast(const struct device * dev)997 static int adin2111_filter_multicast(const struct device *dev)
998 {
999 const struct adin2111_config *cfg = dev->config;
1000 const bool is_adin2111 = (cfg->id == ADIN2111_MAC);
1001 uint8_t mm[NET_ETH_ADDR_LEN] = {BIT(0), 0U, 0U, 0U, 0U, 0U};
1002 uint8_t mmask[NET_ETH_ADDR_LEN] = {0xFFU, 0U, 0U, 0U, 0U, 0U};
1003 uint32_t rules = ADIN2111_ADDR_APPLY2PORT1 |
1004 (is_adin2111 ? ADIN2111_ADDR_APPLY2PORT2 : 0) |
1005 ADIN2111_ADDR_TO_HOST |
1006 ADIN2111_ADDR_TO_OTHER_PORT;
1007
1008 return adin2111_write_filter_address(dev, mm, mmask, rules,
1009 ADIN2111_MULTICAST_ADDR_SLOT);
1010 }
1011
adin2111_filter_broadcast(const struct device * dev)1012 static int adin2111_filter_broadcast(const struct device *dev)
1013 {
1014 const struct adin2111_config *cfg = dev->config;
1015 const bool is_adin2111 = (cfg->id == ADIN2111_MAC);
1016 uint8_t mac[NET_ETH_ADDR_LEN] = {0xFFU, 0xFFU, 0xFFU, 0xFFU, 0xFFU, 0xFFU};
1017 uint32_t rules = ADIN2111_ADDR_APPLY2PORT1 |
1018 (is_adin2111 ? ADIN2111_ADDR_APPLY2PORT2 : 0) |
1019 ADIN2111_ADDR_TO_HOST |
1020 ADIN2111_ADDR_TO_OTHER_PORT;
1021
1022 return adin2111_write_filter_address(dev, mac, mac, rules,
1023 ADIN2111_BROADCAST_ADDR_SLOT);
1024 }
1025
adin2111_filter_unicast(const struct device * dev,uint8_t * addr,const uint16_t port_idx)1026 static int adin2111_filter_unicast(const struct device *dev, uint8_t *addr,
1027 const uint16_t port_idx)
1028 {
1029 uint32_t rules = (port_idx == 0 ? ADIN2111_ADDR_APPLY2PORT1
1030 : ADIN2111_ADDR_APPLY2PORT2)
1031 | ADIN2111_ADDR_TO_HOST;
1032 uint16_t slot = (port_idx == 0 ? ADIN2111_UNICAST_P1_ADDR_SLOT
1033 : ADIN2111_UNICAST_P2_ADDR_SLOT);
1034
1035 return adin2111_write_filter_address(dev, addr, NULL, rules, slot);
1036 }
1037
eth_adin2111_broadcast_filter(const struct device * dev,bool enable)1038 int eth_adin2111_broadcast_filter(const struct device *dev, bool enable)
1039 {
1040 if (!enable) {
1041 /* Clean up */
1042 uint8_t mac[NET_ETH_ADDR_LEN] = {0};
1043
1044 return adin2111_write_filter_address(dev, mac, mac, 0,
1045 ADIN2111_BROADCAST_ADDR_SLOT);
1046 }
1047
1048 return adin2111_filter_broadcast(dev);
1049 }
1050
1051 /*
1052 * Check if a filter exists already.
1053 */
eth_adin2111_find_filter(const struct device * dev,uint8_t * mac,const uint16_t port_idx)1054 static int eth_adin2111_find_filter(const struct device *dev, uint8_t *mac, const uint16_t port_idx)
1055 {
1056 int i, offset, reg, ret;
1057
1058 for (i = ADIN2111_FILTER_FIRST_SLOT; i < ADIN2111_FILTER_SLOTS; i++) {
1059 offset = i << 1;
1060 ret = eth_adin2111_reg_read(dev, ADIN2111_ADDR_FILT_UPR + offset, ®);
1061 if (ret < 0) {
1062 return ret;
1063 }
1064 if ((reg & UINT16_MAX) == sys_get_be16(&mac[0])) {
1065 if ((port_idx == 0 && !(reg & ADIN2111_ADDR_APPLY2PORT1)) ||
1066 (port_idx == 1 && !(reg & ADIN2111_ADDR_APPLY2PORT2))) {
1067 continue;
1068 }
1069
1070 ret = eth_adin2111_reg_read(dev, ADIN2111_ADDR_FILT_LWR + offset, ®);
1071 if (ret < 0) {
1072 return ret;
1073 }
1074 if (reg == sys_get_be32(&mac[2])) {
1075 return i;
1076 }
1077 }
1078 }
1079
1080 return -ENOENT;
1081 }
1082
eth_adin2111_set_mac_filter(const struct device * dev,uint8_t * mac,const uint16_t port_idx)1083 static int eth_adin2111_set_mac_filter(const struct device *dev, uint8_t *mac,
1084 const uint16_t port_idx)
1085 {
1086 int i, ret, offset;
1087 uint32_t reg;
1088
1089 ret = eth_adin2111_find_filter(dev, mac, port_idx);
1090 if (ret >= 0) {
1091 LOG_WRN("MAC filter already set at pos %d, not setting it.", ret);
1092 return ret;
1093 }
1094 if (ret != -ENOENT) {
1095 return ret;
1096 }
1097
1098 for (i = ADIN2111_FILTER_FIRST_SLOT; i < ADIN2111_FILTER_SLOTS; i++) {
1099 offset = i << 1;
1100 ret = eth_adin2111_reg_read(dev, ADIN2111_ADDR_FILT_UPR + offset, ®);
1101 if (ret < 0) {
1102 return ret;
1103 }
1104 if (reg == 0) {
1105 uint32_t rules = (port_idx == 0 ? ADIN2111_ADDR_APPLY2PORT1
1106 : ADIN2111_ADDR_APPLY2PORT2)
1107 | ADIN2111_ADDR_TO_HOST;
1108
1109 return adin2111_write_filter_address(dev, mac, NULL, rules, i);
1110 }
1111 }
1112
1113 return -ENOSPC;
1114 }
1115
eth_adin2111_clear_mac_filter(const struct device * dev,uint8_t * mac,const uint16_t port_idx)1116 static int eth_adin2111_clear_mac_filter(const struct device *dev, uint8_t *mac,
1117 const uint16_t port_idx)
1118 {
1119 int i;
1120 uint8_t cmac[NET_ETH_ADDR_LEN] = {0};
1121
1122 i = eth_adin2111_find_filter(dev, mac, port_idx);
1123 if (i < 0) {
1124 return i;
1125 }
1126
1127 return adin2111_write_filter_address(dev, cmac, cmac, 0, i);
1128 }
1129
1130 #if defined(CONFIG_NET_PROMISCUOUS_MODE)
eth_adin2111_set_promiscuous(const struct device * dev,const uint16_t port_idx,bool enable)1131 static int eth_adin2111_set_promiscuous(const struct device *dev, const uint16_t port_idx,
1132 bool enable)
1133 {
1134 const struct adin2111_config *cfg = dev->config;
1135 const bool is_adin2111 = (cfg->id == ADIN2111_MAC);
1136 uint32_t fwd_mask;
1137
1138 if ((!is_adin2111 && port_idx > 0) || (is_adin2111 && port_idx > 1)) {
1139 return -EINVAL;
1140 }
1141
1142 fwd_mask = port_idx ? ADIN2111_CONFIG2_P2_FWD_UNK2HOST : ADIN2111_CONFIG2_P1_FWD_UNK2HOST;
1143
1144 return eth_adin2111_reg_update(dev, ADIN2111_CONFIG2, fwd_mask, enable ? fwd_mask : 0);
1145 }
1146 #endif
1147
adin2111_port_iface_init(struct net_if * iface)1148 static void adin2111_port_iface_init(struct net_if *iface)
1149 {
1150 const struct device *dev = net_if_get_device(iface);
1151 const struct adin2111_port_config *cfg = dev->config;
1152 struct adin2111_port_data *data = dev->data;
1153 const struct device *adin = cfg->adin;
1154 struct adin2111_data *ctx = adin->data;
1155 int ret;
1156
1157 if (!device_is_ready(adin)) {
1158 LOG_ERR("ADIN %s is not ready, can't init port %u iface",
1159 cfg->adin->name, cfg->port_idx);
1160 return;
1161 }
1162
1163 if (!device_is_ready(cfg->phy)) {
1164 LOG_ERR("PHY %u is not ready, can't init port %u iface",
1165 cfg->phy_addr, cfg->port_idx);
1166 return;
1167 }
1168
1169 ctx->port[cfg->port_idx] = dev;
1170 data->iface = iface;
1171
1172 ret = adin2111_filter_unicast(adin, data->mac_addr, cfg->port_idx);
1173 if (ret < 0) {
1174 LOG_ERR("Port %u, failed to set unicast filter, %d",
1175 cfg->port_idx, ret);
1176 return;
1177 }
1178 net_if_set_link_addr(iface, data->mac_addr, sizeof(data->mac_addr),
1179 NET_LINK_ETHERNET);
1180 ethernet_init(iface);
1181 net_if_carrier_off(iface);
1182
1183 --ctx->ifaces_left_to_init;
1184
1185 /* if all ports are initialized */
1186 if (ctx->ifaces_left_to_init == 0U) {
1187 /* setup rx filters */
1188 ret = adin2111_filter_multicast(adin);
1189 if (ret < 0) {
1190 LOG_ERR("Couldn't set multicast filter, %d", ret);
1191 return;
1192 }
1193 ret = adin2111_filter_broadcast(adin);
1194 if (ret < 0) {
1195 LOG_ERR("Couldn't set broadcast filter, %d", ret);
1196 return;
1197 }
1198
1199 /* sync */
1200 ret = adin2111_config_sync(adin);
1201 if (ret < 0) {
1202 LOG_ERR("Failed to write CONFIG0 SYNC, %d", ret);
1203 return;
1204 }
1205
1206 /* all ifaces are done, start INT processing */
1207 k_thread_create(&ctx->rx_thread, ctx->rx_thread_stack,
1208 K_KERNEL_STACK_SIZEOF(ctx->rx_thread_stack),
1209 adin2111_offload_thread,
1210 (void *)adin, NULL, NULL,
1211 CONFIG_ETH_ADIN2111_IRQ_THREAD_PRIO,
1212 K_ESSENTIAL, K_NO_WAIT);
1213 k_thread_name_set(&ctx->rx_thread, "eth_adin2111_offload");
1214 }
1215 }
1216
adin2111_port_get_capabilities(const struct device * dev)1217 static enum ethernet_hw_caps adin2111_port_get_capabilities(const struct device *dev)
1218 {
1219 ARG_UNUSED(dev);
1220 return ETHERNET_LINK_10BASE_T |
1221 ETHERNET_HW_FILTERING
1222 #if defined(CONFIG_NET_LLDP)
1223 | ETHERNET_LLDP
1224 #endif
1225 | ETHERNET_PROMISC_MODE;
1226 }
1227
adin2111_port_set_config(const struct device * dev,enum ethernet_config_type type,const struct ethernet_config * config)1228 static int adin2111_port_set_config(const struct device *dev,
1229 enum ethernet_config_type type,
1230 const struct ethernet_config *config)
1231 {
1232 const struct adin2111_port_config *cfg = dev->config;
1233 struct adin2111_port_data *data = dev->data;
1234 const struct device *adin = cfg->adin;
1235 int ret = -ENOTSUP;
1236
1237 (void)eth_adin2111_lock(adin, K_FOREVER);
1238
1239 if (type == ETHERNET_CONFIG_TYPE_MAC_ADDRESS) {
1240 ret = adin2111_filter_unicast(adin, (uint8_t *)&config->mac_address.addr[0],
1241 cfg->port_idx);
1242 if (ret < 0) {
1243 goto end_unlock;
1244 }
1245
1246 (void)memcpy(data->mac_addr, config->mac_address.addr, sizeof(data->mac_addr));
1247
1248 (void)net_if_set_link_addr(data->iface, data->mac_addr, sizeof(data->mac_addr),
1249 NET_LINK_ETHERNET);
1250 }
1251
1252 if (type == ETHERNET_CONFIG_TYPE_FILTER) {
1253 /* Filtering for DA only */
1254 if (config->filter.type & ETHERNET_FILTER_TYPE_DST_MAC_ADDRESS) {
1255 uint8_t *mac = (uint8_t *)config->filter.mac_address.addr;
1256
1257 if (config->filter.set) {
1258 ret = eth_adin2111_set_mac_filter(adin, mac, cfg->port_idx);
1259 } else {
1260 ret = eth_adin2111_clear_mac_filter(adin, mac, cfg->port_idx);
1261 }
1262 }
1263 }
1264
1265 #if defined(CONFIG_NET_PROMISCUOUS_MODE)
1266 if (type == ETHERNET_CONFIG_TYPE_PROMISC_MODE) {
1267 ret = eth_adin2111_set_promiscuous(adin, cfg->port_idx, config->promisc_mode);
1268 }
1269 #endif
1270
1271 end_unlock:
1272 (void)eth_adin2111_unlock(adin);
1273 return ret;
1274 }
1275
1276 #if defined(CONFIG_NET_STATISTICS_ETHERNET)
adin2111_port_get_stats(const struct device * dev)1277 static struct net_stats_eth *adin2111_port_get_stats(const struct device *dev)
1278 {
1279 struct adin2111_port_data *data = dev->data;
1280
1281 return &data->stats;
1282 }
1283 #endif /* CONFIG_NET_STATISTICS_ETHERNET */
1284
adin2111_check_spi(const struct device * dev)1285 static int adin2111_check_spi(const struct device *dev)
1286 {
1287 uint32_t count;
1288 uint32_t val;
1289 int ret;
1290
1291 /* check SPI communication by reading PHYID */
1292 for (count = 0U; count < ADIN2111_DEV_AWAIT_RETRY_COUNT; ++count) {
1293 ret = eth_adin2111_reg_read(dev, ADIN2111_PHYID, &val);
1294 if (ret >= 0) {
1295 if (val == ADIN2111_PHYID_RST_VAL || val == ADIN1110_PHYID_RST_VAL) {
1296 break;
1297 }
1298 ret = -ETIMEDOUT;
1299 }
1300 k_sleep(K_USEC(ADIN2111_DEV_AWAIT_DELAY_POLL_US));
1301 }
1302
1303 return ret;
1304 }
1305
adin2111_await_device(const struct device * dev)1306 static int adin2111_await_device(const struct device *dev)
1307 {
1308 uint32_t count;
1309 uint32_t val;
1310 int ret;
1311
1312 /* await reset complete (RESETC) and clear it */
1313 for (count = 0U; count < ADIN2111_RESETC_AWAIT_RETRY_COUNT; ++count) {
1314 ret = eth_adin2111_reg_read(dev, ADIN2111_PHYID, &val);
1315 if (ret >= 0) {
1316 /*
1317 * Even after getting RESETC, for some milliseconds registers are
1318 * still not properly readable (they reads 0),
1319 * so checking OUI read-only value instead.
1320 */
1321 if ((val >> 10) == ADIN2111_PHYID_OUI) {
1322 /* clear RESETC */
1323 ret = eth_adin2111_reg_write(dev, ADIN2111_STATUS0,
1324 ADIN2111_STATUS0_RESETC);
1325 if (ret >= 0) {
1326 break;
1327 }
1328 }
1329 ret = -ETIMEDOUT;
1330 }
1331 k_sleep(K_USEC(ADIN2111_RESETC_AWAIT_DELAY_POLL_US));
1332 }
1333
1334 return ret;
1335 }
1336
eth_adin2111_sw_reset(const struct device * dev,uint16_t delay)1337 int eth_adin2111_sw_reset(const struct device *dev, uint16_t delay)
1338 {
1339 int ret;
1340
1341 ret = eth_adin2111_reg_write(dev, ADIN2111_RESET, ADIN2111_RESET_SWRESET);
1342 if (ret < 0) {
1343 return ret;
1344 }
1345
1346 k_msleep(delay);
1347
1348 ret = adin2111_await_device(dev);
1349 if (ret < 0) {
1350 LOG_ERR("ADIN did't come out of the reset, %d", ret);
1351 return ret;
1352 }
1353
1354 return ret;
1355 }
1356
adin2111_init(const struct device * dev)1357 static int adin2111_init(const struct device *dev)
1358 {
1359 const struct adin2111_config *cfg = dev->config;
1360 const bool is_adin2111 = (cfg->id == ADIN2111_MAC);
1361 struct adin2111_data *ctx = dev->data;
1362 int ret;
1363 uint32_t val;
1364
1365 __ASSERT(cfg->spi.config.frequency <= ADIN2111_SPI_MAX_FREQUENCY,
1366 "SPI frequency exceeds supported maximum\n");
1367
1368 if (!spi_is_ready_dt(&cfg->spi)) {
1369 LOG_ERR("SPI bus %s not ready", cfg->spi.bus->name);
1370 return -ENODEV;
1371 }
1372
1373 if (!gpio_is_ready_dt(&cfg->interrupt)) {
1374 LOG_ERR("Interrupt GPIO device %s is not ready",
1375 cfg->interrupt.port->name);
1376 return -ENODEV;
1377 }
1378
1379 ret = gpio_pin_configure_dt(&cfg->interrupt, GPIO_INPUT);
1380 if (ret < 0) {
1381 LOG_ERR("Failed to configure interrupt GPIO, %d", ret);
1382 return ret;
1383 }
1384
1385 if (cfg->reset.port != NULL) {
1386 if (!gpio_is_ready_dt(&cfg->reset)) {
1387 LOG_ERR("Reset GPIO device %s is not ready",
1388 cfg->reset.port->name);
1389 return -ENODEV;
1390 }
1391
1392 ret = gpio_pin_configure_dt(&cfg->reset, GPIO_OUTPUT_INACTIVE);
1393 if (ret < 0) {
1394 LOG_ERR("Failed to configure reset GPIO, %d", ret);
1395 return ret;
1396 }
1397
1398 /* perform hard reset */
1399 /* assert pin low for 16 µs (10 µs min) */
1400 gpio_pin_set_dt(&cfg->reset, 1);
1401 k_busy_wait(16U);
1402 /* deassert and wait for 90 ms (max) for clocks stabilisation */
1403 gpio_pin_set_dt(&cfg->reset, 0);
1404 k_msleep(ADIN2111_HW_BOOT_DELAY_MS);
1405 }
1406
1407 gpio_init_callback(&(ctx->gpio_int_callback),
1408 adin2111_int_callback,
1409 BIT(cfg->interrupt.pin));
1410
1411 ret = gpio_add_callback(cfg->interrupt.port, &ctx->gpio_int_callback);
1412 if (ret < 0) {
1413 LOG_ERR("Failed to add INT callback, %d", ret);
1414 return ret;
1415 }
1416
1417 k_msleep(ADIN2111_SPI_ACTIVE_DELAY_MS);
1418
1419 ret = adin2111_check_spi(dev);
1420 if (ret < 0) {
1421 LOG_ERR("Failed to communicate over SPI, %d", ret);
1422 return ret;
1423 }
1424
1425 /* perform MACPHY soft reset */
1426 ret = eth_adin2111_sw_reset(dev, ADIN2111_SW_RESET_DELAY_MS);
1427 if (ret < 0) {
1428 LOG_ERR("MACPHY software reset failed, %d", ret);
1429 return ret;
1430 }
1431
1432 /* CONFIG 0 */
1433 /* disable Frame Check Sequence validation on the host */
1434 /* if that is enabled, then CONFIG_ETH_ADIN2111_SPI_CFG0 must be off */
1435 ret = eth_adin2111_reg_read(dev, ADIN2111_CONFIG0, &val);
1436 if (ret < 0) {
1437 LOG_ERR("Failed to read CONFIG0, %d", ret);
1438 return ret;
1439 }
1440
1441 /* RXCTE must be disabled for Generic SPI */
1442 val &= ~ADIN2111_CONFIG0_RXCTE;
1443 val &= ~(ADIN2111_CONFIG0_TXCTE | ADIN2111_CONFIG0_TXFCSVE);
1444
1445 if (ctx->oa) {
1446 val |= ADIN2111_CONFIG0_ZARFE;
1447 }
1448
1449 ret = eth_adin2111_reg_write(dev, ADIN2111_CONFIG0, val);
1450 if (ret < 0) {
1451 LOG_ERR("Failed to write CONFIG0, %d", ret);
1452 return ret;
1453 }
1454
1455 /* CONFIG 2 */
1456 ret = eth_adin2111_reg_read(dev, ADIN2111_CONFIG2, &val);
1457 if (ret < 0) {
1458 LOG_ERR("Failed to read CONFIG2, %d", ret);
1459 return ret;
1460 }
1461
1462 val |= ADIN2111_CONFIG2_CRC_APPEND;
1463
1464 /* configure forwarding of frames with unknown destination address */
1465 /* to the other port. This forwarding is done in hardware. */
1466 /* The setting will take effect after the ports */
1467 /* are out of software powerdown. */
1468 val |= (ADIN2111_CONFIG2_PORT_CUT_THRU_EN |
1469 (is_adin2111 ? ADIN2111_CONFIG2_P1_FWD_UNK2P2 : 0) |
1470 (is_adin2111 ? ADIN2111_CONFIG2_P2_FWD_UNK2P1 : 0));
1471
1472 ret = eth_adin2111_reg_write(dev, ADIN2111_CONFIG2, val);
1473 if (ret < 0) {
1474 LOG_ERR("Failed to write CONFIG2, %d", ret);
1475 return ret;
1476 }
1477
1478 /* configure interrupt masks */
1479 ctx->imask0 = ~((uint32_t)ADIN2111_IMASK0_PHYINTM);
1480 ctx->imask1 = ~(ADIN2111_IMASK1_TX_RDY_MASK |
1481 ADIN2111_IMASK1_P1_RX_RDY_MASK |
1482 ADIN2111_IMASK1_SPI_ERR_MASK |
1483 (is_adin2111 ? ADIN2111_IMASK1_P2_RX_RDY_MASK : 0) |
1484 (is_adin2111 ? ADIN2111_IMASK1_P2_PHYINT_MASK : 0));
1485
1486 /* enable interrupts */
1487 ret = eth_adin2111_reg_write(dev, ADIN2111_IMASK0, ctx->imask0);
1488 if (ret < 0) {
1489 LOG_ERR("Failed to write IMASK0, %d", ret);
1490 return ret;
1491 }
1492 ret = eth_adin2111_reg_write(dev, ADIN2111_IMASK1, ctx->imask1);
1493 if (ret < 0) {
1494 LOG_ERR("Failed to write IMASK1, %d", ret);
1495 return ret;
1496 }
1497
1498 ret = gpio_pin_interrupt_configure_dt(&cfg->interrupt,
1499 GPIO_INT_EDGE_TO_ACTIVE);
1500 if (ret < 0) {
1501 LOG_ERR("Failed to enable INT, %d", ret);
1502 return ret;
1503 }
1504
1505 return ret;
1506 }
1507
1508 static const struct ethernet_api adin2111_port_api = {
1509 .iface_api.init = adin2111_port_iface_init,
1510 .get_capabilities = adin2111_port_get_capabilities,
1511 .set_config = adin2111_port_set_config,
1512 .send = adin2111_port_send,
1513 #if defined(CONFIG_NET_STATISTICS_ETHERNET)
1514 .get_stats = adin2111_port_get_stats,
1515 #endif /* CONFIG_NET_STATISTICS_ETHERNET */
1516 };
1517
1518 #define ADIN2111_STR(x) #x
1519 #define ADIN2111_XSTR(x) ADIN2111_STR(x)
1520
1521 #define ADIN2111_DEF_BUF(name, size) static uint8_t __aligned(4) name[size]
1522
1523 #define ADIN2111_MDIO_PHY_BY_ADDR(adin_n, phy_addr) \
1524 DEVICE_DT_GET(DT_CHILD(DT_INST_CHILD(adin_n, mdio), ethernet_phy_##phy_addr))
1525
1526 #define ADIN2111_PORT_MAC(adin_n, port_n) \
1527 DT_PROP(DT_CHILD(DT_DRV_INST(adin_n), port##port_n), local_mac_address)
1528
1529 #define ADIN2111_PORT_DEVICE_INIT_INSTANCE(parent_n, port_n, phy_n, name) \
1530 static struct adin2111_port_data name##_port_data_##port_n = { \
1531 .mac_addr = ADIN2111_PORT_MAC(parent_n, phy_n), \
1532 }; \
1533 static const struct adin2111_port_config name##_port_config_##port_n = { \
1534 .adin = DEVICE_DT_INST_GET(parent_n), \
1535 .phy = ADIN2111_MDIO_PHY_BY_ADDR(parent_n, phy_n), \
1536 .port_idx = port_n, \
1537 .phy_addr = phy_n, \
1538 }; \
1539 ETH_NET_DEVICE_INIT_INSTANCE(name##_port_##port_n, "port_" ADIN2111_XSTR(port_n), \
1540 port_n, NULL, NULL, &name##_port_data_##port_n, \
1541 &name##_port_config_##port_n, CONFIG_ETH_INIT_PRIORITY, \
1542 &adin2111_port_api, NET_ETH_MTU);
1543
1544 #define ADIN2111_SPI_OPERATION ((uint16_t)(SPI_OP_MODE_MASTER | SPI_TRANSFER_MSB | SPI_WORD_SET(8)))
1545 #define ADIN2111_MAC_INITIALIZE(inst, dev_id, ifaces, name) \
1546 ADIN2111_DEF_BUF(name##_buffer_##inst, CONFIG_ETH_ADIN2111_BUFFER_SIZE); \
1547 COND_CODE_1(DT_INST_PROP(inst, spi_oa), \
1548 ( \
1549 ADIN2111_DEF_BUF(name##_oa_tx_buf_##inst, ADIN2111_OA_BUF_SZ); \
1550 ADIN2111_DEF_BUF(name##_oa_rx_buf_##inst, ADIN2111_OA_BUF_SZ); \
1551 ), ()) \
1552 static const struct adin2111_config name##_config_##inst = { \
1553 .id = dev_id, \
1554 .spi = SPI_DT_SPEC_INST_GET(inst, ADIN2111_SPI_OPERATION, 0), \
1555 .interrupt = GPIO_DT_SPEC_INST_GET(inst, int_gpios), \
1556 .reset = GPIO_DT_SPEC_INST_GET_OR(inst, reset_gpios, { 0 }), \
1557 }; \
1558 static struct adin2111_data name##_data_##inst = { \
1559 .ifaces_left_to_init = ifaces, \
1560 .port = {}, \
1561 .offload_sem = Z_SEM_INITIALIZER(name##_data_##inst.offload_sem, 0, 1), \
1562 .lock = Z_MUTEX_INITIALIZER(name##_data_##inst.lock), \
1563 .buf = name##_buffer_##inst, \
1564 .oa = DT_INST_PROP(inst, spi_oa), \
1565 .oa_prot = DT_INST_PROP(inst, spi_oa_protection), \
1566 .oa_cps = 64, \
1567 .oa_tx_buf = COND_CODE_1(DT_INST_PROP(inst, spi_oa), \
1568 (name##_oa_tx_buf_##inst), (NULL)), \
1569 .oa_rx_buf = COND_CODE_1(DT_INST_PROP(inst, spi_oa), \
1570 (name##_oa_rx_buf_##inst), (NULL)), \
1571 }; \
1572 /* adin */ \
1573 DEVICE_DT_DEFINE(DT_DRV_INST(inst), adin2111_init, NULL, \
1574 &name##_data_##inst, &name##_config_##inst, \
1575 POST_KERNEL, CONFIG_ETH_INIT_PRIORITY, \
1576 NULL);
1577
1578 #define ADIN2111_MAC_INIT(inst) ADIN2111_MAC_INITIALIZE(inst, ADIN2111_MAC, 2, adin2111) \
1579 /* ports */ \
1580 ADIN2111_PORT_DEVICE_INIT_INSTANCE(inst, 0, 1, adin2111) \
1581 ADIN2111_PORT_DEVICE_INIT_INSTANCE(inst, 1, 2, adin2111)
1582
1583 #undef DT_DRV_COMPAT
1584 #define DT_DRV_COMPAT adi_adin2111
1585 DT_INST_FOREACH_STATUS_OKAY(ADIN2111_MAC_INIT)
1586
1587 #define ADIN1110_MAC_INIT(inst) ADIN2111_MAC_INITIALIZE(inst, ADIN1110_MAC, 1, adin1110) \
1588 /* ports */ \
1589 ADIN2111_PORT_DEVICE_INIT_INSTANCE(inst, 0, 1, adin1110)
1590
1591 #undef DT_DRV_COMPAT
1592 #define DT_DRV_COMPAT adi_adin1110
1593 DT_INST_FOREACH_STATUS_OKAY(ADIN1110_MAC_INIT)
1594