ethernet: support phy addr auto detect
This commit is contained in:
parent
f687cedebe
commit
197d5d7378
|
@ -6,7 +6,7 @@ set(priv_requires)
|
|||
|
||||
# If Ethernet disabled in Kconfig, this is a config-only component
|
||||
if(CONFIG_ETH_ENABLED)
|
||||
set(srcs "src/esp_eth.c")
|
||||
set(srcs "src/esp_eth.c" "src/esp_eth_phy.c")
|
||||
set(include "include")
|
||||
set(priv_requires "driver" "log") # require "driver" for using some GPIO APIs
|
||||
|
||||
|
|
|
@ -206,6 +206,19 @@ typedef enum {
|
|||
*/
|
||||
ESP_EVENT_DECLARE_BASE(ETH_EVENT);
|
||||
|
||||
/**
|
||||
* @brief Detect PHY address
|
||||
*
|
||||
* @param[in] eth: mediator of Ethernet driver
|
||||
* @param[out] detected_addr: a valid address after detection
|
||||
* @return
|
||||
* - ESP_OK: detect phy address successfully
|
||||
* - ESP_ERR_INVALID_ARG: invalid parameter
|
||||
* - ESP_ERR_NOT_FOUND: can't detect any PHY device
|
||||
* - ESP_FAIL: detect phy address failed because some error occurred
|
||||
*/
|
||||
esp_err_t esp_eth_detect_phy_addr(esp_eth_mediator_t *eth, uint32_t *detected_addr);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -21,6 +21,8 @@ extern "C" {
|
|||
#include "esp_eth_com.h"
|
||||
#include "sdkconfig.h"
|
||||
|
||||
#define ESP_ETH_PHY_ADDR_AUTO (-1)
|
||||
|
||||
/**
|
||||
* @brief Ethernet PHY
|
||||
*
|
||||
|
@ -176,7 +178,7 @@ struct esp_eth_phy_s {
|
|||
*
|
||||
*/
|
||||
typedef struct {
|
||||
uint32_t phy_addr; /*!< PHY address */
|
||||
int32_t phy_addr; /*!< PHY address, set -1 to enable PHY address detection at initialization stage */
|
||||
uint32_t reset_timeout_ms; /*!< Reset timeout value (Unit: ms) */
|
||||
uint32_t autonego_timeout_ms; /*!< Auto-negotiation timeout value (Unit: ms) */
|
||||
int reset_gpio_num; /*!< Reset GPIO number, -1 means no hardware reset */
|
||||
|
@ -186,12 +188,12 @@ typedef struct {
|
|||
* @brief Default configuration for Ethernet PHY object
|
||||
*
|
||||
*/
|
||||
#define ETH_PHY_DEFAULT_CONFIG() \
|
||||
{ \
|
||||
.phy_addr = 1, \
|
||||
.reset_timeout_ms = 100, \
|
||||
.autonego_timeout_ms = 4000, \
|
||||
.reset_gpio_num = 5, \
|
||||
#define ETH_PHY_DEFAULT_CONFIG() \
|
||||
{ \
|
||||
.phy_addr = ESP_ETH_PHY_ADDR_AUTO, \
|
||||
.reset_timeout_ms = 100, \
|
||||
.autonego_timeout_ms = 4000, \
|
||||
.reset_gpio_num = 5, \
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
44
components/esp_eth/src/esp_eth_phy.c
Normal file
44
components/esp_eth/src/esp_eth_phy.c
Normal file
|
@ -0,0 +1,44 @@
|
|||
// Copyright 2019 Espressif Systems (Shanghai) PTE LTD
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include "esp_log.h"
|
||||
#include "esp_eth.h"
|
||||
#include "eth_phy_regs_struct.h"
|
||||
|
||||
static const char *TAG = "esp_eth.phy";
|
||||
|
||||
esp_err_t esp_eth_detect_phy_addr(esp_eth_mediator_t *eth, uint32_t *detected_addr)
|
||||
{
|
||||
if (!eth || !detected_addr) {
|
||||
ESP_LOGE(TAG, "eth and detected_addr can't be null");
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
uint32_t addr_try = 0;
|
||||
uint32_t reg_value = 0;
|
||||
for (; addr_try < 16; addr_try++) {
|
||||
eth->phy_reg_read(eth, addr_try, ETH_PHY_IDR1_REG_ADDR, ®_value);
|
||||
if (reg_value != 0xFFFF && reg_value != 0x00) {
|
||||
*detected_addr = addr_try;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (addr_try < 16) {
|
||||
ESP_LOGD(TAG, "Found PHY address: %d", addr_try);
|
||||
return ESP_OK;
|
||||
} else {
|
||||
ESP_LOGE(TAG, "No PHY device detected");
|
||||
return ESP_ERR_NOT_FOUND;
|
||||
}
|
||||
}
|
|
@ -285,6 +285,10 @@ static esp_err_t dm9051_init(esp_eth_phy_t *phy)
|
|||
{
|
||||
phy_dm9051_t *dm9051 = __containerof(phy, phy_dm9051_t, parent);
|
||||
esp_eth_mediator_t *eth = dm9051->eth;
|
||||
// Detect PHY address
|
||||
if (dm9051->addr == ESP_ETH_PHY_ADDR_AUTO) {
|
||||
PHY_CHECK(esp_eth_detect_phy_addr(eth, &dm9051->addr) == ESP_OK, "Detect PHY address failed", err);
|
||||
}
|
||||
/* Power on Ethernet PHY */
|
||||
PHY_CHECK(dm9051_pwrctl(phy, true) == ESP_OK, "power control failed", err);
|
||||
/* Reset Ethernet PHY */
|
||||
|
@ -315,7 +319,6 @@ err:
|
|||
esp_eth_phy_t *esp_eth_phy_new_dm9051(const eth_phy_config_t *config)
|
||||
{
|
||||
PHY_CHECK(config, "can't set phy config to null", err);
|
||||
PHY_CHECK(config->phy_addr == 1, "dm9051's phy address can only set to 1", err);
|
||||
phy_dm9051_t *dm9051 = calloc(1, sizeof(phy_dm9051_t));
|
||||
PHY_CHECK(dm9051, "calloc dm9051 failed", err);
|
||||
dm9051->addr = config->phy_addr;
|
||||
|
|
|
@ -41,7 +41,7 @@ static const char *TAG = "dp83848";
|
|||
typedef union {
|
||||
struct {
|
||||
uint32_t link_status : 1; /* Link Status */
|
||||
uint32_t speed_status : 1; /* Link Status */
|
||||
uint32_t speed_status : 1; /* Speed Status */
|
||||
uint32_t duplex_status : 1; /* Duplex Status */
|
||||
uint32_t loopback_status : 1; /* MII Loopback */
|
||||
uint32_t auto_nego_complete : 1; /* Auto-Negotiation Complete */
|
||||
|
@ -98,17 +98,14 @@ static esp_err_t dp83848_update_link_duplex_speed(phy_dp83848_t *dp83848)
|
|||
esp_eth_mediator_t *eth = dp83848->eth;
|
||||
eth_speed_t speed = ETH_SPEED_10M;
|
||||
eth_duplex_t duplex = ETH_DUPLEX_HALF;
|
||||
bmsr_reg_t bmsr;
|
||||
physts_reg_t physts;
|
||||
PHY_CHECK(eth->phy_reg_read(eth, dp83848->addr, ETH_PHY_BMSR_REG_ADDR, &(bmsr.val)) == ESP_OK,
|
||||
"read BMSR failed", err);
|
||||
eth_link_t link = bmsr.link_status ? ETH_LINK_UP : ETH_LINK_DOWN;
|
||||
PHY_CHECK(eth->phy_reg_read(eth, dp83848->addr, ETH_PHY_STS_REG_ADDR, &(physts.val)) == ESP_OK,
|
||||
"read PHYSTS failed", err);
|
||||
eth_link_t link = physts.link_status ? ETH_LINK_UP : ETH_LINK_DOWN;
|
||||
/* check if link status changed */
|
||||
if (dp83848->link_status != link) {
|
||||
/* when link up, read negotiation result */
|
||||
if (link == ETH_LINK_UP) {
|
||||
PHY_CHECK(eth->phy_reg_read(eth, dp83848->addr, ETH_PHY_STS_REG_ADDR, &(physts.val)) == ESP_OK,
|
||||
"read PHYSTS failed", err);
|
||||
if (physts.speed_status) {
|
||||
speed = ETH_SPEED_10M;
|
||||
} else {
|
||||
|
@ -283,6 +280,10 @@ static esp_err_t dp83848_init(esp_eth_phy_t *phy)
|
|||
{
|
||||
phy_dp83848_t *dp83848 = __containerof(phy, phy_dp83848_t, parent);
|
||||
esp_eth_mediator_t *eth = dp83848->eth;
|
||||
// Detect PHY address
|
||||
if (dp83848->addr == ESP_ETH_PHY_ADDR_AUTO) {
|
||||
PHY_CHECK(esp_eth_detect_phy_addr(eth, &dp83848->addr) == ESP_OK, "Detect PHY address failed", err);
|
||||
}
|
||||
/* Power on Ethernet PHY */
|
||||
PHY_CHECK(dp83848_pwrctl(phy, true) == ESP_OK, "power control failed", err);
|
||||
/* Reset Ethernet PHY */
|
||||
|
|
|
@ -128,17 +128,14 @@ static esp_err_t ip101_update_link_duplex_speed(phy_ip101_t *ip101)
|
|||
eth_speed_t speed = ETH_SPEED_10M;
|
||||
eth_duplex_t duplex = ETH_DUPLEX_HALF;
|
||||
cssr_reg_t cssr;
|
||||
bmsr_reg_t bmsr;
|
||||
PHY_CHECK(ip101_page_select(ip101, 16) == ESP_OK, "select page 16 failed", err);
|
||||
PHY_CHECK(eth->phy_reg_read(eth, ip101->addr, ETH_PHY_BMSR_REG_ADDR, &(bmsr.val)) == ESP_OK,
|
||||
"read BMSR failed", err);
|
||||
eth_link_t link = bmsr.link_status ? ETH_LINK_UP : ETH_LINK_DOWN;
|
||||
PHY_CHECK(eth->phy_reg_read(eth, ip101->addr, ETH_PHY_CSSR_REG_ADDR, &(cssr.val)) == ESP_OK,
|
||||
"read CSSR failed", err);
|
||||
eth_link_t link = cssr.link_up ? ETH_LINK_UP : ETH_LINK_DOWN;
|
||||
/* check if link status changed */
|
||||
if (ip101->link_status != link) {
|
||||
/* when link up, read negotiation result */
|
||||
if (link == ETH_LINK_UP) {
|
||||
PHY_CHECK(eth->phy_reg_read(eth, ip101->addr, ETH_PHY_CSSR_REG_ADDR, &(cssr.val)) == ESP_OK,
|
||||
"read CSSR failed", err);
|
||||
switch (cssr.op_mode) {
|
||||
case 1: //10M Half
|
||||
speed = ETH_SPEED_10M;
|
||||
|
@ -320,6 +317,10 @@ static esp_err_t ip101_init(esp_eth_phy_t *phy)
|
|||
{
|
||||
phy_ip101_t *ip101 = __containerof(phy, phy_ip101_t, parent);
|
||||
esp_eth_mediator_t *eth = ip101->eth;
|
||||
// Detect PHY address
|
||||
if (ip101->addr == ESP_ETH_PHY_ADDR_AUTO) {
|
||||
PHY_CHECK(esp_eth_detect_phy_addr(eth, &ip101->addr) == ESP_OK, "Detect PHY address failed", err);
|
||||
}
|
||||
/* Power on Ethernet PHY */
|
||||
PHY_CHECK(ip101_pwrctl(phy, true) == ESP_OK, "power control failed", err);
|
||||
/* Reset Ethernet PHY */
|
||||
|
|
|
@ -364,6 +364,10 @@ static esp_err_t lan8720_init(esp_eth_phy_t *phy)
|
|||
{
|
||||
phy_lan8720_t *lan8720 = __containerof(phy, phy_lan8720_t, parent);
|
||||
esp_eth_mediator_t *eth = lan8720->eth;
|
||||
// Detect PHY address
|
||||
if (lan8720->addr == ESP_ETH_PHY_ADDR_AUTO) {
|
||||
PHY_CHECK(esp_eth_detect_phy_addr(eth, &lan8720->addr) == ESP_OK, "Detect PHY address failed", err);
|
||||
}
|
||||
/* Power on Ethernet PHY */
|
||||
PHY_CHECK(lan8720_pwrctl(phy, true) == ESP_OK, "power control failed", err);
|
||||
/* Reset Ethernet PHY */
|
||||
|
|
|
@ -271,6 +271,10 @@ static esp_err_t rtl8201_init(esp_eth_phy_t *phy)
|
|||
{
|
||||
phy_rtl8201_t *rtl8201 = __containerof(phy, phy_rtl8201_t, parent);
|
||||
esp_eth_mediator_t *eth = rtl8201->eth;
|
||||
// Detect PHY address
|
||||
if (rtl8201->addr == ESP_ETH_PHY_ADDR_AUTO) {
|
||||
PHY_CHECK(esp_eth_detect_phy_addr(eth, &rtl8201->addr) == ESP_OK, "Detect PHY address failed", err);
|
||||
}
|
||||
/* Power on Ethernet PHY */
|
||||
PHY_CHECK(rtl8201_pwrctl(phy, true) == ESP_OK, "power control failed", err);
|
||||
/* Reset Ethernet PHY */
|
||||
|
|
Loading…
Reference in a new issue