MCUXpresso_MIMXRT1052xxxxB/components/phy/fsl_phy.h

334 lines
14 KiB
C

/*
* Copyright 2020-2023 NXP
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#ifndef _FSL_PHY_H_
#define _FSL_PHY_H_
#include "fsl_common.h"
/*! @brief This abstract layer is to unify the PHY interface in SDK, let application
* use one set of PHY interfaces. The data structures are applicable to different
* PHYs.
*/
/*******************************************************************************
* Definitions
******************************************************************************/
/*! @note The following PHY registers are the IEEE802.3 standard definition, same register and bit field may
have different names in various PHYs, but the feature they represent should be same or very similar. */
/*! @brief Defines the IEEE802.3 standard PHY registers. */
#define PHY_BASICCONTROL_REG (0x00U) /*!< The PHY basic control register. */
#define PHY_BASICSTATUS_REG (0x01U) /*!< The PHY basic status register. */
#define PHY_ID1_REG (0x02U) /*!< The PHY ID one register. */
#define PHY_ID2_REG (0x03U) /*!< The PHY ID two register. */
#define PHY_AUTONEG_ADVERTISE_REG (0x04U) /*!< The PHY auto-negotiate advertise register. */
#define PHY_AUTONEG_LINKPARTNER_REG (0x05U) /*!< The PHY auto negotiation link partner ability register. */
#define PHY_AUTONEG_EXPANSION_REG (0x06U) /*!< The PHY auto negotiation expansion register. */
#define PHY_1000BASET_CONTROL_REG (0x09U) /*!< The PHY 1000BASE-T control register. */
#define PHY_MMD_ACCESS_CONTROL_REG (0x0DU) /*!< The PHY MMD access control register. */
#define PHY_MMD_ACCESS_DATA_REG (0x0EU) /*!< The PHY MMD access data register. */
/*! @brief Defines the mask flag in basic control register(Address 0x00). */
#define PHY_BCTL_SPEED1_MASK ((uint16_t)0x0040U) /*!< The PHY speed bit mask(MSB).*/
#define PHY_BCTL_ISOLATE_MASK ((uint16_t)0x0400U) /*!< The PHY isolate mask.*/
#define PHY_BCTL_DUPLEX_MASK ((uint16_t)0x0100U) /*!< The PHY duplex bit mask. */
#define PHY_BCTL_RESTART_AUTONEG_MASK ((uint16_t)0x0200U) /*!< The PHY restart auto negotiation mask. */
#define PHY_BCTL_AUTONEG_MASK ((uint16_t)0x1000U) /*!< The PHY auto negotiation bit mask. */
#define PHY_BCTL_SPEED0_MASK ((uint16_t)0x2000U) /*!< The PHY speed bit mask(LSB). */
#define PHY_BCTL_LOOP_MASK ((uint16_t)0x4000U) /*!< The PHY loop bit mask. */
#define PHY_BCTL_RESET_MASK ((uint16_t)0x8000U) /*!< The PHY reset bit mask. */
/*! @brief Defines the mask flag in basic status register(Address 0x01). */
#define PHY_BSTATUS_LINKSTATUS_MASK ((uint16_t)0x0004U) /*!< The PHY link status mask. */
#define PHY_BSTATUS_AUTONEGABLE_MASK ((uint16_t)0x0008U) /*!< The PHY auto-negotiation ability mask. */
#define PHY_BSTATUS_SPEEDUPLX_MASK ((uint16_t)0x001CU) /*!< The PHY speed and duplex mask. */
#define PHY_BSTATUS_AUTONEGCOMP_MASK ((uint16_t)0x0020U) /*!< The PHY auto-negotiation complete mask. */
/*! @brief Defines the mask flag in PHY auto-negotiation advertise register(Address 0x04). */
#define PHY_100BaseT4_ABILITY_MASK ((uint16_t)0x200U) /*!< The PHY have the T4 ability. */
#define PHY_100BASETX_FULLDUPLEX_MASK ((uint16_t)0x100U) /*!< The PHY has the 100M full duplex ability.*/
#define PHY_100BASETX_HALFDUPLEX_MASK ((uint16_t)0x080U) /*!< The PHY has the 100M full duplex ability.*/
#define PHY_10BASETX_FULLDUPLEX_MASK ((uint16_t)0x040U) /*!< The PHY has the 10M full duplex ability.*/
#define PHY_10BASETX_HALFDUPLEX_MASK ((uint16_t)0x020U) /*!< The PHY has the 10M full duplex ability.*/
#define PHY_IEEE802_3_SELECTOR_MASK ((uint16_t)0x001U) /*!< The message type being sent by Auto-Nego.*/
/*! @brief Defines the mask flag in the 1000BASE-T control register(Address 0x09). */
#define PHY_1000BASET_FULLDUPLEX_MASK ((uint16_t)0x200U) /*!< The PHY has the 1000M full duplex ability.*/
#define PHY_1000BASET_HALFDUPLEX_MASK ((uint16_t)0x100U) /*!< The PHY has the 1000M half duplex ability.*/
typedef struct _phy_handle phy_handle_t;
typedef struct _phy_config phy_config_t;
/*! @brief IEEE 802.3 Clause 22 MDIO write data. */
typedef status_t (*mdioWrite)(uint8_t phyAddr, uint8_t regAddr, uint16_t data);
/*! @brief IEEE 802.3 Clause 22 MDIO read data. */
typedef status_t (*mdioRead)(uint8_t phyAddr, uint8_t regAddr, uint16_t *pData);
/*! @brief IEEE 802.3 Clause 45 MDIO write data. */
typedef status_t (*mdioWriteExt)(uint8_t portAddr, uint8_t devAddr, uint16_t regAddr, uint16_t data);
/*! @brief IEEE 802.3 Clause 45 MDIO read data. */
typedef status_t (*mdioReadExt)(uint8_t portAddr, uint8_t devAddr, uint16_t regAddr, uint16_t *pData);
/*! @brief Defines the PHY link speed. */
typedef enum _phy_speed
{
kPHY_Speed10M = 0U, /*!< ENET PHY 10M speed. */
kPHY_Speed100M, /*!< ENET PHY 100M speed. */
kPHY_Speed1000M /*!< ENET PHY 1000M speed. */
} phy_speed_t;
/*! @brief Defines the PHY link duplex. */
typedef enum _phy_duplex
{
kPHY_HalfDuplex = 0U, /*!< ENET PHY half duplex. */
kPHY_FullDuplex /*!< ENET PHY full duplex. */
} phy_duplex_t;
/*! @brief Defines the PHY loopback mode. */
typedef enum _phy_loop
{
kPHY_LocalLoop = 0U, /*!< ENET PHY local/digital loopback. */
kPHY_RemoteLoop, /*!< ENET PHY remote loopback. */
kPHY_ExternalLoop, /*!< ENET PHY external loopback. */
} phy_loop_t;
/*! @brief Defines the PHY MMD data access mode. */
typedef enum _phy_mmd_access_mode
{
kPHY_MMDAccessNoPostIncrement = (1U << 14), /*!< ENET PHY MMD access data with no address post increment. */
kPHY_MMDAccessRdWrPostIncrement =
(2U << 14), /*!< ENET PHY MMD access data with Read/Write address post increment. */
kPHY_MMDAccessWrPostIncrement = (3U << 14), /*!< ENET PHY MMD access data with Write address post increment. */
} phy_mmd_access_mode_t;
/*! @brief Defines the PHY interrupt type. */
typedef enum _phy_interrupt_type
{
kPHY_IntrDisable = 0U, /*!< ENET PHY interrupt disable. */
kPHY_IntrActiveLow, /*!< ENET PHY interrupt active low. */
kPHY_IntrActiveHigh, /*!< ENET PHY interrupt active high. */
} phy_interrupt_type_t;
/*! @brief PHY device operations. */
typedef struct _phy_operations
{
status_t (*phyInit)(phy_handle_t *handle, const phy_config_t *config);
status_t (*phyWrite)(phy_handle_t *handle, uint8_t phyReg, uint16_t data);
status_t (*phyRead)(phy_handle_t *handle, uint8_t phyReg, uint16_t *pData);
status_t (*getAutoNegoStatus)(phy_handle_t *handle, bool *status);
status_t (*getLinkStatus)(phy_handle_t *handle, bool *status);
status_t (*getLinkSpeedDuplex)(phy_handle_t *handle, phy_speed_t *speed, phy_duplex_t *duplex);
status_t (*setLinkSpeedDuplex)(phy_handle_t *handle, phy_speed_t speed, phy_duplex_t duplex);
status_t (*enableLoopback)(phy_handle_t *handle, phy_loop_t mode, phy_speed_t speed, bool enable);
status_t (*enableLinkInterrupt)(phy_handle_t *handle, phy_interrupt_type_t type);
status_t (*clearInterrupt)(phy_handle_t *handle);
} phy_operations_t;
/*! @brief Defines PHY configuration. */
struct _phy_config
{
uint8_t phyAddr; /*!< PHY address. */
void *resource; /*!< PHY specific resource supporting operation of PHY hardware. */
const phy_operations_t *ops; /*!< PHY operational method. */
phy_speed_t speed; /*!< PHY speed configuration. */
phy_duplex_t duplex; /*!< PHY duplex configuration. */
bool autoNeg; /*!< PHY auto-negotiation, true: enable, false: disable. */
bool enableEEE; /*!< PHY Energy Efficient Ethernet, true: enable, false: disable. */
phy_interrupt_type_t intrType; /*!< PHY interrupt configuration. */
};
/*! @brief PHY device handle. */
struct _phy_handle
{
uint8_t phyAddr; /*!< PHY address. */
void *resource; /*!< PHY specific resource supporting operation of PHY hardware. */
const phy_operations_t *ops; /*!< PHY operational method. */
};
/*******************************************************************************
* API
******************************************************************************/
#if defined(__cplusplus)
extern "C" {
#endif
/*!
* @name PHY Driver
* @{
*/
/*!
* @brief Initializes PHY.
* This function initializes PHY.
*
* @param handle PHY device handle.
* @param config PHY configuration.
* @retval kStatus_Success PHY initialization succeeds
* @retval kStatus_Fail PHY initialization fails
* @retval kStatus_Timeout PHY MDIO visit time out
*/
static inline status_t PHY_Init(phy_handle_t *handle, const phy_config_t *config)
{
handle->ops = config->ops;
return handle->ops->phyInit(handle, config);
}
/*!
* @brief PHY Write function.
* This function writes data over the MDIO to the specified PHY register.
*
* @param handle PHY device handle.
* @param phyReg The PHY register.
* @param data The data written to the PHY register.
* @retval kStatus_Success PHY write success
* @retval kStatus_Timeout PHY MDIO visit time out
*/
static inline status_t PHY_Write(phy_handle_t *handle, uint8_t phyReg, uint16_t data)
{
return handle->ops->phyWrite(handle, phyReg, data);
}
/*!
* @brief PHY Read function.
* This interface reads data over the MDIO from the specified PHY register.
*
* @param handle PHY device handle.
* @param phyReg The PHY register address.
* @param pData The address to store the data read from the PHY register.
* @retval kStatus_Success PHY read success
* @retval kStatus_Timeout PHY MDIO visit time out
*/
static inline status_t PHY_Read(phy_handle_t *handle, uint8_t phyReg, uint16_t *pData)
{
return handle->ops->phyRead(handle, phyReg, pData);
}
/*!
* @brief Gets the PHY auto-negotiation status.
*
* @param handle PHY device handle.
* @param status The auto-negotiation status of the PHY.
* - true the auto-negotiation is over.
* - false the auto-negotiation is on-going or not started.
* @retval kStatus_Success PHY gets status success
* @retval kStatus_Timeout PHY MDIO visit time out
*/
static inline status_t PHY_GetAutoNegotiationStatus(phy_handle_t *handle, bool *status)
{
return handle->ops->getAutoNegoStatus(handle, status);
}
/*!
* @brief Gets the PHY link status.
*
* @param handle PHY device handle.
* @param status The link up or down status of the PHY.
* - true the link is up.
* - false the link is down.
* @retval kStatus_Success PHY get link status success
* @retval kStatus_Timeout PHY MDIO visit time out
*/
static inline status_t PHY_GetLinkStatus(phy_handle_t *handle, bool *status)
{
return handle->ops->getLinkStatus(handle, status);
}
/*!
* @brief Gets the PHY link speed and duplex.
*
* @brief This function gets the speed and duplex mode of PHY. User can give one of speed
* and duplex address paramter and set the other as NULL if only wants to get one of them.
*
* @param handle PHY device handle.
* @param speed The address of PHY link speed.
* @param duplex The link duplex of PHY.
* @retval kStatus_Success PHY get link speed and duplex success
* @retval kStatus_Timeout PHY MDIO visit time out
*/
static inline status_t PHY_GetLinkSpeedDuplex(phy_handle_t *handle, phy_speed_t *speed, phy_duplex_t *duplex)
{
return handle->ops->getLinkSpeedDuplex(handle, speed, duplex);
}
/*!
* @brief Sets the PHY link speed and duplex.
*
* @param handle PHY device handle.
* @param speed Specified PHY link speed.
* @param duplex Specified PHY link duplex.
* @retval kStatus_Success PHY gets status success
* @retval kStatus_Timeout PHY MDIO visit time out
*/
static inline status_t PHY_SetLinkSpeedDuplex(phy_handle_t *handle, phy_speed_t speed, phy_duplex_t duplex)
{
return handle->ops->setLinkSpeedDuplex(handle, speed, duplex);
}
/*!
* @brief Enables/Disables PHY loopback mode.
*
* @param handle PHY device handle.
* @param mode The loopback mode to be enabled, please see "phy_loop_t".
* All loopback modes should not be set together, when one loopback mode is set
* another should be disabled.
* @param speed PHY speed for loopback mode.
* @param enable True to enable, false to disable.
* @retval kStatus_Success PHY get link speed and duplex success
* @retval kStatus_Timeout PHY MDIO visit time out
*/
static inline status_t PHY_EnableLoopback(phy_handle_t *handle, phy_loop_t mode, phy_speed_t speed, bool enable)
{
return handle->ops->enableLoopback(handle, mode, speed, enable);
}
/*!
* @brief Enables/Disables PHY link management interrupt.
*
* This function controls link status change interrupt. Application should get
* status through PHY_GetLinkStatus() and PHY_GetAutoNegotiationStatus() when
* interrupt triggers.
*
* @note Not all PHYs support link up, link down and auto auto-negotiation complete
* interrupt separately. Some PHY may combine link up/down or no link up or no
* auto-negotiation complete interrupt. The interrupt trigger situation depends
* on specific PHY.
*
* @param handle PHY device handle.
* @param type PHY interrupt type.
* @retval kStatus_Success PHY enables/disables interrupt success
* @retval kStatus_Timeout PHY MDIO visit time out
*/
static inline status_t PHY_EnableLinkInterrupt(phy_handle_t *handle, phy_interrupt_type_t type)
{
return handle->ops->enableLinkInterrupt(handle, type);
}
/*!
* @brief Clears PHY interrupt status.
* @note Usually this API clears all interrupts of PHY because related register
* flags are read clear.
*
* @param handle PHY device handle.
* @retval kStatus_Success PHY read and clear interrupt success
* @retval kStatus_Timeout PHY MDIO visit time out
*/
static inline status_t PHY_ClearInterrupt(phy_handle_t *handle)
{
return handle->ops->clearInterrupt(handle);
}
/*! @} */
#if defined(__cplusplus)
}
#endif
/*! @}*/
#endif