drivers: ethernet: phy: Add OPEN Alliance TC14 PLCA generic lib support
10BASE-T1S PHYs can operate in either CSMA/CD or PLCA mode. PLCA mode needs some set of parameters like node id, node count, max burst count, burst timer and TO (Transmit Oppertunity) timer to be configured. OPEN Alliance TC14 specification defined a set of PLCA registers to configure PLCA mode. The below APIs are implemented for PLCA mode. genphy_set_plca_cfg() - to configure PLCA settings. genphy_get_plca_cfg() - to get the configured PLCA settings. genphy_get_plca_sts() - to get the PLCA status like active or inactive. These APIs are implemented as generic library so that all 10BASE-T1S PHYs can use these APIs to configure/access PLCA settings to avoid duplication of code. Signed-off-by: Parthiban Veerasooran <parthiban.veerasooran@microchip.com>
This commit is contained in:
parent
53d5b1efef
commit
2b8880cc38
4 changed files with 271 additions and 0 deletions
|
|
@ -8,3 +8,4 @@ zephyr_library_sources_ifdef(CONFIG_PHY_MICROCHIP_KSZ8081 phy_microchip_ksz8081.
|
|||
zephyr_library_sources_ifdef(CONFIG_PHY_TI_DP83825 phy_ti_dp83825.c)
|
||||
zephyr_library_sources_ifdef(CONFIG_PHY_REALTEK_RTL8211F phy_realtek_rtl8211f.c)
|
||||
zephyr_library_sources_ifdef(CONFIG_PHY_QUALCOMM_AR8031 phy_qualcomm_ar8031.c)
|
||||
zephyr_library_sources_ifdef(CONFIG_PHY_OA_TC14_PLCA_LIB phy_oa_tc14_plca.c)
|
||||
|
|
|
|||
|
|
@ -92,4 +92,9 @@ config PHY_MONITOR_PERIOD
|
|||
periodically executed to detect and report any changes in the
|
||||
PHY link status to the operating system.
|
||||
|
||||
config PHY_OA_TC14_PLCA_LIB
|
||||
bool "Open Alliance TC14 PLCA generic lib"
|
||||
help
|
||||
Enable Open Alliance TC14 PLCA generic lib.
|
||||
|
||||
endif # "Ethernet PHY Drivers"
|
||||
|
|
|
|||
145
drivers/ethernet/phy/phy_oa_tc14_plca.c
Normal file
145
drivers/ethernet/phy/phy_oa_tc14_plca.c
Normal file
|
|
@ -0,0 +1,145 @@
|
|||
/*
|
||||
* Copyright (c) 2024 Microchip Technology Inc.
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include <zephyr/net/mdio.h>
|
||||
#include <zephyr/net/phy.h>
|
||||
#include <errno.h>
|
||||
|
||||
/* Open Alliance TC14 (10BASE-T1S) PLCA registers */
|
||||
#define MDIO_OATC14_PLCA_IDVER 0xca00 /* PLCA ID and version */
|
||||
#define MDIO_OATC14_PLCA_CTRL0 0xca01 /* PLCA Control register 0 */
|
||||
#define MDIO_OATC14_PLCA_CTRL1 0xca02 /* PLCA Control register 1 */
|
||||
#define MDIO_OATC14_PLCA_STATUS 0xca03 /* PLCA Status register */
|
||||
#define MDIO_OATC14_PLCA_TOTMR 0xca04 /* PLCA TO Timer register */
|
||||
#define MDIO_OATC14_PLCA_BURST 0xca05 /* PLCA BURST mode register */
|
||||
|
||||
/* Open Alliance TC14 PLCA IDVER register */
|
||||
#define MDIO_OATC14_PLCA_IDM GENMASK(15, 8) /* PLCA MAP ID */
|
||||
#define MDIO_OATC14_PLCA_VER GENMASK(7, 0) /* PLCA MAP version */
|
||||
|
||||
/* Open Alliance TC14 PLCA CTRL0 register */
|
||||
#define MDIO_OATC14_PLCA_EN BIT(15) /* PLCA enable */
|
||||
#define MDIO_OATC14_PLCA_RST BIT(14) /* PLCA reset */
|
||||
|
||||
/* Open Alliance TC14 PLCA CTRL1 register */
|
||||
#define MDIO_OATC14_PLCA_NCNT GENMASK(15, 8) /* PLCA node count */
|
||||
#define MDIO_OATC14_PLCA_ID GENMASK(7, 0) /* PLCA local node ID */
|
||||
|
||||
/* Open Alliance TC14 PLCA STATUS register */
|
||||
#define MDIO_OATC14_PLCA_PST BIT(15) /* PLCA status indication */
|
||||
|
||||
/* Open Alliance TC14 PLCA TOTMR register */
|
||||
#define MDIO_OATC14_PLCA_TOT GENMASK(7, 0)
|
||||
|
||||
/* Open Alliance TC14 PLCA BURST register */
|
||||
#define MDIO_OATC14_PLCA_MAXBC GENMASK(15, 8)
|
||||
#define MDIO_OATC14_PLCA_BTMR GENMASK(7, 0)
|
||||
|
||||
/* Version Identifiers */
|
||||
#define OATC14_IDM 0x0a00
|
||||
|
||||
int genphy_set_plca_cfg(const struct device *dev, struct phy_plca_cfg *plca_cfg)
|
||||
{
|
||||
uint16_t val;
|
||||
int ret;
|
||||
|
||||
/* Disable plca before doing the configuration */
|
||||
ret = phy_write_c45(dev, MDIO_MMD_VENDOR_SPECIFIC2, MDIO_OATC14_PLCA_CTRL0, 0x0);
|
||||
if (ret) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (!plca_cfg->enable) {
|
||||
/* As the PLCA is disabled above, just return */
|
||||
return 0;
|
||||
}
|
||||
|
||||
val = (plca_cfg->node_count << 8) | plca_cfg->node_id;
|
||||
ret = phy_write_c45(dev, MDIO_MMD_VENDOR_SPECIFIC2, MDIO_OATC14_PLCA_CTRL1, val);
|
||||
if (ret) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
val = (plca_cfg->burst_count << 8) | plca_cfg->burst_timer;
|
||||
ret = phy_write_c45(dev, MDIO_MMD_VENDOR_SPECIFIC2, MDIO_OATC14_PLCA_BURST, val);
|
||||
if (ret) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = phy_write_c45(dev, MDIO_MMD_VENDOR_SPECIFIC2, MDIO_OATC14_PLCA_TOTMR,
|
||||
plca_cfg->to_timer);
|
||||
if (ret) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Enable plca after doing all the configuration */
|
||||
return phy_write_c45(dev, MDIO_MMD_VENDOR_SPECIFIC2, MDIO_OATC14_PLCA_CTRL0,
|
||||
MDIO_OATC14_PLCA_EN);
|
||||
}
|
||||
|
||||
int genphy_get_plca_cfg(const struct device *dev, struct phy_plca_cfg *plca_cfg)
|
||||
{
|
||||
uint16_t val;
|
||||
int ret;
|
||||
|
||||
ret = phy_read_c45(dev, MDIO_MMD_VENDOR_SPECIFIC2, MDIO_OATC14_PLCA_IDVER, &val);
|
||||
if (ret) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
if ((val & MDIO_OATC14_PLCA_IDM) != OATC14_IDM) {
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
plca_cfg->version = ret & ~MDIO_OATC14_PLCA_IDM;
|
||||
|
||||
ret = phy_read_c45(dev, MDIO_MMD_VENDOR_SPECIFIC2, MDIO_OATC14_PLCA_CTRL0, &val);
|
||||
if (ret) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
plca_cfg->enable = !!(val & MDIO_OATC14_PLCA_EN);
|
||||
|
||||
ret = phy_read_c45(dev, MDIO_MMD_VENDOR_SPECIFIC2, MDIO_OATC14_PLCA_CTRL1, &val);
|
||||
if (ret) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
plca_cfg->node_id = val & MDIO_OATC14_PLCA_ID;
|
||||
plca_cfg->node_count = (val & MDIO_OATC14_PLCA_NCNT) >> 8;
|
||||
|
||||
ret = phy_read_c45(dev, MDIO_MMD_VENDOR_SPECIFIC2, MDIO_OATC14_PLCA_BURST, &val);
|
||||
if (ret) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
plca_cfg->burst_timer = val & MDIO_OATC14_PLCA_BTMR;
|
||||
plca_cfg->burst_count = (val & MDIO_OATC14_PLCA_MAXBC) >> 8;
|
||||
|
||||
ret = phy_read_c45(dev, MDIO_MMD_VENDOR_SPECIFIC2, MDIO_OATC14_PLCA_TOTMR, &val);
|
||||
if (ret) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
plca_cfg->to_timer = val & MDIO_OATC14_PLCA_TOT;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int genphy_get_plca_sts(const struct device *dev, bool *plca_sts)
|
||||
{
|
||||
uint16_t val;
|
||||
int ret;
|
||||
|
||||
ret = phy_read_c45(dev, MDIO_MMD_VENDOR_SPECIFIC2, MDIO_OATC14_PLCA_STATUS, &val);
|
||||
if (ret) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
*plca_sts = !!(val & MDIO_OATC14_PLCA_PST);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -83,6 +83,63 @@ struct phy_link_state {
|
|||
bool is_up;
|
||||
};
|
||||
|
||||
/** @brief PLCA (Physical Layer Collision Avoidance) Reconciliation Sublayer configurations */
|
||||
struct phy_plca_cfg {
|
||||
/** PLCA register map version */
|
||||
uint8_t version;
|
||||
/** PLCA configured mode (enable/disable) */
|
||||
bool enable;
|
||||
/** PLCA local node identifier */
|
||||
uint8_t node_id;
|
||||
/** PLCA node count */
|
||||
uint8_t node_count;
|
||||
/** Additional frames a node is allowed to send in single transmit opportunity (TO) */
|
||||
uint8_t burst_count;
|
||||
/** Wait time for the MAC to send a new frame before interrupting the burst */
|
||||
uint8_t burst_timer;
|
||||
/** PLCA to_timer in bit-times, which determines the PLCA transmit opportunity */
|
||||
uint8_t to_timer;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Write PHY PLCA configuration
|
||||
*
|
||||
* This routine provides a generic interface to configure PHY PLCA settings.
|
||||
*
|
||||
* @param[in] dev PHY device structure
|
||||
* @param[in] plca_cfg Pointer to plca configuration structure
|
||||
*
|
||||
* @retval 0 If successful.
|
||||
* @retval -EIO If communication with PHY failed.
|
||||
*/
|
||||
int genphy_get_plca_cfg(const struct device *dev, struct phy_plca_cfg *plca_cfg);
|
||||
|
||||
/**
|
||||
* @brief Read PHY PLCA configuration
|
||||
*
|
||||
* This routine provides a generic interface to get PHY PLCA settings.
|
||||
*
|
||||
* @param[in] dev PHY device structure
|
||||
* @param plca_cfg Pointer to plca configuration structure
|
||||
*
|
||||
* @retval 0 If successful.
|
||||
* @retval -EIO If communication with PHY failed.
|
||||
*/
|
||||
int genphy_set_plca_cfg(const struct device *dev, struct phy_plca_cfg *plca_cfg);
|
||||
|
||||
/**
|
||||
* @brief Read PHY PLCA status
|
||||
*
|
||||
* This routine provides a generic interface to get PHY PLCA status.
|
||||
*
|
||||
* @param[in] dev PHY device structure
|
||||
* @param plca_status Pointer to plca status
|
||||
*
|
||||
* @retval 0 If successful.
|
||||
* @retval -EIO If communication with PHY failed.
|
||||
*/
|
||||
int genphy_get_plca_sts(const struct device *dev, bool *plca_status);
|
||||
|
||||
/**
|
||||
* @typedef phy_callback_t
|
||||
* @brief Define the callback function signature for
|
||||
|
|
@ -122,6 +179,15 @@ __subsystem struct ethphy_driver_api {
|
|||
|
||||
/** Write PHY C45 register */
|
||||
int (*write_c45)(const struct device *dev, uint8_t devad, uint16_t regad, uint16_t data);
|
||||
|
||||
/* Set PLCA settings */
|
||||
int (*set_plca_cfg)(const struct device *dev, struct phy_plca_cfg *plca_cfg);
|
||||
|
||||
/* Get PLCA settings */
|
||||
int (*get_plca_cfg)(const struct device *dev, struct phy_plca_cfg *plca_cfg);
|
||||
|
||||
/* Get PLCA status */
|
||||
int (*get_plca_sts)(const struct device *dev, bool *plca_sts);
|
||||
};
|
||||
/**
|
||||
* @endcond
|
||||
|
|
@ -268,6 +334,60 @@ static inline int phy_write_c45(const struct device *dev, uint8_t devad, uint16_
|
|||
return api->write_c45(dev, devad, regad, data);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Write PHY PLCA configuration
|
||||
*
|
||||
* This routine provides a generic interface to configure PHY PLCA settings.
|
||||
*
|
||||
* @param[in] dev PHY device structure
|
||||
* @param[in] plca_cfg Pointer to plca configuration structure
|
||||
*
|
||||
* @retval 0 If successful.
|
||||
* @retval -EIO If communication with PHY failed.
|
||||
*/
|
||||
static inline int phy_set_plca_cfg(const struct device *dev, struct phy_plca_cfg *plca_cfg)
|
||||
{
|
||||
const struct ethphy_driver_api *api = (const struct ethphy_driver_api *)dev->api;
|
||||
|
||||
return api->set_plca_cfg(dev, plca_cfg);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Read PHY PLCA configuration
|
||||
*
|
||||
* This routine provides a generic interface to get PHY PLCA settings.
|
||||
*
|
||||
* @param[in] dev PHY device structure
|
||||
* @param plca_cfg Pointer to plca configuration structure
|
||||
*
|
||||
* @retval 0 If successful.
|
||||
* @retval -EIO If communication with PHY failed.
|
||||
*/
|
||||
static inline int phy_get_plca_cfg(const struct device *dev, struct phy_plca_cfg *plca_cfg)
|
||||
{
|
||||
const struct ethphy_driver_api *api = (const struct ethphy_driver_api *)dev->api;
|
||||
|
||||
return api->get_plca_cfg(dev, plca_cfg);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Read PHY PLCA status
|
||||
*
|
||||
* This routine provides a generic interface to get PHY PLCA status.
|
||||
*
|
||||
* @param[in] dev PHY device structure
|
||||
* @param plca_status Pointer to plca status
|
||||
*
|
||||
* @retval 0 If successful.
|
||||
* @retval -EIO If communication with PHY failed.
|
||||
*/
|
||||
static inline int phy_get_plca_sts(const struct device *dev, bool *plca_status)
|
||||
{
|
||||
const struct ethphy_driver_api *api = (const struct ethphy_driver_api *)dev->api;
|
||||
|
||||
return api->get_plca_sts(dev, plca_status);
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
|
|
|||
Loading…
Reference in a new issue