mirror of
https://github.com/apache/nuttx.git
synced 2026-05-22 05:42:05 +08:00
net/mdio: add mdio bus
Currently the mdio communication is part of the monolithic 'full netdevs'. This commit serves as an way to add modularity for the netdevs drivers. A new upperhalf/lowerhalf mdio device comes with this commit that manages the data transfer ofer mdio interface. Signed-off-by: Luchian Mihai <luchiann.mihai@gmail.com>
This commit is contained in:
@@ -12,6 +12,7 @@ Network Support
|
||||
nat.rst
|
||||
netdev.rst
|
||||
netdriver.rst
|
||||
mdio.rst
|
||||
netguardsize.rst
|
||||
netlink.rst
|
||||
slip.rst
|
||||
|
||||
@@ -0,0 +1,73 @@
|
||||
.. _mdio_bus:
|
||||
|
||||
.. include:: /substitutions.rst
|
||||
|
||||
=================
|
||||
MDIO Bus Driver
|
||||
=================
|
||||
|
||||
The NuttX MDIO bus driver provides a standardized interface for communicating with Ethernet PHY (Physical Layer) transceivers.
|
||||
It employs a classic upper-half/lower-half architecture to abstract hardware-specific logic from the generic MDIO protocol,
|
||||
which is currently compliant with Clause 22 of the IEEE 802.3 standard.
|
||||
The primary implementation of the upper-half can be found in ``drivers/net/mdio.c``.
|
||||
|
||||
Driver Architecture
|
||||
===================
|
||||
|
||||
The MDIO driver framework serves as an intermediary layer between a network device driver and the physical bus.
|
||||
The intended operational model is ``netdev -> phydev -> mdio``, where the network device communicates with a dedicated PHY driver,
|
||||
which in turn uses the MDIO bus driver for low-level hardware access.
|
||||
Direct interaction between the network device and the MDIO bus is discouraged.
|
||||
|
||||
Upper-Half Implementation
|
||||
-------------------------
|
||||
|
||||
The upper-half driver contains the core logic for the MDIO bus, including bus locking mechanisms to ensure safe transactions.
|
||||
It exposes a generic API for managing the bus lifecycle and is capable of handling multiple, independent MDIO bus instances concurrently.
|
||||
This abstracts implementation details from both the PHY driver and the underlying hardware-specific code.
|
||||
|
||||
Lower-Half Implementation
|
||||
-------------------------
|
||||
|
||||
A lower-half MDIO driver serves as a thin layer that maps the generic operations defined by the upper-half to hardware-specific register manipulations.
|
||||
It is not intended to contain complex logic, but rather to provide a direct translation for bus operations.
|
||||
|
||||
Implementing a Lower-Half Driver
|
||||
================================
|
||||
|
||||
Integrating MDIO support for new hardware requires the implementation of a lower-half driver.
|
||||
The contract between the upper and lower halves is defined in ``include/nuttx/net/mdio.h`` and is centered around two key structures.
|
||||
|
||||
Key Data Structures
|
||||
-------------------
|
||||
|
||||
1. ``struct mdio_ops_s``: A structure containing function pointers that the lower-half driver must implement to perform hardware-level operations.
|
||||
* ``read``: Performs a Clause 22 MDIO read operation.
|
||||
* ``write``: Performs a Clause 22 MDIO write operation.
|
||||
* ``reset``: An optional function to execute a hardware-specific PHY reset.
|
||||
|
||||
2. ``struct mdio_lowerhalf_s``: The container for the lower-half instance, which holds a pointer to the ``mdio_ops_s`` vtable
|
||||
and an optional private data pointer for the driver's internal state.
|
||||
|
||||
Registration and Unregistration
|
||||
-------------------------------
|
||||
|
||||
The board-level initialization logic is responsible for instantiating the lower-half driver and registering it with the upper-half via the ``mdio_register()`` function.
|
||||
Each call to this function with a distinct lower-half driver creates a new, unique bus handle, allowing the system to manage several MDIO buses concurrently.
|
||||
|
||||
.. code-block:: c
|
||||
|
||||
FAR struct mdio_dev_s *mdio_register(FAR struct mdio_lowerhalf_s *lower);
|
||||
|
||||
This function accepts the lower-half instance and returns an opaque handle (``FAR struct mdio_dev_s *``),
|
||||
which is subsequently used by the PHY driver to interact with the bus.
|
||||
|
||||
When a bus instance is no longer required, it should be deallocated by calling the ``mdio_unregister()`` function to ensure proper cleanup of resources.
|
||||
|
||||
.. code-block:: c
|
||||
|
||||
int mdio_unregister(FAR struct mdio_dev_s *dev);
|
||||
|
||||
This function takes the handle returned by ``mdio_register()`` and releases the associated bus instance.
|
||||
|
||||
A (mostly) complete reference implementation for a lower-half driver is available in ``arch/arm/src/stm32h7/stm32_mdio.c``.
|
||||
@@ -185,6 +185,10 @@ if(CONFIG_STM32H7_ETHMAC)
|
||||
list(APPEND SRCS stm32_ethernet.c)
|
||||
endif()
|
||||
|
||||
if(CONFIG_MDIO_BUS)
|
||||
list(APPEND SRCS stm32_mdio.c)
|
||||
endif()
|
||||
|
||||
if(CONFIG_SENSORS_QENCODER)
|
||||
list(APPEND SRCS stm32_qencoder.c)
|
||||
endif()
|
||||
|
||||
@@ -187,6 +187,10 @@ ifeq ($(CONFIG_STM32H7_ETHMAC),y)
|
||||
CHIP_CSRCS += stm32_ethernet.c
|
||||
endif
|
||||
|
||||
ifeq ($(CONFIG_MDIO_BUS),y)
|
||||
CHIP_CSRCS += stm32_mdio.c
|
||||
endif
|
||||
|
||||
ifeq ($(CONFIG_SENSORS_QENCODER),y)
|
||||
CHIP_CSRCS += stm32_qencoder.c
|
||||
endif
|
||||
|
||||
@@ -64,6 +64,7 @@
|
||||
#include "stm32_rcc.h"
|
||||
#include "stm32_ethernet.h"
|
||||
#include "stm32_uid.h"
|
||||
#include "stm32_mdio.h"
|
||||
|
||||
#include <arch/board/board.h>
|
||||
|
||||
@@ -690,6 +691,8 @@ struct stm32_ethmac_s
|
||||
uint16_t segments; /* RX segment count */
|
||||
uint16_t inflight; /* Number of TX transfers "in_flight" */
|
||||
sq_queue_t freeb; /* The free buffer list */
|
||||
|
||||
struct mdio_bus_s *mdio;
|
||||
};
|
||||
|
||||
/****************************************************************************
|
||||
@@ -808,16 +811,13 @@ static void stm32_rxdescinit(struct stm32_ethmac_s *priv,
|
||||
#if defined(CONFIG_NETDEV_PHY_IOCTL) && defined(CONFIG_ARCH_PHY_INTERRUPT)
|
||||
static int stm32_phyintenable(struct stm32_ethmac_s *priv);
|
||||
#endif
|
||||
static int stm32_phyread(uint16_t phydevaddr, uint16_t phyregaddr,
|
||||
uint16_t *value);
|
||||
static int stm32_phywrite(uint16_t phydevaddr, uint16_t phyregaddr,
|
||||
uint16_t value, uint16_t mask);
|
||||
|
||||
#ifdef CONFIG_ETH0_PHY_DM9161
|
||||
static inline int stm32_dm9161(struct stm32_ethmac_s *priv);
|
||||
#endif
|
||||
static int stm32_phyinit(struct stm32_ethmac_s *priv);
|
||||
#ifdef CONFIG_STM32H7_ETHMAC_REGDEBUG
|
||||
static void stm32_phyregdump(void);
|
||||
static void stm32_phyregdump(struct stm32_ethmac_s *priv);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
@@ -3038,7 +3038,8 @@ static int stm32_ioctl(struct net_driver_s *dev, int cmd, unsigned long arg)
|
||||
{
|
||||
struct mii_ioctl_data_s *req =
|
||||
(struct mii_ioctl_data_s *)((uintptr_t)arg);
|
||||
ret = stm32_phyread(req->phy_id, req->reg_num, &req->val_out);
|
||||
ret = mdio_read(priv->mdio,
|
||||
req->phy_id, req->reg_num, &req->val_out);
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -3046,8 +3047,8 @@ static int stm32_ioctl(struct net_driver_s *dev, int cmd, unsigned long arg)
|
||||
{
|
||||
struct mii_ioctl_data_s *req =
|
||||
(struct mii_ioctl_data_s *)((uintptr_t)arg);
|
||||
ret = stm32_phywrite(req->phy_id, req->reg_num, req->val_in,
|
||||
0xffff);
|
||||
ret = mdio_write(priv->mdio,
|
||||
req->phy_id, req->reg_num, req->val_in);
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -3091,148 +3092,6 @@ static int stm32_phyintenable(struct stm32_ethmac_s *priv)
|
||||
}
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Function: stm32_phyread
|
||||
*
|
||||
* Description:
|
||||
* Read a PHY register.
|
||||
*
|
||||
* Parameters:
|
||||
* phydevaddr - The PHY device address
|
||||
* phyregaddr - The PHY register address
|
||||
* value - The location to return the 16-bit PHY register value.
|
||||
*
|
||||
* Returned Value:
|
||||
* OK on success; Negated errno on failure.
|
||||
*
|
||||
* Assumptions:
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static int stm32_phyread(uint16_t phydevaddr, uint16_t phyregaddr,
|
||||
uint16_t *value)
|
||||
{
|
||||
volatile uint32_t timeout;
|
||||
uint32_t regval;
|
||||
|
||||
/* Configure the MACMDIOAR register, preserving CSR Clock Range CR[3:0]
|
||||
* bits
|
||||
*/
|
||||
|
||||
regval = stm32_getreg(STM32_ETH_MACMDIOAR);
|
||||
regval &= ETH_MACMDIOAR_CR_MASK;
|
||||
|
||||
/* Set the PHY device address, PHY register address, and set the buy bit.
|
||||
* the ETH_MACMDIOAR_GOC == 3, indicating a read operation.
|
||||
*/
|
||||
|
||||
regval |= (((uint32_t)phydevaddr << ETH_MACMDIOAR_PA_SHIFT) &
|
||||
ETH_MACMDIOAR_PA_MASK);
|
||||
regval |= (((uint32_t)phyregaddr << ETH_MACMDIOAR_RDA_SHIFT) &
|
||||
ETH_MACMDIOAR_RDA_MASK);
|
||||
regval |= ETH_MACMDIOAR_MB | ETH_MACMDIOAR_GOC_READ;
|
||||
|
||||
stm32_putreg(regval, STM32_ETH_MACMDIOAR);
|
||||
|
||||
/* Wait for the transfer to complete */
|
||||
|
||||
for (timeout = 0; timeout < PHY_READ_TIMEOUT; timeout++)
|
||||
{
|
||||
if ((stm32_getreg(STM32_ETH_MACMDIOAR) & ETH_MACMDIOAR_MB) == 0)
|
||||
{
|
||||
*value = (uint16_t)stm32_getreg(STM32_ETH_MACMDIODR);
|
||||
return OK;
|
||||
}
|
||||
}
|
||||
|
||||
ninfo("MII transfer timed out: phydevaddr: %04x phyregaddr: %04x\n",
|
||||
phydevaddr, phyregaddr);
|
||||
|
||||
return -ETIMEDOUT;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Function: stm32_phywrite
|
||||
*
|
||||
* Description:
|
||||
* Write to a PHY register.
|
||||
*
|
||||
* Parameters:
|
||||
* phydevaddr - The PHY device address
|
||||
* phyregaddr - The PHY register address
|
||||
* value - The 16-bit value to write to the PHY register value.
|
||||
*
|
||||
* Returned Value:
|
||||
* OK on success; Negated errno on failure.
|
||||
*
|
||||
* Assumptions:
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static int stm32_phywrite(uint16_t phydevaddr, uint16_t phyregaddr,
|
||||
uint16_t set, uint16_t clear)
|
||||
{
|
||||
volatile uint32_t timeout;
|
||||
uint32_t regval;
|
||||
uint16_t value;
|
||||
|
||||
/* Configure the MACMDIOAR register, preserving CSR Clock Range CR[3:0]
|
||||
* bits
|
||||
*/
|
||||
|
||||
regval = stm32_getreg(STM32_ETH_MACMDIOAR);
|
||||
regval &= ETH_MACMDIOAR_CR_MASK;
|
||||
|
||||
/* Read the existing register value, if clear mask is given */
|
||||
|
||||
if (clear != 0xffff)
|
||||
{
|
||||
if (stm32_phyread(phydevaddr, phyregaddr, &value) != OK)
|
||||
{
|
||||
return -ETIMEDOUT;
|
||||
}
|
||||
|
||||
value &= ~clear;
|
||||
value |= set;
|
||||
}
|
||||
else
|
||||
{
|
||||
value = set;
|
||||
}
|
||||
|
||||
/* Set the PHY device address, PHY register address, and set the busy bit.
|
||||
* the ETH_MACMDIOAR_GOC == 1, indicating a write operation.
|
||||
*/
|
||||
|
||||
regval |= (((uint32_t)phydevaddr << ETH_MACMDIOAR_PA_SHIFT) &
|
||||
ETH_MACMDIOAR_PA_MASK);
|
||||
regval |= (((uint32_t)phyregaddr << ETH_MACMDIOAR_RDA_SHIFT) &
|
||||
ETH_MACMDIOAR_RDA_MASK);
|
||||
regval |= (ETH_MACMDIOAR_MB | ETH_MACMDIOAR_GOC_WRITE);
|
||||
|
||||
/* Write the value into the MACMDIODR register before setting the new
|
||||
* MACMDIOAR register value.
|
||||
*/
|
||||
|
||||
stm32_putreg(value, STM32_ETH_MACMDIODR);
|
||||
stm32_putreg(regval, STM32_ETH_MACMDIOAR);
|
||||
|
||||
/* Wait for the transfer to complete */
|
||||
|
||||
for (timeout = 0; timeout < PHY_WRITE_TIMEOUT; timeout++)
|
||||
{
|
||||
if ((stm32_getreg(STM32_ETH_MACMDIOAR) & ETH_MACMDIOAR_MB) == 0)
|
||||
{
|
||||
return OK;
|
||||
}
|
||||
}
|
||||
|
||||
ninfo("MII transfer timed out: phydevaddr: %04x phyregaddr: %04x value: "
|
||||
"%04x\n", phydevaddr, phyregaddr, value);
|
||||
|
||||
return -ETIMEDOUT;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Function: stm32_dm9161
|
||||
*
|
||||
@@ -3261,7 +3120,8 @@ static inline int stm32_dm9161(struct stm32_ethmac_s *priv)
|
||||
* indication that check if the DM9161 PHY CHIP is not ready.
|
||||
*/
|
||||
|
||||
ret = stm32_phyread(CONFIG_STM32H7_PHYADDR, MII_PHYID1, &phyval);
|
||||
ret = mdio_read(priv->mdio,
|
||||
CONFIG_STM32H7_PHYADDR, MII_PHYID1, &phyval);
|
||||
if (ret < 0)
|
||||
{
|
||||
nerr("ERROR: Failed to read the PHY ID1: %d\n", ret);
|
||||
@@ -3283,7 +3143,8 @@ static inline int stm32_dm9161(struct stm32_ethmac_s *priv)
|
||||
* Register 16
|
||||
*/
|
||||
|
||||
ret = stm32_phyread(CONFIG_STM32H7_PHYADDR, 16, &phyval);
|
||||
ret = mdio_read(priv->mdio,
|
||||
CONFIG_STM32H7_PHYADDR, 16, &phyval);
|
||||
if (ret < 0)
|
||||
{
|
||||
nerr("ERROR: Failed to read the PHY Register 0x10: %d\n", ret);
|
||||
@@ -3318,7 +3179,7 @@ static inline int stm32_dm9161(struct stm32_ethmac_s *priv)
|
||||
****************************************************************************/
|
||||
|
||||
#ifdef CONFIG_STM32H7_ETHMAC_REGDEBUG
|
||||
static void stm32_phyregdump()
|
||||
static void stm32_phyregdump(struct stm32_ethmac_s *priv)
|
||||
{
|
||||
uint16_t phyval;
|
||||
int ret;
|
||||
@@ -3326,7 +3187,8 @@ static void stm32_phyregdump()
|
||||
|
||||
for (i = 0; i < 0x20; i++)
|
||||
{
|
||||
ret = stm32_phyread(CONFIG_STM32H7_PHYADDR, i, &phyval);
|
||||
ret = mdio_read(priv->mdio,
|
||||
CONFIG_STM32H7_PHYADDR, i, &phyval);
|
||||
if (ret < 0)
|
||||
{
|
||||
nerr("ERROR: Failed to read reg: 0%2x\n", i);
|
||||
@@ -3379,8 +3241,8 @@ static int stm32_phyinit(struct stm32_ethmac_s *priv)
|
||||
|
||||
/* Put the PHY in reset mode */
|
||||
|
||||
ret = stm32_phywrite(CONFIG_STM32H7_PHYADDR, MII_MCR, MII_MCR_RESET,
|
||||
MII_MCR_RESET);
|
||||
ret = mdio_write(priv->mdio,
|
||||
CONFIG_STM32H7_PHYADDR, MII_MCR, MII_MCR_RESET);
|
||||
if (ret < 0)
|
||||
{
|
||||
nerr("ERROR: Failed to reset the PHY: %d\n", ret);
|
||||
@@ -3393,7 +3255,8 @@ static int stm32_phyinit(struct stm32_ethmac_s *priv)
|
||||
up_mdelay(10);
|
||||
to -= 10;
|
||||
phyval = 0xffff;
|
||||
ret = stm32_phyread(CONFIG_STM32H7_PHYADDR, MII_MCR, &phyval);
|
||||
ret = mdio_read(priv->mdio,
|
||||
CONFIG_STM32H7_PHYADDR, MII_MCR, &phyval);
|
||||
|
||||
ninfo("MII_MCR: phyval: %u ret: %d\n", phyval, ret);
|
||||
}
|
||||
@@ -3409,7 +3272,8 @@ static int stm32_phyinit(struct stm32_ethmac_s *priv)
|
||||
ninfo("Phy reset in %d ms\n", PHY_RESET_DELAY - to);
|
||||
}
|
||||
|
||||
ret = stm32_phyread(CONFIG_STM32H7_PHYADDR, MII_PHYID1, &phyval);
|
||||
ret = mdio_read(priv->mdio,
|
||||
CONFIG_STM32H7_PHYADDR, MII_PHYID1, &phyval);
|
||||
|
||||
if (ret < 0)
|
||||
{
|
||||
@@ -3426,7 +3290,8 @@ static int stm32_phyinit(struct stm32_ethmac_s *priv)
|
||||
|
||||
ninfo("MII_PHYID1: phyval: %u ret: %d\n", phyval, ret);
|
||||
|
||||
ret = stm32_phyread(CONFIG_STM32H7_PHYADDR, MII_PHYID2, &phyval);
|
||||
ret = mdio_read(priv->mdio,
|
||||
CONFIG_STM32H7_PHYADDR, MII_PHYID2, &phyval);
|
||||
|
||||
if (ret < 0)
|
||||
{
|
||||
@@ -3444,7 +3309,7 @@ static int stm32_phyinit(struct stm32_ethmac_s *priv)
|
||||
ninfo("MII_PHYID2: phyval: %u ret: %d\n", phyval, ret);
|
||||
|
||||
#ifdef CONFIG_STM32H7_ETHMAC_REGDEBUG
|
||||
stm32_phyregdump();
|
||||
stm32_phyregdump(priv);
|
||||
#endif
|
||||
|
||||
/* Special workaround for the Davicom DM9161 PHY is required. */
|
||||
@@ -3464,7 +3329,8 @@ static int stm32_phyinit(struct stm32_ethmac_s *priv)
|
||||
|
||||
for (timeout = 0; timeout < PHY_RETRY_TIMEOUT; timeout++)
|
||||
{
|
||||
ret = stm32_phyread(CONFIG_STM32H7_PHYADDR, MII_MSR, &phyval);
|
||||
ret = mdio_read(priv->mdio,
|
||||
CONFIG_STM32H7_PHYADDR, MII_MSR, &phyval);
|
||||
if (ret < 0)
|
||||
{
|
||||
nerr("ERROR: Failed to read the PHY MSR: %d\n", ret);
|
||||
@@ -3487,8 +3353,8 @@ static int stm32_phyinit(struct stm32_ethmac_s *priv)
|
||||
|
||||
/* Enable auto-negotiation */
|
||||
|
||||
ret = stm32_phywrite(CONFIG_STM32H7_PHYADDR, MII_MCR, MII_MCR_ANENABLE,
|
||||
MII_MCR_ANENABLE);
|
||||
ret = mdio_write(priv->mdio,
|
||||
CONFIG_STM32H7_PHYADDR, MII_MCR, MII_MCR_ANENABLE);
|
||||
if (ret < 0)
|
||||
{
|
||||
nerr("ERROR: Failed to enable auto-negotiation: %d\n", ret);
|
||||
@@ -3499,7 +3365,8 @@ static int stm32_phyinit(struct stm32_ethmac_s *priv)
|
||||
|
||||
for (timeout = 0; timeout < PHY_RETRY_TIMEOUT; timeout++)
|
||||
{
|
||||
ret = stm32_phyread(CONFIG_STM32H7_PHYADDR, MII_MSR, &phyval);
|
||||
ret = mdio_read(priv->mdio,
|
||||
CONFIG_STM32H7_PHYADDR, MII_MSR, &phyval);
|
||||
if (ret < 0)
|
||||
{
|
||||
nerr("ERROR: Failed to read the PHY MSR: %d\n", ret);
|
||||
@@ -3521,7 +3388,8 @@ static int stm32_phyinit(struct stm32_ethmac_s *priv)
|
||||
|
||||
/* Read the result of the auto-negotiation from the PHY-specific register */
|
||||
|
||||
ret = stm32_phyread(CONFIG_STM32H7_PHYADDR, CONFIG_STM32H7_PHYSR, &phyval);
|
||||
ret = mdio_read(priv->mdio,
|
||||
CONFIG_STM32H7_PHYADDR, CONFIG_STM32H7_PHYSR, &phyval);
|
||||
if (ret < 0)
|
||||
{
|
||||
nerr("ERROR: Failed to read PHY status register\n");
|
||||
@@ -4306,6 +4174,15 @@ static inline int stm32_ethinitialize(int intf)
|
||||
|
||||
stm32_ethgpioconfig(priv);
|
||||
|
||||
/* Initialize the MDIO device */
|
||||
|
||||
priv->mdio = stm32_mdio_bus_initialize();
|
||||
if (!priv->mdio)
|
||||
{
|
||||
nerr("ERROR: Failed to initialize MDIO bus\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
/* Attach the IRQ to the driver */
|
||||
|
||||
if (irq_attach(STM32_IRQ_ETH, stm32_interrupt, NULL))
|
||||
|
||||
@@ -0,0 +1,232 @@
|
||||
/****************************************************************************
|
||||
* arch/arm/src/stm32h7/stm32_mdio.c
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership. The
|
||||
* ASF licenses this file to you 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.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Included Files
|
||||
****************************************************************************/
|
||||
|
||||
#include <arm_internal.h>
|
||||
|
||||
/****************************************************************************
|
||||
* Pre-processor Definitions
|
||||
****************************************************************************/
|
||||
|
||||
#ifdef CONFIG_STM32H7_ETHMAC_REGDEBUG
|
||||
static uint32_t stm32_getreg(uint32_t addr);
|
||||
static void stm32_putreg(uint32_t val, uint32_t addr);
|
||||
static void stm32_checksetup(void);
|
||||
#else
|
||||
# define stm32_getreg(addr) getreg32(addr)
|
||||
# define stm32_putreg(val,addr) putreg32(val,addr)
|
||||
# define stm32_checksetup()
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Included Files
|
||||
****************************************************************************/
|
||||
|
||||
#include <nuttx/mutex.h>
|
||||
#include <nuttx/config.h>
|
||||
|
||||
#include <debug.h>
|
||||
#include <errno.h>
|
||||
#include <inttypes.h>
|
||||
|
||||
#include "stm32_mdio.h"
|
||||
#include "hardware/stm32_ethernet.h"
|
||||
|
||||
/****************************************************************************
|
||||
* Private Types
|
||||
****************************************************************************/
|
||||
|
||||
struct stm32_mdio_bus_s
|
||||
{
|
||||
struct mdio_lowerhalf_s *lower;
|
||||
|
||||
/* MDIO bus timeout in milliseconds */
|
||||
|
||||
int timeout;
|
||||
};
|
||||
|
||||
/****************************************************************************
|
||||
* Private Function Prototypes
|
||||
****************************************************************************/
|
||||
|
||||
static int stm32_c22_read(struct mdio_lowerhalf_s *dev, uint8_t phydev,
|
||||
uint8_t regaddr, uint16_t *value);
|
||||
|
||||
static int stm32_c22_write(struct mdio_lowerhalf_s *dev, uint8_t phydev,
|
||||
uint8_t regaddr, uint16_t value);
|
||||
|
||||
/****************************************************************************
|
||||
* Private Data
|
||||
****************************************************************************/
|
||||
|
||||
const struct mdio_ops_s g_stm32_mdio_ops =
|
||||
{
|
||||
.read = stm32_c22_read,
|
||||
.write = stm32_c22_write,
|
||||
.reset = NULL,
|
||||
};
|
||||
|
||||
struct mdio_lowerhalf_s g_stm32_mdio_lowerhalf =
|
||||
{
|
||||
.ops = &g_stm32_mdio_ops
|
||||
};
|
||||
|
||||
struct stm32_mdio_bus_s g_stm32_mdio_bus =
|
||||
{
|
||||
.lower = &g_stm32_mdio_lowerhalf,
|
||||
.timeout = 10
|
||||
};
|
||||
|
||||
/****************************************************************************
|
||||
* Private Functions
|
||||
****************************************************************************/
|
||||
|
||||
static int stm32_c22_read(struct mdio_lowerhalf_s *dev, uint8_t phydev,
|
||||
uint8_t regaddr, uint16_t *value)
|
||||
{
|
||||
int to;
|
||||
uint32_t regval;
|
||||
|
||||
int retval = -ETIMEDOUT;
|
||||
struct stm32_mdio_bus_s *priv = (struct stm32_mdio_bus_s *)dev;
|
||||
|
||||
/* Configure the MACMDIOAR register, preserving CSR Clock Range CR[3:0]
|
||||
* bits
|
||||
*/
|
||||
|
||||
regval = stm32_getreg(STM32_ETH_MACMDIOAR);
|
||||
regval &= ETH_MACMDIOAR_CR_MASK;
|
||||
|
||||
/* Set the PHY device address, PHY register address, and set the buy bit.
|
||||
* the ETH_MACMDIOAR_GOC == 3, indicating a read operation.
|
||||
*/
|
||||
|
||||
regval |= (((uint32_t)phydev << ETH_MACMDIOAR_PA_SHIFT) &
|
||||
ETH_MACMDIOAR_PA_MASK);
|
||||
regval |= (((uint32_t)regaddr << ETH_MACMDIOAR_RDA_SHIFT) &
|
||||
ETH_MACMDIOAR_RDA_MASK);
|
||||
regval |= ETH_MACMDIOAR_MB | ETH_MACMDIOAR_GOC_READ;
|
||||
|
||||
stm32_putreg(regval, STM32_ETH_MACMDIOAR);
|
||||
|
||||
/* Wait for the transfer to complete */
|
||||
|
||||
for (to = priv->timeout; to >= 0; to--)
|
||||
{
|
||||
if ((stm32_getreg(STM32_ETH_MACMDIOAR) & ETH_MACMDIOAR_MB) == 0)
|
||||
{
|
||||
*value = (uint16_t)stm32_getreg(STM32_ETH_MACMDIODR);
|
||||
retval = OK;
|
||||
break;
|
||||
}
|
||||
|
||||
up_mdelay(5);
|
||||
}
|
||||
|
||||
if (to <= 0)
|
||||
{
|
||||
ninfo("MII transfer timed out: phydev: %04x regaddr: %04x\n",
|
||||
phydev, regaddr);
|
||||
}
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
static int stm32_c22_write(struct mdio_lowerhalf_s *dev, uint8_t phydev,
|
||||
uint8_t regaddr, uint16_t value)
|
||||
{
|
||||
int to;
|
||||
uint32_t regval;
|
||||
|
||||
int retval = -ETIMEDOUT;
|
||||
struct stm32_mdio_bus_s *priv = (struct stm32_mdio_bus_s *)dev;
|
||||
|
||||
/* Configure the MACMDIOAR register, preserving CSR Clock Range CR[3:0]
|
||||
* bits
|
||||
*/
|
||||
|
||||
regval = stm32_getreg(STM32_ETH_MACMDIOAR);
|
||||
regval &= ETH_MACMDIOAR_CR_MASK;
|
||||
|
||||
/* Read the existing register value, if clear mask is given */
|
||||
|
||||
/* Set the PHY device address, PHY register address, and set the busy bit.
|
||||
* the ETH_MACMDIOAR_GOC == 1, indicating a write operation.
|
||||
*/
|
||||
|
||||
regval |= (((uint32_t)phydev << ETH_MACMDIOAR_PA_SHIFT) &
|
||||
ETH_MACMDIOAR_PA_MASK);
|
||||
regval |= (((uint32_t)phydev << ETH_MACMDIOAR_RDA_SHIFT) &
|
||||
ETH_MACMDIOAR_RDA_MASK);
|
||||
regval |= (ETH_MACMDIOAR_MB | ETH_MACMDIOAR_GOC_WRITE);
|
||||
|
||||
/* Write the value into the MACMDIODR register before setting the new
|
||||
* MACMDIOAR register value.
|
||||
*/
|
||||
|
||||
stm32_putreg(value, STM32_ETH_MACMDIODR);
|
||||
stm32_putreg(regval, STM32_ETH_MACMDIOAR);
|
||||
|
||||
/* Wait for the transfer to complete */
|
||||
|
||||
for (to = priv->timeout; to >= 0; to--)
|
||||
{
|
||||
if ((stm32_getreg(STM32_ETH_MACMDIOAR) & ETH_MACMDIOAR_MB) == 0)
|
||||
{
|
||||
retval = OK;
|
||||
break;
|
||||
}
|
||||
|
||||
up_mdelay(5);
|
||||
}
|
||||
|
||||
if (to <= 0)
|
||||
{
|
||||
ninfo("MII transfer timed out: phydevaddr: %04x phyregaddr: %04x"
|
||||
"value: %04x\n", phydev, regaddr, value);
|
||||
}
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Public Functions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: stm32_mdio_bus_initialize
|
||||
*
|
||||
* Description:
|
||||
* Initialize the MDIO bus
|
||||
*
|
||||
* Returned Value:
|
||||
* Initialized MDIO bus structure or NULL on failure
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
struct mdio_bus_s *stm32_mdio_bus_initialize(void)
|
||||
{
|
||||
return mdio_register(&g_stm32_mdio_lowerhalf);
|
||||
}
|
||||
@@ -0,0 +1,58 @@
|
||||
/****************************************************************************
|
||||
* arch/arm/src/stm32h7/stm32_mdio.h
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership. The
|
||||
* ASF licenses this file to you 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.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef __ARCH_ARM_SRC_STM32H7_STM32_MDIO_H
|
||||
#define __ARCH_ARM_SRC_STM32H7_STM32_MDIO_H
|
||||
|
||||
/****************************************************************************
|
||||
* Included Files
|
||||
****************************************************************************/
|
||||
|
||||
#include <nuttx/config.h>
|
||||
#include <nuttx/net/mdio.h>
|
||||
|
||||
/****************************************************************************
|
||||
* Pre-processor Definitions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Public Types
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Public Function Prototypes
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: stm32_mdio_bus_initialize
|
||||
*
|
||||
* Description:
|
||||
* Initialize the MDIO bus
|
||||
*
|
||||
* Returned Value:
|
||||
* Initialized MDIO bus structure or NULL on failure
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
struct mdio_bus_s *stm32_mdio_bus_initialize(void);
|
||||
|
||||
#endif /* __ARCH_ARM_SRC_STM32H7_STM32_MDIO_H */
|
||||
@@ -29,6 +29,10 @@ if(CONFIG_NET)
|
||||
list(APPEND SRCS netdev_upperhalf.c)
|
||||
endif()
|
||||
|
||||
if(CONFIG_MDIO_BUS)
|
||||
list(APPEND SRCS mdio.c)
|
||||
endif()
|
||||
|
||||
if(CONFIG_NET_LOOPBACK)
|
||||
list(APPEND SRCS loopback.c)
|
||||
endif()
|
||||
|
||||
@@ -68,6 +68,20 @@ config NETDEV_RSS
|
||||
When the hardware supports RSS/aRFS function, provide the
|
||||
hash value and CPU ID to the hardware driver.
|
||||
|
||||
menuconfig MDIO_BUS
|
||||
bool "Upper-half MDIO Bus Driver Options"
|
||||
default y
|
||||
|
||||
if MDIO_BUS
|
||||
|
||||
comment "IEEE 802.3 Ethernet MDIO Clauses Support"
|
||||
|
||||
config MDIO_CLAUSE_45
|
||||
bool "MDIO bus supports Clause 45"
|
||||
default n
|
||||
|
||||
endif
|
||||
|
||||
comment "General Ethernet MAC Driver Options"
|
||||
|
||||
config NET_RPMSG_DRV
|
||||
|
||||
@@ -30,6 +30,10 @@ ifeq ($(CONFIG_MM_IOB),y)
|
||||
CSRCS += netdev_upperhalf.c
|
||||
endif
|
||||
|
||||
ifeq ($(CONFIG_MDIO_BUS),y)
|
||||
CSRCS += mdio.c
|
||||
endif
|
||||
|
||||
ifeq ($(CONFIG_NET_LOOPBACK),y)
|
||||
CSRCS += loopback.c
|
||||
endif
|
||||
|
||||
@@ -0,0 +1,253 @@
|
||||
/****************************************************************************
|
||||
* drivers/net/mdio.c
|
||||
*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership. The
|
||||
* ASF licenses this file to you 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.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Included Files
|
||||
****************************************************************************/
|
||||
|
||||
#include <nuttx/config.h>
|
||||
#include <nuttx/kmalloc.h>
|
||||
#include <nuttx/mutex.h>
|
||||
#include <nuttx/net/mdio.h>
|
||||
#include <debug.h>
|
||||
|
||||
/****************************************************************************
|
||||
* Private Defines
|
||||
****************************************************************************/
|
||||
|
||||
#define MDIO_READ(d,a,r,v) d->lower->ops->read(d->lower, a, r, v);
|
||||
|
||||
#define MDIO_WRITE(d,a,r,v) d->lower->ops->write(d->lower, a, r, v);
|
||||
|
||||
#define MDIO_RESET(d,a) d->lower->ops->reset(d->lower, a);
|
||||
|
||||
/****************************************************************************
|
||||
* Private Types
|
||||
****************************************************************************/
|
||||
|
||||
/* This is the opaque handle used by application code to access the
|
||||
* MDIO bus.
|
||||
*/
|
||||
|
||||
struct mdio_bus_s
|
||||
{
|
||||
/* Pointer to the lower-half driver's state */
|
||||
|
||||
FAR struct mdio_lowerhalf_s *lower;
|
||||
|
||||
/* For exclusive access to the bus */
|
||||
|
||||
mutex_t lock;
|
||||
};
|
||||
|
||||
/****************************************************************************
|
||||
* Public Functions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: mdio_register
|
||||
*
|
||||
* Description:
|
||||
* Register a new MDIO bus instance.
|
||||
*
|
||||
* Input Parameters:
|
||||
* lower - An instance of the lower-half MDIO driver, with the ops vtable
|
||||
* as the first member.
|
||||
*
|
||||
* Returned Value:
|
||||
* A non-NULL handle on success; NULL on failure.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
FAR struct mdio_bus_s *mdio_register(FAR struct mdio_lowerhalf_s *lower)
|
||||
{
|
||||
FAR struct mdio_bus_s *dev;
|
||||
|
||||
/* Allocate the upper-half MDIO driver state structure */
|
||||
|
||||
dev = (FAR struct mdio_bus_s *)kmm_zalloc(sizeof(struct mdio_bus_s));
|
||||
if (dev != NULL)
|
||||
{
|
||||
/* Initialize the upper-half driver state */
|
||||
|
||||
nxmutex_init(&dev->lock);
|
||||
dev->lower = lower;
|
||||
}
|
||||
else
|
||||
{
|
||||
nerr("ERROR: Failed to allocate MDIO device structure\n");
|
||||
}
|
||||
|
||||
return dev;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: mdio_unregister
|
||||
*
|
||||
* Description:
|
||||
* Unregister an MDIO bus instance.
|
||||
*
|
||||
* Input Parameters:
|
||||
* dev - The MDIO bus handle returned by mdio_register.
|
||||
*
|
||||
* Returned Value:
|
||||
* Zero (OK) on success; a negated errno value on failure.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
int mdio_unregister(FAR struct mdio_bus_s *dev)
|
||||
{
|
||||
DEBUGASSERT(dev != NULL);
|
||||
|
||||
nxmutex_destroy(&dev->lock);
|
||||
kmm_free(dev);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: mdio_read
|
||||
*
|
||||
* Description:
|
||||
* Read a 16-bit value from a PHY register on the MDIO bus.
|
||||
*
|
||||
* Input Parameters:
|
||||
* dev - The MDIO bus handle.
|
||||
* phyaddr - The PHY address (0-31).
|
||||
* regaddr - The PHY register address (0-31).
|
||||
* value - A pointer to the location to store the read value.
|
||||
*
|
||||
* Returned Value:
|
||||
* Zero (OK) on success; a negated errno value on failure.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
int mdio_read(FAR struct mdio_bus_s *dev, uint8_t phyaddr, uint8_t regaddr,
|
||||
FAR uint16_t *value)
|
||||
{
|
||||
int ret;
|
||||
|
||||
DEBUGASSERT(dev != NULL && dev->lower != NULL);
|
||||
DEBUGASSERT(dev->lower->ops->read != NULL);
|
||||
|
||||
/* Take the mutex */
|
||||
|
||||
ret = nxmutex_lock(&dev->lock);
|
||||
if (ret < 0)
|
||||
{
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Call the lowerhalf driver's read method */
|
||||
|
||||
ret = MDIO_READ(dev, phyaddr, regaddr, value);
|
||||
|
||||
/* Release the mutex */
|
||||
|
||||
nxmutex_unlock(&dev->lock);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: mdio_write
|
||||
*
|
||||
* Description:
|
||||
* Write a 16-bit value to a PHY register on the MDIO bus.
|
||||
*
|
||||
* Input Parameters:
|
||||
* dev - The MDIO bus handle.
|
||||
* phyaddr - The PHY address (0-31).
|
||||
* regaddr - The PHY register address (0-31).
|
||||
* value - The value to write.
|
||||
*
|
||||
* Returned Value:
|
||||
* Zero (OK) on success; a negated errno value on failure.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
int mdio_write(FAR struct mdio_bus_s *dev, uint8_t phyaddr, uint8_t regaddr,
|
||||
uint16_t value)
|
||||
{
|
||||
int ret;
|
||||
|
||||
DEBUGASSERT(dev != NULL && dev->lower != NULL);
|
||||
DEBUGASSERT(dev->lower->ops->write != NULL);
|
||||
|
||||
/* Take the mutex */
|
||||
|
||||
ret = nxmutex_lock(&dev->lock);
|
||||
if (ret < 0)
|
||||
{
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Call the lowerhalf driver's write method */
|
||||
|
||||
ret = MDIO_WRITE(dev, phyaddr, regaddr, value);
|
||||
|
||||
/* Release the mutex */
|
||||
|
||||
nxmutex_unlock(&dev->lock);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: mdio_reset
|
||||
*
|
||||
* Description:
|
||||
* Reset a PHY on the MDIO bus.
|
||||
*
|
||||
* Input Parameters:
|
||||
* dev - The MDIO bus handle.
|
||||
* phyaddr - The PHY address (0-31) to reset.
|
||||
*
|
||||
* Returned Value:
|
||||
* Zero (OK) on success; a negated errno value on failure.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
int mdio_reset(FAR struct mdio_bus_s *dev, uint8_t phyaddr)
|
||||
{
|
||||
int ret = -ENOSYS;
|
||||
|
||||
DEBUGASSERT(dev != NULL && dev->lower != NULL);
|
||||
|
||||
/* Check if the reset method is provided by the lower-half */
|
||||
|
||||
if (dev->lower->ops->reset)
|
||||
{
|
||||
/* Take the mutex */
|
||||
|
||||
ret = nxmutex_lock(&dev->lock);
|
||||
if (ret < 0)
|
||||
{
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Call the lowerhalf driver's reset method */
|
||||
|
||||
ret = MDIO_RESET(dev, phyaddr);
|
||||
|
||||
/* Release the mutex */
|
||||
|
||||
nxmutex_unlock(&dev->lock);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
@@ -0,0 +1,192 @@
|
||||
/****************************************************************************
|
||||
* include/nuttx/net/mdio.h
|
||||
*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership. The
|
||||
* ASF licenses this file to you 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.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef __INCLUDE_NUTTX_NET_MDIO_H
|
||||
#define __INCLUDE_NUTTX_NET_MDIO_H
|
||||
|
||||
/****************************************************************************
|
||||
* Included Files
|
||||
****************************************************************************/
|
||||
|
||||
#include <nuttx/compiler.h>
|
||||
#include <stdint.h>
|
||||
#include <nuttx/mutex.h>
|
||||
|
||||
/****************************************************************************
|
||||
* Pre-processor Definitions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Public Types
|
||||
****************************************************************************/
|
||||
|
||||
/* Forward references */
|
||||
|
||||
struct mdio_bus_s;
|
||||
struct mdio_lowerhalf_s;
|
||||
|
||||
/* This structure defines the interface for the MDIO lower-half driver.
|
||||
* These methods are called by the upper-half MDIO driver.
|
||||
*/
|
||||
|
||||
struct mdio_ops_s
|
||||
{
|
||||
/* Clause 22 MDIO Read. The first argument is a reference to the
|
||||
* lower-half driver's private state.
|
||||
*/
|
||||
|
||||
int (*read)(FAR struct mdio_lowerhalf_s *lower, uint8_t phyaddr,
|
||||
uint8_t regaddr, FAR uint16_t *value);
|
||||
|
||||
/* Clause 22 MDIO Write */
|
||||
|
||||
int (*write)(FAR struct mdio_lowerhalf_s *lower, uint8_t phyaddr,
|
||||
uint8_t regaddr, uint16_t value);
|
||||
|
||||
#ifdef CONFIG_MDIO_CLAUSE_45
|
||||
#endif
|
||||
|
||||
/* PHY Reset. Optional. */
|
||||
|
||||
int (*reset)(FAR struct mdio_lowerhalf_s *lower, uint8_t phyaddr);
|
||||
};
|
||||
|
||||
/* This structure defines the state of the MDIO lower-half driver.
|
||||
* The chip-specific MDIO driver must allocate and initialize one instance
|
||||
* of this structure.
|
||||
*/
|
||||
|
||||
struct mdio_lowerhalf_s
|
||||
{
|
||||
/* The vtable of MDIO lower-half operations.
|
||||
* This must be the first field.
|
||||
*/
|
||||
|
||||
FAR const struct mdio_ops_s *ops;
|
||||
};
|
||||
|
||||
/****************************************************************************
|
||||
* Public Function Prototypes
|
||||
****************************************************************************/
|
||||
|
||||
#ifdef __cplusplus
|
||||
#define EXTERN extern "C"
|
||||
extern "C"
|
||||
{
|
||||
#else
|
||||
#define EXTERN extern
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Name: mdio_register
|
||||
*
|
||||
* Description:
|
||||
* Register a new MDIO bus instance.
|
||||
*
|
||||
* Input Parameters:
|
||||
* lower - An instance of the lower-half MDIO driver, with the ops vtable
|
||||
* as the first member.
|
||||
*
|
||||
* Returned Value:
|
||||
* A non-NULL handle on success; NULL on failure.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
FAR struct mdio_bus_s *mdio_register(FAR struct mdio_lowerhalf_s *lower);
|
||||
|
||||
/****************************************************************************
|
||||
* Name: mdio_unregister
|
||||
*
|
||||
* Description:
|
||||
* Unregister an MDIO bus instance.
|
||||
*
|
||||
* Input Parameters:
|
||||
* dev - The MDIO bus handle returned by mdio_register.
|
||||
*
|
||||
* Returned Value:
|
||||
* Zero (OK) on success; a negated errno value on failure.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
int mdio_unregister(FAR struct mdio_bus_s *dev);
|
||||
|
||||
/****************************************************************************
|
||||
* Name: mdio_read
|
||||
*
|
||||
* Description:
|
||||
* Read a 16-bit value from a PHY register on the MDIO bus.
|
||||
*
|
||||
* Input Parameters:
|
||||
* dev - The MDIO bus handle.
|
||||
* phyaddr - The PHY address (0-31).
|
||||
* regaddr - The PHY register address (0-31).
|
||||
* value - A pointer to the location to store the read value.
|
||||
*
|
||||
* Returned Value:
|
||||
* Zero (OK) on success; a negated errno value on failure.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
int mdio_read(FAR struct mdio_bus_s *dev, uint8_t phyaddr, uint8_t regaddr,
|
||||
FAR uint16_t *value);
|
||||
|
||||
/****************************************************************************
|
||||
* Name: mdio_write
|
||||
*
|
||||
* Description:
|
||||
* Write a 16-bit value to a PHY register on the MDIO bus.
|
||||
*
|
||||
* Input Parameters:
|
||||
* dev - The MDIO bus handle.
|
||||
* phyaddr - The PHY address (0-31).
|
||||
* regaddr - The PHY register address (0-31).
|
||||
* value - The value to write.
|
||||
*
|
||||
* Returned Value:
|
||||
* Zero (OK) on success; a negated errno value on failure.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
int mdio_write(FAR struct mdio_bus_s *dev, uint8_t phyaddr, uint8_t regaddr,
|
||||
uint16_t value);
|
||||
|
||||
/****************************************************************************
|
||||
* Name: mdio_reset
|
||||
*
|
||||
* Description:
|
||||
* Reset a PHY on the MDIO bus.
|
||||
*
|
||||
* Input Parameters:
|
||||
* dev - The MDIO bus handle.
|
||||
* phyaddr - The PHY address (0-31) to reset.
|
||||
*
|
||||
* Returned Value:
|
||||
* Zero (OK) on success; a negated errno value on failure.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
int mdio_reset(FAR struct mdio_bus_s *dev, uint8_t phyaddr);
|
||||
|
||||
#undef EXTERN
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* __INCLUDE_NUTTX_NET_MDIO_H */
|
||||
Reference in New Issue
Block a user