@@ -687,9 +687,9 @@ static int
hns_mac_register_phydev(struct mii_bus *mdio, struct hns_mac_cb *mac_cb,
u32 addr)
{
+ enum phy_access_mode mode;
struct phy_device *phy;
const char *phy_type;
- bool is_c45;
int rc;
rc = fwnode_property_read_string(mac_cb->fw_port,
@@ -698,13 +698,13 @@ hns_mac_register_phydev(struct mii_bus *mdio, struct hns_mac_cb *mac_cb,
return rc;
if (!strcmp(phy_type, phy_modes(PHY_INTERFACE_MODE_XGMII)))
- is_c45 = true;
+ mode = PHY_ACCESS_C45;
else if (!strcmp(phy_type, phy_modes(PHY_INTERFACE_MODE_SGMII)))
- is_c45 = false;
+ mode = PHY_ACCESS_C22;
else
return -ENODATA;
- phy = get_phy_device(mdio, addr, is_c45);
+ phy = get_phy_device(mdio, addr, mode);
if (!phy || IS_ERR(phy))
return -EIO;
@@ -131,9 +131,11 @@ int fwnode_mdiobus_register_phy(struct mii_bus *bus,
is_c45 = fwnode_device_is_compatible(child, "ethernet-phy-ieee802.3-c45");
if (is_c45 || fwnode_get_phy_id(child, &phy_id))
- phy = get_phy_device(bus, addr, is_c45);
+ phy = get_phy_device(bus, addr,
+ is_c45 ? PHY_ACCESS_C45 : PHY_ACCESS_C22);
else
- phy = phy_device_create(bus, addr, phy_id, 0, NULL);
+ phy = phy_device_create(bus, addr, phy_id, PHY_ACCESS_C22,
+ NULL);
if (IS_ERR(phy)) {
rc = PTR_ERR(phy);
goto clean_mii_ts;
@@ -513,12 +513,13 @@ static int mdiobus_create_device(struct mii_bus *bus,
return ret;
}
-static struct phy_device *mdiobus_scan(struct mii_bus *bus, int addr, bool c45)
+static struct phy_device *mdiobus_scan(struct mii_bus *bus, int addr,
+ enum phy_access_mode mode)
{
struct phy_device *phydev = ERR_PTR(-ENODEV);
int err;
- phydev = get_phy_device(bus, addr, c45);
+ phydev = get_phy_device(bus, addr, mode);
if (IS_ERR(phydev))
return phydev;
@@ -550,7 +551,7 @@ static struct phy_device *mdiobus_scan(struct mii_bus *bus, int addr, bool c45)
*/
struct phy_device *mdiobus_scan_c22(struct mii_bus *bus, int addr)
{
- return mdiobus_scan(bus, addr, false);
+ return mdiobus_scan(bus, addr, PHY_ACCESS_C22);
}
EXPORT_SYMBOL(mdiobus_scan_c22);
@@ -568,7 +569,7 @@ EXPORT_SYMBOL(mdiobus_scan_c22);
*/
static struct phy_device *mdiobus_scan_c45(struct mii_bus *bus, int addr)
{
- return mdiobus_scan(bus, addr, true);
+ return mdiobus_scan(bus, addr, PHY_ACCESS_C45);
}
static int mdiobus_scan_bus_c22(struct mii_bus *bus)
@@ -580,7 +580,8 @@ static void tja1102_p1_register(struct work_struct *work)
}
/* Real PHY ID of Port 1 is 0 */
- phy = phy_device_create(bus, addr, PHY_ID_TJA1102, false, NULL);
+ phy = phy_device_create(bus, addr, PHY_ID_TJA1102,
+ PHY_ACCESS_C22, NULL);
if (IS_ERR(phy)) {
dev_err(dev, "Can't create PHY device for Port 1: %i\n",
addr);
@@ -630,7 +630,7 @@ static int phy_request_driver_module(struct phy_device *dev, u32 phy_id)
}
struct phy_device *phy_device_create(struct mii_bus *bus, int addr, u32 phy_id,
- bool is_c45,
+ enum phy_access_mode mode,
struct phy_c45_device_ids *c45_ids)
{
struct phy_device *dev;
@@ -664,7 +664,7 @@ struct phy_device *phy_device_create(struct mii_bus *bus, int addr, u32 phy_id,
dev->autoneg = AUTONEG_ENABLE;
dev->pma_extable = -ENODATA;
- dev->is_c45 = is_c45;
+ dev->access_mode = mode;
dev->phy_id = phy_id;
if (c45_ids)
dev->c45_ids = *c45_ids;
@@ -926,7 +926,7 @@ EXPORT_SYMBOL(fwnode_get_phy_id);
* struct
* @bus: the target MII bus
* @addr: PHY address on the MII bus
- * @is_c45: If true the PHY uses the 802.3 clause 45 protocol
+ * @mode: Access mode of the PHY
*
* Probe for a PHY at @addr on @bus.
*
@@ -937,10 +937,16 @@ EXPORT_SYMBOL(fwnode_get_phy_id);
* If the "devices in package" appears valid, read the ID registers for each
* MMD, allocate and return a &struct phy_device.
*
+ * When using %PHY_ACCESS_C45_OVER_C22 as @mode care have to be taken to not
+ * access a non-PHY device as C45-over-C22 is a property of a PHY and not a
+ * generic MDIO device. As the access involves register writes, it may be
+ * destructive on non-PHY devices. IOW, it cannot be used for bus scanning.
+ *
* Returns an allocated &struct phy_device on success, %-ENODEV if there is
* no PHY present, or %-EIO on bus access error.
*/
-struct phy_device *get_phy_device(struct mii_bus *bus, int addr, bool is_c45)
+struct phy_device *get_phy_device(struct mii_bus *bus, int addr,
+ enum phy_access_mode mode)
{
struct phy_c45_device_ids c45_ids;
u32 phy_id = 0;
@@ -950,10 +956,16 @@ struct phy_device *get_phy_device(struct mii_bus *bus, int addr, bool is_c45)
c45_ids.mmds_present = 0;
memset(c45_ids.device_ids, 0xff, sizeof(c45_ids.device_ids));
- if (is_c45)
- r = get_phy_c45_ids(bus, addr, &c45_ids);
- else
+ switch (mode) {
+ case PHY_ACCESS_C22:
r = get_phy_c22_id(bus, addr, &phy_id);
+ break;
+ case PHY_ACCESS_C45:
+ r = get_phy_c45_ids(bus, addr, &c45_ids);
+ break;
+ default:
+ return ERR_PTR(-EIO);
+ }
if (r)
return ERR_PTR(r);
@@ -963,15 +975,15 @@ struct phy_device *get_phy_device(struct mii_bus *bus, int addr, bool is_c45)
* probe with C45 to see if we're able to get a valid PHY ID in the C45
* space, if successful, create the C45 PHY device.
*/
- if (!is_c45 && phy_id == 0 && bus->read_c45) {
+ if (mode == PHY_ACCESS_C22 && phy_id == 0 && bus->read_c45) {
r = get_phy_c45_ids(bus, addr, &c45_ids);
if (!r)
return phy_device_create(bus, addr, phy_id,
- true, &c45_ids);
+ PHY_ACCESS_C45, &c45_ids);
}
- return phy_device_create(bus, addr, phy_id, is_c45,
- !is_c45 ? NULL : &c45_ids);
+ return phy_device_create(bus, addr, phy_id, mode,
+ mode == PHY_ACCESS_C22 ? NULL : &c45_ids);
}
EXPORT_SYMBOL(get_phy_device);
@@ -1750,12 +1750,13 @@ static void sfp_sm_phy_detach(struct sfp *sfp)
sfp->mod_phy = NULL;
}
-static int sfp_sm_probe_phy(struct sfp *sfp, int addr, bool is_c45)
+static int sfp_sm_probe_phy(struct sfp *sfp, int addr,
+ enum phy_access_mode mode)
{
struct phy_device *phy;
int err;
- phy = get_phy_device(sfp->i2c_mii, addr, is_c45);
+ phy = get_phy_device(sfp->i2c_mii, addr, mode);
if (phy == ERR_PTR(-ENODEV))
return PTR_ERR(phy);
if (IS_ERR(phy)) {
@@ -1879,15 +1880,16 @@ static int sfp_sm_probe_for_phy(struct sfp *sfp)
break;
case MDIO_I2C_MARVELL_C22:
- err = sfp_sm_probe_phy(sfp, SFP_PHY_ADDR, false);
+ err = sfp_sm_probe_phy(sfp, SFP_PHY_ADDR, PHY_ACCESS_C22);
break;
case MDIO_I2C_C45:
- err = sfp_sm_probe_phy(sfp, SFP_PHY_ADDR, true);
+ err = sfp_sm_probe_phy(sfp, SFP_PHY_ADDR, PHY_ACCESS_C45);
break;
case MDIO_I2C_ROLLBALL:
- err = sfp_sm_probe_phy(sfp, SFP_PHY_ADDR_ROLLBALL, true);
+ err = sfp_sm_probe_phy(sfp, SFP_PHY_ADDR_ROLLBALL,
+ PHY_ACCESS_C45);
break;
}
@@ -531,6 +531,17 @@ struct phy_c45_device_ids {
struct macsec_context;
struct macsec_ops;
+/**
+ * enum phy_access_mode - PHY register access mode definitions
+ *
+ * @PHY_ACCESS_C22: use 802.3 c22 MDIO transactions
+ * @PHY_ACCESS_C45: use 802.3 c45 MDIO transactions
+ */
+enum phy_access_mode {
+ PHY_ACCESS_C22,
+ PHY_ACCESS_C45,
+};
+
/**
* struct phy_device - An instance of a PHY
*
@@ -539,8 +550,8 @@ struct macsec_ops;
* @devlink: Create a link between phy dev and mac dev, if the external phy
* used by current mac interface is managed by another mac interface.
* @phy_id: UID for this device found during discovery
- * @c45_ids: 802.3-c45 Device Identifiers if is_c45.
- * @is_c45: Set to true if this PHY uses clause 45 addressing.
+ * @access_mode: MDIO access mode of the PHY.
+ * @c45_ids: 802.3-c45 Device Identifiers if it's an C45 PHY.
* @is_internal: Set to true if this PHY is internal to a MAC.
* @is_pseudo_fixed_link: Set to true if this PHY is an Ethernet switch, etc.
* @is_gigabit_capable: Set to true if PHY supports 1000Mbps
@@ -637,8 +648,9 @@ struct phy_device {
u32 phy_id;
+ enum phy_access_mode access_mode;
+
struct phy_c45_device_ids c45_ids;
- unsigned is_c45:1;
unsigned is_internal:1;
unsigned is_pseudo_fixed_link:1;
unsigned is_gigabit_capable:1;
@@ -768,7 +780,7 @@ static inline struct phy_device *to_phy_device(const struct device *dev)
static inline bool phy_is_c45(struct phy_device *phydev)
{
- return phydev->is_c45;
+ return phydev->access_mode != PHY_ACCESS_C22;
}
/**
@@ -1626,7 +1638,7 @@ int phy_modify_paged(struct phy_device *phydev, int page, u32 regnum,
u16 mask, u16 set);
struct phy_device *phy_device_create(struct mii_bus *bus, int addr, u32 phy_id,
- bool is_c45,
+ enum phy_access_mode mode,
struct phy_c45_device_ids *c45_ids);
#if IS_ENABLED(CONFIG_PHYLIB)
int fwnode_get_phy_id(struct fwnode_handle *fwnode, u32 *phy_id);
@@ -1634,7 +1646,8 @@ struct mdio_device *fwnode_mdio_find_device(struct fwnode_handle *fwnode);
struct phy_device *fwnode_phy_find_device(struct fwnode_handle *phy_fwnode);
struct phy_device *device_phy_find_device(struct device *dev);
struct fwnode_handle *fwnode_get_phy_node(const struct fwnode_handle *fwnode);
-struct phy_device *get_phy_device(struct mii_bus *bus, int addr, bool is_c45);
+struct phy_device *get_phy_device(struct mii_bus *bus, int addr,
+ enum phy_access_mode mode);
int phy_device_register(struct phy_device *phy);
void phy_device_free(struct phy_device *phydev);
#else
@@ -1666,7 +1679,8 @@ struct fwnode_handle *fwnode_get_phy_node(struct fwnode_handle *fwnode)
}
static inline
-struct phy_device *get_phy_device(struct mii_bus *bus, int addr, bool is_c45)
+struct phy_device *get_phy_device(struct mii_bus *bus, int addr,
+ enum phy_access_mode mode)
{
return NULL;
}
Instead of tracing whether the PHY is a C45 one, use the method how the PHY is accessed. For now, that is either by C22 or by C45 transactions. There is no functional change, just a semantical difference. This is a preparation patch to add a third access method C45-over-C22. Signed-off-by: Michael Walle <mwalle@kernel.org> --- drivers/net/ethernet/hisilicon/hns/hns_dsaf_mac.c | 8 +++--- drivers/net/mdio/fwnode_mdio.c | 6 ++-- drivers/net/phy/mdio_bus.c | 9 +++--- drivers/net/phy/nxp-tja11xx.c | 3 +- drivers/net/phy/phy_device.c | 34 +++++++++++++++-------- drivers/net/phy/sfp.c | 12 ++++---- include/linux/phy.h | 28 ++++++++++++++----- 7 files changed, 66 insertions(+), 34 deletions(-)