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