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 frame length is FSIZE - FRAME HEADER - CRC32 */
561 fsize_real = fsize - (ADIN2111_FRAME_HEADER_SIZE + sizeof(uint32_t));
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_real},
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 pkt = net_pkt_rx_alloc_with_buffer(iface, fsize_real, AF_UNSPEC, 0,
594 K_MSEC(CONFIG_ETH_ADIN2111_TIMEOUT));
595 if (!pkt) {
596 eth_stats_update_errors_rx(iface);
597 LOG_ERR("Port %u failed to alloc frame RX buffer, %u bytes",
598 port_idx, fsize_real);
599 return -ENOMEM;
600 }
601
602 ret = net_pkt_write(pkt, ctx->buf, fsize_real);
603 if (ret < 0) {
604 eth_stats_update_errors_rx(iface);
605 net_pkt_unref(pkt);
606 LOG_ERR("Port %u failed to fill RX frame, %d", port_idx, ret);
607 return ret;
608 }
609
610 ret = net_recv_data(iface, pkt);
611 if (ret < 0) {
612 eth_stats_update_errors_rx(iface);
613 net_pkt_unref(pkt);
614 LOG_ERR("Port %u failed to enqueue frame to RX queue, %d",
615 port_idx, ret);
616 return ret;
617 }
618
619 eth_stats_update_bytes_rx(iface, fsize_real);
620 eth_stats_update_pkts_rx(iface);
621
622 return ret;
623 }
624
adin2111_port_on_phyint(const struct device * dev)625 static inline void adin2111_port_on_phyint(const struct device *dev)
626 {
627 const struct adin2111_port_config *cfg = dev->config;
628 struct adin2111_port_data *data = dev->data;
629 struct phy_link_state state;
630
631 if (phy_adin2111_handle_phy_irq(cfg->phy, &state) < 0) {
632 /* no change or error */
633 return;
634 }
635
636 if (state.is_up) {
637 net_eth_carrier_on(data->iface);
638 } else {
639 net_eth_carrier_off(data->iface);
640 }
641 }
642
adin2111_offload_thread(void * p1,void * p2,void * p3)643 static void adin2111_offload_thread(void *p1, void *p2, void *p3)
644 {
645 ARG_UNUSED(p2);
646 ARG_UNUSED(p3);
647
648 const struct device *dev = p1;
649 struct adin2111_data *ctx = dev->data;
650 const struct adin2111_config *adin_cfg = dev->config;
651 bool is_adin2111 = (adin_cfg->id == ADIN2111_MAC);
652 uint32_t status0;
653 uint32_t status1;
654 int ret;
655
656 for (;;) {
657 /* await INT */
658 k_sem_take(&ctx->offload_sem, K_FOREVER);
659
660 /* lock device */
661 eth_adin2111_lock(dev, K_FOREVER);
662
663 /* disable interrupts */
664 ret = eth_adin2111_reg_write(dev, ADIN2111_IMASK0, UINT32_MAX);
665 if (ret < 0) {
666 goto continue_unlock;
667 }
668 ret = eth_adin2111_reg_write(dev, ADIN2111_IMASK1, UINT32_MAX);
669 if (ret < 0) {
670 goto continue_unlock;
671 }
672
673 /* read interrupts */
674 ret = eth_adin2111_reg_read(dev, ADIN2111_STATUS0, &status0);
675 if (ret < 0) {
676 goto continue_unlock;
677 }
678 ret = eth_adin2111_reg_read(dev, ADIN2111_STATUS1, &status1);
679 if (ret < 0) {
680 goto continue_unlock;
681 }
682
683 if (!ctx->oa) {
684 #if CONFIG_ETH_ADIN2111_SPI_CFG0
685 if (status0 & ADIN2111_STATUS1_SPI_ERR) {
686 LOG_WRN("Detected TX SPI CRC error");
687 }
688 #endif
689 }
690
691 /* handle port 1 phy interrupts */
692 if (status0 & ADIN2111_STATUS0_PHYINT) {
693 adin2111_port_on_phyint(ctx->port[0]);
694 }
695
696 /* handle port 2 phy interrupts */
697 if ((status1 & ADIN2111_STATUS1_PHYINT) && is_adin2111) {
698 adin2111_port_on_phyint(ctx->port[1]);
699 }
700
701 if (ctx->oa) {
702 if (status1 & ADIN2111_STATUS1_P1_RX_RDY) {
703 ret = eth_adin2111_oa_data_read(dev, 0);
704 if (ret < 0) {
705 break;
706 }
707 }
708 if (status1 & ADIN2111_STATUS1_P2_RX_RDY) {
709 ret = eth_adin2111_oa_data_read(dev, 1);
710 if (ret < 0) {
711 break;
712 }
713 }
714 goto continue_unlock;
715 }
716
717 /* handle port 1 rx */
718 if (status1 & ADIN2111_STATUS1_P1_RX_RDY) {
719 do {
720 ret = adin2111_read_fifo(dev, 0U);
721 if (ret < 0) {
722 break;
723 }
724
725 ret = eth_adin2111_reg_read(dev, ADIN2111_STATUS1, &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 ((status1 & ADIN2111_STATUS1_P2_RX_RDY) && is_adin2111) {
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, &status1);
741 if (ret < 0) {
742 goto continue_unlock;
743 }
744 } while (!!(status1 & ADIN2111_STATUS1_P2_RX_RDY));
745 }
746
747 continue_unlock:
748 /* clear interrupts */
749 ret = eth_adin2111_reg_write(dev, ADIN2111_STATUS0, ADIN2111_STATUS0_CLEAR);
750 if (ret < 0) {
751 LOG_ERR("Failed to clear STATUS0, %d", ret);
752 }
753 ret = eth_adin2111_reg_write(dev, ADIN2111_STATUS1, ADIN2111_STATUS1_CLEAR);
754 if (ret < 0) {
755 LOG_ERR("Failed to clear STATUS1, %d", ret);
756 }
757 /* enable interrupts */
758 ret = eth_adin2111_reg_write(dev, ADIN2111_IMASK0, ctx->imask0);
759 if (ret < 0) {
760 LOG_ERR("Failed to write IMASK0, %d", ret);
761 }
762 ret = eth_adin2111_reg_write(dev, ADIN2111_IMASK1, ctx->imask1);
763 if (ret < 0) {
764 LOG_ERR("Failed to write IMASK1, %d", ret);
765 }
766 eth_adin2111_unlock(dev);
767 }
768 }
769
adin2111_int_callback(const struct device * dev,struct gpio_callback * cb,uint32_t pins)770 static void adin2111_int_callback(const struct device *dev,
771 struct gpio_callback *cb,
772 uint32_t pins)
773 {
774 ARG_UNUSED(dev);
775 ARG_UNUSED(pins);
776
777 struct adin2111_data *ctx = CONTAINER_OF(cb, struct adin2111_data, gpio_int_callback);
778
779 k_sem_give(&ctx->offload_sem);
780 }
781
adin2111_read_tx_space(const struct device * dev,uint32_t * space)782 static int adin2111_read_tx_space(const struct device *dev, uint32_t *space)
783 {
784 uint32_t val;
785 int ret;
786
787 ret = eth_adin2111_reg_read(dev, ADIN2111_TX_SPACE, &val);
788 if (ret < 0) {
789 return ret;
790 }
791
792 /* tx space is a number of halfwords (16-bits), multiply by 2 for bytes */
793 *space = val * 2;
794
795 return ret;
796 }
797
adin2111_port_send(const struct device * dev,struct net_pkt * pkt)798 static int adin2111_port_send(const struct device *dev, struct net_pkt *pkt)
799 {
800 const struct adin2111_port_config *cfg = dev->config;
801 #if defined(CONFIG_NET_STATISTICS_ETHERNET)
802 struct adin2111_port_data *data = dev->data;
803 #endif /* CONFIG_NET_STATISTICS_ETHERNET */
804 const struct device *adin = cfg->adin;
805 struct adin2111_data *ctx = cfg->adin->data;
806 size_t pkt_len = net_pkt_get_len(pkt);
807 size_t header_size = ADIN2111_WRITE_HEADER_SIZE;
808 size_t padded_size;
809 size_t burst_size;
810 uint32_t tx_space;
811 int ret;
812
813 eth_adin2111_lock(adin, K_FOREVER);
814
815 if (ctx->oa) {
816 uint32_t val, rca = 0;
817 /*
818 * By high-traffic zperf test, noted that ADIN2111 does not like we send
819 * if there is something to be received. It stops to issue rx interrupts
820 * and zperf transfer hangs. Forcing a receive for this case.
821 */
822 ret = eth_adin2111_reg_read(adin, ADIN2111_BUFSTS, &val);
823 if (ret < 0) {
824 return ret;
825 }
826 rca = val & ADIN2111_BUFSTS_RCA_MASK;
827
828 if (rca > 0) {
829 eth_adin2111_unlock(adin);
830 k_sem_give(&ctx->offload_sem);
831 k_yield();
832 eth_adin2111_lock(adin, K_FOREVER);
833 }
834
835 ret = eth_adin2111_send_oa_frame(cfg->adin, pkt, htons(cfg->port_idx));
836
837 goto end_check;
838 }
839
840 /* query remaining tx fifo space */
841 ret = adin2111_read_tx_space(adin, &tx_space);
842 if (ret < 0) {
843 eth_stats_update_errors_tx(data->iface);
844 LOG_ERR("Failed to read TX FIFO space, %d", ret);
845 goto end_unlock;
846 }
847
848 /**
849 * verify that there is space for the frame
850 * (frame + 2b header + 2b size field)
851 */
852 if (tx_space <
853 (pkt_len + ADIN2111_FRAME_HEADER_SIZE + ADIN2111_INTERNAL_HEADER_SIZE)) {
854 /* tx buffer is full */
855 eth_stats_update_errors_tx(data->iface);
856 ret = -EBUSY;
857 goto end_unlock;
858 }
859
860 /**
861 * pad to 64 bytes, otherwise MAC/PHY has to do it
862 * internally MAC adds 4 bytes for forward error correction
863 */
864 if ((pkt_len + ADIN2111_TX_FIFO_BUFFER_MARGIN) < 64) {
865 padded_size = pkt_len
866 + (64 - (pkt_len + ADIN2111_TX_FIFO_BUFFER_MARGIN))
867 + ADIN2111_FRAME_HEADER_SIZE;
868 } else {
869 padded_size = pkt_len + ADIN2111_FRAME_HEADER_SIZE;
870 }
871
872 /* prepare burst write (write data must be in multiples of 4) */
873 burst_size = ROUND_UP(padded_size, 4);
874 if ((burst_size + ADIN2111_WRITE_HEADER_SIZE) > CONFIG_ETH_ADIN2111_BUFFER_SIZE) {
875 ret = -ENOMEM;
876 eth_stats_update_errors_tx(data->iface);
877 goto end_unlock;
878 }
879
880 /* prepare tx buffer */
881 memset(ctx->buf, 0, burst_size + ADIN2111_WRITE_HEADER_SIZE);
882
883 /* spi header */
884 *(uint16_t *)ctx->buf = htons(ADIN2111_TXN_CTRL_TX_REG);
885 #if CONFIG_ETH_ADIN2111_SPI_CFG0
886 ctx->buf[2] = crc8_ccitt(0, ctx->buf, header_size);
887 ++header_size;
888 #endif /* CONFIG_ETH_ADIN2111_SPI_CFG0 */
889
890 /* frame header */
891 *(uint16_t *)(ctx->buf + header_size) = htons(cfg->port_idx);
892
893 /* read pkt into tx buffer */
894 ret = net_pkt_read(pkt,
895 (ctx->buf + header_size + ADIN2111_FRAME_HEADER_SIZE),
896 pkt_len);
897 if (ret < 0) {
898 eth_stats_update_errors_tx(data->iface);
899 LOG_ERR("Port %u failed to read PKT into TX buffer, %d",
900 cfg->port_idx, ret);
901 goto end_unlock;
902 }
903
904 /* write transmit size */
905 ret = eth_adin2111_reg_write(adin, ADIN2111_TX_FSIZE, padded_size);
906 if (ret < 0) {
907 eth_stats_update_errors_tx(data->iface);
908 LOG_ERR("Port %u write FSIZE failed, %d", cfg->port_idx, ret);
909 goto end_unlock;
910 }
911
912 /* write transaction */
913 const struct spi_buf buf = {
914 .buf = ctx->buf,
915 .len = header_size + burst_size
916 };
917 const struct spi_buf_set tx = { .buffers = &buf, .count = 1U };
918
919 ret = spi_write_dt(&((const struct adin2111_config *) adin->config)->spi,
920 &tx);
921 end_check:
922 if (ret < 0) {
923 eth_stats_update_errors_tx(data->iface);
924 LOG_ERR("Port %u frame SPI write failed, %d", cfg->port_idx, ret);
925 goto end_unlock;
926 }
927
928 eth_stats_update_bytes_tx(data->iface, pkt_len);
929 eth_stats_update_pkts_tx(data->iface);
930
931 end_unlock:
932 eth_adin2111_unlock(adin);
933 return ret;
934 }
935
adin2111_config_sync(const struct device * dev)936 static int adin2111_config_sync(const struct device *dev)
937 {
938 int ret;
939 uint32_t val;
940
941 ret = eth_adin2111_reg_read(dev, ADIN2111_CONFIG0, &val);
942 if (ret < 0) {
943 return ret;
944 }
945
946 val |= ADIN2111_CONFIG0_SYNC;
947
948 ret = eth_adin2111_reg_write(dev, ADIN2111_CONFIG0, val);
949 if (ret < 0) {
950 return ret;
951 }
952
953 return 0;
954 }
955
adin2111_write_filter_address(const struct device * dev,uint8_t * addr,uint8_t * mask,uint32_t rules,uint16_t slot)956 static int adin2111_write_filter_address(const struct device *dev,
957 uint8_t *addr, uint8_t *mask,
958 uint32_t rules, uint16_t slot)
959 {
960 uint16_t offset = slot * 2U;
961 int ret;
962
963 ret = eth_adin2111_reg_write(dev, ADIN2111_ADDR_FILT_UPR + offset,
964 rules | sys_get_be16(&addr[0]));
965 if (ret < 0) {
966 return ret;
967 }
968
969 ret = eth_adin2111_reg_write(dev, ADIN2111_ADDR_FILT_LWR + offset,
970 sys_get_be32(&addr[2]));
971 if (ret < 0) {
972 return ret;
973 }
974
975 if (offset > 2U) {
976 /* mask filter addresses are limited to 2 */
977 return 0;
978 }
979
980 ret = eth_adin2111_reg_write(dev, ADIN2111_ADDR_MSK_UPR + offset,
981 sys_get_be16(&mask[0]));
982 if (ret < 0) {
983 return ret;
984 }
985
986 ret = eth_adin2111_reg_write(dev, ADIN2111_ADDR_MSK_LWR + offset,
987 sys_get_be32(&mask[2]));
988 if (ret < 0) {
989 return ret;
990 }
991
992 return ret;
993 }
994
adin2111_filter_multicast(const struct device * dev)995 static int adin2111_filter_multicast(const struct device *dev)
996 {
997 const struct adin2111_config *cfg = dev->config;
998 bool is_adin2111 = (cfg->id == ADIN2111_MAC);
999 uint8_t mm[NET_ETH_ADDR_LEN] = {BIT(0), 0U, 0U, 0U, 0U, 0U};
1000 uint8_t mmask[NET_ETH_ADDR_LEN] = {0xFFU, 0U, 0U, 0U, 0U, 0U};
1001 uint32_t rules = ADIN2111_ADDR_APPLY2PORT1 |
1002 (is_adin2111 ? ADIN2111_ADDR_APPLY2PORT2 : 0) |
1003 ADIN2111_ADDR_TO_HOST |
1004 ADIN2111_ADDR_TO_OTHER_PORT;
1005
1006 return adin2111_write_filter_address(dev, mm, mmask, rules,
1007 ADIN2111_MULTICAST_ADDR_SLOT);
1008 }
1009
adin2111_filter_broadcast(const struct device * dev)1010 static int adin2111_filter_broadcast(const struct device *dev)
1011 {
1012 const struct adin2111_config *cfg = dev->config;
1013 bool is_adin2111 = (cfg->id == ADIN2111_MAC);
1014 uint8_t mac[NET_ETH_ADDR_LEN] = {0xFFU, 0xFFU, 0xFFU, 0xFFU, 0xFFU, 0xFFU};
1015 uint32_t rules = ADIN2111_ADDR_APPLY2PORT1 |
1016 (is_adin2111 ? ADIN2111_ADDR_APPLY2PORT2 : 0) |
1017 ADIN2111_ADDR_TO_HOST |
1018 ADIN2111_ADDR_TO_OTHER_PORT;
1019
1020 return adin2111_write_filter_address(dev, mac, mac, rules,
1021 ADIN2111_BROADCAST_ADDR_SLOT);
1022 }
1023
adin2111_filter_unicast(const struct device * dev,uint8_t * addr,const uint16_t port_idx)1024 static int adin2111_filter_unicast(const struct device *dev, uint8_t *addr,
1025 const uint16_t port_idx)
1026 {
1027 uint32_t rules = (port_idx == 0 ? ADIN2111_ADDR_APPLY2PORT1
1028 : ADIN2111_ADDR_APPLY2PORT2)
1029 | ADIN2111_ADDR_TO_HOST;
1030 uint16_t slot = (port_idx == 0 ? ADIN2111_UNICAST_P1_ADDR_SLOT
1031 : ADIN2111_UNICAST_P2_ADDR_SLOT);
1032
1033 return adin2111_write_filter_address(dev, addr, NULL, rules, slot);
1034 }
1035
eth_adin2111_broadcast_filter(const struct device * dev,bool enable)1036 int eth_adin2111_broadcast_filter(const struct device *dev, bool enable)
1037 {
1038 if (!enable) {
1039 /* Clean up */
1040 uint8_t mac[NET_ETH_ADDR_LEN] = {0};
1041
1042 return adin2111_write_filter_address(dev, mac, mac, 0,
1043 ADIN2111_BROADCAST_ADDR_SLOT);
1044 }
1045
1046 return adin2111_filter_broadcast(dev);
1047 }
1048
1049 /*
1050 * Check if a filter exists already.
1051 */
eth_adin2111_find_filter(const struct device * dev,uint8_t * mac,const uint16_t port_idx)1052 static int eth_adin2111_find_filter(const struct device *dev, uint8_t *mac, const uint16_t port_idx)
1053 {
1054 int i, offset, reg, ret;
1055
1056 for (i = ADIN2111_FILTER_FIRST_SLOT; i < ADIN2111_FILTER_SLOTS; i++) {
1057 offset = i << 1;
1058 ret = eth_adin2111_reg_read(dev, ADIN2111_ADDR_FILT_UPR + offset, ®);
1059 if (ret < 0) {
1060 return ret;
1061 }
1062 if ((reg & UINT16_MAX) == sys_get_be16(&mac[0])) {
1063 if ((port_idx == 0 && !(reg & ADIN2111_ADDR_APPLY2PORT1)) ||
1064 (port_idx == 1 && !(reg & ADIN2111_ADDR_APPLY2PORT2)))
1065 continue;
1066
1067 ret = eth_adin2111_reg_read(dev, ADIN2111_ADDR_FILT_LWR + offset, ®);
1068 if (ret < 0) {
1069 return ret;
1070 }
1071 if (reg == sys_get_be32(&mac[2])) {
1072 return i;
1073 }
1074 }
1075 }
1076
1077 return -ENOENT;
1078 }
1079
eth_adin2111_set_mac_filter(const struct device * dev,uint8_t * mac,const uint16_t port_idx)1080 static int eth_adin2111_set_mac_filter(const struct device *dev, uint8_t *mac,
1081 const uint16_t port_idx)
1082 {
1083 int i, ret, offset;
1084 uint32_t reg;
1085
1086 ret = eth_adin2111_find_filter(dev, mac, port_idx);
1087 if (ret >= 0) {
1088 LOG_WRN("MAC filter already set at pos %d, not setting it.", ret);
1089 return ret;
1090 }
1091 if (ret != -ENOENT) {
1092 return ret;
1093 }
1094
1095 for (i = ADIN2111_FILTER_FIRST_SLOT; i < ADIN2111_FILTER_SLOTS; i++) {
1096 offset = i << 1;
1097 ret = eth_adin2111_reg_read(dev, ADIN2111_ADDR_FILT_UPR + offset, ®);
1098 if (ret < 0) {
1099 return ret;
1100 }
1101 if (reg == 0) {
1102 uint32_t rules = (port_idx == 0 ? ADIN2111_ADDR_APPLY2PORT1
1103 : ADIN2111_ADDR_APPLY2PORT2)
1104 | ADIN2111_ADDR_TO_HOST;
1105
1106 return adin2111_write_filter_address(dev, mac, NULL, rules, i);
1107 }
1108 }
1109
1110 return -ENOSPC;
1111 }
1112
eth_adin2111_clear_mac_filter(const struct device * dev,uint8_t * mac,const uint16_t port_idx)1113 static int eth_adin2111_clear_mac_filter(const struct device *dev, uint8_t *mac,
1114 const uint16_t port_idx)
1115 {
1116 int i;
1117 uint8_t cmac[NET_ETH_ADDR_LEN] = {0};
1118
1119 i = eth_adin2111_find_filter(dev, mac, port_idx);
1120 if (i < 0) {
1121 return i;
1122 }
1123
1124 return adin2111_write_filter_address(dev, cmac, cmac, 0, i);
1125 }
1126
1127 #if defined(CONFIG_NET_PROMISCUOUS_MODE)
eth_adin2111_set_promiscuous(const struct device * dev,const uint16_t port_idx,bool enable)1128 static int eth_adin2111_set_promiscuous(const struct device *dev, const uint16_t port_idx,
1129 bool enable)
1130 {
1131 const struct adin2111_config *cfg = dev->config;
1132 bool is_adin2111 = (cfg->id == ADIN2111_MAC);
1133 uint32_t fwd_mask;
1134
1135 if ((!is_adin2111 && port_idx > 0) || (is_adin2111 && port_idx > 1)) {
1136 return -EINVAL;
1137 }
1138
1139 fwd_mask = port_idx ? ADIN2111_CONFIG2_P2_FWD_UNK2HOST : ADIN2111_CONFIG2_P1_FWD_UNK2HOST;
1140
1141 return eth_adin2111_reg_update(dev, ADIN2111_CONFIG2, fwd_mask, enable ? fwd_mask : 0);
1142 }
1143 #endif
1144
adin2111_port_iface_init(struct net_if * iface)1145 static void adin2111_port_iface_init(struct net_if *iface)
1146 {
1147 const struct device *dev = net_if_get_device(iface);
1148 const struct adin2111_port_config *cfg = dev->config;
1149 struct adin2111_port_data *data = dev->data;
1150 const struct device *adin = cfg->adin;
1151 struct adin2111_data *ctx = adin->data;
1152 int ret;
1153
1154 if (!device_is_ready(adin)) {
1155 LOG_ERR("ADIN %s is not ready, can't init port %u iface",
1156 cfg->adin->name, cfg->port_idx);
1157 return;
1158 }
1159
1160 if (!device_is_ready(cfg->phy)) {
1161 LOG_ERR("PHY %u is not ready, can't init port %u iface",
1162 cfg->phy_addr, cfg->port_idx);
1163 return;
1164 }
1165
1166 ctx->port[cfg->port_idx] = dev;
1167 data->iface = iface;
1168
1169 ret = adin2111_filter_unicast(adin, data->mac_addr, cfg->port_idx);
1170 if (ret < 0) {
1171 LOG_ERR("Port %u, failed to set unicast filter, %d",
1172 cfg->port_idx, ret);
1173 return;
1174 }
1175 net_if_set_link_addr(iface, data->mac_addr, sizeof(data->mac_addr),
1176 NET_LINK_ETHERNET);
1177 ethernet_init(iface);
1178 net_if_carrier_off(iface);
1179
1180 --ctx->ifaces_left_to_init;
1181
1182 /* if all ports are initialized */
1183 if (ctx->ifaces_left_to_init == 0U) {
1184 /* setup rx filters */
1185 ret = adin2111_filter_multicast(adin);
1186 if (ret < 0) {
1187 LOG_ERR("Couldn't set multicast filter, %d", ret);
1188 return;
1189 }
1190 ret = adin2111_filter_broadcast(adin);
1191 if (ret < 0) {
1192 LOG_ERR("Couldn't set broadcast filter, %d", ret);
1193 return;
1194 }
1195
1196 /* sync */
1197 ret = adin2111_config_sync(adin);
1198 if (ret < 0) {
1199 LOG_ERR("Failed to write CONFIG0 SYNC, %d", ret);
1200 return;
1201 }
1202
1203 /* all ifaces are done, start INT processing */
1204 k_thread_create(&ctx->rx_thread, ctx->rx_thread_stack,
1205 K_KERNEL_STACK_SIZEOF(ctx->rx_thread_stack),
1206 adin2111_offload_thread,
1207 (void *)adin, NULL, NULL,
1208 CONFIG_ETH_ADIN2111_IRQ_THREAD_PRIO,
1209 K_ESSENTIAL, K_NO_WAIT);
1210 k_thread_name_set(&ctx->rx_thread, "eth_adin2111_offload");
1211 }
1212 }
1213
adin2111_port_get_capabilities(const struct device * dev)1214 static enum ethernet_hw_caps adin2111_port_get_capabilities(const struct device *dev)
1215 {
1216 ARG_UNUSED(dev);
1217 return ETHERNET_LINK_10BASE_T |
1218 ETHERNET_HW_FILTERING
1219 #if defined(CONFIG_NET_LLDP)
1220 | ETHERNET_LLDP
1221 #endif
1222 | ETHERNET_PROMISC_MODE;
1223 }
1224
adin2111_port_set_config(const struct device * dev,enum ethernet_config_type type,const struct ethernet_config * config)1225 static int adin2111_port_set_config(const struct device *dev,
1226 enum ethernet_config_type type,
1227 const struct ethernet_config *config)
1228 {
1229 const struct adin2111_port_config *cfg = dev->config;
1230 struct adin2111_port_data *data = dev->data;
1231 const struct device *adin = cfg->adin;
1232 int ret = -ENOTSUP;
1233
1234 (void)eth_adin2111_lock(adin, K_FOREVER);
1235
1236 if (type == ETHERNET_CONFIG_TYPE_MAC_ADDRESS) {
1237 ret = adin2111_filter_unicast(adin, (uint8_t *)&config->mac_address.addr[0],
1238 cfg->port_idx);
1239 if (ret < 0) {
1240 goto end_unlock;
1241 }
1242
1243 (void)memcpy(data->mac_addr, config->mac_address.addr, sizeof(data->mac_addr));
1244
1245 (void)net_if_set_link_addr(data->iface, data->mac_addr, sizeof(data->mac_addr),
1246 NET_LINK_ETHERNET);
1247 }
1248
1249 if (type == ETHERNET_CONFIG_TYPE_FILTER) {
1250 /* Filtering for DA only */
1251 if (config->filter.type & ETHERNET_FILTER_TYPE_DST_MAC_ADDRESS) {
1252 uint8_t *mac = (uint8_t *)config->filter.mac_address.addr;
1253
1254 if (config->filter.set) {
1255 ret = eth_adin2111_set_mac_filter(adin, mac, cfg->port_idx);
1256 } else {
1257 ret = eth_adin2111_clear_mac_filter(adin, mac, cfg->port_idx);
1258 }
1259 }
1260 }
1261
1262 #if defined(CONFIG_NET_PROMISCUOUS_MODE)
1263 if (type == ETHERNET_CONFIG_TYPE_PROMISC_MODE) {
1264 ret = eth_adin2111_set_promiscuous(adin, cfg->port_idx, config->promisc_mode);
1265 }
1266 #endif
1267
1268 end_unlock:
1269 (void)eth_adin2111_unlock(adin);
1270 return ret;
1271 }
1272
1273 #if defined(CONFIG_NET_STATISTICS_ETHERNET)
adin2111_port_get_stats(const struct device * dev)1274 static struct net_stats_eth *adin2111_port_get_stats(const struct device *dev)
1275 {
1276 struct adin2111_port_data *data = dev->data;
1277
1278 return &data->stats;
1279 }
1280 #endif /* CONFIG_NET_STATISTICS_ETHERNET */
1281
adin2111_check_spi(const struct device * dev)1282 static int adin2111_check_spi(const struct device *dev)
1283 {
1284 uint32_t count;
1285 uint32_t val;
1286 int ret;
1287
1288 /* check SPI communication by reading PHYID */
1289 for (count = 0U; count < ADIN2111_DEV_AWAIT_RETRY_COUNT; ++count) {
1290 ret = eth_adin2111_reg_read(dev, ADIN2111_PHYID, &val);
1291 if (ret >= 0) {
1292 if (val == ADIN2111_PHYID_RST_VAL || val == ADIN1110_PHYID_RST_VAL) {
1293 break;
1294 }
1295 ret = -ETIMEDOUT;
1296 }
1297 k_sleep(K_USEC(ADIN2111_DEV_AWAIT_DELAY_POLL_US));
1298 }
1299
1300 return ret;
1301 }
1302
adin2111_await_device(const struct device * dev)1303 static int adin2111_await_device(const struct device *dev)
1304 {
1305 uint32_t count;
1306 uint32_t val;
1307 int ret;
1308
1309 /* await reset complete (RESETC) and clear it */
1310 for (count = 0U; count < ADIN2111_RESETC_AWAIT_RETRY_COUNT; ++count) {
1311 ret = eth_adin2111_reg_read(dev, ADIN2111_PHYID, &val);
1312 if (ret >= 0) {
1313 /*
1314 * Even after getting RESETC, for some milliseconds registers are
1315 * still not properly readable (they reads 0),
1316 * so checking OUI read-only value instead.
1317 */
1318 if ((val >> 10) == ADIN2111_PHYID_OUI) {
1319 /* clear RESETC */
1320 ret = eth_adin2111_reg_write(dev, ADIN2111_STATUS0,
1321 ADIN2111_STATUS0_RESETC);
1322 if (ret >= 0) {
1323 break;
1324 }
1325 }
1326 ret = -ETIMEDOUT;
1327 }
1328 k_sleep(K_USEC(ADIN2111_RESETC_AWAIT_DELAY_POLL_US));
1329 }
1330
1331 return ret;
1332 }
1333
eth_adin2111_sw_reset(const struct device * dev,uint16_t delay)1334 int eth_adin2111_sw_reset(const struct device *dev, uint16_t delay)
1335 {
1336 int ret;
1337
1338 ret = eth_adin2111_reg_write(dev, ADIN2111_RESET, ADIN2111_RESET_SWRESET);
1339 if (ret < 0) {
1340 return ret;
1341 }
1342
1343 k_msleep(delay);
1344
1345 ret = adin2111_await_device(dev);
1346 if (ret < 0) {
1347 LOG_ERR("ADIN did't come out of the reset, %d", ret);
1348 return ret;
1349 }
1350
1351 return ret;
1352 }
1353
adin2111_init(const struct device * dev)1354 static int adin2111_init(const struct device *dev)
1355 {
1356 const struct adin2111_config *cfg = dev->config;
1357 bool is_adin2111 = (cfg->id == ADIN2111_MAC);
1358 struct adin2111_data *ctx = dev->data;
1359 int ret;
1360 uint32_t val;
1361
1362 __ASSERT(cfg->spi.config.frequency <= ADIN2111_SPI_MAX_FREQUENCY,
1363 "SPI frequency exceeds supported maximum\n");
1364
1365 if (!spi_is_ready_dt(&cfg->spi)) {
1366 LOG_ERR("SPI bus %s not ready", cfg->spi.bus->name);
1367 return -ENODEV;
1368 }
1369
1370 if (!gpio_is_ready_dt(&cfg->interrupt)) {
1371 LOG_ERR("Interrupt GPIO device %s is not ready",
1372 cfg->interrupt.port->name);
1373 return -ENODEV;
1374 }
1375
1376 ret = gpio_pin_configure_dt(&cfg->interrupt, GPIO_INPUT);
1377 if (ret < 0) {
1378 LOG_ERR("Failed to configure interrupt GPIO, %d", ret);
1379 return ret;
1380 }
1381
1382 if (cfg->reset.port != NULL) {
1383 if (!gpio_is_ready_dt(&cfg->reset)) {
1384 LOG_ERR("Reset GPIO device %s is not ready",
1385 cfg->reset.port->name);
1386 return -ENODEV;
1387 }
1388
1389 ret = gpio_pin_configure_dt(&cfg->reset, GPIO_OUTPUT_INACTIVE);
1390 if (ret < 0) {
1391 LOG_ERR("Failed to configure reset GPIO, %d", ret);
1392 return ret;
1393 }
1394
1395 /* perform hard reset */
1396 /* assert pin low for 16 µs (10 µs min) */
1397 gpio_pin_set_dt(&cfg->reset, 1);
1398 k_busy_wait(16U);
1399 /* deassert and wait for 90 ms (max) for clocks stabilisation */
1400 gpio_pin_set_dt(&cfg->reset, 0);
1401 k_msleep(ADIN2111_HW_BOOT_DELAY_MS);
1402 }
1403
1404 gpio_init_callback(&(ctx->gpio_int_callback),
1405 adin2111_int_callback,
1406 BIT(cfg->interrupt.pin));
1407
1408 ret = gpio_add_callback(cfg->interrupt.port, &ctx->gpio_int_callback);
1409 if (ret < 0) {
1410 LOG_ERR("Failed to add INT callback, %d", ret);
1411 return ret;
1412 }
1413
1414 k_msleep(ADIN2111_SPI_ACTIVE_DELAY_MS);
1415
1416 ret = adin2111_check_spi(dev);
1417 if (ret < 0) {
1418 LOG_ERR("Failed to communicate over SPI, %d", ret);
1419 return ret;
1420 }
1421
1422 /* perform MACPHY soft reset */
1423 ret = eth_adin2111_sw_reset(dev, ADIN2111_SW_RESET_DELAY_MS);
1424 if (ret < 0) {
1425 LOG_ERR("MACPHY software reset failed, %d", ret);
1426 return ret;
1427 }
1428
1429 /* CONFIG 0 */
1430 /* disable Frame Check Sequence validation on the host */
1431 /* if that is enabled, then CONFIG_ETH_ADIN2111_SPI_CFG0 must be off */
1432 ret = eth_adin2111_reg_read(dev, ADIN2111_CONFIG0, &val);
1433 if (ret < 0) {
1434 LOG_ERR("Failed to read CONFIG0, %d", ret);
1435 return ret;
1436 }
1437
1438 /* RXCTE must be disabled for Generic SPI */
1439 val &= ~ADIN2111_CONFIG0_RXCTE;
1440 val &= ~(ADIN2111_CONFIG0_TXCTE | ADIN2111_CONFIG0_TXFCSVE);
1441
1442 if (ctx->oa) {
1443 val |= ADIN2111_CONFIG0_ZARFE;
1444 }
1445
1446 ret = eth_adin2111_reg_write(dev, ADIN2111_CONFIG0, val);
1447 if (ret < 0) {
1448 LOG_ERR("Failed to write CONFIG0, %d", ret);
1449 return ret;
1450 }
1451
1452 /* CONFIG 2 */
1453 ret = eth_adin2111_reg_read(dev, ADIN2111_CONFIG2, &val);
1454 if (ret < 0) {
1455 LOG_ERR("Failed to read CONFIG2, %d", ret);
1456 return ret;
1457 }
1458
1459 val |= ADIN2111_CONFIG2_CRC_APPEND;
1460
1461 /* configure forwarding of frames with unknown destination address */
1462 /* to the other port. This forwarding is done in hardware. */
1463 /* The setting will take effect after the ports */
1464 /* are out of software powerdown. */
1465 val |= (ADIN2111_CONFIG2_PORT_CUT_THRU_EN |
1466 (is_adin2111 ? ADIN2111_CONFIG2_P1_FWD_UNK2P2 : 0) |
1467 (is_adin2111 ? ADIN2111_CONFIG2_P2_FWD_UNK2P1 : 0));
1468
1469 ret = eth_adin2111_reg_write(dev, ADIN2111_CONFIG2, val);
1470 if (ret < 0) {
1471 LOG_ERR("Failed to write CONFIG2, %d", ret);
1472 return ret;
1473 }
1474
1475 /* configure interrupt masks */
1476 ctx->imask0 = ~((uint32_t)ADIN2111_IMASK0_PHYINTM);
1477 ctx->imask1 = ~(ADIN2111_IMASK1_TX_RDY_MASK |
1478 ADIN2111_IMASK1_P1_RX_RDY_MASK |
1479 ADIN2111_IMASK1_SPI_ERR_MASK |
1480 (is_adin2111 ? ADIN2111_IMASK1_P2_RX_RDY_MASK : 0) |
1481 (is_adin2111 ? ADIN2111_IMASK1_P2_PHYINT_MASK : 0));
1482
1483 /* enable interrupts */
1484 ret = eth_adin2111_reg_write(dev, ADIN2111_IMASK0, ctx->imask0);
1485 if (ret < 0) {
1486 LOG_ERR("Failed to write IMASK0, %d", ret);
1487 return ret;
1488 }
1489 ret = eth_adin2111_reg_write(dev, ADIN2111_IMASK1, ctx->imask1);
1490 if (ret < 0) {
1491 LOG_ERR("Failed to write IMASK1, %d", ret);
1492 return ret;
1493 }
1494
1495 ret = gpio_pin_interrupt_configure_dt(&cfg->interrupt,
1496 GPIO_INT_EDGE_TO_ACTIVE);
1497 if (ret < 0) {
1498 LOG_ERR("Failed to enable INT, %d", ret);
1499 return ret;
1500 }
1501
1502 return ret;
1503 }
1504
1505 static const struct ethernet_api adin2111_port_api = {
1506 .iface_api.init = adin2111_port_iface_init,
1507 .get_capabilities = adin2111_port_get_capabilities,
1508 .set_config = adin2111_port_set_config,
1509 .send = adin2111_port_send,
1510 #if defined(CONFIG_NET_STATISTICS_ETHERNET)
1511 .get_stats = adin2111_port_get_stats,
1512 #endif /* CONFIG_NET_STATISTICS_ETHERNET */
1513 };
1514
1515 #define ADIN2111_STR(x) #x
1516 #define ADIN2111_XSTR(x) ADIN2111_STR(x)
1517
1518 #define ADIN2111_DEF_BUF(name, size) static uint8_t __aligned(4) name[size]
1519
1520 #define ADIN2111_MDIO_PHY_BY_ADDR(adin_n, phy_addr) \
1521 DEVICE_DT_GET(DT_CHILD(DT_INST_CHILD(adin_n, mdio), ethernet_phy_##phy_addr))
1522
1523 #define ADIN2111_PORT_MAC(adin_n, port_n) \
1524 DT_PROP(DT_CHILD(DT_DRV_INST(adin_n), port##port_n), local_mac_address)
1525
1526 #define ADIN2111_PORT_DEVICE_INIT_INSTANCE(parent_n, port_n, phy_n, name) \
1527 static struct adin2111_port_data name##_port_data_##port_n = { \
1528 .mac_addr = ADIN2111_PORT_MAC(parent_n, phy_n), \
1529 }; \
1530 static const struct adin2111_port_config name##_port_config_##port_n = { \
1531 .adin = DEVICE_DT_INST_GET(parent_n), \
1532 .phy = ADIN2111_MDIO_PHY_BY_ADDR(parent_n, phy_n), \
1533 .port_idx = port_n, \
1534 .phy_addr = phy_n, \
1535 }; \
1536 ETH_NET_DEVICE_INIT_INSTANCE(name##_port_##port_n, "port_" ADIN2111_XSTR(port_n), \
1537 port_n, NULL, NULL, &name##_port_data_##port_n, \
1538 &name##_port_config_##port_n, CONFIG_ETH_INIT_PRIORITY, \
1539 &adin2111_port_api, NET_ETH_MTU);
1540
1541 #define ADIN2111_SPI_OPERATION ((uint16_t)(SPI_OP_MODE_MASTER | SPI_TRANSFER_MSB | SPI_WORD_SET(8)))
1542 #define ADIN2111_MAC_INITIALIZE(inst, dev_id, ifaces, name) \
1543 ADIN2111_DEF_BUF(name##_buffer_##inst, CONFIG_ETH_ADIN2111_BUFFER_SIZE); \
1544 COND_CODE_1(DT_INST_PROP(inst, spi_oa), \
1545 ( \
1546 ADIN2111_DEF_BUF(name##_oa_tx_buf_##inst, ADIN2111_OA_BUF_SZ); \
1547 ADIN2111_DEF_BUF(name##_oa_rx_buf_##inst, ADIN2111_OA_BUF_SZ); \
1548 ), ()) \
1549 static const struct adin2111_config name##_config_##inst = { \
1550 .id = dev_id, \
1551 .spi = SPI_DT_SPEC_INST_GET(inst, ADIN2111_SPI_OPERATION, 0), \
1552 .interrupt = GPIO_DT_SPEC_INST_GET(inst, int_gpios), \
1553 .reset = GPIO_DT_SPEC_INST_GET_OR(inst, reset_gpios, { 0 }), \
1554 }; \
1555 static struct adin2111_data name##_data_##inst = { \
1556 .ifaces_left_to_init = ifaces, \
1557 .port = {}, \
1558 .offload_sem = Z_SEM_INITIALIZER(name##_data_##inst.offload_sem, 0, 1), \
1559 .lock = Z_MUTEX_INITIALIZER(name##_data_##inst.lock), \
1560 .buf = name##_buffer_##inst, \
1561 .oa = DT_INST_PROP(inst, spi_oa), \
1562 .oa_prot = DT_INST_PROP(inst, spi_oa_protection), \
1563 .oa_cps = 64, \
1564 .oa_tx_buf = COND_CODE_1(DT_INST_PROP(inst, spi_oa), \
1565 (name##_oa_tx_buf_##inst), (NULL)), \
1566 .oa_rx_buf = COND_CODE_1(DT_INST_PROP(inst, spi_oa), \
1567 (name##_oa_rx_buf_##inst), (NULL)), \
1568 }; \
1569 /* adin */ \
1570 DEVICE_DT_DEFINE(DT_DRV_INST(inst), adin2111_init, NULL, \
1571 &name##_data_##inst, &name##_config_##inst, \
1572 POST_KERNEL, CONFIG_ETH_INIT_PRIORITY, \
1573 NULL);
1574
1575 #define ADIN2111_MAC_INIT(inst) ADIN2111_MAC_INITIALIZE(inst, ADIN2111_MAC, 2, adin2111) \
1576 /* ports */ \
1577 ADIN2111_PORT_DEVICE_INIT_INSTANCE(inst, 0, 1, adin2111) \
1578 ADIN2111_PORT_DEVICE_INIT_INSTANCE(inst, 1, 2, adin2111)
1579
1580 #undef DT_DRV_COMPAT
1581 #define DT_DRV_COMPAT adi_adin2111
1582 DT_INST_FOREACH_STATUS_OKAY(ADIN2111_MAC_INIT)
1583
1584 #define ADIN1110_MAC_INIT(inst) ADIN2111_MAC_INITIALIZE(inst, ADIN1110_MAC, 1, adin1110) \
1585 /* ports */ \
1586 ADIN2111_PORT_DEVICE_INIT_INSTANCE(inst, 0, 1, adin1110)
1587
1588 #undef DT_DRV_COMPAT
1589 #define DT_DRV_COMPAT adi_adin1110
1590 DT_INST_FOREACH_STATUS_OKAY(ADIN1110_MAC_INIT)
1591