1 
2 /**
3  * @file xmc_eth_mac.c
4  * @date 2018-08-08
5  *
6  * @cond
7  *********************************************************************************************************************
8  * XMClib v2.1.24 - XMC Peripheral Driver Library
9  *
10  * Copyright (c) 2015-2019, Infineon Technologies AG
11  * All rights reserved.
12  *
13  * Redistribution and use in source and binary forms, with or without modification,are permitted provided that the
14  * following conditions are met:
15  *
16  * Redistributions of source code must retain the above copyright notice, this list of conditions and the following
17  * disclaimer.
18  *
19  * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following
20  * disclaimer in the documentation and/or other materials provided with the distribution.
21  *
22  * Neither the name of the copyright holders nor the names of its contributors may be used to endorse or promote
23  * products derived from this software without specific prior written permission.
24  *
25  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
26  * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
27  * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE  FOR ANY DIRECT, INDIRECT, INCIDENTAL,
28  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
29  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
30  * WHETHER IN CONTRACT, STRICT LIABILITY,OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
31  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32  *
33  * To improve the quality of the software, users are encouraged to share modifications, enhancements or bug fixes with
34  * Infineon Technologies AG dave@infineon.com).
35  *********************************************************************************************************************
36  *
37  * Change History
38  * --------------
39  *
40  * 2015-06-20:
41  *     - Initial
42  *
43  * 2015-09-01:
44  *     - Add clock gating control in enable/disable APIs
45  *     - Add transmit polling if run out of buffers
46  *
47  * 2015-11-30:
48  *     - Fix XMC_ETH_MAC_GetRxFrameSize return value in case of errors
49  *
50  * 2016-03-16:
51  *     - Fix XMC_ETH_MAC_DisableEvent
52  *
53  * 2016-05-19:
54  *     - Changed XMC_ETH_MAC_ReturnTxDescriptor and XMC_ETH_MAC_ReturnRxDescriptor
55  *
56  * 2016-08-30:
57  *     - Changed XMC_ETH_MAC_Init() to disable MMC interrupt events
58  *
59  * 2016-11-22:
60  *     - Changed XMC_ETH_MAC_Init() to optimize access to bus
61  *
62  * 2017-02-25:
63  *     - XMC_ETH_MAC_Enable() and XMC_ETH_MAC_Disable(), fixed compilation warnings
64  *
65  * 2017-03-27:
66  *     - Changed XMC_ETH_MAC_Init() to disable PMT and timestamp interrupt events
67  *
68  * 2017-04-02:
69  *     - Added XMC_ETH_MAC_InitPTPEx()
70  *     - Added XMC_ETH_MAC_SetPTPTime()
71  *     - Added XMC_ETH_MAC_UpdateAddend()
72  *     - Fixed XMC_ETH_MAC_InitPTP(), XMC_ETH_MAC_UpdatePTPTime(), XMC_ETH_MAC_SetPTPAlarm()
73  *       - nanoseconds initializazion
74  *       - added polling to wait for setup
75  *
76  * 2017-04-04:
77  *     - Changed XMC_ETH_MAC_Init() to disable MMC IPC receive interrupt events
78  *
79  * 2017-04-11:
80  *     - Fixed XMC_ETH_MAC_SetPTPAlarm() nanoseconds conversion
81  *
82  * 2017-04-17:
83  *     - Changed XMC_ETH_MAC_GetTxTimeStamp() and XMC_ETH_MAC_GetRxTimeStamp() return the timestamp depending on status bit in descriptor
84  *
85  * 2017-04-27:
86  *     - Fixed XMC_ETH_MAC_GetRxTimeStamp() and XMC_ETH_MAC_GetTxTimeStamp() fixed returned nanoseconds value
87  *
88  * 2017-08-03:
89  *     - Changed XMC_ETH_MAC_InitPTP(), XMC_ETH_MAC_InitPTPEx(), XMC_ETH_MAC_GetPTPTime(), XMC_ETH_MAC_UpdatePTPTime(), XMC_ETH_MAC_SetPTPAlarm(), XMC_ETH_MAC_GetRxTimeStamp(), XMC_ETH_MAC_GetTxTimeStamp()
90  *       rollover mode of nanosecond counter from binary to digital mode, i.e 1ns resolution
91  *
92  * 2017-09-27:
93  *     - Added XMC_ETH_MAC_InitEx()
94  *     - XMC_ETH_MAC_SetAddressEx(), XMC_ETH_MAC_GetAddressEx() and XMC_ETH_MAC_SetAddressPerfectFilterEx() which receives a byte array with the MAC address instead of uint64_t
95  *
96  * 2018-06-21:
97  *     - Fixed XMC_ETH_MAC_SetAddressPerfectFilterEx()
98  *
99  * 2018-08-08:
100  *      - Fixed XMC_ETH_MAC_SetVLANTag() which now accepts a 32bit tag parameter that allows setting ETV bit to compare only VLAN Tag ID
101  *
102  * @endcond
103  */
104 
105 /*******************************************************************************
106  * HEADER FILES
107  *******************************************************************************/
108 #include <xmc_eth_mac.h>
109 
110 #if defined (ETH0)
111 
112 #include <stdlib.h>
113 #include <xmc_scu.h>
114 
115 /*******************************************************************************
116  * MACROS
117  *******************************************************************************/
118 
119 /**
120  * ETH MAC clock speed
121  */
122 #define XMC_ETH_MAC_CLK_SPEED_35MHZ  (35000000U)  /**< ETH MAC clock speed 35 MHZ */
123 #define XMC_ETH_MAC_CLK_SPEED_60MHZ  (60000000U)  /**< ETH MAC clock speed 60 MHZ */
124 #define XMC_ETH_MAC_CLK_SPEED_100MHZ (100000000U) /**< ETH MAC clock speed 100 MHZ */
125 #define XMC_ETH_MAC_CLK_SPEED_150MHZ (150000000U) /**< ETH MAC clock speed 150 MHZ */
126 #define XMC_ETH_MAC_CLK_SPEED_200MHZ (200000000U) /**< ETH MAC clock speed 200 MHZ */
127 #define XMC_ETH_MAC_CLK_SPEED_250MHZ (250000000U) /**< ETH MAC clock speed 250 MHZ */
128 
129 /**
130  * ETH MAC MDC divider
131  */
132 #define XMC_ETH_MAC_MDC_DIVIDER_16  (2U << ETH_GMII_ADDRESS_CR_Pos) /**< MDC clock: ETH clock/16 */
133 #define XMC_ETH_MAC_MDC_DIVIDER_26  (3U << ETH_GMII_ADDRESS_CR_Pos) /**< MDC clock: ETH clock/26 */
134 #define XMC_ETH_MAC_MDC_DIVIDER_42  (0U << ETH_GMII_ADDRESS_CR_Pos) /**< MDC clock: ETH clock/42 */
135 #define XMC_ETH_MAC_MDC_DIVIDER_62  (1U << ETH_GMII_ADDRESS_CR_Pos) /**< MDC clock: ETH clock/62 */
136 #define XMC_ETH_MAC_MDC_DIVIDER_102 (4U << ETH_GMII_ADDRESS_CR_Pos) /**< MDC clock: ETH clock/102 */
137 #define XMC_ETH_MAC_MDC_DIVIDER_124 (5U << ETH_GMII_ADDRESS_CR_Pos) /**< MDC clock: ETH clock/124 */
138 
139 
140 /**
141  * RDES1 Descriptor RX Packet Control
142  */
143 #define ETH_MAC_DMA_RDES1_RBS2 (0x1FFF0000U) /**< Receive buffer 2 size */
144 #define ETH_MAC_DMA_RDES1_RER  (0x00008000U) /**< Receive end of ring */
145 #define ETH_MAC_DMA_RDES1_RCH  (0x00004000U) /**< Second address chained */
146 #define ETH_MAC_DMA_RDES1_RBS1 (0x00001FFFU) /**< Receive buffer 1 size */
147 
148 /**
149  * Interrupt masking
150  */
151 #define ETH_MAC_DISABLE_MMC_INTERRUPT_MSK              (0x03ffffffU) /**< Bit mask to disable MMMC transmit and receive interrupts */
152 #define ETH_MAC_DISABLE_MMC_IPC_RECEIVE_INTERRUPT_MSK  (0x3fff3fffU) /**< Bit mask to disable MMC IPC Receive Checksum Offload Interrupt Mask */
153 
154 /**
155  * Normal MAC events
156  */
157 #define ETH_MAC_EVENT_NORMAL (XMC_ETH_MAC_EVENT_TRANSMIT |\
158                               XMC_ETH_MAC_EVENT_TRANSMIT_BUFFER_UNAVAILABLE |\
159                               XMC_ETH_MAC_EVENT_RECEIVE |\
160                               XMC_ETH_MAC_EVENT_EARLY_RECEIVE)
161 
162 /**
163  * Abnormal MAC events
164  */
165 #define ETH_MAC_EVENT_ABNORMAL (XMC_ETH_MAC_EVENT_TRANSMIT_PROCESS_STOPPED |\
166                                 XMC_ETH_MAC_EVENT_TRANSMIT_JABBER_TIMEOUT |\
167                                 XMC_ETH_MAC_EVENT_RECEIVE_OVERFLOW |\
168                                 XMC_ETH_MAC_EVENT_TRANSMIT_UNDERFLOW |\
169                                 XMC_ETH_MAC_EVENT_RECEIVE_BUFFER_UNAVAILABLE |\
170                                 XMC_ETH_MAC_EVENT_RECEIVE_PROCESS_STOPPED |\
171                                 XMC_ETH_MAC_EVENT_RECEIVE_WATCHDOG_TIMEOUT |\
172                                 XMC_ETH_MAC_EVENT_EARLY_TRANSMIT |\
173                                 XMC_ETH_MAC_EVENT_BUS_ERROR)
174 
175 /* Definition needed in case of device header file previous to v1.5.1*/
176 #ifndef ETH_BUS_MODE_ATDS_Msk
177 #define ETH_BUS_MODE_ATDS_Msk  (0x00000080UL)
178 #endif
179 
180 /* Resolution of sub second counter ~ 20ns */
181 #define XMC_ETH_SUB_SECOND_UPDATE_FREQ (50000000)
182 
183 /*******************************************************************************
184  * API IMPLEMENTATION
185  *******************************************************************************/
186 
187 /* Check if the event passed is a normal event */
XCM_ETH_MAC_IsNormalEvent(uint32_t event)188 __STATIC_INLINE bool XCM_ETH_MAC_IsNormalEvent(uint32_t event)
189 {
190   return (bool)((event & ((uint32_t)XMC_ETH_MAC_EVENT_TRANSMIT |
191                           (uint32_t)XMC_ETH_MAC_EVENT_TRANSMIT_BUFFER_UNAVAILABLE |
192                           (uint32_t)XMC_ETH_MAC_EVENT_RECEIVE |
193                           (uint32_t)XMC_ETH_MAC_EVENT_EARLY_RECEIVE)) != (uint32_t)0);
194 }
195 
196 /* Check if the event passed is an abnormal event */
XCM_ETH_MAC_IsAbnormalEvent(uint32_t event)197 __STATIC_INLINE bool XCM_ETH_MAC_IsAbnormalEvent(uint32_t event)
198 {
199    return (bool)((event & ((uint32_t)XMC_ETH_MAC_EVENT_TRANSMIT_PROCESS_STOPPED |
200                            (uint32_t)XMC_ETH_MAC_EVENT_TRANSMIT_JABBER_TIMEOUT |
201                            (uint32_t)XMC_ETH_MAC_EVENT_RECEIVE_OVERFLOW |
202                            (uint32_t)XMC_ETH_MAC_EVENT_TRANSMIT_UNDERFLOW |
203                            (uint32_t)XMC_ETH_MAC_EVENT_RECEIVE_BUFFER_UNAVAILABLE |
204                            (uint32_t)XMC_ETH_MAC_EVENT_RECEIVE_PROCESS_STOPPED |
205                            (uint32_t)XMC_ETH_MAC_EVENT_RECEIVE_WATCHDOG_TIMEOUT |
206                            (uint32_t)XMC_ETH_MAC_EVENT_EARLY_TRANSMIT |
207                            (uint32_t)XMC_ETH_MAC_EVENT_BUS_ERROR)) != (uint32_t)0);
208  }
209 
210 #ifdef XMC_ASSERT_ENABLE
211 
212 /* Check if the passed argument is a valid ETH module */
XMC_ETH_MAC_IsValidModule(ETH_GLOBAL_TypeDef * const eth)213 __STATIC_INLINE bool XMC_ETH_MAC_IsValidModule(ETH_GLOBAL_TypeDef *const eth)
214 {
215   return (eth == ETH0);
216 }
217 
218 #endif
219 
XMC_ETH_MAC_InitEx(XMC_ETH_MAC_t * const eth_mac)220 void XMC_ETH_MAC_InitEx(XMC_ETH_MAC_t *const eth_mac)
221 {
222   XMC_ASSERT("XMC_ETH_MAC_InitEx: eth_mac is invalid", XMC_ETH_MAC_IsValidModule(eth_mac->regs));
223 
224   XMC_ETH_MAC_Reset(eth_mac);
225 
226   /* Initialize MAC configuration */
227   eth_mac->regs->MAC_CONFIGURATION = (uint32_t)ETH_MAC_CONFIGURATION_IPC_Msk;
228 
229   /* Initialize Filter registers */
230   eth_mac->regs->FLOW_CONTROL = ETH_FLOW_CONTROL_DZPQ_Msk; /* Disable Zero Quanta Pause */
231 
232   eth_mac->regs->OPERATION_MODE = (uint32_t)ETH_OPERATION_MODE_RSF_Msk |
233 	                              (uint32_t)ETH_OPERATION_MODE_TSF_Msk |
234 	                              (uint32_t)ETH_OPERATION_MODE_OSF_Msk;
235 
236   /* Increase enhanced descriptor to 8 WORDS, required when the Advanced Time-Stamp feature or Full IPC Offload Engine is enabled */
237   eth_mac->regs->BUS_MODE = (uint32_t)ETH_BUS_MODE_ATDS_Msk |
238 	                        (uint32_t)ETH_BUS_MODE_AAL_Msk | /* the AHB interface generates all bursts aligned to the start address LS bits */
239 	                        (uint32_t)ETH_BUS_MODE_FB_Msk | /* DMA attempts to execute fixed-length Burst transfers on the AHB Master interface */
240 	                        (uint32_t)(0x20 << ETH_BUS_MODE_PBL_Pos); /* maximum Burst length */
241 
242   /* Initialize DMA Descriptors */
243   XMC_ETH_MAC_InitRxDescriptors(eth_mac);
244   XMC_ETH_MAC_InitTxDescriptors(eth_mac);
245 
246   /* Clear interrupts */
247   eth_mac->regs->STATUS = 0xFFFFFFFFUL;
248 
249   /* Disable MMC interrupt events */
250   eth_mac->regs->MMC_TRANSMIT_INTERRUPT_MASK = ETH_MAC_DISABLE_MMC_INTERRUPT_MSK;
251   eth_mac->regs->MMC_RECEIVE_INTERRUPT_MASK = ETH_MAC_DISABLE_MMC_INTERRUPT_MSK;
252   eth_mac->regs->MMC_IPC_RECEIVE_INTERRUPT_MASK = ETH_MAC_DISABLE_MMC_IPC_RECEIVE_INTERRUPT_MSK;
253 
254   /* Disable PMT and timestamp interrupt events */
255   eth_mac->regs->INTERRUPT_MASK = ETH_INTERRUPT_MASK_PMTIM_Msk | ETH_INTERRUPT_MASK_TSIM_Msk;
256 
257   eth_mac->frame_end = NULL;
258 }
259 
260 /* ETH MAC initialize */
XMC_ETH_MAC_Init(XMC_ETH_MAC_t * const eth_mac)261 XMC_ETH_MAC_STATUS_t XMC_ETH_MAC_Init(XMC_ETH_MAC_t *const eth_mac)
262 {
263   XMC_ETH_MAC_STATUS_t status;
264 
265   XMC_ASSERT("XMC_ETH_MAC_Init: eth_mac is invalid", XMC_ETH_MAC_IsValidModule(eth_mac->regs));
266 
267   XMC_ETH_MAC_Enable(eth_mac);
268   status = XMC_ETH_MAC_SetManagmentClockDivider(eth_mac);
269 
270   XMC_ETH_MAC_InitEx(eth_mac);
271 
272   XMC_ETH_MAC_SetAddress(eth_mac, eth_mac->address);
273 
274   return status;
275 }
276 
277 /* Initialize RX descriptors */
XMC_ETH_MAC_InitRxDescriptors(XMC_ETH_MAC_t * const eth_mac)278 void XMC_ETH_MAC_InitRxDescriptors(XMC_ETH_MAC_t *const eth_mac)
279 {
280   uint32_t i;
281   uint32_t next;
282 
283   XMC_ASSERT("XMC_ETH_MAC_InitRxDescriptors: eth_mac is invalid", XMC_ETH_MAC_IsValidModule(eth_mac->regs));
284 
285   /*
286    * Chained structure (ETH_MAC_DMA_RDES1_RCH), second address in the descriptor
287    * (buffer2) is the next descriptor address
288    */
289   for (i = 0U; i < eth_mac->num_rx_buf; ++i)
290   {
291   eth_mac->rx_desc[i].status = (uint32_t)ETH_MAC_DMA_RDES0_OWN;
292   eth_mac->rx_desc[i].length = (uint32_t)ETH_MAC_DMA_RDES1_RCH | (uint32_t)XMC_ETH_MAC_BUF_SIZE;
293   eth_mac->rx_desc[i].buffer1 = (uint32_t)&(eth_mac->rx_buf[i * XMC_ETH_MAC_BUF_SIZE]);
294     next = i + 1U;
295     if (next == eth_mac->num_rx_buf)
296     {
297       next = 0U;
298     }
299     eth_mac->rx_desc[i].buffer2 = (uint32_t)&(eth_mac->rx_desc[next]);
300   }
301   eth_mac->regs->RECEIVE_DESCRIPTOR_LIST_ADDRESS = (uint32_t)&(eth_mac->rx_desc[0]);
302   eth_mac->rx_index = 0U;
303 }
304 
305 /* Initialize TX descriptors */
XMC_ETH_MAC_InitTxDescriptors(XMC_ETH_MAC_t * const eth_mac)306 void XMC_ETH_MAC_InitTxDescriptors(XMC_ETH_MAC_t *const eth_mac)
307 {
308   uint32_t i;
309   uint32_t next;
310 
311   XMC_ASSERT("XMC_ETH_MAC_InitTxDescriptors: eth_mac is invalid", XMC_ETH_MAC_IsValidModule(eth_mac->regs));
312 
313   /* Chained structure (ETH_MAC_DMA_TDES0_TCH), second address in the descriptor (buffer2) is the next descriptor address */
314   for (i = 0U; i < eth_mac->num_tx_buf; ++i)
315   {
316   eth_mac->tx_desc[i].status = ETH_MAC_DMA_TDES0_TCH | ETH_MAC_DMA_TDES0_LS | ETH_MAC_DMA_TDES0_FS;
317   eth_mac->tx_desc[i].buffer1 = (uint32_t)&(eth_mac->tx_buf[i * XMC_ETH_MAC_BUF_SIZE]);
318     next = i + 1U;
319     if (next == eth_mac->num_tx_buf)
320     {
321         next = 0U;
322     }
323     eth_mac->tx_desc[i].buffer2 = (uint32_t)&(eth_mac->tx_desc[next]);
324   }
325   eth_mac->regs->TRANSMIT_DESCRIPTOR_LIST_ADDRESS = (uint32_t)&(eth_mac->tx_desc[0]);
326   eth_mac->tx_index = 0U;
327 }
328 
XMC_ETH_MAC_SetAddressEx(XMC_ETH_MAC_t * const eth_mac,uint8_t * const addr)329 void XMC_ETH_MAC_SetAddressEx(XMC_ETH_MAC_t *const eth_mac, uint8_t *const addr)
330 {
331   eth_mac->regs->MAC_ADDRESS0_HIGH = addr[4] | (addr[5] << 8);
332   eth_mac->regs->MAC_ADDRESS0_LOW = addr[0] | (addr[1] << 8) | (addr[2] << 16) | (addr[3] << 24);
333 }
334 
XMC_ETH_MAC_GetAddressEx(XMC_ETH_MAC_t * const eth_mac,uint8_t * const addr)335 void XMC_ETH_MAC_GetAddressEx(XMC_ETH_MAC_t *const eth_mac, uint8_t *const addr)
336 {
337   uint32_t low_addr = eth_mac->regs->MAC_ADDRESS0_LOW;
338   uint32_t high_addr = eth_mac->regs->MAC_ADDRESS0_HIGH;
339 
340   addr[0] = low_addr & 0xff;
341   addr[1] = (low_addr >> 8) & 0xff;
342   addr[2] = (low_addr >> 16) & 0xff;
343   addr[3] = (low_addr >> 24) & 0xff;
344   addr[4] = high_addr & 0xff;
345   addr[5] = (high_addr >> 8) & 0xff;
346 }
347 
348 /* Set address perfect filter */
XMC_ETH_MAC_SetAddressPerfectFilter(XMC_ETH_MAC_t * const eth_mac,uint8_t index,const uint64_t addr,uint32_t flags)349 void XMC_ETH_MAC_SetAddressPerfectFilter(XMC_ETH_MAC_t *const eth_mac,
350                                          uint8_t index,
351                                          const uint64_t addr,
352                                          uint32_t flags)
353 {
354   __IO uint32_t *reg;
355 
356   XMC_ASSERT("XMC_ETH_MAC_SetAddressPerfectFilter: eth_mac is invalid", XMC_ETH_MAC_IsValidModule(eth_mac->regs));
357   XMC_ASSERT("XMC_ETH_MAC_SetAddressFilter: index is out of range", ((index > 0) && (index < 4)));
358 
359   reg = &(eth_mac->regs->MAC_ADDRESS0_HIGH);
360   reg[index] = (uint32_t)(addr >> 32U) | flags;
361   reg[index + 1U] = (uint32_t)addr;
362 }
363 
XMC_ETH_MAC_SetAddressPerfectFilterEx(XMC_ETH_MAC_t * const eth_mac,uint8_t index,uint8_t * const addr,uint32_t flags)364 void XMC_ETH_MAC_SetAddressPerfectFilterEx(XMC_ETH_MAC_t *const eth_mac,
365                                            uint8_t index,
366                                            uint8_t *const addr,
367                                            uint32_t flags)
368 {
369   __IO uint32_t *reg;
370 
371   XMC_ASSERT("XMC_ETH_MAC_SetAddressPerfectFilter: eth_mac is invalid", XMC_ETH_MAC_IsValidModule(eth_mac->regs));
372   XMC_ASSERT("XMC_ETH_MAC_SetAddressFilter: index is out of range", ((index > 0) && (index < 4)));
373 
374   reg = &(eth_mac->regs->MAC_ADDRESS0_HIGH);
375   reg[index] = addr[4] | (addr[5] << 8) | flags;
376   reg[index + 1U] = addr[0] | (addr[1] << 8) | (addr[2] << 16) | (addr[3] << 24);
377 }
378 
379 /* Set address hash filter */
XMC_ETH_MAC_SetAddressHashFilter(XMC_ETH_MAC_t * const eth_mac,const uint64_t hash)380 void XMC_ETH_MAC_SetAddressHashFilter(XMC_ETH_MAC_t *const eth_mac, const uint64_t hash)
381 {
382   eth_mac->regs->HASH_TABLE_HIGH = (uint32_t)(hash >> 32);
383   eth_mac->regs->HASH_TABLE_LOW = (uint32_t)hash;
384 }
385 
386 /* Send frame */
XMC_ETH_MAC_SendFrame(XMC_ETH_MAC_t * const eth_mac,const uint8_t * frame,uint32_t len,uint32_t flags)387 XMC_ETH_MAC_STATUS_t XMC_ETH_MAC_SendFrame(XMC_ETH_MAC_t *const eth_mac, const uint8_t *frame, uint32_t len, uint32_t flags)
388 {
389   XMC_ETH_MAC_STATUS_t status;
390   uint8_t *dst;
391   uint32_t ctrl;
392 
393   XMC_ASSERT("XMC_ETH_MAC_SendFrame:", eth_mac != NULL);
394   XMC_ASSERT("XMC_ETH_MAC_SendFrame:", eth_mac->regs == ETH0);
395   XMC_ASSERT("XMC_ETH_MAC_SendFrame:", (frame != NULL) && (len > 0));
396 
397   dst = eth_mac->frame_end;
398 
399   if (eth_mac->tx_desc[eth_mac->tx_index].status & ETH_MAC_DMA_TDES0_OWN)
400   {
401     /* Transmitter is busy, wait */
402     status = XMC_ETH_MAC_STATUS_BUSY;
403     if (eth_mac->regs->STATUS & ETH_STATUS_TU_Msk)
404     {
405       /* Receive buffer unavailable, resume DMA */
406       eth_mac->regs->STATUS = (uint32_t)ETH_STATUS_TU_Msk;
407       eth_mac->regs->TRANSMIT_POLL_DEMAND = 0U;
408     }
409 
410   }
411   else
412   {
413     if (dst == NULL)
414     {
415       /* Start of a new transmit frame */
416       dst = (uint8_t *)eth_mac->tx_desc[eth_mac->tx_index].buffer1;
417       eth_mac->tx_desc[eth_mac->tx_index].length = len;
418     }
419     else
420     {
421       /* Sending data fragments in progress */
422       eth_mac->tx_desc[eth_mac->tx_index].length += len;
423     }
424 
425     memcpy(dst, frame, len);
426 
427     if (flags & (uint32_t)XMC_ETH_MAC_TX_FRAME_FRAGMENT)
428     {
429       /* More data to come, remember current write position */
430       eth_mac->frame_end = dst;
431     }
432     else
433     {
434       /* Frame is now ready, send it to DMA */
435       ctrl = eth_mac->tx_desc[eth_mac->tx_index].status | ETH_MAC_DMA_TDES0_CIC;
436       ctrl &= ~(ETH_MAC_DMA_TDES0_IC | ETH_MAC_DMA_TDES0_TTSE);
437 
438       if (flags & (uint32_t)XMC_ETH_MAC_TX_FRAME_EVENT)
439       {
440       ctrl |= ETH_MAC_DMA_TDES0_IC;
441       }
442 
443       if (flags & (uint32_t)XMC_ETH_MAC_TX_FRAME_TIMESTAMP)
444       {
445       ctrl |= ETH_MAC_DMA_TDES0_TTSE;
446       }
447       eth_mac->tx_ts_index = eth_mac->tx_index;
448 
449       eth_mac->tx_desc[eth_mac->tx_index].status = ctrl | ETH_MAC_DMA_TDES0_OWN;
450 
451       eth_mac->tx_index++;
452       if (eth_mac->tx_index == eth_mac->num_tx_buf)
453       {
454       eth_mac->tx_index = 0U;
455       }
456       eth_mac->frame_end = NULL;
457 
458       /* Start frame transmission */
459       eth_mac->regs->STATUS = (uint32_t)ETH_STATUS_TPS_Msk;
460       eth_mac->regs->TRANSMIT_POLL_DEMAND = 0U;
461     }
462     status = XMC_ETH_MAC_STATUS_OK;
463   }
464 
465   return status;
466 }
467 
468 /* Read frame */
XMC_ETH_MAC_ReadFrame(XMC_ETH_MAC_t * const eth_mac,uint8_t * frame,uint32_t len)469 uint32_t XMC_ETH_MAC_ReadFrame(XMC_ETH_MAC_t *const eth_mac, uint8_t *frame, uint32_t len)
470 {
471   uint8_t const *src;
472 
473   XMC_ASSERT("XMC_ETH_MAC_ReadFrame:", eth_mac != NULL);
474   XMC_ASSERT("XMC_ETH_MAC_ReadFrame:", eth_mac->regs == ETH0);
475   XMC_ASSERT("XMC_ETH_MAC_ReadFrame:", (frame != NULL) && (len > 0));
476 
477   /* Fast-copy data to packet buffer */
478   src = (uint8_t const *)eth_mac->rx_desc[eth_mac->rx_index].buffer1;
479 
480   memcpy(frame, src, len);
481 
482   /* Return this block back to DMA */
483   eth_mac->rx_desc[eth_mac->rx_index].status = ETH_MAC_DMA_RDES0_OWN;
484 
485   eth_mac->rx_index++;
486   if (eth_mac->rx_index == eth_mac->num_rx_buf)
487   {
488     eth_mac->rx_index = 0U;
489   }
490 
491   if (eth_mac->regs->STATUS & ETH_STATUS_RU_Msk)
492   {
493     /* Receive buffer unavailable, resume DMA */
494   eth_mac->regs->STATUS = (uint32_t)ETH_STATUS_RU_Msk;
495   eth_mac->regs->RECEIVE_POLL_DEMAND = 0U;
496   }
497 
498   return (len);
499 }
500 
501 /* Get RX frame size */
XMC_ETH_MAC_GetRxFrameSize(XMC_ETH_MAC_t * const eth_mac)502 uint32_t XMC_ETH_MAC_GetRxFrameSize(XMC_ETH_MAC_t *const eth_mac)
503 {
504   uint32_t status;
505   uint32_t len = 0U;
506 
507   status = eth_mac->rx_desc[eth_mac->rx_index].status;
508 
509   if (status & ETH_MAC_DMA_RDES0_OWN)
510   {
511     /* Owned by DMA */
512     len = 0U;
513   }
514   else if (((status & ETH_MAC_DMA_RDES0_ES) != 0U) ||
515            ((status & ETH_MAC_DMA_RDES0_FS) == 0U) ||
516            ((status & ETH_MAC_DMA_RDES0_LS) == 0U))
517   {
518     /* Error, this block is invalid */
519     len = 0xFFFFFFFFU;
520   }
521   else
522   {
523     /* Subtract CRC */
524     len = ((status & ETH_MAC_DMA_RDES0_FL) >> 16U) - 4U;
525   }
526 
527   return len;
528 }
529 
530 /* Set management clock divider */
XMC_ETH_MAC_SetManagmentClockDivider(XMC_ETH_MAC_t * const eth_mac)531 XMC_ETH_MAC_STATUS_t XMC_ETH_MAC_SetManagmentClockDivider(XMC_ETH_MAC_t *const eth_mac)
532 {
533   uint32_t eth_mac_clk;
534   XMC_ETH_MAC_STATUS_t status;
535   __IO uint32_t *reg;
536 
537   eth_mac_clk = XMC_SCU_CLOCK_GetEthernetClockFrequency();
538   status = XMC_ETH_MAC_STATUS_OK;
539 
540   reg = &(eth_mac->regs->GMII_ADDRESS);
541   if (eth_mac_clk <= XMC_ETH_MAC_CLK_SPEED_35MHZ)
542   {
543     *reg = XMC_ETH_MAC_MDC_DIVIDER_16;
544   }
545   else if (eth_mac_clk <= XMC_ETH_MAC_CLK_SPEED_60MHZ)
546   {
547     *reg = XMC_ETH_MAC_MDC_DIVIDER_26;
548   }
549   else if (eth_mac_clk <= XMC_ETH_MAC_CLK_SPEED_100MHZ)
550   {
551     *reg = XMC_ETH_MAC_MDC_DIVIDER_42;
552   }
553   else if (eth_mac_clk <= XMC_ETH_MAC_CLK_SPEED_150MHZ)
554   {
555     *reg = XMC_ETH_MAC_MDC_DIVIDER_62;
556   }
557   else if (eth_mac_clk <= XMC_ETH_MAC_CLK_SPEED_200MHZ)
558   {
559     *reg = XMC_ETH_MAC_MDC_DIVIDER_102;
560   }
561   else if (eth_mac_clk <= XMC_ETH_MAC_CLK_SPEED_250MHZ)
562   {
563     *reg = XMC_ETH_MAC_MDC_DIVIDER_124;
564   }
565   else
566   {
567     status = XMC_ETH_MAC_STATUS_ERROR;
568   }
569 
570   return status;
571 }
572 
573 /* ETH MAC enable */
XMC_ETH_MAC_Enable(XMC_ETH_MAC_t * const eth_mac)574 void XMC_ETH_MAC_Enable(XMC_ETH_MAC_t *const eth_mac)
575 {
576   XMC_UNUSED_ARG(eth_mac);
577 
578   XMC_SCU_CLOCK_EnableClock(XMC_SCU_CLOCK_ETH);
579 #if UC_DEVICE != XMC4500
580   XMC_SCU_CLOCK_UngatePeripheralClock(XMC_SCU_PERIPHERAL_CLOCK_ETH0);
581 #endif
582   XMC_SCU_RESET_DeassertPeripheralReset(XMC_SCU_PERIPHERAL_RESET_ETH0);
583 }
584 
585 /* ETH MAC disable */
XMC_ETH_MAC_Disable(XMC_ETH_MAC_t * const eth_mac)586 void XMC_ETH_MAC_Disable(XMC_ETH_MAC_t *const eth_mac)
587 {
588   XMC_UNUSED_ARG(eth_mac);
589 
590   XMC_SCU_RESET_AssertPeripheralReset(XMC_SCU_PERIPHERAL_RESET_ETH0);
591 #if UC_DEVICE != XMC4500
592   XMC_SCU_CLOCK_GatePeripheralClock(XMC_SCU_PERIPHERAL_CLOCK_ETH0);
593 #endif
594   XMC_SCU_CLOCK_DisableClock(XMC_SCU_CLOCK_ETH);
595 }
596 
597 /* Read physical layer and obtain status */
XMC_ETH_MAC_ReadPhy(XMC_ETH_MAC_t * eth_mac,uint8_t phy_addr,uint8_t reg_addr,uint16_t * data)598 XMC_ETH_MAC_STATUS_t XMC_ETH_MAC_ReadPhy(XMC_ETH_MAC_t *eth_mac, uint8_t phy_addr, uint8_t reg_addr, uint16_t *data)
599 {
600   uint32_t retries;
601 
602   XMC_ASSERT("XMC_ETH_MAC_PhyRead: Parameter error", data != NULL);
603 
604   eth_mac->regs->GMII_ADDRESS = (uint32_t)((eth_mac->regs->GMII_ADDRESS & (uint32_t)ETH_GMII_ADDRESS_CR_Msk) |
605                                            (uint32_t)ETH_GMII_ADDRESS_MB_Msk |
606                                            (uint32_t)((uint32_t)phy_addr << ETH_GMII_ADDRESS_PA_Pos) |
607                                            (uint32_t)((uint32_t)reg_addr << ETH_GMII_ADDRESS_MR_Pos));
608 
609   /* Poll busy bit during max PHY_TIMEOUT time */
610   retries = 0U;
611   do
612   {
613     if ((eth_mac->regs->GMII_ADDRESS & ETH_GMII_ADDRESS_MB_Msk) == 0U)
614     {
615       *data = (uint16_t)(eth_mac->regs->GMII_DATA & ETH_GMII_DATA_MD_Msk);
616       return XMC_ETH_MAC_STATUS_OK;
617     }
618     ++retries;
619   } while (retries < XMC_ETH_MAC_PHY_MAX_RETRIES);
620 
621   return XMC_ETH_MAC_STATUS_ERROR;
622 }
623 
624 /* Write physical layer and return status */
XMC_ETH_MAC_WritePhy(XMC_ETH_MAC_t * eth_mac,uint8_t phy_addr,uint8_t reg_addr,uint16_t data)625 XMC_ETH_MAC_STATUS_t XMC_ETH_MAC_WritePhy(XMC_ETH_MAC_t *eth_mac, uint8_t phy_addr, uint8_t reg_addr, uint16_t data)
626 {
627   uint32_t retries;
628 
629   eth_mac->regs->GMII_DATA  = data;
630   eth_mac->regs->GMII_ADDRESS = (uint32_t)((eth_mac->regs->GMII_ADDRESS & (uint32_t)ETH_GMII_ADDRESS_CR_Msk) |
631                                            (uint32_t)ETH_GMII_ADDRESS_MB_Msk |
632                                            (uint32_t)ETH_GMII_ADDRESS_MW_Msk |
633                                            (uint32_t)((uint32_t)phy_addr << ETH_GMII_ADDRESS_PA_Pos) |
634                                            (uint32_t)((uint32_t)reg_addr << ETH_GMII_ADDRESS_MR_Pos));
635 
636    /* Poll busy bit during max PHY_TIMEOUT time */
637   retries = 0U;
638   do
639   {
640     if ((eth_mac->regs->GMII_ADDRESS & ETH_GMII_ADDRESS_MB_Msk) == 0U)
641     {
642       return XMC_ETH_MAC_STATUS_OK;
643     }
644     ++retries;
645   } while (retries < XMC_ETH_MAC_PHY_MAX_RETRIES);
646 
647   return XMC_ETH_MAC_STATUS_ERROR;
648 }
649 
650 /* Flush TX */
XMC_ETH_MAC_FlushTx(XMC_ETH_MAC_t * const eth_mac)651 void XMC_ETH_MAC_FlushTx(XMC_ETH_MAC_t *const eth_mac)
652 {
653   eth_mac->regs->OPERATION_MODE &= (uint32_t)~ETH_OPERATION_MODE_ST_Msk;
654   XMC_ETH_MAC_InitTxDescriptors(eth_mac);
655   eth_mac->regs->OPERATION_MODE |= (uint32_t)ETH_OPERATION_MODE_ST_Msk;
656 }
657 
658 /* Flush RX */
XMC_ETH_MAC_FlushRx(XMC_ETH_MAC_t * const eth_mac)659 void XMC_ETH_MAC_FlushRx(XMC_ETH_MAC_t *const eth_mac)
660 {
661   eth_mac->regs->OPERATION_MODE &= (uint32_t)~ETH_OPERATION_MODE_SR_Msk;
662   XMC_ETH_MAC_InitRxDescriptors(eth_mac);
663   eth_mac->regs->OPERATION_MODE |= (uint32_t)ETH_OPERATION_MODE_SR_Msk;
664 }
665 
666 /* Set wakeup frame filter */
XMC_ETH_MAC_SetWakeUpFrameFilter(XMC_ETH_MAC_t * const eth_mac,const uint32_t (* const filter)[XMC_ETH_WAKEUP_REGISTER_LENGTH])667 void XMC_ETH_MAC_SetWakeUpFrameFilter(XMC_ETH_MAC_t *const eth_mac,
668                                       const uint32_t (*const filter)[XMC_ETH_WAKEUP_REGISTER_LENGTH])
669 {
670   uint32_t i = 0U;
671 
672   /* Fill Remote Wake-up frame filter register with buffer data */
673   for (i = 0U; i < XMC_ETH_WAKEUP_REGISTER_LENGTH; i++)
674   {
675     /* Write each time to the same register */
676     eth_mac->regs->REMOTE_WAKE_UP_FRAME_FILTER = (*filter)[i];
677   }
678 }
679 
680 /* Enable event */
XMC_ETH_MAC_EnableEvent(XMC_ETH_MAC_t * const eth_mac,uint32_t event)681 void XMC_ETH_MAC_EnableEvent(XMC_ETH_MAC_t *const eth_mac, uint32_t event)
682 {
683   XMC_ASSERT("XMC_ETH_MAC_EnableDMAEvent: eth_mac is invalid", XMC_ETH_MAC_IsValidModule(eth_mac->regs));
684 
685   eth_mac->regs->INTERRUPT_MASK &= ~(event >> 16U);
686 
687   event &= (uint16_t)0x7fffU;
688   if (XCM_ETH_MAC_IsNormalEvent(event))
689   {
690   event |= (uint32_t)ETH_INTERRUPT_ENABLE_NIE_Msk;
691   }
692 
693   if (XCM_ETH_MAC_IsAbnormalEvent(event))
694   {
695   event |= (uint32_t)ETH_INTERRUPT_ENABLE_AIE_Msk;
696   }
697 
698   eth_mac->regs->INTERRUPT_ENABLE |= event;
699 }
700 
701 /* Disable event */
XMC_ETH_MAC_DisableEvent(XMC_ETH_MAC_t * const eth_mac,uint32_t event)702 void XMC_ETH_MAC_DisableEvent(XMC_ETH_MAC_t *const eth_mac, uint32_t event)
703 {
704   XMC_ASSERT("XMC_ETH_MAC_DisableDMAEvent: eth_mac is invalid", XMC_ETH_MAC_IsValidModule(eth_mac->regs));
705 
706   eth_mac->regs->INTERRUPT_MASK |= event >> 16U;
707 
708   event &= 0x7fffU;
709   eth_mac->regs->INTERRUPT_ENABLE &= ~event;
710 }
711 
712 /* Clear event status */
XMC_ETH_MAC_ClearEventStatus(XMC_ETH_MAC_t * const eth_mac,uint32_t event)713 void XMC_ETH_MAC_ClearEventStatus(XMC_ETH_MAC_t *const eth_mac, uint32_t event)
714 {
715   XMC_ASSERT("XMC_ETH_MAC_ClearEventStatus: eth_mac is invalid", XMC_ETH_MAC_IsValidModule(eth_mac->regs));
716 
717   if ((eth_mac->regs->STATUS & ETH_STATUS_NIS_Msk) != 0U)
718   {
719     event |= (uint32_t)ETH_STATUS_NIS_Msk;
720   }
721 
722   if ((eth_mac->regs->STATUS & ETH_STATUS_AIS_Msk) != 0U)
723   {
724     event |= (uint32_t)ETH_STATUS_AIS_Msk;
725   }
726 
727   eth_mac->regs->STATUS = event & 0x0001FFFFU;
728 }
729 
730 /* Obtain event status */
XMC_ETH_MAC_GetEventStatus(const XMC_ETH_MAC_t * const eth_mac)731 uint32_t XMC_ETH_MAC_GetEventStatus(const XMC_ETH_MAC_t *const eth_mac)
732 {
733   uint32_t temp_status = 0;
734   XMC_ASSERT("XMC_ETH_MAC_GetEventStatus: eth_mac is invalid", XMC_ETH_MAC_IsValidModule(eth_mac->regs));
735 
736   temp_status =  (eth_mac->regs->STATUS & (uint32_t)0x7ffUL);
737 
738   return ((uint32_t)((eth_mac->regs->INTERRUPT_STATUS & (ETH_INTERRUPT_MASK_PMTIM_Msk | ETH_INTERRUPT_MASK_TSIM_Msk)) << 16U) |
739       temp_status);
740 }
741 
742 /* Return RX descriptor */
XMC_ETH_MAC_ReturnRxDescriptor(XMC_ETH_MAC_t * const eth_mac)743 void XMC_ETH_MAC_ReturnRxDescriptor(XMC_ETH_MAC_t *const eth_mac)
744 {
745   eth_mac->rx_desc[eth_mac->rx_index].status |= ETH_MAC_DMA_RDES0_OWN;
746   eth_mac->rx_index++;
747   if (eth_mac->rx_index == eth_mac->num_rx_buf)
748   {
749     eth_mac->rx_index = 0U;
750   }
751 }
752 
753 /* Return TX descriptor */
XMC_ETH_MAC_ReturnTxDescriptor(XMC_ETH_MAC_t * const eth_mac)754 void XMC_ETH_MAC_ReturnTxDescriptor(XMC_ETH_MAC_t *const eth_mac)
755 {
756   eth_mac->tx_ts_index = eth_mac->tx_index;
757 
758   eth_mac->tx_desc[eth_mac->tx_index].status |= ETH_MAC_DMA_TDES0_CIC |ETH_MAC_DMA_TDES0_OWN;
759   eth_mac->tx_index++;
760   if (eth_mac->tx_index == eth_mac->num_tx_buf)
761   {
762     eth_mac->tx_index = 0U;
763   }
764 
765   eth_mac->frame_end = NULL;
766 }
767 
768 /* Set VLAN tag */
XMC_ETH_MAC_SetVLANTag(XMC_ETH_MAC_t * const eth_mac,uint32_t tag)769 void XMC_ETH_MAC_SetVLANTag(XMC_ETH_MAC_t *const eth_mac, uint32_t tag)
770 {
771   XMC_ASSERT("XMC_ETH_MAC_SetVLANTag: eth_mac is invalid", XMC_ETH_MAC_IsValidModule(eth_mac->regs));
772 
773   eth_mac->regs->VLAN_TAG = tag;
774 }
775 
776 /* Initialize PTP */
XMC_ETH_MAC_InitPTP(XMC_ETH_MAC_t * const eth_mac,uint32_t config)777 void XMC_ETH_MAC_InitPTP(XMC_ETH_MAC_t *const eth_mac, uint32_t config)
778 {
779   XMC_ASSERT("XMC_ETH_MAC_InitPTP: eth_mac is invalid", XMC_ETH_MAC_IsValidModule(eth_mac->regs));
780 
781   /* Mask the time stamp interrupt */
782   eth_mac->regs->INTERRUPT_MASK |= (uint32_t)ETH_INTERRUPT_MASK_TSIM_Msk;
783 
784   /* Enable time stamp, rollover mode of nanosecond counter set to digital mode, i.e. after 0x3B9AC9FF */
785   eth_mac->regs->TIMESTAMP_CONTROL = ETH_TIMESTAMP_CONTROL_TSENA_Msk | ETH_TIMESTAMP_CONTROL_TSCTRLSSR_Msk | config;
786 
787   if ((config & (uint32_t)XMC_ETH_MAC_TIMESTAMP_CONFIG_FINE_UPDATE) != 0U)
788   {
789     /* Program sub-second increment register based on PTP clock frequency ~ 50MHz */
790     eth_mac->regs->SUB_SECOND_INCREMENT = 20;
791 
792     /* fSYS = Reference Clock for the Time Stamp Update Logic*/
793     float ratio = (float)XMC_SCU_CLOCK_GetSystemClockFrequency() / (float)XMC_ETH_SUB_SECOND_UPDATE_FREQ;
794     eth_mac->regs->TIMESTAMP_ADDEND = (uint32_t)(((float)0x100000000ULL / ratio) + 0.5F);
795 
796     /* Addend register update */
797     eth_mac->regs->TIMESTAMP_CONTROL |= (uint32_t)ETH_TIMESTAMP_CONTROL_TSADDREG_Msk;
798 
799     /* Poll the Timestamp Control register until the bit TSADDREG is cleared */
800     while (eth_mac->regs->TIMESTAMP_CONTROL & ETH_TIMESTAMP_CONTROL_TSADDREG_Msk);
801   }
802   else
803   {
804   /* Program sub-second increment register based on PTP clock frequency = fSYS/2 */
805   eth_mac->regs->SUB_SECOND_INCREMENT = (uint32_t)(((float)1000000000 / (float)XMC_SCU_CLOCK_GetSystemClockFrequency()) + 0.5F);
806   }
807 
808   eth_mac->regs->TIMESTAMP_CONTROL |= (uint32_t)ETH_TIMESTAMP_CONTROL_TSINIT_Msk;
809   while (eth_mac->regs->TIMESTAMP_CONTROL & ETH_TIMESTAMP_CONTROL_TSINIT_Msk);
810 }
811 
812 /* Initialize PTP using a given time */
XMC_ETH_MAC_InitPTPEx(XMC_ETH_MAC_t * const eth_mac,uint32_t config,XMC_ETH_MAC_TIME_t * const time)813 void XMC_ETH_MAC_InitPTPEx(XMC_ETH_MAC_t *const eth_mac, uint32_t config, XMC_ETH_MAC_TIME_t *const time)
814 {
815   XMC_ASSERT("XMC_ETH_MAC_InitPTP: eth_mac is invalid", XMC_ETH_MAC_IsValidModule(eth_mac->regs));
816 
817   /* Initialize the system time */
818   eth_mac->regs->SYSTEM_TIME_NANOSECONDS_UPDATE = time->nanoseconds;
819   eth_mac->regs->SYSTEM_TIME_SECONDS_UPDATE = time->seconds;
820 
821   XMC_ETH_MAC_InitPTP(eth_mac, config);
822 }
823 
824 /* Get PTP time */
XMC_ETH_MAC_GetPTPTime(XMC_ETH_MAC_t * const eth_mac,XMC_ETH_MAC_TIME_t * const time)825 void XMC_ETH_MAC_GetPTPTime(XMC_ETH_MAC_t *const eth_mac, XMC_ETH_MAC_TIME_t *const time)
826 {
827   XMC_ASSERT("XMC_ETH_MAC_GetPTPTime: eth_mac is invalid", XMC_ETH_MAC_IsValidModule(eth_mac->regs));
828 
829   time->nanoseconds = (uint32_t)(eth_mac->regs->SYSTEM_TIME_NANOSECONDS); /* accuracy of 1 ns */
830   time->seconds = eth_mac->regs->SYSTEM_TIME_SECONDS;
831 }
832 
833 /* Set PTP time */
XMC_ETH_MAC_SetPTPTime(XMC_ETH_MAC_t * const eth_mac,XMC_ETH_MAC_TIME_t * const time)834 void XMC_ETH_MAC_SetPTPTime(XMC_ETH_MAC_t *const eth_mac, XMC_ETH_MAC_TIME_t *const time)
835 {
836   XMC_ASSERT("XMC_ETH_MAC_GetPTPTime: eth_mac is invalid", XMC_ETH_MAC_IsValidModule(eth_mac->regs));
837 
838   eth_mac->regs->SYSTEM_TIME_SECONDS_UPDATE = time->seconds;
839   eth_mac->regs->SYSTEM_TIME_NANOSECONDS_UPDATE = time->nanoseconds;
840 
841   /* Initialize precision timer */
842   ETH0->TIMESTAMP_CONTROL |= ETH_TIMESTAMP_CONTROL_TSINIT_Msk;
843   while (eth_mac->regs->TIMESTAMP_CONTROL & ETH_TIMESTAMP_CONTROL_TSINIT_Msk);
844 }
845 
846 /* Update PTP time */
XMC_ETH_MAC_UpdatePTPTime(XMC_ETH_MAC_t * const eth_mac,const XMC_ETH_MAC_TIME_t * const time)847 void XMC_ETH_MAC_UpdatePTPTime(XMC_ETH_MAC_t *const eth_mac, const XMC_ETH_MAC_TIME_t *const time)
848 {
849   uint32_t temp;
850 
851   XMC_ASSERT("XMC_ETH_MAC_UpdatePTPTime: eth_mac is invalid", XMC_ETH_MAC_IsValidModule(eth_mac->regs));
852   XMC_ASSERT("XMC_ETH_MAC_UpdatePTPTime: time.time_stamp_nanoseconds not in range", (time->nanoseconds < 1000000000.0F));
853 
854   temp = (uint32_t)(abs(time->nanoseconds));
855   if (time->nanoseconds < 0)
856   {
857     temp |= (uint32_t)ETH_SYSTEM_TIME_NANOSECONDS_UPDATE_ADDSUB_Msk;
858   }
859 
860   eth_mac->regs->SYSTEM_TIME_NANOSECONDS_UPDATE = temp;
861   eth_mac->regs->SYSTEM_TIME_SECONDS_UPDATE = time->seconds;
862 
863   eth_mac->regs->TIMESTAMP_CONTROL |= (uint32_t)ETH_TIMESTAMP_CONTROL_TSUPDT_Msk;
864 }
865 
866 /* Set PTP alarm */
XMC_ETH_MAC_SetPTPAlarm(XMC_ETH_MAC_t * const eth_mac,const XMC_ETH_MAC_TIME_t * const time)867 void XMC_ETH_MAC_SetPTPAlarm(XMC_ETH_MAC_t *const eth_mac, const XMC_ETH_MAC_TIME_t *const time)
868 {
869   XMC_ASSERT("XMC_ETH_MAC_SetPTPAlarm: eth_mac is invalid", XMC_ETH_MAC_IsValidModule(eth_mac->regs));
870   XMC_ASSERT("XMC_ETH_MAC_SetPTPAlarm: time.time_stamp_nanoseconds not in range", (time->nanoseconds < 1000000000.0F));
871 
872   eth_mac->regs->TARGET_TIME_NANOSECONDS = time->nanoseconds;
873   eth_mac->regs->TARGET_TIME_SECONDS = time->seconds;
874 }
875 
876 /* Adjust PTP clock */
XMC_ETH_MAC_AdjustPTPClock(XMC_ETH_MAC_t * const eth_mac,uint32_t correction)877 void XMC_ETH_MAC_AdjustPTPClock(XMC_ETH_MAC_t *const eth_mac, uint32_t correction)
878 {
879   XMC_ASSERT("XMC_ETH_MAC_AdjustPTPClock: eth_mac is invalid", XMC_ETH_MAC_IsValidModule(eth_mac->regs));
880 
881   /* Correction factor is Q31 (0x80000000 = 1.000000000) */
882   eth_mac->regs->TIMESTAMP_ADDEND = (uint32_t)(((uint64_t)correction * eth_mac->regs->TIMESTAMP_ADDEND) >> 31U);
883 
884   /* Update addend register */
885   eth_mac->regs->TIMESTAMP_CONTROL |= (uint32_t)ETH_TIMESTAMP_CONTROL_TSADDREG_Msk;
886 
887   /* Poll the Timestamp Control register until the bit TSADDREG is cleared */
888   while (eth_mac->regs->TIMESTAMP_CONTROL & ETH_TIMESTAMP_CONTROL_TSADDREG_Msk);
889 }
890 
891 /* Update Addend */
XMC_ETH_MAC_UpdateAddend(XMC_ETH_MAC_t * const eth_mac,uint32_t addend)892 void XMC_ETH_MAC_UpdateAddend(XMC_ETH_MAC_t *const eth_mac, uint32_t addend)
893 {
894   XMC_ASSERT("XMC_ETH_MAC_AdjustPTPClock: eth_mac is invalid", XMC_ETH_MAC_IsValidModule(eth_mac->regs));
895 
896   eth_mac->regs->TIMESTAMP_ADDEND = addend;
897 
898   /* Update addend register */
899   eth_mac->regs->TIMESTAMP_CONTROL |= (uint32_t)ETH_TIMESTAMP_CONTROL_TSADDREG_Msk;
900 
901   /* Poll the Timestamp Control register until the bit TSADDREG is cleared */
902   while (eth_mac->regs->TIMESTAMP_CONTROL & ETH_TIMESTAMP_CONTROL_TSADDREG_Msk);
903 }
904 
905 /* Set PTP status */
XMC_ETH_MAC_GetPTPStatus(const XMC_ETH_MAC_t * const eth_mac)906 uint32_t XMC_ETH_MAC_GetPTPStatus(const XMC_ETH_MAC_t *const eth_mac)
907 {
908   XMC_ASSERT("XMC_ETH_MAC_GetPTPStatus: eth_mac is invalid", XMC_ETH_MAC_IsValidModule(eth_mac->regs));
909 
910   return (eth_mac->regs->TIMESTAMP_STATUS);
911 }
912 
913 /* Get TX time-stamp */
XMC_ETH_MAC_GetRxTimeStamp(XMC_ETH_MAC_t * const eth_mac,XMC_ETH_MAC_TIME_t * const time)914 XMC_ETH_MAC_STATUS_t XMC_ETH_MAC_GetRxTimeStamp(XMC_ETH_MAC_t *const eth_mac, XMC_ETH_MAC_TIME_t *const time)
915 {
916   XMC_ETH_MAC_DMA_DESC_t *rx_desc;
917   XMC_ETH_MAC_STATUS_t status;
918 
919   XMC_ASSERT("XMC_ETH_MAC_GetRxTimeStamp: eth_mac is invalid", XMC_ETH_MAC_IsValidModule(eth_mac->regs));
920   XMC_ASSERT("XMC_ETH_MAC_GetRxTimeStamp: time is invalid", time != NULL);
921 
922   rx_desc = &eth_mac->rx_desc[eth_mac->rx_index];
923   if (rx_desc->status & ETH_MAC_DMA_RDES0_OWN)
924   {
925     status = XMC_ETH_MAC_STATUS_BUSY;
926   }
927   else
928   {
929     if ((rx_desc->status & (ETH_MAC_DMA_RDES0_TSA | ETH_MAC_DMA_RDES0_LS)) == (ETH_MAC_DMA_RDES0_TSA | ETH_MAC_DMA_RDES0_LS))
930     {
931       time->nanoseconds = (int32_t)(rx_desc->time_stamp_nanoseconds);
932       time->seconds = rx_desc->time_stamp_seconds;
933 
934       status = XMC_ETH_MAC_STATUS_OK;
935     }
936     else
937     {
938       status = XMC_ETH_MAC_STATUS_ERROR;
939     }
940   }
941 
942   return status;
943 }
944 
945 /* Get TX time-stamp */
XMC_ETH_MAC_GetTxTimeStamp(XMC_ETH_MAC_t * const eth_mac,XMC_ETH_MAC_TIME_t * const time)946 XMC_ETH_MAC_STATUS_t XMC_ETH_MAC_GetTxTimeStamp(XMC_ETH_MAC_t *const eth_mac, XMC_ETH_MAC_TIME_t *const time)
947 {
948   XMC_ETH_MAC_DMA_DESC_t *tx_desc;
949   XMC_ETH_MAC_STATUS_t status;
950 
951   XMC_ASSERT("XMC_ETH_MAC_GetTxTimeStamp: eth_mac is invalid", XMC_ETH_MAC_IsValidModule(eth_mac->regs));
952   XMC_ASSERT("XMC_ETH_MAC_GetTxTimeStamp: time is invalid", time != NULL);
953 
954   tx_desc = &eth_mac->tx_desc[eth_mac->tx_ts_index];
955   if (tx_desc->status & ETH_MAC_DMA_TDES0_OWN)
956   {
957     status = XMC_ETH_MAC_STATUS_BUSY;
958   }
959   else
960   {
961     if ((tx_desc->status & (ETH_MAC_DMA_TDES0_TTSS | ETH_MAC_DMA_TDES0_LS)) == (ETH_MAC_DMA_TDES0_TTSS | ETH_MAC_DMA_TDES0_LS))
962     {
963       time->nanoseconds = (int32_t)(tx_desc->time_stamp_nanoseconds); /* accuracy of 1 ns */
964       time->seconds = tx_desc->time_stamp_seconds;
965 
966       status = XMC_ETH_MAC_STATUS_OK;
967     }
968     else
969     {
970       status = XMC_ETH_MAC_STATUS_ERROR;
971     }
972   }
973 
974   return status;
975 }
976 
977 #endif
978