mirror of
https://github.com/espressif/esp-idf.git
synced 2024-10-05 20:47:46 -04:00
ethernet: Refactor PHY support to be part of ethernet component
Move generic PHY support into its own interface
This commit is contained in:
parent
5d6e6f79b9
commit
453722ba54
@ -1,5 +1,5 @@
|
||||
#
|
||||
# Component Makefile
|
||||
#
|
||||
# (Uses default behaviour of compiling all source files in directory, adding 'include' to include path.)
|
||||
|
||||
COMPONENT_SRCDIRS := . eth_phy
|
||||
|
@ -532,7 +532,7 @@ static void emac_set_macaddr_reg(void)
|
||||
static void emac_check_phy_init(void)
|
||||
{
|
||||
emac_config.emac_phy_check_init();
|
||||
if (emac_config.emac_phy_get_duplex_mode() == ETH_MDOE_FULLDUPLEX) {
|
||||
if (emac_config.emac_phy_get_duplex_mode() == ETH_MODE_FULLDUPLEX) {
|
||||
REG_SET_BIT(EMAC_GMACCONFIG_REG, EMAC_GMACDUPLEX);
|
||||
} else {
|
||||
REG_CLR_BIT(EMAC_GMACCONFIG_REG, EMAC_GMACDUPLEX);
|
||||
@ -547,7 +547,7 @@ static void emac_check_phy_init(void)
|
||||
emac_config.emac_flow_ctrl_partner_support = false;
|
||||
#else
|
||||
if (emac_config.emac_flow_ctrl_enable == true) {
|
||||
if (emac_config.emac_phy_get_partner_pause_enable() == true && emac_config.emac_phy_get_duplex_mode() == ETH_MDOE_FULLDUPLEX) {
|
||||
if (emac_config.emac_phy_get_partner_pause_enable() == true && emac_config.emac_phy_get_duplex_mode() == ETH_MODE_FULLDUPLEX) {
|
||||
emac_enable_flowctrl();
|
||||
emac_config.emac_flow_ctrl_partner_support = true;
|
||||
} else {
|
||||
|
75
components/ethernet/eth_phy/phy_common.c
Normal file
75
components/ethernet/eth_phy/phy_common.c
Normal file
@ -0,0 +1,75 @@
|
||||
// Copyright 2015-2016 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 "eth_phy/phy.h"
|
||||
#include "eth_phy/phy_reg.h"
|
||||
#include "driver/gpio.h"
|
||||
#include "esp_log.h"
|
||||
|
||||
static const char *TAG = "phy_common";
|
||||
|
||||
void phy_rmii_configure_data_interface_pins(void)
|
||||
{
|
||||
// CRS_DRV to GPIO27
|
||||
PIN_FUNC_SELECT(PERIPHS_IO_MUX_GPIO27_U, FUNC_GPIO27_EMAC_RX_DV);
|
||||
|
||||
// TXD0 to GPIO19
|
||||
PIN_FUNC_SELECT(PERIPHS_IO_MUX_GPIO19_U, FUNC_GPIO19_EMAC_TXD0);
|
||||
// TX_EN to GPIO21
|
||||
PIN_FUNC_SELECT(PERIPHS_IO_MUX_GPIO21_U, FUNC_GPIO21_EMAC_TX_EN);
|
||||
// TXD1 to GPIO22
|
||||
PIN_FUNC_SELECT(PERIPHS_IO_MUX_GPIO22_U, FUNC_GPIO22_EMAC_TXD1);
|
||||
// RXD0 to GPIO25
|
||||
gpio_set_direction(25, GPIO_MODE_INPUT);
|
||||
// RXD1 to GPIO26
|
||||
gpio_set_direction(26, GPIO_MODE_INPUT);
|
||||
// RMII CLK to GPIO0
|
||||
gpio_set_direction(0, GPIO_MODE_INPUT);
|
||||
}
|
||||
|
||||
void phy_rmii_smi_configure_pins(uint8_t mdc_gpio, uint8_t mdio_gpio)
|
||||
{
|
||||
gpio_matrix_out(mdc_gpio, EMAC_MDC_O_IDX, 0, 0);
|
||||
gpio_matrix_out(mdio_gpio, EMAC_MDO_O_IDX, 0, 0);
|
||||
gpio_matrix_in(mdio_gpio, EMAC_MDI_I_IDX, 0);
|
||||
}
|
||||
|
||||
void phy_mii_enable_flow_ctrl(void)
|
||||
{
|
||||
uint32_t data = esp_eth_smi_read(MII_AUTO_NEG_ADVERTISEMENT_REG);
|
||||
data |= MII_ASM_DIR | MII_PAUSE;
|
||||
esp_eth_smi_write(MII_AUTO_NEG_ADVERTISEMENT_REG, data);
|
||||
}
|
||||
|
||||
bool phy_mii_check_link_status(void)
|
||||
{
|
||||
if ((esp_eth_smi_read(MII_BASIC_MODE_STATUS_REG) & MII_LINK_STATUS)) {
|
||||
ESP_LOGD(TAG, "phy_mii_check_link_status(UP)");
|
||||
return true;
|
||||
} else {
|
||||
ESP_LOGD(TAG, "phy_mii_check_link_status(DOWN)");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool phy_mii_get_partner_pause_enable(void)
|
||||
{
|
||||
if((esp_eth_smi_read(MII_PHY_LINK_PARTNER_ABILITY_REG) & MII_PARTNER_PAUSE)) {
|
||||
ESP_LOGD(TAG, "phy_mii_get_partner_pause_enable(TRUE)");
|
||||
return true;
|
||||
} else {
|
||||
ESP_LOGD(TAG, "phy_mii_get_partner_pause_enable(FALSE)");
|
||||
return false;
|
||||
}
|
||||
}
|
157
components/ethernet/eth_phy/phy_lan8720.c
Normal file
157
components/ethernet/eth_phy/phy_lan8720.c
Normal file
@ -0,0 +1,157 @@
|
||||
// Copyright 2015-2017 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 "esp_attr.h"
|
||||
#include "esp_log.h"
|
||||
#include "esp_eth.h"
|
||||
|
||||
#include "eth_phy/phy_lan8720.h"
|
||||
#include "eth_phy/phy_reg.h"
|
||||
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/task.h"
|
||||
|
||||
/* Value of MII_PHY_IDENTIFIER_REGs for Microchip LAN8720
|
||||
* (Except for bottom 4 bits of ID2, used for model revision)
|
||||
*/
|
||||
#define LAN8720_PHY_ID1 0x0007
|
||||
#define LAN8720_PHY_ID2 0xc0f0
|
||||
|
||||
/* LAN8720-specific registers */
|
||||
#define SW_STRAP_CONTROL_REG (0x9)
|
||||
#define SW_STRAP_CONFIG_DONE BIT(15)
|
||||
#define AUTO_MDIX_ENABLE BIT(14)
|
||||
#define AUTO_NEGOTIATION_ENABLE BIT(13)
|
||||
#define AN_1 BIT(12)
|
||||
#define AN_0 BIT(11)
|
||||
#define LED_CFG BIT(10)
|
||||
#define RMII_ENHANCED_MODE BIT(9)
|
||||
|
||||
#define DEFAULT_STRAP_CONFIG (AUTO_MDIX_ENABLE|AUTO_NEGOTIATION_ENABLE|AN_1|AN_0|LED_CFG)
|
||||
|
||||
#define PHY_SPECIAL_CONTROL_STATUS_REG (0x1f)
|
||||
#define AUTO_NEGOTIATION_DONE BIT(12)
|
||||
#define SPEED_DUPLEX_INDICATION_10T_HALF 0x04
|
||||
#define SPEED_DUPLEX_INDICATION_10T_FULL 0x14
|
||||
#define SPEED_DUPLEX_INDICATION_100T_HALF 0x08
|
||||
#define SPEED_DUPLEX_INDICATION_100T_FULL 0x18
|
||||
#define SPEED_INDICATION_100T BIT(3)
|
||||
#define SPEED_INDICATION_10T BIT(2)
|
||||
#define DUPLEX_INDICATION_FULL BIT(4)
|
||||
|
||||
static const char *TAG = "lan8720";
|
||||
|
||||
void phy_lan8720_check_phy_init(void)
|
||||
{
|
||||
phy_lan8720_dump_registers();
|
||||
|
||||
while((esp_eth_smi_read(MII_BASIC_MODE_STATUS_REG) & MII_AUTO_NEGOTIATION_COMPLETE ) == 0) {
|
||||
vTaskDelay(1);
|
||||
}
|
||||
while((esp_eth_smi_read(PHY_SPECIAL_CONTROL_STATUS_REG) & AUTO_NEGOTIATION_DONE ) == 0) {
|
||||
vTaskDelay(1);
|
||||
}
|
||||
}
|
||||
|
||||
eth_speed_mode_t phy_lan8720_get_speed_mode(void)
|
||||
{
|
||||
if(esp_eth_smi_read(PHY_SPECIAL_CONTROL_STATUS_REG) & SPEED_INDICATION_100T) {
|
||||
ESP_LOGD(TAG, "phy_lan8720_get_speed_mode(100)");
|
||||
return ETH_SPEED_MODE_100M;
|
||||
} else {
|
||||
ESP_LOGD(TAG, "phy_lan8720_get_speed_mode(10)");
|
||||
return ETH_SPEED_MODE_10M;
|
||||
}
|
||||
}
|
||||
|
||||
eth_duplex_mode_t phy_lan8720_get_duplex_mode(void)
|
||||
{
|
||||
if(esp_eth_smi_read(PHY_SPECIAL_CONTROL_STATUS_REG) & DUPLEX_INDICATION_FULL) {
|
||||
ESP_LOGD(TAG, "phy_lan8720_get_duplex_mode(FULL)");
|
||||
return ETH_MODE_FULLDUPLEX;
|
||||
} else {
|
||||
ESP_LOGD(TAG, "phy_lan8720_get_duplex_mode(HALF)");
|
||||
return ETH_MODE_HALFDUPLEX;
|
||||
}
|
||||
}
|
||||
|
||||
void phy_lan8720_power_enable(bool enable)
|
||||
{
|
||||
if (enable) {
|
||||
esp_eth_smi_write(SW_STRAP_CONTROL_REG, DEFAULT_STRAP_CONFIG | SW_STRAP_CONFIG_DONE);
|
||||
// TODO: only enable if config.flow_ctrl_enable == true
|
||||
phy_mii_enable_flow_ctrl();
|
||||
}
|
||||
}
|
||||
|
||||
void phy_lan8720_init(void)
|
||||
{
|
||||
ESP_LOGD(TAG, "phy_lan8720_init()");
|
||||
phy_lan8720_dump_registers();
|
||||
|
||||
esp_eth_smi_write(MII_BASIC_MODE_CONTROL_REG, MII_SOFTWARE_RESET);
|
||||
|
||||
unsigned phy_id1, phy_id2;
|
||||
do {
|
||||
vTaskDelay(1);
|
||||
phy_id1 = esp_eth_smi_read(MII_PHY_IDENTIFIER_1_REG);
|
||||
phy_id2 = esp_eth_smi_read(MII_PHY_IDENTIFIER_2_REG);
|
||||
ESP_LOGD(TAG, "PHY ID 0x%04x 0x%04x", phy_id1, phy_id2);
|
||||
phy_id2 &= 0xFFF0; // Remove model revision code
|
||||
} while (phy_id1 != LAN8720_PHY_ID1 && phy_id2 != LAN8720_PHY_ID2);
|
||||
|
||||
esp_eth_smi_write(SW_STRAP_CONTROL_REG,
|
||||
DEFAULT_STRAP_CONFIG | SW_STRAP_CONFIG_DONE);
|
||||
|
||||
|
||||
ets_delay_us(300);
|
||||
|
||||
// TODO: only enable if config.flow_ctrl_enable == true
|
||||
phy_mii_enable_flow_ctrl();
|
||||
}
|
||||
|
||||
const eth_config_t phy_lan8720_default_ethernet_config = {
|
||||
// By default, the PHY address is 0 or 1 based on PHYAD0
|
||||
// pin. Can also be overriden in software. See datasheet
|
||||
// for defaults.
|
||||
.phy_addr = 0,
|
||||
.mac_mode = ETH_MODE_RMII,
|
||||
//Only FULLDUPLEX mode support flow ctrl now!
|
||||
.flow_ctrl_enable = true,
|
||||
.phy_init = phy_lan8720_init,
|
||||
.phy_check_init = phy_lan8720_check_phy_init,
|
||||
.phy_power_enable = phy_lan8720_power_enable,
|
||||
.phy_check_link = phy_mii_check_link_status,
|
||||
.phy_get_speed_mode = phy_lan8720_get_speed_mode,
|
||||
.phy_get_duplex_mode = phy_lan8720_get_duplex_mode,
|
||||
.phy_get_partner_pause_enable = phy_mii_get_partner_pause_enable,
|
||||
};
|
||||
|
||||
void phy_lan8720_dump_registers()
|
||||
{
|
||||
ESP_LOGD(TAG, "LAN8720 Registers:");
|
||||
ESP_LOGD(TAG, "BCR 0x%04x", esp_eth_smi_read(0x0));
|
||||
ESP_LOGD(TAG, "BSR 0x%04x", esp_eth_smi_read(0x1));
|
||||
ESP_LOGD(TAG, "PHY1 0x%04x", esp_eth_smi_read(0x2));
|
||||
ESP_LOGD(TAG, "PHY2 0x%04x", esp_eth_smi_read(0x3));
|
||||
ESP_LOGD(TAG, "ANAR 0x%04x", esp_eth_smi_read(0x4));
|
||||
ESP_LOGD(TAG, "ANLPAR 0x%04x", esp_eth_smi_read(0x5));
|
||||
ESP_LOGD(TAG, "ANER 0x%04x", esp_eth_smi_read(0x6));
|
||||
ESP_LOGD(TAG, "MCSR 0x%04x", esp_eth_smi_read(0x17));
|
||||
ESP_LOGD(TAG, "SM 0x%04x", esp_eth_smi_read(0x18));
|
||||
ESP_LOGD(TAG, "SECR 0x%04x", esp_eth_smi_read(0x26));
|
||||
ESP_LOGD(TAG, "CSIR 0x%04x", esp_eth_smi_read(0x27));
|
||||
ESP_LOGD(TAG, "ISR 0x%04x", esp_eth_smi_read(0x29));
|
||||
ESP_LOGD(TAG, "IMR 0x%04x", esp_eth_smi_read(0x30));
|
||||
ESP_LOGD(TAG, "PSCSR 0x%04x", esp_eth_smi_read(0x31));
|
||||
}
|
@ -1,26 +1,70 @@
|
||||
// Copyright 2015-2017 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 "esp_attr.h"
|
||||
#include "esp_log.h"
|
||||
#include "esp_eth.h"
|
||||
|
||||
#include "tlk110_phy.h"
|
||||
#include "eth_phy/phy_tlk110.h"
|
||||
#include "eth_phy/phy_reg.h"
|
||||
|
||||
#define DEFAULT_PHY_CONFIG (AUTO_MDIX_ENABLE|AUTO_NEGOTIATION_ENABLE|AN_1|AN_0|LED_CFG)
|
||||
void phy_dump_tlk110_registers();
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/task.h"
|
||||
|
||||
/* Value of MII_PHY_IDENTIFIER_REG for TI TLK110,
|
||||
Excluding bottom 4 bytes of ID2, used for model revision
|
||||
*/
|
||||
#define TLK110_PHY_ID1 0x2000
|
||||
#define TLK110_PHY_ID2 0xa210
|
||||
|
||||
/* TLK110-specific registers */
|
||||
#define SW_STRAP_CONTROL_REG (0x9)
|
||||
#define SW_STRAP_CONFIG_DONE BIT(15)
|
||||
#define AUTO_MDIX_ENABLE BIT(14)
|
||||
#define AUTO_NEGOTIATION_ENABLE BIT(13)
|
||||
#define AN_1 BIT(12)
|
||||
#define AN_0 BIT(11)
|
||||
#define LED_CFG BIT(10)
|
||||
#define RMII_ENHANCED_MODE BIT(9)
|
||||
|
||||
#define DEFAULT_STRAP_CONFIG (AUTO_MDIX_ENABLE|AUTO_NEGOTIATION_ENABLE|AN_1|AN_0|LED_CFG)
|
||||
|
||||
#define PHY_STATUS_REG (0x10)
|
||||
#define AUTO_NEGOTIATION_STATUS BIT(4)
|
||||
#define DUPLEX_STATUS BIT(2)
|
||||
#define SPEED_STATUS BIT(1)
|
||||
|
||||
#define CABLE_DIAGNOSTIC_CONTROL_REG (0x1e)
|
||||
#define DIAGNOSTIC_DONE BIT(1)
|
||||
|
||||
#define PHY_RESET_CONTROL_REG (0x1f)
|
||||
#define SOFTWARE_RESET BIT(15)
|
||||
|
||||
static const char *TAG = "tlk110";
|
||||
|
||||
|
||||
void phy_tlk110_check_phy_init(void)
|
||||
{
|
||||
phy_dump_tlk110_registers();
|
||||
phy_tlk110_dump_registers();
|
||||
|
||||
while((esp_eth_smi_read(BASIC_MODE_STATUS_REG) & AUTO_NEGOTIATION_COMPLETE ) != AUTO_NEGOTIATION_COMPLETE)
|
||||
{};
|
||||
while((esp_eth_smi_read(PHY_STATUS_REG) & AUTO_NEGTIATION_STATUS ) != AUTO_NEGTIATION_STATUS)
|
||||
{};
|
||||
while((esp_eth_smi_read(CABLE_DIAGNOSTIC_CONTROL_REG) & DIAGNOSTIC_DONE ) != DIAGNOSTIC_DONE)
|
||||
{};
|
||||
while((esp_eth_smi_read(MII_BASIC_MODE_STATUS_REG) & MII_AUTO_NEGOTIATION_COMPLETE ) == 0) {
|
||||
vTaskDelay(1);
|
||||
}
|
||||
while((esp_eth_smi_read(PHY_STATUS_REG) & AUTO_NEGOTIATION_STATUS ) == 0) {
|
||||
vTaskDelay(1);
|
||||
}
|
||||
while((esp_eth_smi_read(CABLE_DIAGNOSTIC_CONTROL_REG) & DIAGNOSTIC_DONE ) == 0) {
|
||||
vTaskDelay(1);
|
||||
}
|
||||
}
|
||||
|
||||
eth_speed_mode_t phy_tlk110_get_speed_mode(void)
|
||||
@ -38,74 +82,65 @@ eth_duplex_mode_t phy_tlk110_get_duplex_mode(void)
|
||||
{
|
||||
if((esp_eth_smi_read(PHY_STATUS_REG) & DUPLEX_STATUS ) == DUPLEX_STATUS) {
|
||||
ESP_LOGD(TAG, "phy_tlk110_get_duplex_mode(FULL)");
|
||||
return ETH_MDOE_FULLDUPLEX;
|
||||
return ETH_MODE_FULLDUPLEX;
|
||||
} else {
|
||||
ESP_LOGD(TAG, "phy_tlk110_get_duplex_mode(HALF)");
|
||||
return ETH_MODE_HALFDUPLEX;
|
||||
}
|
||||
}
|
||||
|
||||
bool phy_tlk110_check_phy_link_status(void)
|
||||
void phy_tlk110_power_enable(bool enable)
|
||||
{
|
||||
if ((esp_eth_smi_read(BASIC_MODE_STATUS_REG) & LINK_STATUS) == LINK_STATUS) {
|
||||
ESP_LOGD(TAG, "phy_tlk110_check_phy_link_status(UP)");
|
||||
return true;
|
||||
} else {
|
||||
ESP_LOGD(TAG, "phy_tlk110_check_phy_link_status(DOWN)");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if (enable) {
|
||||
esp_eth_smi_write(SW_STRAP_CONTROL_REG, DEFAULT_STRAP_CONFIG | SW_STRAP_CONFIG_DONE);
|
||||
|
||||
bool phy_tlk110_get_partner_pause_enable(void)
|
||||
{
|
||||
if((esp_eth_smi_read(PHY_LINK_PARTNER_ABILITY_REG) & PARTNER_PAUSE) == PARTNER_PAUSE) {
|
||||
ESP_LOGD(TAG, "phy_tlk110_get_partner_pause_enable(TRUE)");
|
||||
return true;
|
||||
} else {
|
||||
ESP_LOGD(TAG, "phy_tlk110_get_partner_pause_enable(FALSE)");
|
||||
return false;
|
||||
// TODO: only do this if config.flow_ctrl_enable == true
|
||||
phy_mii_enable_flow_ctrl();
|
||||
}
|
||||
}
|
||||
|
||||
void phy_enable_flow_ctrl(void)
|
||||
{
|
||||
uint32_t data = 0;
|
||||
data = esp_eth_smi_read(AUTO_NEG_ADVERTISEMENT_REG);
|
||||
esp_eth_smi_write(AUTO_NEG_ADVERTISEMENT_REG,data|ASM_DIR|PAUSE);
|
||||
}
|
||||
|
||||
void phy_tlk110_init(void)
|
||||
{
|
||||
ESP_LOGD(TAG, "phy_tlk110_init()");
|
||||
phy_dump_tlk110_registers();
|
||||
phy_tlk110_dump_registers();
|
||||
|
||||
esp_eth_smi_write(PHY_RESET_CONTROL_REG, SOFTWARE_RESET);
|
||||
|
||||
while (esp_eth_smi_read(PHY_IDENTIFIER_REG) != OUI_MSB_21TO6_DEF) {
|
||||
}
|
||||
unsigned phy_id1, phy_id2;
|
||||
do {
|
||||
vTaskDelay(1);
|
||||
phy_id1 = esp_eth_smi_read(MII_PHY_IDENTIFIER_1_REG);
|
||||
phy_id2 = esp_eth_smi_read(MII_PHY_IDENTIFIER_2_REG);
|
||||
ESP_LOGD(TAG, "PHY ID 0x%04x 0x%04x", phy_id1, phy_id2);
|
||||
phy_id2 &= 0xFFF0; // Remove model revision code
|
||||
} while (phy_id1 != TLK110_PHY_ID1 && phy_id2 != TLK110_PHY_ID2);
|
||||
|
||||
esp_eth_smi_write(SOFTWARE_STRAP_CONTROL_REG, DEFAULT_PHY_CONFIG |SW_STRAP_CONFIG_DONE);
|
||||
esp_eth_smi_write(SW_STRAP_CONTROL_REG,
|
||||
DEFAULT_STRAP_CONFIG | SW_STRAP_CONFIG_DONE);
|
||||
|
||||
ets_delay_us(300);
|
||||
|
||||
//if config.flow_ctrl_enable == true ,enable this
|
||||
phy_enable_flow_ctrl();
|
||||
// TODO: only do this if config.flow_ctrl_enable == true
|
||||
phy_mii_enable_flow_ctrl();
|
||||
}
|
||||
|
||||
const eth_config_t tlk110_default_ethernet_phy_config = {
|
||||
.phy_addr = CONFIG_PHY_ID,
|
||||
const eth_config_t phy_tlk110_default_ethernet_config = {
|
||||
// PHY address configured by PHYADx pins. Default value of 0x1
|
||||
// is used if all pins are unconnected.
|
||||
.phy_addr = 0x1,
|
||||
.mac_mode = ETH_MODE_RMII,
|
||||
//Only FULLDUPLEX mode support flow ctrl now!
|
||||
.flow_ctrl_enable = true,
|
||||
.phy_init = phy_tlk110_init,
|
||||
.phy_check_init = phy_tlk110_check_phy_init,
|
||||
.phy_check_link = phy_tlk110_check_phy_link_status,
|
||||
.phy_check_link = phy_mii_check_link_status,
|
||||
.phy_get_speed_mode = phy_tlk110_get_speed_mode,
|
||||
.phy_get_duplex_mode = phy_tlk110_get_duplex_mode,
|
||||
.phy_get_partner_pause_enable = phy_tlk110_get_partner_pause_enable
|
||||
.phy_get_partner_pause_enable = phy_mii_get_partner_pause_enable,
|
||||
.phy_power_enable = phy_tlk110_power_enable,
|
||||
};
|
||||
|
||||
void phy_dump_tlk110_registers()
|
||||
void phy_tlk110_dump_registers()
|
||||
{
|
||||
ESP_LOGD(TAG, "TLK110 Registers:");
|
||||
ESP_LOGD(TAG, "BMCR 0x%04x", esp_eth_smi_read(0x0));
|
@ -15,6 +15,7 @@
|
||||
#ifndef __ESP_ETH_H__
|
||||
#define __ESP_ETH_H__
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include "esp_err.h"
|
||||
|
||||
@ -24,7 +25,7 @@ extern "C" {
|
||||
|
||||
typedef enum {
|
||||
ETH_MODE_RMII = 0,
|
||||
ETH_MDOE_MII,
|
||||
ETH_MODE_MII,
|
||||
} eth_mode_t;
|
||||
|
||||
typedef enum {
|
||||
@ -34,7 +35,7 @@ typedef enum {
|
||||
|
||||
typedef enum {
|
||||
ETH_MODE_HALFDUPLEX = 0,
|
||||
ETH_MDOE_FULLDUPLEX,
|
||||
ETH_MODE_FULLDUPLEX,
|
||||
} eth_duplex_mode_t;
|
||||
|
||||
typedef enum {
|
||||
@ -102,6 +103,7 @@ typedef struct {
|
||||
|
||||
} eth_config_t;
|
||||
|
||||
|
||||
/**
|
||||
* @brief Init ethernet mac
|
||||
*
|
||||
|
59
components/ethernet/include/eth_phy/phy.h
Normal file
59
components/ethernet/include/eth_phy/phy.h
Normal file
@ -0,0 +1,59 @@
|
||||
// Copyright 2015-2016 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.
|
||||
|
||||
#pragma once
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include "esp_eth.h"
|
||||
|
||||
/* Common PHY-management functions.
|
||||
|
||||
These are not enough to drive any particular Ethernet PHY, but they provide a common configuration structure and
|
||||
management functions.
|
||||
*/
|
||||
|
||||
/* Configure fixed pins for RMII data interface.
|
||||
|
||||
This configures GPIOs 0, 19, 22, 25, 26, 27 for use with RMII
|
||||
data interface. These pins cannot be changed, and must be wired to
|
||||
ethernet functions.
|
||||
|
||||
This is not sufficient to fully configure the Ethernet PHY,
|
||||
MDIO configuration interface pins (such as SMI MDC, MDO, MDI)
|
||||
must also be configured correctly in the GPIO matrix.
|
||||
*/
|
||||
void phy_rmii_configure_data_interface_pins(void);
|
||||
|
||||
/* Configure variable pins for SMI (MDIO) ethernet functions.
|
||||
|
||||
Calling this function along with mii_configure_default_pins() will
|
||||
fully configure the GPIOs for the ethernet PHY.
|
||||
*/
|
||||
void phy_rmii_smi_configure_pins(uint8_t mdc_gpio, uint8_t mdio_gpio);
|
||||
|
||||
|
||||
/* Enable flow control in standard PHY MII register.
|
||||
*/
|
||||
void phy_mii_enable_flow_ctrl(void);
|
||||
|
||||
bool phy_mii_check_link_status(void);
|
||||
|
||||
bool phy_mii_get_partner_pause_enable(void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
67
components/ethernet/include/eth_phy/phy_lan8720.h
Normal file
67
components/ethernet/include/eth_phy/phy_lan8720.h
Normal file
@ -0,0 +1,67 @@
|
||||
// Copyright 2015-2017 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.
|
||||
|
||||
#pragma once
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include "phy.h"
|
||||
|
||||
|
||||
/* @brief Dump all LAN8720 PHY SMI configuration registers
|
||||
*
|
||||
* @note These registers are dumped at 'debug' level, so output
|
||||
* may not be visible depending on default log levels.
|
||||
*/
|
||||
void phy_lan8720_dump_registers();
|
||||
|
||||
/* @brief Default LAN8720 phy_check_init function.
|
||||
*/
|
||||
void phy_lan8720_check_phy_init(void);
|
||||
|
||||
/* @brief Default LAN8720 phy_get_speed_mode function.
|
||||
*/
|
||||
eth_speed_mode_t phy_lan8720_get_speed_mode(void);
|
||||
|
||||
/* @brief Default LAN8720 phy_get_duplex_mode function.
|
||||
*/
|
||||
eth_duplex_mode_t phy_lan8720_get_duplex_mode(void);
|
||||
|
||||
/* @brief Default LAN8720 phy_power_enable function.
|
||||
*
|
||||
* @note This function may need to be replaced with a custom function
|
||||
* if the PHY has a GPIO to enable power or start a clock.
|
||||
*
|
||||
* Consult the ethernet example to see how this is done.
|
||||
*/
|
||||
void phy_lan8720_power_enable(bool);
|
||||
|
||||
/* @brief Default LAN8720 phy_init function.
|
||||
*/
|
||||
void phy_lan8720_init(void);
|
||||
|
||||
/* @brief Default LAN8720 PHY configuration
|
||||
*
|
||||
* This configuration is not suitable for use as-is, it will need
|
||||
* to be modified for your particular PHY hardware setup.
|
||||
*
|
||||
* Consult the Ethernet example to see how this is done.
|
||||
*/
|
||||
extern const eth_config_t phy_lan8720_default_ethernet_config;
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
37
components/ethernet/include/eth_phy/phy_reg.h
Normal file
37
components/ethernet/include/eth_phy/phy_reg.h
Normal file
@ -0,0 +1,37 @@
|
||||
// Copyright 2015-2016 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.
|
||||
|
||||
#pragma once
|
||||
|
||||
/* This header contains register/bit masks for the standard
|
||||
PHY MII registers that should be supported by all PHY models.
|
||||
*/
|
||||
|
||||
#define MII_BASIC_MODE_CONTROL_REG (0x0)
|
||||
#define MII_SOFTWARE_RESET BIT(15)
|
||||
|
||||
#define MII_BASIC_MODE_STATUS_REG (0x1)
|
||||
#define MII_AUTO_NEGOTIATION_COMPLETE BIT(5)
|
||||
#define MII_LINK_STATUS BIT(2)
|
||||
|
||||
#define MII_PHY_IDENTIFIER_1_REG (0x2)
|
||||
#define MII_PHY_IDENTIFIER_2_REG (0x3)
|
||||
|
||||
#define MII_AUTO_NEG_ADVERTISEMENT_REG (0x4)
|
||||
#define MII_ASM_DIR BIT(11)
|
||||
#define MII_PAUSE BIT(10)
|
||||
|
||||
#define MII_PHY_LINK_PARTNER_ABILITY_REG (0x5)
|
||||
#define MII_PARTNER_ASM_DIR BIT(11)
|
||||
#define MII_PARTNER_PAUSE BIT(10)
|
66
components/ethernet/include/eth_phy/phy_tlk110.h
Normal file
66
components/ethernet/include/eth_phy/phy_tlk110.h
Normal file
@ -0,0 +1,66 @@
|
||||
// Copyright 2015-2017 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.
|
||||
|
||||
#pragma once
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include "phy.h"
|
||||
|
||||
/* @brief Dump all TLK110 PHY SMI configuration registers
|
||||
*
|
||||
* @note These registers are dumped at 'debug' level, so output
|
||||
* may not be visible depending on default log levels.
|
||||
*/
|
||||
void phy_tlk110_dump_registers();
|
||||
|
||||
/* @brief Default TLK110 phy_check_init function.
|
||||
*/
|
||||
void phy_tlk110_check_phy_init(void);
|
||||
|
||||
/* @brief Default TLK110 phy_get_speed_mode function.
|
||||
*/
|
||||
eth_speed_mode_t phy_tlk110_get_speed_mode(void);
|
||||
|
||||
/* @brief Default TLK110 phy_get_duplex_mode function.
|
||||
*/
|
||||
eth_duplex_mode_t phy_tlk110_get_duplex_mode(void);
|
||||
|
||||
/* @brief Default TLK110 phy_power_enable function.
|
||||
*
|
||||
* @note This function may need to be replaced with a custom function
|
||||
* if the PHY has a GPIO to enable power or start a clock.
|
||||
*
|
||||
* Consult the ethernet example to see how this is done.
|
||||
*/
|
||||
void phy_tlk110_power_enable(bool);
|
||||
|
||||
/* @brief Default TLK110 phy_init function.
|
||||
*/
|
||||
void phy_tlk110_init(void);
|
||||
|
||||
/* @brief Default TLK110 PHY configuration
|
||||
*
|
||||
* This configuration is not suitable for use as-is, it will need
|
||||
* to be modified for your particular PHY hardware setup.
|
||||
*
|
||||
* Consult the Ethernet example to see how this is done.
|
||||
*/
|
||||
extern const eth_config_t phy_tlk110_default_ethernet_config;
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
@ -13,10 +13,17 @@ Header Files
|
||||
^^^^^^^^^^^^
|
||||
|
||||
* :component_file:`ethernet/include/esp_eth.h`
|
||||
* :component_file:`ethernet/include/phy/phy.h`
|
||||
|
||||
Macros
|
||||
^^^^^^
|
||||
PHY Interfaces
|
||||
^^^^^^^^^^^^^^
|
||||
|
||||
The configured PHY model(s) are set in software by configuring the eth_config_t structure for the given PHY.
|
||||
|
||||
Headers include a default configuration structure. These default configurations will need some members overriden or re-set before they can be used for a particular PHY hardware configuration. Consult the Ethernet example to see how this is done.
|
||||
|
||||
* :component_file:`ethernet/include/phy/phy_tlk110.h`
|
||||
* :component_file:`ethernet/include/phy/phy_lan8720.h`
|
||||
|
||||
Type Definitions
|
||||
^^^^^^^^^^^^^^^^
|
||||
@ -56,3 +63,10 @@ Functions
|
||||
.. doxygenfunction:: esp_eth_smi_write
|
||||
.. doxygenfunction:: esp_eth_smi_read
|
||||
.. doxygenfunction:: esp_eth_free_rx_buf
|
||||
|
||||
|
||||
PHY Configuration Constants
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
.. doxygenvariable:: phy_tlk110_default_ethernet_config
|
||||
.. doxygenvariable:: phy_lan8720_default_ethernet_config
|
||||
|
@ -34,10 +34,12 @@
|
||||
#include "driver/gpio.h"
|
||||
|
||||
#ifdef CONFIG_PHY_LAN8720
|
||||
#include "lan8720_phy.h"
|
||||
#include "eth_phy/phy_lan8720.h"
|
||||
#define DEFAULT_ETHERNET_PHY_CONFIG phy_lan8720_default_ethernet_config
|
||||
#endif
|
||||
#ifdef CONFIG_PHY_TLK110
|
||||
#include "tlk110_phy.h"
|
||||
#include "eth_phy/phy_tlk110.h"
|
||||
#define DEFAULT_ETHERNET_PHY_CONFIG phy_tlk110_default_ethernet_config
|
||||
#endif
|
||||
|
||||
static const char *TAG = "eth_example";
|
||||
@ -46,57 +48,21 @@ static const char *TAG = "eth_example";
|
||||
#define PIN_SMI_MDC 23
|
||||
#define PIN_SMI_MDIO 18
|
||||
|
||||
void phy_tlk110_check_phy_init(void)
|
||||
{
|
||||
while((esp_eth_smi_read(BASIC_MODE_STATUS_REG) & AUTO_NEGOTIATION_COMPLETE ) != AUTO_NEGOTIATION_COMPLETE)
|
||||
{};
|
||||
while((esp_eth_smi_read(PHY_STATUS_REG) & AUTO_NEGOTIATION_STATUS ) != AUTO_NEGOTIATION_STATUS)
|
||||
{};
|
||||
while((esp_eth_smi_read(CABLE_DIAGNOSTIC_CONTROL_REG) & DIAGNOSTIC_DONE ) != DIAGNOSTIC_DONE)
|
||||
{};
|
||||
}
|
||||
/* This replaces the default PHY power on/off function with one that
|
||||
also uses a GPIO for power on/off.
|
||||
|
||||
eth_speed_mode_t phy_tlk110_get_speed_mode(void)
|
||||
If this GPIO is not connected on your device (and PHY is always powered), you can use the default PHY-specific power
|
||||
on/off function rather than overriding with this one.
|
||||
*/
|
||||
static void phy_device_power_enable_via_gpio(bool enable)
|
||||
{
|
||||
if((esp_eth_smi_read(PHY_STATUS_REG) & SPEED_STATUS ) != SPEED_STATUS) {
|
||||
return ETH_SPEED_MODE_100M;
|
||||
} else {
|
||||
return ETH_SPEED_MODE_10M;
|
||||
assert(DEFAULT_ETHERNET_PHY_CONFIG.phy_power_enable);
|
||||
|
||||
if (!enable) {
|
||||
/* Do the PHY-specific power_enable(false) function before powering down */
|
||||
DEFAULT_ETHERNET_PHY_CONFIG.phy_power_enable(false);
|
||||
}
|
||||
}
|
||||
|
||||
eth_duplex_mode_t phy_tlk110_get_duplex_mode(void)
|
||||
{
|
||||
if((esp_eth_smi_read(PHY_STATUS_REG) & DUPLEX_STATUS ) == DUPLEX_STATUS) {
|
||||
return ETH_MDOE_FULLDUPLEX;
|
||||
} else {
|
||||
return ETH_MODE_HALFDUPLEX;
|
||||
}
|
||||
}
|
||||
|
||||
bool phy_tlk110_check_phy_link_status(void)
|
||||
{
|
||||
return ((esp_eth_smi_read(BASIC_MODE_STATUS_REG) & LINK_STATUS) == LINK_STATUS );
|
||||
}
|
||||
|
||||
bool phy_tlk110_get_partner_pause_enable(void)
|
||||
{
|
||||
if((esp_eth_smi_read(PHY_LINK_PARTNER_ABILITY_REG) & PARTNER_PAUSE) == PARTNER_PAUSE) {
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
void phy_enable_flow_ctrl(void)
|
||||
{
|
||||
uint32_t data = 0;
|
||||
data = esp_eth_smi_read(AUTO_NEG_ADVERTISEMENT_REG);
|
||||
esp_eth_smi_write(AUTO_NEG_ADVERTISEMENT_REG,data|ASM_DIR|PAUSE);
|
||||
}
|
||||
|
||||
void phy_device_power_enable(bool enable)
|
||||
{
|
||||
gpio_pad_select_gpio(PIN_PHY_POWER);
|
||||
gpio_set_direction(PIN_PHY_POWER,GPIO_MODE_OUTPUT);
|
||||
if(enable == true) {
|
||||
@ -107,37 +73,27 @@ void phy_device_power_enable(bool enable)
|
||||
ESP_LOGD(TAG, "power_enable(FALSE)");
|
||||
}
|
||||
|
||||
esp_eth_smi_write(SW_STRAP_CONTROL_REG, DEFAULT_PHY_CONFIG | SW_STRAP_CONFIG_DONE);
|
||||
// Allow the power up/down to take effect, min 300us
|
||||
vTaskDelay(1);
|
||||
|
||||
ets_delay_us(300);
|
||||
|
||||
//if config.flow_ctrl_enable == true ,enable this
|
||||
phy_enable_flow_ctrl();
|
||||
if (enable) {
|
||||
/* Run the PHY-specific power on operations now the PHY has power */
|
||||
DEFAULT_ETHERNET_PHY_CONFIG.phy_power_enable(true);
|
||||
}
|
||||
}
|
||||
|
||||
void eth_gpio_config_rmii(void)
|
||||
static void eth_gpio_config_rmii(void)
|
||||
{
|
||||
//crs_dv to gpio27 ,can not change (default so not needed but physical signal must be connected)
|
||||
//PIN_FUNC_SELECT(PERIPHS_IO_MUX_GPIO27_U, FUNC_GPIO27_EMAC_RX_DV);
|
||||
|
||||
//txd0 to gpio19 ,can not change
|
||||
PIN_FUNC_SELECT(PERIPHS_IO_MUX_GPIO19_U, FUNC_GPIO19_EMAC_TXD0);
|
||||
//tx_en to gpio21 ,can not change
|
||||
PIN_FUNC_SELECT(PERIPHS_IO_MUX_GPIO21_U, FUNC_GPIO21_EMAC_TX_EN);
|
||||
//txd1 to gpio22 , can not change
|
||||
PIN_FUNC_SELECT(PERIPHS_IO_MUX_GPIO22_U, FUNC_GPIO22_EMAC_TXD1);
|
||||
//rxd0 to gpio25 , can not change
|
||||
gpio_set_direction(25, GPIO_MODE_INPUT);
|
||||
//rxd1 to gpio26 ,can not change
|
||||
gpio_set_direction(26, GPIO_MODE_INPUT);
|
||||
//rmii clk ,can not change
|
||||
gpio_set_direction(0, GPIO_MODE_INPUT);
|
||||
|
||||
//mdc to gpio23
|
||||
gpio_matrix_out(PIN_SMI_MDC, EMAC_MDC_O_IDX, 0, 0);
|
||||
//mdio to gpio18
|
||||
gpio_matrix_out(PIN_SMI_MDIO, EMAC_MDO_O_IDX, 0, 0);
|
||||
gpio_matrix_in(PIN_SMI_MDIO, EMAC_MDI_I_IDX, 0);
|
||||
// RMII data pins are fixed:
|
||||
// TXD0 = GPIO19
|
||||
// TXD1 = GPIO22
|
||||
// TX_EN = GPIO21
|
||||
// RXD0 = GPIO25
|
||||
// RXD1 = GPIO26
|
||||
// CLK == GPIO0
|
||||
phy_rmii_configure_data_interface_pins();
|
||||
// MDC is GPIO 23, MDIO is GPIO 18
|
||||
phy_rmii_smi_configure_pins(PIN_SMI_MDC, PIN_SMI_MDIO);
|
||||
}
|
||||
|
||||
void eth_task(void *pvParameter)
|
||||
@ -166,15 +122,15 @@ void app_main()
|
||||
tcpip_adapter_init();
|
||||
esp_event_loop_init(NULL, NULL);
|
||||
|
||||
#ifdef CONFIG_PHY_LAN8720
|
||||
eth_config_t config = lan8720_default_ethernet_phy_config;
|
||||
#endif
|
||||
#ifdef CONFIG_PHY_TLK110
|
||||
eth_config_t config = tlk110_default_ethernet_phy_config;
|
||||
#endif
|
||||
eth_config_t config = DEFAULT_ETHERNET_PHY_CONFIG;
|
||||
/* Set the PHY address in the example configuration */
|
||||
config.phy_addr = CONFIG_PHY_ID;
|
||||
config.gpio_config = eth_gpio_config_rmii;
|
||||
config.tcpip_input = tcpip_adapter_eth_input;
|
||||
config.phy_power_enable = phy_device_power_enable;
|
||||
|
||||
/* Replace the default 'power enable' function with an example-specific
|
||||
one that toggles a power GPIO. */
|
||||
config.phy_power_enable = phy_device_power_enable_via_gpio;
|
||||
|
||||
ret = esp_eth_init(&config);
|
||||
|
||||
|
@ -1,120 +0,0 @@
|
||||
|
||||
#include "esp_attr.h"
|
||||
#include "esp_log.h"
|
||||
#include "esp_eth.h"
|
||||
|
||||
#include "lan8720_phy.h"
|
||||
|
||||
void phy_dump_lan8720_registers();
|
||||
|
||||
static const char *TAG = "lan8720";
|
||||
|
||||
|
||||
void phy_lan8720_check_phy_init(void)
|
||||
{
|
||||
phy_dump_lan8720_registers();
|
||||
|
||||
while((esp_eth_smi_read(BASIC_MODE_STATUS_REG) & AUTO_NEGOTIATION_COMPLETE ) != AUTO_NEGOTIATION_COMPLETE)
|
||||
{};
|
||||
while((esp_eth_smi_read(PHY_SPECIAL_CONTROL_STATUS_REG) & AUTO_NEGOTIATION_DONE ) != AUTO_NEGOTIATION_DONE)
|
||||
{};
|
||||
}
|
||||
|
||||
eth_speed_mode_t phy_lan8720_get_speed_mode(void)
|
||||
{
|
||||
if(esp_eth_smi_read(PHY_SPECIAL_CONTROL_STATUS_REG) & SPEED_INDICATION_100T ) {
|
||||
ESP_LOGD(TAG, "phy_lan8720_get_speed_mode(100)");
|
||||
return ETH_SPEED_MODE_100M;
|
||||
} else {
|
||||
ESP_LOGD(TAG, "phy_lan8720_get_speed_mode(10)");
|
||||
return ETH_SPEED_MODE_10M;
|
||||
}
|
||||
}
|
||||
|
||||
eth_duplex_mode_t phy_lan8720_get_duplex_mode(void)
|
||||
{
|
||||
if(esp_eth_smi_read(PHY_SPECIAL_CONTROL_STATUS_REG) & DUPLEX_INDICATION_FULL ) {
|
||||
ESP_LOGD(TAG, "phy_lan8720_get_duplex_mode(FULL)");
|
||||
return ETH_MDOE_FULLDUPLEX;
|
||||
} else {
|
||||
ESP_LOGD(TAG, "phy_lan8720_get_duplex_mode(HALF)");
|
||||
return ETH_MODE_HALFDUPLEX;
|
||||
}
|
||||
}
|
||||
|
||||
bool phy_lan8720_check_phy_link_status(void)
|
||||
{
|
||||
if ((esp_eth_smi_read(BASIC_MODE_STATUS_REG) & LINK_STATUS) == LINK_STATUS) {
|
||||
ESP_LOGD(TAG, "phy_lan8720_check_phy_link_status(UP)");
|
||||
return true;
|
||||
} else {
|
||||
ESP_LOGD(TAG, "phy_lan8720_check_phy_link_status(DOWN)");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool phy_lan8720_get_partner_pause_enable(void)
|
||||
{
|
||||
if((esp_eth_smi_read(PHY_LINK_PARTNER_ABILITY_REG) & PARTNER_PAUSE) == PARTNER_PAUSE) {
|
||||
ESP_LOGD(TAG, "phy_lan8720_get_partner_pause_enable(TRUE)");
|
||||
return true;
|
||||
} else {
|
||||
ESP_LOGD(TAG, "phy_lan8720_get_partner_pause_enable(FALSE)");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
void phy_enable_flow_ctrl(void)
|
||||
{
|
||||
uint32_t data = 0;
|
||||
data = esp_eth_smi_read(AUTO_NEG_ADVERTISEMENT_REG);
|
||||
esp_eth_smi_write(AUTO_NEG_ADVERTISEMENT_REG,data|ASM_DIR|PAUSE);
|
||||
}
|
||||
|
||||
void phy_lan8720_init(void)
|
||||
{
|
||||
ESP_LOGD(TAG, "phy_lan8720_init()");
|
||||
phy_dump_lan8720_registers();
|
||||
|
||||
esp_eth_smi_write(BASIC_MODE_CONTROL_REG, SOFTWARE_RESET);
|
||||
|
||||
while (esp_eth_smi_read(PHY_IDENTIFIER_REG) != OUI_MSB_21TO6_DEF) {
|
||||
}
|
||||
|
||||
ets_delay_us(300);
|
||||
|
||||
//if config.flow_ctrl_enable == true ,enable this
|
||||
phy_enable_flow_ctrl();
|
||||
}
|
||||
|
||||
const eth_config_t lan8720_default_ethernet_phy_config = {
|
||||
.phy_addr = CONFIG_PHY_ID,
|
||||
.mac_mode = ETH_MODE_RMII,
|
||||
//Only FULLDUPLEX mode support flow ctrl now!
|
||||
.flow_ctrl_enable = true,
|
||||
.phy_init = phy_lan8720_init,
|
||||
.phy_check_init = phy_lan8720_check_phy_init,
|
||||
.phy_check_link = phy_lan8720_check_phy_link_status,
|
||||
.phy_get_speed_mode = phy_lan8720_get_speed_mode,
|
||||
.phy_get_duplex_mode = phy_lan8720_get_duplex_mode,
|
||||
.phy_get_partner_pause_enable = phy_lan8720_get_partner_pause_enable
|
||||
};
|
||||
|
||||
void phy_dump_lan8720_registers()
|
||||
{
|
||||
ESP_LOGD(TAG, "LAN8720 Registers:");
|
||||
ESP_LOGD(TAG, "BCR 0x%04x", esp_eth_smi_read(0x0));
|
||||
ESP_LOGD(TAG, "BSR 0x%04x", esp_eth_smi_read(0x1));
|
||||
ESP_LOGD(TAG, "PHY1 0x%04x", esp_eth_smi_read(0x2));
|
||||
ESP_LOGD(TAG, "PHY2 0x%04x", esp_eth_smi_read(0x3));
|
||||
ESP_LOGD(TAG, "ANAR 0x%04x", esp_eth_smi_read(0x4));
|
||||
ESP_LOGD(TAG, "ANLPAR 0x%04x", esp_eth_smi_read(0x5));
|
||||
ESP_LOGD(TAG, "ANER 0x%04x", esp_eth_smi_read(0x6));
|
||||
ESP_LOGD(TAG, "MCSR 0x%04x", esp_eth_smi_read(0x17));
|
||||
ESP_LOGD(TAG, "SM 0x%04x", esp_eth_smi_read(0x18));
|
||||
ESP_LOGD(TAG, "SECR 0x%04x", esp_eth_smi_read(0x26));
|
||||
ESP_LOGD(TAG, "CSIR 0x%04x", esp_eth_smi_read(0x27));
|
||||
ESP_LOGD(TAG, "ISR 0x%04x", esp_eth_smi_read(0x29));
|
||||
ESP_LOGD(TAG, "IMR 0x%04x", esp_eth_smi_read(0x30));
|
||||
ESP_LOGD(TAG, "PSCSR 0x%04x", esp_eth_smi_read(0x31));
|
||||
}
|
@ -1,37 +0,0 @@
|
||||
#define BASIC_MODE_CONTROL_REG (0x0)
|
||||
#define SOFTWARE_RESET BIT(15)
|
||||
|
||||
#define BASIC_MODE_STATUS_REG (0x1)
|
||||
#define AUTO_NEGOTIATION_COMPLETE BIT(5)
|
||||
#define LINK_STATUS BIT(2)
|
||||
|
||||
#define PHY_IDENTIFIER_REG (0x2)
|
||||
#define OUI_MSB_21TO6_DEF 0x0007
|
||||
|
||||
#define AUTO_NEG_ADVERTISEMENT_REG (0x4)
|
||||
#define ASM_DIR BIT(11)
|
||||
#define PAUSE BIT(10)
|
||||
|
||||
#define PHY_LINK_PARTNER_ABILITY_REG (0x5)
|
||||
#define PARTNER_PAUSE BIT(10)
|
||||
|
||||
#define SOFTWARE_STRAP_CONTROL_REG (0x9)
|
||||
#define SW_STRAP_CONFIG_DONE BIT(15)
|
||||
#define AUTO_MDIX_ENABLE BIT(14)
|
||||
#define AUTO_NEGOTIATION_ENABLE BIT(13)
|
||||
#define AN_1 BIT(12)
|
||||
#define AN_0 BIT(11)
|
||||
#define LED_CFG BIT(10)
|
||||
#define RMII_ENHANCED_MODE BIT(9)
|
||||
|
||||
#define PHY_SPECIAL_CONTROL_STATUS_REG (0x1f)
|
||||
#define AUTO_NEGOTIATION_DONE BIT(12)
|
||||
#define SPEED_DUPLEX_INDICATION_10T_HALF 0x04
|
||||
#define SPEED_DUPLEX_INDICATION_10T_FULL 0x14
|
||||
#define SPEED_DUPLEX_INDICATION_100T_HALF 0x08
|
||||
#define SPEED_DUPLEX_INDICATION_100T_FULL 0x18
|
||||
#define SPEED_INDICATION_100T BIT(3)
|
||||
#define SPEED_INDICATION_10T BIT(2)
|
||||
#define DUPLEX_INDICATION_FULL BIT(4)
|
||||
|
||||
extern const eth_config_t lan8720_default_ethernet_phy_config;
|
@ -1,36 +0,0 @@
|
||||
#define BASIC_MODE_STATUS_REG (0x1)
|
||||
#define AUTO_NEGOTIATION_COMPLETE BIT(5)
|
||||
#define LINK_STATUS BIT(2)
|
||||
|
||||
#define PHY_IDENTIFIER_REG (0x2)
|
||||
#define OUI_MSB_21TO6_DEF 0x2000
|
||||
|
||||
#define AUTO_NEG_ADVERTISEMENT_REG (0x4)
|
||||
#define ASM_DIR BIT(11)
|
||||
#define PAUSE BIT(10)
|
||||
|
||||
#define PHY_LINK_PARTNER_ABILITY_REG (0x5)
|
||||
#define PARTNER_ASM_DIR BIT(11)
|
||||
#define PARTNER_PAUSE BIT(10)
|
||||
|
||||
#define SW_STRAP_CONTROL_REG (0x9)
|
||||
#define SW_STRAP_CONFIG_DONE BIT(15)
|
||||
#define AUTO_MDIX_ENABLE BIT(14)
|
||||
#define AUTO_NEGOTIATION_ENABLE BIT(13)
|
||||
#define AN_1 BIT(12)
|
||||
#define AN_0 BIT(11)
|
||||
#define LED_CFG BIT(10)
|
||||
#define RMII_ENHANCED_MODE BIT(9)
|
||||
|
||||
#define PHY_STATUS_REG (0x10)
|
||||
#define AUTO_NEGOTIATION_STATUS BIT(4)
|
||||
#define DUPLEX_STATUS BIT(2)
|
||||
#define SPEED_STATUS BIT(1)
|
||||
|
||||
#define CABLE_DIAGNOSTIC_CONTROL_REG (0x1e)
|
||||
#define DIAGNOSTIC_DONE BIT(1)
|
||||
|
||||
#define PHY_RESET_CONTROL_REG (0x1f)
|
||||
#define SOFTWARE_RESET BIT(15)
|
||||
|
||||
extern const eth_config_t tlk110_default_ethernet_phy_config;
|
Loading…
x
Reference in New Issue
Block a user