esp_eth: Add functions to access PHY using MDIO

Specifically:
  - Set/get address
  - Read/write data at address with specified MDIO access function
  - Read/write both address and data with a single call
This commit is contained in:
Bogdan Kolendovskyy 2024-01-30 11:56:01 +01:00
parent 4ecc978bd6
commit 8c9657063a
3 changed files with 224 additions and 3 deletions

View File

@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2022-2024 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
@ -28,6 +28,17 @@ typedef struct {
int reset_gpio_num; /*!< Reset GPIO number, -1 means no hardware reset */
} phy_802_3_t;
/**
* @brief IEEE 802.3 MMD modes enumeration
*
*/
typedef enum {
MMD_FUNC_ADDRESS = 0,
MMD_FUNC_DATA_NOINCR = 1,
MMD_FUNC_DATA_RWINCR = 2,
MMD_FUNC_DATA_WINCR = 3
} esp_eth_phy_802_3_mmd_func_t;
/**
* @brief Set Ethernet mediator
*
@ -247,6 +258,88 @@ esp_err_t esp_eth_phy_802_3_read_oui(phy_802_3_t *phy_802_3, uint32_t *oui);
*/
esp_err_t esp_eth_phy_802_3_read_manufac_info(phy_802_3_t *phy_802_3, uint8_t *model, uint8_t *rev);
/**
* @brief Reads MDIO device's internal address register
*
* @param phy_802_3 IEEE 802.3 PHY object infostructure
* @param devaddr Address of MDIO device
* @param[out] mmd_addr Current address stored in device's register
* @return
* - ESP_OK: Address register read successfuly
* - ESP_FAIL: Address register read failed because of some error occured
* - ESP_ERR_INVALID_ARG: Device address provided is out of range (hardware limits device address to 5 bits)
*/
esp_err_t esp_eth_phy_802_3_get_mmd_addr(phy_802_3_t *phy_802_3, uint8_t devaddr, uint16_t *mmd_addr);
/**
* @brief Write to DIO device's internal address register
*
* @param phy_802_3 IEEE 802.3 PHY object infostructure
* @param devaddr Address of MDIO device
* @param[out] mmd_addr New value of MDIO device's address register value
* @return
* - ESP_OK: Address register written to successfuly
* - ESP_FAIL: Address register write failed because of some error occured
* - ESP_ERR_INVALID_ARG: Device address provided is out of range (hardware limits device address to 5 bits)
*/
esp_err_t esp_eth_phy_802_3_set_mmd_addr(phy_802_3_t *phy_802_3, uint8_t devaddr, uint16_t mmd_addr);
/**
* @brief Read data of MDIO device's memory at address register
*
* @param phy_802_3 IEEE 802.3 PHY object infostructure
* @param devaddr Address of MDIO device
* @param function MMD function
* @param[out] data Data read from the device's memory
* @return
* - ESP_OK: Memory read successfuly
* - ESP_FAIL: Memory read failed because of some error occured
* - ESP_ERR_INVALID_ARG: Device address provided is out of range (hardware limits device address to 5 bits) or MMD access function is invalid
*/
esp_err_t esp_eth_phy_802_3_read_mmd_data(phy_802_3_t *phy_802_3, uint8_t devaddr, esp_eth_phy_802_3_mmd_func_t function, uint32_t *data);
/**
* @brief Write data to MDIO device's memory at address register
*
* @param phy_802_3 IEEE 802.3 PHY object infostructure
* @param devaddr Address of MDIO device
* @param function MMD function
* @param[out] data Data to write to the device's memory
* @return
* - ESP_OK: Memory written successfuly
* - ESP_FAIL: Memory write failed because of some error occured
* - ESP_ERR_INVALID_ARG: Device address provided is out of range (hardware limits device address to 5 bits) or MMD access function is invalid
*/
esp_err_t esp_eth_phy_802_3_write_mmd_data(phy_802_3_t *phy_802_3, uint8_t devaddr, esp_eth_phy_802_3_mmd_func_t function, uint32_t data);
/**
* @brief Set MMD address to mmd_addr with function MMD_FUNC_NOINCR and read contents to *data
*
* @param phy_802_3 IEEE 802.3 PHY object infostructure
* @param devaddr Address of MDIO device
* @param mmd_addr Address of MDIO device register
* @param[out] data Data read from the device's memory
* @return
* - ESP_OK: Memory read successfuly
* - ESP_FAIL: Memory read failed because of some error occured
* - ESP_ERR_INVALID_ARG: Device address provided is out of range (hardware limits device address to 5 bits)
*/
esp_err_t esp_eth_phy_802_3_read_mmd_register(phy_802_3_t *phy_802_3, uint8_t devaddr, uint16_t mmd_addr, uint32_t *data);
/**
* @brief Set MMD address to mmd_addr with function MMD_FUNC_NOINCR and write data
*
* @param phy_802_3 IEEE 802.3 PHY object infostructure
* @param devaddr Address of MDIO device
* @param mmd_addr Address of MDIO device register
* @param[out] data Data to write to the device's memory
* @return
* - ESP_OK: Memory written to successfuly
* - ESP_FAIL: Memory write failed because of some error occured
* - ESP_ERR_INVALID_ARG: Device address provided is out of range (hardware limits device address to 5 bits)
*/
esp_err_t esp_eth_phy_802_3_write_mmd_register(phy_802_3_t *phy_802_3, uint8_t devaddr, uint16_t mmd_addr, uint32_t data);
/**
* @brief Returns address to parent IEEE 802.3 PHY object infostructure
*

View File

@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2019-2023 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2019-2024 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
@ -154,6 +154,32 @@ typedef union {
} aner_reg_t;
#define ETH_PHY_ANER_REG_ADDR (0x06)
/**
* @brief MMD Access control register
*
*/
typedef union {
struct {
uint32_t devaddr : 5; /*!< MMD address */
uint32_t reserved0 : 9; /*!< Reserved */
uint32_t function : 2; /*!< MMD function */
};
uint32_t val;
} mmdctrl_reg_t;
#define ETH_PHY_MMDCTRL_REG_ADDR (0x0D)
/**
* @brief MMD Access address register
*
*/
typedef union {
struct {
uint32_t adrdata : 16; /*!< MMD address/data */
};
uint32_t val;
} mmdad_reg_t;
#define ETH_PHY_MMDAD_REG_ADDR (0x0E)
#ifdef __cplusplus
}
#endif

View File

@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2022-2024 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
@ -469,6 +469,108 @@ err:
return ret;
}
esp_err_t esp_eth_phy_802_3_get_mmd_addr(phy_802_3_t *phy_802_3, uint8_t devaddr, uint16_t *mmd_addr)
{
esp_err_t ret = ESP_OK;
esp_eth_mediator_t *eth = phy_802_3->eth;
ESP_GOTO_ON_FALSE(devaddr <= 31, ESP_ERR_INVALID_ARG, err, TAG, "MMD device address can not be greater then 31 (0x1F)");
mmdctrl_reg_t mmdctrl;
mmdad_reg_t mmdad;
mmdctrl.function = MMD_FUNC_ADDRESS;
mmdctrl.devaddr = devaddr;
ESP_GOTO_ON_ERROR(eth->phy_reg_write(eth, phy_802_3->addr, ETH_PHY_MMDCTRL_REG_ADDR, mmdctrl.val), err, TAG, "write MMDCTRL failed");
ESP_GOTO_ON_ERROR(eth->phy_reg_read(eth, phy_802_3->addr, ETH_PHY_MMDAD_REG_ADDR, &mmdad.val), err, TAG, "read MMDAD failed");
*mmd_addr = mmdad.adrdata;
return ESP_OK;
err:
return ret;
}
esp_err_t esp_eth_phy_802_3_set_mmd_addr(phy_802_3_t *phy_802_3, uint8_t devaddr, uint16_t mmd_addr)
{
esp_err_t ret = ESP_OK;
esp_eth_mediator_t *eth = phy_802_3->eth;
ESP_GOTO_ON_FALSE(devaddr <= 31, ESP_ERR_INVALID_ARG, err, TAG, "MMD device address can not be greater then 31 (0x1F)");
mmdctrl_reg_t mmdctrl;
mmdad_reg_t mmdad;
mmdctrl.function = MMD_FUNC_ADDRESS;
mmdctrl.devaddr = devaddr;
ESP_GOTO_ON_ERROR(eth->phy_reg_write(eth, phy_802_3->addr, ETH_PHY_MMDCTRL_REG_ADDR, mmdctrl.val), err, TAG, "write MMDCTRL failed");
mmdad.adrdata = mmd_addr;
ESP_GOTO_ON_ERROR(eth->phy_reg_write(eth, phy_802_3->addr, ETH_PHY_MMDAD_REG_ADDR, mmdad.val), err, TAG, "write MMDAD failed");
return ESP_OK;
err:
return ret;
}
esp_err_t esp_eth_phy_802_3_read_mmd_data(phy_802_3_t *phy_802_3, uint8_t devaddr, esp_eth_phy_802_3_mmd_func_t function, uint32_t *data)
{
esp_err_t ret = ESP_OK;
esp_eth_mediator_t *eth = phy_802_3->eth;
ESP_GOTO_ON_FALSE(devaddr <= 31, ESP_ERR_INVALID_ARG, err, TAG, "MMD device address can not be greater then 31 (0x1F)");
ESP_GOTO_ON_FALSE(function != MMD_FUNC_ADDRESS, ESP_ERR_INVALID_ARG, err, TAG, "Invalid MMD mode for accessing data");
mmdctrl_reg_t mmdctrl;
mmdad_reg_t mmdad;
mmdctrl.devaddr = devaddr;
mmdctrl.function = function;
ESP_GOTO_ON_ERROR(eth->phy_reg_write(eth, phy_802_3->addr, ETH_PHY_MMDCTRL_REG_ADDR, mmdctrl.val), err, TAG, "write MMDCTRL failed");
ESP_GOTO_ON_ERROR(eth->phy_reg_read(eth, phy_802_3->addr, ETH_PHY_MMDAD_REG_ADDR, &mmdad.val), err, TAG, "read MMDAD failed");
*data = mmdad.adrdata;
return ESP_OK;
err:
return ret;
}
esp_err_t esp_eth_phy_802_3_write_mmd_data(phy_802_3_t *phy_802_3, uint8_t devaddr, esp_eth_phy_802_3_mmd_func_t function, uint32_t data)
{
esp_err_t ret = ESP_OK;
esp_eth_mediator_t *eth = phy_802_3->eth;
ESP_GOTO_ON_FALSE(devaddr <= 31, ESP_ERR_INVALID_ARG, err, TAG, "MMD device address can not be greater then 31 (0x1F)");
ESP_GOTO_ON_FALSE(function != MMD_FUNC_ADDRESS, ESP_ERR_INVALID_ARG, err, TAG, "Invalid MMD function for accessing data");
mmdctrl_reg_t mmdctrl;
mmdad_reg_t mmdad;
mmdctrl.devaddr = devaddr;
mmdctrl.function = function;
ESP_GOTO_ON_ERROR(eth->phy_reg_write(eth, phy_802_3->addr, ETH_PHY_MMDCTRL_REG_ADDR, mmdctrl.val), err, TAG, "write MMDCTRL failed");
mmdad.adrdata = data;
ESP_GOTO_ON_ERROR(eth->phy_reg_write(eth, phy_802_3->addr, ETH_PHY_MMDAD_REG_ADDR, mmdad.val), err, TAG, "read MMDAD failed");
return ESP_OK;
err:
return ret;
}
esp_err_t esp_eth_phy_802_3_read_mmd_register(phy_802_3_t *phy_802_3, uint8_t devaddr, uint16_t mmd_addr, uint32_t *data){
esp_err_t ret = ESP_OK;
ESP_GOTO_ON_ERROR(esp_eth_phy_802_3_set_mmd_addr(phy_802_3, devaddr, mmd_addr), err, TAG, "Set MMD address failed");
ESP_GOTO_ON_ERROR(esp_eth_phy_802_3_read_mmd_data(phy_802_3, devaddr, MMD_FUNC_DATA_NOINCR, data), err, TAG, "Read MMD data failed");
return ESP_OK;
err:
return ret;
}
esp_err_t esp_eth_phy_802_3_write_mmd_register(phy_802_3_t *phy_802_3, uint8_t devaddr, uint16_t mmd_addr, uint32_t data){
esp_err_t ret = ESP_OK;
ESP_GOTO_ON_ERROR(esp_eth_phy_802_3_set_mmd_addr(phy_802_3, devaddr, mmd_addr), err, TAG, "Set MMD address failed");
ESP_GOTO_ON_ERROR(esp_eth_phy_802_3_write_mmd_data(phy_802_3, devaddr, MMD_FUNC_DATA_NOINCR, data), err, TAG, "Write MMD data failed");
return ESP_OK;
err:
return ret;
}
esp_err_t esp_eth_phy_802_3_obj_config_init(phy_802_3_t *phy_802_3, const eth_phy_config_t *config)
{
esp_err_t ret = ESP_OK;