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_set_config(const struct device * dev,enum ethernet_config_type type,const struct ethernet_config * config)559 static int enc424j600_set_config(const struct device *dev,
560 enum ethernet_config_type type,
561 const struct ethernet_config *config)
562 {
563 struct enc424j600_runtime *ctx = dev->data;
564 uint16_t tmp;
565
566 switch (type) {
567 case ETHERNET_CONFIG_TYPE_MAC_ADDRESS:
568 ctx->mac_address[0] = config->mac_address.addr[0];
569 ctx->mac_address[1] = config->mac_address.addr[1];
570 ctx->mac_address[2] = config->mac_address.addr[2];
571 ctx->mac_address[3] = config->mac_address.addr[3];
572 ctx->mac_address[4] = config->mac_address.addr[4];
573 ctx->mac_address[5] = config->mac_address.addr[5];
574
575 /* write MAC address byte 2 and 1 */
576 tmp = config->mac_address.addr[0] | config->mac_address.addr[1] << 8;
577 enc424j600_write_sfru(dev, ENC424J600_SFR3_MAADR1L, tmp);
578
579 /* write MAC address byte 4 and 3 */
580 tmp = config->mac_address.addr[2] | config->mac_address.addr[3] << 8;
581 enc424j600_write_sfru(dev, ENC424J600_SFR3_MAADR2L, tmp);
582
583 /* write MAC address byte 6 and 5 */
584 tmp = config->mac_address.addr[4] | config->mac_address.addr[5] << 8;
585 enc424j600_write_sfru(dev, ENC424J600_SFR3_MAADR3L, tmp);
586
587 return 0;
588 default:
589 return -ENOTSUP;
590 }
591 }
592
enc424j600_iface_init(struct net_if * iface)593 static void enc424j600_iface_init(struct net_if *iface)
594 {
595 const struct device *dev = net_if_get_device(iface);
596 struct enc424j600_runtime *context = dev->data;
597
598 net_if_set_link_addr(iface, context->mac_address,
599 sizeof(context->mac_address),
600 NET_LINK_ETHERNET);
601 context->iface = iface;
602 ethernet_init(iface);
603
604 net_if_carrier_off(iface);
605 context->iface_initialized = true;
606 }
607
enc424j600_start_device(const struct device * dev)608 static int enc424j600_start_device(const struct device *dev)
609 {
610 struct enc424j600_runtime *context = dev->data;
611 uint16_t tmp;
612
613 if (!context->suspended) {
614 LOG_INF("Not suspended");
615 return 0;
616 }
617
618 k_sem_take(&context->tx_rx_sem, K_FOREVER);
619
620 enc424j600_set_sfru(dev, ENC424J600_SFR3_ECON2L,
621 ENC424J600_ECON2_ETHEN |
622 ENC424J600_ECON2_STRCH);
623
624 enc424j600_read_phy(dev, ENC424J600_PSFR_PHCON1, &tmp);
625 tmp &= ~ENC424J600_PHCON1_PSLEEP;
626 enc424j600_write_phy(dev, ENC424J600_PSFR_PHCON1, tmp);
627
628 enc424j600_set_sfru(dev, ENC424J600_SFRX_ECON1L,
629 ENC424J600_ECON1_RXEN);
630
631 context->suspended = false;
632 k_sem_give(&context->tx_rx_sem);
633 LOG_INF("started");
634
635 return 0;
636 }
637
enc424j600_stop_device(const struct device * dev)638 static int enc424j600_stop_device(const struct device *dev)
639 {
640 struct enc424j600_runtime *context = dev->data;
641 uint16_t tmp;
642
643 if (context->suspended) {
644 LOG_WRN("Already suspended");
645 return 0;
646 }
647
648 k_sem_take(&context->tx_rx_sem, K_FOREVER);
649
650 enc424j600_clear_sfru(dev, ENC424J600_SFRX_ECON1L,
651 ENC424J600_ECON1_RXEN);
652
653 do {
654 k_sleep(K_MSEC(10U));
655 enc424j600_read_sfru(dev, ENC424J600_SFRX_ESTATL, &tmp);
656 } while (tmp & ENC424J600_ESTAT_RXBUSY);
657
658 do {
659 k_sleep(K_MSEC(10U));
660 enc424j600_read_sfru(dev, ENC424J600_SFRX_ECON1L, &tmp);
661 } while (tmp & ENC424J600_ECON1_TXRTS);
662
663 enc424j600_read_phy(dev, ENC424J600_PSFR_PHCON1, &tmp);
664 tmp |= ENC424J600_PHCON1_PSLEEP;
665 enc424j600_write_phy(dev, ENC424J600_PSFR_PHCON1, tmp);
666
667 enc424j600_clear_sfru(dev, ENC424J600_SFR3_ECON2L,
668 ENC424J600_ECON2_ETHEN |
669 ENC424J600_ECON2_STRCH);
670
671 context->suspended = true;
672 k_sem_give(&context->tx_rx_sem);
673 LOG_INF("stopped");
674
675 return 0;
676 }
677
678 static const struct ethernet_api api_funcs = {
679 .iface_api.init = enc424j600_iface_init,
680 .get_config = enc424j600_get_config,
681 .set_config = enc424j600_set_config,
682 .get_capabilities = enc424j600_get_capabilities,
683 .send = enc424j600_tx,
684 .start = enc424j600_start_device,
685 .stop = enc424j600_stop_device,
686 };
687
enc424j600_init(const struct device * dev)688 static int enc424j600_init(const struct device *dev)
689 {
690 const struct enc424j600_config *config = dev->config;
691 struct enc424j600_runtime *context = dev->data;
692 uint8_t retries = ENC424J600_DEFAULT_NUMOF_RETRIES;
693 uint16_t tmp;
694
695 context->dev = dev;
696
697 /* SPI config */
698 if (!spi_is_ready_dt(&config->spi)) {
699 LOG_ERR("SPI master port %s not ready", config->spi.bus->name);
700 return -EINVAL;
701 }
702
703 /* Initialize GPIO */
704 if (!gpio_is_ready_dt(&config->interrupt)) {
705 LOG_ERR("GPIO port %s not ready", config->interrupt.port->name);
706 return -EINVAL;
707 }
708
709 if (gpio_pin_configure_dt(&config->interrupt, GPIO_INPUT)) {
710 LOG_ERR("Unable to configure GPIO pin %u",
711 config->interrupt.pin);
712 return -EINVAL;
713 }
714
715 gpio_init_callback(&(context->gpio_cb), enc424j600_gpio_callback,
716 BIT(config->interrupt.pin));
717
718 if (gpio_add_callback(config->interrupt.port, &(context->gpio_cb))) {
719 return -EINVAL;
720 }
721
722 gpio_pin_interrupt_configure_dt(&config->interrupt,
723 GPIO_INT_EDGE_TO_ACTIVE);
724
725 /* Check SPI connection */
726 do {
727 k_busy_wait(USEC_PER_MSEC * 1U);
728 enc424j600_write_sfru(dev, ENC424J600_SFRX_EUDASTL, 0x4AFE);
729 enc424j600_read_sfru(dev, ENC424J600_SFRX_EUDASTL, &tmp);
730 retries--;
731 } while (tmp != 0x4AFE && retries);
732
733 if (tmp != 0x4AFE) {
734 LOG_ERR("Timeout, failed to establish SPI connection");
735 return -EIO;
736 }
737
738 retries = ENC424J600_DEFAULT_NUMOF_RETRIES;
739 do {
740 k_busy_wait(USEC_PER_MSEC * 1U);
741 enc424j600_read_sfru(dev, ENC424J600_SFRX_ESTATL, &tmp);
742 retries--;
743 } while (!(tmp & ENC424J600_ESTAT_CLKRDY) && retries);
744
745 if (!(tmp & ENC424J600_ESTAT_CLKRDY)) {
746 LOG_ERR("CLKRDY not set");
747 return -EIO;
748 }
749
750 enc424j600_write_sbc(dev, ENC424J600_1BC_SETETHRST);
751
752 k_busy_wait(ENC424J600_PHY_READY_DELAY);
753 enc424j600_read_sfru(dev, ENC424J600_SFRX_EUDASTL, &tmp);
754 if (tmp) {
755 LOG_ERR("Failed to initialize ENC424J600");
756 return -EIO;
757 }
758
759 /* Disable INTIE and setup interrupt logic */
760 enc424j600_write_sfru(dev, ENC424J600_SFR3_EIEL,
761 ENC424J600_EIE_PKTIE | ENC424J600_EIE_LINKIE);
762
763 if (CONFIG_ETHERNET_LOG_LEVEL == LOG_LEVEL_DBG) {
764 enc424j600_read_sfru(dev, ENC424J600_SFR3_EIEL, &tmp);
765 LOG_DBG("EIE: 0x%04x", tmp);
766 }
767
768 /* Configure TX and RX buffer */
769 enc424j600_write_sfru(dev, ENC424J600_SFR0_ETXSTL,
770 ENC424J600_TXSTART);
771 enc424j600_write_sfru(dev, ENC424J600_SFR0_ERXSTL,
772 ENC424J600_RXSTART);
773 enc424j600_write_sfru(dev, ENC424J600_SFR0_ERXTAILL,
774 (ENC424J600_RXEND - 1));
775 context->next_pkt_ptr = ENC424J600_RXSTART;
776
777 /* Disable user-defined buffer */
778 enc424j600_write_sfru(dev, ENC424J600_SFRX_EUDASTL,
779 (ENC424J600_RXEND - 1));
780 enc424j600_write_sfru(dev, ENC424J600_SFRX_EUDANDL,
781 (ENC424J600_RXEND - 1));
782
783 /* read MAC address byte 2 and 1 */
784 enc424j600_read_sfru(dev, ENC424J600_SFR3_MAADR1L, &tmp);
785 context->mac_address[0] = tmp;
786 context->mac_address[1] = tmp >> 8;
787 /* read MAC address byte 4 and 3 */
788 enc424j600_read_sfru(dev, ENC424J600_SFR3_MAADR2L, &tmp);
789 context->mac_address[2] = tmp;
790 context->mac_address[3] = tmp >> 8;
791 /* read MAC address byte 6 and 5 */
792 enc424j600_read_sfru(dev, ENC424J600_SFR3_MAADR3L, &tmp);
793 context->mac_address[4] = tmp;
794 context->mac_address[5] = tmp >> 8;
795
796 enc424j600_init_filters(dev);
797 enc424j600_init_phy(dev);
798
799 /* Enable Reception */
800 enc424j600_set_sfru(dev, ENC424J600_SFRX_ECON1L, ENC424J600_ECON1_RXEN);
801 if (CONFIG_ETHERNET_LOG_LEVEL == LOG_LEVEL_DBG) {
802 enc424j600_read_sfru(dev, ENC424J600_SFRX_ECON1L, &tmp);
803 LOG_DBG("ECON1: 0x%04x", tmp);
804 }
805
806 /* Start interruption-poll thread */
807 k_thread_create(&context->thread, context->thread_stack,
808 CONFIG_ETH_ENC424J600_RX_THREAD_STACK_SIZE,
809 enc424j600_rx_thread,
810 context, NULL, NULL,
811 K_PRIO_COOP(CONFIG_ETH_ENC424J600_RX_THREAD_PRIO),
812 0, K_NO_WAIT);
813
814 enc424j600_write_sbc(dev, ENC424J600_1BC_SETEIE);
815
816 context->suspended = false;
817 LOG_INF("ENC424J600 Initialized");
818
819 return 0;
820 }
821
822 static struct enc424j600_runtime enc424j600_0_runtime = {
823 .tx_rx_sem = Z_SEM_INITIALIZER(enc424j600_0_runtime.tx_rx_sem,
824 1, UINT_MAX),
825 .int_sem = Z_SEM_INITIALIZER(enc424j600_0_runtime.int_sem,
826 0, UINT_MAX),
827 };
828
829 static const struct enc424j600_config enc424j600_0_config = {
830 .spi = SPI_DT_SPEC_INST_GET(0, SPI_WORD_SET(8), 0),
831 .interrupt = GPIO_DT_SPEC_INST_GET(0, int_gpios),
832 .timeout = CONFIG_ETH_ENC424J600_TIMEOUT,
833 };
834
835 ETH_NET_DEVICE_DT_INST_DEFINE(0,
836 enc424j600_init, NULL,
837 &enc424j600_0_runtime, &enc424j600_0_config,
838 CONFIG_ETH_INIT_PRIORITY, &api_funcs, NET_ETH_MTU);
839