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, ð_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, ð0_data, ð0_config,
1513 CONFIG_ETH_INIT_PRIORITY, ð_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 = ð_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 = ð_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 = ð_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 = ð_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 = ð_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)ð_cfg->pclken,
1724 #else
1725 (clock_control_subsys_t)ð_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