mirror of
https://github.com/espressif/esp-idf.git
synced 2024-10-05 20:47:46 -04:00
feat(esp_eth): added ioctl option to read/write PHY registers
LAN87xx: Added extra delay after setting PHY speed
This commit is contained in:
parent
294c2bd70d
commit
78f791d4d5
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2019-2021 Espressif Systems (Shanghai) CO LTD
|
||||
* SPDX-FileCopyrightText: 2019-2023 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
@ -121,6 +121,15 @@ typedef struct {
|
||||
esp_err_t (*write_phy_reg)(esp_eth_handle_t eth_handle, uint32_t phy_addr, uint32_t phy_reg, uint32_t reg_value);
|
||||
} esp_eth_config_t;
|
||||
|
||||
/**
|
||||
* @brief Data structure to Read/Write PHY register via ioctl API
|
||||
*
|
||||
*/
|
||||
typedef struct {
|
||||
uint32_t reg_addr; /*!< PHY register address */
|
||||
uint32_t *reg_value_p; /*!< Pointer to a memory where the register value is read/written */
|
||||
} esp_eth_phy_reg_rw_data_t;
|
||||
|
||||
/**
|
||||
* @brief Command list for ioctl API
|
||||
*
|
||||
@ -139,6 +148,8 @@ typedef enum {
|
||||
ETH_CMD_G_DUPLEX_MODE, /*!< Get Duplex mode */
|
||||
ETH_CMD_S_DUPLEX_MODE, /*!< Set Duplex mode */
|
||||
ETH_CMD_S_PHY_LOOPBACK, /*!< Set PHY loopback */
|
||||
ETH_CMD_READ_PHY_REG, /*!< Read PHY register */
|
||||
ETH_CMD_WRITE_PHY_REG, /*!< Write PHY register */
|
||||
|
||||
ETH_CMD_CUSTOM_MAC_CMDS = 0x0FFF, // Offset for start of MAC custom commands
|
||||
ETH_CMD_CUSTOM_PHY_CMDS = 0x1FFF, // Offset for start of PHY custom commands
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2019-2022 Espressif Systems (Shanghai) CO LTD
|
||||
* SPDX-FileCopyrightText: 2019-2023 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
@ -466,7 +466,23 @@ esp_err_t esp_eth_ioctl(esp_eth_handle_t hdl, esp_eth_io_cmd_t cmd, void *data)
|
||||
case ETH_CMD_S_PHY_LOOPBACK:
|
||||
ESP_GOTO_ON_FALSE(data, ESP_ERR_INVALID_ARG, err, TAG, "can't set loopback to null");
|
||||
ESP_GOTO_ON_ERROR(phy->loopback(phy, *(bool *)data), err, TAG, "configuration of phy loopback mode failed");
|
||||
|
||||
break;
|
||||
case ETH_CMD_READ_PHY_REG:
|
||||
uint32_t phy_addr;
|
||||
ESP_GOTO_ON_FALSE(data, ESP_ERR_INVALID_ARG, err, TAG, "invalid register read/write info");
|
||||
esp_eth_phy_reg_rw_data_t *phy_r_data = (esp_eth_phy_reg_rw_data_t *)data;
|
||||
ESP_GOTO_ON_FALSE(phy_r_data->reg_value_p, ESP_ERR_INVALID_ARG, err, TAG, "can't read registers to null");
|
||||
ESP_GOTO_ON_ERROR(phy->get_addr(phy, &phy_addr), err, TAG, "get phy address failed");
|
||||
ESP_GOTO_ON_ERROR(eth_driver->mediator.phy_reg_read(ð_driver->mediator,
|
||||
phy_addr, phy_r_data->reg_addr, phy_r_data->reg_value_p), err, TAG, "failed to read PHY register");
|
||||
break;
|
||||
case ETH_CMD_WRITE_PHY_REG:
|
||||
ESP_GOTO_ON_FALSE(data, ESP_ERR_INVALID_ARG, err, TAG, "invalid register read/write info");
|
||||
esp_eth_phy_reg_rw_data_t *phy_w_data = (esp_eth_phy_reg_rw_data_t *)data;
|
||||
ESP_GOTO_ON_FALSE(phy_w_data->reg_value_p, ESP_ERR_INVALID_ARG, err, TAG, "can't write registers from null");
|
||||
ESP_GOTO_ON_ERROR(phy->get_addr(phy, &phy_addr), err, TAG, "get phy address failed");
|
||||
ESP_GOTO_ON_ERROR(eth_driver->mediator.phy_reg_write(ð_driver->mediator,
|
||||
phy_addr, phy_w_data->reg_addr, *(phy_w_data->reg_value_p)), err, TAG, "failed to write PHY register");
|
||||
break;
|
||||
default:
|
||||
if (phy->custom_ioctl != NULL && cmd >= ETH_CMD_CUSTOM_PHY_CMDS) {
|
||||
|
@ -6,6 +6,8 @@
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <sys/cdefs.h>
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/task.h"
|
||||
#include "esp_log.h"
|
||||
#include "esp_check.h"
|
||||
#include "esp_eth_phy_802_3.h"
|
||||
@ -317,6 +319,19 @@ err:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static esp_err_t lan87xx_set_speed(esp_eth_phy_t *phy, eth_speed_t speed)
|
||||
{
|
||||
esp_err_t ret = ESP_OK;
|
||||
phy_802_3_t *phy_802_3 = esp_eth_phy_into_phy_802_3(phy);
|
||||
|
||||
/* It was observed that a delay needs to be introduced after setting speed and prior driver's start.
|
||||
Otherwise, the very first read of PHY registers is not valid data (0xFFFF's). */
|
||||
ESP_GOTO_ON_ERROR(esp_eth_phy_802_3_set_speed(phy_802_3, speed), err, TAG, "set speed failed");
|
||||
vTaskDelay(pdMS_TO_TICKS(10));
|
||||
err:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static esp_err_t lan87xx_init(esp_eth_phy_t *phy)
|
||||
{
|
||||
esp_err_t ret = ESP_OK;
|
||||
@ -359,6 +374,7 @@ esp_eth_phy_t *esp_eth_phy_new_lan87xx(const eth_phy_config_t *config)
|
||||
lan87xx->phy_802_3.parent.get_link = lan87xx_get_link;
|
||||
lan87xx->phy_802_3.parent.autonego_ctrl = lan87xx_autonego_ctrl;
|
||||
lan87xx->phy_802_3.parent.loopback = lan87xx_loopback;
|
||||
lan87xx->phy_802_3.parent.set_speed = lan87xx_set_speed;
|
||||
|
||||
return &lan87xx->phy_802_3.parent;
|
||||
err:
|
||||
|
Loading…
Reference in New Issue
Block a user