diff --git a/components/esp_eth/CMakeLists.txt b/components/esp_eth/CMakeLists.txt index 21b64cc7a9..90e69186ad 100644 --- a/components/esp_eth/CMakeLists.txt +++ b/components/esp_eth/CMakeLists.txt @@ -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 diff --git a/components/esp_eth/include/esp_eth_com.h b/components/esp_eth/include/esp_eth_com.h index 2f40c645b7..ad7aa185f8 100644 --- a/components/esp_eth/include/esp_eth_com.h +++ b/components/esp_eth/include/esp_eth_com.h @@ -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 diff --git a/components/esp_eth/include/esp_eth_phy.h b/components/esp_eth/include/esp_eth_phy.h index 2e27350e3a..4aedff1112 100644 --- a/components/esp_eth/include/esp_eth_phy.h +++ b/components/esp_eth/include/esp_eth_phy.h @@ -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, \ } /** diff --git a/components/esp_eth/src/esp_eth_phy.c b/components/esp_eth/src/esp_eth_phy.c new file mode 100644 index 0000000000..d77812f907 --- /dev/null +++ b/components/esp_eth/src/esp_eth_phy.c @@ -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 +#include +#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; + } +} diff --git a/components/esp_eth/src/esp_eth_phy_dm9051.c b/components/esp_eth/src/esp_eth_phy_dm9051.c index c3775f2042..286a7baa56 100644 --- a/components/esp_eth/src/esp_eth_phy_dm9051.c +++ b/components/esp_eth/src/esp_eth_phy_dm9051.c @@ -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; diff --git a/components/esp_eth/src/esp_eth_phy_dp83848.c b/components/esp_eth/src/esp_eth_phy_dp83848.c index fbb41391a9..9bcfeeda18 100644 --- a/components/esp_eth/src/esp_eth_phy_dp83848.c +++ b/components/esp_eth/src/esp_eth_phy_dp83848.c @@ -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 */ diff --git a/components/esp_eth/src/esp_eth_phy_ip101.c b/components/esp_eth/src/esp_eth_phy_ip101.c index 6b16c2188a..c3ea8a1b01 100644 --- a/components/esp_eth/src/esp_eth_phy_ip101.c +++ b/components/esp_eth/src/esp_eth_phy_ip101.c @@ -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 */ diff --git a/components/esp_eth/src/esp_eth_phy_lan8720.c b/components/esp_eth/src/esp_eth_phy_lan8720.c index d7d62bb781..b6480a6649 100644 --- a/components/esp_eth/src/esp_eth_phy_lan8720.c +++ b/components/esp_eth/src/esp_eth_phy_lan8720.c @@ -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 */ diff --git a/components/esp_eth/src/esp_eth_phy_rtl8201.c b/components/esp_eth/src/esp_eth_phy_rtl8201.c index 814563fdc1..2a5808a22c 100644 --- a/components/esp_eth/src/esp_eth_phy_rtl8201.c +++ b/components/esp_eth/src/esp_eth_phy_rtl8201.c @@ -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 */