1 /*
2 * Copyright (c) 2025 sensry.io
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6
7 #define DT_DRV_COMPAT sensry_sy1xx_mac
8
9 #include <zephyr/logging/log.h>
10 LOG_MODULE_REGISTER(sy1xx_mac, CONFIG_ETHERNET_LOG_LEVEL);
11
12 #include <sys/types.h>
13 #include <zephyr/kernel.h>
14 #include <zephyr/net/ethernet.h>
15 #include <zephyr/sys/barrier.h>
16 #include <zephyr/drivers/pinctrl.h>
17 #include <zephyr/net/phy.h>
18 #include <udma.h>
19 #include "eth.h"
20
21 /* MAC register offsets */
22 #define SY1XX_MAC_VERSION_REG 0x0000
23 #define SY1XX_MAC_ADDRESS_LOW_REG 0x0004
24 #define SY1XX_MAC_ADDRESS_HIGH_REG 0x0008
25 #define SY1XX_MAC_CTRL_REG 0x000c
26
27 /* MAC control register bit offsets */
28 #define SY1XX_MAC_CTRL_RESET_OFFS (0)
29 #define SY1XX_MAC_CTRL_RX_EN_OFFS (1)
30 #define SY1XX_MAC_CTRL_TX_EN_OFFS (2)
31 #define SY1XX_MAC_CTRL_GMII_OFFS (3)
32 #define SY1XX_MAC_CTRL_CLK_DIV_OFFS (8)
33 #define SY1XX_MAC_CTRL_CLK_SEL_OFFS (10)
34
35 /* MAC clock sources */
36 #define SY1XX_MAC_CTRL_CLK_SEL_REF_CLK 0
37 #define SY1XX_MAC_CTRL_CLK_SEL_MII_CLK 1
38
39 /* Clock divider options */
40 #define SY1XX_MAC_CTRL_CLK_DIV_1 0x0
41 #define SY1XX_MAC_CTRL_CLK_DIV_5 0x1
42 #define SY1XX_MAC_CTRL_CLK_DIV_10 0x2
43 #define SY1XX_MAC_CTRL_CLK_DIV_50 0x3
44
45 /* Clock divider mask */
46 #define SY1XX_MAC_CTRL_CLK_DIV_MASK (0x3)
47
48 #define MAX_MAC_PACKET_LEN 1600
49 #define MAX_TX_RETRIES 5
50 #define RECEIVE_GRACE_TIME_MSEC 1
51
52 #define SY1XX_ETH_STACK_SIZE 4096
53 #define SY1XX_ETH_THREAD_PRIORITY K_PRIO_PREEMPT(0)
54
55 struct sy1xx_mac_dev_config {
56 /* address of controller configuration registers */
57 uint32_t ctrl_addr;
58 /* address of udma for data transfers */
59 uint32_t base_addr;
60 /* optional - enable promiscuous mode */
61 bool promiscuous_mode;
62 /* optional - device tree mac */
63 bool use_local_mac_address;
64 uint8_t local_mac_address[6];
65 /* optional - random mac */
66 bool use_zephyr_random_mac;
67
68 /* phy config */
69 const struct device *phy_dev;
70
71 /* pinctrl for rgmii pins */
72 const struct pinctrl_dev_config *pcfg;
73 };
74
75 struct sy1xx_mac_dma_buffers {
76 uint8_t tx[MAX_MAC_PACKET_LEN];
77 uint8_t rx[MAX_MAC_PACKET_LEN];
78 };
79
80 struct sy1xx_mac_dev_data {
81 struct k_mutex mutex;
82
83 /* current state of link and mac address */
84 bool link_is_up;
85 enum phy_link_speed link_speed;
86
87 uint8_t mac_addr[6];
88
89 /* intermediate, linear buffers that can hold a received or transmit msg */
90 struct {
91 uint8_t tx[MAX_MAC_PACKET_LEN];
92 uint16_t tx_len;
93
94 uint8_t rx[MAX_MAC_PACKET_LEN];
95 uint16_t rx_len;
96 } temp;
97
98 /* buffers used for dma transfer, cannot be accessed while transfer active */
99 struct sy1xx_mac_dma_buffers *dma_buffers;
100
101 struct k_thread rx_data_thread;
102
103 K_KERNEL_STACK_MEMBER(rx_data_thread_stack, SY1XX_ETH_STACK_SIZE);
104
105 struct net_if *iface;
106 };
107
108 /* prototypes */
109 static int sy1xx_mac_set_mac_addr(const struct device *dev, uint8_t *mac_addr);
110 static int sy1xx_mac_set_promiscuous_mode(const struct device *dev, bool promiscuous_mode);
111 static int sy1xx_mac_set_config(const struct device *dev, enum ethernet_config_type type,
112 const struct ethernet_config *config);
113 static void sy1xx_mac_rx_thread_entry(void *p1, void *p2, void *p3);
114
sy1xx_mac_initialize(const struct device * dev)115 static int sy1xx_mac_initialize(const struct device *dev)
116 {
117 struct sy1xx_mac_dev_config *cfg = (struct sy1xx_mac_dev_config *)dev->config;
118 struct sy1xx_mac_dev_data *data = (struct sy1xx_mac_dev_data *)dev->data;
119 int ret;
120
121 data->link_is_up = false;
122 data->link_speed = -1;
123
124 k_mutex_init(&data->mutex);
125
126 /* PAD config */
127 ret = pinctrl_apply_state(cfg->pcfg, PINCTRL_STATE_DEFAULT);
128 if (ret) {
129 LOG_ERR("failed to configure pins");
130 return ret;
131 }
132
133 /* create the receiver thread */
134 k_thread_create(&data->rx_data_thread, (k_thread_stack_t *)data->rx_data_thread_stack,
135 SY1XX_ETH_STACK_SIZE, sy1xx_mac_rx_thread_entry, (void *)dev, NULL, NULL,
136 SY1XX_ETH_THREAD_PRIORITY, 0, K_NO_WAIT);
137
138 /* start suspended and resume once we have link */
139 k_thread_suspend(&data->rx_data_thread);
140
141 k_thread_name_set(&data->rx_data_thread, "mac-rx-thread");
142
143 return 0;
144 }
145
sy1xx_mac_set_promiscuous_mode(const struct device * dev,bool promiscuous_mode)146 static int sy1xx_mac_set_promiscuous_mode(const struct device *dev, bool promiscuous_mode)
147 {
148 struct sy1xx_mac_dev_config *cfg = (struct sy1xx_mac_dev_config *)dev->config;
149 uint32_t prom;
150
151 /* set promiscuous mode */
152 prom = sys_read32(cfg->ctrl_addr + SY1XX_MAC_ADDRESS_HIGH_REG);
153 if (promiscuous_mode) {
154 prom &= ~BIT(16);
155 } else {
156 prom |= BIT(16);
157 }
158 sys_write32(prom, cfg->ctrl_addr + SY1XX_MAC_ADDRESS_HIGH_REG);
159
160 return 0;
161 }
162
sy1xx_mac_set_mac_addr(const struct device * dev,uint8_t * mac_addr)163 static int sy1xx_mac_set_mac_addr(const struct device *dev, uint8_t *mac_addr)
164 {
165 struct sy1xx_mac_dev_config *cfg = (struct sy1xx_mac_dev_config *)dev->config;
166 struct sy1xx_mac_dev_data *data = (struct sy1xx_mac_dev_data *)dev->data;
167 int ret;
168 uint32_t v_low, v_high;
169
170 LOG_INF("%s set link address %02x:%02x:%02x:%02x:%02x:%02x", dev->name, mac_addr[0],
171 mac_addr[1], mac_addr[2], mac_addr[3], mac_addr[4], mac_addr[5]);
172
173 /* update mac in controller */
174 v_low = sys_get_le32(&mac_addr[0]);
175 sys_write32(v_low, cfg->ctrl_addr + SY1XX_MAC_ADDRESS_LOW_REG);
176
177 v_high = sys_read32(cfg->ctrl_addr + SY1XX_MAC_ADDRESS_HIGH_REG);
178 v_high |= (v_high & 0xffff0000) | sys_get_le16(&mac_addr[4]);
179 sys_write32(v_high, cfg->ctrl_addr + SY1XX_MAC_ADDRESS_HIGH_REG);
180
181 memcpy(data->mac_addr, mac_addr, 6);
182
183 /* Register Ethernet MAC Address with the upper layer */
184 ret = net_if_set_link_addr(data->iface, data->mac_addr, sizeof(data->mac_addr),
185 NET_LINK_ETHERNET);
186 if (ret) {
187 LOG_ERR("%s failed to set link address", dev->name);
188 return ret;
189 }
190
191 return 0;
192 }
193
sy1xx_mac_start(const struct device * dev)194 static int sy1xx_mac_start(const struct device *dev)
195 {
196 struct sy1xx_mac_dev_config *cfg = (struct sy1xx_mac_dev_config *)dev->config;
197 struct sy1xx_mac_dev_data *data = (struct sy1xx_mac_dev_data *)dev->data;
198 uint8_t rand_mac_addr[6];
199
200 extern void sy1xx_udma_disable_clock(sy1xx_udma_module_t module, uint32_t instance);
201
202 /* UDMA clock reset and enable */
203 sy1xx_udma_enable_clock(SY1XX_UDMA_MODULE_MAC, 0);
204 sy1xx_udma_disable_clock(SY1XX_UDMA_MODULE_MAC, 0);
205 sy1xx_udma_enable_clock(SY1XX_UDMA_MODULE_MAC, 0);
206
207 /* reset mac controller */
208 sys_write32(0x0001, cfg->ctrl_addr + SY1XX_MAC_CTRL_REG);
209 sys_write32(0x0000, cfg->ctrl_addr + SY1XX_MAC_CTRL_REG);
210
211 /* preset mac addr */
212 if (cfg->use_local_mac_address) {
213 /* prio 0 -- from device tree */
214 sy1xx_mac_set_mac_addr(dev, cfg->local_mac_address);
215 } else if (cfg->use_zephyr_random_mac) {
216 /* prio 1 -- generate random, if set in device tree */
217 sys_rand_get(&rand_mac_addr, 6);
218 /* Set MAC address locally administered, unicast (LAA) */
219 rand_mac_addr[0] |= 0x02;
220 sy1xx_mac_set_mac_addr(dev, rand_mac_addr);
221 } else {
222 /* no preset mac address available */
223 }
224
225 sy1xx_mac_set_promiscuous_mode(dev, cfg->promiscuous_mode);
226
227 k_thread_resume(&data->rx_data_thread);
228
229 return 0;
230 }
231
sy1xx_mac_stop(const struct device * dev)232 static int sy1xx_mac_stop(const struct device *dev)
233 {
234 struct sy1xx_mac_dev_data *data = (struct sy1xx_mac_dev_data *)dev->data;
235
236 k_thread_suspend(&data->rx_data_thread);
237 return 0;
238 }
239
phy_link_state_changed(const struct device * pdev,struct phy_link_state * state,void * user_data)240 static void phy_link_state_changed(const struct device *pdev, struct phy_link_state *state,
241 void *user_data)
242 {
243 const struct device *dev = (const struct device *)user_data;
244 struct sy1xx_mac_dev_data *const data = dev->data;
245 const struct sy1xx_mac_dev_config *const cfg = dev->config;
246 bool is_up;
247 enum phy_link_speed speed;
248 uint32_t v, en;
249
250 is_up = state->is_up;
251 speed = state->speed;
252
253 if (speed != data->link_speed) {
254 data->link_speed = speed;
255
256 /* configure mac, based on provided link information 1Gbs/100MBit/... */
257 v = sys_read32(cfg->ctrl_addr + SY1XX_MAC_CTRL_REG);
258
259 /* mask out relevant bits */
260 v &= ~(BIT(SY1XX_MAC_CTRL_GMII_OFFS) | BIT(SY1XX_MAC_CTRL_CLK_SEL_OFFS) |
261 (SY1XX_MAC_CTRL_CLK_DIV_MASK << SY1XX_MAC_CTRL_CLK_DIV_OFFS));
262
263 switch (speed) {
264 case LINK_FULL_10BASE_T:
265 LOG_INF("link speed FULL_10BASE_T");
266 /* 2.5MHz, MAC is clock source */
267 v |= (SY1XX_MAC_CTRL_CLK_SEL_MII_CLK << SY1XX_MAC_CTRL_CLK_SEL_OFFS) |
268 (SY1XX_MAC_CTRL_CLK_DIV_10 << SY1XX_MAC_CTRL_CLK_DIV_OFFS);
269 break;
270 case LINK_FULL_100BASE_T:
271 LOG_INF("link speed FULL_100BASE_T");
272 /* 25MHz, MAC is clock source */
273 v |= (SY1XX_MAC_CTRL_CLK_SEL_MII_CLK << SY1XX_MAC_CTRL_CLK_SEL_OFFS) |
274 (SY1XX_MAC_CTRL_CLK_DIV_1 << SY1XX_MAC_CTRL_CLK_DIV_OFFS);
275 break;
276 case LINK_FULL_1000BASE_T:
277 LOG_INF("link speed FULL_1000BASE_T");
278 /* 125MHz, Phy is clock source */
279 v |= BIT(SY1XX_MAC_CTRL_GMII_OFFS) |
280 (SY1XX_MAC_CTRL_CLK_SEL_REF_CLK << SY1XX_MAC_CTRL_CLK_SEL_OFFS) |
281 (SY1XX_MAC_CTRL_CLK_DIV_1 << SY1XX_MAC_CTRL_CLK_DIV_OFFS);
282 break;
283 default:
284 LOG_ERR("invalid link speed");
285 return;
286 }
287 sys_write32(v, cfg->ctrl_addr + SY1XX_MAC_CTRL_REG);
288 }
289
290 if (is_up != data->link_is_up) {
291 data->link_is_up = is_up;
292
293 if (is_up) {
294 LOG_DBG("Link up");
295
296 /* enable mac controller */
297 en = sys_read32(cfg->ctrl_addr + SY1XX_MAC_CTRL_REG);
298 en |= BIT(SY1XX_MAC_CTRL_TX_EN_OFFS) | BIT(SY1XX_MAC_CTRL_RX_EN_OFFS);
299 sys_write32(en, cfg->ctrl_addr + SY1XX_MAC_CTRL_REG);
300
301 /* Announce link up status */
302 net_eth_carrier_on(data->iface);
303
304 } else {
305 LOG_DBG("Link down");
306
307 /* disable mac controller */
308 en = sys_read32(cfg->ctrl_addr + SY1XX_MAC_CTRL_REG);
309 en &= ~(BIT(SY1XX_MAC_CTRL_TX_EN_OFFS) | BIT(SY1XX_MAC_CTRL_RX_EN_OFFS));
310 sys_write32(en, cfg->ctrl_addr + SY1XX_MAC_CTRL_REG);
311
312 /* Announce link down status */
313 net_eth_carrier_off(data->iface);
314 }
315 }
316 }
317
sy1xx_mac_iface_init(struct net_if * iface)318 static void sy1xx_mac_iface_init(struct net_if *iface)
319 {
320 const struct device *dev = net_if_get_device(iface);
321 struct sy1xx_mac_dev_config *cfg = (struct sy1xx_mac_dev_config *)dev->config;
322 struct sy1xx_mac_dev_data *const data = dev->data;
323
324 LOG_INF("Interface init %s (%.8x)", net_if_get_device(iface)->name, iface);
325
326 data->iface = iface;
327
328 ethernet_init(iface);
329
330 if (device_is_ready(cfg->phy_dev)) {
331 phy_link_callback_set(cfg->phy_dev, &phy_link_state_changed, (void *)dev);
332 } else {
333 LOG_ERR("PHY device not ready");
334 }
335
336 /* Do not start the interface until PHY link is up */
337 if (!(data->link_is_up)) {
338 LOG_INF("found PHY link down");
339 net_if_carrier_off(iface);
340 }
341 }
342
sy1xx_mac_get_caps(const struct device * dev)343 static enum ethernet_hw_caps sy1xx_mac_get_caps(const struct device *dev)
344 {
345 enum ethernet_hw_caps supported = 0;
346
347 /* basic implemented features */
348 supported |= ETHERNET_PROMISC_MODE;
349 supported |= ETHERNET_LINK_1000BASE_T;
350 supported |= ETHERNET_PROMISC_MODE;
351
352 return supported;
353 }
354
sy1xx_mac_get_config(const struct device * dev,enum ethernet_config_type type,struct ethernet_config * config)355 static int sy1xx_mac_get_config(const struct device *dev, enum ethernet_config_type type,
356 struct ethernet_config *config)
357 {
358 struct sy1xx_mac_dev_data *data = (struct sy1xx_mac_dev_data *)dev->data;
359
360 /* we currently support only 1000mbit/s full duplex */
361 switch (type) {
362 case ETHERNET_CONFIG_TYPE_LINK:
363 config->l.link_1000bt = true;
364 break;
365
366 case ETHERNET_CONFIG_TYPE_DUPLEX:
367 config->full_duplex = true;
368 break;
369
370 case ETHERNET_CONFIG_TYPE_MAC_ADDRESS:
371 memcpy(config->mac_address.addr, data->mac_addr, 6);
372 break;
373 default:
374 return -ENOTSUP;
375 }
376 return 0;
377 }
378
sy1xx_mac_set_config(const struct device * dev,enum ethernet_config_type type,const struct ethernet_config * config)379 static int sy1xx_mac_set_config(const struct device *dev, enum ethernet_config_type type,
380 const struct ethernet_config *config)
381 {
382 int ret = 0;
383
384 switch (type) {
385
386 case ETHERNET_CONFIG_TYPE_PROMISC_MODE:
387 ret = sy1xx_mac_set_promiscuous_mode(dev, config->promisc_mode);
388 break;
389
390 case ETHERNET_CONFIG_TYPE_MAC_ADDRESS:
391 ret = sy1xx_mac_set_mac_addr(dev, (uint8_t *)&(config->mac_address.addr));
392 break;
393 default:
394 return -ENOTSUP;
395 }
396 return ret;
397 }
398
sy1xx_mac_get_phy(const struct device * dev)399 static const struct device *sy1xx_mac_get_phy(const struct device *dev)
400 {
401 const struct sy1xx_mac_dev_config *const cfg = dev->config;
402
403 return cfg->phy_dev;
404 }
405
406 /*
407 * rx ready status of eth is different to any other rx udma,
408 * so we implement here
409 */
sy1xx_mac_udma_is_finished_rx(uint32_t base)410 static int32_t sy1xx_mac_udma_is_finished_rx(uint32_t base)
411 {
412 uint32_t isBusy = SY1XX_UDMA_READ_REG(base, SY1XX_UDMA_CFG_REG + 0x00) & (BIT(17));
413
414 return isBusy ? 0 : 1;
415 }
416
sy1xx_mac_low_level_send(const struct device * dev,uint8_t * tx,uint16_t len)417 static int sy1xx_mac_low_level_send(const struct device *dev, uint8_t *tx, uint16_t len)
418 {
419 struct sy1xx_mac_dev_config *cfg = (struct sy1xx_mac_dev_config *)dev->config;
420 struct sy1xx_mac_dev_data *const data = dev->data;
421
422 if (len == 0) {
423 return -EINVAL;
424 }
425
426 if (len > MAX_MAC_PACKET_LEN) {
427 return -EINVAL;
428 }
429
430 if (!SY1XX_UDMA_IS_FINISHED_TX(cfg->base_addr)) {
431 return -EBUSY;
432 }
433
434 /* udma is ready, double check if last transmission was successful */
435 if (SY1XX_UDMA_GET_REMAINING_TX(cfg->base_addr)) {
436 SY1XX_UDMA_CANCEL_TX(cfg->base_addr);
437 LOG_ERR("tx - last transmission failed");
438 return -EINVAL;
439 }
440
441 /* copy data to dma buffer */
442 for (uint32_t i = 0; i < len; i++) {
443 data->dma_buffers->tx[i] = tx[i];
444 }
445
446 /* start dma transfer */
447 SY1XX_UDMA_START_TX(cfg->base_addr, (uint32_t)data->dma_buffers->tx, len, 0);
448
449 return 0;
450 }
451
sy1xx_mac_low_level_receive(const struct device * dev,uint8_t * rx,uint16_t * len)452 static int sy1xx_mac_low_level_receive(const struct device *dev, uint8_t *rx, uint16_t *len)
453 {
454 struct sy1xx_mac_dev_config *cfg = (struct sy1xx_mac_dev_config *)dev->config;
455 struct sy1xx_mac_dev_data *const data = dev->data;
456 int ret;
457 uint32_t bytes_transferred;
458
459 *len = 0;
460
461 /* rx udma still busy */
462 if (0 == sy1xx_mac_udma_is_finished_rx(cfg->base_addr)) {
463 return -EBUSY;
464 }
465
466 /* rx udma is ready */
467 bytes_transferred = SY1XX_UDMA_READ_REG(cfg->base_addr, SY1XX_UDMA_CFG_REG) & 0x0000ffff;
468 if (bytes_transferred) {
469 /* message received, copy data */
470 memcpy(rx, data->dma_buffers->rx, bytes_transferred);
471 *len = bytes_transferred;
472 ret = 0;
473 } else {
474 /* no data, should never happen */
475 SY1XX_UDMA_CANCEL_RX(cfg->base_addr);
476 ret = -EINVAL;
477 }
478
479 /* start new reception */
480 SY1XX_UDMA_START_RX(cfg->base_addr, (uint32_t)data->dma_buffers->rx, MAX_MAC_PACKET_LEN, 0);
481
482 return ret;
483 }
484
sy1xx_mac_send(const struct device * dev,struct net_pkt * pkt)485 static int sy1xx_mac_send(const struct device *dev, struct net_pkt *pkt)
486 {
487 struct sy1xx_mac_dev_data *const data = dev->data;
488 int ret;
489 uint32_t retries_left;
490 struct net_buf *frag;
491
492 k_mutex_lock(&data->mutex, K_FOREVER);
493
494 /* push all fragments of the packet into one linear buffer */
495 frag = pkt->buffer;
496 data->temp.tx_len = 0;
497 do {
498 /* copy fragment to buffer */
499 for (uint32_t i = 0; i < frag->len; i++) {
500 if (data->temp.tx_len < MAX_MAC_PACKET_LEN) {
501 data->temp.tx[data->temp.tx_len++] = frag->data[i];
502 } else {
503 LOG_ERR("tx buffer overflow");
504 k_mutex_unlock(&data->mutex);
505 return -ENOMEM;
506 }
507 }
508
509 frag = frag->frags;
510 } while (frag);
511
512 /* hand over linear tx frame to udma */
513 retries_left = MAX_TX_RETRIES;
514 while (retries_left) {
515 ret = sy1xx_mac_low_level_send(dev, data->temp.tx, data->temp.tx_len);
516 if (ret == 0) {
517 break;
518 }
519 if (ret != -EBUSY) {
520 LOG_ERR("tx error");
521 k_mutex_unlock(&data->mutex);
522 return ret;
523 }
524 k_sleep(K_MSEC(1));
525 retries_left--;
526 };
527
528 k_mutex_unlock(&data->mutex);
529 return ret;
530 }
531
sy1xx_mac_receive_data(const struct device * dev,uint8_t * rx,uint16_t len)532 static int sy1xx_mac_receive_data(const struct device *dev, uint8_t *rx, uint16_t len)
533 {
534 struct sy1xx_mac_dev_data *const data = dev->data;
535 struct net_pkt *rx_pkt;
536 int ret;
537
538 rx_pkt = net_pkt_alloc_with_buffer(data->iface, len, AF_UNSPEC, 0, K_FOREVER);
539 if (rx_pkt == NULL) {
540 LOG_ERR("rx packet allocation failed");
541 return -EINVAL;
542 }
543
544 /* add data to the net_pkt */
545 if (net_pkt_write(rx_pkt, rx, len)) {
546 LOG_ERR("failed to write data to net_pkt");
547 net_pkt_unref(rx_pkt);
548 return -EINVAL;
549 }
550
551 /* register new packet in stack */
552 ret = net_recv_data(data->iface, rx_pkt);
553 if (ret) {
554 LOG_ERR("rx packet registration failed");
555 return ret;
556 }
557
558 return 0;
559 }
560
sy1xx_mac_rx_thread_entry(void * p1,void * p2,void * p3)561 static void sy1xx_mac_rx_thread_entry(void *p1, void *p2, void *p3)
562 {
563 const struct device *dev = p1;
564 struct sy1xx_mac_dev_data *const data = dev->data;
565 int ret;
566
567 while (true) {
568 ret = sy1xx_mac_low_level_receive(dev, data->temp.rx, &data->temp.rx_len);
569 if (ret == 0) {
570 /* register a new received frame */
571 if (data->temp.rx_len) {
572 sy1xx_mac_receive_data(dev, data->temp.rx, data->temp.rx_len);
573 }
574 } else {
575 /*
576 * rx thread is running at higher prio, in case of error or busy,
577 * we could lock up the system partially.
578 */
579
580 /* we wait and try again */
581 k_sleep(K_MSEC(RECEIVE_GRACE_TIME_MSEC));
582 }
583 }
584 }
585
586 const struct ethernet_api sy1xx_mac_driver_api = {
587 .start = sy1xx_mac_start,
588 .stop = sy1xx_mac_stop,
589 .iface_api.init = sy1xx_mac_iface_init,
590 .get_capabilities = sy1xx_mac_get_caps,
591 .get_config = sy1xx_mac_get_config,
592 .set_config = sy1xx_mac_set_config,
593 .send = sy1xx_mac_send,
594 .get_phy = sy1xx_mac_get_phy,
595 };
596
597 #define SY1XX_MAC_INIT(n) \
598 \
599 PINCTRL_DT_INST_DEFINE(n); \
600 \
601 static const struct sy1xx_mac_dev_config sy1xx_mac_dev_config_##n = { \
602 .ctrl_addr = DT_INST_REG_ADDR_BY_NAME(n, ctrl), \
603 .base_addr = DT_INST_REG_ADDR_BY_NAME(n, data), \
604 .pcfg = PINCTRL_DT_INST_DEV_CONFIG_GET(n), \
605 .promiscuous_mode = DT_INST_PROP_OR(n, promiscuous_mode, false), \
606 .local_mac_address = DT_INST_PROP_OR(n, local_mac_address, {0}), \
607 .use_local_mac_address = DT_INST_NODE_HAS_PROP(n, local_mac_address), \
608 .use_zephyr_random_mac = DT_INST_NODE_HAS_PROP(n, zephyr_random_mac_address), \
609 .phy_dev = DEVICE_DT_GET(DT_INST_PHANDLE(0, phy_handle))}; \
610 \
611 static struct sy1xx_mac_dma_buffers __attribute__((section(".udma_access"))) \
612 __aligned(4) sy1xx_mac_dma_buffers_##n; \
613 \
614 static struct sy1xx_mac_dev_data sy1xx_mac_dev_data##n = { \
615 .dma_buffers = &sy1xx_mac_dma_buffers_##n, \
616 }; \
617 \
618 ETH_NET_DEVICE_DT_INST_DEFINE(n, &sy1xx_mac_initialize, NULL, &sy1xx_mac_dev_data##n, \
619 &sy1xx_mac_dev_config_##n, CONFIG_ETH_INIT_PRIORITY, \
620 &sy1xx_mac_driver_api, NET_ETH_MTU);
621
622 DT_INST_FOREACH_STATUS_OKAY(SY1XX_MAC_INIT)
623