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