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