in hw/mcu/nxp/src/ext/nxp-kinetis-sdk/drivers/fsl_enet.c [481:748]
static void ENET_SetMacController(ENET_Type *base,
enet_handle_t *handle,
const enet_config_t *config,
const enet_buffer_config_t *bufferConfig,
uint8_t *macAddr,
uint32_t srcClock_Hz)
{
#if defined(FSL_FEATURE_ENET_HAS_AVB) && FSL_FEATURE_ENET_HAS_AVB
if (FSL_FEATURE_ENET_INSTANCE_HAS_AVBn(base) == 1)
{
/* Check the MII mode/speed/duplex setting. */
if (config->miiSpeed == kENET_MiiSpeed1000M)
{
/* Only RGMII mode has the 1000M bit/s. The 1000M only support full duplex. */
assert(config->miiMode == kENET_RgmiiMode);
assert(config->miiDuplex == kENET_MiiFullDuplex);
}
}
#endif /* FSL_FEATURE_ENET_HAS_AVB */
uint32_t rcr = 0;
uint32_t tcr = 0;
uint32_t ecr = base->ECR;
uint32_t macSpecialConfig = config->macSpecialConfig;
uint32_t maxFrameLen = config->rxMaxFrameLen;
uint32_t configVal = 0;
/* Maximum frame length check. */
if ((0U != (macSpecialConfig & (uint32_t)kENET_ControlVLANTagEnable)) && (maxFrameLen <= ENET_FRAME_MAX_FRAMELEN))
{
maxFrameLen = (ENET_FRAME_MAX_FRAMELEN + ENET_FRAME_VLAN_TAGLEN);
#if defined(FSL_FEATURE_ENET_HAS_AVB) && FSL_FEATURE_ENET_HAS_AVB
if (FSL_FEATURE_ENET_INSTANCE_HAS_AVBn(base) == 1)
{
if (0U != (macSpecialConfig & (uint32_t)kENET_ControlSVLANEnable))
{
/* Double vlan tag (SVLAN) supported. */
maxFrameLen += ENET_FRAME_VLAN_TAGLEN;
}
ecr |= (uint32_t)(((macSpecialConfig & (uint32_t)kENET_ControlSVLANEnable) != 0U) ?
(ENET_ECR_SVLANEN_MASK | ENET_ECR_SVLANDBL_MASK) :
0U) |
(uint32_t)(((macSpecialConfig & (uint32_t)kENET_ControlVLANUseSecondTag) != 0U) ?
ENET_ECR_VLANUSE2ND_MASK :
0U);
}
#endif /* FSL_FEATURE_ENET_HAS_AVB */
}
/* Configures MAC receive controller with user configure structure. */
rcr = ((0U != (macSpecialConfig & (uint32_t)kENET_ControlRxPayloadCheckEnable)) ? ENET_RCR_NLC_MASK : 0U) |
((0U != (macSpecialConfig & (uint32_t)kENET_ControlFlowControlEnable)) ? ENET_RCR_CFEN_MASK : 0U) |
((0U != (macSpecialConfig & (uint32_t)kENET_ControlFlowControlEnable)) ? ENET_RCR_FCE_MASK : 0U) |
((0U != (macSpecialConfig & (uint32_t)kENET_ControlRxPadRemoveEnable)) ? ENET_RCR_PADEN_MASK : 0U) |
((0U != (macSpecialConfig & (uint32_t)kENET_ControlRxBroadCastRejectEnable)) ? ENET_RCR_BC_REJ_MASK : 0U) |
((0U != (macSpecialConfig & (uint32_t)kENET_ControlPromiscuousEnable)) ? ENET_RCR_PROM_MASK : 0U) |
ENET_RCR_MAX_FL(maxFrameLen) | ENET_RCR_CRCFWD_MASK;
/* Set the RGMII or RMII, MII mode and control register. */
#if defined(FSL_FEATURE_ENET_HAS_AVB) && FSL_FEATURE_ENET_HAS_AVB
if (FSL_FEATURE_ENET_INSTANCE_HAS_AVBn(base) == 1)
{
if (config->miiMode == kENET_RgmiiMode)
{
rcr |= ENET_RCR_RGMII_EN_MASK;
}
else
{
rcr &= ~ENET_RCR_RGMII_EN_MASK;
}
if (config->miiSpeed == kENET_MiiSpeed1000M)
{
ecr |= ENET_ECR_SPEED_MASK;
}
else
{
ecr &= ~ENET_ECR_SPEED_MASK;
}
}
#endif /* FSL_FEATURE_ENET_HAS_AVB */
rcr |= ENET_RCR_MII_MODE_MASK;
if (config->miiMode == kENET_RmiiMode)
{
rcr |= ENET_RCR_RMII_MODE_MASK;
}
/* Speed. */
if (config->miiSpeed == kENET_MiiSpeed10M)
{
rcr |= ENET_RCR_RMII_10T_MASK;
}
/* Receive setting for half duplex. */
if (config->miiDuplex == kENET_MiiHalfDuplex)
{
rcr |= ENET_RCR_DRT_MASK;
}
/* Sets internal loop only for MII mode. */
if ((0U != (config->macSpecialConfig & (uint32_t)kENET_ControlMIILoopEnable)) &&
(config->miiMode != kENET_RmiiMode))
{
rcr |= ENET_RCR_LOOP_MASK;
rcr &= ~ENET_RCR_DRT_MASK;
}
base->RCR = rcr;
/* Configures MAC transmit controller: duplex mode, mac address insertion. */
tcr = base->TCR & ~(ENET_TCR_FDEN_MASK | ENET_TCR_ADDINS_MASK);
tcr |= ((kENET_MiiHalfDuplex != config->miiDuplex) ? (uint32_t)ENET_TCR_FDEN_MASK : 0U) |
((0U != (macSpecialConfig & (uint32_t)kENET_ControlMacAddrInsert)) ? (uint32_t)ENET_TCR_ADDINS_MASK : 0U);
base->TCR = tcr;
/* Configures receive and transmit accelerator. */
base->TACC = config->txAccelerConfig;
base->RACC = config->rxAccelerConfig;
/* Sets the pause duration and FIFO threshold for the flow control enabled case. */
if (0U != (macSpecialConfig & (uint32_t)kENET_ControlFlowControlEnable))
{
uint32_t reemReg;
base->OPD = config->pauseDuration;
reemReg = ENET_RSEM_RX_SECTION_EMPTY(config->rxFifoEmptyThreshold);
#if defined(FSL_FEATURE_ENET_HAS_RECEIVE_STATUS_THRESHOLD) && FSL_FEATURE_ENET_HAS_RECEIVE_STATUS_THRESHOLD
reemReg |= ENET_RSEM_STAT_SECTION_EMPTY(config->rxFifoStatEmptyThreshold);
#endif /* FSL_FEATURE_ENET_HAS_RECEIVE_STATUS_THRESHOLD */
base->RSEM = reemReg;
}
/* FIFO threshold setting for store and forward enable/disable case. */
if (0U != (macSpecialConfig & (uint32_t)kENET_ControlStoreAndFwdDisable))
{
/* Transmit fifo watermark settings. */
configVal = ((uint32_t)config->txFifoWatermark) & ENET_TFWR_TFWR_MASK;
base->TFWR = configVal;
/* Receive fifo full threshold settings. */
configVal = ((uint32_t)config->rxFifoFullThreshold) & ENET_RSFL_RX_SECTION_FULL_MASK;
base->RSFL = configVal;
}
else
{
/* Transmit fifo watermark settings. */
base->TFWR = ENET_TFWR_STRFWD_MASK;
base->RSFL = 0;
}
/* Enable store and forward when accelerator is enabled */
if (0U !=
(config->txAccelerConfig & ((uint32_t)kENET_TxAccelIpCheckEnabled | (uint32_t)kENET_TxAccelProtoCheckEnabled)))
{
base->TFWR = ENET_TFWR_STRFWD_MASK;
}
if (0U != ((config->rxAccelerConfig &
((uint32_t)kENET_RxAccelIpCheckEnabled | (uint32_t)kENET_RxAccelProtoCheckEnabled))))
{
base->RSFL = 0;
}
/* Initializes the ring 0. */
#if defined(FSL_FEATURE_MEMORY_HAS_ADDRESS_OFFSET) && FSL_FEATURE_MEMORY_HAS_ADDRESS_OFFSET
base->TDSR = MEMORY_ConvertMemoryMapAddress((uint32_t)bufferConfig->txBdStartAddrAlign, kMEMORY_Local2DMA);
base->RDSR = MEMORY_ConvertMemoryMapAddress((uint32_t)bufferConfig->rxBdStartAddrAlign, kMEMORY_Local2DMA);
#else
base->TDSR = (uint32_t)bufferConfig->txBdStartAddrAlign;
base->RDSR = (uint32_t)bufferConfig->rxBdStartAddrAlign;
#endif
base->MRBR = (uint32_t)bufferConfig->rxBuffSizeAlign;
#if defined(FSL_FEATURE_ENET_HAS_AVB) && FSL_FEATURE_ENET_HAS_AVB
if (FSL_FEATURE_ENET_INSTANCE_HAS_AVBn(base) == 1)
{
const enet_buffer_config_t *buffCfg = bufferConfig;
if (config->ringNum > 1U)
{
/* Initializes the ring 1. */
buffCfg++;
#if defined(FSL_FEATURE_MEMORY_HAS_ADDRESS_OFFSET) && FSL_FEATURE_MEMORY_HAS_ADDRESS_OFFSET
base->TDSR1 = MEMORY_ConvertMemoryMapAddress((uint32_t)buffCfg->txBdStartAddrAlign, kMEMORY_Local2DMA);
base->RDSR1 = MEMORY_ConvertMemoryMapAddress((uint32_t)buffCfg->rxBdStartAddrAlign, kMEMORY_Local2DMA);
#else
base->TDSR1 = (uint32_t)buffCfg->txBdStartAddrAlign;
base->RDSR1 = (uint32_t)buffCfg->rxBdStartAddrAlign;
#endif
base->MRBR1 = (uint32_t)buffCfg->rxBuffSizeAlign;
/* Enable the DMAC for ring 1 and with no rx classification set. */
base->DMACFG[0] = ENET_DMACFG_DMA_CLASS_EN_MASK;
}
if (config->ringNum > 2U)
{
/* Initializes the ring 2. */
buffCfg++;
#if defined(FSL_FEATURE_MEMORY_HAS_ADDRESS_OFFSET) && FSL_FEATURE_MEMORY_HAS_ADDRESS_OFFSET
base->TDSR2 = MEMORY_ConvertMemoryMapAddress((uint32_t)buffCfg->txBdStartAddrAlign, kMEMORY_Local2DMA);
base->RDSR2 = MEMORY_ConvertMemoryMapAddress((uint32_t)buffCfg->rxBdStartAddrAlign, kMEMORY_Local2DMA);
#else
base->TDSR2 = (uint32_t)buffCfg->txBdStartAddrAlign;
base->RDSR2 = (uint32_t)buffCfg->rxBdStartAddrAlign;
#endif
base->MRBR2 = (uint32_t)buffCfg->rxBuffSizeAlign;
/* Enable the DMAC for ring 2 and with no rx classification set. */
base->DMACFG[1] = ENET_DMACFG_DMA_CLASS_EN_MASK;
}
/* Defaulting the class/ring 1 and 2 are not enabled and the receive classification is disabled
* so we set the default transmit scheme with the round-robin mode. Beacuse the legacy bd mode
* only supports the round-robin mode. If the avb feature is required, just call the setup avb
* feature API. */
base->QOS |= ENET_QOS_TX_SCHEME(1);
}
#endif /* FSL_FEATURE_ENET_HAS_AVB */
/* Configures the Mac address. */
ENET_SetMacAddr(base, macAddr);
/* Initialize the SMI if uninitialized. */
if (!ENET_GetSMI(base))
{
ENET_SetSMI(base, srcClock_Hz,
((0U != (config->macSpecialConfig & (uint32_t)kENET_ControlSMIPreambleDisable)) ? true : false));
}
/* Enables Ethernet interrupt, enables the interrupt coalsecing if it is required. */
#if defined(FSL_FEATURE_ENET_HAS_INTERRUPT_COALESCE) && FSL_FEATURE_ENET_HAS_INTERRUPT_COALESCE
if (NULL != config->intCoalesceCfg)
{
uint32_t intMask = (ENET_EIMR_TXB_MASK | ENET_EIMR_RXB_MASK);
#if FSL_FEATURE_ENET_QUEUE > 1
uint8_t queue = 0;
if (FSL_FEATURE_ENET_INSTANCE_QUEUEn(base) > 1)
{
intMask |= ENET_EIMR_TXB2_MASK | ENET_EIMR_RXB2_MASK | ENET_EIMR_TXB1_MASK | ENET_EIMR_RXB1_MASK;
}
#endif /* FSL_FEATURE_ENET_QUEUE > 1 */
/* Clear all buffer interrupts. */
base->EIMR &= ~intMask;
/* Set the interrupt coalescence. */
#if FSL_FEATURE_ENET_QUEUE > 1
for (queue = 0; queue < (uint8_t)FSL_FEATURE_ENET_INSTANCE_QUEUEn(base); queue++)
{
base->TXIC[queue] = ENET_TXIC_ICFT(config->intCoalesceCfg->txCoalesceFrameCount[queue]) |
config->intCoalesceCfg->txCoalesceTimeCount[queue] | ENET_TXIC_ICCS_MASK |
ENET_TXIC_ICEN_MASK;
base->RXIC[queue] = ENET_RXIC_ICFT(config->intCoalesceCfg->rxCoalesceFrameCount[queue]) |
config->intCoalesceCfg->rxCoalesceTimeCount[queue] | ENET_RXIC_ICCS_MASK |
ENET_RXIC_ICEN_MASK;
}
#else
base->TXIC = ENET_TXIC_ICFT(config->intCoalesceCfg->txCoalesceFrameCount[0]) |
config->intCoalesceCfg->txCoalesceTimeCount[0] | ENET_TXIC_ICCS_MASK | ENET_TXIC_ICEN_MASK;
base->RXIC = ENET_RXIC_ICFT(config->intCoalesceCfg->rxCoalesceFrameCount[0]) |
config->intCoalesceCfg->rxCoalesceTimeCount[0] | ENET_RXIC_ICCS_MASK | ENET_RXIC_ICEN_MASK;
#endif /* FSL_FEATURE_ENET_QUEUE > 1 */
}
#endif /* FSL_FEATURE_ENET_HAS_INTERRUPT_COALESCE */
ENET_EnableInterrupts(base, config->interrupt);
#ifdef ENET_ENHANCEDBUFFERDESCRIPTOR_MODE
/* Sets the 1588 enhanced feature. */
ecr |= ENET_ECR_EN1588_MASK;
#endif /* ENET_ENHANCEDBUFFERDESCRIPTOR_MODE */
/* Enables Ethernet module after all configuration except the buffer descriptor active. */
ecr |= ENET_ECR_ETHEREN_MASK | ENET_ECR_DBSWP_MASK;
base->ECR = ecr;
}