static void ENET_SetMacController()

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;
}