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