1 /******************************************************************************
3 * Copyright (C) 2010 - 2015 Xilinx, Inc. All rights reserved.
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:
12 * The above copyright notice and this permission notice shall be included in
13 * all copies or substantial portions of the Software.
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.
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
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.
31 ******************************************************************************/
32 /*****************************************************************************/
36 * @addtogroup emacps_v3_1
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.
43 * MODIFICATION HISTORY:
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
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
54 * 3.1 hk 08/10/15 Update upper 32 bit tx and rx queue ptr registers
57 ******************************************************************************/
59 /***************************** Include Files *********************************/
63 /************************** Constant Definitions *****************************/
66 /**************************** Type Definitions *******************************/
69 /***************** Macros (Inline Functions) Definitions *********************/
72 /************************** Function Prototypes ******************************/
74 void XEmacPs_StubHandler(void); /* Default handler routine */
76 /************************** Variable Definitions *****************************/
79 /*****************************************************************************/
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
86 * The PHY is setup independently from the device. Use the MII or whatever other
87 * interface may be present for setup.
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.
97 * - XST_SUCCESS if initialization was successful
99 ******************************************************************************/
100 LONG XEmacPs_CfgInitialize(XEmacPs *InstancePtr, XEmacPs_Config * CfgPtr,
101 UINTPTR EffectiveAddress)
103 /* Verify arguments */
104 Xil_AssertNonvoid(InstancePtr != NULL);
105 Xil_AssertNonvoid(CfgPtr != NULL);
107 /* Set device base address and ID */
108 InstancePtr->Config.DeviceId = CfgPtr->DeviceId;
109 InstancePtr->Config.BaseAddress = EffectiveAddress;
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);
116 /* Reset the hardware and set default options */
117 InstancePtr->IsReady = XIL_COMPONENT_IS_READY;
118 XEmacPs_Reset(InstancePtr);
120 return (LONG)(XST_SUCCESS);
124 /*****************************************************************************/
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
132 * @param InstancePtr is a pointer to the instance to be worked on.
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.
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
147 * This function must not be preempted by an interrupt that may service the
150 ******************************************************************************/
151 void XEmacPs_Start(XEmacPs *InstancePtr)
155 /* Assert bad arguments and conditions */
156 Xil_AssertVoid(InstancePtr != NULL);
157 Xil_AssertVoid(InstancePtr->IsReady == (u32)XIL_COMPONENT_IS_READY);
160 /* When starting the DMA channels, both transmit and receive sides
161 * need an initialized BD list.
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);
170 XEmacPs_WriteReg(InstancePtr->Config.BaseAddress,
171 XEMACPS_TXQBASE_OFFSET,
172 InstancePtr->TxBdRing.BaseBdAddr);
175 /* clear any existed int status */
176 XEmacPs_WriteReg(InstancePtr->Config.BaseAddress, XEMACPS_ISR_OFFSET,
177 XEMACPS_IXR_ALL_MASK);
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);
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);
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));
206 /* Enable TX Q1 Interrupts */
207 if (InstancePtr->Version > 2)
208 XEmacPs_IntQ1Enable(InstancePtr, XEMACPS_INTQ1_IXR_ALL_MASK);
210 /* Mark as started */
211 InstancePtr->IsStarted = XIL_COMPONENT_IS_STARTED;
217 /*****************************************************************************/
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
224 * Device options currently in effect are not changed.
226 * This function will disable all interrupts. Default interrupts settings that
227 * had been enabled will be restored when XEmacPs_Start() is called.
229 * @param InstancePtr is a pointer to the instance to be worked on.
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
238 * Stopping the DMA channels causes this function to block until the DMA
239 * operation is complete.
241 ******************************************************************************/
242 void XEmacPs_Stop(XEmacPs *InstancePtr)
246 Xil_AssertVoid(InstancePtr != NULL);
247 Xil_AssertVoid(InstancePtr->IsReady == (u32)XIL_COMPONENT_IS_READY);
249 /* Disable all interrupts */
250 XEmacPs_WriteReg(InstancePtr->Config.BaseAddress, XEMACPS_IDR_OFFSET,
251 XEMACPS_IXR_ALL_MASK);
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);
261 /* Mark as stopped */
262 InstancePtr->IsStarted = 0U;
266 /*****************************************************************************/
268 * Perform a graceful reset of the Ethernet MAC. Resets the DMA channels, the
269 * transmitter, and the receiver.
272 * - Stops transmit and receive channels
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
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.
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.
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.
295 * @param InstancePtr is a pointer to the instance to be worked on.
297 ******************************************************************************/
298 void XEmacPs_Reset(XEmacPs *InstancePtr)
302 s8 EmacPs_zero_MAC[6] = { 0x0, 0x0, 0x0, 0x0, 0x0, 0x0 };
304 Xil_AssertVoid(InstancePtr != NULL);
305 Xil_AssertVoid(InstancePtr->IsReady == (u32)XIL_COMPONENT_IS_READY);
307 /* Stop the device and reset hardware */
308 XEmacPs_Stop(InstancePtr);
309 InstancePtr->Options = XEMACPS_DEFAULT_OPTIONS;
311 InstancePtr->Version = XEmacPs_ReadReg(InstancePtr->Config.BaseAddress, 0xFC);
313 InstancePtr->Version = (InstancePtr->Version >> 16) & 0xFFF;
315 InstancePtr->MaxMtuSize = XEMACPS_MTU;
316 InstancePtr->MaxFrameSize = XEMACPS_MTU + XEMACPS_HDR_SIZE +
318 InstancePtr->MaxVlanFrameSize = InstancePtr->MaxFrameSize +
319 XEMACPS_HDR_VLAN_SIZE;
320 InstancePtr->RxBufMask = XEMACPS_RXBUF_LEN_MASK;
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));
329 Reg = XEmacPs_ReadReg(InstancePtr->Config.BaseAddress,
330 XEMACPS_NWCFG_OFFSET);
331 Reg &= XEMACPS_NWCFG_MDCCLKDIV_MASK;
333 Reg = Reg | (u32)XEMACPS_NWCFG_100_MASK |
334 (u32)XEMACPS_NWCFG_FDEN_MASK |
335 (u32)XEMACPS_NWCFG_UCASTHASHEN_MASK;
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));
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);
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) |
362 (u32)XEMACPS_DMACR_ADDR_WIDTH_64 |
364 (u32)XEMACPS_DMACR_INCR16_AHB_BURST));
367 XEmacPs_WriteReg(InstancePtr->Config.BaseAddress,
368 XEMACPS_TXSR_OFFSET, 0x0U);
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);
375 XEmacPs_WriteReg(InstancePtr->Config.BaseAddress,
376 XEMACPS_RXSR_OFFSET, 0x0U);
378 XEmacPs_WriteReg(InstancePtr->Config.BaseAddress, XEMACPS_IDR_OFFSET,
379 XEMACPS_IXR_ALL_MASK);
381 Reg = XEmacPs_ReadReg(InstancePtr->Config.BaseAddress,
383 XEmacPs_WriteReg(InstancePtr->Config.BaseAddress, XEMACPS_ISR_OFFSET,
386 XEmacPs_ClearHash(InstancePtr);
388 for (i = 1U; i < 5U; i++) {
389 (void)XEmacPs_SetMacAddress(InstancePtr, EmacPs_zero_MAC, i);
390 (void)XEmacPs_SetTypeIdCheck(InstancePtr, 0x00000000U, i);
393 /* clear all counters */
394 for (i = 0U; i < (u8)((XEMACPS_LAST_OFFSET - XEMACPS_OCTTXL_OFFSET) / 4U);
396 (void)XEmacPs_ReadReg(InstancePtr->Config.BaseAddress,
397 XEMACPS_OCTTXL_OFFSET + (u32)(((u32)i) * ((u32)4)));
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);
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.
412 (void)XEmacPs_SetOptions(InstancePtr, InstancePtr->Options &
413 ~((u32)XEMACPS_TRANSMITTER_ENABLE_OPTION |
414 (u32)XEMACPS_RECEIVER_ENABLE_OPTION));
416 (void)XEmacPs_ClearOptions(InstancePtr, ~InstancePtr->Options);
420 /******************************************************************************/
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
427 ******************************************************************************/
428 void XEmacPs_StubHandler(void)
430 Xil_AssertVoidAlways();
433 /*****************************************************************************/
435 * This function sets the start address of the transmit/receive buffer queue.
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
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()
446 ******************************************************************************/
447 void XEmacPs_SetQueuePtr(XEmacPs *InstancePtr, UINTPTR QPtr, u8 QueueNum,
450 /* Assert bad arguments and conditions */
451 Xil_AssertVoid(InstancePtr != NULL);
452 Xil_AssertVoid(InstancePtr->IsReady == (u32)XIL_COMPONENT_IS_READY);
454 /* If already started, then there is nothing to do */
455 if (InstancePtr->IsStarted == (u32)XIL_COMPONENT_IS_STARTED) {
459 if (QueueNum == 0x00U) {
460 if (Direction == XEMACPS_SEND) {
461 XEmacPs_WriteReg(InstancePtr->Config.BaseAddress,
462 XEMACPS_TXQBASE_OFFSET,
463 (QPtr & ULONG64_LO_MASK));
465 XEmacPs_WriteReg(InstancePtr->Config.BaseAddress,
466 XEMACPS_RXQBASE_OFFSET,
467 (QPtr & ULONG64_LO_MASK));
471 XEmacPs_WriteReg(InstancePtr->Config.BaseAddress,
472 XEMACPS_TXQ1BASE_OFFSET,
473 (QPtr & ULONG64_LO_MASK));
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));
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));