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