Marvell交換芯片88E6390驅動開發

參考

Marvell交換芯片88E6321/88E6320驅動總結-硬件篇
Marvell交換芯片88E6321/88E6320驅動總結-寄存器篇
Marvell 88E6390交換芯片disable自動學習功能的坑
88E6390端口Link問題BUG解決
STM32連接Marvell交換芯片88E6176的PHY
Marvell 交換芯片DSA(分佈式交換架構)功能介紹
以太網交換芯片及PHY處理相關
二層交換機和三層交換機的區別
zynq and marvell dsa 88e6352 integration, device tree
zynqmp and marvell dsa 88e6320
Problem with Marvell 88E6320 connected to GEM3 in ZynqMP
Zynq and Marvell DSA integration

介紹

Marvell 88E6390是一款11端口全千兆以太網二層交換芯片,1port-8配置爲千兆電口,port9-10千兆光口,88E6390x則具8個集成的1Gb IEEE802.3az PHY和兩個10Gb端口,10Gb端口支持10Gbps、2.5Gbps和1Gbps速率,支持IEEE1588 1-step時間戳,支持最新Audio/Video Bridging(AVB)和Time Sensitive Networking(TSN)標準。

NO_CPU模式

在復位狀態下(RESETn = low)時,設置NO_CPU引腳電平後,RESETn上升沿將鎖存引腳電平。若此時NO_CPU=0則表示芯片由CPU控制,NO_CPU=1則表示芯片非CPU控制。在NO_CPU=0模式下,所有的Port在初始化時都被關閉,PHY的供電關閉,使得CPU可以在芯片工作前進行啓動與配置,該引腳內部上拉,默認上電所有Port打開。爲了方便,可以將NO_CPU置爲1進行調試,調試通過後,考慮低功耗處理時,可以採用NO_CPU=0模式,以屏蔽不需要打開的Port。
NO_CPU模式決定了上電之後端口的默認狀態

MDIO

由於88E6321本身功能強大,即可以做MAC也可以做PHY(2個Port)、SERDES(2個Port),因此雖然只是一個芯片,88E6321有兩種芯片尋址模式:單芯片尋址與多芯片尋址。
通過在復位狀態時設置ADDR[4:0]n引腳的電平可以設置設備地址(需要注意的是,ADDR所設置的地址爲實際SMI地址的反碼,即ADDR=0x1F對應的實際SMI地址爲0x00,,ADDR=0x00對應的實際SMI地址0x1F)。
主控可以通過這個接口(MDC_CPU與MDIO_CPU)對88E6321進行管理。MDC_CPU最高支持20MHz,MDIO_CPU需要外接一個4.7K到10K的上拉電阻。

單芯片尋址模式:

當ADDR[4:0]n=0x1F時,進入單芯片尋址模式,此時通過內部地址直接訪問,在這個模式下,88E6321會響應所有的32個SMI地址,因此必須確保他是惟一的SMI從設備,在設備寄存器映射圖中,SMI設備地址地址0X03、0X04(對應Port3、4的PHY)、0X0C、0X0D(對應Port0、1的SERDES),0X10-0X16(對應Port0-Port7),0X1B-0X1D(對應特殊寄存器Global1-3)是可以直接訪問的,而地址0X03、0X04(對應Port3、4的PHY)、0X0C、0X0D(對應Port0、1的SERDES),當然寄存器也可以通過使用Global2地址的SMI PHY Command和SMI PHY Data兩個寄存器進行間接訪問。

多芯片尋址模式:

當ADDR[4:0]n!=0x1F時,則進入多芯片尋址模式,此時,88E6321只會響應ADDR設置的地址的反碼 (ADDR[4:0]的反碼),同時僅有兩個寄存器可以直接訪問(SMI Command寄存器與SMI Data寄存器),其他寄存器則通過這兩個寄存器間接訪問(包括在單芯片尋址模式下間接訪問的寄存器)。間接訪問的函數,STM32版本,

/*!
 * \fn write_smi_phy_reg
 * \brief PHY寄存器設置
 *          
 * \param [in] ETH_HandleTypeDef *heth STM32以太網結構體定義
 * \param [in] uint16_t dev_addr PHY地址,單芯片尋址模式下爲0x03或0x04
 * \param [in] uint16_t reg_addr 寄存器地址
 * \param [in] uint32_t reg_value 寫入值
 * 
 * \retval error_code_t  
 */
error_code_t write_smi_phy_reg(ETH_HandleTypeDef *heth, uint16_t dev_addr, uint16_t reg_addr, uint32_t reg_value)
{
    volatile uint16_t time_out;
    uint32_t smi_reg;
    time_out = 100;

    /*!
     *  檢測當前PHY是否Busy
     */
    do {
        if (HAL_ETH_ReadPHYRegister_New(heth, GLOBAL2_DEV_ADDR(0x1C), SMI_PHY_CMD_REG(0x18), &smi_reg) != ok) {
            ERROR_MSG("Read SMI_PHY_CMD_REG register failed");
            return error;
        }
        if (time_out-- < 1) {
            ERROR_MSG("Read SMI_PHY_CMD_REG register timed out");
            return error;
        }
    } while (smi_reg & SMI_BUSY(0x8000));

    /*!
     *  先將需要寫入的數據寫入SMI_PHY_DATA_REG,待後續寫命令時完成傳輸
     */
    if (HAL_ETH_WritePHYRegister_New(heth, GLOBAL2_DEV_ADDR, SMI_PHY_DATA_REG, reg_value) != ok) {
        return error;
    }

    smi_reg = SMI_BUSY | (dev_addr << 5) | (SMI_WRITE(0x01) << 10) | (reg_addr << 0) | (SMI_CLAUSE22 << 12);//!< 設置需要寫入的命令(寫命令、smi地址、phy寄存器地址、條款) By: Ouqichen 2019年2月11日
    
    /*!
     *  寫入命令
     */
    if (HAL_ETH_WritePHYRegister_New(heth, GLOBAL2_DEV_ADDR, SMI_PHY_CMD_REG, smi_reg) != ok) {
        ERROR_MSG("Write PHY_QD_REG_SMI_PHY_CMD Register Failed");
        return error;
    }

    return ok;
}

/*!
 * \fn read_smi_phy_reg
 * \brief PHY寄存器讀取
 *          
 * \param [in] ETH_HandleTypeDef *heth STM32以太網結構體定義
 * \param [in] uint16_t dev_addr PHY地址,單芯片尋址模式下爲0x03或0x04
 * \param [in] uint16_t reg_addr 寄存器地址
 * \param [out] uint32_t *reg_value 讀出值
 * 
 * \retval error_code_t 
 */
error_code_t read_smi_phy_reg(ETH_HandleTypeDef *heth, uint16_t dev_addr, uint16_t reg_addr, uint32_t reg_value)
{
    volatile uint16_t time_out;
    uint32_t smi_reg;

    time_out =100;
    /*!
     *  檢測當前PHY是否Busy
     */
    do {
        if (HAL_ETH_ReadPHYRegister_New(heth, GLOBAL2_DEV_ADDR(0x1C), SMI_PHY_CMD_REG(0x18), &smi_reg) != ok) {
            ERROR_MSG("Read SMI_PHY_CMD_REG register failed");
            return error;
        }
        if (time_out-- < 1) {
            ERROR_MSG("Read SMI_PHY_CMD_REG register timed out");
            return error;
        }
    } while (smi_reg & SMI_BUSY(0x8000));

    smi_reg = SMI_BUSY | (dev_addr << 5) | (SMI_READ_22(0x02) << 10) | (reg_addr << 0) | (SMI_CLAUSE22 << 12);//!< 設置需要寫入的命令(讀命令、smi地址、phy寄存器地址、條款) By: Ouqichen 2019年2月11日

    /*!
     *  寫入命令
     */
    if (HAL_ETH_WritePHYRegister_New(heth, GLOBAL2_DEV_ADDR, SMI_PHY_CMD_REG, smi_reg) != ok) {
        ERROR_MSG("Write PHY_QD_REG_SMI_PHY_CMD Register Failed");
        return error;
    }

    time_out =100;
    /*!
     *  檢測當前PHY是否Busy
     */
    do {
        if (HAL_ETH_ReadPHYRegister_New(heth, GLOBAL2_DEV_ADDR(0x1C), SMI_PHY_CMD_REG(0x18), &smi_reg) != ok) {
            ERROR_MSG("Read SMI_PHY_CMD_REG register failed");
            return error;
        }
        if (time_out-- < 1) {
            ERROR_MSG("Read SMI_PHY_CMD_REG register timed out");
            return error;
        }
    } while (smi_reg & SMI_BUSY(0x8000));

    /*!
     *  待總線不忙碌時讀取數據
     */
    if (HAL_ETH_WritePHYRegister_New(heth, GLOBAL2_DEV_ADDR, SMI_PHY_DATA_REG, reg_value) != ok) {
        return error;
    }

    *reg_value = smi_reg;

    return ok; 
}

IEEE中只爲PHY定義了32個寄存器地址,爲了拓展寄存器地址,這裏採用的頁機制,其中寄存器22的[7:0]用於切換頁。切換函數,

/*!
 * \fn read_smi_page_phy_reg
 * \brief 帶頁切換的PHY寄存器讀取
 *          
 * \param [in] ETH_HandleTypeDef *heth STM32以太網結構體定義
 * \param [in] uint16_t port_num 端口號
 * \param [in] uint8_t page_num 頁號碼
 * \param [in] uint16_t reg_addr 寄存器地址
 * \param [out] uint32_t *reg_value 讀出值
 * 
 * \retval error_code_t 
 */
error_code_t read_smi_page_phy_reg(ETH_HandleTypeDef *heth, uint8_t port_num, uint8_t page_num, uint16_t reg_addr, uint32_t *reg_value)
{
    error_code_t ret_value;
    ret_value = write_smi_phy_reg(heth, (uint16_t)port_num, SMI_PHY_PAGE_ANY_REG(0x16), (uint32_t)page_num);

    if (ret_value != ok)
        return ret_value;

    ret_value = read_smi_phy_reg(heth, (uint16_t)port_num, reg_addr, reg_value);
    return ret_value;
}

/*!
 * \fn write_smi_phy_reg
 * \brief PHY寄存器設置
 *          
 * \param [in] ETH_HandleTypeDef *heth STM32以太網結構體定義
 * \param [in] uint16_t port_num 端口號
 * \param [in] uint8_t page_num 頁號碼
 * \param [in] uint16_t reg_addr 寄存器地址
 * \param [in] uint32_t reg_value 寫入值
 * 
 * \retval error_code_t  
 */
error_code_t read_smi_page_phy_reg(ETH_HandleTypeDef *heth, uint8_t port_num, uint8_t page_num, uint16_t reg_addr, uint32_t reg_value)
{

    error_code_t ret_value;
    ret_value = write_smi_phy_reg(heth, (uint16_t)port_num,SMI_PHY_PAGE_ANY_REG(0x16), (uint32_t)page_num);

    if (ret_value != ok)
        return ret_value;

    ret_value = write_smi_phy_reg(heth, (uint16_t)port_num, reg_addr, reg_value);
    return ret_value;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章