Merge pull request #15200 from maribu/mii

drivers: Add utilities for Ethernet Media-Independent Interface (MII) and use them in STM32 `periph_eth`
This commit is contained in:
benpicco 2020-10-12 13:28:35 +02:00 committed by GitHub
commit c1b0e47e98
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 196 additions and 138 deletions

View File

@ -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,

View File

@ -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,

View File

@ -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,

View File

@ -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

View File

@ -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;
}

179
drivers/include/mii.h Normal file
View File

@ -0,0 +1,179 @@
/*
* 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 <marian.buschsieweke@ovgu.de>
*/
#ifndef MII_H
#define MII_H
#include <stdbool.h>
#include <stdint.h>
#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 */
/** @} */
/**
* @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
*
* @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 */
/** @} */