]> git.sur5r.net Git - freertos/blob - FreeRTOS/Demo/CORTEX_A9_Zynq_ZC702/RTOSDemo_bsp/ps7_cortexa9_0/libsrc/emacps_v3_7/src/xemacps.c
Update Zynq, MPSoc Cortex-A53 and MPSoc Cortex-R5 demo projects to build with the...
[freertos] / FreeRTOS / Demo / CORTEX_A9_Zynq_ZC702 / RTOSDemo_bsp / ps7_cortexa9_0 / libsrc / emacps_v3_7 / 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_7
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 * 3.5  hk   08/14/17 Update cache coherency information of the interface in
56 *                    its config structure.
57 *
58 * </pre>
59 ******************************************************************************/
60
61 /***************************** Include Files *********************************/
62
63 #include "xemacps.h"
64
65 /************************** Constant Definitions *****************************/
66
67
68 /**************************** Type Definitions *******************************/
69
70
71 /***************** Macros (Inline Functions) Definitions *********************/
72
73
74 /************************** Function Prototypes ******************************/
75
76 void XEmacPs_StubHandler(void); /* Default handler routine */
77
78 /************************** Variable Definitions *****************************/
79
80
81 /*****************************************************************************/
82 /**
83 * Initialize a specific XEmacPs instance/driver. The initialization entails:
84 * - Initialize fields of the XEmacPs instance structure
85 * - Reset hardware and apply default options
86 * - Configure the DMA channels
87 *
88 * The PHY is setup independently from the device. Use the MII or whatever other
89 * interface may be present for setup.
90 *
91 * @param InstancePtr is a pointer to the instance to be worked on.
92 * @param CfgPtr is the device configuration structure containing required
93 *        hardware build data.
94 * @param EffectiveAddress is the base address of the device. If address
95 *        translation is not utilized, this parameter can be passed in using
96 *        CfgPtr->Config.BaseAddress to specify the physical base address.
97 *
98 * @return
99 * - XST_SUCCESS if initialization was successful
100 *
101 ******************************************************************************/
102 LONG XEmacPs_CfgInitialize(XEmacPs *InstancePtr, XEmacPs_Config * CfgPtr,
103                            UINTPTR EffectiveAddress)
104 {
105         /* Verify arguments */
106         Xil_AssertNonvoid(InstancePtr != NULL);
107         Xil_AssertNonvoid(CfgPtr != NULL);
108
109         /* Set device base address and ID */
110         InstancePtr->Config.DeviceId = CfgPtr->DeviceId;
111         InstancePtr->Config.BaseAddress = EffectiveAddress;
112         InstancePtr->Config.IsCacheCoherent = CfgPtr->IsCacheCoherent;
113
114         /* Set callbacks to an initial stub routine */
115         InstancePtr->SendHandler = ((XEmacPs_Handler)((void*)XEmacPs_StubHandler));
116         InstancePtr->RecvHandler = ((XEmacPs_Handler)(void*)XEmacPs_StubHandler);
117         InstancePtr->ErrorHandler = ((XEmacPs_ErrHandler)(void*)XEmacPs_StubHandler);
118
119         /* Reset the hardware and set default options */
120         InstancePtr->IsReady = XIL_COMPONENT_IS_READY;
121         XEmacPs_Reset(InstancePtr);
122
123         return (LONG)(XST_SUCCESS);
124 }
125
126
127 /*****************************************************************************/
128 /**
129 * Start the Ethernet controller as follows:
130 *   - Enable transmitter if XTE_TRANSMIT_ENABLE_OPTION is set
131 *   - Enable receiver if XTE_RECEIVER_ENABLE_OPTION is set
132 *   - Start the SG DMA send and receive channels and enable the device
133 *     interrupt
134 *
135 * @param InstancePtr is a pointer to the instance to be worked on.
136 *
137 * @return N/A
138 *
139 * @note
140 * Hardware is configured with scatter-gather DMA, the driver expects to start
141 * the scatter-gather channels and expects that the user has previously set up
142 * the buffer descriptor lists.
143 *
144 * This function makes use of internal resources that are shared between the
145 * Start, Stop, and Set/ClearOptions functions. So if one task might be setting
146 * device options while another is trying to start the device, the user is
147 * required to provide protection of this shared data (typically using a
148 * semaphore).
149 *
150 * This function must not be preempted by an interrupt that may service the
151 * device.
152 *
153 ******************************************************************************/
154 void XEmacPs_Start(XEmacPs *InstancePtr)
155 {
156         u32 Reg;
157
158         /* Assert bad arguments and conditions */
159         Xil_AssertVoid(InstancePtr != NULL);
160         Xil_AssertVoid(InstancePtr->IsReady == (u32)XIL_COMPONENT_IS_READY);
161
162         /* Start DMA */
163         /* When starting the DMA channels, both transmit and receive sides
164          * need an initialized BD list.
165          */
166         if (InstancePtr->Version == 2) {
167                 Xil_AssertVoid(InstancePtr->RxBdRing.BaseBdAddr != 0);
168                 Xil_AssertVoid(InstancePtr->TxBdRing.BaseBdAddr != 0);
169         XEmacPs_WriteReg(InstancePtr->Config.BaseAddress,
170                            XEMACPS_RXQBASE_OFFSET,
171                            InstancePtr->RxBdRing.BaseBdAddr);
172
173         XEmacPs_WriteReg(InstancePtr->Config.BaseAddress,
174                            XEMACPS_TXQBASE_OFFSET,
175                            InstancePtr->TxBdRing.BaseBdAddr);
176         }
177
178         /* clear any existed int status */
179         XEmacPs_WriteReg(InstancePtr->Config.BaseAddress, XEMACPS_ISR_OFFSET,
180                            XEMACPS_IXR_ALL_MASK);
181
182         /* Enable transmitter if not already enabled */
183         if ((InstancePtr->Options & (u32)XEMACPS_TRANSMITTER_ENABLE_OPTION)!=0x00000000U) {
184                 Reg = XEmacPs_ReadReg(InstancePtr->Config.BaseAddress,
185                                         XEMACPS_NWCTRL_OFFSET);
186                 if ((!(Reg & XEMACPS_NWCTRL_TXEN_MASK))==TRUE) {
187                         XEmacPs_WriteReg(InstancePtr->Config.BaseAddress,
188                                            XEMACPS_NWCTRL_OFFSET,
189                                    Reg | (u32)XEMACPS_NWCTRL_TXEN_MASK);
190                 }
191         }
192
193         /* Enable receiver if not already enabled */
194         if ((InstancePtr->Options & XEMACPS_RECEIVER_ENABLE_OPTION) != 0x00000000U) {
195                 Reg = XEmacPs_ReadReg(InstancePtr->Config.BaseAddress,
196                                         XEMACPS_NWCTRL_OFFSET);
197                 if ((!(Reg & XEMACPS_NWCTRL_RXEN_MASK))==TRUE) {
198                         XEmacPs_WriteReg(InstancePtr->Config.BaseAddress,
199                                            XEMACPS_NWCTRL_OFFSET,
200                                    Reg | (u32)XEMACPS_NWCTRL_RXEN_MASK);
201                 }
202         }
203
204         /* Enable TX and RX interrupts */
205         XEmacPs_IntEnable(InstancePtr, (XEMACPS_IXR_TX_ERR_MASK |
206         XEMACPS_IXR_RX_ERR_MASK | (u32)XEMACPS_IXR_FRAMERX_MASK |
207         (u32)XEMACPS_IXR_TXCOMPL_MASK));
208
209         /* Enable TX Q1 Interrupts */
210         if (InstancePtr->Version > 2)
211                 XEmacPs_IntQ1Enable(InstancePtr, XEMACPS_INTQ1_IXR_ALL_MASK);
212
213         /* Mark as started */
214         InstancePtr->IsStarted = XIL_COMPONENT_IS_STARTED;
215
216         return;
217 }
218
219
220 /*****************************************************************************/
221 /**
222 * Gracefully stop the Ethernet MAC as follows:
223 *   - Disable all interrupts from this device
224 *   - Stop DMA channels
225 *   - Disable the tansmitter and receiver
226 *
227 * Device options currently in effect are not changed.
228 *
229 * This function will disable all interrupts. Default interrupts settings that
230 * had been enabled will be restored when XEmacPs_Start() is called.
231 *
232 * @param InstancePtr is a pointer to the instance to be worked on.
233 *
234 * @note
235 * This function makes use of internal resources that are shared between the
236 * Start, Stop, SetOptions, and ClearOptions functions. So if one task might be
237 * setting device options while another is trying to start the device, the user
238 * is required to provide protection of this shared data (typically using a
239 * semaphore).
240 *
241 * Stopping the DMA channels causes this function to block until the DMA
242 * operation is complete.
243 *
244 ******************************************************************************/
245 void XEmacPs_Stop(XEmacPs *InstancePtr)
246 {
247         u32 Reg;
248
249         Xil_AssertVoid(InstancePtr != NULL);
250         Xil_AssertVoid(InstancePtr->IsReady == (u32)XIL_COMPONENT_IS_READY);
251
252         /* Disable all interrupts */
253         XEmacPs_WriteReg(InstancePtr->Config.BaseAddress, XEMACPS_IDR_OFFSET,
254                            XEMACPS_IXR_ALL_MASK);
255
256         /* Disable the receiver & transmitter */
257         Reg = XEmacPs_ReadReg(InstancePtr->Config.BaseAddress,
258                                 XEMACPS_NWCTRL_OFFSET);
259         Reg &= (u32)(~XEMACPS_NWCTRL_RXEN_MASK);
260         Reg &= (u32)(~XEMACPS_NWCTRL_TXEN_MASK);
261         XEmacPs_WriteReg(InstancePtr->Config.BaseAddress,
262                            XEMACPS_NWCTRL_OFFSET, Reg);
263
264         /* Mark as stopped */
265         InstancePtr->IsStarted = 0U;
266 }
267
268
269 /*****************************************************************************/
270 /**
271 * Perform a graceful reset of the Ethernet MAC. Resets the DMA channels, the
272 * transmitter, and the receiver.
273 *
274 * Steps to reset
275 * - Stops transmit and receive channels
276 * - Stops DMA
277 * - Configure transmit and receive buffer size to default
278 * - Clear transmit and receive status register and counters
279 * - Clear all interrupt sources
280 * - Clear phy (if there is any previously detected) address
281 * - Clear MAC addresses (1-4) as well as Type IDs and hash value
282 *
283 * All options are placed in their default state. Any frames in the
284 * descriptor lists will remain in the lists. The side effect of doing
285 * this is that after a reset and following a restart of the device, frames
286 * were in the list before the reset may be transmitted or received.
287 *
288 * The upper layer software is responsible for re-configuring (if necessary)
289 * and restarting the MAC after the reset. Note also that driver statistics
290 * are not cleared on reset. It is up to the upper layer software to clear the
291 * statistics if needed.
292 *
293 * When a reset is required, the driver notifies the upper layer software of
294 * this need through the ErrorHandler callback and specific status codes.
295 * The upper layer software is responsible for calling this Reset function
296 * and then re-configuring the device.
297 *
298 * @param InstancePtr is a pointer to the instance to be worked on.
299 *
300 ******************************************************************************/
301 void XEmacPs_Reset(XEmacPs *InstancePtr)
302 {
303         u32 Reg;
304         u8 i;
305         s8 EmacPs_zero_MAC[6] = { 0x0, 0x0, 0x0, 0x0, 0x0, 0x0 };
306
307         Xil_AssertVoid(InstancePtr != NULL);
308         Xil_AssertVoid(InstancePtr->IsReady == (u32)XIL_COMPONENT_IS_READY);
309
310         /* Stop the device and reset hardware */
311         XEmacPs_Stop(InstancePtr);
312         InstancePtr->Options = XEMACPS_DEFAULT_OPTIONS;
313
314         InstancePtr->Version = XEmacPs_ReadReg(InstancePtr->Config.BaseAddress, 0xFC);
315
316         InstancePtr->Version = (InstancePtr->Version >> 16) & 0xFFF;
317
318         InstancePtr->MaxMtuSize = XEMACPS_MTU;
319         InstancePtr->MaxFrameSize = XEMACPS_MTU + XEMACPS_HDR_SIZE +
320                                         XEMACPS_TRL_SIZE;
321         InstancePtr->MaxVlanFrameSize = InstancePtr->MaxFrameSize +
322                                         XEMACPS_HDR_VLAN_SIZE;
323         InstancePtr->RxBufMask = XEMACPS_RXBUF_LEN_MASK;
324
325         /* Setup hardware with default values */
326         XEmacPs_WriteReg(InstancePtr->Config.BaseAddress,
327                         XEMACPS_NWCTRL_OFFSET,
328                         (XEMACPS_NWCTRL_STATCLR_MASK |
329                         XEMACPS_NWCTRL_MDEN_MASK) &
330                         (u32)(~XEMACPS_NWCTRL_LOOPEN_MASK));
331
332         Reg = XEmacPs_ReadReg(InstancePtr->Config.BaseAddress,
333                         XEMACPS_NWCFG_OFFSET);
334         Reg &= XEMACPS_NWCFG_MDCCLKDIV_MASK;
335
336         Reg = Reg | (u32)XEMACPS_NWCFG_100_MASK |
337                         (u32)XEMACPS_NWCFG_FDEN_MASK |
338                         (u32)XEMACPS_NWCFG_UCASTHASHEN_MASK;
339
340         XEmacPs_WriteReg(InstancePtr->Config.BaseAddress,
341                                         XEMACPS_NWCFG_OFFSET, Reg);
342         if (InstancePtr->Version > 2) {
343                 XEmacPs_WriteReg(InstancePtr->Config.BaseAddress, XEMACPS_NWCFG_OFFSET,
344                         (XEmacPs_ReadReg(InstancePtr->Config.BaseAddress, XEMACPS_NWCFG_OFFSET) |
345                                 XEMACPS_NWCFG_DWIDTH_64_MASK));
346         }
347
348         XEmacPs_WriteReg(InstancePtr->Config.BaseAddress,
349                         XEMACPS_DMACR_OFFSET,
350                         (((((u32)XEMACPS_RX_BUF_SIZE / (u32)XEMACPS_RX_BUF_UNIT) +
351                                 (((((u32)XEMACPS_RX_BUF_SIZE %
352                                 (u32)XEMACPS_RX_BUF_UNIT))!=(u32)0) ? 1U : 0U)) <<
353                                 (u32)(XEMACPS_DMACR_RXBUF_SHIFT)) &
354                                 (u32)(XEMACPS_DMACR_RXBUF_MASK)) |
355                                 (u32)XEMACPS_DMACR_RXSIZE_MASK |
356                                 (u32)XEMACPS_DMACR_TXSIZE_MASK);
357
358
359         /* Single bursts */
360         /* FIXME: Why Single bursts? */
361         if (InstancePtr->Version > 2) {
362                 XEmacPs_WriteReg(InstancePtr->Config.BaseAddress, XEMACPS_DMACR_OFFSET,
363                         (XEmacPs_ReadReg(InstancePtr->Config.BaseAddress, XEMACPS_DMACR_OFFSET) |
364 #ifdef __aarch64__
365                         (u32)XEMACPS_DMACR_ADDR_WIDTH_64 |
366 #endif
367                         (u32)XEMACPS_DMACR_INCR16_AHB_BURST));
368         }
369
370         XEmacPs_WriteReg(InstancePtr->Config.BaseAddress,
371                            XEMACPS_TXSR_OFFSET, 0x0U);
372
373         XEmacPs_SetQueuePtr(InstancePtr, 0, 0x00U, (u16)XEMACPS_SEND);
374         if (InstancePtr->Version > 2)
375                 XEmacPs_SetQueuePtr(InstancePtr, 0, 0x01U, (u16)XEMACPS_SEND);
376         XEmacPs_SetQueuePtr(InstancePtr, 0, 0x00U, (u16)XEMACPS_RECV);
377
378         XEmacPs_WriteReg(InstancePtr->Config.BaseAddress,
379                            XEMACPS_RXSR_OFFSET, 0x0U);
380
381         XEmacPs_WriteReg(InstancePtr->Config.BaseAddress, XEMACPS_IDR_OFFSET,
382                            XEMACPS_IXR_ALL_MASK);
383
384         Reg = XEmacPs_ReadReg(InstancePtr->Config.BaseAddress,
385                                 XEMACPS_ISR_OFFSET);
386         XEmacPs_WriteReg(InstancePtr->Config.BaseAddress, XEMACPS_ISR_OFFSET,
387                            Reg);
388
389         XEmacPs_ClearHash(InstancePtr);
390
391         for (i = 1U; i < 5U; i++) {
392                 (void)XEmacPs_SetMacAddress(InstancePtr, EmacPs_zero_MAC, i);
393                 (void)XEmacPs_SetTypeIdCheck(InstancePtr, 0x00000000U, i);
394         }
395
396         /* clear all counters */
397         for (i = 0U; i < (u8)((XEMACPS_LAST_OFFSET - XEMACPS_OCTTXL_OFFSET) / 4U);
398              i++) {
399                 (void)XEmacPs_ReadReg(InstancePtr->Config.BaseAddress,
400                                    XEMACPS_OCTTXL_OFFSET + (u32)(((u32)i) * ((u32)4)));
401         }
402
403         /* Disable the receiver */
404         Reg = XEmacPs_ReadReg(InstancePtr->Config.BaseAddress,
405                                 XEMACPS_NWCTRL_OFFSET);
406         Reg &= (u32)(~XEMACPS_NWCTRL_RXEN_MASK);
407         XEmacPs_WriteReg(InstancePtr->Config.BaseAddress,
408                            XEMACPS_NWCTRL_OFFSET, Reg);
409
410         /* Sync default options with hardware but leave receiver and
411          * transmitter disabled. They get enabled with XEmacPs_Start() if
412          * XEMACPS_TRANSMITTER_ENABLE_OPTION and
413          * XEMACPS_RECEIVER_ENABLE_OPTION are set.
414          */
415         (void)XEmacPs_SetOptions(InstancePtr, InstancePtr->Options &
416                             ~((u32)XEMACPS_TRANSMITTER_ENABLE_OPTION |
417                               (u32)XEMACPS_RECEIVER_ENABLE_OPTION));
418
419         (void)XEmacPs_ClearOptions(InstancePtr, ~InstancePtr->Options);
420 }
421
422
423 /******************************************************************************/
424 /**
425  * This is a stub for the asynchronous callbacks. The stub is here in case the
426  * upper layer forgot to set the handler(s). On initialization, all handlers are
427  * set to this callback. It is considered an error for this handler to be
428  * invoked.
429  *
430  ******************************************************************************/
431 void XEmacPs_StubHandler(void)
432 {
433         Xil_AssertVoidAlways();
434 }
435
436 /*****************************************************************************/
437 /**
438 * This function sets the start address of the transmit/receive buffer queue.
439 *
440 * @param        InstancePtr is a pointer to the instance to be worked on.
441 * @QPtr         Address of the Queue to be written
442 * @QueueNum     Buffer Queue Index
443 * @Direction    Transmit/Recive
444 *
445 * @note
446 * The buffer queue addresses has to be set before starting the transfer, so
447 * this function has to be called in prior to XEmacPs_Start()
448 *
449 ******************************************************************************/
450 void XEmacPs_SetQueuePtr(XEmacPs *InstancePtr, UINTPTR QPtr, u8 QueueNum,
451                          u16 Direction)
452 {
453         /* Assert bad arguments and conditions */
454         Xil_AssertVoid(InstancePtr != NULL);
455         Xil_AssertVoid(InstancePtr->IsReady == (u32)XIL_COMPONENT_IS_READY);
456
457         /* If already started, then there is nothing to do */
458         if (InstancePtr->IsStarted == (u32)XIL_COMPONENT_IS_STARTED) {
459                 return;
460         }
461
462         if (QueueNum == 0x00U) {
463                 if (Direction == XEMACPS_SEND) {
464                         XEmacPs_WriteReg(InstancePtr->Config.BaseAddress,
465                                 XEMACPS_TXQBASE_OFFSET,
466                                 (QPtr & ULONG64_LO_MASK));
467                 } else {
468                         XEmacPs_WriteReg(InstancePtr->Config.BaseAddress,
469                                 XEMACPS_RXQBASE_OFFSET,
470                                 (QPtr & ULONG64_LO_MASK));
471                 }
472         }
473          else {
474                 XEmacPs_WriteReg(InstancePtr->Config.BaseAddress,
475                         XEMACPS_TXQ1BASE_OFFSET,
476                         (QPtr & ULONG64_LO_MASK));
477         }
478 #ifdef __aarch64__
479         if (Direction == XEMACPS_SEND) {
480                 /* Set the MSB of TX Queue start address */
481                 XEmacPs_WriteReg(InstancePtr->Config.BaseAddress,
482                                 XEMACPS_MSBBUF_TXQBASE_OFFSET,
483                                 (u32)((QPtr & ULONG64_HI_MASK) >> 32U));
484         } else {
485                 /* Set the MSB of RX Queue start address */
486                 XEmacPs_WriteReg(InstancePtr->Config.BaseAddress,
487                                 XEMACPS_MSBBUF_RXQBASE_OFFSET,
488                                 (u32)((QPtr & ULONG64_HI_MASK) >> 32U));
489         }
490 #endif
491 }
492 /** @} */