1 /* ENC424J600 Stand-alone Ethernet Controller with SPI
2 *
3 * Copyright (c) 2016 Intel Corporation
4 * Copyright (c) 2019 PHYTEC Messtechnik GmbH
5 * Copyright (c) 2021 Laird Connectivity
6 *
7 * SPDX-License-Identifier: Apache-2.0
8 */
9
10 #define DT_DRV_COMPAT microchip_enc424j600
11
12 #include <zephyr/kernel.h>
13 #include <zephyr/device.h>
14 #include <string.h>
15 #include <errno.h>
16 #include <zephyr/drivers/gpio.h>
17 #include <zephyr/drivers/spi.h>
18 #include <zephyr/net/net_pkt.h>
19 #include <zephyr/net/net_if.h>
20 #include <zephyr/net/ethernet.h>
21 #include <ethernet/eth_stats.h>
22
23 #include "eth_enc424j600_priv.h"
24
25 LOG_MODULE_REGISTER(ethdrv, CONFIG_ETHERNET_LOG_LEVEL);
26
enc424j600_write_sbc(const struct device * dev,uint8_t cmd)27 static void enc424j600_write_sbc(const struct device *dev, uint8_t cmd)
28 {
29 const struct enc424j600_config *config = dev->config;
30 uint8_t buf[2] = { cmd, 0xFF };
31 const struct spi_buf tx_buf = {
32 .buf = buf,
33 .len = 1,
34 };
35 const struct spi_buf_set tx = {
36 .buffers = &tx_buf,
37 .count = 1
38 };
39
40 spi_write_dt(&config->spi, &tx);
41 }
42
enc424j600_write_sfru(const struct device * dev,uint8_t addr,uint16_t value)43 static void enc424j600_write_sfru(const struct device *dev, uint8_t addr,
44 uint16_t value)
45 {
46 const struct enc424j600_config *config = dev->config;
47 uint8_t buf[4];
48 const struct spi_buf tx_buf = {
49 .buf = buf,
50 .len = sizeof(buf)
51 };
52 const struct spi_buf_set tx = {
53 .buffers = &tx_buf,
54 .count = 1
55 };
56
57 buf[0] = ENC424J600_NBC_WCRU;
58 buf[1] = addr;
59 buf[2] = value;
60 buf[3] = value >> 8;
61
62 spi_write_dt(&config->spi, &tx);
63 }
64
enc424j600_read_sfru(const struct device * dev,uint8_t addr,uint16_t * value)65 static void enc424j600_read_sfru(const struct device *dev, uint8_t addr,
66 uint16_t *value)
67 {
68 const struct enc424j600_config *config = dev->config;
69 uint8_t buf[4];
70 const struct spi_buf tx_buf = {
71 .buf = buf,
72 .len = 2
73 };
74 const struct spi_buf_set tx = {
75 .buffers = &tx_buf,
76 .count = 1
77 };
78 struct spi_buf rx_buf = {
79 .buf = buf,
80 .len = sizeof(buf),
81 };
82 const struct spi_buf_set rx = {
83 .buffers = &rx_buf,
84 .count = 1
85 };
86
87 buf[0] = ENC424J600_NBC_RCRU;
88 buf[1] = addr;
89
90 if (!spi_transceive_dt(&config->spi, &tx, &rx)) {
91 *value = ((uint16_t)buf[3] << 8 | buf[2]);
92 } else {
93 LOG_DBG("Failure while reading register 0x%02x", addr);
94 *value = 0U;
95 }
96 }
97
enc424j600_modify_sfru(const struct device * dev,uint8_t opcode,uint16_t addr,uint16_t value)98 static void enc424j600_modify_sfru(const struct device *dev, uint8_t opcode,
99 uint16_t addr, uint16_t value)
100 {
101 const struct enc424j600_config *config = dev->config;
102 uint8_t buf[4];
103 const struct spi_buf tx_buf = {
104 .buf = buf,
105 .len = sizeof(buf)
106 };
107 const struct spi_buf_set tx = {
108 .buffers = &tx_buf,
109 .count = 1
110 };
111
112 buf[0] = opcode;
113 buf[1] = addr;
114 buf[2] = value;
115 buf[3] = value >> 8;
116
117 spi_write_dt(&config->spi, &tx);
118 }
119
120 #define enc424j600_set_sfru(dev, addr, value) \
121 enc424j600_modify_sfru(dev, ENC424J600_NBC_BFSU, addr, value)
122
123 #define enc424j600_clear_sfru(dev, addr, value) \
124 enc424j600_modify_sfru(dev, ENC424J600_NBC_BFCU, addr, value)
125
126
enc424j600_write_phy(const struct device * dev,uint16_t addr,uint16_t data)127 static void enc424j600_write_phy(const struct device *dev, uint16_t addr,
128 uint16_t data)
129 {
130 uint16_t mistat;
131
132 enc424j600_write_sfru(dev, ENC424J600_SFR2_MIREGADRL, addr);
133 enc424j600_write_sfru(dev, ENC424J600_SFR3_MIWRL, data);
134
135 do {
136 k_busy_wait(ENC424J600_PHY_ACCESS_DELAY);
137 enc424j600_read_sfru(dev, ENC424J600_SFR3_MISTATL, &mistat);
138 } while ((mistat & ENC424J600_MISTAT_BUSY));
139 }
140
enc424j600_read_phy(const struct device * dev,uint16_t addr,uint16_t * data)141 static void enc424j600_read_phy(const struct device *dev, uint16_t addr,
142 uint16_t *data)
143 {
144 uint16_t mistat;
145
146 enc424j600_write_sfru(dev, ENC424J600_SFR2_MIREGADRL, addr);
147 enc424j600_write_sfru(dev, ENC424J600_SFR2_MICMDL,
148 ENC424J600_MICMD_MIIRD);
149
150 do {
151 k_busy_wait(ENC424J600_PHY_ACCESS_DELAY);
152 enc424j600_read_sfru(dev, ENC424J600_SFR3_MISTATL, &mistat);
153 } while ((mistat & ENC424J600_MISTAT_BUSY));
154
155 enc424j600_write_sfru(dev, ENC424J600_SFR2_MICMDL, 0);
156 enc424j600_read_sfru(dev, ENC424J600_SFR3_MIRDL, data);
157 }
158
enc424j600_write_mem(const struct device * dev,uint8_t opcode,uint8_t * data_buffer,uint16_t buf_len)159 static void enc424j600_write_mem(const struct device *dev, uint8_t opcode,
160 uint8_t *data_buffer, uint16_t buf_len)
161 {
162 const struct enc424j600_config *config = dev->config;
163 uint8_t buf[1] = { opcode };
164 const struct spi_buf tx_buf[2] = {
165 {
166 .buf = buf,
167 .len = 1
168 },
169 {
170 .buf = data_buffer,
171 .len = buf_len
172 },
173 };
174 const struct spi_buf_set tx = {
175 .buffers = tx_buf,
176 .count = 2
177 };
178
179 if (spi_write_dt(&config->spi, &tx)) {
180 LOG_ERR("Failed to write SRAM buffer");
181 return;
182 }
183 }
184
enc424j600_read_mem(const struct device * dev,uint8_t opcode,uint8_t * data_buffer,uint16_t buf_len)185 static void enc424j600_read_mem(const struct device *dev, uint8_t opcode,
186 uint8_t *data_buffer, uint16_t buf_len)
187 {
188 const struct enc424j600_config *config = dev->config;
189 uint8_t buf[1] = { opcode };
190 const struct spi_buf tx_buf = {
191 .buf = buf,
192 .len = 1
193 };
194 const struct spi_buf_set tx = {
195 .buffers = &tx_buf,
196 .count = 1
197 };
198 struct spi_buf rx_buf[2] = {
199 {
200 .buf = NULL,
201 .len = 1
202 },
203 {
204 .buf = data_buffer,
205 .len = buf_len
206 },
207 };
208 const struct spi_buf_set rx = {
209 .buffers = rx_buf,
210 .count = 2
211 };
212
213 if (spi_transceive_dt(&config->spi, &tx, &rx)) {
214 LOG_ERR("Failed to read SRAM buffer");
215 return;
216 }
217 }
218
enc424j600_gpio_callback(const struct device * dev,struct gpio_callback * cb,uint32_t pins)219 static void enc424j600_gpio_callback(const struct device *dev,
220 struct gpio_callback *cb,
221 uint32_t pins)
222 {
223 struct enc424j600_runtime *context =
224 CONTAINER_OF(cb, struct enc424j600_runtime, gpio_cb);
225
226 k_sem_give(&context->int_sem);
227 }
228
enc424j600_init_filters(const struct device * dev)229 static void enc424j600_init_filters(const struct device *dev)
230 {
231 uint16_t tmp;
232
233 enc424j600_write_sfru(dev, ENC424J600_SFR1_ERXFCONL,
234 ENC424J600_ERXFCON_CRCEN |
235 ENC424J600_ERXFCON_RUNTEN |
236 ENC424J600_ERXFCON_UCEN |
237 ENC424J600_ERXFCON_MCEN |
238 ENC424J600_ERXFCON_BCEN);
239 if (CONFIG_ETHERNET_LOG_LEVEL == LOG_LEVEL_DBG) {
240 enc424j600_read_sfru(dev, ENC424J600_SFR1_ERXFCONL, &tmp);
241 LOG_DBG("ERXFCON: 0x%04x", tmp);
242 }
243 }
244
enc424j600_init_phy(const struct device * dev)245 static void enc424j600_init_phy(const struct device *dev)
246 {
247 uint16_t tmp;
248
249 enc424j600_write_phy(dev, ENC424J600_PSFR_PHANA,
250 ENC424J600_PHANA_ADPAUS_SYMMETRIC_ONLY |
251 ENC424J600_PHANA_AD100FD |
252 ENC424J600_PHANA_AD100 |
253 ENC424J600_PHANA_AD10FD |
254 ENC424J600_PHANA_AD10 |
255 ENC424J600_PHANA_ADIEEE_DEFAULT);
256 if (CONFIG_ETHERNET_LOG_LEVEL == LOG_LEVEL_DBG) {
257 enc424j600_read_phy(dev, ENC424J600_PSFR_PHANA, &tmp);
258 LOG_DBG("PHANA: 0x%04x", tmp);
259 }
260
261 enc424j600_read_phy(dev, ENC424J600_PSFR_PHCON1, &tmp);
262 tmp |= ENC424J600_PHCON1_RENEG;
263 LOG_DBG("PHCON1: 0x%04x", tmp);
264 enc424j600_write_phy(dev, ENC424J600_PSFR_PHCON1, tmp);
265 }
266
enc424j600_setup_mac(const struct device * dev)267 static void enc424j600_setup_mac(const struct device *dev)
268 {
269 uint16_t tmp;
270 uint16_t macon2;
271
272 if (CONFIG_ETHERNET_LOG_LEVEL == LOG_LEVEL_DBG) {
273 enc424j600_read_phy(dev, ENC424J600_PSFR_PHANLPA, &tmp);
274 LOG_DBG("PHANLPA: 0x%04x", tmp);
275 }
276
277 enc424j600_read_phy(dev, ENC424J600_PSFR_PHSTAT3, &tmp);
278
279 if (tmp & ENC424J600_PHSTAT3_SPDDPX_100) {
280 LOG_INF("100Mbps");
281 } else if (tmp & ENC424J600_PHSTAT3_SPDDPX_10) {
282 LOG_INF("10Mbps");
283 } else {
284 LOG_ERR("Unknown speed configuration");
285 }
286
287 if (tmp & ENC424J600_PHSTAT3_SPDDPX_FD) {
288 LOG_INF("full duplex");
289 enc424j600_read_sfru(dev, ENC424J600_SFR2_MACON2L, &macon2);
290 macon2 |= ENC424J600_MACON2_FULDPX;
291 enc424j600_write_sfru(dev, ENC424J600_SFR2_MACON2L, macon2);
292 enc424j600_write_sfru(dev, ENC424J600_SFR2_MABBIPGL,
293 ENC424J600_MABBIPG_DEFAULT);
294
295 } else {
296 LOG_INF("half duplex");
297 }
298
299 if (CONFIG_ETHERNET_LOG_LEVEL == LOG_LEVEL_DBG) {
300 enc424j600_read_sfru(dev, ENC424J600_SFR2_MACON2L, &tmp);
301 LOG_DBG("MACON2: 0x%04x", tmp);
302
303 enc424j600_read_sfru(dev, ENC424J600_SFR2_MAMXFLL, &tmp);
304 LOG_DBG("MAMXFL (maximum frame length): %u", tmp);
305 }
306 }
307
enc424j600_tx(const struct device * dev,struct net_pkt * pkt)308 static int enc424j600_tx(const struct device *dev, struct net_pkt *pkt)
309 {
310 struct enc424j600_runtime *context = dev->data;
311 uint16_t len = net_pkt_get_len(pkt);
312 struct net_buf *frag;
313 uint16_t tmp;
314
315 LOG_DBG("pkt %p (len %u)", pkt, len);
316
317 k_sem_take(&context->tx_rx_sem, K_FOREVER);
318
319 enc424j600_write_sfru(dev, ENC424J600_SFR4_EGPWRPTL,
320 ENC424J600_TXSTART);
321
322 for (frag = pkt->frags; frag; frag = frag->frags) {
323 enc424j600_write_mem(dev, ENC424J600_NBC_WGPDATA, frag->data,
324 frag->len);
325 }
326
327 enc424j600_write_sfru(dev, ENC424J600_SFR0_ETXSTL,
328 ENC424J600_TXSTART);
329 enc424j600_write_sfru(dev, ENC424J600_SFR0_ETXLENL, len);
330 enc424j600_write_sbc(dev, ENC424J600_1BC_SETTXRTS);
331
332 do {
333 k_sleep(K_MSEC(1));
334 enc424j600_read_sfru(dev, ENC424J600_SFRX_ECON1L, &tmp);
335 } while (tmp & ENC424J600_ECON1_TXRTS);
336
337 if (CONFIG_ETHERNET_LOG_LEVEL == LOG_LEVEL_DBG) {
338 enc424j600_read_sfru(dev, ENC424J600_SFR0_ETXSTATL, &tmp);
339 LOG_DBG("ETXSTAT: 0x%04x", tmp);
340 }
341
342 k_sem_give(&context->tx_rx_sem);
343
344 return 0;
345 }
346
enc424j600_rx(const struct device * dev)347 static int enc424j600_rx(const struct device *dev)
348 {
349 struct enc424j600_runtime *context = dev->data;
350 const struct enc424j600_config *config = dev->config;
351 uint8_t info[ENC424J600_RSV_SIZE + ENC424J600_PTR_NXP_PKT_SIZE];
352 struct net_buf *pkt_buf = NULL;
353 struct net_pkt *pkt;
354 uint16_t frm_len = 0U;
355 uint32_t status;
356 uint16_t tmp;
357
358 k_sem_take(&context->tx_rx_sem, K_FOREVER);
359
360 enc424j600_write_sfru(dev, ENC424J600_SFR4_ERXRDPTL,
361 context->next_pkt_ptr);
362 if (CONFIG_ETHERNET_LOG_LEVEL == LOG_LEVEL_DBG) {
363 enc424j600_read_sfru(dev, ENC424J600_SFR4_ERXRDPTL, &tmp);
364 LOG_DBG("set ERXRDPT to 0x%04x", tmp);
365 }
366
367 enc424j600_read_mem(dev, ENC424J600_NBC_RRXDATA, info,
368 sizeof(info));
369
370 if (CONFIG_ETHERNET_LOG_LEVEL == LOG_LEVEL_DBG) {
371 enc424j600_read_sfru(dev, ENC424J600_SFR4_ERXRDPTL, &tmp);
372 LOG_DBG("ERXRDPT is 0x%04x now", tmp);
373 }
374
375 context->next_pkt_ptr = sys_get_le16(&info[0]);
376 frm_len = sys_get_le16(&info[2]);
377 status = sys_get_le32(&info[4]);
378 LOG_DBG("npp 0x%04x, length %u, status 0x%08x",
379 context->next_pkt_ptr, frm_len, status);
380 /* frame length without FCS */
381 frm_len -= 4;
382 if (frm_len > NET_ETH_MAX_FRAME_SIZE) {
383 LOG_ERR("Maximum frame length exceeded");
384 eth_stats_update_errors_rx(context->iface);
385 goto done;
386 }
387
388 /* Get the frame from the buffer */
389 pkt = net_pkt_rx_alloc_with_buffer(context->iface, frm_len,
390 AF_UNSPEC, 0,
391 K_MSEC(config->timeout));
392 if (!pkt) {
393 LOG_ERR("Could not allocate rx buffer");
394 eth_stats_update_errors_rx(context->iface);
395 goto done;
396 }
397
398 pkt_buf = pkt->buffer;
399
400 do {
401 size_t frag_len;
402 uint8_t *data_ptr;
403 size_t spi_frame_len;
404
405 data_ptr = pkt_buf->data;
406
407 /* Review the space available for the new frag */
408 frag_len = net_buf_tailroom(pkt_buf);
409
410 if (frm_len > frag_len) {
411 spi_frame_len = frag_len;
412 } else {
413 spi_frame_len = frm_len;
414 }
415
416 enc424j600_read_mem(dev, ENC424J600_NBC_RRXDATA, data_ptr,
417 spi_frame_len);
418
419 net_buf_add(pkt_buf, spi_frame_len);
420
421 /* One fragment has been written via SPI */
422 frm_len -= spi_frame_len;
423 pkt_buf = pkt_buf->frags;
424 } while (frm_len > 0);
425
426 if (net_recv_data(context->iface, pkt) < 0) {
427 net_pkt_unref(pkt);
428 }
429
430 done:
431 if (context->next_pkt_ptr == ENC424J600_RXSTART) {
432 tmp = ENC424J600_RXEND - 1;
433 LOG_DBG("wrap back");
434 } else {
435 tmp = context->next_pkt_ptr - 2;
436 }
437
438 enc424j600_write_sfru(dev, ENC424J600_SFR0_ERXTAILL, tmp);
439 enc424j600_write_sbc(dev, ENC424J600_1BC_SETPKTDEC);
440 k_sem_give(&context->tx_rx_sem);
441
442 return 0;
443 }
444
enc424j600_rx_thread(void * p1,void * p2,void * p3)445 static void enc424j600_rx_thread(void *p1, void *p2, void *p3)
446 {
447 ARG_UNUSED(p2);
448 ARG_UNUSED(p3);
449
450 struct enc424j600_runtime *context = p1;
451 uint16_t eir;
452 uint16_t estat;
453 uint8_t counter;
454
455 while (true) {
456 k_sem_take(&context->int_sem, K_FOREVER);
457
458 enc424j600_write_sbc(context->dev, ENC424J600_1BC_CLREIE);
459 enc424j600_read_sfru(context->dev, ENC424J600_SFRX_EIRL, &eir);
460 enc424j600_read_sfru(context->dev,
461 ENC424J600_SFRX_ESTATL, &estat);
462 LOG_DBG("ESTAT: 0x%04x", estat);
463
464 if (eir & ENC424J600_EIR_PKTIF) {
465 counter = (uint8_t)estat;
466 while (counter) {
467 enc424j600_rx(context->dev);
468 enc424j600_read_sfru(context->dev,
469 ENC424J600_SFRX_ESTATL,
470 &estat);
471 counter = (uint8_t)estat;
472 LOG_DBG("ESTAT: 0x%04x", estat);
473 }
474 } else if (eir & ENC424J600_EIR_LINKIF) {
475 enc424j600_clear_sfru(context->dev,
476 ENC424J600_SFRX_EIRL,
477 ENC424J600_EIR_LINKIF);
478 if (estat & ENC424J600_ESTAT_PHYLNK) {
479 LOG_INF("Link up");
480 enc424j600_setup_mac(context->dev);
481 net_eth_carrier_on(context->iface);
482 } else {
483 LOG_INF("Link down");
484
485 if (context->iface_initialized) {
486 net_eth_carrier_off(context->iface);
487 }
488 }
489 } else {
490 LOG_ERR("Unknown Interrupt, EIR: 0x%04x", eir);
491 /*
492 * Terminate interrupt handling thread
493 * only when debugging.
494 */
495 if (CONFIG_ETHERNET_LOG_LEVEL == LOG_LEVEL_DBG) {
496 k_oops();
497 }
498 }
499
500 enc424j600_write_sbc(context->dev, ENC424J600_1BC_SETEIE);
501 }
502 }
503
enc424j600_get_config(const struct device * dev,enum ethernet_config_type type,struct ethernet_config * config)504 static int enc424j600_get_config(const struct device *dev,
505 enum ethernet_config_type type,
506 struct ethernet_config *config)
507 {
508 uint16_t tmp;
509 int rc = 0;
510 struct enc424j600_runtime *context = dev->data;
511
512 if (type != ETHERNET_CONFIG_TYPE_LINK &&
513 type != ETHERNET_CONFIG_TYPE_DUPLEX) {
514 /* Unsupported configuration query */
515 return -ENOTSUP;
516 }
517
518 k_sem_take(&context->tx_rx_sem, K_FOREVER);
519
520 if (type == ETHERNET_CONFIG_TYPE_LINK) {
521 /* Query active link speed */
522 enc424j600_read_phy(dev, ENC424J600_PSFR_PHSTAT3, &tmp);
523
524 if (tmp & ENC424J600_PHSTAT3_SPDDPX_100) {
525 /* 100Mbps link speed */
526 config->l.link_100bt = true;
527 } else if (tmp & ENC424J600_PHSTAT3_SPDDPX_10) {
528 /* 10Mbps link speed */
529 config->l.link_10bt = true;
530 } else {
531 /* Unknown link speed */
532 rc = -EINVAL;
533 }
534 } else if (type == ETHERNET_CONFIG_TYPE_DUPLEX) {
535 /* Query if half or full duplex */
536 enc424j600_read_phy(dev, ENC424J600_PSFR_PHSTAT3, &tmp);
537
538 /* Assume operating in half duplex mode */
539 config->full_duplex = false;
540
541 if (tmp & ENC424J600_PHSTAT3_SPDDPX_FD) {
542 /* Operating in full duplex mode */
543 config->full_duplex = true;
544 }
545 }
546
547 k_sem_give(&context->tx_rx_sem);
548
549 return rc;
550 }
551
enc424j600_get_capabilities(const struct device * dev)552 static enum ethernet_hw_caps enc424j600_get_capabilities(const struct device *dev)
553 {
554 ARG_UNUSED(dev);
555
556 return ETHERNET_LINK_10BASE_T | ETHERNET_LINK_100BASE_T;
557 }
558
enc424j600_iface_init(struct net_if * iface)559 static void enc424j600_iface_init(struct net_if *iface)
560 {
561 const struct device *dev = net_if_get_device(iface);
562 struct enc424j600_runtime *context = dev->data;
563
564 net_if_set_link_addr(iface, context->mac_address,
565 sizeof(context->mac_address),
566 NET_LINK_ETHERNET);
567 context->iface = iface;
568 ethernet_init(iface);
569
570 net_if_carrier_off(iface);
571 context->iface_initialized = true;
572 }
573
enc424j600_start_device(const struct device * dev)574 static int enc424j600_start_device(const struct device *dev)
575 {
576 struct enc424j600_runtime *context = dev->data;
577 uint16_t tmp;
578
579 if (!context->suspended) {
580 LOG_INF("Not suspended");
581 return 0;
582 }
583
584 k_sem_take(&context->tx_rx_sem, K_FOREVER);
585
586 enc424j600_set_sfru(dev, ENC424J600_SFR3_ECON2L,
587 ENC424J600_ECON2_ETHEN |
588 ENC424J600_ECON2_STRCH);
589
590 enc424j600_read_phy(dev, ENC424J600_PSFR_PHCON1, &tmp);
591 tmp &= ~ENC424J600_PHCON1_PSLEEP;
592 enc424j600_write_phy(dev, ENC424J600_PSFR_PHCON1, tmp);
593
594 enc424j600_set_sfru(dev, ENC424J600_SFRX_ECON1L,
595 ENC424J600_ECON1_RXEN);
596
597 context->suspended = false;
598 k_sem_give(&context->tx_rx_sem);
599 LOG_INF("started");
600
601 return 0;
602 }
603
enc424j600_stop_device(const struct device * dev)604 static int enc424j600_stop_device(const struct device *dev)
605 {
606 struct enc424j600_runtime *context = dev->data;
607 uint16_t tmp;
608
609 if (context->suspended) {
610 LOG_WRN("Already suspended");
611 return 0;
612 }
613
614 k_sem_take(&context->tx_rx_sem, K_FOREVER);
615
616 enc424j600_clear_sfru(dev, ENC424J600_SFRX_ECON1L,
617 ENC424J600_ECON1_RXEN);
618
619 do {
620 k_sleep(K_MSEC(10U));
621 enc424j600_read_sfru(dev, ENC424J600_SFRX_ESTATL, &tmp);
622 } while (tmp & ENC424J600_ESTAT_RXBUSY);
623
624 do {
625 k_sleep(K_MSEC(10U));
626 enc424j600_read_sfru(dev, ENC424J600_SFRX_ECON1L, &tmp);
627 } while (tmp & ENC424J600_ECON1_TXRTS);
628
629 enc424j600_read_phy(dev, ENC424J600_PSFR_PHCON1, &tmp);
630 tmp |= ENC424J600_PHCON1_PSLEEP;
631 enc424j600_write_phy(dev, ENC424J600_PSFR_PHCON1, tmp);
632
633 enc424j600_clear_sfru(dev, ENC424J600_SFR3_ECON2L,
634 ENC424J600_ECON2_ETHEN |
635 ENC424J600_ECON2_STRCH);
636
637 context->suspended = true;
638 k_sem_give(&context->tx_rx_sem);
639 LOG_INF("stopped");
640
641 return 0;
642 }
643
644 static const struct ethernet_api api_funcs = {
645 .iface_api.init = enc424j600_iface_init,
646 .get_config = enc424j600_get_config,
647 .get_capabilities = enc424j600_get_capabilities,
648 .send = enc424j600_tx,
649 .start = enc424j600_start_device,
650 .stop = enc424j600_stop_device,
651 };
652
enc424j600_init(const struct device * dev)653 static int enc424j600_init(const struct device *dev)
654 {
655 const struct enc424j600_config *config = dev->config;
656 struct enc424j600_runtime *context = dev->data;
657 uint8_t retries = ENC424J600_DEFAULT_NUMOF_RETRIES;
658 uint16_t tmp;
659
660 context->dev = dev;
661
662 /* SPI config */
663 if (!spi_is_ready_dt(&config->spi)) {
664 LOG_ERR("SPI master port %s not ready", config->spi.bus->name);
665 return -EINVAL;
666 }
667
668 /* Initialize GPIO */
669 if (!gpio_is_ready_dt(&config->interrupt)) {
670 LOG_ERR("GPIO port %s not ready", config->interrupt.port->name);
671 return -EINVAL;
672 }
673
674 if (gpio_pin_configure_dt(&config->interrupt, GPIO_INPUT)) {
675 LOG_ERR("Unable to configure GPIO pin %u",
676 config->interrupt.pin);
677 return -EINVAL;
678 }
679
680 gpio_init_callback(&(context->gpio_cb), enc424j600_gpio_callback,
681 BIT(config->interrupt.pin));
682
683 if (gpio_add_callback(config->interrupt.port, &(context->gpio_cb))) {
684 return -EINVAL;
685 }
686
687 gpio_pin_interrupt_configure_dt(&config->interrupt,
688 GPIO_INT_EDGE_TO_ACTIVE);
689
690 /* Check SPI connection */
691 do {
692 k_busy_wait(USEC_PER_MSEC * 1U);
693 enc424j600_write_sfru(dev, ENC424J600_SFRX_EUDASTL, 0x4AFE);
694 enc424j600_read_sfru(dev, ENC424J600_SFRX_EUDASTL, &tmp);
695 retries--;
696 } while (tmp != 0x4AFE && retries);
697
698 if (tmp != 0x4AFE) {
699 LOG_ERR("Timeout, failed to establish SPI connection");
700 return -EIO;
701 }
702
703 retries = ENC424J600_DEFAULT_NUMOF_RETRIES;
704 do {
705 k_busy_wait(USEC_PER_MSEC * 1U);
706 enc424j600_read_sfru(dev, ENC424J600_SFRX_ESTATL, &tmp);
707 retries--;
708 } while (!(tmp & ENC424J600_ESTAT_CLKRDY) && retries);
709
710 if (!(tmp & ENC424J600_ESTAT_CLKRDY)) {
711 LOG_ERR("CLKRDY not set");
712 return -EIO;
713 }
714
715 enc424j600_write_sbc(dev, ENC424J600_1BC_SETETHRST);
716
717 k_busy_wait(ENC424J600_PHY_READY_DELAY);
718 enc424j600_read_sfru(dev, ENC424J600_SFRX_EUDASTL, &tmp);
719 if (tmp) {
720 LOG_ERR("Failed to initialize ENC424J600");
721 return -EIO;
722 }
723
724 /* Disable INTIE and setup interrupt logic */
725 enc424j600_write_sfru(dev, ENC424J600_SFR3_EIEL,
726 ENC424J600_EIE_PKTIE | ENC424J600_EIE_LINKIE);
727
728 if (CONFIG_ETHERNET_LOG_LEVEL == LOG_LEVEL_DBG) {
729 enc424j600_read_sfru(dev, ENC424J600_SFR3_EIEL, &tmp);
730 LOG_DBG("EIE: 0x%04x", tmp);
731 }
732
733 /* Configure TX and RX buffer */
734 enc424j600_write_sfru(dev, ENC424J600_SFR0_ETXSTL,
735 ENC424J600_TXSTART);
736 enc424j600_write_sfru(dev, ENC424J600_SFR0_ERXSTL,
737 ENC424J600_RXSTART);
738 enc424j600_write_sfru(dev, ENC424J600_SFR0_ERXTAILL,
739 (ENC424J600_RXEND - 1));
740 context->next_pkt_ptr = ENC424J600_RXSTART;
741
742 /* Disable user-defined buffer */
743 enc424j600_write_sfru(dev, ENC424J600_SFRX_EUDASTL,
744 (ENC424J600_RXEND - 1));
745 enc424j600_write_sfru(dev, ENC424J600_SFRX_EUDANDL,
746 (ENC424J600_RXEND - 1));
747
748 /* read MAC address byte 2 and 1 */
749 enc424j600_read_sfru(dev, ENC424J600_SFR3_MAADR1L, &tmp);
750 context->mac_address[0] = tmp;
751 context->mac_address[1] = tmp >> 8;
752 /* read MAC address byte 4 and 3 */
753 enc424j600_read_sfru(dev, ENC424J600_SFR3_MAADR2L, &tmp);
754 context->mac_address[2] = tmp;
755 context->mac_address[3] = tmp >> 8;
756 /* read MAC address byte 6 and 5 */
757 enc424j600_read_sfru(dev, ENC424J600_SFR3_MAADR3L, &tmp);
758 context->mac_address[4] = tmp;
759 context->mac_address[5] = tmp >> 8;
760
761 enc424j600_init_filters(dev);
762 enc424j600_init_phy(dev);
763
764 /* Enable Reception */
765 enc424j600_set_sfru(dev, ENC424J600_SFRX_ECON1L, ENC424J600_ECON1_RXEN);
766 if (CONFIG_ETHERNET_LOG_LEVEL == LOG_LEVEL_DBG) {
767 enc424j600_read_sfru(dev, ENC424J600_SFRX_ECON1L, &tmp);
768 LOG_DBG("ECON1: 0x%04x", tmp);
769 }
770
771 /* Start interruption-poll thread */
772 k_thread_create(&context->thread, context->thread_stack,
773 CONFIG_ETH_ENC424J600_RX_THREAD_STACK_SIZE,
774 enc424j600_rx_thread,
775 context, NULL, NULL,
776 K_PRIO_COOP(CONFIG_ETH_ENC424J600_RX_THREAD_PRIO),
777 0, K_NO_WAIT);
778
779 enc424j600_write_sbc(dev, ENC424J600_1BC_SETEIE);
780
781 context->suspended = false;
782 LOG_INF("ENC424J600 Initialized");
783
784 return 0;
785 }
786
787 static struct enc424j600_runtime enc424j600_0_runtime = {
788 .tx_rx_sem = Z_SEM_INITIALIZER(enc424j600_0_runtime.tx_rx_sem,
789 1, UINT_MAX),
790 .int_sem = Z_SEM_INITIALIZER(enc424j600_0_runtime.int_sem,
791 0, UINT_MAX),
792 };
793
794 static const struct enc424j600_config enc424j600_0_config = {
795 .spi = SPI_DT_SPEC_INST_GET(0, SPI_WORD_SET(8), 0),
796 .interrupt = GPIO_DT_SPEC_INST_GET(0, int_gpios),
797 .timeout = CONFIG_ETH_ENC424J600_TIMEOUT,
798 };
799
800 ETH_NET_DEVICE_DT_INST_DEFINE(0,
801 enc424j600_init, NULL,
802 &enc424j600_0_runtime, &enc424j600_0_config,
803 CONFIG_ETH_INIT_PRIORITY, &api_funcs, NET_ETH_MTU);
804