/* ---------------------------------------------------------------------------- | |
* SAM Software Package License | |
* ---------------------------------------------------------------------------- | |
* Copyright (c) 2011, Atmel Corporation | |
* | |
* All rights reserved. | |
* | |
* 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 disclaimer below. | |
* | |
* Atmel's name may not be used to endorse or promote products derived from | |
* this software without specific prior written permission. | |
* | |
* DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR | |
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF | |
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE | |
* DISCLAIMED. IN NO EVENT SHALL ATMEL 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. | |
* ---------------------------------------------------------------------------- | |
*/ | |
/** \file */ | |
/** \addtogroup emac_functions | |
*@{ | |
*/ | |
/*---------------------------------------------------------------------------- | |
* Headers | |
*----------------------------------------------------------------------------*/ | |
#include "chip.h" | |
/*---------------------------------------------------------------------------- | |
* Exported functions | |
*----------------------------------------------------------------------------*/ | |
/** | |
* Write control value | |
*/ | |
void EMAC_NetworkControl(Emac *pEmac, uint32_t bmNCR) | |
{ | |
pEmac->EMAC_NCR = bmNCR; | |
} | |
uint32_t EMAC_GetNetworkControl(Emac *pEmac) | |
{ | |
return pEmac->EMAC_NCR; | |
} | |
/** | |
* Enable/Disable EMAC receive. | |
*/ | |
void EMAC_ReceiveEnable(Emac* pEmac, uint8_t bEnaDis) | |
{ | |
if (bEnaDis) pEmac->EMAC_NCR |= EMAC_NCR_RE; | |
else pEmac->EMAC_NCR &= ~EMAC_NCR_RE; | |
} | |
/** | |
* Enable/Disable EMAC transmit. | |
*/ | |
void EMAC_TransmitEnable(Emac *pEmac, uint8_t bEnaDis) | |
{ | |
if (bEnaDis) pEmac->EMAC_NCR |= EMAC_NCR_TE; | |
else pEmac->EMAC_NCR &= ~EMAC_NCR_TE; | |
} | |
/** | |
* Enable/Disable EMAC management. | |
*/ | |
void EMAC_ManagementEnable(Emac *pEmac, uint8_t bEnaDis) | |
{ | |
if (bEnaDis) pEmac->EMAC_NCR |= EMAC_NCR_MPE; | |
else pEmac->EMAC_NCR &= ~EMAC_NCR_MPE; | |
} | |
/** | |
* Clear all statistics registers | |
*/ | |
void EMAC_ClearStatistics(Emac *pEmac) | |
{ | |
pEmac->EMAC_NCR |= EMAC_NCR_CLRSTAT; | |
//pEmac->EMAC_NCR &= ~EMAC_NCR_CLRSTAT; | |
} | |
/** | |
* Increase all statistics registers | |
*/ | |
void EMAC_IncreaseStatistics(Emac *pEmac) | |
{ | |
pEmac->EMAC_NCR |= EMAC_NCR_INCSTAT; | |
//pEmac->EMAC_NCR &= ~EMAC_NCR_INCSTAT; | |
} | |
/** | |
* Enable/Disable statistics registers writing. | |
*/ | |
void EMAC_StatisticsWriteEnable(Emac *pEmac, uint8_t bEnaDis) | |
{ | |
if (bEnaDis) pEmac->EMAC_NCR |= EMAC_NCR_WESTAT; | |
else pEmac->EMAC_NCR &= ~EMAC_NCR_WESTAT; | |
} | |
/** | |
* In half-duplex mode, forces collisions on all received frames. | |
*/ | |
void EMAC_BackPressureEnable(Emac *pEmac, uint8_t bEnaDis) | |
{ | |
if (bEnaDis) pEmac->EMAC_NCR |= EMAC_NCR_BP; | |
else pEmac->EMAC_NCR &= ~EMAC_NCR_BP; | |
} | |
/** | |
* Start transmission | |
*/ | |
void EMAC_TransmissionStart(Emac *pEmac) | |
{ | |
pEmac->EMAC_NCR |= EMAC_NCR_TSTART; | |
} | |
/** | |
* Halt transmission | |
*/ | |
void EMAC_TransmissionHalt(Emac *pEmac) | |
{ | |
pEmac->EMAC_NCR |= EMAC_NCR_THALT; | |
} | |
/** | |
* Setup network configuration register | |
*/ | |
void EMAC_Configure(Emac *pEmac, uint32_t dwCfg) | |
{ | |
pEmac->EMAC_NCFGR = dwCfg; | |
} | |
/** | |
* Return network configuration. | |
*/ | |
uint32_t EMAC_GetConfigure(Emac *pEmac) | |
{ | |
return pEmac->EMAC_NCFGR; | |
} | |
/** | |
* Set speed. | |
* \param bSpeed 1 to indicate 100Mbps, 0 for 10Mbps. | |
*/ | |
void EMAC_SetSpeed(Emac *pEmac, uint8_t bSpeed) | |
{ | |
if (bSpeed) pEmac->EMAC_NCFGR |= EMAC_NCFGR_SPD; | |
else pEmac->EMAC_NCFGR &= ~EMAC_NCFGR_SPD; | |
} | |
/** | |
* Enable/Disable Full-Duplex mode | |
*/ | |
void EMAC_FullDuplexEnable(Emac *pEmac, uint8_t bFD) | |
{ | |
if (bFD) pEmac->EMAC_NCFGR |= EMAC_NCFGR_FD; | |
else pEmac->EMAC_NCFGR &= ~EMAC_NCFGR_FD; | |
} | |
/** | |
* Enable/Disable Copy(Receive) All Valid Frames | |
*/ | |
void EMAC_CpyAllEnable(Emac *pEmac, uint8_t bCAF) | |
{ | |
if (bCAF) pEmac->EMAC_NCFGR |= EMAC_NCFGR_CAF; | |
else pEmac->EMAC_NCFGR &= ~EMAC_NCFGR_CAF; | |
} | |
/** | |
* Enable/Disable jumbo frames (up to 10240 bytes). | |
*/ | |
void EMAC_JumboFrameEnable(Emac *pEmac, uint8_t bEnaDis) | |
{ | |
if (bEnaDis) pEmac->EMAC_NCFGR |= EMAC_NCFGR_JFRAME; | |
else pEmac->EMAC_NCFGR &= ~EMAC_NCFGR_JFRAME; | |
} | |
/** | |
* Disable/Enable broadcase receiving. | |
*/ | |
void EMAC_BroadcastDisable(Emac *pEmac, uint8_t bDisEna) | |
{ | |
if (bDisEna) pEmac->EMAC_NCFGR |= EMAC_NCFGR_NBC; | |
else pEmac->EMAC_NCFGR &= ~EMAC_NCFGR_NBC; | |
} | |
/** | |
* Enable/Disable multicast hash | |
*/ | |
void EMAC_MulticastHashEnable(Emac *pEmac, uint8_t bEnaDis) | |
{ | |
if (bEnaDis) pEmac->EMAC_NCFGR |= EMAC_NCFGR_UNI; | |
else pEmac->EMAC_NCFGR &= ~EMAC_NCFGR_UNI; | |
} | |
/** | |
* Enable/Disable big frames (over 1518, up to 1536) | |
*/ | |
void EMAC_BigFrameEnable(Emac *pEmac, uint8_t bEnaDis) | |
{ | |
if (bEnaDis) pEmac->EMAC_NCFGR |= EMAC_NCFGR_BIG; | |
else pEmac->EMAC_NCFGR &= ~EMAC_NCFGR_BIG; | |
} | |
/** | |
* Set MDC clock divider | |
* \return 1 if success. | |
*/ | |
uint8_t EMAC_SetClock(Emac *pEmac, uint32_t dwMck) | |
{ | |
uint8_t bCLK = 0; | |
/* Not supported */ | |
if (dwMck > 160*1000*1000) | |
{ | |
return 0; | |
} | |
else if (dwMck > 80*1000*1000) | |
{ | |
bCLK = 3; | |
} | |
else if (dwMck > 40*1000*1000) | |
{ | |
bCLK = 2; | |
} | |
else if (dwMck > 20*1000*1000) | |
{ | |
bCLK = 1; | |
} | |
pEmac->EMAC_NCFGR &= ~EMAC_NCFGR_CLK_Msk; | |
pEmac->EMAC_NCFGR |= (EMAC_NCFGR_CLK_Msk & ((bCLK) << EMAC_NCFGR_CLK_Pos)); | |
return 1; | |
} | |
/** | |
* Enable/Disable retry test | |
*/ | |
void EMAC_RetryTestEnable(Emac *pEmac, uint8_t bEnaDis) | |
{ | |
if (bEnaDis) pEmac->EMAC_NCFGR |= EMAC_NCFGR_RTY; | |
else pEmac->EMAC_NCFGR &= ~EMAC_NCFGR_RTY; | |
} | |
/** | |
* Enable/Disable pause (when a valid pause frame received). | |
*/ | |
void EMAC_PauseFrameEnable(Emac *pEmac, uint8_t bEnaDis) | |
{ | |
if (bEnaDis) pEmac->EMAC_NCFGR |= EMAC_NCFGR_PAE; | |
else pEmac->EMAC_NCFGR &= ~EMAC_NCFGR_PAE; | |
} | |
/** | |
* Set receive buffer offset to 0 ~ 3. | |
*/ | |
void EMAC_SetRxBufferOffset(Emac *pEmac, uint8_t bOffset) | |
{ | |
pEmac->EMAC_NCFGR &= ~EMAC_NCFGR_RBOF_Msk; | |
pEmac->EMAC_NCFGR |= (EMAC_NCFGR_RBOF_Msk & ((bOffset) << EMAC_NCFGR_RBOF_Pos)); | |
} | |
/** | |
* Enable/Disable receive length field checking | |
*/ | |
void EMAC_RxLenthCheckEnable(Emac *pEmac, uint8_t bEnaDis) | |
{ | |
if (bEnaDis) pEmac->EMAC_NCFGR |= EMAC_NCFGR_RLCE; | |
else pEmac->EMAC_NCFGR &= ~EMAC_NCFGR_RLCE; | |
} | |
/** | |
* Enable/Disable discarding FCS field of received frames. | |
*/ | |
void EMAC_DiscardFCSEnable(Emac *pEmac, uint8_t bEnaDis) | |
{ | |
if (bEnaDis) pEmac->EMAC_NCFGR |= EMAC_NCFGR_DRFCS; | |
else pEmac->EMAC_NCFGR &= ~EMAC_NCFGR_DRFCS; | |
} | |
/** | |
* Enable/Disable frames to be received in half-duplex mode | |
* while transmitting. | |
*/ | |
void EMAC_EFRHD(Emac *pEmac, uint8_t bEnaDis) | |
{ | |
if (bEnaDis) pEmac->EMAC_NCFGR |= EMAC_NCFGR_EFRHD; | |
else pEmac->EMAC_NCFGR &= ~EMAC_NCFGR_EFRHD; | |
} | |
/** | |
* Enable/Disable ignore RX FCS | |
*/ | |
void EMAC_IRXFCS(Emac *pEmac, uint8_t bEnaDis) | |
{ | |
if (bEnaDis) pEmac->EMAC_NCFGR |= EMAC_NCFGR_IRXFCS; | |
else pEmac->EMAC_NCFGR &= ~EMAC_NCFGR_IRXFCS; | |
} | |
/** | |
* Return Network Status | |
*/ | |
uint32_t EMAC_GetStatus(Emac *pEmac) | |
{ | |
return pEmac->EMAC_NSR; | |
} | |
/** | |
* Return mdio_in pin status | |
*/ | |
uint8_t EMAC_GetMDIO(Emac *pEmac) | |
{ | |
return ((pEmac->EMAC_NSR & EMAC_NSR_MDIO) > 0); | |
} | |
/** | |
* Return 1 if PHY is idle | |
*/ | |
uint8_t EMAC_IsIdle(Emac *pEmac) | |
{ | |
return ((pEmac->EMAC_NSR & EMAC_NSR_IDLE) > 0); | |
} | |
/** | |
* Return transmit status | |
*/ | |
uint32_t EMAC_GetTxStatus(Emac *pEmac) | |
{ | |
return pEmac->EMAC_TSR; | |
} | |
/** | |
* Clear transmit status | |
*/ | |
void EMAC_ClearTxStatus(Emac *pEmac, uint32_t dwStatus) | |
{ | |
pEmac->EMAC_TSR = dwStatus; | |
} | |
/** | |
* Return receive status | |
*/ | |
uint32_t EMAC_GetRxStatus(Emac *pEmac) | |
{ | |
return pEmac->EMAC_RSR; | |
} | |
/** | |
* Clear receive status | |
*/ | |
void EMAC_ClearRxStatus(Emac *pEmac, uint32_t dwStatus) | |
{ | |
pEmac->EMAC_RSR = dwStatus; | |
} | |
/** | |
* Set Rx Queue | |
*/ | |
void EMAC_SetRxQueue(Emac *pEmac, uint32_t dwAddr) | |
{ | |
pEmac->EMAC_RBQP = EMAC_RBQP_ADDR_Msk & dwAddr; | |
} | |
/** | |
* Get Rx Queue Address | |
*/ | |
uint32_t EMAC_GetRxQueue(Emac *pEmac) | |
{ | |
return pEmac->EMAC_RBQP; | |
} | |
/** | |
* Set Tx Queue | |
*/ | |
void EMAC_SetTxQueue(Emac *pEmac, uint32_t dwAddr) | |
{ | |
pEmac->EMAC_TBQP = EMAC_TBQP_ADDR_Msk & dwAddr; | |
} | |
/** | |
* Get Tx Queue | |
*/ | |
uint32_t EMAC_GetTxQueue(Emac *pEmac) | |
{ | |
return pEmac->EMAC_TBQP; | |
} | |
/** | |
* Enable interrupt(s). | |
*/ | |
void EMAC_EnableIt(Emac *pEmac, uint32_t dwSources) | |
{ | |
pEmac->EMAC_IER = dwSources; | |
} | |
/** | |
* Disable interrupt(s). | |
*/ | |
void EMAC_DisableIt(Emac *pEmac, uint32_t dwSources) | |
{ | |
pEmac->EMAC_IDR = dwSources; | |
} | |
/** | |
* Return interrupt status. | |
*/ | |
uint32_t EMAC_GetItStatus(Emac *pEmac) | |
{ | |
return pEmac->EMAC_ISR; | |
} | |
/** | |
* Return interrupt mask. | |
*/ | |
uint32_t EMAC_GetItMask(Emac *pEmac) | |
{ | |
return pEmac->EMAC_IMR; | |
} | |
/** | |
* Execute PHY maintanance command | |
*/ | |
void EMAC_PHYMaintain(Emac *pEmac, | |
uint8_t bPhyAddr, | |
uint8_t bRegAddr, | |
uint8_t bRW, | |
uint16_t wData) | |
{ | |
/* Wait until bus idle */ | |
while((pEmac->EMAC_NSR & EMAC_NSR_IDLE) == 0); | |
/* Write maintain register */ | |
pEmac->EMAC_MAN = EMAC_MAN_CODE(0x02) | EMAC_MAN_SOF(0x1) | |
| EMAC_MAN_PHYA(bPhyAddr) | |
| EMAC_MAN_REGA(bRegAddr) | |
| EMAC_MAN_RW((bRW ? 0x2 : 0x1)) | |
| EMAC_MAN_DATA(wData) | |
; | |
} | |
/** | |
* Return PHY maintainance data returned | |
*/ | |
uint16_t EMAC_PHYData(Emac *pEmac) | |
{ | |
/* Wait until bus idle */ | |
while((pEmac->EMAC_NSR & EMAC_NSR_IDLE) == 0); | |
/* Return data */ | |
return (uint16_t)(pEmac->EMAC_MAN & EMAC_MAN_DATA_Msk); | |
} | |
/** | |
* Set pause time. | |
*/ | |
void EMAC_SetPauseTime(Emac *pEmac, uint16_t wPTime) | |
{ | |
pEmac->EMAC_PTR = wPTime; | |
} | |
/** | |
* Set Hash | |
*/ | |
void EMAC_SetHash(Emac *pEmac, uint32_t dwHashTop, uint32_t dwHashBottom) | |
{ | |
pEmac->EMAC_HRB = dwHashBottom; | |
pEmac->EMAC_HRT = dwHashTop; | |
} | |
/** | |
* Set Hash | |
*/ | |
void EMAC_SetHash64(Emac *pEmac, uint64_t ddwHash) | |
{ | |
pEmac->EMAC_HRB = (uint32_t)ddwHash; | |
pEmac->EMAC_HRT = (uint32_t)(ddwHash >> 32); | |
} | |
/** | |
* Set MAC Address | |
*/ | |
void EMAC_SetAddress(Emac *pEmac, uint8_t bIndex, uint8_t *pMacAddr) | |
{ | |
pEmac->EMAC_SA[bIndex].EMAC_SAxB = (pMacAddr[3] << 24) | |
| (pMacAddr[2] << 16) | |
| (pMacAddr[1] << 8) | |
| (pMacAddr[0] ) | |
; | |
pEmac->EMAC_SA[bIndex].EMAC_SAxT = (pMacAddr[5] << 8) | |
| (pMacAddr[4] ) | |
; | |
} | |
/** | |
* Set MAC Address via 2 DW | |
*/ | |
void EMAC_SetAddress32(Emac *pEmac, uint8_t bIndex, uint32_t dwMacT, uint32_t dwMacB) | |
{ | |
pEmac->EMAC_SA[bIndex].EMAC_SAxB = dwMacB; | |
pEmac->EMAC_SA[bIndex].EMAC_SAxT = dwMacT; | |
} | |
/** | |
* Set MAC Address via int64 | |
*/ | |
void EMAC_SetAddress64(Emac *pEmac, uint8_t bIndex, uint64_t ddwMac) | |
{ | |
pEmac->EMAC_SA[bIndex].EMAC_SAxB = (uint32_t)ddwMac; | |
pEmac->EMAC_SA[bIndex].EMAC_SAxT = (uint32_t)(ddwMac >> 32); | |
} | |
/** | |
* Set Type ID | |
*/ | |
void EMAC_SetTypeID(Emac *pEmac, uint16_t wTID) | |
{ | |
pEmac->EMAC_TID = EMAC_TID_TID(wTID); | |
} | |
/** | |
* Get Type ID | |
*/ | |
uint16_t EMAC_GetTypeID(Emac *pEmac) | |
{ | |
return (pEmac->EMAC_TID & EMAC_TID_TID_Msk); | |
} | |
/** | |
* Enable/Disable RMII | |
*/ | |
void EMAC_RMIIEnable(Emac *pEmac, uint8_t bEnaDis) | |
{ | |
if (bEnaDis) pEmac->EMAC_USRIO |= EMAC_USRIO_RMII; | |
else pEmac->EMAC_USRIO &= ~EMAC_USRIO_RMII; | |
} | |
/** | |
* Enable/Disable transceiver input clock | |
*/ | |
void EMAC_TransceiverClockEnable(Emac *pEmac, uint8_t bEnaDis) | |
{ | |
if (bEnaDis) pEmac->EMAC_USRIO |= EMAC_USRIO_CLKEN; | |
else pEmac->EMAC_USRIO &= ~EMAC_USRIO_CLKEN; | |
} | |
/**@}*/ | |