drivers/net/phy: add helpers to get/set PLCA configuration
This patch adds support in phylib to read/write PLCA configuration for Ethernet PHYs that support the OPEN Alliance "10BASE-T1S PLCA Management Registers" specifications. These can be found at https://www.opensig.org/about/specifications/ Signed-off-by: Piergiorgio Beruto <piergiorgio.beruto@gmail.com> Reviewed-by: Andrew Lunn <andrew@lunn.ch> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
parent
a23a1e57a6
commit
493323416f
@ -16620,6 +16620,7 @@ PLCA RECONCILIATION SUBLAYER (IEEE802.3 Clause 148)
|
||||
M: Piergiorgio Beruto <piergiorgio.beruto@gmail.com>
|
||||
L: netdev@vger.kernel.org
|
||||
S: Maintained
|
||||
F: drivers/net/phy/mdio-open-alliance.h
|
||||
F: net/ethtool/plca.c
|
||||
|
||||
PLDMFW LIBRARY
|
||||
|
46
drivers/net/phy/mdio-open-alliance.h
Normal file
46
drivers/net/phy/mdio-open-alliance.h
Normal file
@ -0,0 +1,46 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
/*
|
||||
* mdio-open-alliance.h - definition of OPEN Alliance SIG standard registers
|
||||
*/
|
||||
|
||||
#ifndef __MDIO_OPEN_ALLIANCE__
|
||||
#define __MDIO_OPEN_ALLIANCE__
|
||||
|
||||
#include <linux/mdio.h>
|
||||
|
||||
/* NOTE: all OATC14 registers are located in MDIO_MMD_VEND2 */
|
||||
|
||||
/* Open Alliance TC14 (10BASE-T1S) 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 0xff00 /* PLCA MAP ID */
|
||||
#define MDIO_OATC14_PLCA_VER 0x00ff /* 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 0xff00 /* PLCA node count */
|
||||
#define MDIO_OATC14_PLCA_ID 0x00ff /* 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 0x00ff
|
||||
|
||||
/* Open Alliance TC14 PLCA BURST register */
|
||||
#define MDIO_OATC14_PLCA_MAXBC 0xff00
|
||||
#define MDIO_OATC14_PLCA_BTMR 0x00ff
|
||||
|
||||
/* Version Identifiers */
|
||||
#define OATC14_IDM 0x0a00
|
||||
|
||||
#endif /* __MDIO_OPEN_ALLIANCE__ */
|
@ -8,6 +8,8 @@
|
||||
#include <linux/mii.h>
|
||||
#include <linux/phy.h>
|
||||
|
||||
#include "mdio-open-alliance.h"
|
||||
|
||||
/**
|
||||
* genphy_c45_baset1_able - checks if the PMA has BASE-T1 extended abilities
|
||||
* @phydev: target phy_device struct
|
||||
@ -931,6 +933,197 @@ int genphy_c45_fast_retrain(struct phy_device *phydev, bool enable)
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(genphy_c45_fast_retrain);
|
||||
|
||||
/**
|
||||
* genphy_c45_plca_get_cfg - get PLCA configuration from standard registers
|
||||
* @phydev: target phy_device struct
|
||||
* @plca_cfg: output structure to store the PLCA configuration
|
||||
*
|
||||
* Description: if the PHY complies to the Open Alliance TC14 10BASE-T1S PLCA
|
||||
* Management Registers specifications, this function can be used to retrieve
|
||||
* the current PLCA configuration from the standard registers in MMD 31.
|
||||
*/
|
||||
int genphy_c45_plca_get_cfg(struct phy_device *phydev,
|
||||
struct phy_plca_cfg *plca_cfg)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = phy_read_mmd(phydev, MDIO_MMD_VEND2, MDIO_OATC14_PLCA_IDVER);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
if ((ret & MDIO_OATC14_PLCA_IDM) != OATC14_IDM)
|
||||
return -ENODEV;
|
||||
|
||||
plca_cfg->version = ret & ~MDIO_OATC14_PLCA_IDM;
|
||||
|
||||
ret = phy_read_mmd(phydev, MDIO_MMD_VEND2, MDIO_OATC14_PLCA_CTRL0);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
plca_cfg->enabled = !!(ret & MDIO_OATC14_PLCA_EN);
|
||||
|
||||
ret = phy_read_mmd(phydev, MDIO_MMD_VEND2, MDIO_OATC14_PLCA_CTRL1);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
plca_cfg->node_cnt = (ret & MDIO_OATC14_PLCA_NCNT) >> 8;
|
||||
plca_cfg->node_id = (ret & MDIO_OATC14_PLCA_ID);
|
||||
|
||||
ret = phy_read_mmd(phydev, MDIO_MMD_VEND2, MDIO_OATC14_PLCA_TOTMR);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
plca_cfg->to_tmr = ret & MDIO_OATC14_PLCA_TOT;
|
||||
|
||||
ret = phy_read_mmd(phydev, MDIO_MMD_VEND2, MDIO_OATC14_PLCA_BURST);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
plca_cfg->burst_cnt = (ret & MDIO_OATC14_PLCA_MAXBC) >> 8;
|
||||
plca_cfg->burst_tmr = (ret & MDIO_OATC14_PLCA_BTMR);
|
||||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(genphy_c45_plca_get_cfg);
|
||||
|
||||
/**
|
||||
* genphy_c45_plca_set_cfg - set PLCA configuration using standard registers
|
||||
* @phydev: target phy_device struct
|
||||
* @plca_cfg: structure containing the PLCA configuration. Fields set to -1 are
|
||||
* not to be changed.
|
||||
*
|
||||
* Description: if the PHY complies to the Open Alliance TC14 10BASE-T1S PLCA
|
||||
* Management Registers specifications, this function can be used to modify
|
||||
* the PLCA configuration using the standard registers in MMD 31.
|
||||
*/
|
||||
int genphy_c45_plca_set_cfg(struct phy_device *phydev,
|
||||
const struct phy_plca_cfg *plca_cfg)
|
||||
{
|
||||
int ret;
|
||||
u16 val;
|
||||
|
||||
// PLCA IDVER is read-only
|
||||
if (plca_cfg->version >= 0)
|
||||
return -EINVAL;
|
||||
|
||||
// first of all, disable PLCA if required
|
||||
if (plca_cfg->enabled == 0) {
|
||||
ret = phy_clear_bits_mmd(phydev, MDIO_MMD_VEND2,
|
||||
MDIO_OATC14_PLCA_CTRL0,
|
||||
MDIO_OATC14_PLCA_EN);
|
||||
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
}
|
||||
|
||||
// check if we need to set the PLCA node count, node ID, or both
|
||||
if (plca_cfg->node_cnt >= 0 || plca_cfg->node_id >= 0) {
|
||||
/* if one between node count and node ID is -not- to be
|
||||
* changed, read the register to later perform merge/purge of
|
||||
* the configuration as appropriate
|
||||
*/
|
||||
if (plca_cfg->node_cnt < 0 || plca_cfg->node_id < 0) {
|
||||
ret = phy_read_mmd(phydev, MDIO_MMD_VEND2,
|
||||
MDIO_OATC14_PLCA_CTRL1);
|
||||
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
val = ret;
|
||||
}
|
||||
|
||||
if (plca_cfg->node_cnt >= 0)
|
||||
val = (val & ~MDIO_OATC14_PLCA_NCNT) |
|
||||
(plca_cfg->node_cnt << 8);
|
||||
|
||||
if (plca_cfg->node_id >= 0)
|
||||
val = (val & ~MDIO_OATC14_PLCA_ID) |
|
||||
(plca_cfg->node_id);
|
||||
|
||||
ret = phy_write_mmd(phydev, MDIO_MMD_VEND2,
|
||||
MDIO_OATC14_PLCA_CTRL1, val);
|
||||
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (plca_cfg->to_tmr >= 0) {
|
||||
ret = phy_write_mmd(phydev, MDIO_MMD_VEND2,
|
||||
MDIO_OATC14_PLCA_TOTMR,
|
||||
plca_cfg->to_tmr);
|
||||
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
}
|
||||
|
||||
// check if we need to set the PLCA burst count, burst timer, or both
|
||||
if (plca_cfg->burst_cnt >= 0 || plca_cfg->burst_tmr >= 0) {
|
||||
/* if one between burst count and burst timer is -not- to be
|
||||
* changed, read the register to later perform merge/purge of
|
||||
* the configuration as appropriate
|
||||
*/
|
||||
if (plca_cfg->burst_cnt < 0 || plca_cfg->burst_tmr < 0) {
|
||||
ret = phy_read_mmd(phydev, MDIO_MMD_VEND2,
|
||||
MDIO_OATC14_PLCA_BURST);
|
||||
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
val = ret;
|
||||
}
|
||||
|
||||
if (plca_cfg->burst_cnt >= 0)
|
||||
val = (val & ~MDIO_OATC14_PLCA_MAXBC) |
|
||||
(plca_cfg->burst_cnt << 8);
|
||||
|
||||
if (plca_cfg->burst_tmr >= 0)
|
||||
val = (val & ~MDIO_OATC14_PLCA_BTMR) |
|
||||
(plca_cfg->burst_tmr);
|
||||
|
||||
ret = phy_write_mmd(phydev, MDIO_MMD_VEND2,
|
||||
MDIO_OATC14_PLCA_BURST, val);
|
||||
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
}
|
||||
|
||||
// if we need to enable PLCA, do it at the end
|
||||
if (plca_cfg->enabled > 0) {
|
||||
ret = phy_set_bits_mmd(phydev, MDIO_MMD_VEND2,
|
||||
MDIO_OATC14_PLCA_CTRL0,
|
||||
MDIO_OATC14_PLCA_EN);
|
||||
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(genphy_c45_plca_set_cfg);
|
||||
|
||||
/**
|
||||
* genphy_c45_plca_get_status - get PLCA status from standard registers
|
||||
* @phydev: target phy_device struct
|
||||
* @plca_st: output structure to store the PLCA status
|
||||
*
|
||||
* Description: if the PHY complies to the Open Alliance TC14 10BASE-T1S PLCA
|
||||
* Management Registers specifications, this function can be used to retrieve
|
||||
* the current PLCA status information from the standard registers in MMD 31.
|
||||
*/
|
||||
int genphy_c45_plca_get_status(struct phy_device *phydev,
|
||||
struct phy_plca_status *plca_st)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = phy_read_mmd(phydev, MDIO_MMD_VEND2, MDIO_OATC14_PLCA_STATUS);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
plca_st->pst = !!(ret & MDIO_OATC14_PLCA_PST);
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(genphy_c45_plca_get_status);
|
||||
|
||||
struct phy_driver genphy_c45_driver = {
|
||||
.phy_id = 0xffffffff,
|
||||
.phy_id_mask = 0xffffffff,
|
||||
|
@ -1753,6 +1753,12 @@ int genphy_c45_loopback(struct phy_device *phydev, bool enable);
|
||||
int genphy_c45_pma_resume(struct phy_device *phydev);
|
||||
int genphy_c45_pma_suspend(struct phy_device *phydev);
|
||||
int genphy_c45_fast_retrain(struct phy_device *phydev, bool enable);
|
||||
int genphy_c45_plca_get_cfg(struct phy_device *phydev,
|
||||
struct phy_plca_cfg *plca_cfg);
|
||||
int genphy_c45_plca_set_cfg(struct phy_device *phydev,
|
||||
const struct phy_plca_cfg *plca_cfg);
|
||||
int genphy_c45_plca_get_status(struct phy_device *phydev,
|
||||
struct phy_plca_status *plca_st);
|
||||
|
||||
/* Generic C45 PHY driver */
|
||||
extern struct phy_driver genphy_c45_driver;
|
||||
|
Loading…
Reference in New Issue
Block a user