⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 fec.c

📁 motorola 针对coldfire 5275 评估板的Dbug bootloader源程序
💻 C
📖 第 1 页 / 共 3 页
字号:
/*
 * File:    fec.c
 * Purpose: Driver for the Fast Ethernet Controller (FEC)
 *
 * Notes:
 */
#include "src/include/dbug.h"
#include "src/uif/net/net.h"
#include "src/cpu/coldfire/mcf548x/fec.h"
#include "src/cpu/coldfire/mcf548x/fecbd.h"
#include "src/cpu/coldfire/mcf548x/mcdapi/MCD_dma.h"
#include "src/cpu/coldfire/mcf548x/dma_utils.h"

#ifdef DBUG_NETWORK

/********************************************************************/

FEC_EVENT_LOG fec_log[2];

/********************************************************************/
/*
 * Write a value to a PHY's MII register.
 *
 * Parameters:
 *  ch          FEC channel
 *  phy_addr    Address of the PHY.
 *  reg_addr    Address of the register in the PHY.
 *  data        Data to be written to the PHY register.
 *
 * Return Values:
 *  1 on failure
 *  0 on success.
 *
 * Please refer to your PHY manual for registers and their meanings.
 * mii_write() polls for the FEC's MII interrupt event (which should
 * be masked from the interrupt handler) and clears it. If after a
 * suitable amount of time the event isn't triggered, a value of 0
 * is returned.
 */
int
fec_mii_write(uint8 ch, uint8 phy_addr, uint8 reg_addr, uint16 data)
{
    int timeout;
    uint32 eimr;

    ASSERT(ch == 0 || ch == 1);

    /*
     * Clear the MII interrupt bit
     */
    MCF_FEC_EIR(ch) = MCF_FEC_EIR_MII;

    /*
     * Write to the MII Management Frame Register to kick-off
     * the MII write
     */
    MCF_FEC_MMFR(ch) = 0
        | MCF_FEC_MMFR_ST_01
        | MCF_FEC_MMFR_OP_WRITE
        | MCF_FEC_MMFR_PA(phy_addr)
        | MCF_FEC_MMFR_RA(reg_addr)
        | MCF_FEC_MMFR_TA_10
        | MCF_FEC_MMFR_DATA(data);

    /*
     * Mask the MII interrupt
     */
    eimr = MCF_FEC_EIMR(ch);
    MCF_FEC_EIMR(ch) &= ~MCF_FEC_EIMR_MII;

    /*
     * Poll for the MII interrupt (interrupt should be masked)
     */
    for (timeout = 0; timeout < FEC_MII_TIMEOUT; timeout++)
    {
        if (MCF_FEC_EIR(ch) & MCF_FEC_EIR_MII)
            break;
    }
    if(timeout == FEC_MII_TIMEOUT)
        return 1;

    /*
     * Clear the MII interrupt bit
     */
    MCF_FEC_EIR(ch) = MCF_FEC_EIR_MII;

    /*
     * Restore the EIMR
     */
    MCF_FEC_EIMR(ch) = eimr;

    return 0;
}
/********************************************************************/
/*
 * Read a value from a PHY's MII register.
 *
 * Parameters:
 *  ch          FEC channel
 *  phy_addr    Address of the PHY.
 *  reg_addr    Address of the register in the PHY.
 *  data        Pointer to storage for the Data to be read
 *              from the PHY register (passed by reference)
 *
 * Return Values:
 *  1 on failure
 *  0 on success.
 *
 * Please refer to your PHY manual for registers and their meanings.
 * mii_read() polls for the FEC's MII interrupt event (which should
 * be masked from the interrupt handler) and clears it. If after a
 * suitable amount of time the event isn't triggered, a value of 0
 * is returned.
 */
int
fec_mii_read(uint8 ch, uint8 phy_addr, uint8 reg_addr, uint16 *data)
{
    int timeout;

    ASSERT(ch == 0 || ch == 1);

    /*
     * Clear the MII interrupt bit
     */
    MCF_FEC_EIR(ch) = MCF_FEC_EIR_MII;

    /*
     * Write to the MII Management Frame Register to kick-off
     * the MII read
     */
    MCF_FEC_MMFR(ch) = 0
        | MCF_FEC_MMFR_ST_01
        | MCF_FEC_MMFR_OP_READ
        | MCF_FEC_MMFR_PA(phy_addr)
        | MCF_FEC_MMFR_RA(reg_addr)
        | MCF_FEC_MMFR_TA_10;

    /*
     * Poll for the MII interrupt (interrupt should be masked)
     */
    for (timeout = 0; timeout < FEC_MII_TIMEOUT; timeout++)
    {
        if (MCF_FEC_EIR(ch) & MCF_FEC_EIR_MII)
            break;
    }

    if(timeout == FEC_MII_TIMEOUT)
        return 1;

    /*
     * Clear the MII interrupt bit
     */
    MCF_FEC_EIR(ch) = MCF_FEC_EIR_MII;

    *data = (uint16)(MCF_FEC_MMFR(ch) & 0x0000FFFF);

    return 0;
}
/********************************************************************/
/*
 * Initialize the MII interface controller
 *
 * Parameters:
 *  ch      FEC channel
 *  sys_clk System Clock Frequency (in MHz)
 */
void
fec_mii_init(uint8 ch, uint32 sys_clk)
{
    ASSERT(ch == 0 || ch == 1);

    /*
     * Initialize the MII clock (EMDC) frequency
     *
     * Desired MII clock is 2.5MHz
     * MII Speed Setting = System_Clock / (2.5MHz * 2)
     * (plus 1 to make sure we round up)
     */
    MCF_FEC_MSCR(ch) = MCF_FEC_MSCR_MII_SPEED((sys_clk/5)+1);
}
/********************************************************************/
/* Initialize the MIB counters
 *
 * Parameters:
 *  ch      FEC channel
 */
void
fec_mib_init(uint8 ch)
{
    ASSERT(ch == 0 || ch == 1);
//To do
}
/********************************************************************/
/* Display the MIB counters
 *
 * Parameters:
 *  ch      FEC channel
 */
void
fec_mib_dump(uint8 ch)
{
    ASSERT(ch == 0 || ch == 1);
//To do
}
/********************************************************************/
/* Initialize the FEC log
 *
 * Parameters:
 *  ch      FEC channel
 */
void
fec_log_init(uint8 ch)
{
    ASSERT(ch == 0 || ch == 1);
    memset(&fec_log[ch],0,sizeof(FEC_EVENT_LOG));
}
/********************************************************************/
/* Display the FEC log
 *
 * Parameters:
 *  ch      FEC channel
 */
void
fec_log_dump(uint8 ch)
{
    ASSERT(ch == 0 || ch == 1);
    printf("\n   FEC%d Log\n---------------\n",ch);
    printf("Total: %4d\n",fec_log[ch].total);
    printf("hberr: %4d\n",fec_log[ch].hberr);
    printf("babr:  %4d\n",fec_log[ch].babr);
    printf("babt:  %4d\n",fec_log[ch].babt);
    printf("gra:   %4d\n",fec_log[ch].gra);
    printf("txf:   %4d\n",fec_log[ch].txf);
    printf("mii:   %4d\n",fec_log[ch].mii);
    printf("lc:    %4d\n",fec_log[ch].lc);
    printf("rl:    %4d\n",fec_log[ch].rl);
    printf("xfun:  %4d\n",fec_log[ch].xfun);
    printf("xferr: %4d\n",fec_log[ch].xferr);
    printf("rferr: %4d\n",fec_log[ch].rferr);
    printf("dtxf:  %4d\n",fec_log[ch].dtxf);
    printf("drxf:  %4d\n",fec_log[ch].drxf);
    printf("\nRFSW:\n");
    printf("inv:   %4d\n",fec_log[ch].rfsw_inv);
    printf("m:     %4d\n",fec_log[ch].rfsw_m);
    printf("bc:    %4d\n",fec_log[ch].rfsw_bc);
    printf("mc:    %4d\n",fec_log[ch].rfsw_mc);
    printf("lg:    %4d\n",fec_log[ch].rfsw_lg);
    printf("no:    %4d\n",fec_log[ch].rfsw_no);
    printf("cr:    %4d\n",fec_log[ch].rfsw_cr);
    printf("ov:    %4d\n",fec_log[ch].rfsw_ov);
    printf("tr:    %4d\n",fec_log[ch].rfsw_tr);
    printf("---------------\n\n");
}
/********************************************************************/
/*
 * Display some of the registers for debugging
 *
 * Parameters:
 *  ch      FEC channel
 */
void
fec_debug_dump(uint8 ch)
{
    printf("\n------------- FEC%d -------------\n",ch);
    printf("EIR      %08x        \n",MCF_FEC_EIR(ch));
    printf("EIMR     %08x        \n",MCF_FEC_EIMR(ch));
    printf("ECR      %08x        \n",MCF_FEC_ECR(ch));
    printf("RCR      %08x        \n",MCF_FEC_RCR(ch));
    printf("R_HASH   %08x        \n",MCF_FEC_R_HASH(ch));
    printf("TCR      %08x        \n",MCF_FEC_TCR(ch));
    printf("FECTFWR  %08x        \n",MCF_FEC_FECTFWR(ch));
    printf("FECRFSR  %08x        \n",MCF_FEC_FECRFSR(ch));
    printf("FECRFCR  %08x        \n",MCF_FEC_FECRFCR(ch));
    printf("FECRLRFP %08x        \n",MCF_FEC_FECRLRFP(ch));
    printf("FECRLWFP %08x        \n",MCF_FEC_FECRLWFP(ch));
    printf("FECRFAR  %08x        \n",MCF_FEC_FECRFAR(ch));
    printf("FECRFRP  %08x        \n",MCF_FEC_FECRFRP(ch));
    printf("FECRFWP  %08x        \n",MCF_FEC_FECRFWP(ch));
    printf("FECTFSR  %08x        \n",MCF_FEC_FECTFSR(ch));
    printf("FECTFCR  %08x        \n",MCF_FEC_FECTFCR(ch));
    printf("FECTLRFP %08x        \n",MCF_FEC_FECTLRFP(ch));
    printf("FECTLWFP %08x        \n",MCF_FEC_FECTLWFP(ch));
    printf("FECTFAR  %08x        \n",MCF_FEC_FECTFAR(ch));
    printf("FECTFRP  %08x        \n",MCF_FEC_FECTFRP(ch));
    printf("FECTFWP  %08x        \n",MCF_FEC_FECTFWP(ch));
    printf("FRST     %08x        \n",MCF_FEC_FRST(ch));
    printf("--------------------------------\n\n");
}
/********************************************************************/
/*
 * Set the duplex on the selected FEC controller
 *
 * Parameters:
 *  ch      FEC channel
 *  duplex  FEC_MII_FULL_DUPLEX or FEC_MII_HALF_DUPLEX
 */
void
fec_duplex (uint8 ch, uint8 duplex)
{
    ASSERT(ch == 0 || ch == 1);

    switch (duplex)
    {
        case FEC_MII_HALF_DUPLEX:
            MCF_FEC_RCR(ch) |= MCF_FEC_RCR_DRT;
            MCF_FEC_TCR(ch) &= (uint32)~MCF_FEC_TCR_FDEN;
            break;
        case FEC_MII_FULL_DUPLEX:
        default:
            MCF_FEC_RCR(ch) &= (uint32)~MCF_FEC_RCR_DRT;
            MCF_FEC_TCR(ch) |= MCF_FEC_TCR_FDEN;
            break;
    }
}
/********************************************************************/
/*
 * Generate the hash table settings for the given address
 *
 * Parameters:
 *  addr    48-bit (6 byte) Address to generate the hash for
 *
 * Return Value:
 *  The 6 most significant bits of the 32-bit CRC result
 */
uint8
fec_hash_address(const uint8 *addr)
{
    uint32 crc;
    uint8 byte;
    int i, j;

    crc = 0xFFFFFFFF;
    for(i=0; i<6; ++i)
    {
        byte = addr[i];
        for(j=0; j<8; ++j)
        {
            if((byte & 0x01)^(crc & 0x01))
            {
                crc >>= 1;
                crc = crc ^ 0xEDB88320;
            }
            else
                crc >>= 1;
            byte >>= 1;
        }
    }
    return (uint8)(crc >> 26);
}
/********************************************************************/
/*
 * Set the Physical (Hardware) Address and the Individual Address
 * Hash in the selected FEC
 *
 * Parameters:
 *  ch  FEC channel
 *  pa  Physical (Hardware) Address for the selected FEC
 */
void
fec_set_address (uint8 ch, const uint8 *pa)
{
    uint8 crc;

    ASSERT(ch == 0 || ch == 1);

    /*
     * Set the Physical Address
     */
    MCF_FEC_PALR(ch) = (uint32)((pa[0]<<24) | (pa[1]<<16) | (pa[2]<<8) | pa[3]);
    MCF_FEC_PAUR(ch) = (uint32)((pa[4]<<24) | (pa[5]<<16));

    /*
     * Calculate and set the hash for given Physical Address
     * in the  Individual Address Hash registers
     */
    crc = fec_hash_address(pa);
    if(crc >= 32)
        MCF_FEC_IAUR(ch) |= (uint32)(1 << (crc - 32));
    else
        MCF_FEC_IALR(ch) |= (uint32)(1 << crc);
}
/********************************************************************/
/*
 * Reset the selected FEC controller
 *
 * Parameters:
 *  ch      FEC channel
 */
void
fec_reset (uint8 ch)
{
    int i;

    ASSERT(ch == 0 || ch == 1);

    /* Clear any events in the FIFO status registers */
    MCF_FEC_FECRFSR(ch) = (0
        | MCF_FEC_FECRFSR_OF
        | MCF_FEC_FECRFSR_UF
        | MCF_FEC_FECRFSR_RXW
        | MCF_FEC_FECRFSR_FAE
        | MCF_FEC_FECRFSR_IP);
    MCF_FEC_FECTFSR(ch) = (0
        | MCF_FEC_FECRFSR_OF
        | MCF_FEC_FECRFSR_UF
        | MCF_FEC_FECRFSR_RXW
        | MCF_FEC_FECRFSR_FAE
        | MCF_FEC_FECRFSR_IP);

    /* Reset the FIFOs */
    MCF_FEC_FRST(ch) |= MCF_FEC_FRST_SW_RST;
    MCF_FEC_FRST(ch) &= ~MCF_FEC_FRST_SW_RST;

    /* Set the Reset bit and clear the Enable bit */
    MCF_FEC_ECR(ch) = MCF_FEC_ECR_RESET;

    /* Wait at least 8 clock cycles */
    for (i=0; i<10; ++i)
        nop();
}
/********************************************************************/
/*
 * Initialize the selected FEC
 *
 * Parameters:
 *  ch      FEC channel
 *  mode    External interface mode (MII, 7-wire, or internal loopback)
 *  pa      Physical (Hardware) Address for the selected FEC
 */
void
fec_init (uint8 ch, uint8 mode, const uint8 *pa)
{
    ASSERT(ch == 0 || ch == 1);

    /*
     * Enable all the external interface signals
     */
    if (mode == FEC_MODE_7WIRE)
    {
        if (ch == 1)
            MCF_GPIO_PAR_FECI2CIRQ |= MCF_GPIO_PAR_FECI2CIRQ_PAR_E17;
        else
            MCF_GPIO_PAR_FECI2CIRQ |= MCF_GPIO_PAR_FECI2CIRQ_PAR_E07;
    }
    else if (mode == FEC_MODE_MII)
    {
        if (ch == 1)
            MCF_GPIO_PAR_FECI2CIRQ |= 0
                | MCF_GPIO_PAR_FECI2CIRQ_PAR_E1MDC_EMDC
                | MCF_GPIO_PAR_FECI2CIRQ_PAR_E1MDIO_EMDIO
                | MCF_GPIO_PAR_FECI2CIRQ_PAR_E1MII
                | MCF_GPIO_PAR_FECI2CIRQ_PAR_E17;
        else
            MCF_GPIO_PAR_FECI2CIRQ |= 0
                | MCF_GPIO_PAR_FECI2CIRQ_PAR_E0MDC
                | MCF_GPIO_PAR_FECI2CIRQ_PAR_E0MDIO
                | MCF_GPIO_PAR_FECI2CIRQ_PAR_E0MII
                | MCF_GPIO_PAR_FECI2CIRQ_PAR_E07;
    }

    /*
     * Clear the Individual and Group Address Hash registers
     */
    MCF_FEC_IALR(ch) = 0;
    MCF_FEC_IAUR(ch) = 0;
    MCF_FEC_GALR(ch) = 0;
    MCF_FEC_GAUR(ch) = 0;

    /*
     * Set the Physical Address for the selected FEC
     */
    fec_set_address(ch, pa);

    /*
     * Mask all FEC interrupts
     */
    MCF_FEC_EIMR(ch) = MCF_FEC_EIMR_MASK_ALL;

    /*

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -