]> git.sur5r.net Git - freertos/blob - FreeRTOS/Demo/CORTEX_R5_UltraScale_MPSoC/RTOSDemo_R5_bsp/psu_cortexr5_0/libsrc/emacps_v3_3/src/xemacps.c
xTaskGenericNotify() now sets xYieldPending to pdTRUE even when the 'higher priority...
[freertos] / FreeRTOS / Demo / CORTEX_R5_UltraScale_MPSoC / RTOSDemo_R5_bsp / psu_cortexr5_0 / libsrc / emacps_v3_3 / src / xemacps.c
1 /******************************************************************************
2 *
3 * Copyright (C) 2010 - 2015 Xilinx, Inc.  All rights reserved.
4 *
5 * Permission is hereby granted, free of charge, to any person obtaining a copy
6 * of this software and associated documentation files (the "Software"), to deal
7 * in the Software without restriction, including without limitation the rights
8 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 * copies of the Software, and to permit persons to whom the Software is
10 * furnished to do so, subject to the following conditions:
11 *
12 * The above copyright notice and this permission notice shall be included in
13 * all copies or substantial portions of the Software.
14 *
15 * Use of the Software is limited solely to applications:
16 * (a) running on a Xilinx device, or
17 * (b) that interact with a Xilinx device through a bus or interconnect.
18 *
19 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
22 * XILINX  BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
23 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
24 * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
25 * SOFTWARE.
26 *
27 * Except as contained in this notice, the name of the Xilinx shall not be used
28 * in advertising or otherwise to promote the sale, use or other dealings in
29 * this Software without prior written authorization from Xilinx.
30 *
31 ******************************************************************************/
32 /*****************************************************************************/
33 /**
34 *
35 * @file xemacps.c
36 * @addtogroup emacps_v3_1
37 * @{
38 *
39 * The XEmacPs driver. Functions in this file are the minimum required functions
40 * for this driver. See xemacps.h for a detailed description of the driver.
41 *
42 * <pre>
43 * MODIFICATION HISTORY:
44 *
45 * Ver   Who  Date     Changes
46 * ----- ---- -------- -------------------------------------------------------
47 * 1.00a wsy  01/10/10 First release
48 * 2.1  srt  07/15/14 Add support for Zynq Ultrascale Mp GEM specification and
49 *                     64-bit changes.
50 * 3.00 kvn  02/13/15 Modified code for MISRA-C:2012 compliance.
51 * 3.0  hk   02/20/15 Added support for jumbo frames. Increase AHB burst.
52 *                    Disable extended mode. Perform all 64 bit changes under
53 *                    check for arch64.
54 * 3.1  hk   08/10/15 Update upper 32 bit tx and rx queue ptr registers
55 *
56 * </pre>
57 ******************************************************************************/
58
59 /***************************** Include Files *********************************/
60
61 #include "xemacps.h"
62
63 /************************** Constant Definitions *****************************/
64
65
66 /**************************** Type Definitions *******************************/
67
68
69 /***************** Macros (Inline Functions) Definitions *********************/
70
71
72 /************************** Function Prototypes ******************************/
73
74 void XEmacPs_StubHandler(void); /* Default handler routine */
75
76 /************************** Variable Definitions *****************************/
77
78
79 /*****************************************************************************/
80 /**
81 * Initialize a specific XEmacPs instance/driver. The initialization entails:
82 * - Initialize fields of the XEmacPs instance structure
83 * - Reset hardware and apply default options
84 * - Configure the DMA channels
85 *
86 * The PHY is setup independently from the device. Use the MII or whatever other
87 * interface may be present for setup.
88 *
89 * @param InstancePtr is a pointer to the instance to be worked on.
90 * @param CfgPtr is the device configuration structure containing required
91 *        hardware build data.
92 * @param EffectiveAddress is the base address of the device. If address
93 *        translation is not utilized, this parameter can be passed in using
94 *        CfgPtr->Config.BaseAddress to specify the physical base address.
95 *
96 * @return
97 * - XST_SUCCESS if initialization was successful
98 *
99 ******************************************************************************/
100 LONG XEmacPs_CfgInitialize(XEmacPs *InstancePtr, XEmacPs_Config * CfgPtr,
101                            UINTPTR EffectiveAddress)
102 {
103         /* Verify arguments */
104         Xil_AssertNonvoid(InstancePtr != NULL);
105         Xil_AssertNonvoid(CfgPtr != NULL);
106
107         /* Set device base address and ID */
108         InstancePtr->Config.DeviceId = CfgPtr->DeviceId;
109         InstancePtr->Config.BaseAddress = EffectiveAddress;
110
111         /* Set callbacks to an initial stub routine */
112         InstancePtr->SendHandler = ((XEmacPs_Handler)((void*)XEmacPs_StubHandler));
113         InstancePtr->RecvHandler = ((XEmacPs_Handler)(void*)XEmacPs_StubHandler);
114         InstancePtr->ErrorHandler = ((XEmacPs_ErrHandler)(void*)XEmacPs_StubHandler);
115
116         /* Reset the hardware and set default options */
117         InstancePtr->IsReady = XIL_COMPONENT_IS_READY;
118         XEmacPs_Reset(InstancePtr);
119
120         return (LONG)(XST_SUCCESS);
121 }
122
123
124 /*****************************************************************************/
125 /**
126 * Start the Ethernet controller as follows:
127 *   - Enable transmitter if XTE_TRANSMIT_ENABLE_OPTION is set
128 *   - Enable receiver if XTE_RECEIVER_ENABLE_OPTION is set
129 *   - Start the SG DMA send and receive channels and enable the device
130 *     interrupt
131 *
132 * @param InstancePtr is a pointer to the instance to be worked on.
133 *
134 * @return N/A
135 *
136 * @note
137 * Hardware is configured with scatter-gather DMA, the driver expects to start
138 * the scatter-gather channels and expects that the user has previously set up
139 * the buffer descriptor lists.
140 *
141 * This function makes use of internal resources that are shared between the
142 * Start, Stop, and Set/ClearOptions functions. So if one task might be setting
143 * device options while another is trying to start the device, the user is
144 * required to provide protection of this shared data (typically using a
145 * semaphore).
146 *
147 * This function must not be preempted by an interrupt that may service the
148 * device.
149 *
150 ******************************************************************************/
151 void XEmacPs_Start(XEmacPs *InstancePtr)
152 {
153         u32 Reg;
154
155         /* Assert bad arguments and conditions */
156         Xil_AssertVoid(InstancePtr != NULL);
157         Xil_AssertVoid(InstancePtr->IsReady == (u32)XIL_COMPONENT_IS_READY);
158
159         /* Start DMA */
160         /* When starting the DMA channels, both transmit and receive sides
161          * need an initialized BD list.
162          */
163         if (InstancePtr->Version == 2) {
164                 Xil_AssertVoid(InstancePtr->RxBdRing.BaseBdAddr != 0);
165                 Xil_AssertVoid(InstancePtr->TxBdRing.BaseBdAddr != 0);
166         XEmacPs_WriteReg(InstancePtr->Config.BaseAddress,
167                            XEMACPS_RXQBASE_OFFSET,
168                            InstancePtr->RxBdRing.BaseBdAddr);
169
170         XEmacPs_WriteReg(InstancePtr->Config.BaseAddress,
171                            XEMACPS_TXQBASE_OFFSET,
172                            InstancePtr->TxBdRing.BaseBdAddr);
173         }
174
175         /* clear any existed int status */
176         XEmacPs_WriteReg(InstancePtr->Config.BaseAddress, XEMACPS_ISR_OFFSET,
177                            XEMACPS_IXR_ALL_MASK);
178
179         /* Enable transmitter if not already enabled */
180         if ((InstancePtr->Options & (u32)XEMACPS_TRANSMITTER_ENABLE_OPTION)!=0x00000000U) {
181                 Reg = XEmacPs_ReadReg(InstancePtr->Config.BaseAddress,
182                                         XEMACPS_NWCTRL_OFFSET);
183                 if ((!(Reg & XEMACPS_NWCTRL_TXEN_MASK))==TRUE) {
184                         XEmacPs_WriteReg(InstancePtr->Config.BaseAddress,
185                                            XEMACPS_NWCTRL_OFFSET,
186                                    Reg | (u32)XEMACPS_NWCTRL_TXEN_MASK);
187                 }
188         }
189
190         /* Enable receiver if not already enabled */
191         if ((InstancePtr->Options & XEMACPS_RECEIVER_ENABLE_OPTION) != 0x00000000U) {
192                 Reg = XEmacPs_ReadReg(InstancePtr->Config.BaseAddress,
193                                         XEMACPS_NWCTRL_OFFSET);
194                 if ((!(Reg & XEMACPS_NWCTRL_RXEN_MASK))==TRUE) {
195                         XEmacPs_WriteReg(InstancePtr->Config.BaseAddress,
196                                            XEMACPS_NWCTRL_OFFSET,
197                                    Reg | (u32)XEMACPS_NWCTRL_RXEN_MASK);
198                 }
199         }
200
201         /* Enable TX and RX interrupts */
202         XEmacPs_IntEnable(InstancePtr, (XEMACPS_IXR_TX_ERR_MASK |
203         XEMACPS_IXR_RX_ERR_MASK | (u32)XEMACPS_IXR_FRAMERX_MASK |
204         (u32)XEMACPS_IXR_TXCOMPL_MASK));
205
206         /* Enable TX Q1 Interrupts */
207         if (InstancePtr->Version > 2)
208                 XEmacPs_IntQ1Enable(InstancePtr, XEMACPS_INTQ1_IXR_ALL_MASK);
209
210         /* Mark as started */
211         InstancePtr->IsStarted = XIL_COMPONENT_IS_STARTED;
212
213         return;
214 }
215
216
217 /*****************************************************************************/
218 /**
219 * Gracefully stop the Ethernet MAC as follows:
220 *   - Disable all interrupts from this device
221 *   - Stop DMA channels
222 *   - Disable the tansmitter and receiver
223 *
224 * Device options currently in effect are not changed.
225 *
226 * This function will disable all interrupts. Default interrupts settings that
227 * had been enabled will be restored when XEmacPs_Start() is called.
228 *
229 * @param InstancePtr is a pointer to the instance to be worked on.
230 *
231 * @note
232 * This function makes use of internal resources that are shared between the
233 * Start, Stop, SetOptions, and ClearOptions functions. So if one task might be
234 * setting device options while another is trying to start the device, the user
235 * is required to provide protection of this shared data (typically using a
236 * semaphore).
237 *
238 * Stopping the DMA channels causes this function to block until the DMA
239 * operation is complete.
240 *
241 ******************************************************************************/
242 void XEmacPs_Stop(XEmacPs *InstancePtr)
243 {
244         u32 Reg;
245
246         Xil_AssertVoid(InstancePtr != NULL);
247         Xil_AssertVoid(InstancePtr->IsReady == (u32)XIL_COMPONENT_IS_READY);
248
249         /* Disable all interrupts */
250         XEmacPs_WriteReg(InstancePtr->Config.BaseAddress, XEMACPS_IDR_OFFSET,
251                            XEMACPS_IXR_ALL_MASK);
252
253         /* Disable the receiver & transmitter */
254         Reg = XEmacPs_ReadReg(InstancePtr->Config.BaseAddress,
255                                 XEMACPS_NWCTRL_OFFSET);
256         Reg &= (u32)(~XEMACPS_NWCTRL_RXEN_MASK);
257         Reg &= (u32)(~XEMACPS_NWCTRL_TXEN_MASK);
258         XEmacPs_WriteReg(InstancePtr->Config.BaseAddress,
259                            XEMACPS_NWCTRL_OFFSET, Reg);
260
261         /* Mark as stopped */
262         InstancePtr->IsStarted = 0U;
263 }
264
265
266 /*****************************************************************************/
267 /**
268 * Perform a graceful reset of the Ethernet MAC. Resets the DMA channels, the
269 * transmitter, and the receiver.
270 *
271 * Steps to reset
272 * - Stops transmit and receive channels
273 * - Stops DMA
274 * - Configure transmit and receive buffer size to default
275 * - Clear transmit and receive status register and counters
276 * - Clear all interrupt sources
277 * - Clear phy (if there is any previously detected) address
278 * - Clear MAC addresses (1-4) as well as Type IDs and hash value
279 *
280 * All options are placed in their default state. Any frames in the
281 * descriptor lists will remain in the lists. The side effect of doing
282 * this is that after a reset and following a restart of the device, frames
283 * were in the list before the reset may be transmitted or received.
284 *
285 * The upper layer software is responsible for re-configuring (if necessary)
286 * and restarting the MAC after the reset. Note also that driver statistics
287 * are not cleared on reset. It is up to the upper layer software to clear the
288 * statistics if needed.
289 *
290 * When a reset is required, the driver notifies the upper layer software of
291 * this need through the ErrorHandler callback and specific status codes.
292 * The upper layer software is responsible for calling this Reset function
293 * and then re-configuring the device.
294 *
295 * @param InstancePtr is a pointer to the instance to be worked on.
296 *
297 ******************************************************************************/
298 void XEmacPs_Reset(XEmacPs *InstancePtr)
299 {
300         u32 Reg;
301         u8 i;
302         s8 EmacPs_zero_MAC[6] = { 0x0, 0x0, 0x0, 0x0, 0x0, 0x0 };
303
304         Xil_AssertVoid(InstancePtr != NULL);
305         Xil_AssertVoid(InstancePtr->IsReady == (u32)XIL_COMPONENT_IS_READY);
306
307         /* Stop the device and reset hardware */
308         XEmacPs_Stop(InstancePtr);
309         InstancePtr->Options = XEMACPS_DEFAULT_OPTIONS;
310
311         InstancePtr->Version = XEmacPs_ReadReg(InstancePtr->Config.BaseAddress, 0xFC);
312
313         InstancePtr->Version = (InstancePtr->Version >> 16) & 0xFFF;
314
315         InstancePtr->MaxMtuSize = XEMACPS_MTU;
316         InstancePtr->MaxFrameSize = XEMACPS_MTU + XEMACPS_HDR_SIZE +
317                                         XEMACPS_TRL_SIZE;
318         InstancePtr->MaxVlanFrameSize = InstancePtr->MaxFrameSize +
319                                         XEMACPS_HDR_VLAN_SIZE;
320         InstancePtr->RxBufMask = XEMACPS_RXBUF_LEN_MASK;
321
322         /* Setup hardware with default values */
323         XEmacPs_WriteReg(InstancePtr->Config.BaseAddress,
324                         XEMACPS_NWCTRL_OFFSET,
325                         (XEMACPS_NWCTRL_STATCLR_MASK |
326                         XEMACPS_NWCTRL_MDEN_MASK) &
327                         (u32)(~XEMACPS_NWCTRL_LOOPEN_MASK));
328
329         Reg = XEmacPs_ReadReg(InstancePtr->Config.BaseAddress,
330                         XEMACPS_NWCFG_OFFSET);
331         Reg &= XEMACPS_NWCFG_MDCCLKDIV_MASK;
332
333         Reg = Reg | (u32)XEMACPS_NWCFG_100_MASK |
334                         (u32)XEMACPS_NWCFG_FDEN_MASK |
335                         (u32)XEMACPS_NWCFG_UCASTHASHEN_MASK;
336
337         XEmacPs_WriteReg(InstancePtr->Config.BaseAddress,
338                                         XEMACPS_NWCFG_OFFSET, Reg);
339         if (InstancePtr->Version > 2) {
340                 XEmacPs_WriteReg(InstancePtr->Config.BaseAddress, XEMACPS_NWCFG_OFFSET,
341                         (XEmacPs_ReadReg(InstancePtr->Config.BaseAddress, XEMACPS_NWCFG_OFFSET) |
342                                 XEMACPS_NWCFG_DWIDTH_64_MASK));
343         }
344
345         XEmacPs_WriteReg(InstancePtr->Config.BaseAddress,
346                         XEMACPS_DMACR_OFFSET,
347                         (((((u32)XEMACPS_RX_BUF_SIZE / (u32)XEMACPS_RX_BUF_UNIT) +
348                                 (((((u32)XEMACPS_RX_BUF_SIZE %
349                                 (u32)XEMACPS_RX_BUF_UNIT))!=(u32)0) ? 1U : 0U)) <<
350                                 (u32)(XEMACPS_DMACR_RXBUF_SHIFT)) &
351                                 (u32)(XEMACPS_DMACR_RXBUF_MASK)) |
352                                 (u32)XEMACPS_DMACR_RXSIZE_MASK |
353                                 (u32)XEMACPS_DMACR_TXSIZE_MASK);
354
355
356         /* Single bursts */
357         /* FIXME: Why Single bursts? */
358         if (InstancePtr->Version > 2) {
359                 XEmacPs_WriteReg(InstancePtr->Config.BaseAddress, XEMACPS_DMACR_OFFSET,
360                         (XEmacPs_ReadReg(InstancePtr->Config.BaseAddress, XEMACPS_DMACR_OFFSET) |
361 #ifdef __aarch64__
362                         (u32)XEMACPS_DMACR_ADDR_WIDTH_64 |
363 #endif
364                         (u32)XEMACPS_DMACR_INCR16_AHB_BURST));
365         }
366
367         XEmacPs_WriteReg(InstancePtr->Config.BaseAddress,
368                            XEMACPS_TXSR_OFFSET, 0x0U);
369
370         XEmacPs_SetQueuePtr(InstancePtr, 0, 0x00U, (u16)XEMACPS_SEND);
371         if (InstancePtr->Version > 2)
372                 XEmacPs_SetQueuePtr(InstancePtr, 0, 0x01U, (u16)XEMACPS_SEND);
373         XEmacPs_SetQueuePtr(InstancePtr, 0, 0x00U, (u16)XEMACPS_RECV);
374
375         XEmacPs_WriteReg(InstancePtr->Config.BaseAddress,
376                            XEMACPS_RXSR_OFFSET, 0x0U);
377
378         XEmacPs_WriteReg(InstancePtr->Config.BaseAddress, XEMACPS_IDR_OFFSET,
379                            XEMACPS_IXR_ALL_MASK);
380
381         Reg = XEmacPs_ReadReg(InstancePtr->Config.BaseAddress,
382                                 XEMACPS_ISR_OFFSET);
383         XEmacPs_WriteReg(InstancePtr->Config.BaseAddress, XEMACPS_ISR_OFFSET,
384                            Reg);
385
386         XEmacPs_ClearHash(InstancePtr);
387
388         for (i = 1U; i < 5U; i++) {
389                 (void)XEmacPs_SetMacAddress(InstancePtr, EmacPs_zero_MAC, i);
390                 (void)XEmacPs_SetTypeIdCheck(InstancePtr, 0x00000000U, i);
391         }
392
393         /* clear all counters */
394         for (i = 0U; i < (u8)((XEMACPS_LAST_OFFSET - XEMACPS_OCTTXL_OFFSET) / 4U);
395              i++) {
396                 (void)XEmacPs_ReadReg(InstancePtr->Config.BaseAddress,
397                                    XEMACPS_OCTTXL_OFFSET + (u32)(((u32)i) * ((u32)4)));
398         }
399
400         /* Disable the receiver */
401         Reg = XEmacPs_ReadReg(InstancePtr->Config.BaseAddress,
402                                 XEMACPS_NWCTRL_OFFSET);
403         Reg &= (u32)(~XEMACPS_NWCTRL_RXEN_MASK);
404         XEmacPs_WriteReg(InstancePtr->Config.BaseAddress,
405                            XEMACPS_NWCTRL_OFFSET, Reg);
406
407         /* Sync default options with hardware but leave receiver and
408          * transmitter disabled. They get enabled with XEmacPs_Start() if
409          * XEMACPS_TRANSMITTER_ENABLE_OPTION and
410          * XEMACPS_RECEIVER_ENABLE_OPTION are set.
411          */
412         (void)XEmacPs_SetOptions(InstancePtr, InstancePtr->Options &
413                             ~((u32)XEMACPS_TRANSMITTER_ENABLE_OPTION |
414                               (u32)XEMACPS_RECEIVER_ENABLE_OPTION));
415
416         (void)XEmacPs_ClearOptions(InstancePtr, ~InstancePtr->Options);
417 }
418
419
420 /******************************************************************************/
421 /**
422  * This is a stub for the asynchronous callbacks. The stub is here in case the
423  * upper layer forgot to set the handler(s). On initialization, all handlers are
424  * set to this callback. It is considered an error for this handler to be
425  * invoked.
426  *
427  ******************************************************************************/
428 void XEmacPs_StubHandler(void)
429 {
430         Xil_AssertVoidAlways();
431 }
432
433 /*****************************************************************************/
434 /**
435 * This function sets the start address of the transmit/receive buffer queue.
436 *
437 * @param        InstancePtr is a pointer to the instance to be worked on.
438 * @QPtr         Address of the Queue to be written
439 * @QueueNum     Buffer Queue Index
440 * @Direction    Transmit/Recive
441 *
442 * @note
443 * The buffer queue addresses has to be set before starting the transfer, so
444 * this function has to be called in prior to XEmacPs_Start()
445 *
446 ******************************************************************************/
447 void XEmacPs_SetQueuePtr(XEmacPs *InstancePtr, UINTPTR QPtr, u8 QueueNum,
448                          u16 Direction)
449 {
450         /* Assert bad arguments and conditions */
451         Xil_AssertVoid(InstancePtr != NULL);
452         Xil_AssertVoid(InstancePtr->IsReady == (u32)XIL_COMPONENT_IS_READY);
453
454         /* If already started, then there is nothing to do */
455         if (InstancePtr->IsStarted == (u32)XIL_COMPONENT_IS_STARTED) {
456                 return;
457         }
458
459         if (QueueNum == 0x00U) {
460                 if (Direction == XEMACPS_SEND) {
461                         XEmacPs_WriteReg(InstancePtr->Config.BaseAddress,
462                                 XEMACPS_TXQBASE_OFFSET,
463                                 (QPtr & ULONG64_LO_MASK));
464                 } else {
465                         XEmacPs_WriteReg(InstancePtr->Config.BaseAddress,
466                                 XEMACPS_RXQBASE_OFFSET,
467                                 (QPtr & ULONG64_LO_MASK));
468                 }
469         }
470          else {
471                 XEmacPs_WriteReg(InstancePtr->Config.BaseAddress,
472                         XEMACPS_TXQ1BASE_OFFSET,
473                         (QPtr & ULONG64_LO_MASK));
474         }
475 #ifdef __aarch64__
476         if (Direction == XEMACPS_SEND) {
477                 /* Set the MSB of TX Queue start address */
478                 XEmacPs_WriteReg(InstancePtr->Config.BaseAddress,
479                                 XEMACPS_MSBBUF_TXQBASE_OFFSET,
480                                 (u32)((QPtr & ULONG64_HI_MASK) >> 32U));
481         } else {
482                 /* Set the MSB of RX Queue start address */
483                 XEmacPs_WriteReg(InstancePtr->Config.BaseAddress,
484                                 XEMACPS_MSBBUF_RXQBASE_OFFSET,
485                                 (u32)((QPtr & ULONG64_HI_MASK) >> 32U));
486         }
487 #endif
488 }
489 /** @} */