From 33d916b237c7e9f9c6feb0148a75f597b59819a5 Mon Sep 17 00:00:00 2001 From: Marian Buschsieweke Date: Thu, 8 Oct 2020 18:24:26 +0200 Subject: [PATCH 1/3] drivers/mii: Media-Independent Interface utils Add utilities for working with Ethernet Media-Independent Interface for use by Ethernet drivers. --- drivers/include/mii.h | 155 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 155 insertions(+) create mode 100644 drivers/include/mii.h diff --git a/drivers/include/mii.h b/drivers/include/mii.h new file mode 100644 index 0000000000..a747ea4664 --- /dev/null +++ b/drivers/include/mii.h @@ -0,0 +1,155 @@ +/* + * Copyright (C) 2020 Otto-von-Guericke-Universität Magdeburg + * + * This file is subject to the terms and conditions of the GNU Lesser General + * Public License v2.1. See the file LICENSE in the top level directory for more + * details. + */ + +/** + * @defgroup drivers_mii Ethernet Media-Independent Interface (MII) + * Utilities + * @ingroup drivers_netdev + * + * This module contains constants and helpers as library to help working with + * Ethernet PHYs connected via the Media-Independent Interface (MII) or the + * Reduced Media-Independent Interface (RMII) + * + * @{ + * + * @file + * @brief Interface definition for MII/RMII h + * + * @author Marian Buschsieweke + */ + +#ifndef MII_H +#define MII_H + +#include +#include + +#include "bitarithm.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @name Common MII Management Register Set + * + * All registers except @ref MII_BMCR and @ref MII_BMSR are extended registers. + * Support for extended registers is indicated by the @ref MII_BMSR_EXTENDED + * bit in the @ref MII_BMSR register. + * + * @{ + */ +#define MII_BMCR (0x00U) /**< Basic mode control register */ +#define MII_BMSR (0x01U) /**< Basic mode status register */ +#define MII_PHYID1 (0x02U) /**< PHY Identifier 1 */ +#define MII_PHYID2 (0x03U) /**< PHY Identifier 2 */ +#define MII_ADVERTISE (0x04U) /**< Auto-Negotiation Advertisement */ +#define MII_LPA (0x05U) /**< Link Parter Abilities */ +#define MII_EXPANSION (0x06U) /**< Auto-Negotiation Expansion */ +#define MII_ESTATUS (0x0fU) /**< Extended Status Register */ +/** @} */ + +/** + * @name Bits in the MII Basic Mode Control Register + * @{ + */ +#define MII_BMCR_RESET BIT15 /**< Set to perform PHY reset */ +#define MII_BMCR_LOOP BIT14 /**< Set to enable loopback mode */ +#define MII_BMCR_AN_ENABLE BIT12 /**< Set to enable auto-negotiation */ +#define MII_BMCR_POWER_DOWN BIT11 /**< Set to power down PHY */ +#define MII_BMCR_ISOLATE BIT10 /**< Set to electrically isolate PHY from + MII (PHY becomes inoperational) */ +#define MII_BMCR_AN_RESTART BIT9 /**< Set to restart auto-negotation */ +#define MII_BMCR_FULL_DPLX BIT8 /**< Set for full duplex */ +#define MII_BMCR_HALF_DPLX (0) /**< Set for half duplex */ +#define MII_BMCR_COLL_TEST BIT7 /**< Set to enable collision signal test */ +#define MII_BMCR_SPEED_10 (0) /**< Set speed to 10 Mbps */ +#define MII_BMCR_SPEED_100 BIT13 /**< Set speed to 100 Mbps */ +#define MII_BMCR_SPEED_1000 BIT6 /**< Set speed to 1 Gbps */ +/** @} */ + +/** + * @name Bits in the MII Basic Mode Status Register + * @{ + */ +#define MII_BMSR_100_T4 BIT15 /**< PHY supports 100BASE-T4 (half-duplex) */ +#define MII_BMSR_100_TX_F BIT14 /**< PHY supports 100BASE-TX, full duplex */ +#define MII_BMSR_100_TX_H BIT13 /**< PHY supports 100BASE-TX, half duplex */ +#define MII_BMSR_10_F BIT12 /**< PHY supports 10BASE-T, full duplex */ +#define MII_BMSR_10_H BIT11 /**< PHY supports 10BASE-T, half duplex */ +#define MII_BMSR_100_T2_F BIT10 /**< PHY supports 100BASE-T2, full duplex */ +#define MII_BMSR_100_T2_H BIT9 /**< PHY supports 100BASE-T2, half duplex */ +#define MII_BMSR_ESTATUS BIT8 /**< Set, if @ref MII_ESTATUS is + available */ +#define MII_BMSR_AN_DONE BIT5 /**< Set when auto-negotiation is done */ +#define MII_BMSR_FAULT BIT4 /**< Set when remote fault condition + is detected */ +#define MII_BMSR_HAS_AN BIT3 /**< Set if PHY can auto-negotiate */ +#define MII_BMSR_LINK BIT2 /**< Set if link is up */ +#define MII_BMSR_JABBER BIT1 /**< Set when jabber condition detected */ +#define MII_BMSR_EXTENDED BIT0 /**< Extended MII registers available */ +/** @} */ + +/** + * @brief Check if an Ethernet PHY supports 100 Mbps at full duplex + * + * @param[in] bmsr Value of the MII basic mode status register + * + * @retval true PHY supports 100 Mbps at full duplex + * @retval false PHY does not support 100 Mbps at full duplex + */ +static inline bool mii_can_100_mbps_full_dp(uint16_t bmsr) +{ + return (bmsr & (MII_BMSR_100_TX_F | MII_BMSR_100_T2_F)); +} + +/** + * @brief Check if an Ethernet PHY supports 100 Mbps at half duplex + * + * @param[in] bmsr Value of the MII basic mode status register + * + * @retval true PHY supports 100 Mbps at half duplex + * @retval false PHY does not support 100 Mbps at half duplex + */ +static inline bool mii_can_100_mbps_half_dp(uint16_t bmsr) +{ + return (bmsr & (MII_BMSR_100_T4 | MII_BMSR_100_TX_H | MII_BMSR_100_T2_H)); +} + +/** + * @brief Check if an Ethernet PHY supports 10 Mbps at full duplex + * + * @param[in] bmsr Value of the MII basic mode status register + * + * @retval true PHY supports 10 Mbps at full duplex + * @retval false PHY does not support 10 Mbps at full duplex + */ +static inline bool mii_can_10_mbps_full_dp(uint16_t bmsr) +{ + return (bmsr & MII_BMSR_10_F); +} + +/** + * @brief Check if an Ethernet PHY supports 10 Mbps at half duplex + * + * @param[in] bmsr Value of the MII basic mode status register + * + * @retval true PHY supports 10 Mbps at half duplex + * @retval false PHY does not support 10 Mbps at half duplex + */ +static inline bool mii_can_10_mbps_half_dp(uint16_t bmsr) +{ + return (bmsr & MII_BMSR_10_H); +} + +#ifdef __cplusplus +} +#endif + +#endif /* MII_H */ +/** @} */ From 62943826270c1b87ea3cc4d292a3b8f101a2eec6 Mon Sep 17 00:00:00 2001 From: Marian Buschsieweke Date: Fri, 9 Oct 2020 20:10:14 +0200 Subject: [PATCH 2/3] cpu/stm32: Use mii.h for periph_eth Use shared MII definitions and utilities instead own definitions. --- cpu/stm32/include/periph_cpu.h | 139 ++------------------------------- cpu/stm32/periph/eth.c | 7 +- drivers/include/mii.h | 24 ++++++ 3 files changed, 35 insertions(+), 135 deletions(-) diff --git a/cpu/stm32/include/periph_cpu.h b/cpu/stm32/include/periph_cpu.h index 00ef1a8162..80b1954848 100644 --- a/cpu/stm32/include/periph_cpu.h +++ b/cpu/stm32/include/periph_cpu.h @@ -1018,34 +1018,24 @@ void dma_prepare(dma_t dma, void *mem, size_t len, bool incr_mem); * @brief STM32 Ethernet configuration mode */ typedef enum { - MII = 18, /**< Configuration for MII */ - RMII = 9, /**< Configuration for RMII */ - SMI = 2, /**< Configuration for SMI */ + MII = 18, /**< Configuration for MII */ + RMII = 9, /**< Configuration for RMII */ + SMI = 2, /**< Configuration for SMI */ } eth_mode_t; -/** - * @brief STM32 Ethernet speed options - */ -typedef enum { - ETH_SPEED_10T_HD = 0x0000, - ETH_SPEED_10T_FD = 0x0100, - ETH_SPEED_100TX_HD = 0x2000, - ETH_SPEED_100TX_FD = 0x2100, -} eth_speed_t; - /** * @brief Ethernet Peripheral configuration */ typedef struct { eth_mode_t mode; /**< Select configuration mode */ uint8_t addr[6]; /**< Ethernet MAC address */ - eth_speed_t speed; /**< Speed selection */ + uint16_t speed; /**< Speed selection */ uint8_t dma; /**< Locical CMA Descriptor used for TX */ uint8_t dma_chan; /**< DMA channel used for TX */ - char phy_addr; /**< PHY address */ + uint8_t phy_addr; /**< PHY address */ gpio_t pins[]; /**< Pins to use. MII requires 18 pins, - RMII 9 and SMI 9. Not all speeds are - supported by all modes. */ + RMII 9 and SMI 9. Not all speeds are + supported by all modes. */ } eth_conf_t; /** @@ -1144,121 +1134,6 @@ typedef struct eth_dma_desc { #define TX_DESC_STAT_OWN (BIT31) /**< If set, descriptor is owned by DMA, otherwise by CPU */ /** @} */ - -/** -* @name Ethernet PHY Common Registers -* @{ -*/ -#define PHY_BMCR (0x00) -#define PHY_BSMR (0x01) -#define PHY_PHYIDR1 (0x02) -#define PHY_PHYIDR2 (0x03) -#define PHY_ANAR (0x04) -#define PHY_ANLPAR (0x05) -#define PHY_ANER (0x06) -#define PHY_ANNPTR (0x07) -/** @} */ - -/** -* @name Ethernet PHY BMCR Fields -* @{ -*/ -#define BMCR_RESET (0x8000) -#define BMCR_LOOPBACK (0x4000) -#define BMCR_SPEED_SELECT (0x2000) -#define BMCR_AN (0x1000) -#define BMCR_POWER_DOWN (0x0800) -#define BMCR_ISOLATE (0x0400) -#define BMCR_RESTART_AN (0x0200) -#define BMCR_DUPLEX_MODE (0x0100) -#define BMCR_COLLISION_TEST (0x0080) -/** @} */ - -/** -* @name Ethernet PHY BSMR Fields -* @{ -*/ -#define BSMR_100BASE_T4 (0x8000) -#define BSMR_100BASE_TX_FDUPLEX (0x4000) -#define BSMR_100BASE_TX_HDUPLEX (0x2000) -#define BSMR_10BASE_T_FDUPLEX (0x1000) -#define BSMR_10BASE_T_HDUPLEX (0x0800) -#define BSMR_NO_PREAMBLE (0x0040) -#define BSMR_AN_COMPLETE (0x0020) -#define BSMR_REMOTE_FAULT (0x0010) -#define BSMR_AN_ABILITY (0x0008) -#define BSMR_LINK_STATUS (0x0004) -#define BSMR_JABBER_DETECT (0x0002) -#define BSMR_EXTENDED_CAP (0x0001) -/** @} */ - -/** -* @name Ethernet PHY PHYIDR1 Fields -*/ -#define PHYIDR1_OUI (0xffff) - -/** -* @name Ethernet PHY PHYIDR2 Fields -* @{ -*/ -#define PHYIDR2_OUI (0xfe00) -#define PHYIDR2_MODEL (0x01f0) -#define PHYIDR2_REV (0x0007) -/** @} */ - -/** -* @name Ethernet PHY ANAR Fields -* @{ -*/ -#define ANAR_NEXT_PAGE (0x8000) -#define ANAR_REMOTE_FAULT (0x2000) -#define ANAR_PAUSE (0x0600) -#define ANAR_100BASE_T4 (0x0200) -#define ANAR_100BASE_TX_FDUPLEX (0x0100) -#define ANAR_100BASE_TX_HDUPLEX (0x0080) -#define ANAR_10BASE_T_FDUPLEX (0x0040) -#define ANAR_10BASE_T_HDUPLEX (0x0020) -#define ANAR_SELECTOR (0x000f) -/** @} */ - -/** -* @name Ethernet PHY ANLPAR Fields -* @{ -*/ -#define ANLPAR_NEXT_PAGE (0x8000) -#define ANLPAR_ACK (0x4000) -#define ANLPAR_REMOTE_FAULT (0x2000) -#define ANLPAR_PAUSE (0x0600) -#define ANLPAR_100BASE_T4 (0x0200) -#define ANLPAR_100BASE_TX_FDUPLEX (0x0100) -#define ANLPAR_100BASE_TX_HDUPLEX (0x0080) -#define ANLPAR_10BASE_T_FDUPLEX (0x0040) -#define ANLPAR_10BASE_T_HDUPLEX (0x0020) -#define ANLPAR_SELECTOR (0x000f) -/** @} */ - -/** -* @name Ethernet PHY ANNPTR Fields -* @{ -*/ -#define ANNPTR_NEXT_PAGE (0x8000) -#define ANNPTR_MSG_PAGE (0x2000) -#define ANNPTR_ACK2 (0x1000) -#define ANNPTR_TOGGLE_TX (0x0800) -#define ANNPTR_CODE (0x03ff) -/** @} */ - -/** -* @name Ethernet PHY ANER Fields -* @{ -*/ -#define ANER_PDF (0x0010) -#define ANER_LP_NEXT_PAGE_ABLE (0x0008) -#define ANER_NEXT_PAGE_ABLE (0x0004) -#define ANER_PAGE_RX (0x0002) -#define ANER_LP_AN_ABLE (0x0001) -/** @} */ - #ifdef __cplusplus } #endif diff --git a/cpu/stm32/periph/eth.c b/cpu/stm32/periph/eth.c index ce01cea889..c5d0f8bdcd 100644 --- a/cpu/stm32/periph/eth.c +++ b/cpu/stm32/periph/eth.c @@ -25,6 +25,7 @@ #include "bitarithm.h" #include "iolist.h" #include "luid.h" +#include "mii.h" #include "mutex.h" #include "net/ethernet.h" #include "net/netdev/eth.h" @@ -150,7 +151,7 @@ static inline void _mii_reg_write(uint8_t reg, uint16_t value) static inline bool _get_link_status(void) { - return (_mii_reg_read(PHY_BSMR) & BSMR_LINK_STATUS); + return (_mii_reg_read(MII_BMSR) & MII_BMSR_LINK); } static void stm32_eth_get_addr(char *out) @@ -305,7 +306,7 @@ static int stm32_eth_init(netdev_t *netdev) /* configure the PHY (standard for all PHY's) */ /* if there's no PHY, this has no effect */ - _mii_reg_write(PHY_BMCR, BMCR_RESET); + _mii_reg_write(MII_BMCR, MII_BMCR_RESET); /* speed from conf */ ETH->MACCR |= (ETH_MACCR_ROD | ETH_MACCR_IPCO | ETH_MACCR_APCS | @@ -351,7 +352,7 @@ static int stm32_eth_init(netdev_t *netdev) /* configure speed, do it at the end so the PHY had time to * reset */ - _mii_reg_write(PHY_BMCR, eth_config.speed); + _mii_reg_write(MII_BMCR, eth_config.speed); return 0; } diff --git a/drivers/include/mii.h b/drivers/include/mii.h index a747ea4664..8aca59674f 100644 --- a/drivers/include/mii.h +++ b/drivers/include/mii.h @@ -95,6 +95,30 @@ extern "C" { #define MII_BMSR_EXTENDED BIT0 /**< Extended MII registers available */ /** @} */ +/** + * @name Bits in the MII Extended Mode Advertisement Register + * @{ + */ +#define MII_ADVERTISE_100_F BIT8 /**< Advertise 100BASE-T, full duplex */ +#define MII_ADVERTISE_100_H BIT7 /**< Advertise 100BASE-T, half duplex */ +#define MII_ADVERTISE_10_F BIT6 /**< Advertise 10BASE-T, full duplex */ +#define MII_ADVERTISE_10_H BIT5 /**< Advertise 10BASE-T, half duplex */ +#define MII_ADVERTISE_100 (BIT7 | BIT8) /**< Advertise 100BASE-T */ +#define MII_ADVERTISE_10 (BIT5 | BIT6) /**< Advertise 10BASE-T */ +/** @} */ + +/** + * @name Bits in the MII Extended Mode Advertisement Register + * @{ + */ +#define MII_LPA_100_F BIT8 /**< Partner can 100BASE-T, full duplex */ +#define MII_LPA_100_H BIT7 /**< Partner can 100BASE-T, half duplex */ +#define MII_LPA_10_F BIT6 /**< Partner can 10BASE-T, full duplex */ +#define MII_LPA_10_H BIT5 /**< Partner can 10BASE-T, half duplex */ +#define MII_LPA_100 (BIT7 | BIT8) /**< Partner can 100BASE-T */ +#define MII_LPA_10 (BIT5 | BIT6) /**< Partner can 10BASE-T */ +/** @} */ + /** * @brief Check if an Ethernet PHY supports 100 Mbps at full duplex * From bedddce2635eb203f064ef676983e98f55865c38 Mon Sep 17 00:00:00 2001 From: Marian Buschsieweke Date: Fri, 9 Oct 2020 20:12:16 +0200 Subject: [PATCH 3/3] boards/nucleo-{f207zg,f746zg,f767zi}: periph_eth Use shared MII register definitions from mii.h rather than own definitions. --- boards/nucleo-f207zg/include/periph_conf.h | 3 ++- boards/nucleo-f746zg/include/periph_conf.h | 3 ++- boards/nucleo-f767zi/include/periph_conf.h | 3 ++- 3 files changed, 6 insertions(+), 3 deletions(-) diff --git a/boards/nucleo-f207zg/include/periph_conf.h b/boards/nucleo-f207zg/include/periph_conf.h index cff404180a..ca1332c0e4 100644 --- a/boards/nucleo-f207zg/include/periph_conf.h +++ b/boards/nucleo-f207zg/include/periph_conf.h @@ -35,6 +35,7 @@ #include "f2f4f7/cfg_clock_default_120.h" #include "cfg_i2c1_pb8_pb9.h" #include "cfg_usb_otg_fs.h" +#include "mii.h" #ifdef __cplusplus extern "C" { @@ -248,7 +249,7 @@ static const adc_conf_t adc_config[] = { static const eth_conf_t eth_config = { .mode = RMII, .addr = { 0 }, - .speed = ETH_SPEED_100TX_FD, + .speed = MII_BMCR_SPEED_100 | MII_BMCR_FULL_DPLX, .dma = 6, .dma_chan = 8, .phy_addr = 0x00, diff --git a/boards/nucleo-f746zg/include/periph_conf.h b/boards/nucleo-f746zg/include/periph_conf.h index 1ff6dc6d79..ce1cc54ee4 100644 --- a/boards/nucleo-f746zg/include/periph_conf.h +++ b/boards/nucleo-f746zg/include/periph_conf.h @@ -35,6 +35,7 @@ #include "cfg_rtt_default.h" #include "cfg_timer_tim2.h" #include "cfg_usb_otg_fs.h" +#include "mii.h" #ifdef __cplusplus extern "C" { @@ -219,7 +220,7 @@ static const spi_conf_t spi_config[] = { static const eth_conf_t eth_config = { .mode = RMII, .addr = { 0 }, - .speed = ETH_SPEED_100TX_FD, + .speed = MII_BMCR_SPEED_100 | MII_BMCR_FULL_DPLX, .dma = 7, .dma_chan = 8, .phy_addr = 0x00, diff --git a/boards/nucleo-f767zi/include/periph_conf.h b/boards/nucleo-f767zi/include/periph_conf.h index 440a55c8c9..46e6347ee6 100644 --- a/boards/nucleo-f767zi/include/periph_conf.h +++ b/boards/nucleo-f767zi/include/periph_conf.h @@ -35,6 +35,7 @@ #include "cfg_rtt_default.h" #include "cfg_timer_tim2.h" #include "cfg_usb_otg_fs.h" +#include "mii.h" #ifdef __cplusplus extern "C" { @@ -167,7 +168,7 @@ static const spi_conf_t spi_config[] = { static const eth_conf_t eth_config = { .mode = RMII, .addr = { 0 }, - .speed = ETH_SPEED_100TX_FD, + .speed = MII_BMCR_SPEED_100 | MII_BMCR_FULL_DPLX, .dma = 3, .dma_chan = 8, .phy_addr = 0x00,