1 /*
2  * SPDX-License-Identifier: Apache-2.0
3  * Copyright (C) 2022, Intel Corporation
4  * Description:
5  * 3504-0 Universal 10/100/1000 Ethernet MAC (DWC_gmac)
6  * Driver specifically designed for Cyclone V SoC DevKit use only.
7  *
8  * based on Intel SOC FPGA HWLIB Repo
9  * https://github.com/altera-opensource/intel-socfpga-hwlib
10  */
11 
12 #define LOG_MODULE_NAME eth_cyclonev
13 #define LOG_LEVEL	CONFIG_ETHERNET_LOG_LEVEL
14 #include <zephyr/logging/log.h>
15 LOG_MODULE_REGISTER(LOG_MODULE_NAME);
16 
17 #define DT_DRV_COMPAT snps_ethernet_cyclonev
18 
19 #include "eth_cyclonev_priv.h"
20 
21 #include <stdio.h>
22 
23 #include <zephyr/devicetree.h>
24 #include <zephyr/kernel.h>
25 #include <zephyr/net/ethernet.h>
26 
27 #include "phy_cyclonev.c"
28 #include <ethernet/eth_stats.h>
29 #include <sys/types.h>
30 #include <zephyr/irq.h>
31 #define TX_AVAIL_WAIT	    K_MSEC(1)
32 #define INC_WRAP(idx, size) ({ idx = (idx + 1) % size; })
33 
34 static const uint8_t eth_cyclonev_mac_addr[6] = DT_INST_PROP(0, local_mac_address);
35 
36 void eth_cyclonev_reset(uint32_t instance);
37 void eth_cyclonev_set_mac_addr(uint8_t *address, uint32_t instance, uint32_t n,
38 				struct eth_cyclonev_priv *p);
39 int eth_cyclonev_get_software_reset_status(uint32_t instance, struct eth_cyclonev_priv *p);
40 int eth_cyclonev_software_reset(uint32_t instance, struct eth_cyclonev_priv *p);
41 void eth_cyclonev_setup_rxdesc(struct eth_cyclonev_priv *p);
42 void eth_cyclonev_setup_txdesc(struct eth_cyclonev_priv *p);
43 static void eth_cyclonev_iface_init(struct net_if *iface);
44 static int eth_cyclonev_send(const struct device *dev, struct net_pkt *pkt);
45 void eth_cyclonev_isr(const struct device *dev);
46 int set_mac_conf_status(int instance, uint32_t *mac_config_reg_settings,
47 				struct eth_cyclonev_priv *p);
48 int eth_cyclonev_probe(const struct device *dev);
49 static int eth_cyclonev_start(const struct device *dev);
50 static int eth_cyclonev_stop(const struct device *dev);
51 static void eth_cyclonev_receive(struct eth_cyclonev_priv *p);
52 static void eth_cyclonev_tx_release(struct eth_cyclonev_priv *p);
53 static int eth_cyclonev_set_config(const struct device *dev, enum ethernet_config_type type,
54 				const struct ethernet_config *config);
55 static enum ethernet_hw_caps eth_cyclonev_caps(const struct device *dev);
56 
57 /** Device config */
58 struct eth_cyclonev_config {
59 	/** BBRAM base address */
60 	uint8_t *base;
61 	/** BBRAM size (Unit:bytes) */
62 	int size;
63 	uint32_t emac_index;
64 	void (*irq_config)(void);
65 };
66 
67 /**
68  * @brief Reset gmac device function
69  * Function initialise HPS interface, see
70  * https://www.intel.com/content/dam/www/programmable
71  * /us/en/pdfs/literature/hb/cyclone-v/cv_54001.pdf p. 1252
72  *
73  * @param instance Number of instance (0 or 1 in Cyclone V HPS)
74  */
75 
eth_cyclonev_reset(uint32_t instance)76 void eth_cyclonev_reset(uint32_t instance)
77 {
78 	/*	 1. After the HPS is released from cold or warm reset,
79 	 *reset the Ethernet Controller module by setting the appropriate
80 	 *emac bit in the permodrst register in the Reset Manager.
81 	 */
82 
83 	sys_set_bits(RSTMGR_PERMODRST_ADDR, Rstmgr_Permodrst_Emac_Set_Msk[instance]);
84 
85 	/*	 4a. Set the physel_* field in the ctrl register of the System Manager
86 	 *(EMAC Group) to 0x1 to select the RGMII PHY interface.
87 	 */
88 
89 	alt_replbits_word(SYSMGR_EMAC_ADDR, Sysmgr_Core_Emac_Phy_Intf_Sel_Set_Msk[instance],
90 			  Sysmgr_Emac_Phy_Intf_Sel_E_Rgmii[instance]);
91 
92 	/*	 4b. Disable the Ethernet Controller FPGA interfaces by clearing the
93 	 * emac_* bit in the module register of the System Manager (FPGA Interface
94 	 * group).
95 	 */
96 
97 	sys_clear_bits(SYSMGR_FPGAINTF_INDIV_ADDR, Sysmgr_Fpgaintf_En_3_Emac_Set_Msk[instance]);
98 
99 	/*	 7. After confirming the settings are valid, software can clear the emac
100 	 * bit in the permodrst register of the Reset Manager to bring the EMAC out of
101 	 * reset.
102 	 */
103 
104 	sys_clear_bits(RSTMGR_PERMODRST_ADDR, Rstmgr_Permodrst_Emac_Set_Msk[instance]);
105 }
106 
107 /**
108  * @brief Set MAC Address function
109  * Loads the selected MAC Address in device's registers.
110  *
111  * @param address Pointer to Mac Address table
112  * @param instance Number of instance (0 or 1 in Cyclone V HPS)
113  * @param n Selected index of MAC Address, n <= 15. There's no implementation
114  * of setting MAC Addresses for n > 15.
115  *
116  */
117 
eth_cyclonev_set_mac_addr(uint8_t * address,uint32_t instance,uint32_t n,struct eth_cyclonev_priv * p)118 void eth_cyclonev_set_mac_addr(uint8_t *address, uint32_t instance, uint32_t n,
119 	struct eth_cyclonev_priv *p)
120 {
121 	uint32_t tmpreg;
122 
123 	if (instance > 1) {
124 		return;
125 	}
126 	if (n > 15) {
127 		LOG_ERR("Invalid index of MAC Address: %d", n);
128 		return;
129 	}
130 
131 	/* Calculate the selected MAC address high register */
132 	tmpreg = ((uint32_t)address[5] << 8) | (uint32_t)address[4];
133 
134 	/* Load the selected MAC address high register */
135 	sys_write32(tmpreg, EMAC_GMAC_MAC_ADDR_HIGH_ADDR(p->base_addr, n));
136 
137 	/* Calculate the selected MAC address low register */
138 	tmpreg = ((uint32_t)address[3] << 24) | ((uint32_t)address[2] << 16) |
139 		 ((uint32_t)address[1] << 8) | address[0];
140 
141 	/* Load the selected MAC address low register */
142 	sys_write32(tmpreg, EMAC_GMAC_MAC_ADDR_LOW_ADDR(p->base_addr, n));
143 }
144 
145 /**
146  * @brief Get software reset status function
147  * Check status of SWR bit in DMA Controller Bus_Mode Register
148  *
149  * @param instance Number of instance (0 or 1 in Cyclone V HPS)
150  * @retval 1 if DMA Controller Resets Logic, 0 otherwise
151  */
152 
eth_cyclonev_get_software_reset_status(uint32_t instance,struct eth_cyclonev_priv * p)153 int eth_cyclonev_get_software_reset_status(uint32_t instance, struct eth_cyclonev_priv *p)
154 {
155 	if (instance > 1) {
156 		return -1;
157 	}
158 	return EMAC_DMA_MODE_SWR_GET(sys_read32(EMAC_DMAGRP_BUS_MODE_ADDR(p->base_addr)));
159 }
160 
161 /**
162  * @brief Perform software reset
163  * Resets all MAC subsystem registers and logic, wait for the software reset to
164  * clear
165  *
166  * @param instance Number of instance (0 or 1 in Cyclone V HPS)
167  * @retval 0 if Reset was successful, -1 otherwise
168  */
169 
eth_cyclonev_software_reset(uint32_t instance,struct eth_cyclonev_priv * p)170 int eth_cyclonev_software_reset(uint32_t instance, struct eth_cyclonev_priv *p)
171 {
172 	unsigned int i;
173 
174 	if (instance > 1) {
175 		return -1;
176 	}
177 
178 	/* Set the SWR bit: resets all MAC subsystem internal registers and logic */
179 	/* After reset all the registers holds their respective reset values */
180 	sys_set_bits(EMAC_DMAGRP_BUS_MODE_ADDR(p->base_addr), EMAC_DMA_MODE_SWR_SET_MSK);
181 
182 	/* Wait for the software reset to clear */
183 	for (i = 0; i < 10; i++) {
184 		k_sleep(K_MSEC(10));
185 		if (eth_cyclonev_get_software_reset_status(instance, p) == 0) {
186 			break;
187 		}
188 	}
189 
190 	if (i == 10) {
191 		return -1;
192 	}
193 
194 	return 0;
195 }
196 
197 /**
198  * @brief RX descriptor ring initialisation function
199  * Sets up RX descriptor ring with chained descriptors,
200  * sets OWN bit in each descriptor, inits rx variables and stats
201  *
202  * @param p Pointer to device structure.
203  */
204 
eth_cyclonev_setup_rxdesc(struct eth_cyclonev_priv * p)205 void eth_cyclonev_setup_rxdesc(struct eth_cyclonev_priv *p)
206 {
207 	int32_t i;
208 	struct eth_cyclonev_dma_desc *rx_desc;
209 
210 	/* For each descriptor where i = descriptor index do: */
211 	for (i = 0; i < NB_RX_DESCS; i++) {
212 		rx_desc = &p->rx_desc_ring[i];
213 		rx_desc->buffer1_addr = (uint32_t)&p->rx_buf[i * ETH_BUFFER_SIZE];
214 		rx_desc->control_buffer_size = ETH_DMARXDESC_RCH | ETH_BUFFER_SIZE;
215 
216 		/*set own bit*/
217 		rx_desc->status = ETH_DMARXDESC_OWN;
218 
219 		rx_desc->buffer2_next_desc_addr = (uint32_t)&p->rx_desc_ring[i + 1];
220 		if (i == (NB_RX_DESCS - 1)) {
221 			rx_desc->buffer2_next_desc_addr = (uint32_t)&p->rx_desc_ring[0];
222 		}
223 	}
224 
225 	p->rx_current_desc_number = 0;
226 	p->rxints = 0;
227 
228 	/* Set RX Descriptor List Address Register */
229 	sys_write32((uint32_t)&p->rx_desc_ring[0],
230 		    EMAC_DMA_RX_DESC_LIST_ADDR(p->base_addr));
231 }
232 
233 /**
234  * @brief TX descriptor ring initialisation function
235  * Sets up TX descriptor ring with chained descriptors,
236  * sets OWN bit in each descriptor, inits rx variables and stats
237  *
238  * @param p Pointer to device structure.
239  */
240 
eth_cyclonev_setup_txdesc(struct eth_cyclonev_priv * p)241 void eth_cyclonev_setup_txdesc(struct eth_cyclonev_priv *p)
242 {
243 	int32_t i;
244 
245 	struct eth_cyclonev_dma_desc *tx_desc;
246 
247 	/* For each descriptor where i = descriptor index do: */
248 	for (i = 0; i < NB_TX_DESCS; i++) {
249 		tx_desc = &p->tx_desc_ring[i];
250 		tx_desc->buffer1_addr = (uint32_t)&p->tx_buf[i * ETH_BUFFER_SIZE];
251 		tx_desc->buffer2_next_desc_addr = (uint32_t)&p->tx_desc_ring[i + 1];
252 		tx_desc->status = 0;
253 		tx_desc->control_buffer_size = 0;
254 
255 		if (i == (NB_TX_DESCS - 1)) {
256 			tx_desc->buffer2_next_desc_addr = (uint32_t)&p->tx_desc_ring[0];
257 		}
258 	}
259 
260 	p->tx_current_desc_number = 0;
261 	p->txints = 0;
262 	p->tx_tail = 0;
263 
264 	/* Set TX Descriptor List Address Register */
265 	sys_write32((uint32_t)&p->tx_desc_ring[0],
266 		    EMAC_DMA_TX_DESC_LIST_ADDR(p->base_addr));
267 }
268 
269 /**
270  * @brief Ethernet interface initialisation function
271  * Inits interface, sets interface link MAC address
272  *
273  * @param iface Pointer to net_if structure
274  */
275 
276 /* Initialisation of interface */
eth_cyclonev_iface_init(struct net_if * iface)277 static void eth_cyclonev_iface_init(struct net_if *iface)
278 {
279 	const struct device *dev = net_if_get_device(iface);
280 	const struct eth_cyclonev_config *config = dev->config;
281 	struct eth_cyclonev_priv *p = dev->data;
282 
283 	p->iface = iface;
284 	ethernet_init(iface);
285 	net_if_set_link_addr(iface, p->mac_addr, sizeof(p->mac_addr), NET_LINK_ETHERNET);
286 
287 	/*
288 	 * Semaphores are used to represent number of available descriptors.
289 	 * The total is one less than ring size in order to always have
290 	 * at least one inactive slot for the hardware tail pointer to
291 	 * stop at and to prevent our head indexes from looping back
292 	 * onto our tail indexes.
293 	 */
294 	k_sem_init(&p->free_tx_descs, NB_TX_DESCS - 1, NB_TX_DESCS - 1);
295 
296 	/* Initialize the ethernet irq handler */
297 	config->irq_config();
298 
299 	p->initialised = 1;
300 	LOG_DBG("done");
301 }
302 
303 /**
304  * @brief Ethernet set config function usually called by
305  *	Zephyr Ethernet stack. It supports currently two options:
306  *	Set of Mac address and Enabling Promiscuous Mode
307  *
308  * @param dev Pointer to net_if structure
309  * @param type Enumerated type of configuration to do
310  * @param config Pointer to ethernet_config structure
311  * @retval ret 0 if successful
312  */
313 
eth_cyclonev_set_config(const struct device * dev,enum ethernet_config_type type,const struct ethernet_config * config)314 static int eth_cyclonev_set_config(const struct device *dev, enum ethernet_config_type type,
315 				   const struct ethernet_config *config)
316 {
317 	struct eth_cyclonev_priv *p = dev->data;
318 	const struct eth_cyclonev_config *cv_config = dev->config;
319 	uint32_t reg_val;
320 	int ret = 0;
321 
322 	(void)reg_val; /* silence the "unused variable" warning */
323 
324 	switch (type) {
325 	case ETHERNET_CONFIG_TYPE_MAC_ADDRESS:
326 		memcpy(p->mac_addr, config->mac_address.addr, sizeof(p->mac_addr));
327 		eth_cyclonev_set_mac_addr(p->mac_addr, cv_config->emac_index, 0, p); /* Set MAC */
328 		net_if_set_link_addr(p->iface, p->mac_addr, sizeof(p->mac_addr), NET_LINK_ETHERNET);
329 		break;
330 #if defined(CONFIG_NET_PROMISCUOUS_MODE)
331 	case ETHERNET_CONFIG_TYPE_PROMISC_MODE:
332 		reg_val = sys_read32(EMAC_GMACGRP_MAC_FRAME_FILTER_ADDR(p->base_addr));
333 		if (config->promisc_mode && !(reg_val & EMAC_GMACGRP_MAC_FRAME_FILTER_PR_SET_MSK)) {
334 			/* Turn on Promisc Mode */
335 			sys_set_bits(EMAC_GMACGRP_MAC_FRAME_FILTER_ADDR(p->base_addr),
336 				     EMAC_GMACGRP_MAC_FRAME_FILTER_PR_SET_MSK);
337 		} else if (!config->promisc_mode &&
338 			   (reg_val & EMAC_GMACGRP_MAC_FRAME_FILTER_PR_SET_MSK)) {
339 			/* Turn off Promisc Mode */
340 			sys_clear_bits(EMAC_GMACGRP_MAC_FRAME_FILTER_ADDR(p->base_addr),
341 				       EMAC_GMACGRP_MAC_FRAME_FILTER_PR_SET_MSK);
342 		} else {
343 			ret = -EALREADY;
344 		}
345 		break;
346 #endif
347 	default:
348 		ret = -ENOTSUP;
349 		break;
350 	}
351 	LOG_DBG("set_config: ret = %d ", ret);
352 	return ret;
353 }
354 
355 /**
356  * @brief Get capabilities function usually called by
357  *	Zephyr Ethernet stack.
358  *
359  * @param dev Pointer to net_if structure
360  * @retval caps Enumerated capabilities of device
361  */
362 
eth_cyclonev_caps(const struct device * dev)363 static enum ethernet_hw_caps eth_cyclonev_caps(const struct device *dev)
364 {
365 	struct eth_cyclonev_priv *p = dev->data;
366 	enum ethernet_hw_caps caps = 0;
367 
368 	if (p->feature & EMAC_DMA_HW_FEATURE_MIISEL) {
369 		caps |= ETHERNET_LINK_10BASE_T;
370 		caps |= ETHERNET_LINK_100BASE_T;
371 	}
372 	if (p->feature & EMAC_DMA_HW_FEATURE_GMIISEL) {
373 		caps |= ETHERNET_LINK_1000BASE_T;
374 	}
375 	if (p->feature & EMAC_DMA_HW_FEATURE_RXTYP2COE) {
376 		caps |= ETHERNET_HW_RX_CHKSUM_OFFLOAD;
377 	}
378 	if (p->feature & EMAC_DMA_HW_FEATURE_RXTYP1COE) {
379 		caps |= ETHERNET_HW_RX_CHKSUM_OFFLOAD;
380 	}
381 
382 	caps |= ETHERNET_PROMISC_MODE;
383 
384 	return caps;
385 }
386 
387 /**
388  * @brief Send packet function
389  * Sends packet of data. See:
390  * https://www.intel.com/content/dam/www/programmable/us/en/pdfs/
391  * literature/hb/cyclone-v/cv_54001.pdf p.1254 and p.1206
392  *
393  * @param dev Pointer to device structure
394  * @param pkt Pointer to net_pkt structure containing packet to sent
395  * @retval 0 if successful, -1 otherwise
396  */
397 
eth_cyclonev_send(const struct device * dev,struct net_pkt * pkt)398 static int eth_cyclonev_send(const struct device *dev, struct net_pkt *pkt)
399 {
400 	LOG_DBG("ethernet CVSX sending...\n");
401 
402 	struct eth_cyclonev_priv *p = dev->data;
403 	struct eth_cyclonev_dma_desc *tx_desc;
404 	int32_t index = 0;
405 	uint16_t len = net_pkt_get_len(pkt);
406 	int first = 1;
407 	struct net_buf *frag;
408 
409 	LOG_DBG("Pkt length: %d", len);
410 	frag = pkt->buffer;
411 	do {
412 
413 		/* reserve a free descriptor for this fragment */
414 		if (k_sem_take(&p->free_tx_descs, TX_AVAIL_WAIT) != 0) {
415 			LOG_DBG("no more free tx descriptors");
416 			goto abort;
417 		}
418 
419 		tx_desc = &p->tx_desc_ring[p->tx_current_desc_number];
420 
421 		/* Check if it is a free descriptor.  */
422 		if (tx_desc->status & ETH_DMATXDESC_OWN) {
423 			/* Buffer is still owned by device.  */
424 			LOG_ERR("No free tx descriptors!\n");
425 			goto abort;
426 		}
427 
428 		/* check if len is too large */
429 		if (len >= ETH_BUFFER_SIZE) {
430 			LOG_ERR("Length of packet is too long\n");
431 			goto abort;
432 		}
433 
434 		/* Copy data to local buffer   */
435 
436 		if (frag) {
437 			memcpy(&p->tx_buf[p->tx_current_desc_number * ETH_BUFFER_SIZE], frag->data,
438 			       len);
439 		}
440 
441 		/* Set the buffer size.  */
442 		tx_desc->control_buffer_size = (frag->len & ETH_DMATXDESC_TBS1);
443 
444 		LOG_DBG("Desc[%d] at address: 0x%08x: , Frag size: %d, Buffer Addr: %p",
445 			p->tx_current_desc_number,
446 			(unsigned int)&p->tx_desc_ring[p->tx_current_desc_number], frag->len,
447 			(void *)tx_desc->buffer1_addr);
448 
449 		tx_desc->status = ETH_DMATXDESC_TCH;
450 
451 		/* Set the Descriptor's FS bit.  */
452 		if (first) {
453 			tx_desc->status |= (ETH_DMATXDESC_FS | ETH_DMATXDESC_CIC_BYPASS);
454 			first = 0;
455 		}
456 
457 		/* If Last: then (...) */
458 		if (!frag->frags) {
459 			/* set the Descriptor's LS and IC bit.  */
460 			tx_desc->status |= (ETH_DMATXDESC_LS | ETH_DMATXDESC_IC);
461 			index = p->tx_current_desc_number;
462 		}
463 
464 		/* Set the current index to the next descriptor.  */
465 		p->tx_current_desc_number = (p->tx_current_desc_number + 1);
466 		if (p->tx_current_desc_number >= NB_TX_DESCS) {
467 			p->tx_current_desc_number = 0;
468 		}
469 
470 		if (!frag->frags) {
471 
472 			while (1) {
473 
474 				tx_desc = &p->tx_desc_ring[index];
475 
476 				if (tx_desc->status & ETH_DMATXDESC_OWN) {
477 					LOG_ERR("Send packet error!\n");
478 					/* Restart DMA transmission and re-initialise
479 					 * TX descriptors
480 					 */
481 					sys_clear_bits(EMAC_DMAGRP_OPERATION_MODE_ADDR(
482 							       p->base_addr),
483 						       EMAC_DMAGRP_OPERATION_MODE_ST_SET_MSK);
484 					sys_set_bits(EMAC_DMAGRP_OPERATION_MODE_ADDR(
485 							     p->base_addr),
486 						     EMAC_DMAGRP_OPERATION_MODE_FTF_SET_MSK);
487 					eth_cyclonev_setup_txdesc(p);
488 					sys_set_bits(EMAC_DMAGRP_OPERATION_MODE_ADDR(
489 							     p->base_addr),
490 						     EMAC_DMAGRP_OPERATION_MODE_ST_SET_MSK);
491 					goto abort;
492 				}
493 
494 				/* Set OWN bit.  */
495 				tx_desc->status |= ETH_DMATXDESC_OWN;
496 
497 				if (tx_desc->status & ETH_DMATXDESC_FS) {
498 					break;
499 				}
500 
501 				index--;
502 				if (index < 0) {
503 					index = NB_TX_DESCS - 1;
504 				}
505 			}
506 
507 			LOG_DBG("Current Host Transmit Descriptor Register: 0x%08x",
508 				sys_read32(
509 					EMAC_DMA_CURR_HOST_TX_DESC_ADDR(p->base_addr)));
510 			LOG_DBG("Current Host Transmit Buffer Register: 0x%08x",
511 				sys_read32(
512 					EMAC_DMA_CURR_HOST_TX_BUFF_ADDR(p->base_addr)));
513 
514 			/* If the DMA transmission is suspended, resume transmission.  */
515 			if (sys_read32(EMAC_DMAGRP_STATUS_ADDR(p->base_addr)) &
516 			    EMAC_DMAGRP_STATUS_TS_SET_MSK) {
517 
518 				/* Clear TBUS ETHERNET DMA flag */
519 				sys_write32(EMAC_DMAGRP_STATUS_TS_SET_MSK,
520 					    EMAC_DMAGRP_STATUS_ADDR(p->base_addr));
521 
522 				/* Resume DMA transmission */
523 				sys_write32(0,
524 					    EMAC_DMA_TX_POLL_DEMAND_ADDR(p->base_addr));
525 			}
526 		}
527 		frag = frag->frags;
528 	} while (frag);
529 
530 	LOG_DBG("Sent");
531 	return 0;
532 
533 abort:
534 	k_sem_give(&p->free_tx_descs); /* Multi-descriptor package release (?) */
535 
536 	return -1;
537 }
538 
539 /**
540  * @brief Interrupt handling function
541  * Detects interrupt status, invokes necessary actions
542  * and clears interrupt status register
543  *
544  * @param dev Pointer to device structure
545  */
546 
eth_cyclonev_isr(const struct device * dev)547 void eth_cyclonev_isr(const struct device *dev)
548 {
549 	struct eth_cyclonev_priv *p = dev->data;
550 	const struct eth_cyclonev_config *config = dev->config;
551 	uint32_t irq_status = 0;
552 	uint32_t irq_status_emac = 0;
553 
554 	irq_status =
555 		sys_read32(EMAC_DMAGRP_STATUS_ADDR(p->base_addr)) & p->interrupt_mask;
556 	irq_status_emac = sys_read32(EMAC_GMAC_INT_STAT_ADDR(p->base_addr));
557 	LOG_DBG("DMA_IRQ_STATUS = 0x%08x, emac: 0x%08x", irq_status, irq_status_emac);
558 
559 	if (irq_status & EMAC_DMA_INT_EN_NIE_SET_MSK) {
560 		sys_write32(EMAC_DMA_INT_EN_NIE_SET_MSK,
561 			    EMAC_DMAGRP_STATUS_ADDR(p->base_addr));
562 	}
563 
564 	if (irq_status & EMAC_DMA_INT_EN_TIE_SET_MSK) {
565 		p->txints++;
566 		eth_cyclonev_tx_release(p);
567 		/* Clear the selected ETHERNET DMA bit(s) */
568 		sys_write32(EMAC_DMA_INT_EN_TIE_SET_MSK,
569 			    EMAC_DMAGRP_STATUS_ADDR(p->base_addr));
570 	}
571 
572 	if (irq_status & EMAC_DMA_INT_EN_RIE_SET_MSK) {
573 		p->rxints++;
574 		eth_cyclonev_receive(p);
575 		/* Clear the selected ETHERNET DMA bit(s) */
576 		sys_write32(EMAC_DMA_INT_EN_RIE_SET_MSK,
577 			    EMAC_DMAGRP_STATUS_ADDR(p->base_addr));
578 	}
579 
580 	if (irq_status_emac & EMAC_GMAC_INT_STAT_RGSMIIIS_SET_MSK) {
581 		/* Clear the selected ETHERNET GMAC bit(s) */
582 		uint32_t regval = sys_read32(GMACGRP_CONTROL_STATUS_ADDR(p->base_addr));
583 
584 		if (EMAC_GMAC_MII_CTL_STAT_LNKSTS_GET(regval)) {
585 			LOG_INF("Link is up");
586 		} else {
587 			LOG_INF("Link is down");
588 			return;
589 		}
590 
591 		if (EMAC_GMAC_MII_CTL_STAT_LNKMOD_GET(regval)) {
592 			LOG_INF("Full duplex");
593 		} else {
594 			LOG_INF("Half duplex");
595 		}
596 
597 		switch (EMAC_GMAC_MII_CTL_STAT_LNKSPEED_GET(regval)) {
598 		case 0:
599 			LOG_INF("Link Speed 2.5MHz");
600 			break;
601 		case 1:
602 			LOG_INF("Link Speed 25MHz");
603 			break;
604 		case 2:
605 			LOG_INF("Link Speed 125MHz");
606 			break;
607 		default:
608 			LOG_ERR("LNKSPEED_GET_ERROR");
609 			break;
610 		}
611 
612 		if (p->initialised) {
613 			uint32_t cfg_reg_set;
614 
615 			cfg_reg_set = sys_read32(GMACGRP_MAC_CONFIG_ADDR(p->base_addr));
616 
617 			if (eth_cyclonev_stop(dev) == -1) {
618 				LOG_ERR("Couldn't stop device: %s", dev->name);
619 				return;
620 			}
621 
622 			set_mac_conf_status(config->emac_index, &cfg_reg_set, p);
623 			sys_write32(cfg_reg_set, GMACGRP_MAC_CONFIG_ADDR(p->base_addr));
624 
625 			eth_cyclonev_start(dev);
626 		}
627 	}
628 }
629 
630 /**
631  * @brief Receive packet function (IRQ)
632  * In the event of receive completion interrupt, this function
633  * copies data from buffer to necessary net stack structures
634  * performs general error checking and returns descriptor to hardware.
635  *
636  * @param p Pointer to device structure
637  *
638  */
639 
eth_cyclonev_receive(struct eth_cyclonev_priv * p)640 static void eth_cyclonev_receive(struct eth_cyclonev_priv *p)
641 {
642 	struct eth_cyclonev_dma_desc *rx_desc;
643 	struct net_pkt *pkt;
644 	uint32_t index, frame_length, rx_search, wrap, data_remaining, last_desc_index, buf_size;
645 
646 	index = p->rx_current_desc_number;
647 	rx_desc = &p->rx_desc_ring[index];
648 
649 	while (!(rx_desc->status & ETH_DMARXDESC_OWN)) {
650 
651 		LOG_DBG("RDES0[%d] = 0x%08x", index, rx_desc->status);
652 		/* Look for FS bit */
653 		if (!(rx_desc->status & ETH_DMARXDESC_FS)) {
654 			LOG_ERR("Unexpected missing FS bit");
655 			rx_desc->status |= ETH_DMARXDESC_OWN;
656 			goto cont;
657 		}
658 		/* Look for EOF bit, save frame length including multiple
659 		 * buffers and index of last descriptor
660 		 */
661 		rx_search = index;
662 		wrap = index;
663 		do {
664 			rx_desc = &p->rx_desc_ring[rx_search];
665 			/* Frame length */
666 			frame_length = data_remaining = (ETH_DMARXDESC_FL & rx_desc->status) >> 16;
667 			last_desc_index = rx_search;
668 			if (!(rx_desc->status & ETH_DMARXDESC_LS)) {
669 				INC_WRAP(rx_search, NB_RX_DESCS);
670 				if (rx_search == wrap) {
671 					LOG_ERR("Couldn't find EOF bit!");
672 					rx_desc = &p->rx_desc_ring[index];
673 					rx_desc->status |= ETH_DMARXDESC_OWN;
674 					goto cont;
675 				}
676 			}
677 		} while (!(rx_desc->status & ETH_DMARXDESC_LS));
678 
679 		LOG_DBG("Frame length = %d, Last descriptor = %d", frame_length, last_desc_index);
680 		p->rx_current_desc_number = last_desc_index;
681 
682 		/* Allocate packet with buffer */
683 		pkt = net_pkt_rx_alloc_with_buffer(p->iface, frame_length, AF_UNSPEC, 0, K_NO_WAIT);
684 		if (!pkt) {
685 			LOG_ERR("net_pkt_rx_alloc_with_buffer() failed");
686 			eth_stats_update_errors_rx(p->iface);
687 		}
688 
689 		/* Copy data from multiple buffers and descriptors */
690 		rx_search = index;
691 		wrap = index;
692 		do {
693 			rx_desc = &p->rx_desc_ring[rx_search];
694 			if (data_remaining < ETH_BUFFER_SIZE) {
695 				buf_size = data_remaining;
696 			} else {
697 				buf_size = ETH_BUFFER_SIZE;
698 			}
699 			if (pkt) {
700 				net_pkt_write(pkt, &p->rx_buf[rx_search * ETH_BUFFER_SIZE],
701 					      buf_size);
702 			}
703 			data_remaining -= buf_size;
704 			rx_desc->status |= ETH_DMARXDESC_OWN;
705 			if (last_desc_index != rx_search) {
706 				INC_WRAP(rx_search, NB_RX_DESCS);
707 				if (rx_search == wrap) {
708 					LOG_ERR("Couldn't find last descriptor! Data remaining: %d",
709 						data_remaining);
710 					goto cont;
711 				}
712 				if (rx_search == last_desc_index) {
713 					/* One more iteration */
714 					rx_desc = &p->rx_desc_ring[rx_search];
715 					if (data_remaining < ETH_BUFFER_SIZE) {
716 						buf_size = data_remaining;
717 					} else {
718 						buf_size = ETH_BUFFER_SIZE;
719 					}
720 					if (pkt) {
721 						net_pkt_write(
722 							pkt,
723 							&p->rx_buf[rx_search * ETH_BUFFER_SIZE],
724 							buf_size);
725 					}
726 					data_remaining -= buf_size;
727 
728 					rx_desc->status |= ETH_DMARXDESC_OWN;
729 				}
730 			}
731 		} while (last_desc_index != rx_search);
732 
733 		/* Hand-over packet into IP stack */
734 		if (pkt) {
735 			if (net_recv_data(p->iface, pkt) < 0) {
736 				LOG_ERR("RX packet hand-over to IP stack failed");
737 				net_pkt_unref(pkt);
738 			}
739 			LOG_DBG("Received packet %p, len %d", pkt, frame_length);
740 		}
741 
742 cont:
743 		p->rx_current_desc_number++;
744 		if (p->rx_current_desc_number == NB_RX_DESCS) {
745 			p->rx_current_desc_number = 0;
746 		}
747 		index = p->rx_current_desc_number;
748 		rx_desc = &p->rx_desc_ring[index];
749 	}
750 }
751 
752 /**
753  * @brief Release tx function
754  * Main purpose of its function is to track current descriptor number
755  * and give back succeding tx semaphore when it have been used.
756  *
757  * @param p Pointer to device structure
758  */
759 
eth_cyclonev_tx_release(struct eth_cyclonev_priv * p)760 static void eth_cyclonev_tx_release(struct eth_cyclonev_priv *p)
761 {
762 	unsigned int d_idx;
763 	struct eth_cyclonev_dma_desc *d;
764 	uint32_t des3_val;
765 
766 	for (d_idx = p->tx_tail; d_idx != p->tx_current_desc_number;
767 	     INC_WRAP(d_idx, NB_TX_DESCS), k_sem_give(&p->free_tx_descs)) {
768 
769 		d = &p->tx_desc_ring[d_idx];
770 		des3_val = d->status;
771 		LOG_DBG("TDES3[%d] = 0x%08x", d_idx, des3_val);
772 
773 		/* stop here if hardware still owns it */
774 		if (des3_val & ETH_DMATXDESC_OWN) {
775 			break;
776 		}
777 
778 		/* last packet descriptor: */
779 		if (des3_val & ETH_DMATXDESC_LS) {
780 			/* log any errors */
781 			if (des3_val & ETH_DMATXDESC_ES) {
782 				LOG_ERR("tx error (DES3 = 0x%08x)", des3_val);
783 				eth_stats_update_errors_tx(p->iface);
784 			}
785 		}
786 	}
787 	p->tx_tail = d_idx;
788 }
789 
790 /**
791  * @brief Sets MAC Config Register (not implemented)
792  * Detects PHY Mode and assigns MAC Config Register
793  *
794  * @param instance Number of instance (0 or 1 in Cyclone V HPS)
795  * @param mac_config_reg_settings Mac_config register mask to set
796  * @retval updated mac_config_reg mask (>=0), -1 otherwise
797  */
798 /* Configure the MAC with the speed fixed by the auto-negotiation process */
set_mac_conf_status(int instance,uint32_t * mac_config_reg_settings,struct eth_cyclonev_priv * p)799 int set_mac_conf_status(int instance, uint32_t *mac_config_reg_settings,
800 	struct eth_cyclonev_priv *p)
801 {
802 	uint16_t phy_duplex_status, phy_speed;
803 	int ret;
804 
805 	ret = alt_eth_phy_get_duplex_and_speed(&phy_duplex_status, &phy_speed, instance, p);
806 	if (ret != 0) {
807 		LOG_ERR("alt_eth_phy_get_duplex_and_speed failure!");
808 		return ret;
809 	}
810 
811 	/* Set Ethernet duplex mode to Full-duplex following the auto-negotiation */
812 	if (phy_duplex_status != 0) {
813 		*mac_config_reg_settings |= EMAC_GMACGRP_MAC_CONFIGURATION_DM_SET_MSK;
814 	}
815 	/* Set Ethernet duplex mode to Half-duplex following the auto-negotiation */
816 	else {
817 		*mac_config_reg_settings &= ~EMAC_GMACGRP_MAC_CONFIGURATION_DM_SET_MSK;
818 	}
819 
820 	/* Set Ethernet speed to 10M following the auto-negotiation */
821 	if (phy_speed == 10) {
822 		*mac_config_reg_settings &= ~EMAC_GMACGRP_MAC_CONFIGURATION_FES_SET_MSK;
823 		*mac_config_reg_settings |= EMAC_GMACGRP_MAC_CONFIGURATION_PS_SET_MSK;
824 	}
825 
826 	/* Set Ethernet speed to 100M following the auto-negotiation */
827 	if (phy_speed == 100) {
828 		*mac_config_reg_settings |= EMAC_GMACGRP_MAC_CONFIGURATION_FES_SET_MSK;
829 		*mac_config_reg_settings |= EMAC_GMACGRP_MAC_CONFIGURATION_PS_SET_MSK;
830 	}
831 
832 	/* Set Ethernet speed to 1G following the auto-negotiation */
833 	if (phy_speed == 1000) {
834 		*mac_config_reg_settings &= ~EMAC_GMACGRP_MAC_CONFIGURATION_PS_SET_MSK;
835 	}
836 
837 	return 0;
838 }
839 
840 /**
841  * @brief Hardware initialisation function
842  * Performs EMAC HPS interface initialisation, DMA initialisation,
843  * EMAC initialisation and configuration. See:
844  * https://www.intel.com/content/dam/
845  * www/programmable/us/en/pdfs/literature/hb/cyclone-v/cv_54001.pdf p.1252-54
846  *
847  * @param dev Pointer to device structure
848  * @retval 0 if successful, -1 otherwise
849  */
850 
eth_cyclonev_probe(const struct device * dev)851 int eth_cyclonev_probe(const struct device *dev)
852 {
853 	struct eth_cyclonev_priv *p = dev->data;
854 	const struct eth_cyclonev_config *config = dev->config;
855 	uint32_t tmpreg = 0, interrupt_mask;
856 	uint32_t mac_config_reg_settings = 0;
857 	int ret;
858 
859 	p->base_addr = (mem_addr_t)config->base;
860 	p->running = 0;
861 	p->initialised = 0;
862 
863 	/* EMAC HPS Interface Initialization */
864 
865 	/* Reset the EMAC */
866 	eth_cyclonev_reset(config->emac_index);
867 
868 	/* Reset the PHY  */
869 	ret = alt_eth_phy_reset(config->emac_index, p);
870 	if (ret != 0) {
871 		LOG_ERR("alt_eth_phy_reset failure!\n");
872 		return ret;
873 	}
874 
875 	/* Configure the PHY */
876 	ret = alt_eth_phy_config(config->emac_index, p);
877 	if (ret != 0) {
878 		LOG_ERR("alt_eth_phy_config failure!\n");
879 		return ret;
880 	}
881 
882 	/* Read HW feature register */
883 
884 	p->feature = sys_read32(EMAC_DMA_HW_FEATURE_ADDR(p->base_addr));
885 
886 	/* DMA Initialisation */
887 
888 	/* 1. Provide a software reset to reset all of the EMAC internal registers and
889 	 *logic. (DMA Register 0 (BusMode Register) – bit 0).
890 	 * 2. Wait for the completion of the reset process (poll bit 0 of the DMA
891 	 *Register 0 (Bus Mode Register), which is only cleared after the reset
892 	 *operation is completed).
893 	 */
894 
895 	ret = eth_cyclonev_software_reset(config->emac_index, p);
896 	if (ret != 0) {
897 		LOG_ERR("eth_cyclonev_software_reset failure!\n");
898 		return ret;
899 	}
900 
901 	/* 4. Program the following fields to initialize the Bus Mode Register by
902 	 * setting values in DMA Register 0 (Bus Mode Register):
903 	 */
904 
905 	sys_write32((tmpreg | EMAC_DMA_MODE_FB_SET_MSK /* Fixed Burst */
906 		     ),
907 		    EMAC_DMAGRP_BUS_MODE_ADDR(p->base_addr));
908 
909 	/*	 5. Program the interface options in Register 10 (AXI Bus Mode
910 	 * Register). If fixed burst-length is enabled, then select the maximum
911 	 * burst-length possible on the bus (bits[7:1]).(58)
912 	 */
913 
914 	tmpreg = sys_read32(EMAC_DMAGRP_AXI_BUS_MODE_ADDR(p->base_addr));
915 
916 	sys_write32(
917 		tmpreg | EMAC_DMAGRP_AXI_BUS_MODE_BLEN16_SET_MSK,
918 		EMAC_DMAGRP_AXI_BUS_MODE_ADDR(p->base_addr)); /* Set Burst Length = 16 */
919 
920 	/* 6. Create a proper descriptor chain for transmit and receive. In addition,
921 	 * ensure that the receive descriptors are owned by DMA (bit 31 of descriptor
922 	 * should be set).
923 	 * 7. Make sure that your software creates three or more different transmit or
924 	 * receive descriptors in the chain before reusing any of the descriptors
925 	 * 8. Initialize receive and transmit descriptor list address with the base
926 	 * address of the transmit and receive descriptor (Register 3 (Receive
927 	 * Descriptor List Address Register) and Register 4 (Transmit Descriptor List
928 	 * Address Register) respectively).
929 	 */
930 
931 	eth_cyclonev_setup_rxdesc(p);
932 	eth_cyclonev_setup_txdesc(p);
933 
934 	/*	9. Program the following fields to initialize the mode of operation in
935 	 * Register 6 (Operation Mode Register):
936 	 */
937 
938 	sys_write32((0 | EMAC_DMAGRP_OPERATION_MODE_TSF_SET_MSK /* Transmit Store and Forward */
939 		     | EMAC_DMAGRP_OPERATION_MODE_RSF_SET_MSK	/* Receive Store and Forward */
940 		     | EMAC_DMAGRP_OPERATION_MODE_FTF_SET_MSK	/* Receive Store and Forward */
941 		     ),
942 		    EMAC_DMAGRP_OPERATION_MODE_ADDR(p->base_addr));
943 
944 	/*	10.Clear the interrupt requests, by writing to those bits of the status
945 	 * register (interrupt bits only) that are set. For example, by writing 1 into
946 	 * bit 16, the normal interrupt summary clears this bit (DMA Register 5
947 	 * (Status Register)).
948 	 */
949 
950 	interrupt_mask = EMAC_DMA_INT_EN_NIE_SET_MSK | EMAC_DMA_INT_EN_RIE_SET_MSK |
951 			 EMAC_DMA_INT_EN_TIE_SET_MSK;
952 
953 	p->interrupt_mask = interrupt_mask;
954 
955 	/* Clear the selected ETHERNET DMA bit(s) */
956 	sys_write32(interrupt_mask, EMAC_DMAGRP_STATUS_ADDR(p->base_addr));
957 
958 	/*	11.Enable the interrupts by programming Register 7 (Interrupt Enable
959 	 * Register).
960 	 */
961 
962 	sys_set_bits(EMAC_DMA_INT_EN_ADDR(p->base_addr), interrupt_mask);
963 
964 	/* 12.Read Register 11 (AHB or AXI Status) to confirm that
965 	 * all previous transactions are complete.
966 	 */
967 
968 	if (sys_read32(EMAC_DMAGRP_AHB_OR_AXI_STATUS_ADDR(p->base_addr)) != 0) {
969 		LOG_ERR("AHB_OR_AXI_STATUS Fail!\n");
970 		return -1;
971 	}
972 
973 	/* EMAC Initialization and Configuration */
974 
975 	/*	1. Program the GMII Address Register (offset 0x10) for controlling the
976 	 * management cycles for theexternal PHY. Bits[15:11] of the GMII Address
977 	 * Register are written with the Physical Layer Address of the PHY before
978 	 * reading or writing. Bit 0 indicates if the PHY is busy and is set before
979 	 * reading or writing to the PHY management interface.
980 	 * 2. Read the 16-bit data of the GMII Data Register from the PHY for link up,
981 	 * speed of operation, and mode of operation, by specifying the appropriate
982 	 * address value in bits[15:11] of the GMII Address Register.
983 	 */
984 
985 	mac_config_reg_settings = (EMAC_GMACGRP_MAC_CONFIGURATION_IPC_SET_MSK
986 				   /* Checksum Offload */
987 				   | EMAC_GMACGRP_MAC_CONFIGURATION_JD_SET_MSK
988 				   /* Jabber Disable */
989 				   | EMAC_GMACGRP_MAC_CONFIGURATION_BE_SET_MSK
990 				   /* Frame Burst Enable */
991 				   | EMAC_GMACGRP_MAC_CONFIGURATION_WD_SET_MSK
992 				   /* Watchdog Disable */
993 				   | EMAC_GMACGRP_MAC_CONFIGURATION_TC_SET_MSK
994 				   /* Enable Transmission to PHY */
995 	);
996 
997 	ret = set_mac_conf_status(config->emac_index, &mac_config_reg_settings, p);
998 	if (ret != 0) {
999 		return -1;
1000 	}
1001 
1002 	/*	3. Provide the MAC address registers (MAC Address0 High Register
1003 	 * through MAC Address15 High Register and MAC Address0 Low Register
1004 	 * through MAC Address15 Low Register).
1005 	 */
1006 
1007 	memcpy(p->mac_addr, eth_cyclonev_mac_addr, sizeof(p->mac_addr));
1008 	eth_cyclonev_set_mac_addr(p->mac_addr, config->emac_index, 0, p);
1009 
1010 	/* 5. Program the following fields to set the appropriate filters for the
1011 	 * incoming frames in the MAC Frame Filter Register:
1012 	 * • Receive All
1013 	 * • Promiscuous mode
1014 	 * • Hash or Perfect Filter
1015 	 * • Unicast, multicast, broadcast, and control frames filter settings
1016 	 */
1017 
1018 	sys_clear_bits(EMAC_GMACGRP_MAC_FRAME_FILTER_ADDR(p->base_addr),
1019 		       EMAC_GMACGRP_MAC_FRAME_FILTER_PR_SET_MSK); /* Disable promiscuous mode */
1020 
1021 	/*	7. Program the Interrupt Mask Register bits,
1022 	 * as required and if applicable for your configuration.
1023 	 */
1024 
1025 	sys_set_bits(EMAC_GMAC_INT_MSK_ADDR(p->base_addr),
1026 		     EMAC_GMAC_INT_STAT_LPIIS_SET_MSK |	       /* Disable Low Power IRQ */
1027 			     EMAC_GMAC_INT_STAT_TSIS_SET_MSK); /* Disable Timestamp IRQ */
1028 
1029 	/* 8. Program the appropriate fields in MAC Configuration Register to
1030 	 * configure receive and transmit operation modes...
1031 	 */
1032 
1033 	sys_write32(mac_config_reg_settings, GMACGRP_MAC_CONFIG_ADDR(p->base_addr));
1034 
1035 	LOG_DBG("func_eth_cyclonev_probe Success!\n");
1036 	return 0;
1037 }
1038 
1039 /**
1040  * @brief Start device function
1041  * Starts DMA and EMAC transmitter and receiver. See:
1042  * https://www.intel.com/content/dam/
1043  * www/programmable/us/en/pdfs/literature/hb/cyclone-v/cv_54001.pdf p.1255-56
1044  *
1045  * @param dev Pointer to device structure
1046  * @retval 0
1047  */
1048 
eth_cyclonev_start(const struct device * dev)1049 static int eth_cyclonev_start(const struct device *dev)
1050 {
1051 
1052 	struct eth_cyclonev_priv *p = dev->data;
1053 
1054 	if (p->running) {
1055 		LOG_DBG("Device already running!");
1056 		return 0;
1057 	}
1058 
1059 	/*6. To re-start the operation, first start the DMA and then enable
1060 	 * the EMAC transmitter and receiver.
1061 	 */
1062 
1063 	/* Start the DMA */
1064 	sys_set_bits(EMAC_DMAGRP_OPERATION_MODE_ADDR(p->base_addr),
1065 		     EMAC_DMAGRP_OPERATION_MODE_ST_SET_MSK);
1066 	sys_set_bits(EMAC_DMAGRP_OPERATION_MODE_ADDR(p->base_addr),
1067 		     EMAC_DMAGRP_OPERATION_MODE_SR_SET_MSK);
1068 
1069 	/* Enable the EMAC transmitter and receiver */
1070 	sys_set_bits(GMACGRP_MAC_CONFIG_ADDR(p->base_addr),
1071 		     EMAC_GMACGRP_MAC_CONFIGURATION_TE_SET_MSK);
1072 	sys_set_bits(EMAC_DMAGRP_OPERATION_MODE_ADDR(p->base_addr),
1073 		     EMAC_DMAGRP_OPERATION_MODE_FTF_SET_MSK); /* Flush Transmit FIFO */
1074 	sys_set_bits(GMACGRP_MAC_CONFIG_ADDR(p->base_addr),
1075 		     EMAC_GMACGRP_MAC_CONFIGURATION_RE_SET_MSK);
1076 
1077 	p->running = 1;
1078 	LOG_DBG("Starting Device...");
1079 	return 0;
1080 }
1081 
1082 /**
1083  * @brief Stop device function
1084  * Stops DMA and EMAC transmitter and receiver. See:
1085  * https://www.intel.com/content/dam/www/
1086  * programmable/us/en/pdfs/literature/hb/cyclone-v/cv_54001.pdf p.1255-56
1087  *
1088  * @param dev Pointer to device structure
1089  * @retval 0 if successful, -1 otherwise
1090  */
1091 
eth_cyclonev_stop(const struct device * dev)1092 static int eth_cyclonev_stop(const struct device *dev)
1093 {
1094 
1095 	struct eth_cyclonev_priv *p = dev->data;
1096 
1097 	if (!p->running) {
1098 		LOG_DBG("Device is not running!");
1099 		return 0;
1100 	}
1101 	/* 1. Disable the transmit DMA (if applicable), by clearing bit 13
1102 	 * (Start or Stop Transmission Command) of Register 6 (Operation Mode
1103 	 * Register).
1104 	 */
1105 
1106 	sys_clear_bits(EMAC_DMAGRP_OPERATION_MODE_ADDR(p->base_addr),
1107 		       EMAC_DMAGRP_OPERATION_MODE_ST_SET_MSK);
1108 
1109 	/* 3. Disable the EMAC transmitter and EMAC receiver by clearing Bit 3
1110 	 * (TE) and Bit 2 (RE) in Register 0 (MAC Configuration Register).
1111 	 */
1112 	sys_clear_bits(GMACGRP_MAC_CONFIG_ADDR(p->base_addr),
1113 		       EMAC_GMACGRP_MAC_CONFIGURATION_TE_SET_MSK);
1114 	sys_set_bits(EMAC_DMAGRP_OPERATION_MODE_ADDR(p->base_addr),
1115 		     EMAC_DMAGRP_OPERATION_MODE_FTF_SET_MSK); /* Flush Transmit FIFO */
1116 	sys_clear_bits(GMACGRP_MAC_CONFIG_ADDR(p->base_addr),
1117 		       EMAC_GMACGRP_MAC_CONFIGURATION_RE_SET_MSK);
1118 
1119 	/* 4. Disable the receive DMA (if applicable), after making sure that the data
1120 	 * in the RX FIFO buffer is transferred to the system memory
1121 	 * (by reading Register 9 (Debug Register).
1122 	 */
1123 
1124 	sys_clear_bits(EMAC_DMAGRP_OPERATION_MODE_ADDR(p->base_addr),
1125 		       EMAC_DMAGRP_OPERATION_MODE_SR_SET_MSK);
1126 
1127 	/* 5. Make sure that both the TX FIFO buffer and RX FIFO buffer are empty. */
1128 
1129 	if (EMAC_DMAGRP_DEBUG_RXFSTS_GET(
1130 		    sys_read32(EMAC_DMAGRP_DEBUG_ADDR(p->base_addr))) != 0x0) {
1131 		return -1;
1132 	}
1133 
1134 	p->running = 0;
1135 	LOG_DBG("Stopping Device...");
1136 	return 0;
1137 }
1138 
1139 const struct ethernet_api eth_cyclonev_api = {.iface_api.init = eth_cyclonev_iface_init,
1140 					      .get_capabilities = eth_cyclonev_caps,
1141 					      .send = eth_cyclonev_send,
1142 					      .start = eth_cyclonev_start,
1143 					      .stop = eth_cyclonev_stop,
1144 					      .set_config = eth_cyclonev_set_config};
1145 
1146 #define CYCLONEV_ETH_INIT(inst) \
1147 	static struct eth_cyclonev_priv eth_cyclonev_##inst##_data; \
1148 	static void eth_cyclonev_##inst##_irq_config(void); \
1149  \
1150 	static const struct eth_cyclonev_config eth_cyclonev_##inst##_cfg = { \
1151 			.base = (uint8_t *)(DT_INST_REG_ADDR(inst)), \
1152 			.size = DT_INST_REG_SIZE(inst), \
1153 			.emac_index = DT_INST_PROP(inst, emac_index), \
1154 			.irq_config = eth_cyclonev_##inst##_irq_config, \
1155 	}; \
1156 	ETH_NET_DEVICE_DT_INST_DEFINE(inst, eth_cyclonev_probe, NULL, \
1157 			&eth_cyclonev_##inst##_data, \
1158 			&eth_cyclonev_##inst##_cfg, \
1159 			CONFIG_ETH_INIT_PRIORITY, \
1160 			&eth_cyclonev_api, \
1161 			NET_ETH_MTU); \
1162  \
1163 	static void eth_cyclonev_##inst##_irq_config(void) \
1164 	{ \
1165 		IRQ_CONNECT(DT_INST_IRQN(inst), \
1166 			    DT_INST_IRQ(inst, priority), eth_cyclonev_isr, \
1167 			    DEVICE_DT_INST_GET(inst), \
1168 			    0); \
1169 		irq_enable(DT_INST_IRQN(inst)); \
1170 DT_INST_FOREACH_STATUS_OKAY(CYCLONEV_ETH_INIT)
1171