]> git.sur5r.net Git - freertos/blobdiff - FreeRTOS/Demo/CORTEX_R5_UltraScale_MPSoC/RTOSDemo_R5_bsp/psu_cortexr5_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_R5_UltraScale_MPSoC / RTOSDemo_R5_bsp / psu_cortexr5_0 / libsrc / emacps_v3_7 / src / xemacps.c
diff --git a/FreeRTOS/Demo/CORTEX_R5_UltraScale_MPSoC/RTOSDemo_R5_bsp/psu_cortexr5_0/libsrc/emacps_v3_7/src/xemacps.c b/FreeRTOS/Demo/CORTEX_R5_UltraScale_MPSoC/RTOSDemo_R5_bsp/psu_cortexr5_0/libsrc/emacps_v3_7/src/xemacps.c
new file mode 100644 (file)
index 0000000..c013c49
--- /dev/null
@@ -0,0 +1,492 @@
+/******************************************************************************
+*
+* Copyright (C) 2010 - 2015 Xilinx, Inc.  All rights reserved.
+*
+* Permission is hereby granted, free of charge, to any person obtaining a copy
+* of this software and associated documentation files (the "Software"), to deal
+* in the Software without restriction, including without limitation the rights
+* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+* copies of the Software, and to permit persons to whom the Software is
+* furnished to do so, subject to the following conditions:
+*
+* The above copyright notice and this permission notice shall be included in
+* all copies or substantial portions of the Software.
+*
+* Use of the Software is limited solely to applications:
+* (a) running on a Xilinx device, or
+* (b) that interact with a Xilinx device through a bus or interconnect.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+* XILINX  BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
+* OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+* SOFTWARE.
+*
+* Except as contained in this notice, the name of the Xilinx shall not be used
+* in advertising or otherwise to promote the sale, use or other dealings in
+* this Software without prior written authorization from Xilinx.
+*
+******************************************************************************/
+/*****************************************************************************/
+/**
+*
+* @file xemacps.c
+* @addtogroup emacps_v3_7
+* @{
+*
+* The XEmacPs driver. Functions in this file are the minimum required functions
+* for this driver. See xemacps.h for a detailed description of the driver.
+*
+* <pre>
+* MODIFICATION HISTORY:
+*
+* Ver   Who  Date     Changes
+* ----- ---- -------- -------------------------------------------------------
+* 1.00a wsy  01/10/10 First release
+* 2.1  srt  07/15/14 Add support for Zynq Ultrascale Mp GEM specification and
+*                    64-bit changes.
+* 3.00 kvn  02/13/15 Modified code for MISRA-C:2012 compliance.
+* 3.0  hk   02/20/15 Added support for jumbo frames. Increase AHB burst.
+*                    Disable extended mode. Perform all 64 bit changes under
+*                    check for arch64.
+* 3.1  hk   08/10/15 Update upper 32 bit tx and rx queue ptr registers
+* 3.5  hk   08/14/17 Update cache coherency information of the interface in
+*                    its config structure.
+*
+* </pre>
+******************************************************************************/
+
+/***************************** Include Files *********************************/
+
+#include "xemacps.h"
+
+/************************** Constant Definitions *****************************/
+
+
+/**************************** Type Definitions *******************************/
+
+
+/***************** Macros (Inline Functions) Definitions *********************/
+
+
+/************************** Function Prototypes ******************************/
+
+void XEmacPs_StubHandler(void);        /* Default handler routine */
+
+/************************** Variable Definitions *****************************/
+
+
+/*****************************************************************************/
+/**
+* Initialize a specific XEmacPs instance/driver. The initialization entails:
+* - Initialize fields of the XEmacPs instance structure
+* - Reset hardware and apply default options
+* - Configure the DMA channels
+*
+* The PHY is setup independently from the device. Use the MII or whatever other
+* interface may be present for setup.
+*
+* @param InstancePtr is a pointer to the instance to be worked on.
+* @param CfgPtr is the device configuration structure containing required
+*        hardware build data.
+* @param EffectiveAddress is the base address of the device. If address
+*        translation is not utilized, this parameter can be passed in using
+*        CfgPtr->Config.BaseAddress to specify the physical base address.
+*
+* @return
+* - XST_SUCCESS if initialization was successful
+*
+******************************************************************************/
+LONG XEmacPs_CfgInitialize(XEmacPs *InstancePtr, XEmacPs_Config * CfgPtr,
+                          UINTPTR EffectiveAddress)
+{
+       /* Verify arguments */
+       Xil_AssertNonvoid(InstancePtr != NULL);
+       Xil_AssertNonvoid(CfgPtr != NULL);
+
+       /* Set device base address and ID */
+       InstancePtr->Config.DeviceId = CfgPtr->DeviceId;
+       InstancePtr->Config.BaseAddress = EffectiveAddress;
+       InstancePtr->Config.IsCacheCoherent = CfgPtr->IsCacheCoherent;
+
+       /* Set callbacks to an initial stub routine */
+       InstancePtr->SendHandler = ((XEmacPs_Handler)((void*)XEmacPs_StubHandler));
+       InstancePtr->RecvHandler = ((XEmacPs_Handler)(void*)XEmacPs_StubHandler);
+       InstancePtr->ErrorHandler = ((XEmacPs_ErrHandler)(void*)XEmacPs_StubHandler);
+
+       /* Reset the hardware and set default options */
+       InstancePtr->IsReady = XIL_COMPONENT_IS_READY;
+       XEmacPs_Reset(InstancePtr);
+
+       return (LONG)(XST_SUCCESS);
+}
+
+
+/*****************************************************************************/
+/**
+* Start the Ethernet controller as follows:
+*   - Enable transmitter if XTE_TRANSMIT_ENABLE_OPTION is set
+*   - Enable receiver if XTE_RECEIVER_ENABLE_OPTION is set
+*   - Start the SG DMA send and receive channels and enable the device
+*     interrupt
+*
+* @param InstancePtr is a pointer to the instance to be worked on.
+*
+* @return N/A
+*
+* @note
+* Hardware is configured with scatter-gather DMA, the driver expects to start
+* the scatter-gather channels and expects that the user has previously set up
+* the buffer descriptor lists.
+*
+* This function makes use of internal resources that are shared between the
+* Start, Stop, and Set/ClearOptions functions. So if one task might be setting
+* device options while another is trying to start the device, the user is
+* required to provide protection of this shared data (typically using a
+* semaphore).
+*
+* This function must not be preempted by an interrupt that may service the
+* device.
+*
+******************************************************************************/
+void XEmacPs_Start(XEmacPs *InstancePtr)
+{
+       u32 Reg;
+
+       /* Assert bad arguments and conditions */
+       Xil_AssertVoid(InstancePtr != NULL);
+       Xil_AssertVoid(InstancePtr->IsReady == (u32)XIL_COMPONENT_IS_READY);
+
+       /* Start DMA */
+       /* When starting the DMA channels, both transmit and receive sides
+        * need an initialized BD list.
+        */
+       if (InstancePtr->Version == 2) {
+               Xil_AssertVoid(InstancePtr->RxBdRing.BaseBdAddr != 0);
+               Xil_AssertVoid(InstancePtr->TxBdRing.BaseBdAddr != 0);
+       XEmacPs_WriteReg(InstancePtr->Config.BaseAddress,
+                          XEMACPS_RXQBASE_OFFSET,
+                          InstancePtr->RxBdRing.BaseBdAddr);
+
+       XEmacPs_WriteReg(InstancePtr->Config.BaseAddress,
+                          XEMACPS_TXQBASE_OFFSET,
+                          InstancePtr->TxBdRing.BaseBdAddr);
+       }
+
+       /* clear any existed int status */
+       XEmacPs_WriteReg(InstancePtr->Config.BaseAddress, XEMACPS_ISR_OFFSET,
+                          XEMACPS_IXR_ALL_MASK);
+
+       /* Enable transmitter if not already enabled */
+       if ((InstancePtr->Options & (u32)XEMACPS_TRANSMITTER_ENABLE_OPTION)!=0x00000000U) {
+               Reg = XEmacPs_ReadReg(InstancePtr->Config.BaseAddress,
+                                       XEMACPS_NWCTRL_OFFSET);
+               if ((!(Reg & XEMACPS_NWCTRL_TXEN_MASK))==TRUE) {
+                       XEmacPs_WriteReg(InstancePtr->Config.BaseAddress,
+                                          XEMACPS_NWCTRL_OFFSET,
+                                  Reg | (u32)XEMACPS_NWCTRL_TXEN_MASK);
+               }
+       }
+
+       /* Enable receiver if not already enabled */
+       if ((InstancePtr->Options & XEMACPS_RECEIVER_ENABLE_OPTION) != 0x00000000U) {
+               Reg = XEmacPs_ReadReg(InstancePtr->Config.BaseAddress,
+                                       XEMACPS_NWCTRL_OFFSET);
+               if ((!(Reg & XEMACPS_NWCTRL_RXEN_MASK))==TRUE) {
+                       XEmacPs_WriteReg(InstancePtr->Config.BaseAddress,
+                                          XEMACPS_NWCTRL_OFFSET,
+                                  Reg | (u32)XEMACPS_NWCTRL_RXEN_MASK);
+               }
+       }
+
+        /* Enable TX and RX interrupts */
+        XEmacPs_IntEnable(InstancePtr, (XEMACPS_IXR_TX_ERR_MASK |
+       XEMACPS_IXR_RX_ERR_MASK | (u32)XEMACPS_IXR_FRAMERX_MASK |
+       (u32)XEMACPS_IXR_TXCOMPL_MASK));
+
+       /* Enable TX Q1 Interrupts */
+       if (InstancePtr->Version > 2)
+               XEmacPs_IntQ1Enable(InstancePtr, XEMACPS_INTQ1_IXR_ALL_MASK);
+
+       /* Mark as started */
+       InstancePtr->IsStarted = XIL_COMPONENT_IS_STARTED;
+
+       return;
+}
+
+
+/*****************************************************************************/
+/**
+* Gracefully stop the Ethernet MAC as follows:
+*   - Disable all interrupts from this device
+*   - Stop DMA channels
+*   - Disable the tansmitter and receiver
+*
+* Device options currently in effect are not changed.
+*
+* This function will disable all interrupts. Default interrupts settings that
+* had been enabled will be restored when XEmacPs_Start() is called.
+*
+* @param InstancePtr is a pointer to the instance to be worked on.
+*
+* @note
+* This function makes use of internal resources that are shared between the
+* Start, Stop, SetOptions, and ClearOptions functions. So if one task might be
+* setting device options while another is trying to start the device, the user
+* is required to provide protection of this shared data (typically using a
+* semaphore).
+*
+* Stopping the DMA channels causes this function to block until the DMA
+* operation is complete.
+*
+******************************************************************************/
+void XEmacPs_Stop(XEmacPs *InstancePtr)
+{
+       u32 Reg;
+
+       Xil_AssertVoid(InstancePtr != NULL);
+       Xil_AssertVoid(InstancePtr->IsReady == (u32)XIL_COMPONENT_IS_READY);
+
+       /* Disable all interrupts */
+       XEmacPs_WriteReg(InstancePtr->Config.BaseAddress, XEMACPS_IDR_OFFSET,
+                          XEMACPS_IXR_ALL_MASK);
+
+       /* Disable the receiver & transmitter */
+       Reg = XEmacPs_ReadReg(InstancePtr->Config.BaseAddress,
+                               XEMACPS_NWCTRL_OFFSET);
+       Reg &= (u32)(~XEMACPS_NWCTRL_RXEN_MASK);
+       Reg &= (u32)(~XEMACPS_NWCTRL_TXEN_MASK);
+       XEmacPs_WriteReg(InstancePtr->Config.BaseAddress,
+                          XEMACPS_NWCTRL_OFFSET, Reg);
+
+       /* Mark as stopped */
+       InstancePtr->IsStarted = 0U;
+}
+
+
+/*****************************************************************************/
+/**
+* Perform a graceful reset of the Ethernet MAC. Resets the DMA channels, the
+* transmitter, and the receiver.
+*
+* Steps to reset
+* - Stops transmit and receive channels
+* - Stops DMA
+* - Configure transmit and receive buffer size to default
+* - Clear transmit and receive status register and counters
+* - Clear all interrupt sources
+* - Clear phy (if there is any previously detected) address
+* - Clear MAC addresses (1-4) as well as Type IDs and hash value
+*
+* All options are placed in their default state. Any frames in the
+* descriptor lists will remain in the lists. The side effect of doing
+* this is that after a reset and following a restart of the device, frames
+* were in the list before the reset may be transmitted or received.
+*
+* The upper layer software is responsible for re-configuring (if necessary)
+* and restarting the MAC after the reset. Note also that driver statistics
+* are not cleared on reset. It is up to the upper layer software to clear the
+* statistics if needed.
+*
+* When a reset is required, the driver notifies the upper layer software of
+* this need through the ErrorHandler callback and specific status codes.
+* The upper layer software is responsible for calling this Reset function
+* and then re-configuring the device.
+*
+* @param InstancePtr is a pointer to the instance to be worked on.
+*
+******************************************************************************/
+void XEmacPs_Reset(XEmacPs *InstancePtr)
+{
+       u32 Reg;
+       u8 i;
+       s8 EmacPs_zero_MAC[6] = { 0x0, 0x0, 0x0, 0x0, 0x0, 0x0 };
+
+       Xil_AssertVoid(InstancePtr != NULL);
+       Xil_AssertVoid(InstancePtr->IsReady == (u32)XIL_COMPONENT_IS_READY);
+
+       /* Stop the device and reset hardware */
+       XEmacPs_Stop(InstancePtr);
+       InstancePtr->Options = XEMACPS_DEFAULT_OPTIONS;
+
+       InstancePtr->Version = XEmacPs_ReadReg(InstancePtr->Config.BaseAddress, 0xFC);
+
+       InstancePtr->Version = (InstancePtr->Version >> 16) & 0xFFF;
+
+       InstancePtr->MaxMtuSize = XEMACPS_MTU;
+       InstancePtr->MaxFrameSize = XEMACPS_MTU + XEMACPS_HDR_SIZE +
+                                       XEMACPS_TRL_SIZE;
+       InstancePtr->MaxVlanFrameSize = InstancePtr->MaxFrameSize +
+                                       XEMACPS_HDR_VLAN_SIZE;
+       InstancePtr->RxBufMask = XEMACPS_RXBUF_LEN_MASK;
+
+       /* Setup hardware with default values */
+       XEmacPs_WriteReg(InstancePtr->Config.BaseAddress,
+                       XEMACPS_NWCTRL_OFFSET,
+                       (XEMACPS_NWCTRL_STATCLR_MASK |
+                       XEMACPS_NWCTRL_MDEN_MASK) &
+                       (u32)(~XEMACPS_NWCTRL_LOOPEN_MASK));
+
+       Reg = XEmacPs_ReadReg(InstancePtr->Config.BaseAddress,
+                       XEMACPS_NWCFG_OFFSET);
+       Reg &= XEMACPS_NWCFG_MDCCLKDIV_MASK;
+
+       Reg = Reg | (u32)XEMACPS_NWCFG_100_MASK |
+                       (u32)XEMACPS_NWCFG_FDEN_MASK |
+                       (u32)XEMACPS_NWCFG_UCASTHASHEN_MASK;
+
+       XEmacPs_WriteReg(InstancePtr->Config.BaseAddress,
+                                       XEMACPS_NWCFG_OFFSET, Reg);
+       if (InstancePtr->Version > 2) {
+               XEmacPs_WriteReg(InstancePtr->Config.BaseAddress, XEMACPS_NWCFG_OFFSET,
+                       (XEmacPs_ReadReg(InstancePtr->Config.BaseAddress, XEMACPS_NWCFG_OFFSET) |
+                               XEMACPS_NWCFG_DWIDTH_64_MASK));
+       }
+
+       XEmacPs_WriteReg(InstancePtr->Config.BaseAddress,
+                       XEMACPS_DMACR_OFFSET,
+                       (((((u32)XEMACPS_RX_BUF_SIZE / (u32)XEMACPS_RX_BUF_UNIT) +
+                               (((((u32)XEMACPS_RX_BUF_SIZE %
+                               (u32)XEMACPS_RX_BUF_UNIT))!=(u32)0) ? 1U : 0U)) <<
+                               (u32)(XEMACPS_DMACR_RXBUF_SHIFT)) &
+                               (u32)(XEMACPS_DMACR_RXBUF_MASK)) |
+                               (u32)XEMACPS_DMACR_RXSIZE_MASK |
+                               (u32)XEMACPS_DMACR_TXSIZE_MASK);
+
+
+       /* Single bursts */
+       /* FIXME: Why Single bursts? */
+       if (InstancePtr->Version > 2) {
+               XEmacPs_WriteReg(InstancePtr->Config.BaseAddress, XEMACPS_DMACR_OFFSET,
+                       (XEmacPs_ReadReg(InstancePtr->Config.BaseAddress, XEMACPS_DMACR_OFFSET) |
+#ifdef __aarch64__
+                       (u32)XEMACPS_DMACR_ADDR_WIDTH_64 |
+#endif
+                       (u32)XEMACPS_DMACR_INCR16_AHB_BURST));
+       }
+
+       XEmacPs_WriteReg(InstancePtr->Config.BaseAddress,
+                          XEMACPS_TXSR_OFFSET, 0x0U);
+
+       XEmacPs_SetQueuePtr(InstancePtr, 0, 0x00U, (u16)XEMACPS_SEND);
+       if (InstancePtr->Version > 2)
+               XEmacPs_SetQueuePtr(InstancePtr, 0, 0x01U, (u16)XEMACPS_SEND);
+       XEmacPs_SetQueuePtr(InstancePtr, 0, 0x00U, (u16)XEMACPS_RECV);
+
+       XEmacPs_WriteReg(InstancePtr->Config.BaseAddress,
+                          XEMACPS_RXSR_OFFSET, 0x0U);
+
+       XEmacPs_WriteReg(InstancePtr->Config.BaseAddress, XEMACPS_IDR_OFFSET,
+                          XEMACPS_IXR_ALL_MASK);
+
+       Reg = XEmacPs_ReadReg(InstancePtr->Config.BaseAddress,
+                               XEMACPS_ISR_OFFSET);
+       XEmacPs_WriteReg(InstancePtr->Config.BaseAddress, XEMACPS_ISR_OFFSET,
+                          Reg);
+
+       XEmacPs_ClearHash(InstancePtr);
+
+       for (i = 1U; i < 5U; i++) {
+               (void)XEmacPs_SetMacAddress(InstancePtr, EmacPs_zero_MAC, i);
+               (void)XEmacPs_SetTypeIdCheck(InstancePtr, 0x00000000U, i);
+       }
+
+       /* clear all counters */
+       for (i = 0U; i < (u8)((XEMACPS_LAST_OFFSET - XEMACPS_OCTTXL_OFFSET) / 4U);
+            i++) {
+               (void)XEmacPs_ReadReg(InstancePtr->Config.BaseAddress,
+                                   XEMACPS_OCTTXL_OFFSET + (u32)(((u32)i) * ((u32)4)));
+       }
+
+       /* Disable the receiver */
+       Reg = XEmacPs_ReadReg(InstancePtr->Config.BaseAddress,
+                               XEMACPS_NWCTRL_OFFSET);
+       Reg &= (u32)(~XEMACPS_NWCTRL_RXEN_MASK);
+       XEmacPs_WriteReg(InstancePtr->Config.BaseAddress,
+                          XEMACPS_NWCTRL_OFFSET, Reg);
+
+       /* Sync default options with hardware but leave receiver and
+         * transmitter disabled. They get enabled with XEmacPs_Start() if
+        * XEMACPS_TRANSMITTER_ENABLE_OPTION and
+         * XEMACPS_RECEIVER_ENABLE_OPTION are set.
+        */
+       (void)XEmacPs_SetOptions(InstancePtr, InstancePtr->Options &
+                           ~((u32)XEMACPS_TRANSMITTER_ENABLE_OPTION |
+                             (u32)XEMACPS_RECEIVER_ENABLE_OPTION));
+
+       (void)XEmacPs_ClearOptions(InstancePtr, ~InstancePtr->Options);
+}
+
+
+/******************************************************************************/
+/**
+ * This is a stub for the asynchronous callbacks. The stub is here in case the
+ * upper layer forgot to set the handler(s). On initialization, all handlers are
+ * set to this callback. It is considered an error for this handler to be
+ * invoked.
+ *
+ ******************************************************************************/
+void XEmacPs_StubHandler(void)
+{
+       Xil_AssertVoidAlways();
+}
+
+/*****************************************************************************/
+/**
+* This function sets the start address of the transmit/receive buffer queue.
+*
+* @param       InstancePtr is a pointer to the instance to be worked on.
+* @QPtr                Address of the Queue to be written
+* @QueueNum    Buffer Queue Index
+* @Direction   Transmit/Recive
+*
+* @note
+* The buffer queue addresses has to be set before starting the transfer, so
+* this function has to be called in prior to XEmacPs_Start()
+*
+******************************************************************************/
+void XEmacPs_SetQueuePtr(XEmacPs *InstancePtr, UINTPTR QPtr, u8 QueueNum,
+                        u16 Direction)
+{
+       /* Assert bad arguments and conditions */
+       Xil_AssertVoid(InstancePtr != NULL);
+       Xil_AssertVoid(InstancePtr->IsReady == (u32)XIL_COMPONENT_IS_READY);
+
+        /* If already started, then there is nothing to do */
+        if (InstancePtr->IsStarted == (u32)XIL_COMPONENT_IS_STARTED) {
+                return;
+        }
+
+       if (QueueNum == 0x00U) {
+               if (Direction == XEMACPS_SEND) {
+                       XEmacPs_WriteReg(InstancePtr->Config.BaseAddress,
+                               XEMACPS_TXQBASE_OFFSET,
+                               (QPtr & ULONG64_LO_MASK));
+               } else {
+                       XEmacPs_WriteReg(InstancePtr->Config.BaseAddress,
+                               XEMACPS_RXQBASE_OFFSET,
+                               (QPtr & ULONG64_LO_MASK));
+               }
+       }
+        else {
+               XEmacPs_WriteReg(InstancePtr->Config.BaseAddress,
+                       XEMACPS_TXQ1BASE_OFFSET,
+                       (QPtr & ULONG64_LO_MASK));
+       }
+#ifdef __aarch64__
+       if (Direction == XEMACPS_SEND) {
+               /* Set the MSB of TX Queue start address */
+               XEmacPs_WriteReg(InstancePtr->Config.BaseAddress,
+                               XEMACPS_MSBBUF_TXQBASE_OFFSET,
+                               (u32)((QPtr & ULONG64_HI_MASK) >> 32U));
+       } else {
+               /* Set the MSB of RX Queue start address */
+               XEmacPs_WriteReg(InstancePtr->Config.BaseAddress,
+                               XEMACPS_MSBBUF_RXQBASE_OFFSET,
+                               (u32)((QPtr & ULONG64_HI_MASK) >> 32U));
+       }
+#endif
+}
+/** @} */