/** * \file cpsw.c * * \brief CPSW device abstraction layer APIs. * * This file contains the device abstraction layer APIs for CPSW RGMII. */ /* * Copyright (C) 2010 Texas Instruments Incorporated - http://www.ti.com/ */ /* * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the * distribution. * * Neither the name of Texas Instruments Incorporated nor the names of * its contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #include "hw_types.h" #include "cpsw.h" /******************************************************************************* * INTERNAL MACRO DEFINITIONS *******************************************************************************/ #define CPSW_CORE_OFFSET (0x10u) #define CPSW_MAX_HEADER_DESC (0x08u) #define CPDMA_P0_DEF_TX_MAP (0x76543210u) #define ALE_ENTRY_WORDS (0x03u) #define CPDMA_ERR_CHANNEL_POS (0xFFu) #define CPSW_PORT_DUAL_MAC_MODE (0x01u << \ CPSW_PORT_P0_TX_IN_CTL_TX_IN_SEL_SHIFT) #define CPSW_PORT_RATE_LIM_MODE (0x02u << \ CPSW_PORT_P0_TX_IN_CTL_TX_IN_SEL_SHIFT) /******************************************************************************* * API FUNCTION DEFINITIONS *******************************************************************************/ /** * \brief Resets the CPSW Subsystem. * * \param baseAddr Base address of the CPSW Subsystem * * \return None **/ void CPSWSSReset(unsigned int baseAddr) { /* Reset the CPSW */ HWREG(baseAddr + CPSW_SS_SOFT_RESET) = CPSW_SS_SOFT_RESET_SOFT_RESET; while(HWREG(baseAddr + CPSW_SS_SOFT_RESET) & CPSW_SS_SOFT_RESET_SOFT_RESET); } /** * \brief Force the CPGMAC_SL into gigabit mode if the input GMII_MTCLK has * been stopped by the PHY * * \param baseAddr Base address of the CPSW Sliver Module registers. * * \return None * **/ void CPSWSlGigModeForceEnable(unsigned int baseAddr) { HWREG(baseAddr + CPSW_SL_MACCONTROL) |= CPSW_SL_MACCONTROL_GIG_FORCE; } /** * \brief Enables the fullduplex and gigabit mode to be selected * from the FULLDUPLEX_IN and GIG_IN input signals and not from the * fullduplex and gig bits in this register. The FULLDUPLEX_MODE bit * reflects the actual fullduplex mode selected * * \param baseAddr Base address of the CPSW Sliver Module registers. * * \return None * **/ void CPSWSlControlExtEnable(unsigned int baseAddr) { HWREG(baseAddr + CPSW_SL_MACCONTROL) |= CPSW_SL_MACCONTROL_EXT_EN; } /** * \brief Disables the CPGMAC_SL gigabit mode if the input GMII_MTCLK has * been stopped by the PHY * * \param baseAddr Base address of the CPSW Sliver Module registers. * * \return None * **/ void CPSWSlGigModeForceDisable(unsigned int baseAddr) { HWREG(baseAddr + CPSW_SL_MACCONTROL) &= ~CPSW_SL_MACCONTROL_GIG_FORCE; } /** * \brief Sets the Transfer mode, 10/100 or gigabit mode and the duplex * mode for the sliver. * * \param baseAddr Base address of the CPSW Sliver Module registers. * \param mode The transfer mode * 'mode' can take one of the below values. \n * CPSW_SLIVER_NON_GIG_HALF_DUPLEX - 10/100 Mbps mode, half duplex. \n * CPSW_SLIVER_NON_GIG_FULL_DUPLEX - 10/100 Mbps mode, full duplex. \n * CPSW_SLIVER_GIG_FULL_DUPLEX - 1000 Mbps mode, full duplex. \n * Note: for 10Mbps mode, CPSW_SLIVER_INBAND has to be configured. \n * * \return None * **/ void CPSWSlTransferModeSet(unsigned int baseAddr, unsigned int mode) { HWREG(baseAddr + CPSW_SL_MACCONTROL) &= ~(CPSW_SL_MACCONTROL_GIG | CPSW_SL_MACCONTROL_FULLDUPLEX); HWREG(baseAddr + CPSW_SL_MACCONTROL) |= mode; } /** * \brief Returns the MAC Status. The value will be the contents of the MAC * status register. * * \param baseAddr Base address of the CPSW Sliver Module registers. * \param statFlag Status flags to be read. * statFlag can take an OR combination of the below values. \n * CPSW_SLIVER_STATE - The Sliver state. \n * CPSW_SLIVER_EXT_GIG_INPUT_BIT - The EXT_GIG input bit mask.\n * CPSW_SLIVER_EXT_FULL_DUPLEX_BIT - The EXT_FULLDUPLEX input * bit mask. \n * CPSW_SLIVER_RX_FLOWCTRL - The receive flow control active. \n * CPSW_SLIVER_TX_FLOWCTRL - The transmit flow control. * * * \return MAC Status * The MAC status register value returned can be compared against * the below tokens. \n * CPSW_SLIVER_STATE_IDLE - The Sliver is in idle state. \n * CPSW_SLIVER_EXT_GIG_INPUT_HIGH - The EXT_GIG input * bit is in HIGH state.\n * CPSW_SLIVER_EXT_FULL_DUPLEX_HIGH - The EXT_FULLDUPLEX input * bit is in HIGH state. \n * CPSW_SLIVER_RX_FLOWCTRL_ACTIVE - The receive flow control is * active. \n * CPSW_SLIVER_TX_FLOWCTRL_ACTIVE - The pause time period is * observed for a received * pause frame * **/ unsigned int CPSWSlMACStatusGet(unsigned int baseAddr, unsigned int statFlag) { /* Return the required status only */ return (HWREG(baseAddr + CPSW_SL_MACSTATUS) & statFlag); } /** * \brief Resets the CPSW Sliver Logic. * * \param baseAddr Base address of the CPSW Sliver Module registers. * * \return None * **/ void CPSWSlReset(unsigned int baseAddr) { /* Reset the sliver logic */ HWREG(baseAddr + CPSW_SL_SOFT_RESET) = CPSW_SL_SOFT_RESET_SOFT_RESET; /* Wait till the reset completes */ while(CPSW_SL_SOFT_RESET_SOFT_RESET == ((HWREG(baseAddr + CPSW_SL_SOFT_RESET)) & CPSW_SL_SOFT_RESET_SOFT_RESET)); } /** * \brief Sets the maximum length for received frame. * * \param baseAddr Base address of the CPSW Sliver Module registers. * \param rxMaxLen Maximum length for a received frame * The default value for 'rxMaxLen' is 1518. The maximum value * which can be set is 16383. * * \return None * **/ void CPSWSlRxMaxLenSet(unsigned int baseAddr, unsigned int rxMaxLen) { /* Set the desired maximum length */ HWREG(baseAddr + CPSW_SL_RX_MAXLEN) = rxMaxLen; } /** * \brief Enables GMII for the sliver. * * \param baseAddr Base address of the CPSW Sliver Module registers. * * \return None **/ void CPSWSlGMIIEnable(unsigned int baseAddr) { HWREG(baseAddr + CPSW_SL_MACCONTROL) |= CPSW_SL_MACCONTROL_GMII_EN; } /** * \brief Enables RGMII for the sliver. * * \param baseAddr Base address of the CPSW Sliver Module registers. * * \return None **/ void CPSWSlRGMIIEnable(unsigned int baseAddr) { HWREG(baseAddr + CPSW_SL_MACCONTROL) |= (CPSW_SL_MACCONTROL_GMII_EN | CPSW_SL_MACCONTROL_IFCTL_A | CPSW_SL_MACCONTROL_IFCTL_B); } /** * \brief Resets the CPSW Wrapper module. * * \param baseAddr Base address of the CPSW Wrapper Module * * \return None **/ void CPSWWrReset(unsigned int baseAddr) { /* Reset the CPSW Wrapper */ HWREG(baseAddr + CPSW_WR_SOFT_RESET) = CPSW_WR_SOFT_RESET_SOFT_RESET; while(HWREG(baseAddr + CPSW_WR_SOFT_RESET) & CPSW_WR_SOFT_RESET_SOFT_RESET); } /** * \brief Resets the Control Register of CPSW Wrapper module * * \param baseAddr Base address of the CPSW Wrapper Module * * \return None **/ void CPSWWrControlRegReset(unsigned int baseAddr) { /* Reset the CPSW Wrapper control Register */ HWREG(baseAddr + CPSW_WR_CONTROL) = CPSW_WR_CONTROL_MMR_RESET; } /** * \brief Enables an interrupt for the specified core. * * \param baseAddr Base address of the CPSW Wrapper Module * \param core Core number * \param channel Channel number * \param intFlag Interrupt to be enabled * 'intFlag' can take one of the below values. \n * CPSW_CORE_INT_RX_THRESH - RX threshold interrupt \n * CPSW_CORE_INT_RX_PULSE - RX pulse interrupt \n * CPSW_CORE_INT_TX_PULSE - TX pulse interrupt \n * CPSW_CORE_INT_MISC - Miscellaneous interrupt * * \return None **/ void CPSWWrCoreIntEnable(unsigned int baseAddr, unsigned int core, unsigned int channel, unsigned int intFlag) { HWREG(baseAddr + CPSW_WR_C_RX_THRESH_EN(core) + intFlag) |= (1 << channel); } /** * \brief Disables an interrupt for the specified core. * * \param baseAddr Base address of thei CPSW Wrapper Module * \param core Core number * \param channel Channel number * \param intFlag Interrupt to be disabled * 'intFlag' can take one of the below values. \n * CPSW_CORE_INT_RX_THRESH - RX threshold interrupt \n * CPSW_CORE_INT_RX_PULSE - RX pulse interrupt \n * CPSW_CORE_INT_TX_PULSE - TX pulse interrupt \n * CPSW_CORE_INT_MISC - Miscellaneous interrupt * * \return None **/ void CPSWWrCoreIntDisable(unsigned int baseAddr, unsigned int core, unsigned int channel, unsigned int intFlag) { HWREG(baseAddr + CPSW_WR_C_RX_THRESH_EN(core) + intFlag) &= ~(1 << channel); } /** * \brief Returns the interrupt status of the core for the specified * channel * * \param baseAddr Base address of thei CPSW Wrapper Module * \param core Core number * \param channel Channel number * \param intFlag Interrupt status to be read * 'intFlag' can take one of the below values. \n * CPSW_CORE_INT_RX_THRESH - RX threshold interrupt \n * CPSW_CORE_INT_RX_PULSE - RX pulse interrupt \n * CPSW_CORE_INT_TX_PULSE - TX pulse interrupt \n * CPSW_CORE_INT_MISC - Miscellaneous interrupt * * \return same as intFlag if the status is set * '0' if the status is cleared **/ unsigned int CPSWWrCoreIntStatusGet(unsigned int baseAddr, unsigned int core, unsigned int channel, unsigned int intFlag) { return (HWREG(baseAddr + CPSW_WR_C_RX_THRESH_STAT(core) + intFlag) & (1 << channel)); } /** * \brief Returns the RGMII status requested. * * \param baseAddr Base address of the CPSW Wrapper Module * \param statFlag Status to be checked * 'statFlag' can take a combination of the below values. \n * CPSW_RGMII2_DUPLEX - Duplex of RGMII2 \n * CPSW_RGMII2_SPEED - Speed of RGMII2 \n * CPSW_RGMII2_LINK_STAT - Link Status of RGMII2 \n * CPSW_RGMII1_DUPLEX - Duplex of RGMII1 \n * CPSW_RGMII1_SPEED - Speed of RGMII1 \n * CPSW_RGMII1_LINK_STAT - Link Status of RGMII1 \n * * The returned value can be compared agains the below values \n * CPSW_RGMII2_DUPLEX_FULL - RGMII2 full duplex \n * CPSW_RGMII2_DUPLEX_HALF - RGMII2 half duplex \n * CPSW_RGMII2_SPEED_10M - Speed is 10 Mbps \n * CPSW_RGMII2_SPEED_100M - Speed is 100 Mbps \n * CPSW_RGMII2_SPEED_1000M - Speed is 1000 Mbps \n * CPSW_RGMII2_LINK_UP - RGMII2 link is up\n * CPSW_RGMII2_LINK_DOWN - RGMII2 link is down \n * CPSW_RGMII1_DUPLEX_FULL - RGMII1 full duplex \n * CPSW_RGMII1_DUPLEX_HALF - RGMII1 half duplex \n * CPSW_RGMII1_SPEED_10M - Speed is 10 Mbps \n * CPSW_RGMII1_SPEED_100M - Speed is 100 Mbps \n * CPSW_RGMII1_SPEED_1000M - Speed is 1000 Mbps \n * CPSW_RGMII1_LINK_UP - RGMII1 link is up\n * CPSW_RGMII1_LINK_DOWN - RGMII1 link is down \n * * \return Status of RGMII. Return value can be compared agains the same * statFlag passed. **/ unsigned int CPSWWrRGMIIStatusGet(unsigned int baseAddr, unsigned int statFlag) { return (HWREG(baseAddr + CPSW_WR_RGMII_CTL) & statFlag); } /** * \brief Initializes the ALE. The ALE logic is reset and the ALE table * entries are cleared. * * \param baseAddr Base address of the ALE module * * \return None **/ void CPSWALEInit(unsigned int baseAddr) { HWREG(baseAddr + CPSW_ALE_CONTROL) = (CPSW_ALE_CONTROL_CLEAR_TABLE | CPSW_ALE_CONTROL_ENABLE_ALE); } /** * \brief Age Out Address Table. The Untouched ageable ALE table * entries are cleared. * * \param baseAddr Base address of the ALE module * * \return None **/ void CPSWALEAgeOut(unsigned int baseAddr) { HWREG(baseAddr + CPSW_ALE_CONTROL) |= CPSW_ALE_CONTROL_AGE_OUT_NOW; while(CPSW_ALE_CONTROL_AGE_OUT_NOW & (HWREG(baseAddr + CPSW_ALE_CONTROL))); } /** * \brief Sets the Broadcast Packet Rate Limit * * \param baseAddr Base Address of the ALE module * \param bplVal The Broadcast Packet Rate Limit Value * * \return None * **/ void CPSWALEBroadcastRateLimitSet(unsigned int baseAddr, unsigned int portNum, unsigned int bplVal) { HWREG(baseAddr + CPSW_ALE_PORTCTL(portNum)) &= ~CPSW_ALE_PORTCTL0_BCAST_LIMIT; HWREG(baseAddr + CPSW_ALE_PORTCTL(portNum)) |= (bplVal << CPSW_ALE_PORTCTL0_BCAST_LIMIT_SHIFT); } /** * \brief Sets the Multicast Packet Rate Limit * * \param baseAddr Base Address of the ALE module * \param mplVal The Multicast Packet Rate Limit Value * * \return None * **/ void CPSWALEMulticastRateLimitSet(unsigned int baseAddr, unsigned int portNum, unsigned int mplVal) { HWREG(baseAddr + CPSW_ALE_PORTCTL(portNum)) &= ~CPSW_ALE_PORTCTL0_MCAST_LIMIT; HWREG(baseAddr + CPSW_ALE_PORTCTL(portNum)) |= (mplVal << CPSW_ALE_PORTCTL0_MCAST_LIMIT_SHIFT); } /** * \brief VLAN ID Ingress Check * * \param baseAddr Base Address of the ALE module * * \return None * **/ void CPSWALEVIDIngressCheckSet(unsigned int baseAddr, unsigned int portNum) { HWREG(baseAddr + CPSW_ALE_PORTCTL(portNum)) |= CPSW_ALE_PORTCTL0_MCAST_LIMIT; } /** * \brief Sets the port state in the ALE for a given port * * \param baseAddr Base address of the ALE module * \param portNum The port number * \param portState The port state to be set * 'portState' can take one of the below values \n * CPSW_ALE_PORT_STATE_FWD - ALE state is Forward \n * CPSW_ALE_PORT_STATE_LEARN - ALE state is Learn \n * CPSW_ALE_PORT_STATE_BLOCKED - ALE state is Blocked \n * CPSW_ALE_PORT_STATE_DISABLED - ALE state is Disabled * * \return None **/ void CPSWALEPortStateSet(unsigned int baseAddr, unsigned int portNum, unsigned int portState) { HWREG(baseAddr + CPSW_ALE_PORTCTL(portNum)) &= ~CPSW_ALE_PORTCTL0_PORT_STATE; HWREG(baseAddr + CPSW_ALE_PORTCTL(portNum)) |= portState; } /** * \brief Sets VLAN Aware mode for ALE to Flood if VLAN not found * * \param baseAddr Base address of the ALE Module * * \return None **/ void CPSWALEVLANAwareSet(unsigned int baseAddr) { HWREG(baseAddr + CPSW_ALE_CONTROL) |= CPSW_ALE_CONTROL_ALE_VLAN_AWARE; } /** * \brief Clears VLAN Aware mode for ALE to drop packets * * \param baseAddr Base address of the ALE Module * * \return None **/ void CPSWALEVLANAwareClear(unsigned int baseAddr) { HWREG(baseAddr + CPSW_ALE_CONTROL) &= ~CPSW_ALE_CONTROL_ALE_VLAN_AWARE; } /** * \brief Configure Rate Limit to TX Mode * * \param baseAddr Base address of the ALE Module * * \return None **/ void CPSWALERateLimitTXMode(unsigned int baseAddr) { HWREG(baseAddr + CPSW_ALE_CONTROL) |= CPSW_ALE_CONTROL_RATE_LIMIT_TX; } /** * \brief Configure Rate Limit to RX Mode * * \param baseAddr Base address of the ALE Module * * \return None **/ void CPSWALERateLimitRXMode(unsigned int baseAddr) { HWREG(baseAddr + CPSW_ALE_CONTROL) &= ~CPSW_ALE_CONTROL_RATE_LIMIT_TX; } /** * \brief Enable Rate Limit for ALE * * \param baseAddr Base address of the ALE Module * * \return None **/ void CPSWALERateLimitEnable(unsigned int baseAddr) { HWREG(baseAddr + CPSW_ALE_CONTROL) |= CPSW_ALE_CONTROL_ENABLE_RATE_LIMIT; } /** * \brief Disable Rate Limit for ALE * * \param baseAddr Base address of the ALE Module * * \return None **/ void CPSWALERateLimitDisable(unsigned int baseAddr) { HWREG(baseAddr + CPSW_ALE_CONTROL) &= ~CPSW_ALE_CONTROL_ENABLE_RATE_LIMIT; } /** * \brief Enable MAC Authorization Mode for ALE * * \param baseAddr Base address of the ALE Module * * \return None **/ void CPSWALEAUTHModeSet(unsigned int baseAddr) { HWREG(baseAddr + CPSW_ALE_CONTROL) |= CPSW_ALE_CONTROL_ENABLE_AUTH_MODE; } /** * \brief Disable MAC Authorization Mode for ALE * * \param baseAddr Base address of the ALE Module * * \return None **/ void CPSWALEAUTHModeClear(unsigned int baseAddr) { HWREG(baseAddr + CPSW_ALE_CONTROL) &= ~CPSW_ALE_CONTROL_ENABLE_AUTH_MODE; } /** * \brief Sets an ALE table entry * * \param baseAddr Base address of the ALE Module * \param aleTblIdx The Index of the table entry * \param aleEntryPtr The address of the entry to be set * * \return None **/ void CPSWALETableEntrySet(unsigned int baseAddr, unsigned int aleTblIdx, unsigned int *aleEntryPtr) { unsigned int cnt; for (cnt = 0; cnt < ALE_ENTRY_WORDS; cnt++) { HWREG(baseAddr + CPSW_ALE_TBLW(cnt)) = *(aleEntryPtr + cnt); } HWREG(baseAddr + CPSW_ALE_TBLCTL) = aleTblIdx | CPSW_ALE_TBLCTL_WRITE_RDZ; } /** * \brief Returns an ALE table entry * * \param baseAddr Base address of the ALE Module * \param aleTblIdx The Index of the table entry * \param aleEntryPtr The address where the ALE entry to be written * * \return None **/ void CPSWALETableEntryGet(unsigned int baseAddr, unsigned int aleTblIdx, unsigned int *aleEntryPtr) { unsigned int cnt; HWREG(baseAddr + CPSW_ALE_TBLCTL) = aleTblIdx; for (cnt = 0; cnt < ALE_ENTRY_WORDS; cnt++) { *(aleEntryPtr + cnt) = HWREG(baseAddr + CPSW_ALE_TBLW(cnt)); } } /** * \brief Returns the prescale value for ALE. The input clock is divided * by this value to use in the broadcast/multicast rate limiters. * * \param baseAddr Base Address of the ALE module * * \return Prescale value * **/ unsigned int CPSWALEPrescaleGet(unsigned int baseAddr) { return (HWREG(baseAddr + CPSW_ALE_PRESCALE) & CPSW_ALE_PRESCALE_ALE_PRESCALE); } /** * \brief Sets the prescale value for ALE. The input clock is divided * by this value to use in the broadcast/multicast rate limiters. * * \param baseAddr Base Address of the ALE module * \param psVal The prescale value * * \return None * **/ void CPSWALEPrescaleSet(unsigned int baseAddr, unsigned int psVal) { HWREG(baseAddr + CPSW_ALE_PRESCALE) |= psVal & CPSW_ALE_PRESCALE_ALE_PRESCALE ; } /** * \brief Sets the Unknown VLAN Force Untagged Egress * * \param baseAddr Base Address of the ALE module * \param ueVal The Unknown VLAN Fornce Untagged Egress value * * \return None * **/ void CPSWALEUnknownUntaggedEgressSet(unsigned int baseAddr, unsigned int ueVal) { HWREG(baseAddr + CPSW_ALE_UNKNOWN_VLAN) &= ~CPSW_ALE_UNKNOWN_VLAN_UNKNOWN_FORCE_UNTA; HWREG(baseAddr + CPSW_ALE_UNKNOWN_VLAN) |= (ueVal << CPSW_ALE_UNKNOWN_VLAN_UNKNOWN_FORCE_UNTA_SHIFT); } /** * \brief Sets the Unknown VLAN Registered Multicast Flood Mask * * \param baseAddr Base Address of the ALE module * \param rfmVal Unknown VLAN Registered Multicast Flood Mask Value * * \return None * **/ void CPSWALEUnknownRegFloodMaskSet(unsigned int baseAddr, unsigned int rfmVal) { HWREG(baseAddr + CPSW_ALE_UNKNOWN_VLAN) &= ~CPSW_ALE_UNKNOWN_VLAN_UNKNOWN_MCAST_FLO; HWREG(baseAddr + CPSW_ALE_UNKNOWN_VLAN) |= (rfmVal << CPSW_ALE_UNKNOWN_VLAN_UNKNOWN_MCAST_FLO_SHIFT); } /** * \brief Sets the Unknown VLAN UnRegistered Multicast Flood Mask * * \param baseAddr Base Address of the ALE module * \param ufmVal Unknown VLAN UnRegistered Multicast Flood Mask Value * * \return None * **/ void CPSWALEUnknownUnRegFloodMaskSet(unsigned int baseAddr, unsigned int ufmVal) { HWREG(baseAddr + CPSW_ALE_UNKNOWN_VLAN) &= ~CPSW_ALE_UNKNOWN_VLAN_UNKNOWN_REG_MCAST; HWREG(baseAddr + CPSW_ALE_UNKNOWN_VLAN) |= (ufmVal << CPSW_ALE_UNKNOWN_VLAN_UNKNOWN_REG_MCAST_SHIFT); } /** * \brief Sets the Unknown VLAN Member List * * \param baseAddr Base Address of the ALE module * \param mlVal Unknown VLAN UnRegistered Multicast Flood Mask Value * * \return None * **/ void CPSWALEUnknownMemberListSet(unsigned int baseAddr, unsigned int mlVal) { HWREG(baseAddr + CPSW_ALE_UNKNOWN_VLAN) &= ~CPSW_ALE_UNKNOWN_VLAN_UNKNOWN_VLAN_MEM; HWREG(baseAddr + CPSW_ALE_UNKNOWN_VLAN) |= (mlVal << CPSW_ALE_UNKNOWN_VLAN_UNKNOWN_VLAN_MEM_SHIFT); } /** * \brief Enables the bypassing of the ALE logic * * \param baseAddr Base Address of the ALE module * * \return None * **/ void CPSWALEBypassEnable(unsigned int baseAddr) { HWREG(baseAddr + CPSW_ALE_CONTROL) |= CPSW_ALE_CONTROL_ALE_BYPASS; } /** * \brief Disables the bypassing of the ALE logic * * \param baseAddr Base Address of the ALE module * * \return None * **/ void CPSWALEBypassDisable(unsigned int baseAddr) { HWREG(baseAddr + CPSW_ALE_CONTROL) &= ~CPSW_ALE_CONTROL_ALE_BYPASS; } /** * \brief Enables the receive flow control for CPSW for a given port * * \param baseAddr Base Address of the CPSW subsystem * \param portNum The port number * * \return None * **/ void CPSWRxFlowControlEnable(unsigned int baseAddr, unsigned int portNum) { HWREG(baseAddr + CPSW_SS_FLOW_CONTROL) |= (1 << portNum); } /** * \brief Disables the receive flow control for CPSW for a given port * * \param baseAddr Base Address of the CPSW subsystem * \param portNum The port number * * \return None * **/ void CPSWRxFlowControlDisable(unsigned int baseAddr, unsigned int portNum) { HWREG(baseAddr + CPSW_SS_FLOW_CONTROL) &= ~(1 << portNum); } /** * \brief Enables the software idle mode, causing the switch fabric to stop * forward packets at the next start of packet. * * \param baseAddr Base Address of the CPSW subsystem * * \return None * **/ void CPSWSoftwareIdleEnable(unsigned int baseAddr) { HWREG(baseAddr + CPSW_SS_SOFT_IDLE) |= CPSW_SS_SOFT_IDLE_SOFT_IDLE; } /** * \brief Disables the software idle mode, causing the switch fabric to * forward packets at the next start of packet. * * \param baseAddr Base Address of the CPSW subsystem * * \return None * **/ void CPSWSoftwareIdleDisable(unsigned int baseAddr, unsigned int portNum) { (void) portNum; HWREG(baseAddr + CPSW_SS_SOFT_IDLE) &= ~CPSW_SS_SOFT_IDLE_SOFT_IDLE; } /** * \brief Enables the CPSW statistics for the given port * * \param baseAddr Base Address of the CPSW subsystem * \param portNum The port number * * \return None * **/ void CPSWStatisticsEnable(unsigned int baseAddr) { HWREG(baseAddr + CPSW_SS_STAT_PORT_EN) = CPSW_SS_STAT_PORT_EN_P0_STAT_EN | CPSW_SS_STAT_PORT_EN_P1_STAT_EN | CPSW_SS_STAT_PORT_EN_P2_STAT_EN; } /** * \brief Enables the VLAN aware mode for CPSW * * \param baseAddr Base Address of the CPSW subsystem * * \return None * **/ void CPSWVLANAwareEnable(unsigned int baseAddr) { HWREG(baseAddr + CPSW_SS_CONTROL) |= CPSW_SS_CONTROL_VLAN_AWARE; } /** * \brief Disables the VLAN aware mode for CPSW * * \param baseAddr Base Address of the CPSW subsystem * * \return None * **/ void CPSWVLANAwareDisable(unsigned int baseAddr) { HWREG(baseAddr + CPSW_SS_CONTROL) &= ~CPSW_SS_CONTROL_VLAN_AWARE; } /** * \brief Sets the ethernet address at the CPSW port * * \param baseAddr Base address of the CPSW Port Module registers * \param ethAddr Start address of the 6 byte ethernet address * * \return None * **/ void CPSWPortSrcAddrSet(unsigned int baseAddr, unsigned char *ethAddr) { HWREG(baseAddr + CPSW_PORT_SA_HI) = ethAddr[0] | (ethAddr[1] << CPSW_PORT_P1_SA_HI_MACSRCADDR_39_32_SHIFT) | (ethAddr[2] << CPSW_PORT_P1_SA_HI_MACSRCADDR_31_24_SHIFT) | (ethAddr[3] << CPSW_PORT_P1_SA_HI_MACSRCADDR_23_16_SHIFT); HWREG(baseAddr + CPSW_PORT_SA_LO) = ethAddr[4] | (ethAddr[5] << CPSW_PORT_P1_SA_LO_MACSRCADDR_7_0_SHIFT); } /** * \brief Sets Dual Mac Mode for CPSW Port0 * * \param baseAddr Base address of the CPSW Host Port Module registers * * \return None * **/ void CPSWHostPortDualMacModeSet(unsigned int baseAddr) { HWREG(baseAddr + CPSW_PORT_TX_IN_CTL) &= ~CPSW_PORT_P0_TX_IN_CTL_TX_IN_SEL; HWREG(baseAddr + CPSW_PORT_TX_IN_CTL) |= CPSW_PORT_P0_TX_IN_CTL_TX_IN_DUAL_MAC; } /** * \brief Configures Port VLAN * * \param baseAddr Base address of the CPSW Port Module registers * \param vlanId VLAN ID to be set * \param cfiBit CFI value to be set * \param vlanPri Port VLAN priority * 'vlanId' can take a value from 0 to 0xFFF \n * 'cfiBit' can be either 0 or 1. \n * 'vlanPri' can be any value between and including 0 and 7. * * \return None * **/ void CPSWPortVLANConfig(unsigned int baseAddr, unsigned int vlanId, unsigned int cfiBit, unsigned int vlanPri) { HWREG(baseAddr + CPSW_PORT_PORT_VLAN) = vlanId | (cfiBit << CPSW_PORT_P2_PORT_VLAN_PORT_CFI_SHIFT) | (vlanPri << CPSW_PORT_P2_PORT_VLAN_PORT_PRI_SHIFT); } /** * \brief Returns the requested CPSW Statistics * * \param baseAddr Base address of the CPSW Status Module registers. * \param statReg Statistics Register to be read * * \return The requested statistics * **/ unsigned int CPSWStatisticsGet(unsigned int baseAddr, unsigned int statReg) { return (HWREG(baseAddr + statReg)); } /** * \brief Resets the CPDMA * * \param baseAddr Base address of the CPDMA Module registers. * * \return None * **/ void CPSWCPDMAReset(unsigned int baseAddr) { unsigned int cnt; /* Reset the CPDMA */ HWREG(baseAddr + CPSW_CPDMA_CPDMA_SOFT_RESET) = CPSW_CPDMA_CPDMA_SOFT_RESET_SOFT_RESET; /* Wait till the reset completes */ while(HWREG(baseAddr + CPSW_CPDMA_CPDMA_SOFT_RESET) & CPSW_CPDMA_CPDMA_SOFT_RESET_SOFT_RESET); /* Initialize all the header descriptor pointer registers */ for(cnt = 0; cnt< CPSW_MAX_HEADER_DESC; cnt++) { HWREG(baseAddr + CPSW_CPDMA_TX_HDP(cnt)) = 0; HWREG(baseAddr + CPSW_CPDMA_RX_HDP(cnt)) = 0; HWREG(baseAddr + CPSW_CPDMA_TX_CP(cnt)) = 0; HWREG(baseAddr + CPSW_CPDMA_RX_CP(cnt)) = 0; } } /** * \brief Enables the TXPULSE Interrupt Generation. * * \param baseAddr Base address of the CPDMA Module registers. * \param channel Channel number for which interrupt to be enabled * * \return None * **/ void CPSWCPDMATxIntEnable(unsigned int baseAddr, unsigned int channel) { HWREG(baseAddr + CPSW_CPDMA_TX_INTMASK_SET) |= (1 << channel); } /** * \brief Enables the RXPULSE Interrupt Generation. * * \param baseAddr Base address of the CPDMA Module registers. * \param channel Channel number for which interrupt to be enabled * * \return None * **/ void CPSWCPDMARxIntEnable(unsigned int baseAddr, unsigned int channel) { HWREG(baseAddr + CPSW_CPDMA_RX_INTMASK_SET) |= (1 << channel); } /** * \brief Disables the TXPULSE Interrupt Generation. * * \param baseAddr Base address of the CPDMA Module registers. * \param channel Channel number for which interrupt to be disabled * * \return None * **/ void CPSWCPDMATxIntDisable(unsigned int baseAddr, unsigned int channel) { HWREG(baseAddr + CPSW_CPDMA_TX_INTMASK_CLEAR) |= (1 << channel); } /** * \brief Disables the RXPULSE Interrupt Generation. * * \param baseAddr Base address of the CPDMA Module registers. * \param channel Channel number for which interrupt to be disabled * * \return None * **/ void CPSWCPDMARxIntDisable(unsigned int baseAddr, unsigned int channel) { HWREG(baseAddr + CPSW_CPDMA_RX_INTMASK_CLEAR) |= (1 << channel); } /** * \brief API to enable the transmit in the TX Control Register. * After the transmit is enabled, any write to TXHDP of * a channel will start transmission * * \param baseAddr Base Address of the CPDMA module registers. * * \return None * **/ void CPSWCPDMATxEnable(unsigned int baseAddr) { HWREG(baseAddr + CPSW_CPDMA_TX_CONTROL) = CPSW_CPDMA_TX_CONTROL_TX_EN; } /** * \brief API to enable the receive in the RX Control Register. * After the receive is enabled, and write to RXHDP of * a channel, the data can be received in the destination * specified by the corresponding RX buffer descriptor. * * \param baseAddr Base Address of the CPDMA module registers. * * \return None * **/ void CPSWCPDMARxEnable(unsigned int baseAddr) { HWREG(baseAddr + CPSW_CPDMA_RX_CONTROL) = CPSW_CPDMA_RX_CONTROL_RX_EN; } /** * \brief API to write the TX HDP register. If transmit is enabled, * write to the TX HDP will immediately start transmission. * The data will be taken from the buffer pointer of the TX buffer * descriptor written to the TX HDP * * \param baseAddr Base Address of the CPDMA module registers. * \param descHdr Address of the TX buffer descriptor * \param channel Channel Number * * \return None * **/ #include void CPSWCPDMATxHdrDescPtrWrite(unsigned int baseAddr, unsigned int descHdr, unsigned int channel) { HWREG(baseAddr + CPSW_CPDMA_TX_HDP(channel)) = descHdr; } /** * \brief API to write the RX HDP register. If receive is enabled, * write to the RX HDP will enable data reception to point to * the corresponding RX buffer descriptor's buffer pointer. * * \param baseAddr Base Address of the CPDMA module registers. * \param descHdr Address of the RX buffer descriptor * \param channel Channel Number * * \return None * **/ void CPSWCPDMARxHdrDescPtrWrite(unsigned int baseAddr, unsigned int descHdr, unsigned int channel) { HWREG(baseAddr + CPSW_CPDMA_RX_HDP(channel)) = descHdr; } /** * \brief Writes the DMA End Of Interrupt Vector. * * \param baseAddr Base Address of the CPDMA module registers. * \param eoiFlag Type of interrupt to acknowledge to the CPDMA * 'eoiFlag' can take the following values \n * CPSW_EOI_TX_PULSE - TX Pulse Interrupt \n * CPSW_EOI_RX_PULSE - RX Pulse Interrupt \n * CPSW_EOI_RX_THRESH_PULSE - RX Pulse Threshold Interrupt \n * CPSW_EOI_MISC_PULSE - Misc Interrupt \n * * \return None * **/ void CPSWCPDMAEndOfIntVectorWrite(unsigned int baseAddr, unsigned int eoiFlag) { /* Acknowledge the CPDMA */ HWREG(baseAddr + CPSW_CPDMA_CPDMA_EOI_VECTOR) = eoiFlag; } /** * \brief Reads the RX Completion Pointer for a specific channel * * \param baseAddr Base Address of the CPDMA module registers. * \param channel Channel Number. * * \return RX Completion Pointer value. * **/ unsigned int CPSWCPDMATxCPRead(unsigned int baseAddr, unsigned int channel) { return HWREG(baseAddr + CPSW_CPDMA_TX_CP(channel)); } /** * \brief Writes the the TX Completion Pointer for a specific channel * * \param baseAddr Base Address of the CPDMA module registers. * \param channel Channel Number. * \param comPtr Completion Pointer Value to be written * * \return None * **/ void CPSWCPDMATxCPWrite(unsigned int baseAddr, unsigned int channel, unsigned int comPtr) { HWREG(baseAddr + CPSW_CPDMA_TX_CP(channel)) = comPtr; } /** * \brief Reads the RX Completion Pointer for a specific channel * * \param baseAddr Base Address of the CPDMA module registers. * \param channel Channel Number. * * \return RX Completion Pointer value. * **/ unsigned int CPSWCPDMARxCPRead(unsigned int baseAddr, unsigned int channel) { return HWREG(baseAddr + CPSW_CPDMA_RX_CP(channel)); } /** * \brief Writes the the RX Completion Pointer for a specific channel * * \param baseAddr Base Address of the CPDMA module registers. * \param channel Channel Number. * \param comPtr Completion Pointer Value to be written * * \return None * **/ void CPSWCPDMARxCPWrite(unsigned int baseAddr, unsigned int channel, unsigned int comPtr) { HWREG(baseAddr + CPSW_CPDMA_RX_CP(channel)) = comPtr; } /** * \brief Set the free buffers for a specific channel * * \param baseAddr Base Address of the CPDMA module registers. * \param channel Channel Number. * \param nBuf Number of free buffers * * \return None * **/ void CPSWCPDMANumFreeBufSet(unsigned int baseAddr, unsigned int channel, unsigned int nBuf) { HWREG(baseAddr + CPSW_CPDMA_RX_FREEBUFFER(channel)) = nBuf; } /** * \brief Returns the CPDMA Status. * * \param baseAddr Base Address of the CPDMA module registers. * \param statFlag The status flags to be read * 'statFlag' can take one of the following values \n * CPDMA_STAT_IDLE - to check if CPDMA is idle. \n * CPDMA_STAT_TX_HOST_ERR_CODE - TX host error code. \n * CPDMA_STAT_TX_HOST_ERR_CHAN - TX host error channel. \n * CPDMA_STAT_RX_HOST_ERR_CODE - RX host error code. \n * CPDMA_STAT_RX_HOST_ERR_CHAN - RX host error channel. \n * * \return the DMA status for the status flag passed. * The return values for CPDMA_STAT_IDLE are, \n * CPDMA_STAT_IDLE - CPDMA is in idle state \n * CPDMA_STAT_NOT_IDLE - CPDMA is not in idle state \n * * The return values for CPDMA_STAT_TX_HOST_ERR_CODE are, \n * CPDMA_STAT_TX_NO_ERR - No error \n * CPDMA_STAT_TX_SOP_ERR - SOP error \n * CPDMA_STAT_TX_OWN_ERR - Ownership bit not * set in SOP buffer \n * CPDMA_STAT_TX_ZERO_DESC - Zero Next Buffer * Descriptor Pointer Without EOP \n * CPDMA_STAT_TX_ZERO_BUF_PTR - Zero Buffer Pointer \n * CPDMA_STAT_TX_ZERO_BUF_LEN - Zero Buffer Length \n * CPDMA_STAT_TX_PKT_LEN_ERR - Packet Length Error \n * * The return values for CPDMA_STAT_RX_HOST_ERR_CODE are, \n * CPDMA_STAT_RXi_NO_ERR - No error \n * CPDMA_STAT_RX_OWN_NOT_SET - Ownership bit not set in input buffer \n * CPDMA_STAT_RX_ZERO_BUF_PTR - Zero Buffer Pointer\n * CPDMA_STAT_RX_ZERO_BUF_LEN - Zero Buffer Length on * non-SOP descriptor \n * CPDMA_STAT_RX_SOP_BUF_LEN_ERR - SOP buffer length not * greater than offset\n * **/ unsigned int CPSWCPDMAStatusGet(unsigned int baseAddr, unsigned int statFlag) { return (((HWREG(baseAddr + CPSW_CPDMA_DMASTATUS)) & statFlag) >> (statFlag & CPDMA_ERR_CHANNEL_POS)); } /** * \brief Configures the CPDMA module by writing the configuration value * to the DMA control register. * * \param baseAddr Base Address of the CPDMA module registers * \param cfg CPDMA configuration written to control register * 'cfg' shall be CPDMA_CFG(tx_rlim, rx_cef, cmd_idle, * rx_offlen_blk, rx_own, tx_ptype). \n * The parameter 'tx_rlim' to CPDMA_CFG can take one of the below * values, showing which all channels are rate-limited. \n * CPDMA_CFG_TX_RATE_LIM_CH_7 \n * CPDMA_CFG_TX_RATE_LIM_CH_7_TO_6 \n * CPDMA_CFG_TX_RATE_LIM_CH_7_TO_5 \n * CPDMA_CFG_TX_RATE_LIM_CH_7_TO_4 \n * CPDMA_CFG_TX_RATE_LIM_CH_7_TO_3 \n * CPDMA_CFG_TX_RATE_LIM_CH_7_TO_2 \n * CPDMA_CFG_TX_RATE_LIM_CH_7_TO_1 \n * CPDMA_CFG_TX_RATE_LIM_CH_7_TO_0 \n * The parameter 'rx_cef' to CPDMA_CFG can take one of the below * values \n * CPDMA_CFG_COPY_ERR_FRAMES - To copy error frames to memory \n * CPDMA_CFG_NO_COPY_ERR_FRAMES - Not to copy error frames \n * The parameter 'cmd_idle' to CPDMA_CFG can take one of the below * values \n * CPDMA_CFG_IDLE_COMMAND - Idle commanded \n * CPDMA_CFG_IDLE_COMMAND_NONE - Idle not commanded \n * The parameter 'rx_offlen_blk' to CPDMA_CFG can take one of the below * values \n * CPDMA_CFG_BLOCK_RX_OFF_LEN_WRITE - Block the DMA writes to the * offset/length field during * packet processing. \n * CPDMA_CFG_NOT_BLOCK_RX_OFF_LEN_WRITE - Do not Block the DMA writes * to the offset/length field during * packet processing. \n * The parameter 'rx_own' to CPDMA_CFG can take one of the below * values \n * CPDMA_CFG_RX_OWN_1 - The CPDMA writes 1 to the ownership bit at * the end of packet processing. \n * CPDMA_CFG_RX_OWN_0 - The CPDMA writes 0 to the ownership bit at * the end of packet processing. \n * The parameter 'tx_ptype' to CPDMA_CFG can take one of the below * values \n * CPDMA_CFG_TX_PRI_ROUND_ROBIN - The next channel for transmit is * chosen round-robin. \n * CPDMA_CFG_TX_PRI_FIXED - The next channel for transmit is * chosen priority based, channel 7 with the * highest priority \n * * \return None * **/ void CPSWCPDMAConfig(unsigned int baseAddr, unsigned int cfg) { HWREG(baseAddr + CPSW_CPDMA_DMACONTROL) = cfg; } /** * \brief Enable the command idle mode for CPDMA. When this API is called, the * CPSW stops all the reception and transmission. However, if receiving * the current frame will be received completely before going to the idle * state. Also, while transmitting, the contents in the fifo will be sent * fully. * * \param baseAddr Base Address of the CPDMA module registers * * \return None * **/ void CPSWCPDMACmdIdleEnable(unsigned int baseAddr) { HWREG(baseAddr + CPSW_CPDMA_DMACONTROL) |= CPSW_CPDMA_DMACONTROL_CMD_IDLE; /* Wait till the state changes to idle */ while((HWREG(baseAddr + CPSW_CPDMA_DMASTATUS) & CPSW_CPDMA_DMASTATUS_IDLE) != CPSW_CPDMA_DMASTATUS_IDLE); } /** * \brief Disable the command idle mode for CPDMA. * * \param baseAddr Base Address of the CPDMA module registers * * \return None * **/ void CPSWCPDMACmdIdleDisable(unsigned int baseAddr) { HWREG(baseAddr + CPSW_CPDMA_DMACONTROL) &= ~CPSW_CPDMA_DMACONTROL_CMD_IDLE; } /** * \brief Sets the RX buffer offset value. The RX buffer offset will be * written by the port into each frame SOP buffer descriptor * buffer_offset field. The frame data will begin after the * rx_buffer_offset value of bytes. This value will be used for * all the channels . * * \param baseAddr Base Address of the CPDMA module registers * \param bufOff Buffer offset value * * \return None * **/ void CPSWCPDMARxBufOffsetSet(unsigned int baseAddr, unsigned int bufOff) { HWREG(baseAddr + CPSW_CPDMA_RX_BUFFER_OFFSET) = bufOff; } /** * \brief Returns the raw transmit interrupt pending status. * * \param baseAddr Base Address of the CPDMA module registers * \param chanMask Channel Mask * 'chanMask' can be given for one or more channels. \n * 0x01- for 0th channel, 0x80 for 7th channel, 0x81 for both 0th * and 7th channel etc. \n * * \return Raw receive interrupt status \n * bits for the 'chanMask' will be set if interrupt is pending \n * bits for the 'chanMask' will be clear if interrupt is not * pending \n * **/ unsigned int CPSWCPDMATxIntStatRawGet(unsigned int baseAddr, unsigned int chanMask) { return (HWREG(baseAddr + CPSW_CPDMA_TX_INTSTAT_RAW) & chanMask); } /** * \brief Returns the masked transmit interrupt pending status. * * \param baseAddr Base Address of the CPDMA module registers * \param chanMask Channel Mask * 'chanMask' can be given for one or more channels. \n * 0x01- for 0th channel, 0x80 for 7th channel, 0x81 for both 0th * and 7th channel etc. \n * * \return Masked transmit interrupt status \n * bits for the 'chanMask' will be set if interrupt is pending \n * bits for the 'chanMask' will be cleared if interrupt is not * pending \n * **/ unsigned int CPSWCPDMATxIntStatMaskedGet(unsigned int baseAddr, unsigned int chanMask) { return (HWREG(baseAddr + CPSW_CPDMA_TX_INTSTAT_MASKED) & chanMask); } /** * \brief Returns the raw receive interrupt pending status. * * \param baseAddr Base Address of the CPDMA module registers * \param chanMask Channel Mask * \param intType Interrupt type * 'chanMask' can be given for one or more channels. \n * 0x01- for 0th channel, 0x80 for 7th channel, 0x81 for both 0th * and 7th channel etc. \n * 'intType' can take one of the following values. \n * CPDMA_RX_INT_THRESH_PEND - RX threshold interrupt pending \n * CPDMA_RX_INT_PULSE_PEND - RX pulse interrupt pending \n * * \return Raw receive interrupt status \n * bits for the 'chanMask' will be set if interrupt is pending \n * bits for the 'chanMask' will be cleared if interrupt is not * pending \n * **/ unsigned int CPSWCPDMARxIntStatRawGet(unsigned int baseAddr, unsigned int chanMask, unsigned int intType) { return ((HWREG(baseAddr + CPSW_CPDMA_RX_INTSTAT_RAW) >> intType) & chanMask); } /** * \brief Returns the masked receive interrupt pending status. * * \param baseAddr Base Address of the CPDMA module registers * \param chanMask Channel Mask * \param intType Interrupt type * 'chanMask' can be given for one or more channels. \n * 0x01- for 0th channel, 0x80 for 7th channel, 0x81 for both 0th * and 7th channel etc. \n * 'intType' can take one of the following values. \n * CPDMA_RX_INT_THRESH_PEND - RX threshold interrupt pending \n * CPDMA_RX_INT_PULSE_PEND - RX pulse interrupt pending \n * * \return Masked receive interrupt status \n * bits for the 'chanMask' will be set if interrupt is pending \n * bits for the 'chanMask' will be cleared if interrupt is not * pending \n * **/ unsigned int CPSWCPDMARxIntStatMaskedGet(unsigned int baseAddr, unsigned int chanMask, unsigned int intType) { return ((HWREG(baseAddr + CPSW_CPDMA_RX_INTSTAT_MASKED) >> intType) & chanMask); } /** * \brief Saves the CPSW register context. This can be used while going * to power down mode where CPSW power will be cut down. * * \param contextPtr Pointer to the structure where CPSW register context * need to be saved. * * \return None * **/ void CPSWContextSave(CPSWCONTEXT *contextPtr) { unsigned int idx; unsigned int *cppiDest = (unsigned int*)contextPtr->cppiRamBase; CPSWCPDMACmdIdleEnable(contextPtr->cpdmaBase); /* Restore the CPPI RAM contents */ for(idx = 0; idx < (CPSW_SIZE_CPPI_RAM / 4); idx++, cppiDest++) { contextPtr->cppiRam[idx] = *cppiDest; } contextPtr->aleCtrl = HWREG(contextPtr->aleBase + CPSW_ALE_CONTROL); contextPtr->alePortCtl[0] = HWREG(contextPtr->aleBase + CPSW_ALE_PORTCTL(0)); contextPtr->alePortCtl[1] = HWREG(contextPtr->aleBase + CPSW_ALE_PORTCTL(1)); contextPtr->alePortCtl[2] = HWREG(contextPtr->aleBase + CPSW_ALE_PORTCTL(2)); for(idx = 0; idx < CPSW_MAX_NUM_ALE_ENTRY; idx++) { CPSWALETableEntryGet(contextPtr->aleBase, idx, &(contextPtr->aleEntry[idx * 3])); } contextPtr->ssStatPortEn = HWREG(contextPtr->ssBase + CPSW_SS_STAT_PORT_EN); contextPtr->port1SaHi = HWREG(contextPtr->port1Base + CPSW_PORT_SA_HI); contextPtr->port1SaLo = HWREG(contextPtr->port1Base + CPSW_PORT_SA_LO); contextPtr->port2SaHi = HWREG(contextPtr->port2Base + CPSW_PORT_SA_HI); contextPtr->port2SaLo = HWREG(contextPtr->port2Base + CPSW_PORT_SA_LO); contextPtr->port1TxInCtl = HWREG(contextPtr->port1Base + CPSW_PORT_TX_IN_CTL); contextPtr->port2TxInCtl = HWREG(contextPtr->port2Base + CPSW_PORT_TX_IN_CTL); contextPtr->port1Vlan = HWREG(contextPtr->port1Base + CPSW_PORT_PORT_VLAN); contextPtr->port2Vlan = HWREG(contextPtr->port2Base + CPSW_PORT_PORT_VLAN); contextPtr->cpdmaRxFB = HWREG(contextPtr->cpdmaBase + CPSW_CPDMA_RX_FREEBUFFER(0)); contextPtr->cpdmaTxCtl = HWREG(contextPtr->cpdmaBase + CPSW_CPDMA_TX_CONTROL); contextPtr->cpdmaRxCtl = HWREG(contextPtr->cpdmaBase + CPSW_CPDMA_RX_CONTROL); contextPtr->cpdmaRxHdp = HWREG(contextPtr->cpdmaBase + CPSW_CPDMA_RX_HDP(0)); contextPtr->txIntMaskSet = HWREG(contextPtr->cpdmaBase + CPSW_CPDMA_TX_INTMASK_SET); contextPtr->wrCoreIntTxPulse = HWREG(contextPtr->wrBase + CPSW_WR_C_RX_THRESH_EN(0) + 0x04); contextPtr->rxIntMaskSet = HWREG(contextPtr->cpdmaBase + CPSW_CPDMA_RX_INTMASK_SET); contextPtr->wrCoreIntRxPulse = HWREG(contextPtr->wrBase + CPSW_WR_C_RX_THRESH_EN(0) + 0x08); contextPtr->sl1MacCtl = HWREG(contextPtr->sl1Base + CPSW_SL_MACCONTROL); contextPtr->sl2MacCtl = HWREG(contextPtr->sl2Base + CPSW_SL_MACCONTROL); } /** * \brief Restores the CPSW register context. This can be used while coming * back from power down mode where CPSW power will be cut down. * * \param contextPtr Pointer to the structure where CPSW register context * need to be restored from. * * \return None * **/ void CPSWContextRestore(CPSWCONTEXT *contextPtr) { unsigned int idx; unsigned int *cppiDest = (unsigned int*)contextPtr->cppiRamBase; /* Restore the CPPI RAM contents */ for(idx = 0; idx < (CPSW_SIZE_CPPI_RAM / 4); idx++, cppiDest++) { *cppiDest = contextPtr->cppiRam[idx] ; } HWREG(contextPtr->aleBase + CPSW_ALE_CONTROL) = contextPtr->aleCtrl; HWREG(contextPtr->aleBase + CPSW_ALE_PORTCTL(0)) = contextPtr->alePortCtl[0]; HWREG(contextPtr->aleBase + CPSW_ALE_PORTCTL(1)) = contextPtr->alePortCtl[1]; HWREG(contextPtr->aleBase + CPSW_ALE_PORTCTL(2)) = contextPtr->alePortCtl[2]; for(idx = 0; idx < CPSW_MAX_NUM_ALE_ENTRY; idx++) { CPSWALETableEntrySet(contextPtr->aleBase, idx, &(contextPtr->aleEntry[idx * 3])); } HWREG(contextPtr->ssBase + CPSW_SS_STAT_PORT_EN) = contextPtr->ssStatPortEn; HWREG(contextPtr->port1Base + CPSW_PORT_SA_HI) = contextPtr->port1SaHi; HWREG(contextPtr->port1Base + CPSW_PORT_SA_LO) = contextPtr->port1SaLo; HWREG(contextPtr->port2Base + CPSW_PORT_SA_HI) = contextPtr->port2SaHi; HWREG(contextPtr->port2Base + CPSW_PORT_SA_LO) = contextPtr->port2SaLo; HWREG(contextPtr->port1Base + CPSW_PORT_TX_IN_CTL) = contextPtr->port1TxInCtl; HWREG(contextPtr->port2Base + CPSW_PORT_TX_IN_CTL) = contextPtr->port2TxInCtl; HWREG(contextPtr->port1Base + CPSW_PORT_PORT_VLAN) = contextPtr->port1Vlan; HWREG(contextPtr->port2Base + CPSW_PORT_PORT_VLAN) = contextPtr->port2Vlan; HWREG(contextPtr->cpdmaBase + CPSW_CPDMA_RX_FREEBUFFER(0)) = contextPtr->cpdmaRxFB; HWREG(contextPtr->cpdmaBase + CPSW_CPDMA_TX_CONTROL) = contextPtr->cpdmaTxCtl; HWREG(contextPtr->cpdmaBase + CPSW_CPDMA_RX_CONTROL) = contextPtr->cpdmaRxCtl; HWREG(contextPtr->cpdmaBase + CPSW_CPDMA_RX_HDP(0)) = contextPtr->cpdmaRxHdp; HWREG(contextPtr->cpdmaBase + CPSW_CPDMA_TX_INTMASK_SET) = contextPtr->txIntMaskSet; HWREG(contextPtr->wrBase + CPSW_WR_C_RX_THRESH_EN(0) + 0x04) = contextPtr->wrCoreIntTxPulse; HWREG(contextPtr->cpdmaBase + CPSW_CPDMA_RX_INTMASK_SET) = contextPtr->rxIntMaskSet; HWREG(contextPtr->wrBase + CPSW_WR_C_RX_THRESH_EN(0) + 0x08) = contextPtr->wrCoreIntRxPulse; HWREG(contextPtr->sl1Base + CPSW_SL_MACCONTROL) = contextPtr->sl1MacCtl; HWREG(contextPtr->sl2Base + CPSW_SL_MACCONTROL) = contextPtr->sl2MacCtl; }