diff --git a/connectivity/drivers/emac/CompositeEMAC.md b/connectivity/drivers/emac/CompositeEMAC.md index 42d89ea57ea..e66be58a6f2 100644 --- a/connectivity/drivers/emac/CompositeEMAC.md +++ b/connectivity/drivers/emac/CompositeEMAC.md @@ -63,12 +63,12 @@ Unlike the MAC driver and the DMA, the PHY driver does not need to be subclassed ```json5 "MY_TARGET": { - "nsapi.emac-phy-model": "LAN8742", + "nsapi.emac-phy-model": "LAN87XX", "nsapi.emac-phy-mdio-address": 0 } ``` -This will work out of the box, as long as `LAN8742` names a PHY driver defined in PhyDrivers.cpp. Individual PHY models will generally need their own drivers, since often PHYs have errata that need to be worked around or need other configuration that isn't defined in the standard. However, GenericEthPhy allows implementing the absolute minimum amount of logic per-phy as possible! +This will work out of the box, as long as `LAN87XX` names a PHY driver defined in PhyDrivers.cpp. Individual PHY models will generally need their own drivers, since often PHYs have errata that need to be worked around or need other configuration that isn't defined in the standard. However, GenericEthPhy allows implementing the absolute minimum amount of logic per-phy as possible! Since user boards may want to use a different ethernet PHY, the driver can be customized in an application by overriding the `mbed::get_eth_phy_driver` weak function to return a different driver class. This might look something like diff --git a/connectivity/drivers/emac/TARGET_STM/TARGET_STM32F4/TARGET_NUCLEO_F439ZI/stm32f4_eth_init.c b/connectivity/drivers/emac/TARGET_STM/TARGET_STM32F4/TARGET_NUCLEO_F439ZI/stm32f4_eth_init.c index b8958960c51..b356adb767c 100644 --- a/connectivity/drivers/emac/TARGET_STM/TARGET_STM32F4/TARGET_NUCLEO_F439ZI/stm32f4_eth_init.c +++ b/connectivity/drivers/emac/TARGET_STM/TARGET_STM32F4/TARGET_NUCLEO_F439ZI/stm32f4_eth_init.c @@ -35,6 +35,8 @@ void EthInitPinmappings(void) { + GPIO_InitTypeDef GPIO_InitStructure; + /* Enable GPIOs clocks */ __HAL_RCC_GPIOA_CLK_ENABLE(); __HAL_RCC_GPIOB_CLK_ENABLE(); diff --git a/connectivity/drivers/emac/TARGET_STM/TARGET_STM32F7/TARGET_DISCO_F746NG/stm32f7_eth_init.c b/connectivity/drivers/emac/TARGET_STM/TARGET_STM32F7/TARGET_DISCO_F746NG/stm32f7_eth_init.c index a4112a8a62f..dd985ce7753 100644 --- a/connectivity/drivers/emac/TARGET_STM/TARGET_STM32F7/TARGET_DISCO_F746NG/stm32f7_eth_init.c +++ b/connectivity/drivers/emac/TARGET_STM/TARGET_STM32F7/TARGET_DISCO_F746NG/stm32f7_eth_init.c @@ -34,6 +34,8 @@ void EthInitPinmappings(void) { + GPIO_InitTypeDef GPIO_InitStructure; + /* Enable GPIOs clocks */ __HAL_RCC_GPIOA_CLK_ENABLE(); __HAL_RCC_GPIOC_CLK_ENABLE(); diff --git a/connectivity/drivers/emac/TARGET_STM/TARGET_STM32F7/TARGET_NUCLEO_F746ZG/stm32f7_eth_init.c b/connectivity/drivers/emac/TARGET_STM/TARGET_STM32F7/TARGET_NUCLEO_F746ZG/stm32f7_eth_init.c index 41a44fb8120..31ac9878c63 100644 --- a/connectivity/drivers/emac/TARGET_STM/TARGET_STM32F7/TARGET_NUCLEO_F746ZG/stm32f7_eth_init.c +++ b/connectivity/drivers/emac/TARGET_STM/TARGET_STM32F7/TARGET_NUCLEO_F746ZG/stm32f7_eth_init.c @@ -35,6 +35,8 @@ void EthInitPinmappings(void) { + GPIO_InitTypeDef GPIO_InitStructure; + /* Enable GPIOs clocks */ __HAL_RCC_GPIOA_CLK_ENABLE(); __HAL_RCC_GPIOB_CLK_ENABLE(); diff --git a/connectivity/drivers/emac/TARGET_STM/TARGET_STM32F7/TARGET_NUCLEO_F756ZG/stm32f7_eth_init.c b/connectivity/drivers/emac/TARGET_STM/TARGET_STM32F7/TARGET_NUCLEO_F756ZG/stm32f7_eth_init.c index 41a44fb8120..31ac9878c63 100644 --- a/connectivity/drivers/emac/TARGET_STM/TARGET_STM32F7/TARGET_NUCLEO_F756ZG/stm32f7_eth_init.c +++ b/connectivity/drivers/emac/TARGET_STM/TARGET_STM32F7/TARGET_NUCLEO_F756ZG/stm32f7_eth_init.c @@ -35,6 +35,8 @@ void EthInitPinmappings(void) { + GPIO_InitTypeDef GPIO_InitStructure; + /* Enable GPIOs clocks */ __HAL_RCC_GPIOA_CLK_ENABLE(); __HAL_RCC_GPIOB_CLK_ENABLE(); diff --git a/connectivity/drivers/emac/include/GenericEthPhy.h b/connectivity/drivers/emac/include/GenericEthPhy.h index a05aea62313..b8156d3fc02 100644 --- a/connectivity/drivers/emac/include/GenericEthPhy.h +++ b/connectivity/drivers/emac/include/GenericEthPhy.h @@ -85,9 +85,10 @@ class GenericEthPhy : public mbed::CompositeEMAC::PHYDriver { /// 24-bit OUI of the organization that produced the ethernet PHY. uint32_t OUI; - /// 5-bit model number of the phy. This plus the OUI is used to verify that the + /// Range of 5-bit model number of the phy. This plus the OUI is used to verify that the /// chip in hardware matches what's expected. - uint8_t model; + uint8_t model_min; + uint8_t model_max; /// MDIO address of the phy chip. /// NOTE: 0 is *supposed* to be reserved as the general call address but lots of phy chips use diff --git a/connectivity/drivers/emac/sources/GenericEthPhy.cpp b/connectivity/drivers/emac/sources/GenericEthPhy.cpp index b1873e0be13..928c23928ea 100644 --- a/connectivity/drivers/emac/sources/GenericEthPhy.cpp +++ b/connectivity/drivers/emac/sources/GenericEthPhy.cpp @@ -49,7 +49,8 @@ CompositeEMAC::ErrCode GenericEthPhy::init() { // ID1 should be the upper 18 MSBits of the OUI, with the two MSBits chopped off. const uint16_t expectedID1 = config.OUI >> 6; // Bits 10-15 of ID2 are the 6 LSBits of the OUI. Bits 4-9 are the model number. Bits 0-3 are the revision and may be anything. - const uint16_t expectedID2 = (config.OUI << 10) | (config.model << 4); + const uint16_t expectedID2Min = (config.OUI << 10) | (config.model_min << 4); + const uint16_t expectedID2Max = (config.OUI << 10) | (config.model_max << 4); const uint16_t expectedID2Mask = 0xFFF0; // Read IDs @@ -58,16 +59,16 @@ CompositeEMAC::ErrCode GenericEthPhy::init() { FORWARD_ERR(mac->mdioRead(config.address, GenPhyRegs::PHYIDR1, actualID1)); FORWARD_ERR(mac->mdioRead(config.address, GenPhyRegs::PHYIDR2, actualID2)); - if(actualID1 == expectedID1 && (actualID2 & expectedID2Mask) == expectedID2) { + if(actualID1 == expectedID1 && (actualID2 & expectedID2Mask) >= expectedID2Min && (actualID2 & expectedID2Mask) <= expectedID2Max) { // OK - tr_info("Detected ethernet PHY at MDIO addr %" PRIu8 " with OUI 0x%" PRIx32 ", model 0x%" PRIx8 ", and revision number %" PRIu8, config.address, config.OUI, config.model, actualID2 % 0xF); + tr_info("Detected ethernet PHY at MDIO addr %" PRIu8 " with OUI 0x%" PRIx32 ", model 0x%" PRIx8 ", and revision number %" PRIu8, config.address, config.OUI, (actualID2 >> 4) & 0x3F, actualID2 % 0xF); } else if(actualID1 == std::numeric_limits::max() && actualID2 == std::numeric_limits::max()) { tr_error("Got all 0xFFs when reading Ethernet PHY. Since MDIO is an open drain bus, this means the phy is not connected or not responding."); return CompositeEMAC::ErrCode::PHY_NOT_RESPONDING; } else { - tr_error("Ethernet phy model number verification mismatch. Expected PHYIDR1 = %" PRIu16 ", PHYIDR2 = %" PRIu16 ", got PHYIDR1 = %" PRIu16 ", PHYIDR2 = %" PRIu16 " [note: bottom 4 bits of PHYIDR2 ignored]", expectedID1, expectedID2, actualID1, actualID2); + tr_error("Ethernet phy model number verification mismatch. Expected PHYIDR1 = %" PRIu16 ", PHYIDR2 = %" PRIu16 "-%" PRIu16 ", got PHYIDR1 = %" PRIu16 ", PHYIDR2 = %" PRIu16 " [note: bottom 4 bits of PHYIDR2 ignored]", expectedID1, expectedID2Min, expectedID2Max, actualID1, actualID2); return CompositeEMAC::ErrCode::PHY_NOT_RESPONDING; } diff --git a/connectivity/drivers/emac/sources/PhyDrivers.cpp b/connectivity/drivers/emac/sources/PhyDrivers.cpp index f0f47e7a192..3f239bf0bfc 100644 --- a/connectivity/drivers/emac/sources/PhyDrivers.cpp +++ b/connectivity/drivers/emac/sources/PhyDrivers.cpp @@ -20,15 +20,17 @@ namespace mbed { using namespace std::chrono_literals; -namespace LAN8742 { +namespace LAN87XX { -/// Driver for the Microchip LAN8742 PHY +/// Driver for the Microchip LAN8742 & LAN8720 PHY /// Datasheet: https://ww1.microchip.com/downloads/aemDocuments/documents/OTH/ProductDocuments/DataSheets/DS_LAN8742_00001989A.pdf +/// https://ww1.microchip.com/downloads/en/devicedoc/8720a.pdf /// @{ inline constexpr GenericEthPhy::Config DefaultConfig = { .OUI = 0x1F0, - .model = 0x13, + .model_min = 0x0F, // LAN8720 + .model_max = 0x13, // LAN8742 .address = 0, // Address set via PHYAD[0] strap. }; @@ -52,7 +54,8 @@ namespace IP101G { inline constexpr GenericEthPhy::Config DefaultConfig = { .OUI = 0x90C3, - .model = 0x5, + .model_min = 0x5, + .model_max = 0x5, .address = 1, // Address set via strapping pins, 1 is used on Nuvoton boards }; @@ -68,6 +71,32 @@ namespace IP101G { } +namespace DP8384X { + + /// Driver for the DP8384X PHY + /// Datasheet: https://www.ti.com/lit/ds/symlink/dp83848c.pdf + /// https://www.ti.com/lit/ds/symlink/dp83849i.pdf + /// @{ + + inline constexpr GenericEthPhy::Config DefaultConfig = { + .OUI = 0x80017, + .model_min = 0x09, // DP83848VV, DP83849I + .model_max = 0x0A, // DP83848C/I/VYB/YB + .address = 1, // Address set via PHYAD[0] strap. + }; + + class Driver : public GenericEthPhy { + public: + explicit Driver(GenericEthPhy::Config const & config = DefaultConfig): + GenericEthPhy(config) + {} + }; + + + /// @} + +} + /** * @brief Obtains the PHY driver for Ethernet port 0. * diff --git a/connectivity/netsocket/mbed_lib.json5 b/connectivity/netsocket/mbed_lib.json5 index c3e7e12418a..bc2f091410c 100644 --- a/connectivity/netsocket/mbed_lib.json5 +++ b/connectivity/netsocket/mbed_lib.json5 @@ -113,7 +113,7 @@ }, "MCU_STM32": { // First-party STM32 boards generally use a LAN8742 PHY at MDIO address 0 - "nsapi.emac-phy-model": "LAN8742", + "nsapi.emac-phy-model": "LAN87XX", "nsapi.emac-phy-mdio-address": 0 }, "MCU_M480": {