This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

DP83822H: Unable to switch on 50MHz Reference Clock for RMII Master Signalling

Part Number: DP83822H

Hello there:

Having trouble setting up the RMII interface: specifically Unable to switch on 50MHz Reference Clock for RMII Master Signalling.

  • I have setup the following registers:
  • BMCR.MII_Loopback = 1
  • BMCR.SpeedSelection = 0 (10MBps)
  • BMCR.Autonegotiate = 1 
  • BMCR.DuplexMode = 1 
  • RCSR = 0x61 (enable RMII)
  • EECFG = 0x18A (Disable EEE)
  • IOMUX-GPIO3 = 0x8600 (RMII Master ref clock 50MHz)

Please advise if I missed anything.

Thanks.

Alan Chu 

Software Engineer

  • Hi,

    After above steps, are you triggering soft reset ?

    Kindly advise the strap settings you have configured on PHY ?

    Also, please read register 0x467 and 0x468. These register reads the latched strap values.

    Regards,
    Geet


    Regards,
    Geet
  • /*
     * Copyright (c) 2011-2012, Freescale Semiconductor, Inc.
     * All rights reserved.
     *
     * Redistribution and use in source and binary forms, with or without modification,
     * are permitted provided that the following conditions are met:
     *
     * o Redistributions of source code must retain the above copyright notice, this list
     *   of conditions and the following disclaimer.
     *
     * o Redistributions in binary form must reproduce the above copyright notice, this
     *   list of conditions and the following disclaimer in the documentation and/or
     *   other materials provided with the distribution.
     *
     * o Neither the name of Freescale Semiconductor, Inc. nor the names of its
     *   contributors may be used to endorse or promote products derived from this
     *   software without specific prior written permission.
     *
     * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
     * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
     * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
     * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS 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 enet_drv.c
     * @brief Driver of the i.MX ENET controller.
     *
     * @ingroup diag_enet
     */
    
    //#include "sdk.h"
    #include "hal_build.h"
    #include "imx_enet.h"
    #include "registers/regsenet.h"
    
    #include "enet_private.h"
    
    /*!
     *Global variable which defines the buffer descriptions for receiving frame
     *  comment:: it must aligned by 128-bits.
     */
    static imx_enet_bd_t imx_enet_rx_bd[ENET_BD_RX_NUM * NUM_OF_ETH_DEVS] __attribute__ ((aligned(32)));
    
    /*!
     *Global variable which defines the buffer descriptions for receiving frame
     *  comment:: it must aligned by 128-bits.
     */
    static imx_enet_bd_t imx_enet_tx_bd[ENET_BD_TX_NUM * NUM_OF_ETH_DEVS] __attribute__ ((aligned(32)));
    
    /*!
     * Global variable which contains the frame buffers ,
     */
    static unsigned char imx_enet_rx_buf[ENET_BD_RX_NUM * NUM_OF_ETH_DEVS][2048]
        __attribute__ ((aligned(32)));
    
    /*!
     * Global variable which contains the frame buffers ,
     */
    static unsigned char imx_enet_tx_buf[ENET_BD_TX_NUM * NUM_OF_ETH_DEVS][2048]
        __attribute__ ((aligned(32)));
    
    /*!
     * This function gets the value of the PHY registers through the MII interface.
     */
    int imx_enet_mii_read(volatile ENET_Type * enet_reg, unsigned char phy_addr,
                          unsigned char reg_addr, unsigned short int *value)
    {
        unsigned long waiting = ENET_MII_TIMEOUT;
    
        if (enet_reg->EIR & ENET_EIR_MII_MASK) {
            enet_reg->EIR = ENET_EIR_MII_MASK;
        }
    
        enet_reg->MMFR = ENET_MII_READ(phy_addr, reg_addr);   /*Write CMD */
    
        while (1) {
            if (enet_reg->EIR & ENET_EIR_MII_MASK) {
                enet_reg->EIR = ENET_EIR_MII_MASK;
                break;
            }
            if ((--waiting) == 0)
                return -1;
            npl_timer_delay_ms( 1 );
        }
    
        *value = ENET_MII_GET_DATA(enet_reg->MMFR);
        return 0;
    }
    
    /*!
     * This function sets the value of the PHY registers through the MII interface.
     */
    int imx_enet_mii_write(volatile ENET_Type * enet_reg, unsigned char phy_addr,
                           unsigned char reg_addr, unsigned short int value)
    {
        unsigned long waiting = ENET_MII_TIMEOUT;
    
        if (enet_reg->EIR & ENET_EIR_MII_MASK) {
            enet_reg->EIR = ENET_EIR_MII_MASK;
        }
    
        enet_reg->MMFR = ENET_MII_WRITE(phy_addr, reg_addr, value);   /* Write CMD */
    
        while (1) {
            if (enet_reg->EIR & ENET_EIR_MII_MASK) {
                enet_reg->EIR = ENET_EIR_MII_MASK;
                break;
            }
    
            if ((--waiting) == 0)
                return -1;
    
            npl_timer_delay_ms( 1 );
        }
    
        return 0;
    }
    
    /*!
     * The function initializes the description buffer for receiving or transmitting.
     */
    static void imx_enet_bd_init(imx_enet_priv_t * dev, int dev_idx)
    {
        int i;
        imx_enet_bd_t *p;
        imx_enet_bd_t *rx_bd_base = imx_enet_rx_bd, *tx_bd_base = imx_enet_tx_bd;
    
        rx_bd_base += (dev_idx * ENET_BD_RX_NUM);
        tx_bd_base += (dev_idx * ENET_BD_TX_NUM);
    
        p = dev->rx_bd = (imx_enet_bd_t *) rx_bd_base;
    
        for (i = 0; i < ENET_BD_RX_NUM; i++, p++) {
            p->status = BD_RX_ST_EMPTY;
            p->length = 0;
            p->data = (unsigned char *)imx_enet_rx_buf[i + dev_idx * ENET_BD_RX_NUM];
            //printf("rx bd %x, buffer is %x\n", (unsigned int)p, (unsigned int)p->data);
        }
    
        dev->rx_bd[i - 1].status |= BD_RX_ST_WRAP;
        dev->rx_cur = dev->rx_bd;
    
        p = dev->tx_bd = (imx_enet_bd_t *) tx_bd_base;
    
        for (i = 0; i < ENET_BD_TX_NUM; i++, p++) {
            p->status = 0;
            p->length = 0;
            p->data = (unsigned char *)imx_enet_tx_buf[i + dev_idx * ENET_BD_TX_NUM];
            //printf("tx bd %x, buffer is %x\n", (unsigned int)p, (unsigned int)p->data);
        }
    
        dev->tx_bd[i - 1].status |= BD_TX_ST_WRAP;
        dev->tx_cur = dev->tx_bd;
    
        /*TODO:: add the sync function for items */
    }
    
    /*!
     * This function initializes the ENET controller.
     */
    
    static void imx_enet_chip_init(imx_enet_priv_t * dev)
    {
    //    volatile hw_enet_t *enet_reg = (hw_enet_t *) dev->enet_reg;
        volatile ENET_Type *enet_reg = (ENET_Type *) dev->enet_reg;
    
        unsigned int ipg_clk;
    printf("enet_reg->ECR  = ENET_ECR_RESET(1);\n");
        enet_reg->ECR  = ENET_ECR_RESET(1);
    
        while (enet_reg->ECR & ENET_ECR_RESET(1)) {
            npl_timer_delay_ms( 1 );
        }
    printf("enet_reg->EIMR\n");
    //    enet_reg->EIMR = 0x00000000;
        enet_reg->EIMR = 0xFFFF0000;
    
        enet_reg->EIR  = 0xFFFFFFFF;
    
        /*
         * setup the MII gasket for RMII mode
         */
    printf("enet_reg->RCR\n");
        enet_reg->RCR = (enet_reg->RCR) &( ~(0x0000003F)) | (ENET_RCR_MII_MODE(1)| ENET_RCR_RMII_10T(1) | ENET_RCR_PROM(1)| ENET_RCR_FCE(1));
    
    printf("enet_reg->TCR\n");
        enet_reg->TCR |= ENET_TCR_FDEN(1);
    printf("enet_reg->MIBC\n");
        enet_reg->MIBC |= ENET_MIBC_MIB_DIS(1);
    
        enet_reg->IAUR = 0;
        enet_reg->IALR = 0;
        enet_reg->GAUR = 0;
        enet_reg->GALR = 0;
    printf("enet_reg->MSCR\n");
        //Internal Module Clock Frequency = 66MHz
        //MII_SPPED=0xD
        //enet_reg->MSCR.U = (enet_reg->MSCR.U & (~0x7e)) | (((ipg_clk + 499999) / 5000000) << 1);
        enet_reg->MSCR = (enet_reg->MSCR & (~0x7e)) | (ENET_MSCR_MII_SPEED(0xD));
    printf("enet_reg->MRBR\n");
        //Enable ETHER_EN
        enet_reg->MRBR = 2048 - 16;
        enet_reg->RDSR = (unsigned long)dev->rx_bd;
        enet_reg->TDSR = (unsigned long)dev->tx_bd;
    
    #if 0//defined(CHIP_MX6DQ) || defined(CHIP_MX6SDL)
        /* Enable Swap to support little-endian device */
        enet_reg->ECR.U |= (0x1 << 8); //BM_ENET_ECR_DBSWP;
        /* set ENET tx at store and forward mode */
        enet_reg->TFWR.U |= BM_ENET_TFWR_STRFWD; //(0x1 << 8);
    #endif
    }
    
    
    /*!
     * This function initializes the PHY connected to the ENET controller.
     */
    void imx_enet_phy_init(imx_enet_priv_t * dev)
    {
        unsigned short value = 0;
        unsigned long id = 0;
    
        // Read PHY ID registers.
        imx_enet_mii_read(dev->enet_reg, dev->phy_addr, PHY_IDENTIFY_1, &value);
        id = (value & PHY_ID1_MASK) << PHY_ID1_SHIFT;
        imx_enet_mii_read(dev->enet_reg, dev->phy_addr, PHY_IDENTIFY_2, &value);
        id |= (value & PHY_ID2_MASK) << PHY_ID2_SHIFT;
        id &= 0xfffffff0; // mask off lower 4 bits
    
        printf("\n\nENET DP83822 PHY: ID=%lx\n\n", id);
    
        dev->phy_id = id;
    
        // Reset PHY
        imx_enet_mii_read(dev->enet_reg, dev->phy_addr, PHY_CTRL_REG, &value);
        value |= PHY_CTRL_RESET;
        imx_enet_mii_write(dev->enet_reg, dev->phy_addr, PHY_CTRL_REG, value);
    
        // Wait for reset to complete.
        do {
            imx_enet_mii_read(dev->enet_reg, dev->phy_addr, PHY_CTRL_REG, &value);
        } while (value & PHY_CTRL_RESET);
    
        /* restart auto-negotiation - full duplex */
        imx_enet_mii_read(dev->enet_reg, dev->phy_addr, PHY_CTRL_REG, &value);
        value |= 0x1300;
        imx_enet_mii_write(dev->enet_reg, dev->phy_addr, PHY_CTRL_REG, value);
        imx_enet_mii_read(dev->enet_reg, dev->phy_addr, PHY_CTRL_REG, &value);
        printf("\n\nThe value of PHY_CTRL_REG = %x\n\n", value);
    
    
        /* Enable RMII : RCSR = 0x61 */
        imx_enet_mii_write(dev->enet_reg, dev->phy_addr, PHY_RCSR_ADDR, PHY_ENABLE_RMII);
        imx_enet_mii_read(dev->enet_reg, dev->phy_addr, PHY_RCSR_ADDR, &value);
        printf("\n\nThe value of PHY_RCSR_ADDR = %x\n\n", value);
    
    
        /* Disable EEE : EECFG3 = 0x18A */
        imx_enet_mii_write(dev->enet_reg, dev->phy_addr, PHY_REGCR_ADDR, PHY_EXTENDED_REG_ADDRESS);
        imx_enet_mii_write(dev->enet_reg, dev->phy_addr, PHY_ADDAR_ADDR, PHY_EECFG3_ADDR);
    
        imx_enet_mii_write(dev->enet_reg, dev->phy_addr, PHY_REGCR_ADDR, PHY_EXTENDED_REG_DATA);
        imx_enet_mii_write(dev->enet_reg, dev->phy_addr, PHY_ADDAR_ADDR, PHY_DISABLE_EEE);
        imx_enet_mii_read(dev->enet_reg, dev->phy_addr, PHY_ADDAR_ADDR, &value);
        printf("\n\nThe value of PHY_EECFG3_ADDR = %x\n\n", value);
    
        /* IOMUX-GPIO3 Clock source: RMII Master Ref Clock = 50MHz, Control = Based on the Ref CLock*/
        imx_enet_mii_write(dev->enet_reg, dev->phy_addr, PHY_REGCR_ADDR, PHY_EXTENDED_REG_ADDRESS);
        imx_enet_mii_write(dev->enet_reg, dev->phy_addr, PHY_ADDAR_ADDR, PHY_IOCTRL1_ADDR);
    
        imx_enet_mii_write(dev->enet_reg, dev->phy_addr, PHY_REGCR_ADDR, PHY_EXTENDED_REG_DATA);
        imx_enet_mii_write(dev->enet_reg, dev->phy_addr, PHY_ADDAR_ADDR, PHY_IOCTRL1_RMII_CLK_50MHZ);
        imx_enet_mii_read(dev->enet_reg, dev->phy_addr, PHY_ADDAR_ADDR, &value);
        printf("\n\nThe value of PHY_IOCTRL1_ADDR = %x\n\n", value);
    
        // Read strap latch-in register #1 PHY status.
        imx_enet_mii_write(dev->enet_reg, dev->phy_addr, PHY_REGCR_ADDR, PHY_EXTENDED_REG_ADDRESS);
        imx_enet_mii_write(dev->enet_reg, dev->phy_addr, PHY_ADDAR_ADDR, PHY_STRAP_IN_1_ADDR);
    
        imx_enet_mii_write(dev->enet_reg, dev->phy_addr, PHY_REGCR_ADDR, PHY_EXTENDED_REG_DATA);
        imx_enet_mii_read(dev->enet_reg, dev->phy_addr, PHY_ADDAR_ADDR, &value);
        printf("\n\nThe value of Strap Latch In Register 1 = %x\n\n", value);
    
        // Read strap latch-in register #2 PHY status.
        imx_enet_mii_write(dev->enet_reg, dev->phy_addr, PHY_REGCR_ADDR, PHY_EXTENDED_REG_ADDRESS);
        imx_enet_mii_write(dev->enet_reg, dev->phy_addr, PHY_ADDAR_ADDR, PHY_STRAP_IN_2_ADDR);
    
        imx_enet_mii_write(dev->enet_reg, dev->phy_addr, PHY_REGCR_ADDR, PHY_EXTENDED_REG_DATA);
        imx_enet_mii_read(dev->enet_reg, dev->phy_addr, PHY_ADDAR_ADDR, &value);
        printf("\n\nThe value of Strap Latch In Register 2 = %x\n\n", value);
    
        // Reset PHY
        imx_enet_mii_read(dev->enet_reg, dev->phy_addr, PHY_CTRL_REG, &value);
        value |= PHY_CTRL_RESET;
        imx_enet_mii_write(dev->enet_reg, dev->phy_addr, PHY_CTRL_REG, value);
    
        // Wait for reset to complete.
        do {
            imx_enet_mii_read(dev->enet_reg, dev->phy_addr, PHY_CTRL_REG, &value);
        } while (value & PHY_CTRL_RESET);
    
        // Read current PHY status.
        imx_enet_get_phy_status(dev);
    
    }
    
    uint32_t imx_enet_get_phy_status(imx_enet_priv_t * dev)
    {
        uint16_t value;
    
        // Reset saved status.
        dev->status = 0;
    
        imx_enet_mii_read(dev->enet_reg, dev->phy_addr, PHY_STATUS_REG, &value);
    
        printf("****** Enet phy status %0d: %04x\n", dev->phy_addr, value);    //  0x7809 or 0x782d
    
        if (value & PHY_STATUS_LINK_ST)
        {
            dev->status |= ENET_STATUS_LINK_ON;
        }
        else
        {
            dev->status &= ~ENET_STATUS_LINK_ON;
        }
    // Below is specific to the DP83822 PHY
        if(value & (1<<14) || value & (1<<12))
        {
            dev->status |= ENET_STATUS_FULL_DPLX;
        } else if(value & (1<<13) || value & (1<<11))
        {
            dev->status &= ~ENET_STATUS_FULL_DPLX;
        }
    
        if(value & (1<<14) || value & (1<<13))
        {
            dev->status |= ENET_STATUS_100M;
            dev->status &= ~ENET_STATUS_10M;
            dev->status &= ~ENET_STATUS_1000M;
        } else if(value & (1<<13) || value & (1<<11))
        {
            dev->status |= ENET_STATUS_10M;
            dev->status &= ~ENET_STATUS_100M;
            dev->status &= ~ENET_STATUS_1000M;
        }
    
    
         printf("ENET %0d: [ %s ] [ %s ] [ %s ]:\n", dev->phy_addr,
                (dev->status & ENET_STATUS_FULL_DPLX) ? "FULL_DUPLEX" : "HALF_DUPLEX",
                (dev->status & ENET_STATUS_LINK_ON) ? "connected" : "disconnected",
                (dev->status & ENET_STATUS_1000M) ? "1000M bps" : (dev->status & ENET_STATUS_100M) ?
                "100M bps" : "10M bps");
    
        return dev->status;
    }
    
    void imx_enet_phy_enable_external_loopback(imx_enet_priv_t * dev)
    {
        uint16_t val;
    
        // Config External Loopback on the PHY
        // BMCR on the DP83822 - register address 0x16 as specified by TI datasheet DP83822
        imx_enet_mii_write(dev->enet_reg, dev->phy_addr, PHY_BISCR_REG, 0x110); // External Loopback = 1  and Power Mode = 1
    }
    
    void imx_enet_phy_enable_mii_loopback(imx_enet_priv_t * dev)
    {
        uint16_t val;
        // Config MII Loopback on the PHY
        // BMCR on the DP83822 - register address 0x0 as specified by IEEE802.3 clause 22
        imx_enet_mii_write(dev->enet_reg, dev->phy_addr, PHY_CTRL_REG, 0x5100); // MII Loopback enable, select speed 10Mbps, Enable Auto Negotiate
    }
    
    unsigned long imx_enet_poll(imx_enet_priv_t * dev)
    {
        volatile ENET_Type *enet_reg = dev->enet_reg;
        unsigned int value = 0;
    
    
    // ACDEBUG
        printf("\n Reading EIR: %x \n", value);
    
    
        value = enet_reg->EIR;
        enet_reg->EIR = value & (~ENET_EIR_MII(1));
    
    
        if (value & (ENET_EIR_BABT(1) | ENET_EIR_LC(1) | ENET_EIR_RL(1) | ENET_EIR_UN(1))) {
            printf("WARNING[POLL]: There are error(%x) for transmit\n", value & (ENET_EIR_BABT(1) | ENET_EIR_LC(1) | ENET_EIR_RL(1) | ENET_EIR_UN(1)));
            dev->tx_busy = 0;
        } else {
            if (value & ENET_EIR_TXF(1)) {
                dev->tx_busy = 0;
            }
        }
    
        if (value & ENET_EIR_RXF(1)) {
            //imx_enet_check_rx_bd(sc);
        }
    
    //    if (value & ENET_EIR_EBERR(1)) {
    //        printf("WARNGING[POLL]: Hearbeat error!\n");
    //    }
    
        if (value & ENET_EIR_EBERR(1)) {
            printf("WARNING[POLL]: Ethernet Bus Error!\n");
        }
    
        return value;
    }
    
    int imx_enet_send(imx_enet_priv_t * dev, unsigned char *buf, int length, unsigned long key)
    {
        volatile ENET_Type *enet_reg = dev->enet_reg;
        imx_enet_bd_t *p = dev->tx_cur;
    
    printf("\n\nSending data buffer length %d\n", length);
    printf("\nShow the ENET Control Register %x\n\n", enet_reg->ECR);
    
        memcpy(p->data, buf, length);
    
        p->length = length;
        p->status &= ~(BD_TX_ST_LAST | BD_TX_ST_RDY | BD_TX_ST_TC | BD_TX_ST_ABC);
        p->status |= BD_TX_ST_LAST | BD_TX_ST_RDY | BD_TX_ST_TC;
    
        if (p->status & BD_TX_ST_WRAP) {
            p = dev->tx_bd;
        } else
            p++;
    
        dev->tx_cur = p;
        dev->tx_busy = 1;
        dev->tx_key = key;
        enet_reg->TDAR = ENET_RX_TX_ACTIVE;
    
        return 0;
    }
    
    int imx_enet_recv(imx_enet_priv_t * dev, unsigned char *buf, int *length)
    {
        imx_enet_bd_t *p = dev->rx_cur;
        volatile ENET_Type *enet_reg = dev->enet_reg;
    
        if (p->status & BD_RX_ST_EMPTY) {
            return -1;
        }
    
        if (!(p->status & BD_RX_ST_LAST)) {
            printf("BUG[RX]: status=%x, length=%x\n", p->status, p->length);
            return -1;
        }
    
        if ((p->status & BD_RX_ST_ERRS) || (p->length > ENET_FRAME_LEN)) {
            printf("BUG1[RX]: status=%x, length=%x\n", p->status, p->length);
        } else {
            memcpy(buf, p->data, p->length - 4);
            *length = p->length - 4;
        }
    
        p->status = (p->status & BD_RX_ST_WRAP) | BD_RX_ST_EMPTY;
    
        if (p->status & BD_RX_ST_WRAP) {
            p = dev->rx_bd;
        } else {
            p++;
        }
    
        dev->rx_cur = p;
        enet_reg->ECR |= ENET_ECR_ETHEREN(1);
        //enet_reg->RDAR |= ENET_RX_TX_ACTIVE;
    
        return 0;
    }
    
    int imx_enet_init(imx_enet_priv_t * dev, unsigned long reg_base, int phy_addr)
    {
    
        dev->enet_reg = (ENET_Type *) reg_base;
        dev->tx_busy = 0;
        dev->status = 0;
        dev->phy_addr = phy_addr;   /* 0 or 1 */
        printf("Set up Ethernet Driver for PHY #%d\n", phy_addr);
        imx_enet_bd_init(dev, phy_addr); // Setup the Ethernet Driver
        printf("Set up MII Interface\n");
        imx_enet_chip_init(dev);  // Setup MII
        printf("Set up PHY device\n");
        imx_enet_phy_init(dev); // Engage the PHY and Reset the PHY
        return 0;
    }
    
    static void imx_enet_set_mac_address(volatile ENET_Type * enet_reg, unsigned char *enaddr)
    {
        unsigned long value;
    
        value = enaddr[0];
        value = (value << 8) + enaddr[1];
        value = (value << 8) + enaddr[2];
        value = (value << 8) + enaddr[3];
        enet_reg->PALR = value;
    
        value = enaddr[4];
        value = (value << 8) + enaddr[5];
        enet_reg->PAUR = (value << 16);
    }
    
    void imx_enet_start(imx_enet_priv_t * dev, unsigned char *enaddr)
    {
        volatile ENET_Type *enet_reg = dev->enet_reg;
    
        imx_enet_set_mac_address(dev->enet_reg, enaddr);
    
        dev->tx_busy = 0;
        enet_reg->ECR |= ENET_ECR_ETHEREN(1);
    
        dev->enet_reg->RDAR |= ENET_RX_TX_ACTIVE;
    }
    
    void imx_enet_stop(imx_enet_priv_t * dev)
    {
        volatile ENET_Type *enet_reg = dev->enet_reg;
        enet_reg->ECR &= ~ENET_ECR_ETHEREN(1);
    }
    
    int imx_enet_isolate_phy(imx_enet_priv_t * dev)
    {
        unsigned short value = 0;
    
        if (!imx_enet_mii_read(dev->enet_reg, dev->phy_addr, PHY_CTRL_REG, &value)) {
            value |= (0x01 << 10);
            if (!imx_enet_mii_write(dev->enet_reg, dev->phy_addr, PHY_CTRL_REG, value)) {
                return 0;
            }
        }
        return -1;
    }
    
    int imx_enet_unisolate_phy(imx_enet_priv_t * dev)
    {
        unsigned short value = 0;
    
        if (!imx_enet_mii_read(dev->enet_reg, dev->phy_addr, PHY_CTRL_REG, &value)) {
            value &= ~(0x01 << 10);
            if (!imx_enet_mii_write(dev->enet_reg, dev->phy_addr, PHY_CTRL_REG, value)) {
                imx_enet_mii_read(dev->enet_reg, dev->phy_addr, PHY_CTRL_REG, &value);
                return 0;
            }
        }
        return -1;
    }
    
    int imx_enet_mii_type(imx_enet_priv_t * dev, enum imx_mii_type mii_type)
    {
        volatile ENET_Type *enet_reg = dev->enet_reg;
    
        switch (mii_type) {
        case MII:
            /*clear RMII */
            printf("Selec MII mode\n");
            enet_reg->RCR &= ~(ENET_RCR_RMII_MODE(1));
            break;
        case RMII:
            /*set RMII */
            printf("Select RMII mode\n");
            enet_reg->RCR |= (ENET_RCR_RMII_MODE(1));
            printf("Select RMII mode - succesful\n");
            break;
        default:
            printf("BUG:unknown MII type=%x\n", mii_type);
            break;
        }
        return 0;
    }
    
    (1) The following values were read back from the PHY after initialisation. (See attached code)

    ENET DP83822 PHY: ID=2000a240

    The value of PHY_CTRL_REG = 3100

    The value of PHY_RCSR_ADDR = 61

    The value of PHY_EECFG3_ADDR = 18a

    The value of PHY_IOCTRL1_ADDR = 4300

    The value of Strap Latch In Register 1 (0x467)= fc3

    The value of Strap Latch In Register 2 (ox468)= 0

    (2) A soft reset was called after the above steps.

  • Hi,

    Strap latch of 0x467= 0x0FC3. RX_DV strap controls the RMII Master and Slave Mode. RX_DV is bit[5:4]. Both are 00 which means you in mode 1.

    Mode 1 as in Table 11 is RMII_EN and XI_50 as disabled. You need to be in mode 3 for RMII Master. and RX_ER as Mode 1 or Mode 4 to disable RGMII.


    Regards,
    Geet
  • Surely these settings are latched at power on but we can change to RMII mode via the RW bits RMII clock select and RGMII mode and RMII mode of register RCSR (0x0017). Is my understanding incorrect?

  • Alternate way to do is :
    - Keep the device in Power Down Mode ( using Pin),
    - Get the device out of reset
    - Program the configuration registers ( change to RMII mode etc).
    - Remove the device from Power Down Mode

    Regards,
    Geet
  • Hi,

    I am closing this thread. Incase you need further assistance on this topic, please open new thread and provide reference to this thread.

    Regards,
    Geet