DM9161_AutoNegotiate
Default mainpageat91libcomponentsethernetdm9161DM9161_AutoNegotiate
Description Source Call Graph
Start Line: 319
unsigned char DM9161_AutoNegotiate(Dm9161 *pDm)
{
    unsigned int retryMax;
    unsigned int value;
    unsigned int phyAnar;
    unsigned int phyAnalpar;
    unsigned int retryCount= 0;
    unsigned char phyAddress;
    unsigned char rc = 1;

    ASSERT(pDm, "-F- DM9161_AutoNegotiate\n\r");
    phyAddress = pDm->phyAddress;
    retryMax = pDm->retryMax;

    EMAC_EnableMdio();

    if (!EMAC_ReadPhy(phyAddress, DM9161_PHYID1, &value, retryMax)) {
        TRACE_ERROR("Pb EMAC_ReadPhy Id1\n\r");
        rc = 0;
        goto AutoNegotiateExit;
    }
    TRACE_DEBUG("ReadPhy Id1 0x%X, addresse: %d\n\r", value, phyAddress);
    if (!EMAC_ReadPhy(phyAddress, DM9161_PHYID2, &phyAnar, retryMax)) {
        TRACE_ERROR("Pb EMAC_ReadPhy Id2\n\r");
        rc = 0;
        goto AutoNegotiateExit;
    }
    TRACE_DEBUG("ReadPhy Id2 0x%X\n\r", phyAnar);

    if( ( value == DM9161_OUI_MSB )
     && ( ((phyAnar>>10)&DM9161_LSB_MASK) == DM9161_OUI_LSB ) ) {

        TRACE_DEBUG("Vendor Number Model = 0x%X\n\r", ((phyAnar>>4)&0x3F));
        TRACE_DEBUG("Model Revision Number = 0x%X\n\r", (phyAnar&0x7));
    }
    else {
        TRACE_ERROR("Problem OUI value\n\r");
    }        

    // Setup control register
    rc  = EMAC_ReadPhy(phyAddress, DM9161_BMCR, &value, retryMax);
    if (rc == 0) {

        goto AutoNegotiateExit;
    }

    value &= ~DM9161_AUTONEG;   // Remove autonegotiation enable
    value &= ~(DM9161_LOOPBACK|DM9161_POWER_DOWN);
    value |=  DM9161_ISOLATE;   // Electrically isolate PHY
    rc = EMAC_WritePhy(phyAddress, DM9161_BMCR, value, retryMax);
    if (rc == 0) {

        goto AutoNegotiateExit;
    }

    // Set the Auto_negotiation Advertisement Register
    // MII advertising for Next page
    // 100BaseTxFD and HD, 10BaseTFD and HD, IEEE 802.3
    phyAnar = DM9161_NP | DM9161_TX_FDX | DM9161_TX_HDX |
              DM9161_10_FDX | DM9161_10_HDX | DM9161_AN_IEEE_802_3;
    rc = EMAC_WritePhy(phyAddress, DM9161_ANAR, phyAnar, retryMax);
    if (rc == 0) {

        goto AutoNegotiateExit;
    }

    // Read & modify control register
    rc  = EMAC_ReadPhy(phyAddress, DM9161_BMCR, &value, retryMax);
    if (rc == 0) {

        goto AutoNegotiateExit;
    }

    value |= DM9161_SPEED_SELECT | DM9161_AUTONEG | DM9161_DUPLEX_MODE;
    rc = EMAC_WritePhy(phyAddress, DM9161_BMCR, value, retryMax);
    if (rc == 0) {

        goto AutoNegotiateExit;
    }

    // Restart Auto_negotiation
    value |=  DM9161_RESTART_AUTONEG;
    value &= ~DM9161_ISOLATE;
    rc = EMAC_WritePhy(phyAddress, DM9161_BMCR, value, retryMax);
    if (rc == 0) {

        goto AutoNegotiateExit;
    }
    TRACE_DEBUG(" _BMCR: 0x%X\n\r", value);

    // Check AutoNegotiate complete
    while (1) {

        rc  = EMAC_ReadPhy(phyAddress, DM9161_BMSR, &value, retryMax);
        if (rc == 0) {

            TRACE_ERROR("rc==0\n\r");
            goto AutoNegotiateExit;
        }
        // Done successfully
        if (value & DM9161_AUTONEG_COMP) {

            TRACE_INFO("AutoNegotiate complete\n\r");
            break;
        }
        // Timeout check
        if (retryMax) {

            if (++ retryCount >= retryMax) {

                DM9161_DumpRegisters(pDm);
                TRACE_FATAL("TimeOut\n\r");
                goto AutoNegotiateExit;
            }
        }
    }

    // Get the AutoNeg Link partner base page
    rc  = EMAC_ReadPhy(phyAddress, DM9161_ANLPAR, &phyAnalpar, retryMax);
    if (rc == 0) {

        goto AutoNegotiateExit;
    }

    // Setup the EMAC link speed
    if ((phyAnar & phyAnalpar) & DM9161_TX_FDX) {

        // set MII for 100BaseTX and Full Duplex
        EMAC_SetLinkSpeed(1, 1);
    }
    else if ((phyAnar & phyAnalpar) & DM9161_10_FDX) {

        // set MII for 10BaseT and Full Duplex
        EMAC_SetLinkSpeed(0, 1);
    }
    else if ((phyAnar & phyAnalpar) & DM9161_TX_HDX) {

        // set MII for 100BaseTX and half Duplex
        EMAC_SetLinkSpeed(1, 0);
    }
    else if ((phyAnar & phyAnalpar) & DM9161_10_HDX) {

        // set MII for 10BaseT and half Duplex
        EMAC_SetLinkSpeed(0, 0);
    }

    // Setup EMAC mode
#if BOARD_EMAC_MODE_RMII != 1
    EMAC_EnableMII();
#else
    EMAC_EnableRMII();
#endif

AutoNegotiateExit:
    EMAC_DisableMdio();
    return rc;
}