1 /*
2  * Copyright (c) 2017 Erwin Rol <erwin@erwinrol.com>
3  * Copyright (c) 2020 Alexander Kozhinov <ak.alexander.kozhinov@gmail.com>
4  * Copyright (c) 2021 Carbon Robotics
5  * SPDX-License-Identifier: Apache-2.0
6  */
7 
8 #define DT_DRV_COMPAT st_stm32_ethernet
9 
10 #define LOG_MODULE_NAME eth_stm32_hal
11 #define LOG_LEVEL CONFIG_ETHERNET_LOG_LEVEL
12 
13 #include <zephyr/logging/log.h>
14 LOG_MODULE_REGISTER(LOG_MODULE_NAME);
15 
16 #include <zephyr/kernel.h>
17 #include <zephyr/device.h>
18 #include <zephyr/sys/__assert.h>
19 #include <zephyr/sys/util.h>
20 #include <zephyr/sys/crc.h>
21 #include <errno.h>
22 #include <stdbool.h>
23 #include <zephyr/net/net_pkt.h>
24 #include <zephyr/net/net_if.h>
25 #include <zephyr/net/ethernet.h>
26 #include <zephyr/net/phy.h>
27 #include <ethernet/eth_stats.h>
28 #include <soc.h>
29 #include <zephyr/sys/printk.h>
30 #include <zephyr/drivers/clock_control.h>
31 #include <zephyr/drivers/clock_control/stm32_clock_control.h>
32 #include <zephyr/drivers/pinctrl.h>
33 #include <zephyr/irq.h>
34 #include <zephyr/net/lldp.h>
35 #include <zephyr/drivers/hwinfo.h>
36 
37 #if defined(CONFIG_NET_DSA)
38 #include <zephyr/net/dsa.h>
39 #endif
40 
41 #if defined(CONFIG_PTP_CLOCK_STM32_HAL)
42 #include <zephyr/drivers/ptp_clock.h>
43 #endif /* CONFIG_PTP_CLOCK_STM32_HAL */
44 
45 #include "eth.h"
46 #include "eth_stm32_hal_priv.h"
47 
48 #if DT_INST_PROP(0, zephyr_random_mac_address)
49 #define ETH_STM32_RANDOM_MAC
50 #endif
51 
52 #if defined(CONFIG_ETH_STM32_HAL_USE_DTCM_FOR_DMA_BUFFER) && \
53 	    !DT_NODE_HAS_STATUS_OKAY(DT_CHOSEN(zephyr_dtcm))
54 #error DTCM for DMA buffer is activated but zephyr,dtcm is not present in dts
55 #endif
56 
57 #define PHY_ADDR	CONFIG_ETH_STM32_HAL_PHY_ADDRESS
58 
59 #if defined(CONFIG_ETH_STM32_HAL_API_V2)
60 #define PHY_SCSR               ((uint16_t)0x001FU) /*!< PHY Special Control/Status */
61 #define PHY_SCSR_AUTONEGO_DONE ((uint16_t)0x1000U) /*!< Auto-Negotiation Done Status */
62 #define PHY_HCDSPEEDMASK       ((uint16_t)0x001CU) /*!< High Capability Speed Mask */
63 #define PHY_10BT_HD            ((uint16_t)0x0004U) /*!< 10Base-T half-duplex */
64 #define PHY_10BT_FD            ((uint16_t)0x0014U) /*!< 10Base-T full-duplex */
65 #define PHY_100BTX_HD          ((uint16_t)0x0008U) /*!< 100Base-TX half-duplex */
66 #define PHY_100BTX_FD          ((uint16_t)0x0018U) /*!< 100Base-TX full-duplex */
67 #define PHY_AUTONEGO_ENABLE    ((uint16_t)0x1000U) /*!< Auto-negotiation enable bit */
68 #define PHY_TIMEOUT            (5000U)             /*!< PHY operation timeout in msec */
69 
70 #define PHY_STATUS_LINK_DOWN           ((int32_t)1) /*!< Link down status */
71 #define PHY_STATUS_100MBITS_FULLDUPLEX ((int32_t)2) /*!< 100 Mbps full-duplex status */
72 #define PHY_STATUS_100MBITS_HALFDUPLEX ((int32_t)3) /*!< 100 Mbps half-duplex status */
73 #define PHY_STATUS_10MBITS_FULLDUPLEX  ((int32_t)4) /*!< 10 Mbps full-duplex status */
74 #define PHY_STATUS_10MBITS_HALFDUPLEX  ((int32_t)5) /*!< 10 Mbps half-duplex status */
75 #define PHY_STATUS_AUTONEGO_NOTDONE    ((int32_t)6) /*!< Auto-negotiation not done */
76 #endif
77 
78 #if DT_HAS_COMPAT_STATUS_OKAY(st_stm32_mdio)
79 
80 #define DEVICE_PHY_BY_NAME(n) \
81 	    DEVICE_DT_GET(DT_CHILD(DT_INST_CHILD(n, mdio), _CONCAT(ethernet_phy_, PHY_ADDR)))
82 
83 static const struct device *eth_stm32_phy_dev = DEVICE_PHY_BY_NAME(0);
84 
85 #endif
86 
87 #if DT_HAS_COMPAT_STATUS_OKAY(st_stm32h7_ethernet)
88 
89 #define PHY_BCR           ((uint16_t)0x0000U) /*!< Transceiver Basic Control Register */
90 #define PHY_BSR           ((uint16_t)0x0001U) /*!< Transceiver Basic Status Register */
91 #define PHY_LINKED_STATUS ((uint16_t)0x0004U) /*!< Valid link established */
92 
93 #define IS_ETH_DMATXDESC_OWN(dma_tx_desc)	(dma_tx_desc->DESC3 & \
94 							ETH_DMATXNDESCRF_OWN)
95 
96 #define ETH_RXBUFNB	ETH_RX_DESC_CNT
97 #define ETH_TXBUFNB	ETH_TX_DESC_CNT
98 
99 #define ETH_MEDIA_INTERFACE_MII		HAL_ETH_MII_MODE
100 #define ETH_MEDIA_INTERFACE_RMII	HAL_ETH_RMII_MODE
101 
102 /* Only one tx_buffer is sufficient to pass only 1 dma_buffer */
103 #define ETH_TXBUF_DEF_NB	1U
104 #else
105 
106 #define IS_ETH_DMATXDESC_OWN(dma_tx_desc)	(dma_tx_desc->Status & \
107 							ETH_DMATXDESC_OWN)
108 
109 #endif /* DT_HAS_COMPAT_STATUS_OKAY(st_stm32h7_ethernet) */
110 
111 #define MAC_NODE DT_NODELABEL(mac)
112 
113 #define STM32_ETH_PHY_MODE(node_id) \
114 	(DT_ENUM_HAS_VALUE(node_id, phy_connection_type, mii) ? \
115 		ETH_MEDIA_INTERFACE_MII : ETH_MEDIA_INTERFACE_RMII)
116 
117 #define ETH_DMA_TX_TIMEOUT_MS	20U  /* transmit timeout in milliseconds */
118 
119 #if defined(CONFIG_ETH_STM32_HAL_USE_DTCM_FOR_DMA_BUFFER) && \
120 	    DT_NODE_HAS_STATUS_OKAY(DT_CHOSEN(zephyr_dtcm))
121 #define __eth_stm32_desc __dtcm_noinit_section
122 #define __eth_stm32_buf  __dtcm_noinit_section
123 #elif defined(CONFIG_SOC_SERIES_STM32H7X)
124 #define __eth_stm32_desc __attribute__((section(".eth_stm32_desc")))
125 #define __eth_stm32_buf  __attribute__((section(".eth_stm32_buf")))
126 #elif defined(CONFIG_NOCACHE_MEMORY)
127 #define __eth_stm32_desc __nocache __aligned(4)
128 #define __eth_stm32_buf  __nocache __aligned(4)
129 #else
130 #define __eth_stm32_desc __aligned(4)
131 #define __eth_stm32_buf  __aligned(4)
132 #endif
133 
134 #if DT_HAS_COMPAT_STATUS_OKAY(st_stm32n6_ethernet)
135 static ETH_DMADescTypeDef
136 	dma_rx_desc_tab[ETH_DMA_RX_CH_CNT][ETH_RXBUFNB] ALIGN_32BYTES(__eth_stm32_desc);
137 static ETH_DMADescTypeDef
138 	dma_tx_desc_tab[ETH_DMA_TX_CH_CNT][ETH_TXBUFNB] ALIGN_32BYTES(__eth_stm32_desc);
139 #else
140 static ETH_DMADescTypeDef dma_rx_desc_tab[ETH_RXBUFNB] __eth_stm32_desc;
141 static ETH_DMADescTypeDef dma_tx_desc_tab[ETH_TXBUFNB] __eth_stm32_desc;
142 #endif
143 
144 static uint8_t dma_rx_buffer[ETH_RXBUFNB][ETH_STM32_RX_BUF_SIZE] __eth_stm32_buf;
145 static uint8_t dma_tx_buffer[ETH_TXBUFNB][ETH_STM32_TX_BUF_SIZE] __eth_stm32_buf;
146 
147 #if defined(CONFIG_ETH_STM32_HAL_API_V2)
148 
149 BUILD_ASSERT(ETH_STM32_RX_BUF_SIZE % 4 == 0, "Rx buffer size must be a multiple of 4");
150 
151 struct eth_stm32_rx_buffer_header {
152 	struct eth_stm32_rx_buffer_header *next;
153 	uint16_t size;
154 	bool used;
155 };
156 
157 struct eth_stm32_tx_buffer_header {
158 	ETH_BufferTypeDef tx_buff;
159 	bool used;
160 };
161 
162 struct eth_stm32_tx_context {
163 	struct net_pkt *pkt;
164 	uint16_t first_tx_buffer_index;
165 	bool used;
166 };
167 
168 static struct eth_stm32_rx_buffer_header dma_rx_buffer_header[ETH_RXBUFNB];
169 static struct eth_stm32_tx_buffer_header dma_tx_buffer_header[ETH_TXBUFNB];
170 static struct eth_stm32_tx_context dma_tx_context[ETH_TX_DESC_CNT];
171 
HAL_ETH_RxAllocateCallback(uint8_t ** buf)172 void HAL_ETH_RxAllocateCallback(uint8_t **buf)
173 {
174 	for (size_t i = 0; i < ETH_RXBUFNB; ++i) {
175 		if (!dma_rx_buffer_header[i].used) {
176 			dma_rx_buffer_header[i].next = NULL;
177 			dma_rx_buffer_header[i].size = 0;
178 			dma_rx_buffer_header[i].used = true;
179 			*buf = dma_rx_buffer[i];
180 			return;
181 		}
182 	}
183 	*buf = NULL;
184 }
185 
186 /* Pointer to an array of ETH_STM32_RX_BUF_SIZE uint8_t's */
187 typedef uint8_t (*RxBufferPtr)[ETH_STM32_RX_BUF_SIZE];
188 
189 /* called by HAL_ETH_ReadData() */
HAL_ETH_RxLinkCallback(void ** pStart,void ** pEnd,uint8_t * buff,uint16_t Length)190 void HAL_ETH_RxLinkCallback(void **pStart, void **pEnd, uint8_t *buff, uint16_t Length)
191 {
192 	/* buff points to the begin on one of the rx buffers,
193 	 * so we can compute the index of the given buffer
194 	 */
195 	size_t index = (RxBufferPtr)buff - &dma_rx_buffer[0];
196 	struct eth_stm32_rx_buffer_header *header = &dma_rx_buffer_header[index];
197 
198 	__ASSERT_NO_MSG(index < ETH_RXBUFNB);
199 
200 	header->size = Length;
201 
202 	if (!*pStart) {
203 		/* first packet, set head pointer of linked list */
204 		*pStart = header;
205 		*pEnd = header;
206 	} else {
207 		__ASSERT_NO_MSG(*pEnd != NULL);
208 		/* not the first packet, add to list and adjust tail pointer */
209 		((struct eth_stm32_rx_buffer_header *)*pEnd)->next = header;
210 		*pEnd = header;
211 	}
212 }
213 
214 /* Called by HAL_ETH_ReleaseTxPacket */
HAL_ETH_TxFreeCallback(uint32_t * buff)215 void HAL_ETH_TxFreeCallback(uint32_t *buff)
216 {
217 	__ASSERT_NO_MSG(buff != NULL);
218 
219 	/* buff is the user context in tx_config.pData */
220 	struct eth_stm32_tx_context *ctx = (struct eth_stm32_tx_context *)buff;
221 	struct eth_stm32_tx_buffer_header *buffer_header =
222 		&dma_tx_buffer_header[ctx->first_tx_buffer_index];
223 
224 	while (buffer_header != NULL) {
225 		buffer_header->used = false;
226 		if (buffer_header->tx_buff.next != NULL) {
227 			buffer_header = CONTAINER_OF(buffer_header->tx_buff.next,
228 				struct eth_stm32_tx_buffer_header, tx_buff);
229 		} else {
230 			buffer_header = NULL;
231 		}
232 	}
233 	ctx->used = false;
234 }
235 
236 /* allocate a tx buffer and mark it as used */
allocate_tx_buffer(void)237 static inline uint16_t allocate_tx_buffer(void)
238 {
239 	for (;;) {
240 		for (uint16_t index = 0; index < ETH_TXBUFNB; index++) {
241 			if (!dma_tx_buffer_header[index].used) {
242 				dma_tx_buffer_header[index].used = true;
243 				return index;
244 			}
245 		}
246 		k_yield();
247 	}
248 }
249 
250 /* allocate a tx context and mark it as used, the first tx buffer is also allocated */
allocate_tx_context(struct net_pkt * pkt)251 static inline struct eth_stm32_tx_context *allocate_tx_context(struct net_pkt *pkt)
252 {
253 	for (;;) {
254 		for (uint16_t index = 0; index < ETH_TX_DESC_CNT; index++) {
255 			if (!dma_tx_context[index].used) {
256 				dma_tx_context[index].used = true;
257 				dma_tx_context[index].pkt = pkt;
258 				dma_tx_context[index].first_tx_buffer_index = allocate_tx_buffer();
259 				return &dma_tx_context[index];
260 			}
261 		}
262 		k_yield();
263 	}
264 }
265 #endif /* CONFIG_ETH_STM32_HAL_API_V2 */
266 
267 #if defined(CONFIG_ETH_STM32_HAL_API_V2)
268 static ETH_TxPacketConfig tx_config;
269 #endif
270 
read_eth_phy_register(ETH_HandleTypeDef * heth,uint32_t PHYAddr,uint32_t PHYReg,uint32_t * RegVal)271 static HAL_StatusTypeDef read_eth_phy_register(ETH_HandleTypeDef *heth,
272 						uint32_t PHYAddr,
273 						uint32_t PHYReg,
274 						uint32_t *RegVal)
275 {
276 #if DT_HAS_COMPAT_STATUS_OKAY(st_stm32_mdio)
277 	return phy_read(eth_stm32_phy_dev, PHYReg, RegVal);
278 #elif defined(CONFIG_ETH_STM32_HAL_API_V2)
279 	return HAL_ETH_ReadPHYRegister(heth, PHYAddr, PHYReg, RegVal);
280 #else
281 	ARG_UNUSED(PHYAddr);
282 	return HAL_ETH_ReadPHYRegister(heth, PHYReg, RegVal);
283 #endif /* CONFIG_ETH_STM32_HAL_API_V2 */
284 }
285 
setup_mac_filter(ETH_HandleTypeDef * heth)286 static inline void setup_mac_filter(ETH_HandleTypeDef *heth)
287 {
288 	__ASSERT_NO_MSG(heth != NULL);
289 
290 #if DT_HAS_COMPAT_STATUS_OKAY(st_stm32h7_ethernet)
291 	ETH_MACFilterConfigTypeDef MACFilterConf;
292 
293 	HAL_ETH_GetMACFilterConfig(heth, &MACFilterConf);
294 #if defined(CONFIG_ETH_STM32_MULTICAST_FILTER)
295 	MACFilterConf.HashMulticast = ENABLE;
296 	MACFilterConf.PassAllMulticast = DISABLE;
297 #else
298 	MACFilterConf.HashMulticast = DISABLE;
299 	MACFilterConf.PassAllMulticast = ENABLE;
300 #endif /* CONFIG_ETH_STM32_MULTICAST_FILTER */
301 	MACFilterConf.HachOrPerfectFilter = DISABLE;
302 
303 	HAL_ETH_SetMACFilterConfig(heth, &MACFilterConf);
304 
305 	k_sleep(K_MSEC(1));
306 #else
307 	uint32_t tmp = heth->Instance->MACFFR;
308 
309 	/* clear all multicast filter bits, resulting in perfect filtering */
310 	tmp &= ~(ETH_MULTICASTFRAMESFILTER_PERFECTHASHTABLE |
311 		 ETH_MULTICASTFRAMESFILTER_HASHTABLE |
312 		 ETH_MULTICASTFRAMESFILTER_PERFECT |
313 		 ETH_MULTICASTFRAMESFILTER_NONE);
314 
315 	if (IS_ENABLED(CONFIG_ETH_STM32_MULTICAST_FILTER)) {
316 		/* enable multicast hash receive filter */
317 		tmp |= ETH_MULTICASTFRAMESFILTER_HASHTABLE;
318 	} else {
319 		/* enable receiving all multicast frames */
320 		tmp |= ETH_MULTICASTFRAMESFILTER_NONE;
321 	}
322 
323 	heth->Instance->MACFFR = tmp;
324 
325 	/* Wait until the write operation will be taken into account:
326 	 * at least four TX_CLK/RX_CLK clock cycles
327 	 */
328 	tmp = heth->Instance->MACFFR;
329 	k_sleep(K_MSEC(1));
330 	heth->Instance->MACFFR = tmp;
331 #endif /* DT_HAS_COMPAT_STATUS_OKAY(st_stm32h7_ethernet) */
332 }
333 
334 #if defined(CONFIG_PTP_CLOCK_STM32_HAL)
eth_is_ptp_pkt(struct net_if * iface,struct net_pkt * pkt)335 static bool eth_is_ptp_pkt(struct net_if *iface, struct net_pkt *pkt)
336 {
337 	if (ntohs(NET_ETH_HDR(pkt)->type) != NET_ETH_PTYPE_PTP) {
338 		return false;
339 	}
340 
341 	net_pkt_set_priority(pkt, NET_PRIORITY_CA);
342 
343 	return true;
344 }
345 #if defined(CONFIG_ETH_STM32_HAL_API_V2)
HAL_ETH_TxPtpCallback(uint32_t * buff,ETH_TimeStampTypeDef * timestamp)346 void HAL_ETH_TxPtpCallback(uint32_t *buff, ETH_TimeStampTypeDef *timestamp)
347 {
348 	struct eth_stm32_tx_context *ctx = (struct eth_stm32_tx_context *)buff;
349 
350 	ctx->pkt->timestamp.second = timestamp->TimeStampHigh;
351 	ctx->pkt->timestamp.nanosecond = timestamp->TimeStampLow;
352 
353 	net_if_add_tx_timestamp(ctx->pkt);
354 }
355 #endif /* CONFIG_ETH_STM32_HAL_API_V2 */
356 #endif /* CONFIG_PTP_CLOCK_STM32_HAL */
357 
eth_tx(const struct device * dev,struct net_pkt * pkt)358 static int eth_tx(const struct device *dev, struct net_pkt *pkt)
359 {
360 	struct eth_stm32_hal_dev_data *dev_data = dev->data;
361 	ETH_HandleTypeDef *heth;
362 	int res;
363 	size_t total_len;
364 #if defined(CONFIG_ETH_STM32_HAL_API_V2)
365 	size_t remaining_read;
366 	struct eth_stm32_tx_context *ctx = NULL;
367 	struct eth_stm32_tx_buffer_header *buf_header = NULL;
368 #else
369 	uint8_t *dma_buffer;
370 	__IO ETH_DMADescTypeDef *dma_tx_desc;
371 #endif /* CONFIG_ETH_STM32_HAL_API_V2 */
372 	HAL_StatusTypeDef hal_ret = HAL_OK;
373 #if defined(CONFIG_PTP_CLOCK_STM32_HAL)
374 	bool timestamped_frame;
375 #endif /* CONFIG_PTP_CLOCK_STM32_HAL */
376 
377 	__ASSERT_NO_MSG(pkt != NULL);
378 	__ASSERT_NO_MSG(pkt->frags != NULL);
379 	__ASSERT_NO_MSG(dev != NULL);
380 	__ASSERT_NO_MSG(dev_data != NULL);
381 
382 	heth = &dev_data->heth;
383 
384 	total_len = net_pkt_get_len(pkt);
385 	if (total_len > (ETH_STM32_TX_BUF_SIZE * ETH_TXBUFNB)) {
386 		LOG_ERR("PKT too big");
387 		return -EIO;
388 	}
389 
390 	k_mutex_lock(&dev_data->tx_mutex, K_FOREVER);
391 
392 #if defined(CONFIG_ETH_STM32_HAL_API_V2)
393 	ctx = allocate_tx_context(pkt);
394 	buf_header = &dma_tx_buffer_header[ctx->first_tx_buffer_index];
395 #else
396 	dma_tx_desc = heth->TxDesc;
397 	while (IS_ETH_DMATXDESC_OWN(dma_tx_desc) != (uint32_t)RESET) {
398 		k_yield();
399 	}
400 #endif /* CONFIG_ETH_STM32_HAL_API_V2 */
401 
402 #if defined(CONFIG_PTP_CLOCK_STM32_HAL)
403 	timestamped_frame = eth_is_ptp_pkt(net_pkt_iface(pkt), pkt) ||
404 			    net_pkt_is_tx_timestamping(pkt);
405 	if (timestamped_frame) {
406 		/* Enable transmit timestamp */
407 #if defined(CONFIG_ETH_STM32_HAL_API_V2)
408 		HAL_ETH_PTP_InsertTxTimestamp(heth);
409 #else
410 		dma_tx_desc->Status |= ETH_DMATXDESC_TTSE;
411 #endif /* CONFIG_ETH_STM32_HAL_API_V2 */
412 	}
413 #endif /* CONFIG_PTP_CLOCK_STM32_HAL */
414 
415 #if defined(CONFIG_ETH_STM32_HAL_API_V2)
416 	remaining_read = total_len;
417 	/* fill and allocate buffer until remaining data fits in one buffer */
418 	while (remaining_read > ETH_STM32_TX_BUF_SIZE) {
419 		if (net_pkt_read(pkt, buf_header->tx_buff.buffer, ETH_STM32_TX_BUF_SIZE)) {
420 			res = -ENOBUFS;
421 			goto error;
422 		}
423 		const uint16_t next_buffer_id = allocate_tx_buffer();
424 
425 		buf_header->tx_buff.len = ETH_STM32_TX_BUF_SIZE;
426 		/* append new buffer to the linked list */
427 		buf_header->tx_buff.next = &dma_tx_buffer_header[next_buffer_id].tx_buff;
428 		/* and adjust tail pointer */
429 		buf_header = &dma_tx_buffer_header[next_buffer_id];
430 		remaining_read -= ETH_STM32_TX_BUF_SIZE;
431 	}
432 	if (net_pkt_read(pkt, buf_header->tx_buff.buffer, remaining_read)) {
433 		res = -ENOBUFS;
434 		goto error;
435 	}
436 	buf_header->tx_buff.len = remaining_read;
437 	buf_header->tx_buff.next = NULL;
438 
439 #else
440 	dma_buffer = (uint8_t *)(dma_tx_desc->Buffer1Addr);
441 
442 	if (net_pkt_read(pkt, dma_buffer, total_len)) {
443 		res = -ENOBUFS;
444 		goto error;
445 	}
446 #endif /* CONFIG_ETH_STM32_HAL_API_V2 */
447 
448 #if defined(CONFIG_ETH_STM32_HAL_API_V2)
449 	tx_config.Length = total_len;
450 	tx_config.pData = ctx;
451 	tx_config.TxBuffer = &dma_tx_buffer_header[ctx->first_tx_buffer_index].tx_buff;
452 
453 	/* Reset TX complete interrupt semaphore before TX request*/
454 	k_sem_reset(&dev_data->tx_int_sem);
455 
456 	/* tx_buffer is allocated on function stack, we need */
457 	/* to wait for the transfer to complete */
458 	/* So it is not freed before the interrupt happens */
459 	hal_ret = HAL_ETH_Transmit_IT(heth, &tx_config);
460 
461 	if (hal_ret != HAL_OK) {
462 		LOG_ERR("HAL_ETH_Transmit: failed!");
463 		res = -EIO;
464 		goto error;
465 	}
466 
467 	/* the tx context is now owned by the HAL */
468 	ctx = NULL;
469 
470 	/* Wait for end of TX buffer transmission */
471 	/* If the semaphore timeout breaks, it means */
472 	/* an error occurred or IT was not fired */
473 	if (k_sem_take(&dev_data->tx_int_sem,
474 			K_MSEC(ETH_DMA_TX_TIMEOUT_MS)) != 0) {
475 
476 		LOG_ERR("HAL_ETH_TransmitIT tx_int_sem take timeout");
477 		res = -EIO;
478 
479 		/* Check for errors */
480 		/* Ethernet device was put in error state */
481 		/* Error state is unrecoverable ? */
482 		if (HAL_ETH_GetState(heth) == HAL_ETH_STATE_ERROR) {
483 			LOG_ERR("%s: ETH in error state: errorcode:%x",
484 				__func__,
485 				HAL_ETH_GetError(heth));
486 			/* TODO recover from error state by restarting eth */
487 		}
488 
489 		/* Check for DMA errors */
490 		if (HAL_ETH_GetDMAError(heth)) {
491 			LOG_ERR("%s: ETH DMA error: dmaerror:%x",
492 				__func__,
493 				HAL_ETH_GetDMAError(heth));
494 			/* DMA fatal bus errors are putting in error state*/
495 			/* TODO recover from this */
496 		}
497 
498 		/* Check for MAC errors */
499 		if (HAL_ETH_GetMACError(heth)) {
500 			LOG_ERR("%s: ETH MAC error: macerror:%x",
501 				__func__,
502 				HAL_ETH_GetMACError(heth));
503 			/* MAC errors are putting in error state*/
504 			/* TODO recover from this */
505 		}
506 
507 		goto error;
508 	}
509 
510 #else
511 	hal_ret = HAL_ETH_TransmitFrame(heth, total_len);
512 
513 	if (hal_ret != HAL_OK) {
514 		LOG_ERR("HAL_ETH_Transmit: failed!");
515 		res = -EIO;
516 		goto error;
517 	}
518 
519 	/* When Transmit Underflow flag is set, clear it and issue a
520 	 * Transmit Poll Demand to resume transmission.
521 	 */
522 	if ((heth->Instance->DMASR & ETH_DMASR_TUS) != (uint32_t)RESET) {
523 		/* Clear TUS ETHERNET DMA flag */
524 		heth->Instance->DMASR = ETH_DMASR_TUS;
525 		/* Resume DMA transmission*/
526 		heth->Instance->DMATPDR = 0;
527 		res = -EIO;
528 		goto error;
529 	}
530 #endif /* CONFIG_ETH_STM32_HAL_API_V2 */
531 
532 #if defined(CONFIG_PTP_CLOCK_STM32_HAL) && !defined(CONFIG_ETH_STM32_HAL_API_V2)
533 	if (timestamped_frame) {
534 		/* Retrieve transmission timestamp from last DMA TX descriptor */
535 		__IO ETH_DMADescTypeDef *last_dma_tx_desc = dma_tx_desc;
536 
537 		while (!(last_dma_tx_desc->Status & ETH_DMATXDESC_LS) &&
538 				last_dma_tx_desc->Buffer2NextDescAddr) {
539 			last_dma_tx_desc =
540 				(ETH_DMADescTypeDef *)last_dma_tx_desc->Buffer2NextDescAddr;
541 		}
542 
543 		while (IS_ETH_DMATXDESC_OWN(last_dma_tx_desc) != (uint32_t)RESET) {
544 			/* Wait for transmission */
545 			k_yield();
546 		}
547 
548 		if (last_dma_tx_desc->Status & ETH_DMATXDESC_LS &&
549 				last_dma_tx_desc->Status & ETH_DMATXDESC_TTSS) {
550 			pkt->timestamp.second = last_dma_tx_desc->TimeStampHigh;
551 			pkt->timestamp.nanosecond = last_dma_tx_desc->TimeStampLow;
552 		} else {
553 			/* Invalid value */
554 			pkt->timestamp.second = UINT64_MAX;
555 			pkt->timestamp.nanosecond = UINT32_MAX;
556 		}
557 		net_if_add_tx_timestamp(pkt);
558 	}
559 #endif /* CONFIG_PTP_CLOCK_STM32_HAL && !CONFIG_ETH_STM32_HAL_API_V2 */
560 
561 	res = 0;
562 error:
563 
564 #if defined(CONFIG_ETH_STM32_HAL_API_V2)
565 	if (!ctx) {
566 		/* The HAL owns the tx context */
567 		HAL_ETH_ReleaseTxPacket(heth);
568 	} else {
569 		/* We need to release the tx context and its buffers */
570 		HAL_ETH_TxFreeCallback((uint32_t *)ctx);
571 	}
572 #endif /* CONFIG_ETH_STM32_HAL_API_V2 */
573 
574 	k_mutex_unlock(&dev_data->tx_mutex);
575 
576 	return res;
577 }
578 
get_iface(struct eth_stm32_hal_dev_data * ctx)579 static struct net_if *get_iface(struct eth_stm32_hal_dev_data *ctx)
580 {
581 	return ctx->iface;
582 }
583 
eth_rx(const struct device * dev)584 static struct net_pkt *eth_rx(const struct device *dev)
585 {
586 	struct eth_stm32_hal_dev_data *dev_data;
587 	ETH_HandleTypeDef *heth;
588 	struct net_pkt *pkt;
589 	size_t total_len = 0;
590 #if defined(CONFIG_ETH_STM32_HAL_API_V2)
591 	void *appbuf = NULL;
592 	struct eth_stm32_rx_buffer_header *rx_header;
593 #else
594 	__IO ETH_DMADescTypeDef *dma_rx_desc;
595 	uint8_t *dma_buffer;
596 	HAL_StatusTypeDef hal_ret = HAL_OK;
597 #endif /* CONFIG_ETH_STM32_HAL_API_V2 */
598 #if defined(CONFIG_PTP_CLOCK_STM32_HAL)
599 	struct net_ptp_time timestamp;
600 #if defined(CONFIG_ETH_STM32_HAL_API_V2)
601 	ETH_TimeStampTypeDef ts_registers;
602 #endif /* CONFIG_ETH_STM32_HAL_API_V2 */
603 	/* Default to invalid value. */
604 	timestamp.second = UINT64_MAX;
605 	timestamp.nanosecond = UINT32_MAX;
606 #endif /* CONFIG_PTP_CLOCK_STM32_HAL */
607 
608 	__ASSERT_NO_MSG(dev != NULL);
609 
610 	dev_data = dev->data;
611 
612 	__ASSERT_NO_MSG(dev_data != NULL);
613 
614 	heth = &dev_data->heth;
615 
616 #if defined(CONFIG_ETH_STM32_HAL_API_V2)
617 	if (HAL_ETH_ReadData(heth, &appbuf) != HAL_OK) {
618 		/* no frame available */
619 		return NULL;
620 	}
621 
622 	/* computing total length */
623 	for (rx_header = (struct eth_stm32_rx_buffer_header *)appbuf;
624 			rx_header; rx_header = rx_header->next) {
625 		total_len += rx_header->size;
626 	}
627 #else
628 	hal_ret = HAL_ETH_GetReceivedFrame_IT(heth);
629 	if (hal_ret != HAL_OK) {
630 		/* no frame available */
631 		return NULL;
632 	}
633 
634 	total_len = heth->RxFrameInfos.length;
635 	dma_buffer = (uint8_t *)heth->RxFrameInfos.buffer;
636 #endif /* CONFIG_ETH_STM32_HAL_API_V2 */
637 
638 #if defined(CONFIG_PTP_CLOCK_STM32_HAL)
639 #if defined(CONFIG_ETH_STM32_HAL_API_V2)
640 
641 	if (HAL_ETH_PTP_GetRxTimestamp(heth, &ts_registers) == HAL_OK) {
642 		timestamp.second = ts_registers.TimeStampHigh;
643 		timestamp.nanosecond = ts_registers.TimeStampLow;
644 	}
645 #else
646 	__IO ETH_DMADescTypeDef *last_dma_rx_desc;
647 
648 	last_dma_rx_desc = heth->RxFrameInfos.LSRxDesc;
649 	if (last_dma_rx_desc->TimeStampHigh != UINT32_MAX ||
650 			last_dma_rx_desc->TimeStampLow != UINT32_MAX) {
651 		timestamp.second = last_dma_rx_desc->TimeStampHigh;
652 		timestamp.nanosecond = last_dma_rx_desc->TimeStampLow;
653 	}
654 #endif /* CONFIG_ETH_STM32_HAL_API_V2 */
655 #endif /* CONFIG_PTP_CLOCK_STM32_HAL */
656 
657 	pkt = net_pkt_rx_alloc_with_buffer(get_iface(dev_data),
658 					   total_len, AF_UNSPEC, 0, K_MSEC(100));
659 	if (!pkt) {
660 		LOG_ERR("Failed to obtain RX buffer");
661 		goto release_desc;
662 	}
663 
664 #if defined(CONFIG_ETH_STM32_HAL_API_V2)
665 	for (rx_header = (struct eth_stm32_rx_buffer_header *)appbuf;
666 			rx_header; rx_header = rx_header->next) {
667 		const size_t index = rx_header - &dma_rx_buffer_header[0];
668 
669 		__ASSERT_NO_MSG(index < ETH_RXBUFNB);
670 		if (net_pkt_write(pkt, dma_rx_buffer[index], rx_header->size)) {
671 			LOG_ERR("Failed to append RX buffer to context buffer");
672 			net_pkt_unref(pkt);
673 			pkt = NULL;
674 			goto release_desc;
675 		}
676 	}
677 #else
678 	if (net_pkt_write(pkt, dma_buffer, total_len)) {
679 		LOG_ERR("Failed to append RX buffer to context buffer");
680 		net_pkt_unref(pkt);
681 		pkt = NULL;
682 		goto release_desc;
683 	}
684 #endif /* CONFIG_ETH_STM32_HAL_API_V2 */
685 
686 release_desc:
687 #if defined(CONFIG_ETH_STM32_HAL_API_V2)
688 	for (rx_header = (struct eth_stm32_rx_buffer_header *)appbuf;
689 			rx_header; rx_header = rx_header->next) {
690 		rx_header->used = false;
691 	}
692 #else
693 	/* Release descriptors to DMA */
694 	/* Point to first descriptor */
695 	dma_rx_desc = heth->RxFrameInfos.FSRxDesc;
696 	/* Set Own bit in Rx descriptors: gives the buffers back to DMA */
697 	for (int i = 0; i < heth->RxFrameInfos.SegCount; i++) {
698 		dma_rx_desc->Status |= ETH_DMARXDESC_OWN;
699 		dma_rx_desc = (ETH_DMADescTypeDef *)
700 			(dma_rx_desc->Buffer2NextDescAddr);
701 	}
702 
703 	/* Clear Segment_Count */
704 	heth->RxFrameInfos.SegCount = 0;
705 
706 	/* When Rx Buffer unavailable flag is set: clear it
707 	 * and resume reception.
708 	 */
709 	if ((heth->Instance->DMASR & ETH_DMASR_RBUS) != (uint32_t)RESET) {
710 		/* Clear RBUS ETHERNET DMA flag */
711 		heth->Instance->DMASR = ETH_DMASR_RBUS;
712 		/* Resume DMA reception */
713 		heth->Instance->DMARPDR = 0;
714 	}
715 #endif /* CONFIG_ETH_STM32_HAL_API_V2 */
716 
717 	if (!pkt) {
718 		goto out;
719 	}
720 
721 #if defined(CONFIG_PTP_CLOCK_STM32_HAL)
722 	pkt->timestamp.second = timestamp.second;
723 	pkt->timestamp.nanosecond = timestamp.nanosecond;
724 	if (timestamp.second != UINT64_MAX) {
725 		net_pkt_set_rx_timestamping(pkt, true);
726 	}
727 #endif /* CONFIG_PTP_CLOCK_STM32_HAL */
728 
729 out:
730 	if (!pkt) {
731 		eth_stats_update_errors_rx(get_iface(dev_data));
732 	}
733 
734 	return pkt;
735 }
736 
rx_thread(void * arg1,void * unused1,void * unused2)737 static void rx_thread(void *arg1, void *unused1, void *unused2)
738 {
739 	const struct device *dev;
740 	struct eth_stm32_hal_dev_data *dev_data;
741 	struct net_if *iface;
742 	struct net_pkt *pkt;
743 	int res;
744 	uint32_t status;
745 	HAL_StatusTypeDef hal_ret = HAL_OK;
746 
747 	__ASSERT_NO_MSG(arg1 != NULL);
748 	ARG_UNUSED(unused1);
749 	ARG_UNUSED(unused2);
750 
751 	dev = (const struct device *)arg1;
752 	dev_data = dev->data;
753 
754 	__ASSERT_NO_MSG(dev_data != NULL);
755 
756 	while (1) {
757 		res = k_sem_take(
758 			&dev_data->rx_int_sem,
759 			COND_CODE_1(CONFIG_ETH_STM32_CARRIER_CHECK,
760 				(K_MSEC(CONFIG_ETH_STM32_CARRIER_CHECK_RX_IDLE_TIMEOUT_MS)),
761 				(K_FOREVER)));
762 		if (res == 0) {
763 			/* semaphore taken, update link status and receive packets */
764 			if (dev_data->link_up != true) {
765 				dev_data->link_up = true;
766 				net_eth_carrier_on(get_iface(dev_data));
767 			}
768 			while ((pkt = eth_rx(dev)) != NULL) {
769 				iface = net_pkt_iface(pkt);
770 #if defined(CONFIG_NET_DSA)
771 				iface = dsa_net_recv(iface, &pkt);
772 #endif
773 				res = net_recv_data(iface, pkt);
774 				if (res < 0) {
775 					eth_stats_update_errors_rx(
776 							net_pkt_iface(pkt));
777 					LOG_ERR("Failed to enqueue frame "
778 						"into RX queue: %d", res);
779 					net_pkt_unref(pkt);
780 				}
781 			}
782 		} else if (IS_ENABLED(CONFIG_ETH_STM32_CARRIER_CHECK) && res == -EAGAIN) {
783 			/* semaphore timeout period expired, check link status */
784 			hal_ret = read_eth_phy_register(&dev_data->heth,
785 				    PHY_ADDR, PHY_BSR, (uint32_t *) &status);
786 			if (hal_ret == HAL_OK) {
787 				if ((status & PHY_LINKED_STATUS) == PHY_LINKED_STATUS) {
788 					if (dev_data->link_up != true) {
789 						dev_data->link_up = true;
790 						net_eth_carrier_on(
791 							get_iface(dev_data));
792 					}
793 				} else {
794 					if (dev_data->link_up != false) {
795 						dev_data->link_up = false;
796 						net_eth_carrier_off(
797 							get_iface(dev_data));
798 					}
799 				}
800 			}
801 		}
802 	}
803 }
804 
eth_isr(const struct device * dev)805 static void eth_isr(const struct device *dev)
806 {
807 	struct eth_stm32_hal_dev_data *dev_data;
808 	ETH_HandleTypeDef *heth;
809 
810 	__ASSERT_NO_MSG(dev != NULL);
811 
812 	dev_data = dev->data;
813 
814 	__ASSERT_NO_MSG(dev_data != NULL);
815 
816 	heth = &dev_data->heth;
817 
818 	__ASSERT_NO_MSG(heth != NULL);
819 
820 	HAL_ETH_IRQHandler(heth);
821 }
822 #if defined(CONFIG_ETH_STM32_HAL_API_V2)
HAL_ETH_TxCpltCallback(ETH_HandleTypeDef * heth_handle)823 void HAL_ETH_TxCpltCallback(ETH_HandleTypeDef *heth_handle)
824 {
825 	__ASSERT_NO_MSG(heth_handle != NULL);
826 
827 	struct eth_stm32_hal_dev_data *dev_data =
828 		CONTAINER_OF(heth_handle, struct eth_stm32_hal_dev_data, heth);
829 
830 	__ASSERT_NO_MSG(dev_data != NULL);
831 
832 	k_sem_give(&dev_data->tx_int_sem);
833 
834 }
835 #endif /* CONFIG_ETH_STM32_HAL_API_V2 */
836 
837 #if defined(CONFIG_ETH_STM32_HAL_API_V2)
HAL_ETH_ErrorCallback(ETH_HandleTypeDef * heth)838 void HAL_ETH_ErrorCallback(ETH_HandleTypeDef *heth)
839 {
840 	/* Do not log errors. If errors are reported due to high traffic,
841 	 * logging errors will only increase traffic issues
842 	 */
843 #if defined(CONFIG_NET_STATISTICS_ETHERNET)
844 	__ASSERT_NO_MSG(heth != NULL);
845 
846 	uint32_t dma_error;
847 #if DT_HAS_COMPAT_STATUS_OKAY(st_stm32h7_ethernet)
848 	uint32_t mac_error;
849 #endif /* DT_HAS_COMPAT_STATUS_OKAY(st_stm32h7_ethernet) */
850 	const uint32_t error_code = HAL_ETH_GetError(heth);
851 
852 	struct eth_stm32_hal_dev_data *dev_data =
853 		CONTAINER_OF(heth, struct eth_stm32_hal_dev_data, heth);
854 
855 	switch (error_code) {
856 #if DT_HAS_COMPAT_STATUS_OKAY(st_stm32n6_ethernet)
857 	case HAL_ETH_ERROR_DMA_CH0:
858 	case HAL_ETH_ERROR_DMA_CH1:
859 #else
860 	case HAL_ETH_ERROR_DMA:
861 #endif
862 		dma_error = HAL_ETH_GetDMAError(heth);
863 
864 #if DT_HAS_COMPAT_STATUS_OKAY(st_stm32h7_ethernet)
865 		if ((dma_error & ETH_DMA_RX_WATCHDOG_TIMEOUT_FLAG)   ||
866 			(dma_error & ETH_DMA_RX_PROCESS_STOPPED_FLAG)    ||
867 			(dma_error & ETH_DMA_RX_BUFFER_UNAVAILABLE_FLAG)) {
868 			eth_stats_update_errors_rx(dev_data->iface);
869 		}
870 		if ((dma_error & ETH_DMA_EARLY_TX_IT_FLAG) ||
871 			(dma_error & ETH_DMA_TX_PROCESS_STOPPED_FLAG)) {
872 			eth_stats_update_errors_tx(dev_data->iface);
873 		}
874 #else
875 		if ((dma_error & ETH_DMASR_RWTS) ||
876 			(dma_error & ETH_DMASR_RPSS) ||
877 			(dma_error & ETH_DMASR_RBUS)) {
878 			eth_stats_update_errors_rx(dev_data->iface);
879 		}
880 		if ((dma_error & ETH_DMASR_ETS)  ||
881 			(dma_error & ETH_DMASR_TPSS) ||
882 			(dma_error & ETH_DMASR_TJTS)) {
883 			eth_stats_update_errors_tx(dev_data->iface);
884 		}
885 #endif /* DT_HAS_COMPAT_STATUS_OKAY(st_stm32h7_ethernet) */
886 		break;
887 
888 #if DT_HAS_COMPAT_STATUS_OKAY(st_stm32h7_ethernet)
889 	case HAL_ETH_ERROR_MAC:
890 		mac_error = HAL_ETH_GetMACError(heth);
891 
892 		if (mac_error & ETH_RECEIVE_WATCHDOG_TIMEOUT) {
893 			eth_stats_update_errors_rx(dev_data->iface);
894 		}
895 
896 		if ((mac_error & ETH_EXECESSIVE_COLLISIONS)  ||
897 			(mac_error & ETH_LATE_COLLISIONS)        ||
898 			(mac_error & ETH_EXECESSIVE_DEFERRAL)    ||
899 			(mac_error & ETH_TRANSMIT_JABBR_TIMEOUT) ||
900 			(mac_error & ETH_LOSS_OF_CARRIER)        ||
901 			(mac_error & ETH_NO_CARRIER)) {
902 			eth_stats_update_errors_tx(dev_data->iface);
903 		}
904 		break;
905 #endif /* DT_HAS_COMPAT_STATUS_OKAY(st_stm32h7_ethernet) */
906 	}
907 
908 #if DT_HAS_COMPAT_STATUS_OKAY(st_stm32h7_ethernet)
909 	dev_data->stats.error_details.rx_crc_errors = heth->Instance->MMCRCRCEPR;
910 	dev_data->stats.error_details.rx_align_errors = heth->Instance->MMCRAEPR;
911 #else
912 	dev_data->stats.error_details.rx_crc_errors = heth->Instance->MMCRFCECR;
913 	dev_data->stats.error_details.rx_align_errors = heth->Instance->MMCRFAECR;
914 #endif /* DT_HAS_COMPAT_STATUS_OKAY(st_stm32h7_ethernet) */
915 
916 #endif /* CONFIG_NET_STATISTICS_ETHERNET */
917 }
918 #endif /* CONFIG_ETH_STM32_HAL_API_V2 */
919 
HAL_ETH_RxCpltCallback(ETH_HandleTypeDef * heth_handle)920 void HAL_ETH_RxCpltCallback(ETH_HandleTypeDef *heth_handle)
921 {
922 	__ASSERT_NO_MSG(heth_handle != NULL);
923 
924 	struct eth_stm32_hal_dev_data *dev_data =
925 		CONTAINER_OF(heth_handle, struct eth_stm32_hal_dev_data, heth);
926 
927 	__ASSERT_NO_MSG(dev_data != NULL);
928 
929 	k_sem_give(&dev_data->rx_int_sem);
930 }
931 
generate_mac(uint8_t * mac_addr)932 static void generate_mac(uint8_t *mac_addr)
933 {
934 #if defined(ETH_STM32_RANDOM_MAC)
935 	/* "zephyr,random-mac-address" is set, generate a random mac address */
936 	gen_random_mac(mac_addr, ST_OUI_B0, ST_OUI_B1, ST_OUI_B2);
937 #else /* Use user defined mac address */
938 	mac_addr[0] = ST_OUI_B0;
939 	mac_addr[1] = ST_OUI_B1;
940 	mac_addr[2] = ST_OUI_B2;
941 #if NODE_HAS_VALID_MAC_ADDR(DT_DRV_INST(0))
942 	mac_addr[3] = NODE_MAC_ADDR_OCTET(DT_DRV_INST(0), 3);
943 	mac_addr[4] = NODE_MAC_ADDR_OCTET(DT_DRV_INST(0), 4);
944 	mac_addr[5] = NODE_MAC_ADDR_OCTET(DT_DRV_INST(0), 5);
945 #else
946 	uint8_t unique_device_ID_12_bytes[12];
947 	uint32_t result_mac_32_bits;
948 
949 	/* Nothing defined by the user, use device id */
950 	hwinfo_get_device_id(unique_device_ID_12_bytes, 12);
951 	result_mac_32_bits = crc32_ieee((uint8_t *)unique_device_ID_12_bytes, 12);
952 	memcpy(&mac_addr[3], &result_mac_32_bits, 3);
953 
954 #endif /* NODE_HAS_VALID_MAC_ADDR(DT_DRV_INST(0))) */
955 #endif
956 }
957 
958 #if DT_HAS_COMPAT_STATUS_OKAY(st_stm32n6_ethernet)
959 /**
960  * Configures the RISAF (RIF Security Attribute Framework) for Ethernet on STM32N6.
961  * This function sets up the master and slave security attributes for the Ethernet peripheral.
962  */
963 
RISAF_Config(void)964 static void RISAF_Config(void)
965 {
966 	/* Define and initialize the master configuration structure */
967 	RIMC_MasterConfig_t RIMC_master = {0};
968 
969 	/* Enable the clock for the RIFSC (RIF Security Controller) */
970 	__HAL_RCC_RIFSC_CLK_ENABLE();
971 
972 	RIMC_master.MasterCID = RIF_CID_1;
973 	RIMC_master.SecPriv = RIF_ATTRIBUTE_SEC | RIF_ATTRIBUTE_PRIV;
974 
975 	/* Configure the master attributes for the Ethernet peripheral (ETH1) */
976 	HAL_RIF_RIMC_ConfigMasterAttributes(RIF_MASTER_INDEX_ETH1, &RIMC_master);
977 
978 	/* Set the secure and privileged attributes for the Ethernet peripheral (ETH1) as a slave */
979 	HAL_RIF_RISC_SetSlaveSecureAttributes(RIF_RISC_PERIPH_INDEX_ETH1,
980 					      RIF_ATTRIBUTE_SEC | RIF_ATTRIBUTE_PRIV);
981 }
982 #endif
983 
eth_initialize(const struct device * dev)984 static int eth_initialize(const struct device *dev)
985 {
986 	struct eth_stm32_hal_dev_data *dev_data;
987 	const struct eth_stm32_hal_dev_cfg *cfg;
988 	ETH_HandleTypeDef *heth;
989 	int ret = 0;
990 
991 	__ASSERT_NO_MSG(dev != NULL);
992 
993 	dev_data = dev->data;
994 	cfg = dev->config;
995 
996 	__ASSERT_NO_MSG(dev_data != NULL);
997 	__ASSERT_NO_MSG(cfg != NULL);
998 
999 	dev_data->clock = DEVICE_DT_GET(STM32_CLOCK_CONTROL_NODE);
1000 
1001 	if (!device_is_ready(dev_data->clock)) {
1002 		LOG_ERR("clock control device not ready");
1003 		return -ENODEV;
1004 	}
1005 
1006 #if DT_HAS_COMPAT_STATUS_OKAY(st_stm32n6_ethernet)
1007 	/* RISAF Configuration */
1008 	RISAF_Config();
1009 #endif
1010 
1011 	/* enable clock */
1012 	ret = clock_control_on(dev_data->clock,
1013 		(clock_control_subsys_t)&cfg->pclken);
1014 	ret |= clock_control_on(dev_data->clock,
1015 		(clock_control_subsys_t)&cfg->pclken_tx);
1016 	ret |= clock_control_on(dev_data->clock,
1017 		(clock_control_subsys_t)&cfg->pclken_rx);
1018 #if DT_INST_CLOCKS_HAS_NAME(0, mac_clk_ptp)
1019 	ret |= clock_control_on(dev_data->clock,
1020 		(clock_control_subsys_t)&cfg->pclken_ptp);
1021 #endif
1022 
1023 	if (ret) {
1024 		LOG_ERR("Failed to enable ethernet clock");
1025 		return -EIO;
1026 	}
1027 
1028 	/* configure pinmux */
1029 	ret = pinctrl_apply_state(cfg->pcfg, PINCTRL_STATE_DEFAULT);
1030 	if (ret < 0) {
1031 		LOG_ERR("Could not configure ethernet pins");
1032 		return ret;
1033 	}
1034 
1035 	heth = &dev_data->heth;
1036 
1037 	generate_mac(dev_data->mac_addr);
1038 
1039 	heth->Init.MACAddr = dev_data->mac_addr;
1040 
1041 #if !defined(CONFIG_ETH_STM32_HAL_API_V2)
1042 	HAL_StatusTypeDef hal_ret = HAL_OK;
1043 
1044 	hal_ret = HAL_ETH_Init(heth);
1045 	if (hal_ret == HAL_TIMEOUT) {
1046 		/* HAL Init time out. This could be linked to */
1047 		/* a recoverable error. Log the issue and continue */
1048 		/* driver initialisation */
1049 		LOG_ERR("HAL_ETH_Init Timed out");
1050 	} else if (hal_ret != HAL_OK) {
1051 		LOG_ERR("HAL_ETH_Init failed: %d", hal_ret);
1052 		return -EINVAL;
1053 	}
1054 
1055 	dev_data->link_up = false;
1056 
1057 	/* Initialize semaphores */
1058 	k_mutex_init(&dev_data->tx_mutex);
1059 	k_sem_init(&dev_data->rx_int_sem, 0, K_SEM_MAX_LIMIT);
1060 
1061 	HAL_ETH_DMATxDescListInit(heth, dma_tx_desc_tab,
1062 		&dma_tx_buffer[0][0], ETH_TXBUFNB);
1063 	HAL_ETH_DMARxDescListInit(heth, dma_rx_desc_tab,
1064 		&dma_rx_buffer[0][0], ETH_RXBUFNB);
1065 
1066 	hal_ret = HAL_ETH_Start(heth);
1067 	if (hal_ret != HAL_OK) {
1068 		LOG_ERR("HAL_ETH_Start{_IT} failed");
1069 	}
1070 #endif /* !CONFIG_ETH_STM32_HAL_API_V2 */
1071 
1072 	setup_mac_filter(heth);
1073 
1074 
1075 	LOG_DBG("MAC %02x:%02x:%02x:%02x:%02x:%02x",
1076 		dev_data->mac_addr[0], dev_data->mac_addr[1],
1077 		dev_data->mac_addr[2], dev_data->mac_addr[3],
1078 		dev_data->mac_addr[4], dev_data->mac_addr[5]);
1079 
1080 	return 0;
1081 }
1082 
1083 #if defined(CONFIG_ETH_STM32_MULTICAST_FILTER)
eth_stm32_mcast_filter(const struct device * dev,const struct ethernet_filter * filter)1084 static void eth_stm32_mcast_filter(const struct device *dev, const struct ethernet_filter *filter)
1085 {
1086 	struct eth_stm32_hal_dev_data *dev_data = (struct eth_stm32_hal_dev_data *)dev->data;
1087 	ETH_HandleTypeDef *heth;
1088 	uint32_t crc;
1089 	uint32_t hash_table[2];
1090 	uint32_t hash_index;
1091 
1092 	heth = &dev_data->heth;
1093 
1094 	crc = __RBIT(crc32_ieee(filter->mac_address.addr, sizeof(struct net_eth_addr)));
1095 	hash_index = (crc >> 26) & 0x3f;
1096 
1097 	__ASSERT_NO_MSG(hash_index < ARRAY_SIZE(dev_data->hash_index_cnt));
1098 
1099 #if DT_HAS_COMPAT_STATUS_OKAY(st_stm32h7_ethernet)
1100 	hash_table[0] = heth->Instance->MACHT0R;
1101 	hash_table[1] = heth->Instance->MACHT1R;
1102 #else
1103 	hash_table[0] = heth->Instance->MACHTLR;
1104 	hash_table[1] = heth->Instance->MACHTHR;
1105 #endif /* DT_HAS_COMPAT_STATUS_OKAY(st_stm32h7_ethernet) */
1106 
1107 	if (filter->set) {
1108 		dev_data->hash_index_cnt[hash_index]++;
1109 		hash_table[hash_index / 32] |= (1 << (hash_index % 32));
1110 	} else {
1111 		if (dev_data->hash_index_cnt[hash_index] == 0) {
1112 			__ASSERT_NO_MSG(false);
1113 			return;
1114 		}
1115 
1116 		dev_data->hash_index_cnt[hash_index]--;
1117 		if (dev_data->hash_index_cnt[hash_index] == 0) {
1118 			hash_table[hash_index / 32] &= ~(1 << (hash_index % 32));
1119 		}
1120 	}
1121 
1122 #if DT_HAS_COMPAT_STATUS_OKAY(st_stm32h7_ethernet)
1123 	heth->Instance->MACHT0R = hash_table[0];
1124 	heth->Instance->MACHT1R = hash_table[1];
1125 #else
1126 	heth->Instance->MACHTLR = hash_table[0];
1127 	heth->Instance->MACHTHR = hash_table[1];
1128 #endif /* DT_HAS_COMPAT_STATUS_OKAY(st_stm32h7_ethernet) */
1129 }
1130 
1131 #endif /* CONFIG_ETH_STM32_MULTICAST_FILTER */
1132 
1133 #if defined(CONFIG_ETH_STM32_HAL_API_V2)
1134 #if defined(CONFIG_ETH_STM32_AUTO_NEGOTIATION_ENABLE)
eth_phy_get_link_state(ETH_HandleTypeDef * heth)1135 static uint32_t eth_phy_get_link_state(ETH_HandleTypeDef *heth)
1136 {
1137 	uint32_t readval = 0;
1138 	uint32_t tickstart = 0U;
1139 
1140 	tickstart = k_uptime_get_32();
1141 
1142 	/* Wait for linked status */
1143 	do {
1144 		HAL_ETH_ReadPHYRegister(heth, PHY_ADDR, PHY_BSR, &readval);
1145 
1146 		/* Check for the Timeout */
1147 		if ((k_uptime_get_32() - tickstart) > PHY_TIMEOUT) {
1148 			return HAL_TIMEOUT;
1149 		}
1150 	} while (((readval & PHY_LINKED_STATUS) != PHY_LINKED_STATUS));
1151 
1152 	if ((readval & PHY_LINKED_STATUS) == 0) {
1153 		LOG_ERR("Link Down");
1154 		return PHY_STATUS_LINK_DOWN;
1155 	}
1156 
1157 	/* Check Auto negotiation */
1158 	if (HAL_ETH_ReadPHYRegister(heth, PHY_ADDR, PHY_BCR, &readval) != HAL_OK) {
1159 		LOG_INF("Error reading BCR register\n");
1160 		return HAL_ERROR;
1161 	}
1162 
1163 	if ((readval & PHY_AUTONEGO_ENABLE) != PHY_AUTONEGO_ENABLE) {
1164 		/* Enable Auto-Negotiation */
1165 		if ((HAL_ETH_WritePHYRegister(heth, PHY_ADDR, PHY_BCR, PHY_AUTONEGO_ENABLE)) !=
1166 		    HAL_OK) {
1167 			return HAL_ERROR;
1168 		}
1169 	}
1170 
1171 	/* Auto Nego enabled */
1172 	LOG_DBG("Auto nego enabled");
1173 	if (HAL_ETH_ReadPHYRegister(heth, PHY_ADDR, PHY_SCSR, &readval) != HAL_OK) {
1174 		return HAL_ERROR;
1175 	}
1176 
1177 	/* Check if auto nego not done */
1178 	if ((readval & PHY_SCSR_AUTONEGO_DONE) == 0) {
1179 		return PHY_STATUS_AUTONEGO_NOTDONE;
1180 	}
1181 
1182 	if ((readval & PHY_HCDSPEEDMASK) == PHY_100BTX_FD) {
1183 		return PHY_STATUS_100MBITS_FULLDUPLEX;
1184 	} else if ((readval & PHY_HCDSPEEDMASK) == PHY_100BTX_HD) {
1185 		return PHY_STATUS_100MBITS_HALFDUPLEX;
1186 	} else if ((readval & PHY_HCDSPEEDMASK) == PHY_10BT_FD) {
1187 		return PHY_STATUS_10MBITS_FULLDUPLEX;
1188 	} else {
1189 		return PHY_STATUS_10MBITS_HALFDUPLEX;
1190 	}
1191 }
1192 
get_auto_nego_speed_duplex(ETH_HandleTypeDef * heth,ETH_MACConfigTypeDef * mac_config)1193 static void get_auto_nego_speed_duplex(ETH_HandleTypeDef *heth, ETH_MACConfigTypeDef *mac_config)
1194 {
1195 	uint32_t phyLinkState;
1196 	uint32_t tickstart = k_uptime_get_32();
1197 
1198 	do {
1199 		phyLinkState = eth_phy_get_link_state(heth);
1200 	} while ((phyLinkState <= PHY_STATUS_LINK_DOWN) &&
1201 		 ((k_uptime_get_32() - tickstart) < PHY_TIMEOUT));
1202 
1203 	/* Get link state */
1204 	if (phyLinkState <= PHY_STATUS_LINK_DOWN) {
1205 		return;
1206 	}
1207 
1208 	switch (phyLinkState) {
1209 	case PHY_STATUS_100MBITS_FULLDUPLEX:
1210 		mac_config->DuplexMode = ETH_FULLDUPLEX_MODE;
1211 		mac_config->Speed = ETH_SPEED_100M;
1212 		break;
1213 	case PHY_STATUS_100MBITS_HALFDUPLEX:
1214 		mac_config->DuplexMode = ETH_HALFDUPLEX_MODE;
1215 		mac_config->Speed = ETH_SPEED_100M;
1216 		break;
1217 	case PHY_STATUS_10MBITS_FULLDUPLEX:
1218 		mac_config->DuplexMode = ETH_FULLDUPLEX_MODE;
1219 		mac_config->Speed = ETH_SPEED_10M;
1220 		break;
1221 	case PHY_STATUS_10MBITS_HALFDUPLEX:
1222 		mac_config->DuplexMode = ETH_HALFDUPLEX_MODE;
1223 		mac_config->Speed = ETH_SPEED_10M;
1224 		break;
1225 	default:
1226 		mac_config->DuplexMode = ETH_FULLDUPLEX_MODE;
1227 		mac_config->Speed = ETH_SPEED_100M;
1228 		break;
1229 	}
1230 }
1231 #endif /* CONFIG_ETH_STM32_AUTO_NEGOTIATION_ENABLE */
1232 
eth_init_api_v2(const struct device * dev)1233 static int eth_init_api_v2(const struct device *dev)
1234 {
1235 	HAL_StatusTypeDef hal_ret = HAL_OK;
1236 	struct eth_stm32_hal_dev_data *dev_data;
1237 	ETH_HandleTypeDef *heth;
1238 	ETH_MACConfigTypeDef mac_config;
1239 
1240 	dev_data = dev->data;
1241 	heth = &dev_data->heth;
1242 
1243 #if DT_HAS_COMPAT_STATUS_OKAY(st_stm32n6_ethernet)
1244 	for (int ch = 0; ch < ETH_DMA_CH_CNT; ch++) {
1245 		heth->Init.TxDesc[ch] = dma_tx_desc_tab[ch];
1246 		heth->Init.RxDesc[ch] = dma_rx_desc_tab[ch];
1247 	}
1248 #else
1249 	heth->Init.TxDesc = dma_tx_desc_tab;
1250 	heth->Init.RxDesc = dma_rx_desc_tab;
1251 #endif
1252 	heth->Init.RxBuffLen = ETH_STM32_RX_BUF_SIZE;
1253 
1254 	hal_ret = HAL_ETH_Init(heth);
1255 	if (hal_ret == HAL_TIMEOUT) {
1256 		/* HAL Init time out. This could be linked to */
1257 		/* a recoverable error. Log the issue and continue */
1258 		/* driver initialisation */
1259 		LOG_ERR("HAL_ETH_Init Timed out");
1260 	} else if (hal_ret != HAL_OK) {
1261 		LOG_ERR("HAL_ETH_Init failed: %d", hal_ret);
1262 		return -EINVAL;
1263 	}
1264 
1265 #if defined(CONFIG_PTP_CLOCK_STM32_HAL)
1266 	/* Enable timestamping of RX packets. We enable all packets to be
1267 	 * timestamped to cover both IEEE 1588 and gPTP.
1268 	 */
1269 #if DT_HAS_COMPAT_STATUS_OKAY(st_stm32h7_ethernet)
1270 	heth->Instance->MACTSCR |= ETH_MACTSCR_TSENALL;
1271 #else
1272 	heth->Instance->PTPTSCR |= ETH_PTPTSCR_TSSARFE;
1273 #endif /* DT_HAS_COMPAT_STATUS_OKAY(st_stm32h7_ethernet) */
1274 #endif /* CONFIG_PTP_CLOCK_STM32_HAL */
1275 
1276 	dev_data->link_up = false;
1277 
1278 	/* Initialize semaphores */
1279 	k_mutex_init(&dev_data->tx_mutex);
1280 	k_sem_init(&dev_data->rx_int_sem, 0, K_SEM_MAX_LIMIT);
1281 	k_sem_init(&dev_data->tx_int_sem, 0, K_SEM_MAX_LIMIT);
1282 
1283 	/* Tx config init: */
1284 	memset(&tx_config, 0, sizeof(ETH_TxPacketConfig));
1285 	tx_config.Attributes = ETH_TX_PACKETS_FEATURES_CSUM |
1286 				ETH_TX_PACKETS_FEATURES_CRCPAD;
1287 	tx_config.ChecksumCtrl = IS_ENABLED(CONFIG_ETH_STM32_HW_CHECKSUM) ?
1288 			ETH_CHECKSUM_IPHDR_PAYLOAD_INSERT_PHDR_CALC : ETH_CHECKSUM_DISABLE;
1289 	tx_config.CRCPadCtrl = ETH_CRC_PAD_INSERT;
1290 
1291 	HAL_ETH_SetMDIOClockRange(heth);
1292 
1293 	HAL_ETH_GetMACConfig(heth, &mac_config);
1294 
1295 #if defined(CONFIG_ETH_STM32_AUTO_NEGOTIATION_ENABLE)
1296 	/* Auto Nego enabled */
1297 	get_auto_nego_speed_duplex(heth, &mac_config);
1298 
1299 #else /* Auto Nego disabled */
1300 	mac_config.DuplexMode = IS_ENABLED(CONFIG_ETH_STM32_MODE_HALFDUPLEX) ? ETH_HALFDUPLEX_MODE
1301 									     : ETH_FULLDUPLEX_MODE;
1302 	mac_config.Speed = IS_ENABLED(CONFIG_ETH_STM32_SPEED_10M) ? ETH_SPEED_10M : ETH_SPEED_100M;
1303 #endif
1304 
1305 	hal_ret = HAL_ETH_SetMACConfig(heth, &mac_config);
1306 	if (hal_ret != HAL_OK) {
1307 		LOG_ERR("HAL_ETH_SetMACConfig: failed: %d", hal_ret);
1308 	}
1309 
1310 	/* prepare tx buffer header */
1311 	for (uint16_t i = 0; i < ETH_TXBUFNB; ++i) {
1312 		dma_tx_buffer_header[i].tx_buff.buffer = dma_tx_buffer[i];
1313 	}
1314 
1315 	hal_ret = HAL_ETH_Start_IT(heth);
1316 	if (hal_ret != HAL_OK) {
1317 		LOG_ERR("HAL_ETH_Start{_IT} failed");
1318 	}
1319 
1320 	return 0;
1321 }
1322 #endif /* CONFIG_ETH_STM32_HAL_API_V2 */
1323 
eth_iface_init(struct net_if * iface)1324 static void eth_iface_init(struct net_if *iface)
1325 {
1326 	const struct device *dev;
1327 	struct eth_stm32_hal_dev_data *dev_data;
1328 	bool is_first_init = false;
1329 
1330 	__ASSERT_NO_MSG(iface != NULL);
1331 
1332 	dev = net_if_get_device(iface);
1333 	__ASSERT_NO_MSG(dev != NULL);
1334 
1335 	dev_data = dev->data;
1336 	__ASSERT_NO_MSG(dev_data != NULL);
1337 
1338 	if (dev_data->iface == NULL) {
1339 		dev_data->iface = iface;
1340 		is_first_init = true;
1341 	}
1342 
1343 	/* Register Ethernet MAC Address with the upper layer */
1344 	net_if_set_link_addr(iface, dev_data->mac_addr,
1345 			     sizeof(dev_data->mac_addr),
1346 			     NET_LINK_ETHERNET);
1347 
1348 #if defined(CONFIG_NET_DSA)
1349 	dsa_register_master_tx(iface, &eth_tx);
1350 #endif
1351 
1352 	ethernet_init(iface);
1353 
1354 #if defined(CONFIG_ETH_STM32_HAL_API_V2)
1355 	/* This function requires the Ethernet interface to be
1356 	 * properly initialized. In auto-negotiation mode, it reads the speed
1357 	 * and duplex settings to configure the driver accordingly.
1358 	 */
1359 	eth_init_api_v2(dev);
1360 #endif
1361 
1362 	net_if_carrier_off(iface);
1363 
1364 	net_lldp_set_lldpdu(iface);
1365 
1366 	if (is_first_init) {
1367 		const struct eth_stm32_hal_dev_cfg *cfg = dev->config;
1368 		/* Now that the iface is setup, we are safe to enable IRQs. */
1369 		__ASSERT_NO_MSG(cfg->config_func != NULL);
1370 		cfg->config_func();
1371 
1372 		/* Start interruption-poll thread */
1373 		k_thread_create(&dev_data->rx_thread, dev_data->rx_thread_stack,
1374 				K_KERNEL_STACK_SIZEOF(dev_data->rx_thread_stack),
1375 				rx_thread, (void *) dev, NULL, NULL,
1376 				IS_ENABLED(CONFIG_ETH_STM32_HAL_RX_THREAD_PREEMPTIVE)
1377 					? K_PRIO_PREEMPT(CONFIG_ETH_STM32_HAL_RX_THREAD_PRIO)
1378 					: K_PRIO_COOP(CONFIG_ETH_STM32_HAL_RX_THREAD_PRIO),
1379 				0, K_NO_WAIT);
1380 
1381 		k_thread_name_set(&dev_data->rx_thread, "stm_eth");
1382 	}
1383 }
1384 
eth_stm32_hal_get_capabilities(const struct device * dev)1385 static enum ethernet_hw_caps eth_stm32_hal_get_capabilities(const struct device *dev)
1386 {
1387 	ARG_UNUSED(dev);
1388 
1389 	return ETHERNET_LINK_10BASE_T | ETHERNET_LINK_100BASE_T
1390 #if defined(CONFIG_NET_VLAN)
1391 		| ETHERNET_HW_VLAN
1392 #endif
1393 #if defined(CONFIG_NET_PROMISCUOUS_MODE)
1394 		| ETHERNET_PROMISC_MODE
1395 #endif
1396 #if defined(CONFIG_PTP_CLOCK_STM32_HAL)
1397 		| ETHERNET_PTP
1398 #endif
1399 #if defined(CONFIG_NET_LLDP)
1400 		| ETHERNET_LLDP
1401 #endif
1402 #if defined(CONFIG_ETH_STM32_HW_CHECKSUM)
1403 		| ETHERNET_HW_RX_CHKSUM_OFFLOAD
1404 		| ETHERNET_HW_TX_CHKSUM_OFFLOAD
1405 #endif
1406 #if defined(CONFIG_NET_DSA)
1407 		| ETHERNET_DSA_MASTER_PORT
1408 #endif
1409 #if defined(CONFIG_ETH_STM32_MULTICAST_FILTER)
1410 		| ETHERNET_HW_FILTERING
1411 #endif
1412 		;
1413 }
1414 
eth_stm32_hal_set_config(const struct device * dev,enum ethernet_config_type type,const struct ethernet_config * config)1415 static int eth_stm32_hal_set_config(const struct device *dev,
1416 				    enum ethernet_config_type type,
1417 				    const struct ethernet_config *config)
1418 {
1419 	int ret = -ENOTSUP;
1420 	struct eth_stm32_hal_dev_data *dev_data;
1421 	ETH_HandleTypeDef *heth;
1422 
1423 	dev_data = dev->data;
1424 	heth = &dev_data->heth;
1425 
1426 	switch (type) {
1427 	case ETHERNET_CONFIG_TYPE_MAC_ADDRESS:
1428 		memcpy(dev_data->mac_addr, config->mac_address.addr, 6);
1429 		heth->Instance->MACA0HR = (dev_data->mac_addr[5] << 8) |
1430 			dev_data->mac_addr[4];
1431 		heth->Instance->MACA0LR = (dev_data->mac_addr[3] << 24) |
1432 			(dev_data->mac_addr[2] << 16) |
1433 			(dev_data->mac_addr[1] << 8) |
1434 			dev_data->mac_addr[0];
1435 		net_if_set_link_addr(dev_data->iface, dev_data->mac_addr,
1436 				     sizeof(dev_data->mac_addr),
1437 				     NET_LINK_ETHERNET);
1438 		ret = 0;
1439 		break;
1440 	case ETHERNET_CONFIG_TYPE_PROMISC_MODE:
1441 #if defined(CONFIG_NET_PROMISCUOUS_MODE)
1442 #if DT_HAS_COMPAT_STATUS_OKAY(st_stm32h7_ethernet)
1443 		if (config->promisc_mode) {
1444 			heth->Instance->MACPFR |= ETH_MACPFR_PR;
1445 		} else {
1446 			heth->Instance->MACPFR &= ~ETH_MACPFR_PR;
1447 		}
1448 #else
1449 		if (config->promisc_mode) {
1450 			heth->Instance->MACFFR |= ETH_MACFFR_PM;
1451 		} else {
1452 			heth->Instance->MACFFR &= ~ETH_MACFFR_PM;
1453 		}
1454 #endif /* DT_HAS_COMPAT_STATUS_OKAY(st_stm32h7_ethernet) */
1455 		ret = 0;
1456 #endif /* CONFIG_NET_PROMISCUOUS_MODE */
1457 		break;
1458 #if defined(CONFIG_ETH_STM32_MULTICAST_FILTER)
1459 	case ETHERNET_CONFIG_TYPE_FILTER:
1460 		eth_stm32_mcast_filter(dev, &config->filter);
1461 		break;
1462 #endif /* CONFIG_ETH_STM32_MULTICAST_FILTER */
1463 	default:
1464 		break;
1465 	}
1466 
1467 	return ret;
1468 }
1469 
1470 #if DT_HAS_COMPAT_STATUS_OKAY(st_stm32_mdio)
eth_stm32_hal_get_phy(const struct device * dev)1471 static const struct device *eth_stm32_hal_get_phy(const struct device *dev)
1472 {
1473 	ARG_UNUSED(dev);
1474 	return eth_stm32_phy_dev;
1475 }
1476 #endif /* DT_HAS_COMPAT_STATUS_OKAY(st_stm32_mdio) */
1477 
1478 #if defined(CONFIG_PTP_CLOCK_STM32_HAL)
eth_stm32_get_ptp_clock(const struct device * dev)1479 static const struct device *eth_stm32_get_ptp_clock(const struct device *dev)
1480 {
1481 	struct eth_stm32_hal_dev_data *dev_data = dev->data;
1482 
1483 	return dev_data->ptp_clock;
1484 }
1485 #endif /* CONFIG_PTP_CLOCK_STM32_HAL */
1486 
1487 #if defined(CONFIG_NET_STATISTICS_ETHERNET)
eth_stm32_hal_get_stats(const struct device * dev)1488 static struct net_stats_eth *eth_stm32_hal_get_stats(const struct device *dev)
1489 {
1490 	struct eth_stm32_hal_dev_data *dev_data = dev->data;
1491 
1492 	return &dev_data->stats;
1493 }
1494 #endif /* CONFIG_NET_STATISTICS_ETHERNET */
1495 
1496 static const struct ethernet_api eth_api = {
1497 	.iface_api.init = eth_iface_init,
1498 #if defined(CONFIG_PTP_CLOCK_STM32_HAL)
1499 	.get_ptp_clock = eth_stm32_get_ptp_clock,
1500 #endif /* CONFIG_PTP_CLOCK_STM32_HAL */
1501 	.get_capabilities = eth_stm32_hal_get_capabilities,
1502 	.set_config = eth_stm32_hal_set_config,
1503 #if DT_HAS_COMPAT_STATUS_OKAY(st_stm32_mdio)
1504 	.get_phy = eth_stm32_hal_get_phy,
1505 #endif
1506 #if defined(CONFIG_NET_DSA)
1507 	.send = dsa_tx,
1508 #else
1509 	.send = eth_tx,
1510 #endif
1511 #if defined(CONFIG_NET_STATISTICS_ETHERNET)
1512 	.get_stats = eth_stm32_hal_get_stats,
1513 #endif /* CONFIG_NET_STATISTICS_ETHERNET */
1514 };
1515 
eth0_irq_config(void)1516 static void eth0_irq_config(void)
1517 {
1518 	IRQ_CONNECT(DT_INST_IRQN(0), DT_INST_IRQ(0, priority), eth_isr,
1519 		    DEVICE_DT_INST_GET(0), 0);
1520 	irq_enable(DT_INST_IRQN(0));
1521 }
1522 
1523 PINCTRL_DT_INST_DEFINE(0);
1524 
1525 static const struct eth_stm32_hal_dev_cfg eth0_config = {
1526 	.config_func = eth0_irq_config,
1527 	.pclken = {.bus = DT_INST_CLOCKS_CELL_BY_NAME(0, stmmaceth, bus),
1528 		   .enr = DT_INST_CLOCKS_CELL_BY_NAME(0, stmmaceth, bits)},
1529 	.pclken_tx = {.bus = DT_INST_CLOCKS_CELL_BY_NAME(0, mac_clk_tx, bus),
1530 		      .enr = DT_INST_CLOCKS_CELL_BY_NAME(0, mac_clk_tx, bits)},
1531 	.pclken_rx = {.bus = DT_INST_CLOCKS_CELL_BY_NAME(0, mac_clk_rx, bus),
1532 		      .enr = DT_INST_CLOCKS_CELL_BY_NAME(0, mac_clk_rx, bits)},
1533 #if DT_INST_CLOCKS_HAS_NAME(0, mac_clk_ptp)
1534 	.pclken_ptp = {.bus = DT_INST_CLOCKS_CELL_BY_NAME(0, mac_clk_ptp, bus),
1535 		       .enr = DT_INST_CLOCKS_CELL_BY_NAME(0, mac_clk_ptp, bits)},
1536 #endif
1537 	.pcfg = PINCTRL_DT_INST_DEV_CONFIG_GET(0),
1538 };
1539 
1540 BUILD_ASSERT(DT_ENUM_HAS_VALUE(MAC_NODE, phy_connection_type, mii) ||
1541 	     DT_ENUM_HAS_VALUE(MAC_NODE, phy_connection_type, rmii),
1542 	     "Unsupported PHY connection type selected");
1543 
1544 static struct eth_stm32_hal_dev_data eth0_data = {
1545 	.heth = {
1546 		.Instance = (ETH_TypeDef *)DT_INST_REG_ADDR(0),
1547 		.Init = {
1548 #if !defined(CONFIG_ETH_STM32_HAL_API_V2)
1549 #if defined(CONFIG_ETH_STM32_AUTO_NEGOTIATION_ENABLE)
1550 			.AutoNegotiation = ETH_AUTONEGOTIATION_ENABLE,
1551 #else
1552 			.AutoNegotiation = ETH_AUTONEGOTIATION_DISABLE,
1553 			.Speed = IS_ENABLED(CONFIG_ETH_STM32_SPEED_10M) ?
1554 				 ETH_SPEED_10M : ETH_SPEED_100M,
1555 			.DuplexMode = IS_ENABLED(CONFIG_ETH_STM32_MODE_HALFDUPLEX) ?
1556 				      ETH_MODE_HALFDUPLEX : ETH_MODE_FULLDUPLEX,
1557 #endif /* !CONFIG_ETH_STM32_AUTO_NEGOTIATION_ENABLE */
1558 			.PhyAddress = PHY_ADDR,
1559 			.RxMode = ETH_RXINTERRUPT_MODE,
1560 			.ChecksumMode = IS_ENABLED(CONFIG_ETH_STM32_HW_CHECKSUM) ?
1561 					ETH_CHECKSUM_BY_HARDWARE : ETH_CHECKSUM_BY_SOFTWARE,
1562 #endif /* !CONFIG_SOC_SERIES_STM32H7X */
1563 			.MediaInterface = STM32_ETH_PHY_MODE(MAC_NODE),
1564 		},
1565 	},
1566 };
1567 
1568 ETH_NET_DEVICE_DT_INST_DEFINE(0, eth_initialize,
1569 		    NULL, &eth0_data, &eth0_config,
1570 		    CONFIG_ETH_INIT_PRIORITY, &eth_api, ETH_STM32_HAL_MTU);
1571 
1572 #if defined(CONFIG_PTP_CLOCK_STM32_HAL)
1573 
1574 struct ptp_context {
1575 	struct eth_stm32_hal_dev_data *eth_dev_data;
1576 };
1577 
1578 static struct ptp_context ptp_stm32_0_context;
1579 
ptp_clock_stm32_set(const struct device * dev,struct net_ptp_time * tm)1580 static int ptp_clock_stm32_set(const struct device *dev,
1581 			      struct net_ptp_time *tm)
1582 {
1583 	struct ptp_context *ptp_context = dev->data;
1584 	struct eth_stm32_hal_dev_data *eth_dev_data = ptp_context->eth_dev_data;
1585 	ETH_HandleTypeDef *heth = &eth_dev_data->heth;
1586 	unsigned int key;
1587 
1588 	key = irq_lock();
1589 
1590 #if DT_HAS_COMPAT_STATUS_OKAY(st_stm32h7_ethernet)
1591 	heth->Instance->MACSTSUR = tm->second;
1592 	heth->Instance->MACSTNUR = tm->nanosecond;
1593 	heth->Instance->MACTSCR |= ETH_MACTSCR_TSINIT;
1594 	while (heth->Instance->MACTSCR & ETH_MACTSCR_TSINIT_Msk) {
1595 		/* spin lock */
1596 	}
1597 #else
1598 	heth->Instance->PTPTSHUR = tm->second;
1599 	heth->Instance->PTPTSLUR = tm->nanosecond;
1600 	heth->Instance->PTPTSCR |= ETH_PTPTSCR_TSSTI;
1601 	while (heth->Instance->PTPTSCR & ETH_PTPTSCR_TSSTI_Msk) {
1602 		/* spin lock */
1603 	}
1604 #endif /* DT_HAS_COMPAT_STATUS_OKAY(st_stm32h7_ethernet) */
1605 
1606 	irq_unlock(key);
1607 
1608 	return 0;
1609 }
1610 
ptp_clock_stm32_get(const struct device * dev,struct net_ptp_time * tm)1611 static int ptp_clock_stm32_get(const struct device *dev,
1612 			      struct net_ptp_time *tm)
1613 {
1614 	struct ptp_context *ptp_context = dev->data;
1615 	struct eth_stm32_hal_dev_data *eth_dev_data = ptp_context->eth_dev_data;
1616 	ETH_HandleTypeDef *heth = &eth_dev_data->heth;
1617 	unsigned int key;
1618 	uint32_t second_2;
1619 
1620 	key = irq_lock();
1621 
1622 #if DT_HAS_COMPAT_STATUS_OKAY(st_stm32h7_ethernet)
1623 	tm->second = heth->Instance->MACSTSR;
1624 	tm->nanosecond = heth->Instance->MACSTNR;
1625 	second_2 = heth->Instance->MACSTSR;
1626 #else
1627 	tm->second = heth->Instance->PTPTSHR;
1628 	tm->nanosecond = heth->Instance->PTPTSLR;
1629 	second_2 = heth->Instance->PTPTSHR;
1630 #endif /* DT_HAS_COMPAT_STATUS_OKAY(st_stm32h7_ethernet) */
1631 
1632 	irq_unlock(key);
1633 
1634 	if (tm->second != second_2 && tm->nanosecond < NSEC_PER_SEC / 2) {
1635 		/* Second rollover has happened during first measurement: second register
1636 		 * was read before second boundary and nanosecond register was read after.
1637 		 * We will use second_2 as a new second value.
1638 		 */
1639 		tm->second = second_2;
1640 	}
1641 
1642 	return 0;
1643 }
1644 
ptp_clock_stm32_adjust(const struct device * dev,int increment)1645 static int ptp_clock_stm32_adjust(const struct device *dev, int increment)
1646 {
1647 	struct ptp_context *ptp_context = dev->data;
1648 	struct eth_stm32_hal_dev_data *eth_dev_data = ptp_context->eth_dev_data;
1649 	ETH_HandleTypeDef *heth = &eth_dev_data->heth;
1650 	int key, ret;
1651 
1652 	if ((increment <= (int32_t)(-NSEC_PER_SEC)) ||
1653 			(increment >= (int32_t)NSEC_PER_SEC)) {
1654 		ret = -EINVAL;
1655 	} else {
1656 		key = irq_lock();
1657 
1658 #if DT_HAS_COMPAT_STATUS_OKAY(st_stm32h7_ethernet)
1659 		heth->Instance->MACSTSUR = 0;
1660 		if (increment >= 0) {
1661 			heth->Instance->MACSTNUR = increment;
1662 		} else {
1663 			heth->Instance->MACSTNUR = ETH_MACSTNUR_ADDSUB | (NSEC_PER_SEC + increment);
1664 		}
1665 		heth->Instance->MACTSCR |= ETH_MACTSCR_TSUPDT;
1666 		while (heth->Instance->MACTSCR & ETH_MACTSCR_TSUPDT_Msk) {
1667 			/* spin lock */
1668 		}
1669 #else
1670 		heth->Instance->PTPTSHUR = 0;
1671 		if (increment >= 0) {
1672 			heth->Instance->PTPTSLUR = increment;
1673 		} else {
1674 			heth->Instance->PTPTSLUR = ETH_PTPTSLUR_TSUPNS | (-increment);
1675 		}
1676 		heth->Instance->PTPTSCR |= ETH_PTPTSCR_TSSTU;
1677 		while (heth->Instance->PTPTSCR & ETH_PTPTSCR_TSSTU_Msk) {
1678 			/* spin lock */
1679 		}
1680 #endif /* DT_HAS_COMPAT_STATUS_OKAY(st_stm32h7_ethernet) */
1681 
1682 		ret = 0;
1683 		irq_unlock(key);
1684 	}
1685 
1686 	return ret;
1687 }
1688 
ptp_clock_stm32_rate_adjust(const struct device * dev,double ratio)1689 static int ptp_clock_stm32_rate_adjust(const struct device *dev, double ratio)
1690 {
1691 	struct ptp_context *ptp_context = dev->data;
1692 	struct eth_stm32_hal_dev_data *eth_dev_data = ptp_context->eth_dev_data;
1693 	ETH_HandleTypeDef *heth = &eth_dev_data->heth;
1694 	int key, ret;
1695 	uint32_t addend_val;
1696 
1697 	/* No change needed */
1698 	if (ratio == 1.0L) {
1699 		return 0;
1700 	}
1701 
1702 	key = irq_lock();
1703 
1704 	ratio *= (double)eth_dev_data->clk_ratio_adj;
1705 
1706 	/* Limit possible ratio */
1707 	if (ratio * 100 < CONFIG_ETH_STM32_HAL_PTP_CLOCK_ADJ_MIN_PCT ||
1708 			ratio * 100 > CONFIG_ETH_STM32_HAL_PTP_CLOCK_ADJ_MAX_PCT) {
1709 		ret = -EINVAL;
1710 		goto error;
1711 	}
1712 
1713 	/* Save new ratio */
1714 	eth_dev_data->clk_ratio_adj = ratio;
1715 
1716 	/* Update addend register */
1717 	addend_val = UINT32_MAX * (double)eth_dev_data->clk_ratio * ratio;
1718 
1719 #if DT_HAS_COMPAT_STATUS_OKAY(st_stm32h7_ethernet)
1720 	heth->Instance->MACTSAR = addend_val;
1721 	heth->Instance->MACTSCR |= ETH_MACTSCR_TSADDREG;
1722 	while (heth->Instance->MACTSCR & ETH_MACTSCR_TSADDREG_Msk) {
1723 		/* spin lock */
1724 	}
1725 #else
1726 	heth->Instance->PTPTSAR = addend_val;
1727 	heth->Instance->PTPTSCR |= ETH_PTPTSCR_TSARU;
1728 	while (heth->Instance->PTPTSCR & ETH_PTPTSCR_TSARU_Msk) {
1729 		/* spin lock */
1730 	}
1731 #endif /* DT_HAS_COMPAT_STATUS_OKAY(st_stm32h7_ethernet) */
1732 
1733 	ret = 0;
1734 
1735 error:
1736 	irq_unlock(key);
1737 
1738 	return ret;
1739 }
1740 
1741 static DEVICE_API(ptp_clock, api) = {
1742 	.set = ptp_clock_stm32_set,
1743 	.get = ptp_clock_stm32_get,
1744 	.adjust = ptp_clock_stm32_adjust,
1745 	.rate_adjust = ptp_clock_stm32_rate_adjust,
1746 };
1747 
ptp_stm32_init(const struct device * port)1748 static int ptp_stm32_init(const struct device *port)
1749 {
1750 	const struct device *const dev = DEVICE_DT_GET(DT_NODELABEL(mac));
1751 	struct eth_stm32_hal_dev_data *eth_dev_data = dev->data;
1752 	const struct eth_stm32_hal_dev_cfg *eth_cfg = dev->config;
1753 	struct ptp_context *ptp_context = port->data;
1754 	ETH_HandleTypeDef *heth = &eth_dev_data->heth;
1755 	int ret;
1756 	uint32_t ptp_hclk_rate;
1757 	uint32_t ss_incr_ns;
1758 	uint32_t addend_val;
1759 
1760 	eth_dev_data->ptp_clock = port;
1761 	ptp_context->eth_dev_data = eth_dev_data;
1762 
1763 	/* Mask the Timestamp Trigger interrupt */
1764 #if DT_HAS_COMPAT_STATUS_OKAY(st_stm32h7_ethernet)
1765 	heth->Instance->MACIER &= ~(ETH_MACIER_TSIE);
1766 #else
1767 	heth->Instance->MACIMR &= ~(ETH_MACIMR_TSTIM);
1768 #endif /* DT_HAS_COMPAT_STATUS_OKAY(st_stm32h7_ethernet) */
1769 
1770 	/* Enable timestamping */
1771 #if DT_HAS_COMPAT_STATUS_OKAY(st_stm32h7_ethernet)
1772 	heth->Instance->MACTSCR |= ETH_MACTSCR_TSENA;
1773 #else
1774 	heth->Instance->PTPTSCR |= ETH_PTPTSCR_TSE;
1775 #endif /* DT_HAS_COMPAT_STATUS_OKAY(st_stm32h7_ethernet) */
1776 
1777 	/* Query ethernet clock rate */
1778 	ret = clock_control_get_rate(eth_dev_data->clock,
1779 #if DT_HAS_COMPAT_STATUS_OKAY(st_stm32h7_ethernet)
1780 				     (clock_control_subsys_t)&eth_cfg->pclken,
1781 #else
1782 				     (clock_control_subsys_t)&eth_cfg->pclken_ptp,
1783 #endif /* DT_HAS_COMPAT_STATUS_OKAY(st_stm32h7_ethernet) */
1784 				     &ptp_hclk_rate);
1785 	if (ret) {
1786 		LOG_ERR("Failed to query ethernet clock");
1787 		return -EIO;
1788 	}
1789 
1790 	/* Program the subsecond increment register based on the PTP clock freq */
1791 	if (NSEC_PER_SEC % CONFIG_ETH_STM32_HAL_PTP_CLOCK_SRC_HZ != 0) {
1792 		LOG_ERR("PTP clock period must be an integer nanosecond value");
1793 		return -EINVAL;
1794 	}
1795 	ss_incr_ns = NSEC_PER_SEC / CONFIG_ETH_STM32_HAL_PTP_CLOCK_SRC_HZ;
1796 	if (ss_incr_ns > UINT8_MAX) {
1797 		LOG_ERR("PTP clock period is more than %d nanoseconds", UINT8_MAX);
1798 		return -EINVAL;
1799 	}
1800 #if DT_HAS_COMPAT_STATUS_OKAY(st_stm32h7_ethernet)
1801 	heth->Instance->MACSSIR = ss_incr_ns << ETH_MACMACSSIR_SSINC_Pos;
1802 #else
1803 	heth->Instance->PTPSSIR = ss_incr_ns;
1804 #endif /* DT_HAS_COMPAT_STATUS_OKAY(st_stm32h7_ethernet) */
1805 
1806 	/* Program timestamp addend register */
1807 	eth_dev_data->clk_ratio =
1808 		((double)CONFIG_ETH_STM32_HAL_PTP_CLOCK_SRC_HZ) / ((double)ptp_hclk_rate);
1809 	/*
1810 	 * clk_ratio is a ratio between desired PTP clock frequency and HCLK rate.
1811 	 * Because HCLK is defined by a physical oscillator, it might drift due
1812 	 * to manufacturing tolerances and environmental effects (e.g. temperature).
1813 	 * clk_ratio_adj compensates for such inaccuracies. It starts off as 1.0
1814 	 * and gets adjusted by calling ptp_clock_stm32_rate_adjust().
1815 	 */
1816 	eth_dev_data->clk_ratio_adj = 1.0f;
1817 	addend_val =
1818 		UINT32_MAX * eth_dev_data->clk_ratio * eth_dev_data->clk_ratio_adj;
1819 #if DT_HAS_COMPAT_STATUS_OKAY(st_stm32h7_ethernet)
1820 	heth->Instance->MACTSAR = addend_val;
1821 	heth->Instance->MACTSCR |= ETH_MACTSCR_TSADDREG;
1822 	while (heth->Instance->MACTSCR & ETH_MACTSCR_TSADDREG_Msk) {
1823 		k_yield();
1824 	}
1825 #else
1826 	heth->Instance->PTPTSAR = addend_val;
1827 	heth->Instance->PTPTSCR |= ETH_PTPTSCR_TSARU;
1828 	while (heth->Instance->PTPTSCR & ETH_PTPTSCR_TSARU_Msk) {
1829 		k_yield();
1830 	}
1831 #endif /* DT_HAS_COMPAT_STATUS_OKAY(st_stm32h7_ethernet) */
1832 
1833 	/* Enable fine timestamp correction method */
1834 #if DT_HAS_COMPAT_STATUS_OKAY(st_stm32h7_ethernet)
1835 	heth->Instance->MACTSCR |= ETH_MACTSCR_TSCFUPDT;
1836 #else
1837 	heth->Instance->PTPTSCR |= ETH_PTPTSCR_TSFCU;
1838 #endif /* DT_HAS_COMPAT_STATUS_OKAY(st_stm32h7_ethernet) */
1839 
1840 	/* Enable nanosecond rollover into a new second */
1841 #if DT_HAS_COMPAT_STATUS_OKAY(st_stm32h7_ethernet)
1842 	heth->Instance->MACTSCR |= ETH_MACTSCR_TSCTRLSSR;
1843 #else
1844 	heth->Instance->PTPTSCR |= ETH_PTPTSCR_TSSSR;
1845 #endif /* DT_HAS_COMPAT_STATUS_OKAY(st_stm32h7_ethernet) */
1846 
1847 	/* Initialize timestamp */
1848 #if DT_HAS_COMPAT_STATUS_OKAY(st_stm32h7_ethernet)
1849 	heth->Instance->MACSTSUR = 0;
1850 	heth->Instance->MACSTNUR = 0;
1851 	heth->Instance->MACTSCR |= ETH_MACTSCR_TSINIT;
1852 	while (heth->Instance->MACTSCR & ETH_MACTSCR_TSINIT_Msk) {
1853 		k_yield();
1854 	}
1855 #else
1856 	heth->Instance->PTPTSHUR = 0;
1857 	heth->Instance->PTPTSLUR = 0;
1858 	heth->Instance->PTPTSCR |= ETH_PTPTSCR_TSSTI;
1859 	while (heth->Instance->PTPTSCR & ETH_PTPTSCR_TSSTI_Msk) {
1860 		k_yield();
1861 	}
1862 #endif /* DT_HAS_COMPAT_STATUS_OKAY(st_stm32h7_ethernet) */
1863 
1864 #if defined(CONFIG_ETH_STM32_HAL_API_V2)
1865 	/* Set PTP Configuration done */
1866 	heth->IsPtpConfigured = ETH_STM32_PTP_CONFIGURED;
1867 #endif
1868 
1869 	return 0;
1870 }
1871 
1872 DEVICE_DEFINE(stm32_ptp_clock_0, PTP_CLOCK_NAME, ptp_stm32_init,
1873 		NULL, &ptp_stm32_0_context, NULL, POST_KERNEL,
1874 		CONFIG_ETH_STM32_HAL_PTP_CLOCK_INIT_PRIO, &api);
1875 
1876 #endif /* CONFIG_PTP_CLOCK_STM32_HAL */
1877